aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/irqchip/irq-orion.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/irqchip/irq-orion.c')
-rw-r--r--drivers/irqchip/irq-orion.c22
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);
111static void orion_bridge_irq_handler(unsigned int irq, struct irq_desc *desc) 111static void orion_bridge_irq_handler(unsigned int irq, struct irq_desc *desc)
112{ 112{
113 struct irq_domain *d = irq_get_handler_data(irq); 113 struct irq_domain *d = irq_get_handler_data(irq);
114 struct irq_chip_generic *gc = irq_get_domain_generic_chip(d, irq); 114
115 struct irq_chip_generic *gc = irq_get_domain_generic_chip(d, 0);
115 u32 stat = readl_relaxed(gc->reg_base + ORION_BRIDGE_IRQ_CAUSE) & 116 u32 stat = readl_relaxed(gc->reg_base + ORION_BRIDGE_IRQ_CAUSE) &
116 gc->mask_cache; 117 gc->mask_cache;
117 118
@@ -123,6 +124,19 @@ static void orion_bridge_irq_handler(unsigned int irq, struct irq_desc *desc)
123 } 124 }
124} 125}
125 126
127/*
128 * Bridge IRQ_CAUSE is asserted regardless of IRQ_MASK register.
129 * To avoid interrupt events on stale irqs, we clear them before unmask.
130 */
131static unsigned int orion_bridge_irq_startup(struct irq_data *d)
132{
133 struct irq_chip_type *ct = irq_data_get_chip_type(d);
134
135 ct->chip.irq_ack(d);
136 ct->chip.irq_unmask(d);
137 return 0;
138}
139
126static int __init orion_bridge_irq_init(struct device_node *np, 140static int __init orion_bridge_irq_init(struct device_node *np,
127 struct device_node *parent) 141 struct device_node *parent)
128{ 142{
@@ -143,7 +157,7 @@ static int __init orion_bridge_irq_init(struct device_node *np,
143 } 157 }
144 158
145 ret = irq_alloc_domain_generic_chips(domain, nrirqs, 1, np->name, 159 ret = irq_alloc_domain_generic_chips(domain, nrirqs, 1, np->name,
146 handle_level_irq, clr, 0, IRQ_GC_INIT_MASK_CACHE); 160 handle_edge_irq, clr, 0, IRQ_GC_INIT_MASK_CACHE);
147 if (ret) { 161 if (ret) {
148 pr_err("%s: unable to alloc irq domain gc\n", np->name); 162 pr_err("%s: unable to alloc irq domain gc\n", np->name);
149 return ret; 163 return ret;
@@ -176,12 +190,14 @@ static int __init orion_bridge_irq_init(struct device_node *np,
176 190
177 gc->chip_types[0].regs.ack = ORION_BRIDGE_IRQ_CAUSE; 191 gc->chip_types[0].regs.ack = ORION_BRIDGE_IRQ_CAUSE;
178 gc->chip_types[0].regs.mask = ORION_BRIDGE_IRQ_MASK; 192 gc->chip_types[0].regs.mask = ORION_BRIDGE_IRQ_MASK;
193 gc->chip_types[0].chip.irq_startup = orion_bridge_irq_startup;
179 gc->chip_types[0].chip.irq_ack = irq_gc_ack_clr_bit; 194 gc->chip_types[0].chip.irq_ack = irq_gc_ack_clr_bit;
180 gc->chip_types[0].chip.irq_mask = irq_gc_mask_clr_bit; 195 gc->chip_types[0].chip.irq_mask = irq_gc_mask_clr_bit;
181 gc->chip_types[0].chip.irq_unmask = irq_gc_mask_set_bit; 196 gc->chip_types[0].chip.irq_unmask = irq_gc_mask_set_bit;
182 197
183 /* mask all interrupts */ 198 /* mask and clear all interrupts */
184 writel(0, gc->reg_base + ORION_BRIDGE_IRQ_MASK); 199 writel(0, gc->reg_base + ORION_BRIDGE_IRQ_MASK);
200 writel(0, gc->reg_base + ORION_BRIDGE_IRQ_CAUSE);
185 201
186 irq_set_handler_data(irq, domain); 202 irq_set_handler_data(irq, domain);
187 irq_set_chained_handler(irq, orion_bridge_irq_handler); 203 irq_set_chained_handler(irq, orion_bridge_irq_handler);