Messages in this thread Patch in this message | | | From | Holger Dengler <> | Subject | [PATCH 06/11] mfd: flexcard: add DMA interrupt domain | Date | Wed, 25 Mar 2015 10:51:55 +0100 |
| |
From: Benedikt Spranger <b.spranger@linutronix.de>
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@linutronix.de> Signed-off-by: Benedikt Spranger <b.spranger@linutronix.de> cc: Samuel Ortiz <sameo@linux.intel.com> cc: Lee Jones <lee.jones@linaro.org> --- 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
| |