MIPS: BCM63xx: Wire up the second cpu's irq line
authorJonas Gorski <jogo@openwrt.org>
Sat, 12 Jul 2014 10:49:40 +0000 (12:49 +0200)
committerRalf Baechle <ralf@linux-mips.org>
Wed, 30 Jul 2014 13:29:41 +0000 (15:29 +0200)
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
Cc: linux-mips@linux-mips.org
Cc: John Crispin <blogic@openwrt.org>
Cc: Maxime Bizon <mbizon@freebox.fr>
Cc: Florian Fainelli <florian@openwrt.org>
Cc: Kevin Cernekee <cernekee@gmail.com>
Cc: Gregory Fong <gregory.0xf0@gmail.com>
Patchwork: https://patchwork.linux-mips.org/patch/7322/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
arch/mips/bcm63xx/irq.c

index 2f1939122bc347ecd8d0b7e3e269a4a5c887264e..615b25bb34f5fcfbf1361558a2782fbe06d24e2c 100644 (file)
@@ -102,11 +102,17 @@ static void __internal_irq_mask_##width(unsigned int irq)         \
        unsigned reg = (irq / 32) ^ (width/32 - 1);                     \
        unsigned bit = irq & 0x1f;                                      \
        unsigned long flags;                                            \
+       int cpu;                                                        \
                                                                        \
        spin_lock_irqsave(&ipic_lock, flags);                           \
-       val = bcm_readl(irq_mask_addr[0] + reg * sizeof(u32));          \
-       val &= ~(1 << bit);                                             \
-       bcm_writel(val, irq_mask_addr[0] + reg * sizeof(u32));          \
+       for_each_present_cpu(cpu) {                                     \
+               if (!irq_mask_addr[cpu])                                \
+                       break;                                          \
+                                                                       \
+               val = bcm_readl(irq_mask_addr[cpu] + reg * sizeof(u32));\
+               val &= ~(1 << bit);                                     \
+               bcm_writel(val, irq_mask_addr[cpu] + reg * sizeof(u32));\
+       }                                                               \
        spin_unlock_irqrestore(&ipic_lock, flags);                      \
 }                                                                      \
                                                                        \
@@ -116,11 +122,20 @@ static void __internal_irq_unmask_##width(unsigned int irq)               \
        unsigned reg = (irq / 32) ^ (width/32 - 1);                     \
        unsigned bit = irq & 0x1f;                                      \
        unsigned long flags;                                            \
+       int cpu;                                                        \
                                                                        \
        spin_lock_irqsave(&ipic_lock, flags);                           \
-       val = bcm_readl(irq_mask_addr[0] + reg * sizeof(u32));          \
-       val |= (1 << bit);                                              \
-       bcm_writel(val, irq_mask_addr[0] + reg * sizeof(u32));          \
+       for_each_present_cpu(cpu) {                                     \
+               if (!irq_mask_addr[cpu])                                \
+                       break;                                          \
+                                                                       \
+               val = bcm_readl(irq_mask_addr[cpu] + reg * sizeof(u32));\
+               if (cpu_online(cpu))                                    \
+                       val |= (1 << bit);                              \
+               else                                                    \
+                       val &= ~(1 << bit);                             \
+               bcm_writel(val, irq_mask_addr[cpu] + reg * sizeof(u32));\
+       }                                                               \
        spin_unlock_irqrestore(&ipic_lock, flags);                      \
 }
 
@@ -145,7 +160,10 @@ asmlinkage void plat_irq_dispatch(void)
                        do_IRQ(1);
                if (cause & CAUSEF_IP2)
                        dispatch_internal(0);
-               if (!is_ext_irq_cascaded) {
+               if (is_ext_irq_cascaded) {
+                       if (cause & CAUSEF_IP3)
+                               dispatch_internal(1);
+               } else {
                        if (cause & CAUSEF_IP3)
                                do_IRQ(IRQ_EXT_0);
                        if (cause & CAUSEF_IP4)
@@ -358,6 +376,14 @@ static struct irqaction cpu_ip2_cascade_action = {
        .flags          = IRQF_NO_THREAD,
 };
 
+#ifdef CONFIG_SMP
+static struct irqaction cpu_ip3_cascade_action = {
+       .handler        = no_action,
+       .name           = "cascade_ip3",
+       .flags          = IRQF_NO_THREAD,
+};
+#endif
+
 static struct irqaction cpu_ext_cascade_action = {
        .handler        = no_action,
        .name           = "cascade_extirq",
@@ -494,4 +520,8 @@ void __init arch_init_irq(void)
        }
 
        setup_irq(MIPS_CPU_IRQ_BASE + 2, &cpu_ip2_cascade_action);
+#ifdef CONFIG_SMP
+       if (is_ext_irq_cascaded)
+               setup_irq(MIPS_CPU_IRQ_BASE + 3, &cpu_ip3_cascade_action);
+#endif
 }