X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=cpu%2Fppc4xx%2Finterrupts.c;h=494bd8c9ef9573b8319a9be3c308c5d8112d23df;hb=33211469f7d7e2afacf103cc55790f734572f7a6;hp=886f405156229a730667660a5ca848f9bcfeeaf8;hpb=3754d6987cac587ba9278cb679d6d70d286dde76;p=oweals%2Fu-boot.git diff --git a/cpu/ppc4xx/interrupts.c b/cpu/ppc4xx/interrupts.c index 886f405156..494bd8c9ef 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,15 +35,13 @@ #include #include #include +#include #include #include #include -#include "vecnum.h" DECLARE_GLOBAL_DATA_PTR; -/****************************************************************************/ - /* * CPM interrupt vector functions. */ @@ -48,28 +50,8 @@ struct irq_action { void *arg; int count; }; +static struct irq_action irq_vecs[IRQ_MAX]; -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_440GX) || defined(CONFIG_440SPE) -static struct irq_action irq_vecs2[32]; /* For UIC2 */ -void uic2_interrupt( void * parms); /* UIC2 handler */ -#endif /* CONFIG_440GX CONFIG_440SPE */ - -#if defined(CONFIG_440SPE) -static struct irq_action irq_vecs3[32]; /* For UIC3 */ -void uic3_interrupt( void * parms); /* UIC3 handler */ -#endif /* CONFIG_440SPE */ - -#endif /* CONFIG_440 */ - -/****************************************************************************/ #if defined(CONFIG_440) /* SPRN changed in 440 */ @@ -98,8 +80,6 @@ static __inline__ void set_evpr(unsigned long val) } #endif /* defined(CONFIG_440 */ -/****************************************************************************/ - int interrupt_init_cpu (unsigned *decrementer_count) { int vec; @@ -111,25 +91,10 @@ int interrupt_init_cpu (unsigned *decrementer_count) /* * Mark all irqs as free */ - for (vec=0; vec<32; vec++) { + for (vec = 0; vec < IRQ_MAX; vec++) { irq_vecs[vec].handler = NULL; irq_vecs[vec].arg = NULL; irq_vecs[vec].count = 0; -#if defined(CONFIG_440) - irq_vecs1[vec].handler = NULL; - irq_vecs1[vec].arg = NULL; - irq_vecs1[vec].count = 0; -#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) - irq_vecs2[vec].handler = NULL; - irq_vecs2[vec].arg = NULL; - irq_vecs2[vec].count = 0; -#endif /* CONFIG_440GX */ -#if defined(CONFIG_440SPE) - irq_vecs3[vec].handler = NULL; - irq_vecs3[vec].arg = NULL; - irq_vecs3[vec].count = 0; -#endif /* CONFIG_440SPE */ -#endif } #ifdef CONFIG_4xx @@ -170,449 +135,73 @@ int interrupt_init_cpu (unsigned *decrementer_count) */ set_evpr(0x00000000); -#if defined(CONFIG_440) -#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_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 + pic_enable(); return (0); } -/****************************************************************************/ - -/* - * Handle external interrupts - */ -#if defined(CONFIG_440GX) -void external_interrupt(struct pt_regs *regs) -{ - ulong uic_msr; - - /* - * Read masked interrupt status register to determine interrupt source - */ - /* 440 GX uses base uic register */ - uic_msr = mfdcr(uicb0msr); - - if ( (UICB0_UIC0CI & uic_msr) || (UICB0_UIC0NCI & uic_msr) ) - uic0_interrupt(0); - - if ( (UICB0_UIC1CI & uic_msr) || (UICB0_UIC1NCI & uic_msr) ) - uic1_interrupt(0); - - if ( (UICB0_UIC2CI & uic_msr) || (UICB0_UIC2NCI & uic_msr) ) - uic2_interrupt(0); - - mtdcr(uicb0sr, uic_msr); - - return; - -} /* external_interrupt CONFIG_440GX */ - -#elif defined(CONFIG_440SPE) -void external_interrupt(struct pt_regs *regs) +void timer_interrupt_cpu(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); - + /* nothing to do here */ return; -} /* external_interrupt CONFIG_440SPE */ - -#else - -void external_interrupt(struct pt_regs *regs) -{ - ulong uic_msr; - ulong msr_shift; - int vec; - - /* - * Read masked interrupt status register to determine interrupt source - */ - uic_msr = mfdcr(uicmsr); - msr_shift = uic_msr; - vec = 0; - - 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 { - mtdcr(uicer, mfdcr(uicer) & ~(0x80000000 >> vec)); - printf ("Masking bogus interrupt vector 0x%x\n", vec); - } - - /* - * After servicing the interrupt, we have to remove the status indicator. - */ - mtdcr(uicsr, (0x80000000 >> vec)); - } - - /* - * Shift msr to next position and increment vector - */ - msr_shift <<= 1; - vec++; - } -} -#endif - -#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) -/* Handler for UIC0 interrupt */ -void uic0_interrupt( void * parms) -{ - ulong uic_msr; - ulong msr_shift; - int vec; - - /* - * Read masked interrupt status register to determine interrupt source - */ - uic_msr = mfdcr(uicmsr); - msr_shift = uic_msr; - vec = 0; - - 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 { - mtdcr(uicer, mfdcr(uicer) & ~(0x80000000 >> vec)); - printf ("Masking bogus interrupt vector (uic0) 0x%x\n", vec); - } - - /* - * After servicing the interrupt, we have to remove the status indicator. - */ - mtdcr(uicsr, (0x80000000 >> vec)); - } - - /* - * Shift msr to next position and increment vector - */ - msr_shift <<= 1; - vec++; - } -} - -#endif /* CONFIG_440GX */ - -#if defined(CONFIG_440) -/* Handler for UIC1 interrupt */ -void uic1_interrupt( void * parms) -{ - ulong uic1_msr; - ulong msr_shift; - int vec; - - /* - * Read masked interrupt status register to determine interrupt source - */ - uic1_msr = mfdcr(uic1msr); - msr_shift = uic1_msr; - vec = 0; - - while (msr_shift != 0) { - if (msr_shift & 0x80000000) { - /* - * Increment irq counter (for debug purpose only) - */ - irq_vecs1[vec].count++; - - if (irq_vecs1[vec].handler != NULL) { - /* call isr */ - (*irq_vecs1[vec].handler)(irq_vecs1[vec].arg); - } else { - mtdcr(uic1er, mfdcr(uic1er) & ~(0x80000000 >> vec)); - printf ("Masking bogus interrupt vector (uic1) 0x%x\n", vec); - } - - /* - * After servicing the interrupt, we have to remove the status indicator. - */ - mtdcr(uic1sr, (0x80000000 >> vec)); - } - - /* - * Shift msr to next position and increment vector - */ - msr_shift <<= 1; - vec++; - } } -#endif /* defined(CONFIG_440) */ -#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) -/* Handler for UIC2 interrupt */ -void uic2_interrupt( void * parms) +void interrupt_run_handler(int vec) { - ulong uic2_msr; - ulong msr_shift; - int vec; + irq_vecs[vec].count++; - /* - * Read masked interrupt status register to determine interrupt source - */ - uic2_msr = mfdcr(uic2msr); - msr_shift = uic2_msr; - vec = 0; - - while (msr_shift != 0) { - if (msr_shift & 0x80000000) { - /* - * Increment irq counter (for debug purpose only) - */ - irq_vecs2[vec].count++; - - if (irq_vecs2[vec].handler != NULL) { - /* call isr */ - (*irq_vecs2[vec].handler)(irq_vecs2[vec].arg); - } else { - mtdcr(uic2er, mfdcr(uic2er) & ~(0x80000000 >> vec)); - printf ("Masking bogus interrupt vector (uic2) 0x%x\n", vec); - } - - /* - * After servicing the interrupt, we have to remove the status indicator. - */ - mtdcr(uic2sr, (0x80000000 >> vec)); - } - - /* - * Shift msr to next position and increment vector - */ - msr_shift <<= 1; - vec++; + 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); } -} -#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++; - } + pic_irq_ack(vec); + return; } -#endif /* defined(CONFIG_440SPE) */ -/****************************************************************************/ - -/* - * Install and free a interrupt handler. - */ - -void irq_install_handler (int vec, interrupt_handler_t * handler, void *arg) +void irq_install_handler(int vec, interrupt_handler_t * handler, void *arg) { - struct irq_action *irqa = irq_vecs; - int i = vec; - -#if defined(CONFIG_440) -#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) - if ((vec > 31) && (vec < 64)) { - i = vec - 32; - irqa = irq_vecs1; - } else if (vec > 63) { - i = vec - 64; - irqa = irq_vecs2; - } -#else /* CONFIG_440GX */ - if (vec > 31) { - i = vec - 32; - irqa = irq_vecs1; - } -#endif /* CONFIG_440GX */ -#endif /* CONFIG_440 */ - /* - * print warning when replacing with a different irq vector + * Print warning when replacing with a different irq vector */ - if ((irqa[i].handler != NULL) && (irqa[i].handler != handler)) { - printf ("Interrupt vector %d: handler 0x%x replacing 0x%x\n", - vec, (uint) handler, (uint) irqa[i].handler); + if ((irq_vecs[vec].handler != NULL) && (irq_vecs[vec].handler != handler)) { + printf("Interrupt vector %d: handler 0x%x replacing 0x%x\n", + vec, (uint) handler, (uint) irq_vecs[vec].handler); } - irqa[i].handler = handler; - irqa[i].arg = arg; + irq_vecs[vec].handler = handler; + irq_vecs[vec].arg = arg; -#if defined(CONFIG_440) -#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) - if ((vec > 31) && (vec < 64)) - mtdcr (uic1er, mfdcr (uic1er) | (0x80000000 >> i)); - else if (vec > 63) - mtdcr (uic2er, mfdcr (uic2er) | (0x80000000 >> i)); - else -#endif /* CONFIG_440GX */ - if (vec > 31) - mtdcr (uic1er, mfdcr (uic1er) | (0x80000000 >> i)); - else -#endif - mtdcr (uicer, mfdcr (uicer) | (0x80000000 >> i)); -#if 0 - printf ("Install interrupt for vector %d ==> %p\n", vec, handler); -#endif + pic_irq_enable(vec); + return; } -void irq_free_handler (int vec) +void irq_free_handler(int vec) { - struct irq_action *irqa = irq_vecs; - int i = vec; + debug("Free interrupt for vector %d ==> %p\n", + vec, irq_vecs[vec].handler); -#if defined(CONFIG_440) -#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) - if ((vec > 31) && (vec < 64)) { - irqa = irq_vecs1; - i = vec - 32; - } else if (vec > 63) { - irqa = irq_vecs2; - i = vec - 64; - } -#endif /* CONFIG_440GX */ - if (vec > 31) { - irqa = irq_vecs1; - i = vec - 32; - } -#endif + pic_irq_disable(vec); -#if 0 - printf ("Free interrupt for vector %d ==> %p\n", - vec, irq_vecs[vec].handler); -#endif - -#if defined(CONFIG_440) -#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) - if ((vec > 31) && (vec < 64)) - mtdcr (uic1er, mfdcr (uic1er) & ~(0x80000000 >> i)); - else if (vec > 63) - mtdcr (uic2er, mfdcr (uic2er) & ~(0x80000000 >> i)); - else -#endif /* CONFIG_440GX */ - if (vec > 31) - mtdcr (uic1er, mfdcr (uic1er) & ~(0x80000000 >> i)); - else -#endif - mtdcr (uicer, mfdcr (uicer) & ~(0x80000000 >> i)); - - irqa[i].handler = NULL; - irqa[i].arg = NULL; -} - -/****************************************************************************/ - -void timer_interrupt_cpu (struct pt_regs *regs) -{ - /* nothing to do here */ + irq_vecs[vec].handler = NULL; + irq_vecs[vec].arg = NULL; return; } -/****************************************************************************/ - -#if (CONFIG_COMMANDS & CFG_CMD_IRQ) - -/******************************************************************************* - * - * irqinfo - print information about PCI devices - * - */ -int -do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +#if defined(CONFIG_CMD_IRQ) +int do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { int vec; - printf ("\nInterrupt-Information:\n"); -#if defined(CONFIG_440) - printf ("\nUIC 0\n"); -#endif + printf ("Interrupt-Information:\n"); printf ("Nr Routine Arg Count\n"); - for (vec=0; vec<32; vec++) { + for (vec = 0; vec < IRQ_MAX; vec++) { if (irq_vecs[vec].handler != NULL) { printf ("%02d %08lx %08lx %d\n", vec, @@ -622,45 +211,6 @@ do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) } } -#if defined(CONFIG_440) - printf ("\nUIC 1\n"); - printf ("Nr Routine Arg Count\n"); - - for (vec=0; vec<32; vec++) { - if (irq_vecs1[vec].handler != NULL) - printf ("%02d %08lx %08lx %d\n", - vec+31, (ulong)irq_vecs1[vec].handler, - (ulong)irq_vecs1[vec].arg, irq_vecs1[vec].count); - } - printf("\n"); -#endif - -#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) - printf ("\nUIC 2\n"); - printf ("Nr Routine Arg Count\n"); - - for (vec=0; vec<32; vec++) { - if (irq_vecs2[vec].handler != NULL) - printf ("%02d %08lx %08lx %d\n", - vec+63, (ulong)irq_vecs2[vec].handler, - (ulong)irq_vecs2[vec].arg, irq_vecs2[vec].count); - } - 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 */ +#endif