Merge branch 'Makefile' of git://git.denx.de/u-boot-arm
[platform/kernel/u-boot.git] / cpu / ppc4xx / interrupts.c
index 8620e2b..494bd8c 100644 (file)
@@ -8,6 +8,10 @@
  * (C) Copyright 2003 (440GX port)
  * Travis B. Sawyer, Sandburst Corporation, tsawyer@sandburst.com
  *
+ * (C) Copyright 2008 (PPC440X05 port for Virtex 5 FX)
+ * Ricardo Ribalda-Universidad Autonoma de Madrid-ricardo.ribalda@uam.es
+ * Work supported by Qtechnology (htpp://qtec.com)
+ *
  * See file CREDITS for list of people who contributed to this
  * project.
  *
 #include <watchdog.h>
 #include <command.h>
 #include <asm/processor.h>
+#include <asm/interrupt.h>
 #include <ppc4xx.h>
 #include <ppc_asm.tmpl>
 #include <commproc.h>
-#include <asm/ppc4xx-intvec.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
 /*
- * Define the number of UIC's
- */
-#if defined(CONFIG_440SPE) || \
-    defined(CONFIG_460EX) || defined(CONFIG_460GT)
-#define UIC_MAX                4
-#elif defined(CONFIG_440GX) || \
-    defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
-    defined(CONFIG_405EX)
-#define UIC_MAX                3
-#elif defined(CONFIG_440GP) || defined(CONFIG_440SP) || \
-    defined(CONFIG_440EP) || defined(CONFIG_440GR)
-#define UIC_MAX                2
-#else
-#define UIC_MAX                1
-#endif
-
-/*
  * CPM interrupt vector functions.
  */
 struct irq_action {
@@ -63,15 +50,7 @@ struct       irq_action {
        void *arg;
        int count;
 };
-
-static struct irq_action irq_vecs[UIC_MAX * 32];
-
-u32 get_dcr(u16);
-void set_dcr(u16, u32);
-
-#if (UIC_MAX > 1) && !defined(CONFIG_440GX)
-static void uic_cascade_interrupt(void *para);
-#endif
+static struct irq_action irq_vecs[IRQ_MAX];
 
 #if defined(CONFIG_440)
 
@@ -112,7 +91,7 @@ int interrupt_init_cpu (unsigned *decrementer_count)
        /*
         * Mark all irqs as free
         */
-       for (vec = 0; vec < (UIC_MAX * 32); vec++) {
+       for (vec = 0; vec < IRQ_MAX; vec++) {
                irq_vecs[vec].handler = NULL;
                irq_vecs[vec].arg = NULL;
                irq_vecs[vec].count = 0;
@@ -156,160 +135,38 @@ int interrupt_init_cpu (unsigned *decrementer_count)
         */
        set_evpr(0x00000000);
 
-#if !defined(CONFIG_440GX)
-#if (UIC_MAX > 1)
-       /* Install the UIC1 handlers */
-       irq_install_handler(VECNUM_UIC1NC, uic_cascade_interrupt, 0);
-       irq_install_handler(VECNUM_UIC1C, uic_cascade_interrupt, 0);
-#endif
-#if (UIC_MAX > 2)
-       irq_install_handler(VECNUM_UIC2NC, uic_cascade_interrupt, 0);
-       irq_install_handler(VECNUM_UIC2C, uic_cascade_interrupt, 0);
-#endif
-#if (UIC_MAX > 3)
-       irq_install_handler(VECNUM_UIC3NC, uic_cascade_interrupt, 0);
-       irq_install_handler(VECNUM_UIC3C, uic_cascade_interrupt, 0);
-#endif
-#else /* !defined(CONFIG_440GX) */
-       /* Take the GX out of compatibility mode
-        * Travis Sawyer, 9 Mar 2004
-        * NOTE: 440gx user manual inconsistency here
-        *       Compatibility mode and Ethernet Clock select are not
-        *       correct in the manual
+       /*
+        * Call uic or xilinx_irq pic_enable
         */
-       mfsdr(sdr_mfr, val);
-       val &= ~0x10000000;
-       mtsdr(sdr_mfr,val);
-
-       /* Enable UIC interrupts via UIC Base Enable Register */
-       mtdcr(uicb0sr, UICB0_ALL);
-       mtdcr(uicb0er, 0x54000000);
-       /* None are critical */
-       mtdcr(uicb0cr, 0);
-#endif /* !defined(CONFIG_440GX) */
+       pic_enable();
 
        return (0);
 }
 
-/* Handler for UIC interrupt */
-static void uic_interrupt(u32 uic_base, int vec_base)
+void timer_interrupt_cpu(struct pt_regs *regs)
 {
-       u32 uic_msr;
-       u32 msr_shift;
-       int vec;
-
-       /*
-        * Read masked interrupt status register to determine interrupt source
-        */
-       uic_msr = get_dcr(uic_base + UIC_MSR);
-       msr_shift = uic_msr;
-       vec = vec_base;
-
-       while (msr_shift != 0) {
-               if (msr_shift & 0x80000000) {
-                       /*
-                        * Increment irq counter (for debug purpose only)
-                        */
-                       irq_vecs[vec].count++;
-
-                       if (irq_vecs[vec].handler != NULL) {
-                               /* call isr */
-                               (*irq_vecs[vec].handler)(irq_vecs[vec].arg);
-                       } else {
-                               set_dcr(uic_base + UIC_ER,
-                                       get_dcr(uic_base + UIC_ER) &
-                                       ~(0x80000000 >> (vec & 0x1f)));
-                               printf("Masking bogus interrupt vector %d"
-                                      " (UIC_BASE=0x%x)\n", vec, uic_base);
-                       }
-
-                       /*
-                        * After servicing the interrupt, we have to remove the
-                        * status indicator
-                        */
-                       set_dcr(uic_base + UIC_SR, (0x80000000 >> (vec & 0x1f)));
-               }
-
-               /*
-                * Shift msr to next position and increment vector
-                */
-               msr_shift <<= 1;
-               vec++;
-       }
+       /* nothing to do here */
+       return;
 }
 
-#if (UIC_MAX > 1) && !defined(CONFIG_440GX)
-static void uic_cascade_interrupt(void *para)
+void interrupt_run_handler(int vec)
 {
-       external_interrupt(para);
-}
-#endif
-
-#if defined(CONFIG_440)
-#if defined(CONFIG_440GX)
-/* 440GX uses base uic register */
-#define UIC_BMSR       uicb0msr
-#define UIC_BSR                uicb0sr
-#else
-#define UIC_BMSR       uic0msr
-#define UIC_BSR                uic0sr
-#endif
-#else /* CONFIG_440 */
-#define UIC_BMSR       uicmsr
-#define UIC_BSR                uicsr
-#endif /* CONFIG_440 */
-
-/*
- * Handle external interrupts
- */
-void external_interrupt(struct pt_regs *regs)
-{
-       u32 uic_msr;
-
-       /*
-        * Read masked interrupt status register to determine interrupt source
-        */
-       uic_msr = mfdcr(UIC_BMSR);
-
-#if (UIC_MAX > 1)
-       if ((UICB0_UIC1CI & uic_msr) || (UICB0_UIC1NCI & uic_msr))
-               uic_interrupt(UIC1_DCR_BASE, 32);
-#endif
-
-#if (UIC_MAX > 2)
-       if ((UICB0_UIC2CI & uic_msr) || (UICB0_UIC2NCI & uic_msr))
-               uic_interrupt(UIC2_DCR_BASE, 64);
-#endif
-
-#if (UIC_MAX > 3)
-       if ((UICB0_UIC3CI & uic_msr) || (UICB0_UIC3NCI & uic_msr))
-               uic_interrupt(UIC3_DCR_BASE, 96);
-#endif
-
-#if defined(CONFIG_440)
-#if !defined(CONFIG_440GX)
-       if (uic_msr & ~(UICB0_ALL))
-               uic_interrupt(UIC0_DCR_BASE, 0);
-#else
-       if ((UICB0_UIC0CI & uic_msr) || (UICB0_UIC0NCI & uic_msr))
-               uic_interrupt(UIC0_DCR_BASE, 0);
-#endif
-#else /* CONFIG_440 */
-       uic_interrupt(UIC0_DCR_BASE, 0);
-#endif /* CONFIG_440 */
-
-       mtdcr(UIC_BSR, uic_msr);
+       irq_vecs[vec].count++;
+
+       if (irq_vecs[vec].handler != NULL) {
+               /* call isr */
+               (*irq_vecs[vec].handler) (irq_vecs[vec].arg);
+       } else {
+               pic_irq_disable(vec);
+               printf("Masking bogus interrupt vector %d\n", vec);
+       }
 
+       pic_irq_ack(vec);
        return;
 }
 
-/*
- * Install and free a interrupt handler.
- */
 void irq_install_handler(int vec, interrupt_handler_t * handler, void *arg)
 {
-       int i;
-
        /*
         * Print warning when replacing with a different irq vector
         */
@@ -320,55 +177,19 @@ void irq_install_handler(int vec, interrupt_handler_t * handler, void *arg)
        irq_vecs[vec].handler = handler;
        irq_vecs[vec].arg = arg;
 
-       i = vec & 0x1f;
-       if ((vec >= 0) && (vec < 32))
-               mtdcr(uicer, mfdcr(uicer) | (0x80000000 >> i));
-#if (UIC_MAX > 1)
-       else if ((vec >= 32) && (vec < 64))
-               mtdcr(uic1er, mfdcr(uic1er) | (0x80000000 >> i));
-#endif
-#if (UIC_MAX > 2)
-       else if ((vec >= 64) && (vec < 96))
-               mtdcr(uic2er, mfdcr(uic2er) | (0x80000000 >> i));
-#endif
-#if (UIC_MAX > 3)
-       else if (vec >= 96)
-               mtdcr(uic3er, mfdcr(uic3er) | (0x80000000 >> i));
-#endif
-
-       debug("Install interrupt for vector %d ==> %p\n", vec, handler);
+       pic_irq_enable(vec);
+       return;
 }
 
-void irq_free_handler (int vec)
+void irq_free_handler(int vec)
 {
-       int i;
-
        debug("Free interrupt for vector %d ==> %p\n",
              vec, irq_vecs[vec].handler);
 
-       i = vec & 0x1f;
-       if ((vec >= 0) && (vec < 32))
-               mtdcr(uicer, mfdcr(uicer) & ~(0x80000000 >> i));
-#if (UIC_MAX > 1)
-       else if ((vec >= 32) && (vec < 64))
-               mtdcr(uic1er, mfdcr(uic1er) & ~(0x80000000 >> i));
-#endif
-#if (UIC_MAX > 2)
-       else if ((vec >= 64) && (vec < 96))
-               mtdcr(uic2er, mfdcr(uic2er) & ~(0x80000000 >> i));
-#endif
-#if (UIC_MAX > 3)
-       else if (vec >= 96)
-               mtdcr(uic3er, mfdcr(uic3er) & ~(0x80000000 >> i));
-#endif
+       pic_irq_disable(vec);
 
        irq_vecs[vec].handler = NULL;
        irq_vecs[vec].arg = NULL;
-}
-
-void timer_interrupt_cpu (struct pt_regs *regs)
-{
-       /* nothing to do here */
        return;
 }
 
@@ -380,7 +201,7 @@ int do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
        printf ("Interrupt-Information:\n");
        printf ("Nr  Routine   Arg       Count\n");
 
-       for (vec = 0; vec < (UIC_MAX * 32); vec++) {
+       for (vec = 0; vec < IRQ_MAX; vec++) {
                if (irq_vecs[vec].handler != NULL) {
                        printf ("%02d  %08lx  %08lx  %d\n",
                                vec,