aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/irqchip/irq-mips-gic.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/irqchip/irq-mips-gic.c')
-rw-r--r--drivers/irqchip/irq-mips-gic.c57
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 {
43static struct gic_pcpu_mask pcpu_masks[NR_CPUS]; 43static struct gic_pcpu_mask pcpu_masks[NR_CPUS];
44static struct gic_pending_regs pending_regs[NR_CPUS]; 44static struct gic_pending_regs pending_regs[NR_CPUS];
45static struct gic_intrmask_regs intrmask_regs[NR_CPUS]; 45static struct gic_intrmask_regs intrmask_regs[NR_CPUS];
46static 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)
48cycle_t gic_read_count(void) 49cycle_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 248static int gic_set_type(struct irq_data *d, unsigned int type)
248static 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
250static int gic_set_affinity(struct irq_data *d, const struct cpumask *cpumask, 302static 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