diff options
author | Arnd Bergmann <arnd@arndb.de> | 2014-02-25 17:49:13 +0100 |
---|---|---|
committer | Arnd Bergmann <arnd@arndb.de> | 2014-02-25 17:49:35 +0100 |
commit | 96f9d40db89fbf59f0f115877ab90d94bb66f503 (patch) | |
tree | fd0ce70119d00c03c89c6fcc90e01fea76ae6d5b /drivers/irqchip | |
parent | 8c4a57bcd80532c4fef5f87d0c53be25718294ed (diff) | |
parent | d86e9af6336c0ad586a5dbd70064253d40bbb5ff (diff) |
Merge tag 'irqchip-mvebu-fixes-3.14' of git://git.infradead.org/linux-mvebu into next/drivers
irqchip mvebu fixes for v3.14
- orion:
- fixes for clearing bridge cause register, and clearing stale interrupts
* tag 'irqchip-mvebu-fixes-3.14' of git://git.infradead.org/linux-mvebu:
irqchip: orion: Fix getting generic chip pointer.
irqchip: orion: clear stale interrupts in irq_startup
irqchip: orion: use handle_edge_irq on bridge irqs
irqchip: orion: clear bridge cause register on init
This is a dependency for the mvebu watchdog changes.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Diffstat (limited to 'drivers/irqchip')
-rw-r--r-- | drivers/irqchip/irq-orion.c | 22 |
1 files changed, 19 insertions, 3 deletions
diff --git a/drivers/irqchip/irq-orion.c b/drivers/irqchip/irq-orion.c index e51d40031884..8e41be62812e 100644 --- a/drivers/irqchip/irq-orion.c +++ b/drivers/irqchip/irq-orion.c @@ -111,7 +111,8 @@ IRQCHIP_DECLARE(orion_intc, "marvell,orion-intc", orion_irq_init); static void orion_bridge_irq_handler(unsigned int irq, struct irq_desc *desc) { struct irq_domain *d = irq_get_handler_data(irq); - struct irq_chip_generic *gc = irq_get_domain_generic_chip(d, irq); + + struct irq_chip_generic *gc = irq_get_domain_generic_chip(d, 0); u32 stat = readl_relaxed(gc->reg_base + ORION_BRIDGE_IRQ_CAUSE) & gc->mask_cache; @@ -123,6 +124,19 @@ static void orion_bridge_irq_handler(unsigned int irq, struct irq_desc *desc) } } +/* + * Bridge IRQ_CAUSE is asserted regardless of IRQ_MASK register. + * To avoid interrupt events on stale irqs, we clear them before unmask. + */ +static unsigned int orion_bridge_irq_startup(struct irq_data *d) +{ + struct irq_chip_type *ct = irq_data_get_chip_type(d); + + ct->chip.irq_ack(d); + ct->chip.irq_unmask(d); + return 0; +} + static int __init orion_bridge_irq_init(struct device_node *np, struct device_node *parent) { @@ -143,7 +157,7 @@ static int __init orion_bridge_irq_init(struct device_node *np, } ret = irq_alloc_domain_generic_chips(domain, nrirqs, 1, np->name, - handle_level_irq, clr, 0, IRQ_GC_INIT_MASK_CACHE); + handle_edge_irq, clr, 0, IRQ_GC_INIT_MASK_CACHE); if (ret) { pr_err("%s: unable to alloc irq domain gc\n", np->name); return ret; @@ -176,12 +190,14 @@ static int __init orion_bridge_irq_init(struct device_node *np, gc->chip_types[0].regs.ack = ORION_BRIDGE_IRQ_CAUSE; gc->chip_types[0].regs.mask = ORION_BRIDGE_IRQ_MASK; + gc->chip_types[0].chip.irq_startup = orion_bridge_irq_startup; gc->chip_types[0].chip.irq_ack = irq_gc_ack_clr_bit; gc->chip_types[0].chip.irq_mask = irq_gc_mask_clr_bit; gc->chip_types[0].chip.irq_unmask = irq_gc_mask_set_bit; - /* mask all interrupts */ + /* mask and clear all interrupts */ writel(0, gc->reg_base + ORION_BRIDGE_IRQ_MASK); + writel(0, gc->reg_base + ORION_BRIDGE_IRQ_CAUSE); irq_set_handler_data(irq, domain); irq_set_chained_handler(irq, orion_bridge_irq_handler); |