summaryrefslogtreecommitdiff
path: root/cpu/ppc4xx/interrupts.c
diff options
context:
space:
mode:
Diffstat (limited to 'cpu/ppc4xx/interrupts.c')
-rw-r--r--cpu/ppc4xx/interrupts.c237
1 files changed, 29 insertions, 208 deletions
diff --git a/cpu/ppc4xx/interrupts.c b/cpu/ppc4xx/interrupts.c
index 8620e2b4847..494bd8c9ef9 100644
--- a/cpu/ppc4xx/interrupts.c
+++ b/cpu/ppc4xx/interrupts.c
@@ -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.
*
@@ -31,31 +35,14 @@
#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,