ARM: omap1: Switch to use MULTI_IRQ
[firefly-linux-kernel-4.4.55.git] / arch / arm / mach-omap1 / irq.c
index 3651b17aeb1022657e01b236bfd2acbdb9e64689..567fba35bd9475eb5f783b167731ea96c7d333c9 100644 (file)
@@ -43,6 +43,7 @@
 #include <linux/io.h>
 
 #include <asm/irq.h>
+#include <asm/exception.h>
 #include <asm/mach/irq.h>
 
 #include "soc.h"
@@ -61,7 +62,7 @@ struct omap_irq_bank {
        unsigned long wake_enable;
 };
 
-u32 omap_irq_flags;
+static u32 omap_l2_irq;
 static unsigned int irq_bank_count;
 static struct omap_irq_bank *irq_banks;
 static struct irq_domain *domain;
@@ -140,6 +141,36 @@ static struct omap_irq_bank omap1610_irq_banks[] = {
 };
 #endif
 
+asmlinkage void __exception_irq_entry omap1_handle_irq(struct pt_regs *regs)
+{
+       void __iomem *l1 = irq_banks[0].va;
+       void __iomem *l2 = irq_banks[1].va;
+       u32 irqnr;
+
+       do {
+               irqnr = readl_relaxed(l1 + IRQ_ITR_REG_OFFSET);
+               irqnr &= ~(readl_relaxed(l1 + IRQ_MIR_REG_OFFSET) & 0xffffffff);
+               if (!irqnr)
+                       break;
+
+               irqnr = readl_relaxed(l1 + IRQ_SIR_FIQ_REG_OFFSET);
+               if (irqnr)
+                       goto irq;
+
+               irqnr = readl_relaxed(l1 + IRQ_SIR_IRQ_REG_OFFSET);
+               if (irqnr == omap_l2_irq) {
+                       irqnr = readl_relaxed(l2 + IRQ_SIR_IRQ_REG_OFFSET);
+                       if (irqnr)
+                               irqnr += 32;
+               }
+irq:
+               if (irqnr)
+                       handle_domain_irq(domain, irqnr, regs);
+               else
+                       break;
+       } while (irqnr);
+}
+
 static __init void
 omap_alloc_gc(void __iomem *base, unsigned int irq_start, unsigned int num)
 {
@@ -167,26 +198,22 @@ void __init omap1_init_irq(void)
 
 #if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
        if (cpu_is_omap7xx()) {
-               omap_irq_flags = INT_7XX_IH2_IRQ;
                irq_banks = omap7xx_irq_banks;
                irq_bank_count = ARRAY_SIZE(omap7xx_irq_banks);
        }
 #endif
 #ifdef CONFIG_ARCH_OMAP15XX
        if (cpu_is_omap1510()) {
-               omap_irq_flags = INT_1510_IH2_IRQ;
                irq_banks = omap1510_irq_banks;
                irq_bank_count = ARRAY_SIZE(omap1510_irq_banks);
        }
        if (cpu_is_omap310()) {
-               omap_irq_flags = INT_1510_IH2_IRQ;
                irq_banks = omap310_irq_banks;
                irq_bank_count = ARRAY_SIZE(omap310_irq_banks);
        }
 #endif
 #if defined(CONFIG_ARCH_OMAP16XX)
        if (cpu_is_omap16xx()) {
-               omap_irq_flags = INT_1510_IH2_IRQ;
                irq_banks = omap1610_irq_banks;
                irq_bank_count = ARRAY_SIZE(omap1610_irq_banks);
        }
@@ -205,6 +232,7 @@ void __init omap1_init_irq(void)
                pr_warn("Couldn't allocate IRQ numbers\n");
                irq_base = 0;
        }
+       omap_l2_irq = cpu_is_omap7xx() ? irq_base + 1 : irq_base;
 
        domain = irq_domain_add_legacy(NULL, nr_irqs, irq_base, 0,
                                       &irq_domain_simple_ops, NULL);
@@ -239,7 +267,7 @@ void __init omap1_init_irq(void)
        }
 
        /* Unmask level 2 handler */
-       d = irq_get_irq_data(omap_irq_flags);
+       d = irq_get_irq_data(irq_find_mapping(domain, omap_l2_irq));
        if (d) {
                ct = irq_data_get_chip_type(d);
                ct->chip.irq_unmask(d);