ARM: GIC: Add global gic_handle_irq() function
authorMarc Zyngier <marc.zyngier@arm.com>
Tue, 6 Sep 2011 08:56:17 +0000 (09:56 +0100)
committerMarc Zyngier <marc.zyngier@arm.com>
Tue, 15 Nov 2011 18:13:05 +0000 (18:13 +0000)
Provide the GIC code with a low level handler that can be used
by platforms using CONFIG_MULTI_IRQ_HANDLER.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
arch/arm/common/gic.c
arch/arm/include/asm/hardware/gic.h

index 43cb6f1a7cf2e31ad364405f9217ba7a08d5c1b9..3c78b7c60691ec0ddecee5c50d4297a346889f6f 100644 (file)
@@ -40,6 +40,7 @@
 #include <linux/slab.h>
 
 #include <asm/irq.h>
+#include <asm/exception.h>
 #include <asm/mach/irq.h>
 #include <asm/hardware/gic.h>
 
@@ -272,6 +273,32 @@ static int gic_set_wake(struct irq_data *d, unsigned int on)
 #define gic_set_wake   NULL
 #endif
 
+asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs)
+{
+       u32 irqstat, irqnr;
+       struct gic_chip_data *gic = &gic_data[0];
+       void __iomem *cpu_base = gic_data_cpu_base(gic);
+
+       do {
+               irqstat = readl_relaxed(cpu_base + GIC_CPU_INTACK);
+               irqnr = irqstat & ~0x1c00;
+
+               if (likely(irqnr > 15 && irqnr < 1021)) {
+                       irqnr = irq_domain_to_irq(&gic->domain, irqnr);
+                       handle_IRQ(irqnr, regs);
+                       continue;
+               }
+               if (irqnr < 16) {
+                       writel_relaxed(irqstat, cpu_base + GIC_CPU_EOI);
+#ifdef CONFIG_SMP
+                       handle_IPI(irqnr, regs);
+#endif
+                       continue;
+               }
+               break;
+       } while (1);
+}
+
 static void gic_handle_cascade_irq(unsigned int irq, struct irq_desc *desc)
 {
        struct gic_chip_data *chip_data = irq_get_handler_data(irq);
index 2721d90625e59f5d91a924bb60aefdacdf9fa6c1..ecf7c02fa16cf73bb940f2035bf00ac93ac28981 100644 (file)
@@ -43,6 +43,7 @@ void gic_init_bases(unsigned int, int, void __iomem *, void __iomem *,
                    u32 offset);
 int gic_of_init(struct device_node *node, struct device_node *parent);
 void gic_secondary_init(unsigned int);
+void gic_handle_irq(struct pt_regs *regs);
 void gic_cascade_irq(unsigned int gic_nr, unsigned int irq);
 void gic_raise_softirq(const struct cpumask *mask, unsigned int irq);