diff options
Diffstat (limited to 'drivers/irqchip/irq-mips-gic.c')
-rw-r--r-- | drivers/irqchip/irq-mips-gic.c | 57 |
1 files changed, 55 insertions, 2 deletions
diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c index 76658660ea4f..360b323a9862 100644 --- a/drivers/irqchip/irq-mips-gic.c +++ b/drivers/irqchip/irq-mips-gic.c | |||
@@ -43,6 +43,7 @@ struct gic_intrmask_regs { | |||
43 | static struct gic_pcpu_mask pcpu_masks[NR_CPUS]; | 43 | static struct gic_pcpu_mask pcpu_masks[NR_CPUS]; |
44 | static struct gic_pending_regs pending_regs[NR_CPUS]; | 44 | static struct gic_pending_regs pending_regs[NR_CPUS]; |
45 | static struct gic_intrmask_regs intrmask_regs[NR_CPUS]; | 45 | static struct gic_intrmask_regs intrmask_regs[NR_CPUS]; |
46 | static DEFINE_SPINLOCK(gic_lock); | ||
46 | 47 | ||
47 | #if defined(CONFIG_CSRC_GIC) || defined(CONFIG_CEVT_GIC) | 48 | #if defined(CONFIG_CSRC_GIC) || defined(CONFIG_CEVT_GIC) |
48 | cycle_t gic_read_count(void) | 49 | cycle_t gic_read_count(void) |
@@ -244,9 +245,60 @@ static void gic_ack_irq(struct irq_data *d) | |||
244 | GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), d->irq - gic_irq_base); | 245 | GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), d->irq - gic_irq_base); |
245 | } | 246 | } |
246 | 247 | ||
247 | #ifdef CONFIG_SMP | 248 | static int gic_set_type(struct irq_data *d, unsigned int type) |
248 | static DEFINE_SPINLOCK(gic_lock); | 249 | { |
250 | unsigned int irq = d->irq - gic_irq_base; | ||
251 | unsigned long flags; | ||
252 | bool is_edge; | ||
253 | |||
254 | spin_lock_irqsave(&gic_lock, flags); | ||
255 | switch (type & IRQ_TYPE_SENSE_MASK) { | ||
256 | case IRQ_TYPE_EDGE_FALLING: | ||
257 | GIC_SET_POLARITY(irq, GIC_POL_NEG); | ||
258 | GIC_SET_TRIGGER(irq, GIC_TRIG_EDGE); | ||
259 | GIC_SET_DUAL(irq, GIC_TRIG_DUAL_DISABLE); | ||
260 | is_edge = true; | ||
261 | break; | ||
262 | case IRQ_TYPE_EDGE_RISING: | ||
263 | GIC_SET_POLARITY(irq, GIC_POL_POS); | ||
264 | GIC_SET_TRIGGER(irq, GIC_TRIG_EDGE); | ||
265 | GIC_SET_DUAL(irq, GIC_TRIG_DUAL_DISABLE); | ||
266 | is_edge = true; | ||
267 | break; | ||
268 | case IRQ_TYPE_EDGE_BOTH: | ||
269 | /* polarity is irrelevant in this case */ | ||
270 | GIC_SET_TRIGGER(irq, GIC_TRIG_EDGE); | ||
271 | GIC_SET_DUAL(irq, GIC_TRIG_DUAL_ENABLE); | ||
272 | is_edge = true; | ||
273 | break; | ||
274 | case IRQ_TYPE_LEVEL_LOW: | ||
275 | GIC_SET_POLARITY(irq, GIC_POL_NEG); | ||
276 | GIC_SET_TRIGGER(irq, GIC_TRIG_LEVEL); | ||
277 | GIC_SET_DUAL(irq, GIC_TRIG_DUAL_DISABLE); | ||
278 | is_edge = false; | ||
279 | break; | ||
280 | case IRQ_TYPE_LEVEL_HIGH: | ||
281 | default: | ||
282 | GIC_SET_POLARITY(irq, GIC_POL_POS); | ||
283 | GIC_SET_TRIGGER(irq, GIC_TRIG_LEVEL); | ||
284 | GIC_SET_DUAL(irq, GIC_TRIG_DUAL_DISABLE); | ||
285 | is_edge = false; | ||
286 | break; | ||
287 | } | ||
249 | 288 | ||
289 | if (is_edge) { | ||
290 | gic_irq_flags[irq] |= GIC_TRIG_EDGE; | ||
291 | __irq_set_handler_locked(d->irq, handle_edge_irq); | ||
292 | } else { | ||
293 | gic_irq_flags[irq] &= ~GIC_TRIG_EDGE; | ||
294 | __irq_set_handler_locked(d->irq, handle_level_irq); | ||
295 | } | ||
296 | spin_unlock_irqrestore(&gic_lock, flags); | ||
297 | |||
298 | return 0; | ||
299 | } | ||
300 | |||
301 | #ifdef CONFIG_SMP | ||
250 | static int gic_set_affinity(struct irq_data *d, const struct cpumask *cpumask, | 302 | static int gic_set_affinity(struct irq_data *d, const struct cpumask *cpumask, |
251 | bool force) | 303 | bool force) |
252 | { | 304 | { |
@@ -282,6 +334,7 @@ static struct irq_chip gic_irq_controller = { | |||
282 | .irq_ack = gic_ack_irq, | 334 | .irq_ack = gic_ack_irq, |
283 | .irq_mask = gic_mask_irq, | 335 | .irq_mask = gic_mask_irq, |
284 | .irq_unmask = gic_unmask_irq, | 336 | .irq_unmask = gic_unmask_irq, |
337 | .irq_set_type = gic_set_type, | ||
285 | #ifdef CONFIG_SMP | 338 | #ifdef CONFIG_SMP |
286 | .irq_set_affinity = gic_set_affinity, | 339 | .irq_set_affinity = gic_set_affinity, |
287 | #endif | 340 | #endif |