aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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}