powerpc: Add support for CoreInt delivery of interrupts on MPIC
authorKumar Gala <galak@kernel.crashing.org>
Wed, 7 Jan 2009 21:53:29 +0000 (15:53 -0600)
committerKumar Gala <galak@kernel.crashing.org>
Mon, 6 Apr 2009 14:09:14 +0000 (09:09 -0500)
CoreInt provides a mechansim to deliver the IRQ vector directly
into the core on an interrupt (via the SPR EPR) rather than having
to go IACK on the PIC.  This is suppose to provide an improvment
in interrupt latency by reducing the time to get the IRQ vector.

Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
arch/powerpc/include/asm/mpic.h
arch/powerpc/sysdev/mpic.c

index c2ccca5..a002682 100644 (file)
 #define MPIC_GREG_FEATURE_1            0x00010
 #define MPIC_GREG_GLOBAL_CONF_0                0x00020
 #define                MPIC_GREG_GCONF_RESET                   0x80000000
+/* On the FSL mpic implementations the Mode field is expand to be
+ * 2 bits wide:
+ *     0b00 = pass through (interrupts routed to IRQ0)
+ *     0b01 = Mixed mode
+ *     0b10 = reserved
+ *     0b11 = External proxy / coreint
+ */
+#define                MPIC_GREG_GCONF_COREINT                 0x60000000
 #define                MPIC_GREG_GCONF_8259_PTHROU_DIS         0x20000000
 #define                MPIC_GREG_GCONF_NO_BIAS                 0x10000000
 #define                MPIC_GREG_GCONF_BASE_MASK               0x000fffff
@@ -357,6 +365,8 @@ struct mpic
 #define MPIC_BROKEN_FRR_NIRQS          0x00000800
 /* Destination only supports a single CPU at a time */
 #define MPIC_SINGLE_DEST_CPU           0x00001000
+/* Enable CoreInt delivery of interrupts */
+#define MPIC_ENABLE_COREINT            0x00002000
 
 /* MPIC HW modification ID */
 #define MPIC_REGSET_MASK               0xf0000000
@@ -470,6 +480,8 @@ extern void mpic_end_irq(unsigned int irq);
 extern unsigned int mpic_get_one_irq(struct mpic *mpic);
 /* This one gets from the primary mpic */
 extern unsigned int mpic_get_irq(void);
+/* This one gets from the primary mpic via CoreInt*/
+extern unsigned int mpic_get_coreint_irq(void);
 /* Fetch Machine Check interrupt from primary mpic */
 extern unsigned int mpic_get_mcirq(void);
 
index 532e205..21b9567 100644 (file)
@@ -1170,6 +1170,12 @@ struct mpic * __init mpic_alloc(struct device_node *node,
                        mb();
        }
 
+       /* CoreInt */
+       if (flags & MPIC_ENABLE_COREINT)
+               mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0),
+                          mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0))
+                          | MPIC_GREG_GCONF_COREINT);
+
        if (flags & MPIC_ENABLE_MCK)
                mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0),
                           mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0))
@@ -1525,6 +1531,34 @@ unsigned int mpic_get_irq(void)
        return mpic_get_one_irq(mpic);
 }
 
+unsigned int mpic_get_coreint_irq(void)
+{
+#ifdef CONFIG_BOOKE
+       struct mpic *mpic = mpic_primary;
+       u32 src;
+
+       BUG_ON(mpic == NULL);
+
+       src = mfspr(SPRN_EPR);
+
+       if (unlikely(src == mpic->spurious_vec)) {
+               if (mpic->flags & MPIC_SPV_EOI)
+                       mpic_eoi(mpic);
+               return NO_IRQ;
+       }
+       if (unlikely(mpic->protected && test_bit(src, mpic->protected))) {
+               if (printk_ratelimit())
+                       printk(KERN_WARNING "%s: Got protected source %d !\n",
+                              mpic->name, (int)src);
+               return NO_IRQ;
+       }
+
+       return irq_linear_revmap(mpic->irqhost, src);
+#else
+       return NO_IRQ;
+#endif
+}
+
 unsigned int mpic_get_mcirq(void)
 {
        struct mpic *mpic = mpic_primary;