aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Anholt <eric@anholt.net>2015-08-06 19:00:30 -0400
committerThomas Gleixner <tglx@linutronix.de>2015-08-20 16:38:41 -0400
commitde58e52f207e3318cb1e1d43f951454e0c83827f (patch)
tree4313613cc6d999d3f8ae0b5cbb24cce34ff49d37
parent649953b5b89dc308747797810812747333d971cd (diff)
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 <eric@anholt.net> Acked-by: Stephen Warren <swarren@wwwdotorg.org> Cc: linux-rpi-kernel@lists.infradead.org Cc: Lee Jones <lee@kernel.org> Cc: Jason Cooper <jason@lakedaemon.net> Cc: linux-arm-kernel@lists.infradead.org Link: http://lkml.kernel.org/r/1438902033-31477-2-git-send-email-eric@anholt.net Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r--drivers/irqchip/irq-bcm2835.c57
1 files changed, 29 insertions, 28 deletions
diff --git a/drivers/irqchip/irq-bcm2835.c b/drivers/irqchip/irq-bcm2835.c
index ca35171e8afc..a40d97268b8a 100644
--- a/drivers/irqchip/irq-bcm2835.c
+++ b/drivers/irqchip/irq-bcm2835.c
@@ -178,44 +178,45 @@ static int __init armctrl_of_init(struct device_node *node,
178 * handle_IRQ may briefly re-enable interrupts for soft IRQ handling. 178 * handle_IRQ may briefly re-enable interrupts for soft IRQ handling.
179 */ 179 */
180 180
181static void armctrl_handle_bank(int bank, struct pt_regs *regs) 181static u32 armctrl_translate_bank(int bank)
182{ 182{
183 u32 stat, irq; 183 u32 stat = readl_relaxed(intc.pending[bank]);
184 184
185 while ((stat = readl_relaxed(intc.pending[bank]))) { 185 return MAKE_HWIRQ(bank, ffs(stat) - 1);
186 irq = MAKE_HWIRQ(bank, ffs(stat) - 1); 186}
187 handle_IRQ(irq_linear_revmap(intc.domain, irq), regs); 187
188 } 188static u32 armctrl_translate_shortcut(int bank, u32 stat)
189{
190 return MAKE_HWIRQ(bank, shortcuts[ffs(stat >> SHORTCUT_SHIFT) - 1]);
189} 191}
190 192
191static void armctrl_handle_shortcut(int bank, struct pt_regs *regs, 193static u32 get_next_armctrl_hwirq(void)
192 u32 stat)
193{ 194{
194 u32 irq = MAKE_HWIRQ(bank, shortcuts[ffs(stat >> SHORTCUT_SHIFT) - 1]); 195 u32 stat = readl_relaxed(intc.pending[0]) & BANK0_VALID_MASK;
195 handle_IRQ(irq_linear_revmap(intc.domain, irq), regs); 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();
196} 211}
197 212
198static void __exception_irq_entry bcm2835_handle_irq( 213static void __exception_irq_entry bcm2835_handle_irq(
199 struct pt_regs *regs) 214 struct pt_regs *regs)
200{ 215{
201 u32 stat, irq; 216 u32 hwirq;
202 217
203 while ((stat = readl_relaxed(intc.pending[0]) & BANK0_VALID_MASK)) { 218 while ((hwirq = get_next_armctrl_hwirq()) != ~0)
204 if (stat & BANK0_HWIRQ_MASK) { 219 handle_IRQ(irq_linear_revmap(intc.domain, hwirq), regs);
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 }
219} 220}
220 221
221IRQCHIP_DECLARE(bcm2835_armctrl_ic, "brcm,bcm2835-armctrl-ic", armctrl_of_init); 222IRQCHIP_DECLARE(bcm2835_armctrl_ic, "brcm,bcm2835-armctrl-ic", armctrl_of_init);