fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / arch / ppc / syslib / ppc4xx_pic.c
index 05686fa..ee0da4b 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * arch/ppc/syslib/ppc4xx_pic.c
- *
  * Interrupt controller driver for PowerPC 4xx-based processors.
  *
  * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
@@ -15,7 +13,6 @@
  * Free Software Foundation;  either version 2 of the  License, or (at your
  * option) any later version.
 */
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/signal.h>
@@ -25,6 +22,7 @@
 #include <asm/system.h>
 #include <asm/irq.h>
 #include <asm/ppc4xx_pic.h>
+#include <asm/machdep.h>
 
 /* See comment in include/arch-ppc/ppc4xx_pic.h
  * for more info about these two variables
@@ -37,6 +35,7 @@ extern unsigned char ppc4xx_uic_ext_irq_cfg[] __attribute__ ((weak));
 #define IRQ_MASK_UICx(irq)             (1 << (31 - ((irq) & 0x1f)))
 #define IRQ_MASK_UIC1(irq)             IRQ_MASK_UICx(irq)
 #define IRQ_MASK_UIC2(irq)             IRQ_MASK_UICx(irq)
+#define IRQ_MASK_UIC3(irq)             IRQ_MASK_UICx(irq)
 
 #define UIC_HANDLERS(n)                                                        \
 static void ppc4xx_uic##n##_enable(unsigned int irq)                   \
@@ -87,7 +86,38 @@ static void ppc4xx_uic##n##_end(unsigned int irq)                    \
        .end            = ppc4xx_uic##n##_end,                          \
 }                                                                      \
 
-#if NR_UICS == 3
+#if NR_UICS == 4
+#define ACK_UIC0_PARENT
+#define ACK_UIC1_PARENT        mtdcr(DCRN_UIC_SR(UIC0), UIC0_UIC1NC);
+#define ACK_UIC2_PARENT        mtdcr(DCRN_UIC_SR(UIC0), UIC0_UIC2NC);
+#define ACK_UIC3_PARENT        mtdcr(DCRN_UIC_SR(UIC0), UIC0_UIC3NC);
+UIC_HANDLERS(0);
+UIC_HANDLERS(1);
+UIC_HANDLERS(2);
+UIC_HANDLERS(3);
+
+static int ppc4xx_pic_get_irq(void)
+{
+       u32 uic0 = mfdcr(DCRN_UIC_MSR(UIC0));
+       if (uic0 & UIC0_UIC1NC)
+               return 64 - ffs(mfdcr(DCRN_UIC_MSR(UIC1)));
+       else if (uic0 & UIC0_UIC2NC)
+               return 96 - ffs(mfdcr(DCRN_UIC_MSR(UIC2)));
+       else if (uic0 & UIC0_UIC3NC)
+               return 128 - ffs(mfdcr(DCRN_UIC_MSR(UIC3)));
+       else
+               return uic0 ? 32 - ffs(uic0) : -1;
+}
+
+static void __init ppc4xx_pic_impl_init(void)
+{
+       /* Enable cascade interrupts in UIC0 */
+       ppc_cached_irq_mask[0] |= UIC0_UIC1NC | UIC0_UIC2NC | UIC0_UIC3NC;
+       mtdcr(DCRN_UIC_SR(UIC0), UIC0_UIC1NC | UIC0_UIC2NC | UIC0_UIC3NC);
+       mtdcr(DCRN_UIC_ER(UIC0), ppc_cached_irq_mask[0]);
+}
+
+#elif NR_UICS == 3
 #define ACK_UIC0_PARENT        mtdcr(DCRN_UIC_SR(UICB), UICB_UIC0NC);
 #define ACK_UIC1_PARENT        mtdcr(DCRN_UIC_SR(UICB), UICB_UIC1NC);
 #define ACK_UIC2_PARENT        mtdcr(DCRN_UIC_SR(UICB), UICB_UIC2NC);
@@ -95,7 +125,7 @@ UIC_HANDLERS(0);
 UIC_HANDLERS(1);
 UIC_HANDLERS(2);
 
-static int ppc4xx_pic_get_irq(struct pt_regs *regs)
+static int ppc4xx_pic_get_irq(void)
 {
        u32 uicb = mfdcr(DCRN_UIC_MSR(UICB));
        if (uicb & UICB_UIC0NC)
@@ -110,6 +140,10 @@ static int ppc4xx_pic_get_irq(struct pt_regs *regs)
 
 static void __init ppc4xx_pic_impl_init(void)
 {
+#if defined(CONFIG_440GX)
+       /* Disable 440GP compatibility mode if it was enabled in firmware */
+       SDR_WRITE(DCRN_SDR_MFR, SDR_READ(DCRN_SDR_MFR) & ~DCRN_SDR_MFR_PCM);
+#endif
        /* Configure Base UIC */
        mtdcr(DCRN_UIC_CR(UICB), 0);
        mtdcr(DCRN_UIC_TR(UICB), 0);
@@ -124,7 +158,7 @@ static void __init ppc4xx_pic_impl_init(void)
 UIC_HANDLERS(0);
 UIC_HANDLERS(1);
 
-static int ppc4xx_pic_get_irq(struct pt_regs *regs)
+static int ppc4xx_pic_get_irq(void)
 {
        u32 uic0 = mfdcr(DCRN_UIC_MSR(UIC0));
        if (uic0 & UIC0_UIC1NC)
@@ -145,7 +179,7 @@ static void __init ppc4xx_pic_impl_init(void)
 #define ACK_UIC0_PARENT
 UIC_HANDLERS(0);
 
-static int ppc4xx_pic_get_irq(struct pt_regs *regs)
+static int ppc4xx_pic_get_irq(void)
 {
        u32 uic0 = mfdcr(DCRN_UIC_MSR(UIC0));
        return uic0 ? 32 - ffs(uic0) : -1;
@@ -165,6 +199,9 @@ static struct ppc4xx_uic_impl {
        { .decl = DECLARE_UIC(1), .base = UIC1 },
 #if NR_UICS > 2
        { .decl = DECLARE_UIC(2), .base = UIC2 },
+#if NR_UICS > 3
+       { .decl = DECLARE_UIC(3), .base = UIC3 },
+#endif
 #endif
 #endif
 };
@@ -238,7 +275,7 @@ void __init ppc4xx_pic_init(void)
 
        /* Attach low-level handlers */
        for (i = 0; i < (NR_UICS << 5); ++i) {
-               irq_desc[i].handler = &__uic[i >> 5].decl;
+               irq_desc[i].chip = &__uic[i >> 5].decl;
                if (is_level_sensitive(i))
                        irq_desc[i].status |= IRQ_LEVEL;
        }