]> git.sur5r.net Git - u-boot/blobdiff - cpu/ppc4xx/interrupts.c
ppc4xx: Code cleanup
[u-boot] / cpu / ppc4xx / interrupts.c
index c0e51f9293396436ebf0c64a7bb09469516cf51c..c5a9f02566af75c5d142d743392ef9ab9677e16a 100644 (file)
@@ -36,6 +36,8 @@
 #include <commproc.h>
 #include "vecnum.h"
 
+DECLARE_GLOBAL_DATA_PTR;
+
 /****************************************************************************/
 
 /*
@@ -48,18 +50,23 @@ struct      irq_action {
 };
 
 static struct irq_action irq_vecs[32];
+void uic0_interrupt( void * parms); /* UIC0 handler */
 
 #if defined(CONFIG_440)
 static struct irq_action irq_vecs1[32]; /* For UIC1 */
 
 void uic1_interrupt( void * parms); /* UIC1 handler */
 
-#if defined(CONFIG_440_GX)
+#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \
+    defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
 static struct irq_action irq_vecs2[32]; /* For UIC2 */
-
-void uic0_interrupt( void * parms); /* UIC0 handler */
 void uic2_interrupt( void * parms); /* UIC2 handler */
-#endif /* CONFIG_440_GX */
+#endif /* CONFIG_440GX CONFIG_440SPE */
+
+#if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
+static struct irq_action irq_vecs3[32]; /* For UIC3 */
+void uic3_interrupt( void * parms); /* UIC3 handler */
+#endif /* CONFIG_440SPE */
 
 #endif /* CONFIG_440 */
 
@@ -96,8 +103,6 @@ static __inline__ void set_evpr(unsigned long val)
 
 int interrupt_init_cpu (unsigned *decrementer_count)
 {
-       DECLARE_GLOBAL_DATA_PTR;
-
        int vec;
        unsigned long val;
 
@@ -115,11 +120,17 @@ int interrupt_init_cpu (unsigned *decrementer_count)
                irq_vecs1[vec].handler = NULL;
                irq_vecs1[vec].arg = NULL;
                irq_vecs1[vec].count = 0;
-#if defined(CONFIG_440_GX)
+#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \
+    defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
                irq_vecs2[vec].handler = NULL;
                irq_vecs2[vec].arg = NULL;
                irq_vecs2[vec].count = 0;
-#endif /* CONFIG_440_GX */
+#endif /* CONFIG_440GX */
+#if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
+               irq_vecs3[vec].handler = NULL;
+               irq_vecs3[vec].arg = NULL;
+               irq_vecs3[vec].count = 0;
+#endif /* CONFIG_440SPE */
 #endif
        }
 
@@ -162,14 +173,14 @@ int interrupt_init_cpu (unsigned *decrementer_count)
        set_evpr(0x00000000);
 
 #if defined(CONFIG_440)
-#if !defined(CONFIG_440_GX)
+#if !defined(CONFIG_440GX)
        /* Install the UIC1 handlers */
        irq_install_handler(VECNUM_UIC1NC, uic1_interrupt, 0);
        irq_install_handler(VECNUM_UIC1C, uic1_interrupt, 0);
 #endif
 #endif
 
-#if defined(CONFIG_440_GX)
+#if defined(CONFIG_440GX)
        /* Take the GX out of compatibility mode
         * Travis Sawyer, 9 Mar 2004
         * NOTE: 440gx user manual inconsistency here
@@ -195,7 +206,7 @@ int interrupt_init_cpu (unsigned *decrementer_count)
 /*
  * Handle external interrupts
  */
-#if defined(CONFIG_440_GX)
+#if defined(CONFIG_440GX)
 void external_interrupt(struct pt_regs *regs)
 {
        ulong uic_msr;
@@ -219,7 +230,61 @@ void external_interrupt(struct pt_regs *regs)
 
        return;
 
-} /* external_interrupt CONFIG_440_GX */
+} /* external_interrupt CONFIG_440GX */
+
+#elif defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
+void external_interrupt(struct pt_regs *regs)
+{
+       ulong uic_msr;
+
+       /*
+        * Read masked interrupt status register to determine interrupt source
+        */
+       /* 440 SPe uses base uic register */
+       uic_msr = mfdcr(uic0msr);
+
+       if ( (UICB0_UIC1CI & uic_msr) || (UICB0_UIC1NCI & uic_msr) )
+               uic1_interrupt(0);
+
+       if ( (UICB0_UIC2CI & uic_msr) || (UICB0_UIC2NCI & uic_msr) )
+               uic2_interrupt(0);
+
+       if (uic_msr & ~(UICB0_ALL))
+               uic0_interrupt(0);
+
+       mtdcr(uic0sr, uic_msr);
+
+       return;
+
+} /* external_interrupt CONFIG_440EPX & CONFIG_440GRX */
+
+#elif defined(CONFIG_440SPE)
+void external_interrupt(struct pt_regs *regs)
+{
+       ulong uic_msr;
+
+       /*
+        * Read masked interrupt status register to determine interrupt source
+        */
+       /* 440 SPe uses base uic register */
+       uic_msr = mfdcr(uic0msr);
+
+       if ( (UICB0_UIC1CI & uic_msr) || (UICB0_UIC1NCI & uic_msr) )
+               uic1_interrupt(0);
+
+       if ( (UICB0_UIC2CI & uic_msr) || (UICB0_UIC2NCI & uic_msr) )
+               uic2_interrupt(0);
+
+       if ( (UICB0_UIC3CI & uic_msr) || (UICB0_UIC3NCI & uic_msr) )
+               uic3_interrupt(0);
+
+       if (uic_msr & ~(UICB0_ALL))
+               uic0_interrupt(0);
+
+       mtdcr(uic0sr, uic_msr);
+
+       return;
+} /* external_interrupt CONFIG_440SPE */
 
 #else
 
@@ -266,7 +331,8 @@ void external_interrupt(struct pt_regs *regs)
 }
 #endif
 
-#if defined(CONFIG_440_GX)
+#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \
+    defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
 /* Handler for UIC0 interrupt */
 void uic0_interrupt( void * parms)
 {
@@ -310,7 +376,7 @@ void uic0_interrupt( void * parms)
        }
 }
 
-#endif /* CONFIG_440_GX */
+#endif /* CONFIG_440GX */
 
 #if defined(CONFIG_440)
 /* Handler for UIC1 interrupt */
@@ -357,8 +423,9 @@ void uic1_interrupt( void * parms)
 }
 #endif /* defined(CONFIG_440) */
 
-#if defined(CONFIG_440_GX)
-/* Handler for UIC1 interrupt */
+#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \
+    defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
+/* Handler for UIC2 interrupt */
 void uic2_interrupt( void * parms)
 {
        ulong uic2_msr;
@@ -384,7 +451,7 @@ void uic2_interrupt( void * parms)
                                (*irq_vecs2[vec].handler)(irq_vecs2[vec].arg);
                        } else {
                                mtdcr(uic2er, mfdcr(uic2er) & ~(0x80000000 >> vec));
-                               printf ("Masking bogus interrupt vector (uic1) 0x%x\n", vec);
+                               printf ("Masking bogus interrupt vector (uic2) 0x%x\n", vec);
                        }
 
                        /*
@@ -400,7 +467,52 @@ void uic2_interrupt( void * parms)
                vec++;
        }
 }
-#endif /* defined(CONFIG_440_GX) */
+#endif /* defined(CONFIG_440GX) */
+
+#if defined(CONFIG_440SPE)
+/* Handler for UIC3 interrupt */
+void uic3_interrupt( void * parms)
+{
+       ulong uic3_msr;
+       ulong msr_shift;
+       int vec;
+
+       /*
+        * Read masked interrupt status register to determine interrupt source
+        */
+       uic3_msr = mfdcr(uic3msr);
+       msr_shift = uic3_msr;
+       vec = 0;
+
+       while (msr_shift != 0) {
+               if (msr_shift & 0x80000000) {
+                       /*
+                        * Increment irq counter (for debug purpose only)
+                        */
+                       irq_vecs3[vec].count++;
+
+                       if (irq_vecs3[vec].handler != NULL) {
+                               /* call isr */
+                               (*irq_vecs3[vec].handler)(irq_vecs3[vec].arg);
+                       } else {
+                               mtdcr(uic3er, mfdcr(uic3er) & ~(0x80000000 >> vec));
+                               printf ("Masking bogus interrupt vector (uic3) 0x%x\n", vec);
+                       }
+
+                       /*
+                        * After servicing the interrupt, we have to remove the status indicator.
+                        */
+                       mtdcr(uic3sr, (0x80000000 >> vec));
+               }
+
+               /*
+                * Shift msr to next position and increment vector
+                */
+               msr_shift <<= 1;
+               vec++;
+       }
+}
+#endif /* defined(CONFIG_440SPE) */
 
 /****************************************************************************/
 
@@ -414,7 +526,8 @@ void irq_install_handler (int vec, interrupt_handler_t * handler, void *arg)
        int i = vec;
 
 #if defined(CONFIG_440)
-#if defined(CONFIG_440_GX)
+#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \
+    defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
        if ((vec > 31) && (vec < 64)) {
                i = vec - 32;
                irqa = irq_vecs1;
@@ -422,12 +535,12 @@ void irq_install_handler (int vec, interrupt_handler_t * handler, void *arg)
                i = vec - 64;
                irqa = irq_vecs2;
        }
-#else  /* CONFIG_440_GX */
+#else  /* CONFIG_440GX */
        if (vec > 31) {
                i = vec - 32;
                irqa = irq_vecs1;
        }
-#endif /* CONFIG_440_GX */
+#endif /* CONFIG_440GX */
 #endif /* CONFIG_440 */
 
        /*
@@ -441,13 +554,14 @@ void irq_install_handler (int vec, interrupt_handler_t * handler, void *arg)
        irqa[i].arg = arg;
 
 #if defined(CONFIG_440)
-#if defined(CONFIG_440_GX)
+#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \
+    defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
        if ((vec > 31) && (vec < 64))
                mtdcr (uic1er, mfdcr (uic1er) | (0x80000000 >> i));
        else if (vec > 63)
                mtdcr (uic2er, mfdcr (uic2er) | (0x80000000 >> i));
        else
-#endif /* CONFIG_440_GX */
+#endif /* CONFIG_440GX */
        if (vec > 31)
                mtdcr (uic1er, mfdcr (uic1er) | (0x80000000 >> i));
        else
@@ -464,7 +578,8 @@ void irq_free_handler (int vec)
        int i = vec;
 
 #if defined(CONFIG_440)
-#if defined(CONFIG_440_GX)
+#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \
+    defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
        if ((vec > 31) && (vec < 64)) {
                irqa = irq_vecs1;
                i = vec - 32;
@@ -472,7 +587,7 @@ void irq_free_handler (int vec)
                irqa = irq_vecs2;
                i = vec - 64;
        }
-#endif /* CONFIG_440_GX */
+#endif /* CONFIG_440GX */
        if (vec > 31) {
                irqa = irq_vecs1;
                i = vec - 32;
@@ -485,13 +600,14 @@ void irq_free_handler (int vec)
 #endif
 
 #if defined(CONFIG_440)
-#if defined(CONFIG_440_GX)
+#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \
+    defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
        if ((vec > 31) && (vec < 64))
                mtdcr (uic1er, mfdcr (uic1er) & ~(0x80000000 >> i));
        else if (vec > 63)
                mtdcr (uic2er, mfdcr (uic2er) & ~(0x80000000 >> i));
        else
-#endif /* CONFIG_440_GX */
+#endif /* CONFIG_440GX */
        if (vec > 31)
                mtdcr (uic1er, mfdcr (uic1er) & ~(0x80000000 >> i));
        else
@@ -553,7 +669,8 @@ do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
        printf("\n");
 #endif
 
-#if defined(CONFIG_440_GX)
+#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \
+    defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
        printf ("\nUIC 2\n");
        printf ("Nr  Routine   Arg       Count\n");
 
@@ -566,6 +683,19 @@ do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
        printf("\n");
 #endif
 
+#if defined(CONFIG_440SPE)
+       printf ("\nUIC 3\n");
+       printf ("Nr  Routine   Arg       Count\n");
+
+       for (vec=0; vec<32; vec++) {
+               if (irq_vecs3[vec].handler != NULL)
+                       printf ("%02d  %08lx  %08lx  %d\n",
+                                       vec+63, (ulong)irq_vecs3[vec].handler,
+                                       (ulong)irq_vecs3[vec].arg, irq_vecs3[vec].count);
+       }
+       printf("\n");
+#endif
+
        return 0;
 }
 #endif  /* CONFIG_COMMANDS & CFG_CMD_IRQ */