irqchip: sun4i: Fix irq 0 not working
authorHans de Goede <hdegoede@redhat.com>
Thu, 13 Mar 2014 18:03:52 +0000 (19:03 +0100)
committerThomas Gleixner <tglx@linutronix.de>
Fri, 14 Mar 2014 12:43:33 +0000 (13:43 +0100)
SUN4I_IRQ_VECTOR_REG containing 0 can mean one of 3 things:

1) no more irqs pending
2) irq 0 pending
3) spurious irq

So if we immediately get a reading of 0, check the irq-pending reg
to differentiate between 2 and 3. We only do this once to avoid
the extra check in the common case of 1) hapening after having
read the vector-reg once.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-sunxi@googlegroups.com
Link: http://lkml.kernel.org/r/1394733834-26839-3-git-send-email-hdegoede@redhat.com
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
drivers/irqchip/irq-sun4i.c

index 15999551ff7ffb74641d35aab7d8f3cd30676172..7ae85ec61e56ee022a349f56f88640b0cb2ddf8f 100644 (file)
@@ -140,10 +140,24 @@ static void __exception_irq_entry sun4i_handle_irq(struct pt_regs *regs)
 {
        u32 irq, hwirq;
 
+       /*
+        * hwirq == 0 can mean one of 3 things:
+        * 1) no more irqs pending
+        * 2) irq 0 pending
+        * 3) spurious irq
+        * So if we immediately get a reading of 0, check the irq-pending reg
+        * to differentiate between 2 and 3. We only do this once to avoid
+        * the extra check in the common case of 1 hapening after having
+        * read the vector-reg once.
+        */
        hwirq = readl(sun4i_irq_base + SUN4I_IRQ_VECTOR_REG) >> 2;
-       while (hwirq != 0) {
+       if (hwirq == 0 &&
+                 !(readl(sun4i_irq_base + SUN4I_IRQ_PENDING_REG(0)) & BIT(0)))
+               return;
+
+       do {
                irq = irq_find_mapping(sun4i_irq_domain, hwirq);
                handle_IRQ(irq, regs);
                hwirq = readl(sun4i_irq_base + SUN4I_IRQ_VECTOR_REG) >> 2;
-       }
+       } while (hwirq != 0);
 }