Skip to content

Commit de58e52

Browse files
anholtKAGA-KOKO
authored andcommitted
irqchip/bcm2835: Refactor handle_IRQ() calls out of MAKE_HWIRQ
For BCM2836, we want to chain into this IRQ chip from the root controller, and for chaining we need to do something else instead of handle_IRQ() once we have decoded the IRQ. Note that this changes the behavior a little bit: Previously for a non-shortcut IRQ, we'd loop reading and handling the second level IRQ status until it was cleared before returning to the loop reading the top level IRQ status (Note that the top level bit is just an OR of the low level bits). For the expected case of just one interrupt to be handled, this was an extra register read, so we're down from 4 to 3 reads. Signed-off-by: Eric Anholt <[email protected]> Acked-by: Stephen Warren <[email protected]> Cc: [email protected] Cc: Lee Jones <[email protected]> Cc: Jason Cooper <[email protected]> Cc: [email protected] Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Thomas Gleixner <[email protected]>
1 parent 649953b commit de58e52

File tree

1 file changed

+29
-28
lines changed

1 file changed

+29
-28
lines changed

drivers/irqchip/irq-bcm2835.c

Lines changed: 29 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -178,44 +178,45 @@ static int __init armctrl_of_init(struct device_node *node,
178178
* handle_IRQ may briefly re-enable interrupts for soft IRQ handling.
179179
*/
180180

181-
static void armctrl_handle_bank(int bank, struct pt_regs *regs)
181+
static u32 armctrl_translate_bank(int bank)
182182
{
183-
u32 stat, irq;
183+
u32 stat = readl_relaxed(intc.pending[bank]);
184184

185-
while ((stat = readl_relaxed(intc.pending[bank]))) {
186-
irq = MAKE_HWIRQ(bank, ffs(stat) - 1);
187-
handle_IRQ(irq_linear_revmap(intc.domain, irq), regs);
188-
}
185+
return MAKE_HWIRQ(bank, ffs(stat) - 1);
186+
}
187+
188+
static u32 armctrl_translate_shortcut(int bank, u32 stat)
189+
{
190+
return MAKE_HWIRQ(bank, shortcuts[ffs(stat >> SHORTCUT_SHIFT) - 1]);
189191
}
190192

191-
static void armctrl_handle_shortcut(int bank, struct pt_regs *regs,
192-
u32 stat)
193+
static u32 get_next_armctrl_hwirq(void)
193194
{
194-
u32 irq = MAKE_HWIRQ(bank, shortcuts[ffs(stat >> SHORTCUT_SHIFT) - 1]);
195-
handle_IRQ(irq_linear_revmap(intc.domain, irq), regs);
195+
u32 stat = readl_relaxed(intc.pending[0]) & BANK0_VALID_MASK;
196+
197+
if (stat == 0)
198+
return ~0;
199+
else if (stat & BANK0_HWIRQ_MASK)
200+
return MAKE_HWIRQ(0, ffs(stat & BANK0_HWIRQ_MASK) - 1);
201+
else if (stat & SHORTCUT1_MASK)
202+
return armctrl_translate_shortcut(1, stat & SHORTCUT1_MASK);
203+
else if (stat & SHORTCUT2_MASK)
204+
return armctrl_translate_shortcut(2, stat & SHORTCUT2_MASK);
205+
else if (stat & BANK1_HWIRQ)
206+
return armctrl_translate_bank(1);
207+
else if (stat & BANK2_HWIRQ)
208+
return armctrl_translate_bank(2);
209+
else
210+
BUG();
196211
}
197212

198213
static void __exception_irq_entry bcm2835_handle_irq(
199214
struct pt_regs *regs)
200215
{
201-
u32 stat, irq;
202-
203-
while ((stat = readl_relaxed(intc.pending[0]) & BANK0_VALID_MASK)) {
204-
if (stat & BANK0_HWIRQ_MASK) {
205-
irq = MAKE_HWIRQ(0, ffs(stat & BANK0_HWIRQ_MASK) - 1);
206-
handle_IRQ(irq_linear_revmap(intc.domain, irq), regs);
207-
} else if (stat & SHORTCUT1_MASK) {
208-
armctrl_handle_shortcut(1, regs, stat & SHORTCUT1_MASK);
209-
} else if (stat & SHORTCUT2_MASK) {
210-
armctrl_handle_shortcut(2, regs, stat & SHORTCUT2_MASK);
211-
} else if (stat & BANK1_HWIRQ) {
212-
armctrl_handle_bank(1, regs);
213-
} else if (stat & BANK2_HWIRQ) {
214-
armctrl_handle_bank(2, regs);
215-
} else {
216-
BUG();
217-
}
218-
}
216+
u32 hwirq;
217+
218+
while ((hwirq = get_next_armctrl_hwirq()) != ~0)
219+
handle_IRQ(irq_linear_revmap(intc.domain, hwirq), regs);
219220
}
220221

221222
IRQCHIP_DECLARE(bcm2835_armctrl_ic, "brcm,bcm2835-armctrl-ic", armctrl_of_init);

0 commit comments

Comments
 (0)