|
@@ -43,6 +43,7 @@ struct gic_intrmask_regs {
|
|
static struct gic_pcpu_mask pcpu_masks[NR_CPUS];
|
|
static struct gic_pcpu_mask pcpu_masks[NR_CPUS];
|
|
static struct gic_pending_regs pending_regs[NR_CPUS];
|
|
static struct gic_pending_regs pending_regs[NR_CPUS];
|
|
static struct gic_intrmask_regs intrmask_regs[NR_CPUS];
|
|
static struct gic_intrmask_regs intrmask_regs[NR_CPUS];
|
|
|
|
+static DEFINE_SPINLOCK(gic_lock);
|
|
|
|
|
|
#if defined(CONFIG_CSRC_GIC) || defined(CONFIG_CEVT_GIC)
|
|
#if defined(CONFIG_CSRC_GIC) || defined(CONFIG_CEVT_GIC)
|
|
cycle_t gic_read_count(void)
|
|
cycle_t gic_read_count(void)
|
|
@@ -244,9 +245,60 @@ static void gic_ack_irq(struct irq_data *d)
|
|
GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), d->irq - gic_irq_base);
|
|
GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), d->irq - gic_irq_base);
|
|
}
|
|
}
|
|
|
|
|
|
-#ifdef CONFIG_SMP
|
|
|
|
-static DEFINE_SPINLOCK(gic_lock);
|
|
|
|
|
|
+static int gic_set_type(struct irq_data *d, unsigned int type)
|
|
|
|
+{
|
|
|
|
+ unsigned int irq = d->irq - gic_irq_base;
|
|
|
|
+ unsigned long flags;
|
|
|
|
+ bool is_edge;
|
|
|
|
+
|
|
|
|
+ spin_lock_irqsave(&gic_lock, flags);
|
|
|
|
+ switch (type & IRQ_TYPE_SENSE_MASK) {
|
|
|
|
+ case IRQ_TYPE_EDGE_FALLING:
|
|
|
|
+ GIC_SET_POLARITY(irq, GIC_POL_NEG);
|
|
|
|
+ GIC_SET_TRIGGER(irq, GIC_TRIG_EDGE);
|
|
|
|
+ GIC_SET_DUAL(irq, GIC_TRIG_DUAL_DISABLE);
|
|
|
|
+ is_edge = true;
|
|
|
|
+ break;
|
|
|
|
+ case IRQ_TYPE_EDGE_RISING:
|
|
|
|
+ GIC_SET_POLARITY(irq, GIC_POL_POS);
|
|
|
|
+ GIC_SET_TRIGGER(irq, GIC_TRIG_EDGE);
|
|
|
|
+ GIC_SET_DUAL(irq, GIC_TRIG_DUAL_DISABLE);
|
|
|
|
+ is_edge = true;
|
|
|
|
+ break;
|
|
|
|
+ case IRQ_TYPE_EDGE_BOTH:
|
|
|
|
+ /* polarity is irrelevant in this case */
|
|
|
|
+ GIC_SET_TRIGGER(irq, GIC_TRIG_EDGE);
|
|
|
|
+ GIC_SET_DUAL(irq, GIC_TRIG_DUAL_ENABLE);
|
|
|
|
+ is_edge = true;
|
|
|
|
+ break;
|
|
|
|
+ case IRQ_TYPE_LEVEL_LOW:
|
|
|
|
+ GIC_SET_POLARITY(irq, GIC_POL_NEG);
|
|
|
|
+ GIC_SET_TRIGGER(irq, GIC_TRIG_LEVEL);
|
|
|
|
+ GIC_SET_DUAL(irq, GIC_TRIG_DUAL_DISABLE);
|
|
|
|
+ is_edge = false;
|
|
|
|
+ break;
|
|
|
|
+ case IRQ_TYPE_LEVEL_HIGH:
|
|
|
|
+ default:
|
|
|
|
+ GIC_SET_POLARITY(irq, GIC_POL_POS);
|
|
|
|
+ GIC_SET_TRIGGER(irq, GIC_TRIG_LEVEL);
|
|
|
|
+ GIC_SET_DUAL(irq, GIC_TRIG_DUAL_DISABLE);
|
|
|
|
+ is_edge = false;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
|
|
|
|
+ if (is_edge) {
|
|
|
|
+ gic_irq_flags[irq] |= GIC_TRIG_EDGE;
|
|
|
|
+ __irq_set_handler_locked(d->irq, handle_edge_irq);
|
|
|
|
+ } else {
|
|
|
|
+ gic_irq_flags[irq] &= ~GIC_TRIG_EDGE;
|
|
|
|
+ __irq_set_handler_locked(d->irq, handle_level_irq);
|
|
|
|
+ }
|
|
|
|
+ spin_unlock_irqrestore(&gic_lock, flags);
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+#ifdef CONFIG_SMP
|
|
static int gic_set_affinity(struct irq_data *d, const struct cpumask *cpumask,
|
|
static int gic_set_affinity(struct irq_data *d, const struct cpumask *cpumask,
|
|
bool force)
|
|
bool force)
|
|
{
|
|
{
|
|
@@ -282,6 +334,7 @@ static struct irq_chip gic_irq_controller = {
|
|
.irq_ack = gic_ack_irq,
|
|
.irq_ack = gic_ack_irq,
|
|
.irq_mask = gic_mask_irq,
|
|
.irq_mask = gic_mask_irq,
|
|
.irq_unmask = gic_unmask_irq,
|
|
.irq_unmask = gic_unmask_irq,
|
|
|
|
+ .irq_set_type = gic_set_type,
|
|
#ifdef CONFIG_SMP
|
|
#ifdef CONFIG_SMP
|
|
.irq_set_affinity = gic_set_affinity,
|
|
.irq_set_affinity = gic_set_affinity,
|
|
#endif
|
|
#endif
|