From f8a073ee378b9893aee0749c3868a6ecfb0c1636 Mon Sep 17 00:00:00 2001 From: Ludovic Desroches Date: Wed, 20 Jun 2012 16:13:30 +0200 Subject: ARM: at91: add of irq priorities support Add a third cell to define irq priority. Signed-off-by: Ludovic Desroches Reviewed-by: Rob Herring Signed-off-by: Nicolas Ferre --- arch/arm/mach-at91/irq.c | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) (limited to 'arch/arm/mach-at91/irq.c') diff --git a/arch/arm/mach-at91/irq.c b/arch/arm/mach-at91/irq.c index df8605fd7bad..db8e14112eda 100644 --- a/arch/arm/mach-at91/irq.c +++ b/arch/arm/mach-at91/irq.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -42,6 +43,7 @@ void __iomem *at91_aic_base; static struct irq_domain *at91_aic_domain; static struct device_node *at91_aic_np; +static unsigned int *at91_aic_irq_priorities; static void at91_aic_mask_irq(struct irq_data *d) { @@ -177,8 +179,9 @@ static int at91_aic_irq_map(struct irq_domain *h, unsigned int virq, /* Put virq number in Source Vector Register */ at91_aic_write(AT91_AIC_SVR(hw), virq); - /* Active Low interrupt, without priority */ - at91_aic_write(AT91_AIC_SMR(hw), AT91_AIC_SRCTYPE_LOW); + /* Active Low interrupt, with priority */ + at91_aic_write(AT91_AIC_SMR(hw), + AT91_AIC_SRCTYPE_LOW | at91_aic_irq_priorities[hw]); irq_set_chip_and_handler(virq, &at91_aic_chip, handle_fasteoi_irq); set_irq_flags(virq, IRQF_VALID | IRQF_PROBE); @@ -186,9 +189,28 @@ static int at91_aic_irq_map(struct irq_domain *h, unsigned int virq, return 0; } +static int at91_aic_irq_domain_xlate(struct irq_domain *d, struct device_node *ctrlr, + const u32 *intspec, unsigned int intsize, + irq_hw_number_t *out_hwirq, unsigned int *out_type) +{ + if (WARN_ON(intsize < 3)) + return -EINVAL; + if (WARN_ON(intspec[0] >= NR_AIC_IRQS)) + return -EINVAL; + if (WARN_ON((intspec[2] < AT91_AIC_IRQ_MIN_PRIORITY) + || (intspec[2] > AT91_AIC_IRQ_MAX_PRIORITY))) + return -EINVAL; + + *out_hwirq = intspec[0]; + *out_type = intspec[1] & IRQ_TYPE_SENSE_MASK; + at91_aic_irq_priorities[*out_hwirq] = intspec[2]; + + return 0; +} + static struct irq_domain_ops at91_aic_irq_ops = { .map = at91_aic_irq_map, - .xlate = irq_domain_xlate_twocell, + .xlate = at91_aic_irq_domain_xlate, }; int __init at91_aic_of_init(struct device_node *node, @@ -198,6 +220,12 @@ int __init at91_aic_of_init(struct device_node *node, const __be32 *p; u32 val; + at91_aic_irq_priorities = kzalloc(NR_AIC_IRQS + * sizeof(*at91_aic_irq_priorities), + GFP_KERNEL); + if (!at91_aic_irq_priorities) + return -ENOMEM; + at91_aic_base = of_iomap(node, 0); at91_aic_np = node; -- cgit v1.2.3