aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/irqchip
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2014-03-13 14:03:52 -0400
committerThomas Gleixner <tglx@linutronix.de>2014-03-14 08:43:33 -0400
commit56af0416b00f6edc7845a7b3f2ef179e385c8e15 (patch)
tree26eaa832e994ace995b8643fcdfa194110cfb637 /drivers/irqchip
parent328a4978df833249b099c9875738d7b72042ffe1 (diff)
irqchip: sun4i: Fix irq 0 not working
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>
Diffstat (limited to 'drivers/irqchip')
-rw-r--r--drivers/irqchip/irq-sun4i.c18
1 files changed, 16 insertions, 2 deletions
diff --git a/drivers/irqchip/irq-sun4i.c b/drivers/irqchip/irq-sun4i.c
index 15999551ff7f..7ae85ec61e56 100644
--- a/drivers/irqchip/irq-sun4i.c
+++ b/drivers/irqchip/irq-sun4i.c
@@ -140,10 +140,24 @@ static void __exception_irq_entry sun4i_handle_irq(struct pt_regs *regs)
140{ 140{
141 u32 irq, hwirq; 141 u32 irq, hwirq;
142 142
143 /*
144 * hwirq == 0 can mean one of 3 things:
145 * 1) no more irqs pending
146 * 2) irq 0 pending
147 * 3) spurious irq
148 * So if we immediately get a reading of 0, check the irq-pending reg
149 * to differentiate between 2 and 3. We only do this once to avoid
150 * the extra check in the common case of 1 hapening after having
151 * read the vector-reg once.
152 */
143 hwirq = readl(sun4i_irq_base + SUN4I_IRQ_VECTOR_REG) >> 2; 153 hwirq = readl(sun4i_irq_base + SUN4I_IRQ_VECTOR_REG) >> 2;
144 while (hwirq != 0) { 154 if (hwirq == 0 &&
155 !(readl(sun4i_irq_base + SUN4I_IRQ_PENDING_REG(0)) & BIT(0)))
156 return;
157
158 do {
145 irq = irq_find_mapping(sun4i_irq_domain, hwirq); 159 irq = irq_find_mapping(sun4i_irq_domain, hwirq);
146 handle_IRQ(irq, regs); 160 handle_IRQ(irq, regs);
147 hwirq = readl(sun4i_irq_base + SUN4I_IRQ_VECTOR_REG) >> 2; 161 hwirq = readl(sun4i_irq_base + SUN4I_IRQ_VECTOR_REG) >> 2;
148 } 162 } while (hwirq != 0);
149} 163}