diff options
author | Andrew Bresticker <abrestic@chromium.org> | 2014-09-18 17:47:26 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2014-11-24 01:44:56 -0500 |
commit | 4a6a3ea392306b04fc687d4314efba562121cc9a (patch) | |
tree | 108812971050e86179140b7754d335b54b134509 /drivers/irqchip/irq-mips-gic.c | |
parent | fbd552417bf275f6da591a0118a019b3006245fd (diff) |
irqchip: mips-gic: Use separate edge/level irq_chips
GIC edge-triggered interrupts must be acknowledged by clearing the edge
detector via a write to GIC_SH_WEDGE. Create a separate edge-triggered
irq_chip with the appropriate irq_ack() callback. This also allows us
to get rid of gic_irq_flags.
Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
Acked-by: Jason Cooper <jason@lakedaemon.net>
Reviewed-by: Qais Yousef <qais.yousef@imgtec.com>
Tested-by: Qais Yousef <qais.yousef@imgtec.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Jeffrey Deans <jeffrey.deans@imgtec.com>
Cc: Markos Chandras <markos.chandras@imgtec.com>
Cc: Paul Burton <paul.burton@imgtec.com>
Cc: Jonas Gorski <jogo@openwrt.org>
Cc: John Crispin <blogic@openwrt.org>
Cc: David Daney <ddaney.cavm@gmail.com>
Cc: linux-mips@linux-mips.org
Cc: linux-kernel@vger.kernel.org
Patchwork: https://patchwork.linux-mips.org/patch/7818/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'drivers/irqchip/irq-mips-gic.c')
-rw-r--r-- | drivers/irqchip/irq-mips-gic.c | 32 |
1 files changed, 21 insertions, 11 deletions
diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c index 3cd91d34973d..64d7d571df62 100644 --- a/drivers/irqchip/irq-mips-gic.c +++ b/drivers/irqchip/irq-mips-gic.c | |||
@@ -24,7 +24,6 @@ | |||
24 | unsigned int gic_frequency; | 24 | unsigned int gic_frequency; |
25 | unsigned int gic_present; | 25 | unsigned int gic_present; |
26 | unsigned long _gic_base; | 26 | unsigned long _gic_base; |
27 | unsigned int gic_irq_flags[GIC_NUM_INTRS]; | ||
28 | unsigned int gic_cpu_pin; | 27 | unsigned int gic_cpu_pin; |
29 | 28 | ||
30 | struct gic_pcpu_mask { | 29 | struct gic_pcpu_mask { |
@@ -45,6 +44,7 @@ static struct gic_intrmask_regs intrmask_regs[NR_CPUS]; | |||
45 | static DEFINE_SPINLOCK(gic_lock); | 44 | static DEFINE_SPINLOCK(gic_lock); |
46 | static struct irq_domain *gic_irq_domain; | 45 | static struct irq_domain *gic_irq_domain; |
47 | static int gic_shared_intrs; | 46 | static int gic_shared_intrs; |
47 | static struct irq_chip gic_level_irq_controller, gic_edge_irq_controller; | ||
48 | 48 | ||
49 | static void __gic_irq_dispatch(void); | 49 | static void __gic_irq_dispatch(void); |
50 | 50 | ||
@@ -229,9 +229,7 @@ static void gic_ack_irq(struct irq_data *d) | |||
229 | { | 229 | { |
230 | unsigned int irq = d->hwirq; | 230 | unsigned int irq = d->hwirq; |
231 | 231 | ||
232 | /* Clear edge detector */ | 232 | GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), irq); |
233 | if (gic_irq_flags[irq] & GIC_TRIG_EDGE) | ||
234 | GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), irq); | ||
235 | } | 233 | } |
236 | 234 | ||
237 | static int gic_set_type(struct irq_data *d, unsigned int type) | 235 | static int gic_set_type(struct irq_data *d, unsigned int type) |
@@ -276,11 +274,13 @@ static int gic_set_type(struct irq_data *d, unsigned int type) | |||
276 | } | 274 | } |
277 | 275 | ||
278 | if (is_edge) { | 276 | if (is_edge) { |
279 | gic_irq_flags[irq] |= GIC_TRIG_EDGE; | 277 | __irq_set_chip_handler_name_locked(d->irq, |
280 | __irq_set_handler_locked(d->irq, handle_edge_irq); | 278 | &gic_edge_irq_controller, |
279 | handle_edge_irq, NULL); | ||
281 | } else { | 280 | } else { |
282 | gic_irq_flags[irq] &= ~GIC_TRIG_EDGE; | 281 | __irq_set_chip_handler_name_locked(d->irq, |
283 | __irq_set_handler_locked(d->irq, handle_level_irq); | 282 | &gic_level_irq_controller, |
283 | handle_level_irq, NULL); | ||
284 | } | 284 | } |
285 | spin_unlock_irqrestore(&gic_lock, flags); | 285 | spin_unlock_irqrestore(&gic_lock, flags); |
286 | 286 | ||
@@ -318,7 +318,17 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *cpumask, | |||
318 | } | 318 | } |
319 | #endif | 319 | #endif |
320 | 320 | ||
321 | static struct irq_chip gic_irq_controller = { | 321 | static struct irq_chip gic_level_irq_controller = { |
322 | .name = "MIPS GIC", | ||
323 | .irq_mask = gic_mask_irq, | ||
324 | .irq_unmask = gic_unmask_irq, | ||
325 | .irq_set_type = gic_set_type, | ||
326 | #ifdef CONFIG_SMP | ||
327 | .irq_set_affinity = gic_set_affinity, | ||
328 | #endif | ||
329 | }; | ||
330 | |||
331 | static struct irq_chip gic_edge_irq_controller = { | ||
322 | .name = "MIPS GIC", | 332 | .name = "MIPS GIC", |
323 | .irq_ack = gic_ack_irq, | 333 | .irq_ack = gic_ack_irq, |
324 | .irq_mask = gic_mask_irq, | 334 | .irq_mask = gic_mask_irq, |
@@ -431,7 +441,6 @@ static void __init gic_basic_init(int numvpes) | |||
431 | GIC_SET_POLARITY(i, GIC_POL_POS); | 441 | GIC_SET_POLARITY(i, GIC_POL_POS); |
432 | GIC_SET_TRIGGER(i, GIC_TRIG_LEVEL); | 442 | GIC_SET_TRIGGER(i, GIC_TRIG_LEVEL); |
433 | GIC_CLR_INTR_MASK(i); | 443 | GIC_CLR_INTR_MASK(i); |
434 | gic_irq_flags[i] = 0; | ||
435 | } | 444 | } |
436 | 445 | ||
437 | vpe_local_setup(numvpes); | 446 | vpe_local_setup(numvpes); |
@@ -442,7 +451,8 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int virq, | |||
442 | { | 451 | { |
443 | unsigned long flags; | 452 | unsigned long flags; |
444 | 453 | ||
445 | irq_set_chip_and_handler(virq, &gic_irq_controller, handle_level_irq); | 454 | irq_set_chip_and_handler(virq, &gic_level_irq_controller, |
455 | handle_level_irq); | ||
446 | 456 | ||
447 | spin_lock_irqsave(&gic_lock, flags); | 457 | spin_lock_irqsave(&gic_lock, flags); |
448 | GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_PIN(hw)), | 458 | GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_PIN(hw)), |