diff options
Diffstat (limited to 'drivers/irqchip/irq-mips-gic.c')
-rw-r--r-- | drivers/irqchip/irq-mips-gic.c | 46 |
1 files changed, 37 insertions, 9 deletions
diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c index f2d269bca789..57f09cb54464 100644 --- a/drivers/irqchip/irq-mips-gic.c +++ b/drivers/irqchip/irq-mips-gic.c @@ -239,7 +239,7 @@ int gic_get_c0_compare_int(void) int gic_get_c0_perfcount_int(void) { if (!gic_local_irq_is_routable(GIC_LOCAL_INT_PERFCTR)) { - /* Is the erformance counter shared with the timer? */ + /* Is the performance counter shared with the timer? */ if (cp0_perfcount_irq < 0) return -1; return MIPS_CPU_IRQ_BASE + cp0_perfcount_irq; @@ -248,6 +248,29 @@ int gic_get_c0_perfcount_int(void) GIC_LOCAL_TO_HWIRQ(GIC_LOCAL_INT_PERFCTR)); } +int gic_get_c0_fdc_int(void) +{ + if (!gic_local_irq_is_routable(GIC_LOCAL_INT_FDC)) { + /* Is the FDC IRQ even present? */ + if (cp0_fdc_irq < 0) + return -1; + return MIPS_CPU_IRQ_BASE + cp0_fdc_irq; + } + + /* + * Some cores claim the FDC is routable but it doesn't actually seem to + * be connected. + */ + switch (current_cpu_type()) { + case CPU_INTERAPTIV: + case CPU_PROAPTIV: + return -1; + } + + return irq_create_mapping(gic_irq_domain, + GIC_LOCAL_TO_HWIRQ(GIC_LOCAL_INT_FDC)); +} + static void gic_handle_shared_int(void) { unsigned int i, intr, virq; @@ -366,19 +389,19 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *cpumask, int i; cpumask_and(&tmp, cpumask, cpu_online_mask); - if (cpus_empty(tmp)) + if (cpumask_empty(&tmp)) return -EINVAL; /* Assumption : cpumask refers to a single CPU */ spin_lock_irqsave(&gic_lock, flags); /* Re-route this IRQ */ - gic_map_to_vpe(irq, first_cpu(tmp)); + gic_map_to_vpe(irq, cpumask_first(&tmp)); /* Update the pcpu_masks */ for (i = 0; i < NR_CPUS; i++) clear_bit(irq, pcpu_masks[i].pcpu_mask); - set_bit(irq, pcpu_masks[first_cpu(tmp)].pcpu_mask); + set_bit(irq, pcpu_masks[cpumask_first(&tmp)].pcpu_mask); cpumask_copy(d->affinity, cpumask); spin_unlock_irqrestore(&gic_lock, flags); @@ -613,15 +636,20 @@ static int gic_local_irq_domain_map(struct irq_domain *d, unsigned int virq, * of the MIPS kernel code does not use the percpu IRQ API for * the CP0 timer and performance counter interrupts. */ - if (intr != GIC_LOCAL_INT_TIMER && intr != GIC_LOCAL_INT_PERFCTR) { + switch (intr) { + case GIC_LOCAL_INT_TIMER: + case GIC_LOCAL_INT_PERFCTR: + case GIC_LOCAL_INT_FDC: + irq_set_chip_and_handler(virq, + &gic_all_vpes_local_irq_controller, + handle_percpu_irq); + break; + default: irq_set_chip_and_handler(virq, &gic_local_irq_controller, handle_percpu_devid_irq); irq_set_percpu_devid(virq); - } else { - irq_set_chip_and_handler(virq, - &gic_all_vpes_local_irq_controller, - handle_percpu_irq); + break; } spin_lock_irqsave(&gic_lock, flags); |