Commit ec79b577 authored by Thomas Gleixner's avatar Thomas Gleixner

Merge tag 'irqchip-mvebu-fixes-3.14' of git://git.infradead.org/linux-mvebu into irq/urgent

irqchip mvebu fixes for v3.14

 - orion:
    - fixes for clearing bridge cause register, and clearing stale interrupts
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
parents 2c45aada d86e9af6
...@@ -111,7 +111,8 @@ IRQCHIP_DECLARE(orion_intc, "marvell,orion-intc", orion_irq_init); ...@@ -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) static void orion_bridge_irq_handler(unsigned int irq, struct irq_desc *desc)
{ {
struct irq_domain *d = irq_get_handler_data(irq); 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) & u32 stat = readl_relaxed(gc->reg_base + ORION_BRIDGE_IRQ_CAUSE) &
gc->mask_cache; gc->mask_cache;
...@@ -123,6 +124,19 @@ static void orion_bridge_irq_handler(unsigned int irq, struct irq_desc *desc) ...@@ -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, static int __init orion_bridge_irq_init(struct device_node *np,
struct device_node *parent) struct device_node *parent)
{ {
...@@ -143,7 +157,7 @@ static int __init orion_bridge_irq_init(struct device_node *np, ...@@ -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, 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) { if (ret) {
pr_err("%s: unable to alloc irq domain gc\n", np->name); pr_err("%s: unable to alloc irq domain gc\n", np->name);
return ret; return ret;
...@@ -176,12 +190,14 @@ static int __init orion_bridge_irq_init(struct device_node *np, ...@@ -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.ack = ORION_BRIDGE_IRQ_CAUSE;
gc->chip_types[0].regs.mask = ORION_BRIDGE_IRQ_MASK; 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_ack = irq_gc_ack_clr_bit;
gc->chip_types[0].chip.irq_mask = irq_gc_mask_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; 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_MASK);
writel(0, gc->reg_base + ORION_BRIDGE_IRQ_CAUSE);
irq_set_handler_data(irq, domain); irq_set_handler_data(irq, domain);
irq_set_chained_handler(irq, orion_bridge_irq_handler); irq_set_chained_handler(irq, orion_bridge_irq_handler);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment