[PATCH 06/11] mfd: flexcard: add DMA interrupt domain
From: Holger Dengler
Date: Wed Mar 25 2015 - 05:53:54 EST
From: Benedikt Spranger <b.spranger@xxxxxxxxxxxxx>
The Flexcard comprise an interrupt controller for the attached
tinys, timer, a Flexray related trigger and a second one for DMA.
Both controllers share a single IRQ line.
Add an interrupt domain for the DMA Controller interrupts.
Signed-off-by: Holger Dengler <dengler@xxxxxxxxxxxxx>
Signed-off-by: Benedikt Spranger <b.spranger@xxxxxxxxxxxxx>
cc: Samuel Ortiz <sameo@xxxxxxxxxxxxxxx>
cc: Lee Jones <lee.jones@xxxxxxxxxx>
---
drivers/mfd/flexcard/irq.c | 95 +++++++++++++++++++++++++++++++++++++++++---
drivers/mfd/flexcard/irq.h | 11 +++++
include/linux/mfd/flexcard.h | 23 +++++++++++
3 files changed, 124 insertions(+), 5 deletions(-)
diff --git a/drivers/mfd/flexcard/irq.c b/drivers/mfd/flexcard/irq.c
index fefcb24..17e8b2c 100644
--- a/drivers/mfd/flexcard/irq.c
+++ b/drivers/mfd/flexcard/irq.c
@@ -27,11 +27,13 @@
static irqreturn_t flexcard_demux(int irq, void *data)
{
struct flexcard_device *priv = data;
- u32 stat;
+ u32 stat, dma_stat;
int i, cur;
stat = readl(&priv->conf->irs);
- if (!stat)
+ dma_stat = readl(&priv->conf->dma_irsr);
+
+ if (!stat && !dma_stat)
return IRQ_NONE;
for (i = 0; i < NR_FLEXCARD_IRQ; i++) {
@@ -41,6 +43,15 @@ static irqreturn_t flexcard_demux(int irq, void *data)
generic_handle_irq(cur);
}
}
+
+ for (i = 0; i < NR_FLEXCARD_DMA_IRQ; i++) {
+ if (dma_stat & flexcard_dma_irq_tab[i].status) {
+ cur = irq_find_mapping(priv->dma_domain, i);
+ if (cur)
+ generic_handle_irq(cur);
+ }
+ }
+
return IRQ_HANDLED;
}
@@ -125,6 +136,63 @@ static struct irq_domain_ops flexcard_irq_domain_ops = {
.map = flexcard_irq_domain_map,
};
+static void flexcard_dma_irq_ack(struct irq_data *d)
+{
+ struct flexcard_device *priv = irq_data_get_irq_chip_data(d);
+
+ writel(flexcard_dma_irq_tab[d->hwirq].reset, &priv->conf->dma_irsr);
+}
+
+static void flexcard_dma_irq_mask(struct irq_data *d)
+{
+ struct flexcard_device *priv = irq_data_get_irq_chip_data(d);
+ unsigned long flags;
+ u32 irer;
+
+ raw_spin_lock_irqsave(&priv->irq_lock, flags);
+ irer = readl(&priv->conf->dma_irer);
+ irer &= ~flexcard_dma_irq_tab[d->hwirq].enable;
+ writel(irer, &priv->conf->dma_irer);
+ raw_spin_unlock_irqrestore(&priv->irq_lock, flags);
+}
+
+static void flexcard_dma_irq_unmask(struct irq_data *d)
+{
+ struct flexcard_device *priv = irq_data_get_irq_chip_data(d);
+ unsigned long flags;
+ u32 irer;
+
+ raw_spin_lock_irqsave(&priv->irq_lock, flags);
+ irer = readl(&priv->conf->dma_irer);
+ irer |= FLEXCARD_DMA_IRER_DIRE | flexcard_dma_irq_tab[d->hwirq].enable;
+ writel(irer, &priv->conf->dma_irer);
+ raw_spin_unlock_irqrestore(&priv->irq_lock, flags);
+}
+
+static struct irq_chip flexcard_dma_irq_chip = {
+ .name = "flexcard_dma_irq",
+ .irq_ack = flexcard_dma_irq_ack,
+ .irq_mask = flexcard_dma_irq_mask,
+ .irq_unmask = flexcard_dma_irq_unmask,
+};
+
+static int flexcard_dma_irq_domain_map(struct irq_domain *d, unsigned int irq,
+ irq_hw_number_t hw)
+{
+ struct flexcard_device *priv = d->host_data;
+
+ irq_set_chip_and_handler_name(irq, &flexcard_dma_irq_chip,
+ handle_level_irq, "flexcard-dma");
+ irq_set_chip_data(irq, priv);
+ irq_modify_status(irq, IRQ_NOREQUEST | IRQ_NOAUTOEN, IRQ_NOPROBE);
+
+ return 0;
+}
+
+static struct irq_domain_ops flexcard_dma_irq_domain_ops = {
+ .map = flexcard_dma_irq_domain_map,
+};
+
int flexcard_setup_irq(struct pci_dev *pdev)
{
struct flexcard_device *priv = pci_get_drvdata(pdev);
@@ -143,12 +211,27 @@ int flexcard_setup_irq(struct pci_dev *pdev)
dev_err(&pdev->dev, "could not request irq domain\n");
return -ENODEV;
}
-
priv->irq_domain = domain;
+ domain = irq_domain_add_linear(NULL, NR_FLEXCARD_DMA_IRQ,
+ &flexcard_dma_irq_domain_ops, priv);
+ if (!domain) {
+ dev_err(&pdev->dev, "could not request dma irq domain\n");
+ ret = -ENODEV;
+ goto out_irq;
+ }
+ priv->dma_domain = domain;
+
ret = flexcard_req_irq(pdev);
if (ret)
- irq_domain_remove(priv->dma_domain);
+ goto out_dma;
+
+ return 0;
+
+out_dma:
+ irq_domain_remove(priv->dma_domain);
+out_irq:
+ irq_domain_remove(priv->irq_domain);
return ret;
}
@@ -161,7 +244,9 @@ void flexcard_remove_irq(struct pci_dev *pdev)
writel(0, &priv->conf->irc);
writel(0, &priv->conf->dma_irer);
+ irq_domain_remove(priv->dma_domain);
+ irq_domain_remove(priv->irq_domain);
+
free_irq(pdev->irq, priv);
pci_disable_msi(pdev);
- irq_domain_remove(priv->irq_domain);
}
diff --git a/drivers/mfd/flexcard/irq.h b/drivers/mfd/flexcard/irq.h
index b18fb5b..0e6fe18 100644
--- a/drivers/mfd/flexcard/irq.h
+++ b/drivers/mfd/flexcard/irq.h
@@ -1,6 +1,8 @@
#ifndef FLEXCARD_IRQ_H
#define FLEXCARD_IRQ_H
+#define FLEXCARD_DMA_IRER_DIRE (1 << 31)
+
struct flexcard_irq_tab {
u32 enable;
u32 reset;
@@ -47,4 +49,13 @@ static const struct flexcard_irq_tab flexcard_irq_tab[] = {
#define NR_FLEXCARD_IRQ ARRAY_SIZE(flexcard_irq_tab)
+static const struct flexcard_irq_tab flexcard_dma_irq_tab[] = {
+ to_irq_tab_ack(0, 0, 0), /* DMA_C0 */
+ to_irq_tab_ack(1, 1, 1), /* DMA_TE */
+ to_irq_tab_ack(4, 4, 4), /* DMA_TI */
+ to_irq_tab_ack(5, 5, 5), /* DMA_CBL */
+};
+
+#define NR_FLEXCARD_DMA_IRQ ARRAY_SIZE(flexcard_dma_irq_tab)
+
#endif /* FLEXCARD_IRQ_H */
diff --git a/include/linux/mfd/flexcard.h b/include/linux/mfd/flexcard.h
index f5b789f..f9b0962 100644
--- a/include/linux/mfd/flexcard.h
+++ b/include/linux/mfd/flexcard.h
@@ -30,6 +30,7 @@ struct flexcard_device {
struct miscdevice dev;
struct kref ref;
struct irq_domain *irq_domain;
+ struct irq_domain *dma_domain;
int cardnr;
char name[FLEXCARD_MAX_NAME];
};
@@ -39,4 +40,26 @@ enum flexcard_cell_id {
FLEXCARD_CELL_FLEXRAY,
};
+#define FLEXCARD_IRQ_CC1CCYS_OFF 0
+#define FLEXCARD_IRQ_CC2CCYS_OFF 1
+#define FLEXCARD_IRQ_CC3CCYS_OFF 2
+#define FLEXCARD_IRQ_CC4CCYS_OFF 3
+#define FLEXCARD_IRQ_WAKE4A_OFF 4
+#define FLEXCARD_IRQ_WAKE4B_OFF 5
+#define FLEXCARD_IRQ_WAKE3A_OFF 6
+#define FLEXCARD_IRQ_WAKE3B_OFF 7
+#define FLEXCARD_IRQ_WAKE2A_OFF 8
+#define FLEXCARD_IRQ_WAKE2B_OFF 9
+#define FLEXCARD_IRQ_WAKE1A_OFF 10
+#define FLEXCARD_IRQ_WAKE1B_OFF 11
+#define FLEXCARD_IRQ_CC1T0_OFF 12
+#define FLEXCARD_IRQ_CC2T0_OFF 13
+#define FLEXCARD_IRQ_CC3T0_OFF 14
+#define FLEXCARD_IRQ_CC4T0_OFF 15
+
+#define FLEXCARD_DMA_IRQ_CO 0
+#define FLEXCARD_DMA_IRQ_TE 1
+#define FLEXCARD_DMA_IRQ_TI 2
+#define FLEXCARD_DMA_IRQ_CBL 3
+
#endif /* FLEXCARD_H */
--
2.1.4
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/