X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=cpu%2Fppc4xx%2Finterrupts.c;h=494bd8c9ef9573b8319a9be3c308c5d8112d23df;hb=33211469f7d7e2afacf103cc55790f734572f7a6;hp=b6a956c152ced8f08e4b2e7f95e525d014bb5cb4;hpb=8bde7f776c77b343aca29b8c7b58464d915ac245;p=oweals%2Fu-boot.git diff --git a/cpu/ppc4xx/interrupts.c b/cpu/ppc4xx/interrupts.c index b6a956c152..494bd8c9ef 100644 --- a/cpu/ppc4xx/interrupts.c +++ b/cpu/ppc4xx/interrupts.c @@ -5,6 +5,13 @@ * (C) Copyright 2002 (440 port) * Scott McNutt, Artesyn Communication Producs, smcnutt@artsyncp.com * + * (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. * @@ -28,16 +35,12 @@ #include #include #include +#include #include #include #include -#include "vecnum.h" - -/****************************************************************************/ - -unsigned decrementer_count; /* count value for 1e6/HZ microseconds */ -/****************************************************************************/ +DECLARE_GLOBAL_DATA_PTR; /* * CPM interrupt vector functions. @@ -47,29 +50,7 @@ struct irq_action { void *arg; int count; }; - -static struct irq_action irq_vecs[32]; - -#if defined(CONFIG_440) -static struct irq_action irq_vecs1[32]; /* For UIC1 */ - -void uic1_interrupt( void * parms); /* UIC1 handler */ -#endif - -/****************************************************************************/ - -static __inline__ unsigned long get_msr(void) -{ - unsigned long msr; - - asm volatile("mfmsr %0" : "=r" (msr) :); - return msr; -} - -static __inline__ void set_msr(unsigned long msr) -{ - asm volatile("mtmsr %0" : : "r" (msr)); -} +static struct irq_action irq_vecs[IRQ_MAX]; #if defined(CONFIG_440) @@ -81,21 +62,6 @@ static __inline__ void set_evpr(unsigned long val) #else /* !defined(CONFIG_440) */ -static __inline__ unsigned long get_dec(void) -{ - unsigned long val; - - asm volatile("mfdec %0" : "=r" (val) :); - return val; -} - - -static __inline__ void set_dec(unsigned long val) -{ - asm volatile("mtdec %0" : : "r" (val)); -} - - static __inline__ void set_pit(unsigned long val) { asm volatile("mtpit %0" : : "r" (val)); @@ -114,41 +80,21 @@ static __inline__ void set_evpr(unsigned long val) } #endif /* defined(CONFIG_440 */ - -void enable_interrupts (void) -{ - set_msr (get_msr() | MSR_EE); -} - -/* returns flag if MSR_EE was set before */ -int disable_interrupts (void) -{ - ulong msr = get_msr(); - set_msr (msr & ~MSR_EE); - return ((msr & MSR_EE) != 0); -} - -/****************************************************************************/ - -int interrupt_init(void) +int interrupt_init_cpu (unsigned *decrementer_count) { - DECLARE_GLOBAL_DATA_PTR; - int vec; unsigned long val; + /* decrementer is automatically reloaded */ + *decrementer_count = 0; + /* * 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; -#endif } #ifdef CONFIG_4xx @@ -162,7 +108,7 @@ int interrupt_init(void) mtspr( dec, 0 ); /* Prevent exception after TSR clear*/ mtspr( decar, 0 ); /* clear reload */ mtspr( tsr, 0x08000000 ); /* clear DEC status */ - val = gd->bd->bi_intfreq/100; /* 10 msec */ + val = gd->bd->bi_intfreq/1000; /* 1 msec */ mtspr( decar, val ); /* Set auto-reload value */ mtspr( dec, val ); /* Set inital val */ #else @@ -189,239 +135,73 @@ int interrupt_init(void) */ set_evpr(0x00000000); -#if defined(CONFIG_440) - /* Install the UIC1 handlers */ - irq_install_handler(VECNUM_UIC1NC, uic1_interrupt, 0); - irq_install_handler(VECNUM_UIC1C, uic1_interrupt, 0); -#endif /* - * Enable external interrupts (including PIT) + * Call uic or xilinx_irq pic_enable */ - set_msr (get_msr() | MSR_EE); + pic_enable(); return (0); } -/****************************************************************************/ - -/* - * Handle external interrupts - */ -void external_interrupt(struct pt_regs *regs) +void timer_interrupt_cpu(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++; - } + /* nothing to do here */ + return; } -#if defined(CONFIG_440) -/* Handler for UIC1 interrupt */ -void uic1_interrupt( void * parms) +void interrupt_run_handler(int vec) { - ulong uic1_msr; - ulong msr_shift; - int vec; + irq_vecs[vec].count++; - /* - * 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++; + 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_440) */ -/****************************************************************************/ - -/* - * Install and free a interrupt handler. - */ - -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 (vec > 31) { - i = vec - 32; - irqa = irq_vecs1; - } -#endif - - if (irqa[i].handler != NULL) { - printf ("Interrupt vector %d: handler 0x%x replacing 0x%x\n", - vec, (uint)handler, (uint)irqa[i].handler); - } - irqa[i].handler = handler; - irqa[i].arg = arg; - -#if defined(CONFIG_440) - 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_ack(vec); + return; } -void -irq_free_handler(int vec) +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 (vec > 31) { - irqa = irq_vecs1; - i = vec - 32; + /* + * Print warning when replacing with a different irq vector + */ + 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); } -#endif - -#if 0 - printf ("Free interrupt for vector %d ==> %p\n", - vec, irq_vecs[vec].handler); -#endif + irq_vecs[vec].handler = handler; + irq_vecs[vec].arg = arg; -#if defined(CONFIG_440) - 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; + pic_irq_enable(vec); + return; } -/****************************************************************************/ - - -volatile ulong timestamp = 0; - -/* - * timer_interrupt - gets called when the decrementer overflows, - * with interrupts disabled. - * Trivial implementation - no need to be really accurate. - */ -void timer_interrupt(struct pt_regs *regs) -{ -#if 0 - printf ("*** Timer Interrupt *** "); -#endif - timestamp++; - -#if defined(CONFIG_WATCHDOG) - if ((timestamp % 1000) == 0) - reset_4xx_watchdog(); -#endif /* CONFIG_WATCHDOG */ -} - -/****************************************************************************/ - -void reset_timer (void) +void irq_free_handler(int vec) { - timestamp = 0; -} + debug("Free interrupt for vector %d ==> %p\n", + vec, irq_vecs[vec].handler); -ulong get_timer (ulong base) -{ - return (timestamp - base); -} + pic_irq_disable(vec); -void set_timer (ulong t) -{ - timestamp = t; + 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, @@ -431,21 +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 return 0; } - - -#endif /* CONFIG_COMMANDS & CFG_CMD_IRQ */ +#endif