summaryrefslogtreecommitdiff
path: root/cpu/ppc4xx
diff options
context:
space:
mode:
authorStefan Roese <sr@denx.de>2008-06-26 17:36:39 +0200
committerStefan Roese <sr@denx.de>2008-07-11 13:18:14 +0200
commit5de851403b01489b493fa83137ad990b8ce60d1c (patch)
tree5cec8babce21b513667055b34157efec7182b3e6 /cpu/ppc4xx
parentd1631fe1a05b063ccaf62ea892a8887b829847d1 (diff)
downloadu-boot-imx-5de851403b01489b493fa83137ad990b8ce60d1c.zip
u-boot-imx-5de851403b01489b493fa83137ad990b8ce60d1c.tar.gz
u-boot-imx-5de851403b01489b493fa83137ad990b8ce60d1c.tar.bz2
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.c9
-rw-r--r--cpu/ppc4xx/cpu_init.c15
-rw-r--r--cpu/ppc4xx/interrupts.c97
3 files changed, 36 insertions, 85 deletions
diff --git a/cpu/ppc4xx/4xx_enet.c b/cpu/ppc4xx/4xx_enet.c
index 01712b0..8a38335 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 ac64279..e2d0402 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 6dbd6d2..8215dc6 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;