diff options
| -rw-r--r-- | drivers/irqchip/irq-mips-gic.c | 27 |
1 files changed, 27 insertions, 0 deletions
diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c index 2b0468e3df6a..56b96c63dc4b 100644 --- a/drivers/irqchip/irq-mips-gic.c +++ b/drivers/irqchip/irq-mips-gic.c | |||
| @@ -37,6 +37,7 @@ static struct irq_domain *gic_irq_domain; | |||
| 37 | static int gic_shared_intrs; | 37 | static int gic_shared_intrs; |
| 38 | static int gic_vpes; | 38 | static int gic_vpes; |
| 39 | static unsigned int gic_cpu_pin; | 39 | static unsigned int gic_cpu_pin; |
| 40 | static unsigned int timer_cpu_pin; | ||
| 40 | static struct irq_chip gic_level_irq_controller, gic_edge_irq_controller; | 41 | static struct irq_chip gic_level_irq_controller, gic_edge_irq_controller; |
| 41 | 42 | ||
| 42 | static void __gic_irq_dispatch(void); | 43 | static void __gic_irq_dispatch(void); |
| @@ -616,6 +617,8 @@ static int gic_local_irq_domain_map(struct irq_domain *d, unsigned int virq, | |||
| 616 | gic_write(GIC_REG(VPE_OTHER, GIC_VPE_COMPARE_MAP), val); | 617 | gic_write(GIC_REG(VPE_OTHER, GIC_VPE_COMPARE_MAP), val); |
| 617 | break; | 618 | break; |
| 618 | case GIC_LOCAL_INT_TIMER: | 619 | case GIC_LOCAL_INT_TIMER: |
| 620 | /* CONFIG_MIPS_CMP workaround (see __gic_init) */ | ||
| 621 | val = GIC_MAP_TO_PIN_MSK | timer_cpu_pin; | ||
| 619 | gic_write(GIC_REG(VPE_OTHER, GIC_VPE_TIMER_MAP), val); | 622 | gic_write(GIC_REG(VPE_OTHER, GIC_VPE_TIMER_MAP), val); |
| 620 | break; | 623 | break; |
| 621 | case GIC_LOCAL_INT_PERFCTR: | 624 | case GIC_LOCAL_INT_PERFCTR: |
| @@ -713,12 +716,36 @@ static void __init __gic_init(unsigned long gic_base_addr, | |||
| 713 | if (cpu_has_veic) { | 716 | if (cpu_has_veic) { |
| 714 | /* Always use vector 1 in EIC mode */ | 717 | /* Always use vector 1 in EIC mode */ |
| 715 | gic_cpu_pin = 0; | 718 | gic_cpu_pin = 0; |
| 719 | timer_cpu_pin = gic_cpu_pin; | ||
| 716 | set_vi_handler(gic_cpu_pin + GIC_PIN_TO_VEC_OFFSET, | 720 | set_vi_handler(gic_cpu_pin + GIC_PIN_TO_VEC_OFFSET, |
| 717 | __gic_irq_dispatch); | 721 | __gic_irq_dispatch); |
| 718 | } else { | 722 | } else { |
| 719 | gic_cpu_pin = cpu_vec - GIC_CPU_PIN_OFFSET; | 723 | gic_cpu_pin = cpu_vec - GIC_CPU_PIN_OFFSET; |
| 720 | irq_set_chained_handler(MIPS_CPU_IRQ_BASE + cpu_vec, | 724 | irq_set_chained_handler(MIPS_CPU_IRQ_BASE + cpu_vec, |
| 721 | gic_irq_dispatch); | 725 | gic_irq_dispatch); |
| 726 | /* | ||
| 727 | * With the CMP implementation of SMP (deprecated), other CPUs | ||
| 728 | * are started by the bootloader and put into a timer based | ||
| 729 | * waiting poll loop. We must not re-route those CPU's local | ||
| 730 | * timer interrupts as the wait instruction will never finish, | ||
| 731 | * so just handle whatever CPU interrupt it is routed to by | ||
| 732 | * default. | ||
| 733 | * | ||
| 734 | * This workaround should be removed when CMP support is | ||
| 735 | * dropped. | ||
| 736 | */ | ||
| 737 | if (IS_ENABLED(CONFIG_MIPS_CMP) && | ||
| 738 | gic_local_irq_is_routable(GIC_LOCAL_INT_TIMER)) { | ||
| 739 | timer_cpu_pin = gic_read(GIC_REG(VPE_LOCAL, | ||
| 740 | GIC_VPE_TIMER_MAP)) & | ||
| 741 | GIC_MAP_MSK; | ||
| 742 | irq_set_chained_handler(MIPS_CPU_IRQ_BASE + | ||
| 743 | GIC_CPU_PIN_OFFSET + | ||
| 744 | timer_cpu_pin, | ||
| 745 | gic_irq_dispatch); | ||
| 746 | } else { | ||
| 747 | timer_cpu_pin = gic_cpu_pin; | ||
| 748 | } | ||
| 722 | } | 749 | } |
| 723 | 750 | ||
| 724 | gic_irq_domain = irq_domain_add_simple(node, GIC_NUM_LOCAL_INTRS + | 751 | gic_irq_domain = irq_domain_add_simple(node, GIC_NUM_LOCAL_INTRS + |
