diff options
author | Stefan Roese <sr@denx.de> | 2008-06-26 17:36:39 +0200 |
---|---|---|
committer | Stefan Roese <sr@denx.de> | 2008-07-11 13:18:14 +0200 |
commit | 5de851403b01489b493fa83137ad990b8ce60d1c (patch) | |
tree | 5cec8babce21b513667055b34157efec7182b3e6 /cpu/ppc4xx | |
parent | d1631fe1a05b063ccaf62ea892a8887b829847d1 (diff) |
ppc4xx: Rework 440GX UIC handling
This patch reworks the 440GX interrupt handling so that the common 4xx
code can be used. The 440GX is an exception to all other 4xx variants
by having the cascading interrupt vectors not on UIC0 but on a special
UIC named UICB0 (UIC Base 0). With this patch now, U-Boot references
the 440GX UICB0 when UIC0 is selected. And the common 4xx interrupt
handling is simpler without any 440GX special cases.
Also some additional cleanup to cpu/ppc4xx/interrupt.c is done.
Signed-off-by: Stefan Roese <sr@denx.de>
Diffstat (limited to 'cpu/ppc4xx')
-rw-r--r-- | cpu/ppc4xx/4xx_enet.c | 9 | ||||
-rw-r--r-- | cpu/ppc4xx/cpu_init.c | 15 | ||||
-rw-r--r-- | cpu/ppc4xx/interrupts.c | 97 |
3 files changed, 36 insertions, 85 deletions
diff --git a/cpu/ppc4xx/4xx_enet.c b/cpu/ppc4xx/4xx_enet.c index 01712b056e0..8a3833513e2 100644 --- a/cpu/ppc4xx/4xx_enet.c +++ b/cpu/ppc4xx/4xx_enet.c @@ -169,12 +169,15 @@ * UIC. Only exception is 440GX where the EMAC interrupts are * spread over two UIC's! */ +#if defined(CONFIG_440GX) +#define UIC_BASE_MAL UIC1_DCR_BASE +#define UIC_BASE_MAL_ERR UIC2_DCR_BASE +#define UIC_BASE_EMAC UIC2_DCR_BASE +#define UIC_BASE_EMAC_B UIC3_DCR_BASE +#else #define UIC_BASE_MAL (UIC0_DCR_BASE + (UIC_NR(VECNUM_MAL_TXEOB) * 0x10)) #define UIC_BASE_MAL_ERR (UIC0_DCR_BASE + (UIC_NR(VECNUM_MAL_SERR) * 0x10)) #define UIC_BASE_EMAC (UIC0_DCR_BASE + (UIC_NR(ETH_IRQ_NUM(0)) * 0x10)) -#if defined(CONFIG_440GX) -#define UIC_BASE_EMAC_B (UIC0_DCR_BASE + (UIC_NR(ETH_IRQ_NUM(2)) * 0x10)) -#else #define UIC_BASE_EMAC_B (UIC0_DCR_BASE + (UIC_NR(ETH_IRQ_NUM(0)) * 0x10)) #endif diff --git a/cpu/ppc4xx/cpu_init.c b/cpu/ppc4xx/cpu_init.c index ac642790516..e2d04027815 100644 --- a/cpu/ppc4xx/cpu_init.c +++ b/cpu/ppc4xx/cpu_init.c @@ -138,9 +138,10 @@ void reconfigure_pll(u32 new_cpu_freq) void cpu_init_f (void) { -#if defined(CONFIG_WATCHDOG) || defined(CONFIG_460EX) +#if defined(CONFIG_WATCHDOG) || defined(CONFIG_440GX) || defined(CONFIG_460EX) u32 val; #endif + reconfigure_pll(CFG_PLL_RECONFIG); #if (defined(CONFIG_405EP) || defined (CONFIG_405EX)) && !defined(CFG_4xx_GPIO_TABLE) @@ -273,6 +274,18 @@ cpu_init_f (void) reset_4xx_watchdog(); #endif /* CONFIG_WATCHDOG */ +#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 + */ + mfsdr(sdr_mfr, val); + val &= ~0x10000000; + mtsdr(sdr_mfr,val); +#endif /* CONFIG_440GX */ + #if defined(CONFIG_460EX) /* * Set SDR0_AHB_CFG[A2P_INCR4] (bit 24) and diff --git a/cpu/ppc4xx/interrupts.c b/cpu/ppc4xx/interrupts.c index 6dbd6d28190..8215dc652ed 100644 --- a/cpu/ppc4xx/interrupts.c +++ b/cpu/ppc4xx/interrupts.c @@ -40,14 +40,8 @@ UIC_MASK(VECNUM_UIC2CI) | UIC_MASK(VECNUM_UIC2NCI) | \ UIC_MASK(VECNUM_UIC3CI) | UIC_MASK(VECNUM_UIC3NCI)) #elif (UIC_MAX > 2) -#if defined(CONFIG_440GX) -#define UICB0_ALL (UIC_MASK(VECNUM_UIC0CI) | UIC_MASK(VECNUM_UIC0NCI) | \ - UIC_MASK(VECNUM_UIC1CI) | UIC_MASK(VECNUM_UIC1NCI) | \ - UIC_MASK(VECNUM_UIC2CI) | UIC_MASK(VECNUM_UIC2NCI)) -#else #define UICB0_ALL (UIC_MASK(VECNUM_UIC1CI) | UIC_MASK(VECNUM_UIC1NCI) | \ UIC_MASK(VECNUM_UIC2CI) | UIC_MASK(VECNUM_UIC2NCI)) -#endif #elif (UIC_MAX > 1) #define UICB0_ALL (UIC_MASK(VECNUM_UIC1CI) | UIC_MASK(VECNUM_UIC1NCI)) #else @@ -70,10 +64,6 @@ 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 - #if defined(CONFIG_440) /* SPRN changed in 440 */ @@ -157,42 +147,19 @@ 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_UIC1NCI, uic_cascade_interrupt, 0); - irq_install_handler(VECNUM_UIC1CI, uic_cascade_interrupt, 0); + irq_install_handler(VECNUM_UIC1NCI, (void *)(void *)external_interrupt, 0); + irq_install_handler(VECNUM_UIC1CI, (void *)(void *)external_interrupt, 0); #endif #if (UIC_MAX > 2) - irq_install_handler(VECNUM_UIC2NCI, uic_cascade_interrupt, 0); - irq_install_handler(VECNUM_UIC2CI, uic_cascade_interrupt, 0); + irq_install_handler(VECNUM_UIC2NCI, (void *)(void *)external_interrupt, 0); + irq_install_handler(VECNUM_UIC2CI, (void *)(void *)external_interrupt, 0); #endif #if (UIC_MAX > 3) - irq_install_handler(VECNUM_UIC3NCI, uic_cascade_interrupt, 0); - irq_install_handler(VECNUM_UIC3CI, uic_cascade_interrupt, 0); + irq_install_handler(VECNUM_UIC3NCI, (void *)(void *)external_interrupt, 0); + irq_install_handler(VECNUM_UIC3CI, (void *)(void *)external_interrupt, 0); #endif -#else /* !defined(CONFIG_440GX) */ - /* - * ToDo: Remove this 440GX special handling: - * Move SDR0_MFR setup to cpu.c and use common code with UICB0 - * on 440GX. 2008-06-26, sr - */ - /* 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 - */ - mfsdr(sdr_mfr, val); - val &= ~0x10000000; - mtsdr(sdr_mfr,val); - - /* Enable UIC interrupts via UIC Base Enable Register */ - mtdcr(uicb0sr, UICB0_ALL); - mtdcr(uicb0er, UICB0_ALL); - /* None are critical */ - mtdcr(uicb0cr, 0); -#endif /* !defined(CONFIG_440GX) */ return (0); } @@ -243,22 +210,6 @@ static void uic_interrupt(u32 uic_base, int vec_base) } } -#if (UIC_MAX > 1) && !defined(CONFIG_440GX) -static void uic_cascade_interrupt(void *para) -{ - external_interrupt(para); -} -#endif - -#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 - /* * Handle external interrupts */ @@ -269,7 +220,7 @@ void external_interrupt(struct pt_regs *regs) /* * Read masked interrupt status register to determine interrupt source */ - uic_msr = mfdcr(UIC_BMSR); + uic_msr = mfdcr(uic0msr); #if (UIC_MAX > 1) if ((UIC_MASK(VECNUM_UIC1CI) & uic_msr) || @@ -289,20 +240,10 @@ void external_interrupt(struct pt_regs *regs) 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 ((UIC_MASK(VECNUM_UIC0CI) & uic_msr) || - (UIC_MASK(VECNUM_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); + mtdcr(uic0sr, uic_msr); return; } @@ -312,8 +253,6 @@ void external_interrupt(struct pt_regs *regs) */ void irq_install_handler(int vec, interrupt_handler_t * handler, void *arg) { - int i; - /* * Print warning when replacing with a different irq vector */ @@ -324,20 +263,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)); + mtdcr(uicer, mfdcr(uicer) | UIC_MASK(vec)); #if (UIC_MAX > 1) else if ((vec >= 32) && (vec < 64)) - mtdcr(uic1er, mfdcr(uic1er) | (0x80000000 >> i)); + mtdcr(uic1er, mfdcr(uic1er) | UIC_MASK(vec)); #endif #if (UIC_MAX > 2) else if ((vec >= 64) && (vec < 96)) - mtdcr(uic2er, mfdcr(uic2er) | (0x80000000 >> i)); + mtdcr(uic2er, mfdcr(uic2er) | UIC_MASK(vec)); #endif #if (UIC_MAX > 3) else if (vec >= 96) - mtdcr(uic3er, mfdcr(uic3er) | (0x80000000 >> i)); + mtdcr(uic3er, mfdcr(uic3er) | UIC_MASK(vec)); #endif debug("Install interrupt for vector %d ==> %p\n", vec, handler); @@ -345,25 +283,22 @@ void irq_install_handler(int vec, interrupt_handler_t * handler, void *arg) 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)); + mtdcr(uicer, mfdcr(uicer) & ~UIC_MASK(vec)); #if (UIC_MAX > 1) else if ((vec >= 32) && (vec < 64)) - mtdcr(uic1er, mfdcr(uic1er) & ~(0x80000000 >> i)); + mtdcr(uic1er, mfdcr(uic1er) & ~UIC_MASK(vec)); #endif #if (UIC_MAX > 2) else if ((vec >= 64) && (vec < 96)) - mtdcr(uic2er, mfdcr(uic2er) & ~(0x80000000 >> i)); + mtdcr(uic2er, mfdcr(uic2er) & ~UIC_MASK(vec)); #endif #if (UIC_MAX > 3) else if (vec >= 96) - mtdcr(uic3er, mfdcr(uic3er) & ~(0x80000000 >> i)); + mtdcr(uic3er, mfdcr(uic3er) & ~UIC_MASK(vec)); #endif irq_vecs[vec].handler = NULL; |