summaryrefslogtreecommitdiff
path: root/cpu
diff options
context:
space:
mode:
Diffstat (limited to 'cpu')
-rw-r--r--cpu/ppc4xx/405gp_pci.c9
-rw-r--r--cpu/ppc4xx/4xx_enet.c78
-rw-r--r--cpu/ppc4xx/cpu.c18
-rw-r--r--cpu/ppc4xx/interrupts.c123
-rw-r--r--cpu/ppc4xx/miiphy.c59
-rw-r--r--cpu/ppc4xx/serial.c39
-rw-r--r--cpu/ppc4xx/speed.c254
-rw-r--r--cpu/ppc4xx/start.S70
-rw-r--r--cpu/ppc4xx/vecnum.h43
9 files changed, 623 insertions, 70 deletions
diff --git a/cpu/ppc4xx/405gp_pci.c b/cpu/ppc4xx/405gp_pci.c
index fad895b..0ccb3d8 100644
--- a/cpu/ppc4xx/405gp_pci.c
+++ b/cpu/ppc4xx/405gp_pci.c
@@ -438,7 +438,7 @@ void pci_440_init (struct pci_controller *hose)
* The PCI initialization sequence enable bit must be set ... if not abort
* pci setup since updating the bit requires chip reset.
*--------------------------------------------------------------------------*/
-#if defined(CONFIG_440GX) || defined(CONFIG_440SP)
+#if defined(CONFIG_440GX) || defined(CONFIG_440SP) || defined(CONFIG_440SPE)
unsigned long strap;
mfsdr(sdr_sdstp1,strap);
@@ -502,7 +502,7 @@ void pci_440_init (struct pci_controller *hose)
out16r( PCIX0_CLS, 0x00060000 ); /* Bridge, host bridge */
#endif
-#if defined(CONFIG_440GX)
+#if defined(CONFIG_440GX) || defined(CONFIG_440SPE)
out32r( PCIX0_BRDGOPT1, 0x04000060 ); /* PLB Rq pri highest */
out32r( PCIX0_BRDGOPT2, in32(PCIX0_BRDGOPT2) | 0x83 ); /* Enable host config, clear Timeout, ensure int src1 */
#elif defined(PCIX0_BRDGOPT1)
@@ -520,8 +520,13 @@ void pci_440_init (struct pci_controller *hose)
out32r( PCIX0_POM0SA, 0 ); /* disable */
out32r( PCIX0_POM1SA, 0 ); /* disable */
out32r( PCIX0_POM2SA, 0 ); /* disable */
+#if defined(CONFIG_440SPE)
+ out32r( PCIX0_POM0LAL, 0x10000000 );
+ out32r( PCIX0_POM0LAH, 0x0000000c );
+#else
out32r( PCIX0_POM0LAL, 0x00000000 );
out32r( PCIX0_POM0LAH, 0x00000003 );
+#endif
out32r( PCIX0_POM0PCIAL, CFG_PCI_MEMBASE );
out32r( PCIX0_POM0PCIAH, 0x00000000 );
out32r( PCIX0_POM0SA, 0xf0000001 ); /* 256MB, enabled */
diff --git a/cpu/ppc4xx/4xx_enet.c b/cpu/ppc4xx/4xx_enet.c
index 86dc2d0..fab65af 100644
--- a/cpu/ppc4xx/4xx_enet.c
+++ b/cpu/ppc4xx/4xx_enet.c
@@ -181,6 +181,9 @@ static void ppc_4xx_eth_halt (struct eth_device *dev)
{
EMAC_4XX_HW_PST hw_p = dev->priv;
uint32_t failsafe = 10000;
+#if defined(CONFIG_440SPE)
+ unsigned long mfr;
+#endif
out32 (EMAC_IER + hw_p->hw_addr, 0x00000000); /* disable emac interrupts */
@@ -202,8 +205,23 @@ static void ppc_4xx_eth_halt (struct eth_device *dev)
}
/* EMAC RESET */
+#if defined(CONFIG_440SPE)
+ /* provide clocks for EMAC internal loopback */
+ mfsdr (sdr_mfr, mfr);
+ mfr |= 0x08000000;
+ mtsdr(sdr_mfr, mfr);
+#endif
+
out32 (EMAC_M0 + hw_p->hw_addr, EMAC_M0_SRST);
+#if defined(CONFIG_440SPE)
+ /* remove clocks for EMAC internal loopback */
+ mfsdr (sdr_mfr, mfr);
+ mfr &= ~0x08000000;
+ mtsdr(sdr_mfr, mfr);
+#endif
+
+
#ifndef CONFIG_NETCONSOLE
hw_p->print_speed = 1; /* print speed message again next time */
#endif
@@ -301,7 +319,7 @@ int ppc_4xx_eth_setup_bridge(int devnum, bd_t * bis)
return ((int)pfc1);
}
-#endif
+#endif /* CONFIG_440_GX */
static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
{
@@ -314,12 +332,16 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
unsigned mode_reg;
unsigned short devnum;
unsigned short reg_short;
-#if defined(CONFIG_440GX) || defined(CONFIG_440SP)
+#if defined(CONFIG_440GX) || defined(CONFIG_440SP) || defined(CONFIG_440SPE)
sys_info_t sysinfo;
-#if defined(CONFIG_440GX)
+#if defined(CONFIG_440GX) || defined(CONFIG_440SPE)
int ethgroup = -1;
#endif
#endif
+#if defined(CONFIG_440SPE)
+ unsigned long mfr;
+#endif
+
EMAC_4XX_HW_PST hw_p = dev->priv;
@@ -330,7 +352,7 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
return -1;
}
-#if defined(CONFIG_440GX) || defined(CONFIG_440SP)
+#if defined(CONFIG_440GX) || defined(CONFIG_440SP) || defined(CONFIG_440SPE)
/* Need to get the OPB frequency so we can access the PHY */
get_sys_info (&sysinfo);
#endif
@@ -360,6 +382,7 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
hw_p->stats.pkts_tx = 0;
hw_p->stats.pkts_rx = 0;
hw_p->stats.pkts_handled = 0;
+ hw_p->print_speed = 1; /* print speed message again next time */
#endif
hw_p->tx_err_index = 0; /* Transmit Error Index for tx_err_log */
@@ -373,7 +396,7 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
hw_p->tx_i_index = 0; /* Transmit Interrupt Queue Index */
hw_p->tx_u_index = 0; /* Transmit User Queue Index */
-#if defined(CONFIG_440) && !defined(CONFIG_440SP)
+#if defined(CONFIG_440) && !defined(CONFIG_440SP) && !defined(CONFIG_440SPE)
/* set RMII mode */
/* NOTE: 440GX spec states that mode is mutually exclusive */
/* NOTE: Therefore, disable all other EMACS, since we handle */
@@ -406,6 +429,12 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
__asm__ volatile ("eieio");
/* reset emac so we have access to the phy */
+#if defined(CONFIG_440SPE)
+ /* provide clocks for EMAC internal loopback */
+ mfsdr (sdr_mfr, mfr);
+ mfr |= 0x08000000;
+ mtsdr(sdr_mfr, mfr);
+#endif
out32 (EMAC_M0 + hw_p->hw_addr, EMAC_M0_SRST);
__asm__ volatile ("eieio");
@@ -416,7 +445,14 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
failsafe--;
}
-#if defined(CONFIG_440GX) || defined(CONFIG_440SP)
+#if defined(CONFIG_440SPE)
+ /* remove clocks for EMAC internal loopback */
+ mfsdr (sdr_mfr, mfr);
+ mfr &= ~0x08000000;
+ mtsdr(sdr_mfr, mfr);
+#endif
+
+#if defined(CONFIG_440GX) || defined(CONFIG_440SP) || defined(CONFIG_440SPE)
/* Whack the M1 register */
mode_reg = 0x0;
mode_reg &= ~0x00000038;
@@ -468,7 +504,7 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
if (hw_p->first_init == 0) {
miiphy_reset (dev->name, reg);
-#if defined(CONFIG_440GX) || defined(CONFIG_440SP)
+#if defined(CONFIG_440GX) || defined(CONFIG_440SP) || defined(CONFIG_440SPE)
#if defined(CONFIG_CIS8201_PHY)
/*
* Cicada 8201 PHY needs to have an extended register whacked
@@ -544,7 +580,7 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
(int) speed, (duplex == HALF) ? "HALF" : "FULL");
}
-#if defined(CONFIG_440) && !defined(CONFIG_440SP)
+#if defined(CONFIG_440) && !defined(CONFIG_440SP) && !defined(CONFIG_440SPE)
#if defined(CONFIG_440EP) || defined(CONFIG_440GR)
mfsdr(sdr_mfr, reg);
if (speed == 100) {
@@ -575,7 +611,7 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
#endif /* defined(CONFIG_440) && !defined(CONFIG_440SP) */
/* set the Mal configuration reg */
-#if defined(CONFIG_440GX) || defined(CONFIG_440SP)
+#if defined(CONFIG_440GX) || defined(CONFIG_440SP) || defined(CONFIG_440SPE)
mtdcr (malmcr, MAL_CR_PLBB | MAL_CR_OPBBL | MAL_CR_LEA |
MAL_CR_PLBLT_DEFAULT | MAL_CR_EOPIE | 0x00330000);
#else
@@ -759,8 +795,7 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
/* set speed */
if (speed == _1000BASET) {
-#if defined(CONFIG_440SP)
-#define SDR0_PFC1_EM_1000 0x00200000
+#if defined(CONFIG_440SP) || defined(CONFIG_440SPE)
unsigned long pfc1;
mfsdr (sdr_pfc1, pfc1);
pfc1 |= SDR0_PFC1_EM_1000;
@@ -787,7 +822,7 @@ static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
/* set receive low/high water mark register */
#if defined(CONFIG_440)
- /* 440GP has a 64 byte burst length */
+ /* 440s has a 64 byte burst length */
out32 (EMAC_RX_HI_LO_WMARK + hw_p->hw_addr, 0x80009000);
#else
/* 405s have a 16 byte burst length */
@@ -895,7 +930,7 @@ static int ppc_4xx_eth_send (struct eth_device *dev, volatile void *ptr,
#if defined (CONFIG_440)
-#if defined(CONFIG_440SP)
+#if defined(CONFIG_440SP) || defined(CONFIG_440SPE)
/*
* Hack: On 440SP all enet irq sources are located on UIC1
* Needs some cleanup. --sr
@@ -1367,21 +1402,20 @@ int ppc_4xx_eth_initialize (bd_t * bis)
#endif
/* set phy num and mode */
bis->bi_phynum[0] = CONFIG_PHY_ADDR;
+ bis->bi_phymode[0] = 0;
+
#if defined(CONFIG_PHY1_ADDR)
bis->bi_phynum[1] = CONFIG_PHY1_ADDR;
+ bis->bi_phymode[1] = 0;
#endif
#if defined(CONFIG_440GX)
bis->bi_phynum[2] = CONFIG_PHY2_ADDR;
bis->bi_phynum[3] = CONFIG_PHY3_ADDR;
- bis->bi_phymode[0] = 0;
- bis->bi_phymode[1] = 0;
bis->bi_phymode[2] = 2;
bis->bi_phymode[3] = 2;
-#if defined (CONFIG_440GX)
ppc_4xx_eth_setup_bridge(0, bis);
#endif
-#endif
for (eth_num = 0; eth_num < LAST_EMAC_NUM; eth_num++) {
@@ -1478,9 +1512,15 @@ int ppc_4xx_eth_initialize (bd_t * bis)
if (0 == virgin) {
/* set the MAL IER ??? names may change with new spec ??? */
+#if defined(CONFIG_440SPE)
+ mal_ier =
+ MAL_IER_PT | MAL_IER_PRE | MAL_IER_PWE |
+ MAL_IER_DE | MAL_IER_OTE | MAL_IER_OE | MAL_IER_PE ;
+#else
mal_ier =
MAL_IER_DE | MAL_IER_NE | MAL_IER_TE |
MAL_IER_OPBE | MAL_IER_PLBE;
+#endif
mtdcr (malesr, 0xffffffff); /* clear pending interrupts */
mtdcr (maltxdeir, 0xffffffff); /* clear pending interrupts */
mtdcr (malrxdeir, 0xffffffff); /* clear pending interrupts */
@@ -1510,11 +1550,13 @@ int ppc_4xx_eth_initialize (bd_t * bis)
#else
emac0_dev = dev;
#endif
+
+#if defined(CONFIG_NET_MULTI)
#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)
miiphy_register (dev->name,
emac4xx_miiphy_read, emac4xx_miiphy_write);
#endif
-
+#endif
} /* end for each supported device */
return (1);
}
diff --git a/cpu/ppc4xx/cpu.c b/cpu/ppc4xx/cpu.c
index d9b5d32..6a84b09 100644
--- a/cpu/ppc4xx/cpu.c
+++ b/cpu/ppc4xx/cpu.c
@@ -82,7 +82,9 @@ int pci_arbiter_enabled(void)
return (mfdcr(cpc0_strp1) & CPC0_STRP1_PAE_MASK);
#endif
-#if defined(CONFIG_440GX) || defined(CONFIG_440EP) || defined(CONFIG_440GR) || defined(CONFIG_440SP)
+#if defined(CONFIG_440GX) || defined(CONFIG_440EP) || \
+ defined(CONFIG_440GR) || defined(CONFIG_440SP) || \
+ defined(CONFIG_440SPE)
unsigned long val;
mfsdr(sdr_sdstp1, val);
@@ -91,8 +93,8 @@ int pci_arbiter_enabled(void)
}
#endif
-#if defined(CONFIG_405EP)|| defined(CONFIG_440EP) || defined(CONFIG_440GR) || \
- defined(CONFIG_440GX) || defined(CONFIG_440SP)
+#if defined(CONFIG_405EP) || defined(CONFIG_440EP) || defined(CONFIG_440GR) || \
+ defined(CONFIG_440GX) || defined(CONFIG_440SP) || defined(CONFIG_440SPE)
#define I2C_BOOTROM
@@ -102,7 +104,9 @@ int i2c_bootrom_enabled(void)
return (mfdcr(cpc0_boot) & CPC0_BOOT_SEP);
#endif
-#if defined(CONFIG_440GX) || defined(CONFIG_440EP) || defined(CONFIG_440GR) || defined(CONFIG_440SP)
+#if defined(CONFIG_440GX) || defined(CONFIG_440EP) || \
+ defined(CONFIG_440GR) || defined(CONFIG_440SP) || \
+ defined(CONFIG_440SPE)
unsigned long val;
mfsdr(sdr_sdcs, val);
@@ -248,6 +252,12 @@ int checkcpu (void)
puts("SP Rev. B");
break;
+ case PVR_440SPe_RA:
+ puts("SPe 3GA533C");
+ break;
+ case PVR_440SPe_RB:
+ puts("SPe 3GB533C");
+ break;
default:
printf (" UNKNOWN (PVR=%08x)", pvr);
break;
diff --git a/cpu/ppc4xx/interrupts.c b/cpu/ppc4xx/interrupts.c
index 3aae4ce..886f405 100644
--- a/cpu/ppc4xx/interrupts.c
+++ b/cpu/ppc4xx/interrupts.c
@@ -50,18 +50,22 @@ struct irq_action {
};
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)
+#if defined(CONFIG_440GX) || defined(CONFIG_440SPE)
static struct irq_action irq_vecs2[32]; /* For UIC2 */
-
-void uic0_interrupt( void * parms); /* UIC0 handler */
void uic2_interrupt( void * parms); /* UIC2 handler */
-#endif /* CONFIG_440GX */
+#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 */
@@ -115,11 +119,16 @@ int interrupt_init_cpu (unsigned *decrementer_count)
irq_vecs1[vec].handler = NULL;
irq_vecs1[vec].arg = NULL;
irq_vecs1[vec].count = 0;
-#if defined(CONFIG_440GX)
+#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
}
@@ -221,6 +230,34 @@ void external_interrupt(struct pt_regs *regs)
} /* external_interrupt CONFIG_440GX */
+#elif defined(CONFIG_440SPE)
+void external_interrupt(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);
+
+ return;
+} /* external_interrupt CONFIG_440SPE */
+
#else
void external_interrupt(struct pt_regs *regs)
@@ -266,7 +303,7 @@ void external_interrupt(struct pt_regs *regs)
}
#endif
-#if defined(CONFIG_440GX)
+#if defined(CONFIG_440GX) || defined(CONFIG_440SPE)
/* Handler for UIC0 interrupt */
void uic0_interrupt( void * parms)
{
@@ -357,8 +394,8 @@ void uic1_interrupt( void * parms)
}
#endif /* defined(CONFIG_440) */
-#if defined(CONFIG_440GX)
-/* Handler for UIC1 interrupt */
+#if defined(CONFIG_440GX) || defined(CONFIG_440SPE)
+/* Handler for UIC2 interrupt */
void uic2_interrupt( void * parms)
{
ulong uic2_msr;
@@ -384,7 +421,7 @@ void uic2_interrupt( void * parms)
(*irq_vecs2[vec].handler)(irq_vecs2[vec].arg);
} else {
mtdcr(uic2er, mfdcr(uic2er) & ~(0x80000000 >> vec));
- printf ("Masking bogus interrupt vector (uic1) 0x%x\n", vec);
+ printf ("Masking bogus interrupt vector (uic2) 0x%x\n", vec);
}
/*
@@ -402,6 +439,51 @@ void uic2_interrupt( void * parms)
}
#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++;
+ }
+}
+#endif /* defined(CONFIG_440SPE) */
+
/****************************************************************************/
/*
@@ -414,7 +496,7 @@ void irq_install_handler (int vec, interrupt_handler_t * handler, void *arg)
int i = vec;
#if defined(CONFIG_440)
-#if defined(CONFIG_440GX)
+#if defined(CONFIG_440GX) || defined(CONFIG_440SPE)
if ((vec > 31) && (vec < 64)) {
i = vec - 32;
irqa = irq_vecs1;
@@ -441,7 +523,7 @@ void irq_install_handler (int vec, interrupt_handler_t * handler, void *arg)
irqa[i].arg = arg;
#if defined(CONFIG_440)
-#if defined(CONFIG_440GX)
+#if defined(CONFIG_440GX) || defined(CONFIG_440SPE)
if ((vec > 31) && (vec < 64))
mtdcr (uic1er, mfdcr (uic1er) | (0x80000000 >> i));
else if (vec > 63)
@@ -464,7 +546,7 @@ void irq_free_handler (int vec)
int i = vec;
#if defined(CONFIG_440)
-#if defined(CONFIG_440GX)
+#if defined(CONFIG_440GX) || defined(CONFIG_440SPE)
if ((vec > 31) && (vec < 64)) {
irqa = irq_vecs1;
i = vec - 32;
@@ -485,7 +567,7 @@ void irq_free_handler (int vec)
#endif
#if defined(CONFIG_440)
-#if defined(CONFIG_440GX)
+#if defined(CONFIG_440GX) || defined(CONFIG_440SPE)
if ((vec > 31) && (vec < 64))
mtdcr (uic1er, mfdcr (uic1er) & ~(0x80000000 >> i));
else if (vec > 63)
@@ -553,7 +635,7 @@ do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
printf("\n");
#endif
-#if defined(CONFIG_440GX)
+#if defined(CONFIG_440GX) || defined(CONFIG_440SPE)
printf ("\nUIC 2\n");
printf ("Nr Routine Arg Count\n");
@@ -566,6 +648,19 @@ do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
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 */
diff --git a/cpu/ppc4xx/miiphy.c b/cpu/ppc4xx/miiphy.c
index f26f2a2..aa580ed 100644
--- a/cpu/ppc4xx/miiphy.c
+++ b/cpu/ppc4xx/miiphy.c
@@ -50,7 +50,7 @@
#include <405_mal.h>
#include <miiphy.h>
-
+#undef ET_DEBUG
/***********************************************************/
/* Dump out to the screen PHY regs */
/***********************************************************/
@@ -90,6 +90,10 @@ int phy_setup_aneg (char *devname, unsigned char addr)
PHY_ANLPAR_10);
miiphy_write (devname, addr, PHY_ANAR, adv);
+ miiphy_read (devname, addr, PHY_1000BTCR, &adv);
+ adv |= (0x0300);
+ miiphy_write (devname, addr, PHY_1000BTCR, adv);
+
/* Start/Restart aneg */
miiphy_read (devname, addr, PHY_BMCR, &ctl);
ctl |= (PHY_BMCR_AUTON | PHY_BMCR_RST_NEG);
@@ -104,7 +108,7 @@ int phy_setup_aneg (char *devname, unsigned char addr)
/***********************************************************/
unsigned int miiphy_getemac_offset (void)
{
-#if (defined(CONFIG_440) && !defined(CONFIG_440SP)) && defined(CONFIG_NET_MULTI)
+#if (defined(CONFIG_440) && !defined(CONFIG_440SP) && !defined(CONFIG_440SPE)) && defined(CONFIG_NET_MULTI)
unsigned long zmii;
unsigned long eoffset;
@@ -155,10 +159,12 @@ int emac4xx_miiphy_read (char *devname, unsigned char addr,
i = 0;
/* see if it is ready for sec */
- while ((in32 (EMAC_STACR + emac_reg) & EMAC_STACR_OC) == 0) {
+ while ((in32 (EMAC_STACR + emac_reg) & EMAC_STACR_OC) == EMAC_STACR_OC_MASK) {
udelay (7);
if (i > 5) {
-#if 0
+#ifdef ET_DEBUG
+ sta_reg = in32 (EMAC_STACR + emac_reg);
+ printf ("read : EMAC_STACR=0x%0x\n", sta_reg); /* test-only */
printf ("read err 1\n");
#endif
return -1;
@@ -167,31 +173,41 @@ int emac4xx_miiphy_read (char *devname, unsigned char addr,
}
sta_reg = reg; /* reg address */
/* set clock (50Mhz) and read flags */
-#if defined(CONFIG_440GX)
- sta_reg |= EMAC_STACR_READ;
+#if defined(CONFIG_440GX) || defined(CONFIG_440SPE)
+#if defined(CONFIG_IBM_EMAC4_V4) /* EMAC4 V4 changed bit setting */
+ sta_reg = (sta_reg & ~EMAC_STACR_OP_MASK) | EMAC_STACR_READ;
+#else
+ sta_reg |= EMAC_STACR_READ;
+#endif
#else
sta_reg = (sta_reg | EMAC_STACR_READ) & ~EMAC_STACR_CLK_100MHZ;
#endif
-#if defined(CONFIG_PHY_CLK_FREQ) && !defined(CONFIG_440GX)
+#if defined(CONFIG_PHY_CLK_FREQ) && !defined(CONFIG_440GX) && !defined(CONFIG__440SP) && !defined(CONFIG__440SPE)
sta_reg = sta_reg | CONFIG_PHY_CLK_FREQ;
#endif
sta_reg = sta_reg | (addr << 5); /* Phy address */
-
+ sta_reg = sta_reg | EMAC_STACR_OC_MASK; /* new IBM emac v4 */
out32 (EMAC_STACR + emac_reg, sta_reg);
-#if 0 /* test-only */
+#ifdef ET_DEBUG
printf ("a2: write: EMAC_STACR=0x%0x\n", sta_reg); /* test-only */
#endif
sta_reg = in32 (EMAC_STACR + emac_reg);
+#ifdef ET_DEBUG
+ printf ("a21: read : EMAC_STACR=0x%0x\n", sta_reg); /* test-only */
+#endif
i = 0;
- while ((sta_reg & EMAC_STACR_OC) == 0) {
+ while ((sta_reg & EMAC_STACR_OC) == EMAC_STACR_OC_MASK) {
udelay (7);
if (i > 5) {
return -1;
}
i++;
sta_reg = in32 (EMAC_STACR + emac_reg);
+#ifdef ET_DEBUG
+ printf ("a22: read : EMAC_STACR=0x%0x\n", sta_reg); /* test-only */
+#endif
}
if ((sta_reg & EMAC_STACR_PHYE) != 0) {
return -1;
@@ -219,7 +235,7 @@ int emac4xx_miiphy_write (char *devname, unsigned char addr,
/* see if it is ready for 1000 nsec */
i = 0;
- while ((in32 (EMAC_STACR + emac_reg) & EMAC_STACR_OC) == 0) {
+ while ((in32 (EMAC_STACR + emac_reg) & EMAC_STACR_OC) == EMAC_STACR_OC_MASK) {
if (i > 5)
return -1;
udelay (7);
@@ -228,16 +244,21 @@ int emac4xx_miiphy_write (char *devname, unsigned char addr,
sta_reg = 0;
sta_reg = reg; /* reg address */
/* set clock (50Mhz) and read flags */
-#if defined(CONFIG_440GX)
- sta_reg |= EMAC_STACR_WRITE;
+#if defined(CONFIG_440GX) || defined(CONFIG_440SPE)
+#if defined(CONFIG_IBM_EMAC4_V4) /* EMAC4 V4 changed bit setting */
+ sta_reg = (sta_reg & ~EMAC_STACR_OP_MASK) | EMAC_STACR_WRITE;
+#else
+ sta_reg |= EMAC_STACR_WRITE;
+#endif
#else
sta_reg = (sta_reg | EMAC_STACR_WRITE) & ~EMAC_STACR_CLK_100MHZ;
#endif
-#if defined(CONFIG_PHY_CLK_FREQ) && !defined(CONFIG_440GX)
+#if defined(CONFIG_PHY_CLK_FREQ) && !defined(CONFIG_440GX) && !defined(CONFIG__440SP) && !defined(CONFIG__440SPE)
sta_reg = sta_reg | CONFIG_PHY_CLK_FREQ; /* Set clock frequency (PLB freq. dependend) */
#endif
- sta_reg = sta_reg | ((unsigned long) addr << 5); /* Phy address */
+ sta_reg = sta_reg | ((unsigned long) addr << 5);/* Phy address */
+ sta_reg = sta_reg | EMAC_STACR_OC_MASK; /* new IBM emac v4 */
memcpy (&sta_reg, &value, 2); /* put in data */
out32 (EMAC_STACR + emac_reg, sta_reg);
@@ -245,12 +266,18 @@ int emac4xx_miiphy_write (char *devname, unsigned char addr,
/* wait for completion */
i = 0;
sta_reg = in32 (EMAC_STACR + emac_reg);
- while ((sta_reg & EMAC_STACR_OC) == 0) {
+#ifdef ET_DEBUG
+ printf ("a31: read : EMAC_STACR=0x%0x\n", sta_reg); /* test-only */
+#endif
+ while ((sta_reg & EMAC_STACR_OC) == EMAC_STACR_OC_MASK) {
udelay (7);
if (i > 5)
return -1;
i++;
sta_reg = in32 (EMAC_STACR + emac_reg);
+#ifdef ET_DEBUG
+ printf ("a32: read : EMAC_STACR=0x%0x\n", sta_reg); /* test-only */
+#endif
}
if ((sta_reg & EMAC_STACR_PHYE) != 0)
diff --git a/cpu/ppc4xx/serial.c b/cpu/ppc4xx/serial.c
index 83c9479..3749811 100644
--- a/cpu/ppc4xx/serial.c
+++ b/cpu/ppc4xx/serial.c
@@ -275,11 +275,11 @@ int serial_tstc ()
#define UART1_BASE CFG_PERIPHERAL_BASE + 0x00000300
#endif
-#if defined(CONFIG_440SP)
+#if defined(CONFIG_440SP) || defined(CONFIG_440SPE)
#define UART2_BASE CFG_PERIPHERAL_BASE + 0x00000600
#endif
-#if defined(CONFIG_440GX) || defined(CONFIG_440EP) || defined(CONFIG_440GR) || defined(CONFIG_440SP)
+#if defined(CONFIG_440GX) || defined(CONFIG_440EP) || defined(CONFIG_440GR) || defined(CONFIG_440SP) || defined(CONFIG_440SPE)
#define CR0_MASK 0xdfffffff
#define CR0_EXTCLK_ENA 0x00800000
#define CR0_UDIV_POS 0
@@ -309,14 +309,18 @@ int serial_tstc ()
#if defined(CONFIG_UART1_CONSOLE)
#define ACTING_UART0_BASE UART1_BASE
#define ACTING_UART1_BASE UART0_BASE
-#if defined(CONFIG_440GX) || defined(CONFIG_440EP) || defined(CONFIG_440GR) || defined(CONFIG_440SP)
+#if defined(CONFIG_440GX) || defined(CONFIG_440EP) || \
+ defined(CONFIG_440GR) || defined(CONFIG_440SP) || \
+ defined(CONFIG_440SPE)
#define UART0_SDR sdr_uart1
#define UART1_SDR sdr_uart0
#endif /* CONFIG_440GX */
#else
#define ACTING_UART0_BASE UART0_BASE
#define ACTING_UART1_BASE UART1_BASE
-#if defined(CONFIG_440GX) || defined(CONFIG_440EP) || defined(CONFIG_440GR) || defined(CONFIG_440SP)
+#if defined(CONFIG_440GX) || defined(CONFIG_440EP) || \
+ defined(CONFIG_440GR) || defined(CONFIG_440SP) || \
+ defined(CONFIG_440SPE)
#define UART0_SDR sdr_uart0
#define UART1_SDR sdr_uart1
#endif /* CONFIG_440GX */
@@ -437,7 +441,8 @@ int serial_init(void)
unsigned long tmp;
#endif
-#if defined(CONFIG_440GX) || defined(CONFIG_440SP)
+#if defined(CONFIG_440GX) || defined(CONFIG_440SP) || \
+ defined(CONFIG_440SPE)
#if defined(CONFIG_SERIAL_MULTI)
if (UART0_BASE == dev_base) {
mfsdr(UART0_SDR,reg);
@@ -466,7 +471,9 @@ int serial_init(void)
serial_divs (gd->baudrate, &udiv, &bdiv);
#endif
-#if defined(CONFIG_440GX) || defined(CONFIG_440EP) || defined(CONFIG_440GR) || defined(CONFIG_440SP)
+#if defined(CONFIG_440GX) || defined(CONFIG_440EP) || \
+ defined(CONFIG_440GR) || defined(CONFIG_440SP) || \
+ defined(CONFIG_440SPE)
reg |= udiv << CR0_UDIV_POS; /* set the UART divisor */
#if defined(CONFIG_SERIAL_MULTI)
if (UART0_BASE == dev_base) {
@@ -607,8 +614,28 @@ void serial_setbrg (void)
#else
udiv = ((mfdcr (cntrl0) & 0x3e) >> 1) + 1;
#endif /* CONFIG_405EP */
+
+#if !defined(CFG_EXT_SERIAL_CLOCK) && \
+ ( defined(CONFIG_440GX) || defined(CONFIG_440EP) || \
+ defined(CONFIG_440GR) || defined(CONFIG_440SP) || \
+ defined(CONFIG_440SPE) )
+ serial_divs (gd->baudrate, &udiv, &bdiv);
+ tmp = udiv << CR0_UDIV_POS; /* set the UART divisor */
+#if defined(CONFIG_SERIAL_MULTI)
+ if (UART0_BASE == dev_base) {
+ mtsdr (UART0_SDR, tmp);
+ } else {
+ mtsdr (UART1_SDR, tmp);
+ }
+#else
+ mtsdr (UART0_SDR, tmp);
+#endif
+
+#else
+
tmp = gd->baudrate * udiv * 16;
bdiv = (clk + tmp / 2) / tmp;
+#endif /* !defined(CFG_EXT_SERIAL_CLOCK) && (...) */
#if defined(CONFIG_SERIAL_MULTI)
out8 (dev_base + UART_LCR, 0x80); /* set DLAB bit */
diff --git a/cpu/ppc4xx/speed.c b/cpu/ppc4xx/speed.c
index 02b4383..e552c03 100644
--- a/cpu/ppc4xx/speed.c
+++ b/cpu/ppc4xx/speed.c
@@ -29,7 +29,11 @@
DECLARE_GLOBAL_DATA_PTR;
#define ONE_BILLION 1000000000
-
+#ifdef DEBUG
+#define DEBUGF(fmt,args...) printf(fmt ,##args)
+#else
+#define DEBUGF(fmt,args...)
+#endif
#if defined(CONFIG_405GP) || defined(CONFIG_405CR)
@@ -283,7 +287,7 @@ ulong get_PCI_freq (void)
return sys_info.freqPCI;
}
-#elif !defined(CONFIG_440GX) && !defined(CONFIG_440SP)
+#elif !defined(CONFIG_440GX) && !defined(CONFIG_440SP) && !defined(CONFIG_440SPE)
void get_sys_info (sys_info_t * sysInfo)
{
unsigned long strp0;
@@ -326,6 +330,26 @@ void get_sys_info (sys_info_t * sysInfo)
unsigned long m;
unsigned long prbdv0;
+#if defined(CONFIG_440SPE)
+ unsigned long sys_freq;
+ unsigned long sys_per=0;
+ unsigned long msr;
+ unsigned long pci_clock_per;
+ unsigned long sdr_ddrpll;
+
+ /*-------------------------------------------------------------------------+
+ | Get the system clock period.
+ +-------------------------------------------------------------------------*/
+ sys_per = determine_sysper();
+
+ msr = (mfmsr () & ~(MSR_EE)); /* disable interrupts */
+
+ /*-------------------------------------------------------------------------+
+ | Calculate the system clock speed from the period.
+ +-------------------------------------------------------------------------*/
+ sys_freq=(ONE_BILLION/sys_per)*1000;
+#endif
+
/* Extract configured divisors */
mfsdr( sdr_sdstp0,strp0 );
mfsdr( sdr_sdstp1,strp1 );
@@ -360,12 +384,238 @@ void get_sys_info (sys_info_t * sysInfo)
m = sysInfo->pllExtBusDiv * sysInfo->pllOpbDiv * sysInfo->pllFwdDivB;
/* Now calculate the individual clocks */
+#if defined(CONFIG_440SPE)
+ sysInfo->freqVCOMhz = (m * sys_freq) ;
+#else
sysInfo->freqVCOMhz = (m * CONFIG_SYS_CLK_FREQ) + (m>>1);
+#endif
sysInfo->freqProcessor = sysInfo->freqVCOMhz/sysInfo->pllFwdDivA;
sysInfo->freqPLB = sysInfo->freqVCOMhz/sysInfo->pllFwdDivB/prbdv0;
sysInfo->freqOPB = sysInfo->freqPLB/sysInfo->pllOpbDiv;
sysInfo->freqEPB = sysInfo->freqOPB/sysInfo->pllExtBusDiv;
+#if defined(CONFIG_440SPE)
+ /* Determine PCI Clock Period */
+ pci_clock_per = determine_pci_clock_per();
+ sysInfo->freqPCI = (ONE_BILLION/pci_clock_per) * 1000;
+ mfsdr(sdr_ddr0, sdr_ddrpll);
+ sysInfo->freqDDR = ((sysInfo->freqPLB) * SDR0_DDR0_DDRM_DECODE(sdr_ddrpll));
+#endif
+
+
+}
+
+#endif
+
+#if defined(CONFIG_440SPE)
+unsigned long determine_sysper(void)
+{
+ unsigned int fpga_clocking_reg;
+ unsigned int master_clock_selection;
+ unsigned long master_clock_per = 0;
+ unsigned long fb_div_selection;
+ unsigned int vco_div_reg_value;
+ unsigned long vco_div_selection;
+ unsigned long sys_per = 0;
+ int extClkVal;
+
+ /*-------------------------------------------------------------------------+
+ | Read FPGA reg 0 and reg 1 to get FPGA reg information
+ +-------------------------------------------------------------------------*/
+ fpga_clocking_reg = in16(FPGA_REG16);
+
+
+ /* Determine Master Clock Source Selection */
+ master_clock_selection = fpga_clocking_reg & FPGA_REG16_MASTER_CLK_MASK;
+
+ switch(master_clock_selection) {
+ case FPGA_REG16_MASTER_CLK_66_66:
+ master_clock_per = PERIOD_66_66MHZ;
+ break;
+ case FPGA_REG16_MASTER_CLK_50:
+ master_clock_per = PERIOD_50_00MHZ;
+ break;
+ case FPGA_REG16_MASTER_CLK_33_33:
+ master_clock_per = PERIOD_33_33MHZ;
+ break;
+ case FPGA_REG16_MASTER_CLK_25:
+ master_clock_per = PERIOD_25_00MHZ;
+ break;
+ case FPGA_REG16_MASTER_CLK_EXT:
+ if ((extClkVal==EXTCLK_33_33)
+ && (extClkVal==EXTCLK_50)
+ && (extClkVal==EXTCLK_66_66)
+ && (extClkVal==EXTCLK_83)) {
+ /* calculate master clock period from external clock value */
+ master_clock_per=(ONE_BILLION/extClkVal) * 1000;
+ } else {
+ /* Unsupported */
+ DEBUGF ("%s[%d] *** master clock selection failed ***\n", __FUNCTION__,__LINE__);
+ hang();
+ }
+ break;
+ default:
+ /* Unsupported */
+ DEBUGF ("%s[%d] *** master clock selection failed ***\n", __FUNCTION__,__LINE__);
+ hang();
+ break;
+ }
+
+ /* Determine FB divisors values */
+ if ((fpga_clocking_reg & FPGA_REG16_FB1_DIV_MASK) == FPGA_REG16_FB1_DIV_LOW) {
+ if ((fpga_clocking_reg & FPGA_REG16_FB2_DIV_MASK) == FPGA_REG16_FB2_DIV_LOW)
+ fb_div_selection = FPGA_FB_DIV_6;
+ else
+ fb_div_selection = FPGA_FB_DIV_12;
+ } else {
+ if ((fpga_clocking_reg & FPGA_REG16_FB2_DIV_MASK) == FPGA_REG16_FB2_DIV_LOW)
+ fb_div_selection = FPGA_FB_DIV_10;
+ else
+ fb_div_selection = FPGA_FB_DIV_20;
+ }
+
+ /* Determine VCO divisors values */
+ vco_div_reg_value = fpga_clocking_reg & FPGA_REG16_VCO_DIV_MASK;
+
+ switch(vco_div_reg_value) {
+ case FPGA_REG16_VCO_DIV_4:
+ vco_div_selection = FPGA_VCO_DIV_4;
+ break;
+ case FPGA_REG16_VCO_DIV_6:
+ vco_div_selection = FPGA_VCO_DIV_6;
+ break;
+ case FPGA_REG16_VCO_DIV_8:
+ vco_div_selection = FPGA_VCO_DIV_8;
+ break;
+ case FPGA_REG16_VCO_DIV_10:
+ default:
+ vco_div_selection = FPGA_VCO_DIV_10;
+ break;
+ }
+
+ if (master_clock_selection == FPGA_REG16_MASTER_CLK_EXT) {
+ switch(master_clock_per) {
+ case PERIOD_25_00MHZ:
+ if (fb_div_selection == FPGA_FB_DIV_12) {
+ if (vco_div_selection == FPGA_VCO_DIV_4)
+ sys_per = PERIOD_75_00MHZ;
+ if (vco_div_selection == FPGA_VCO_DIV_6)
+ sys_per = PERIOD_50_00MHZ;
+ }
+ break;
+ case PERIOD_33_33MHZ:
+ if (fb_div_selection == FPGA_FB_DIV_6) {
+ if (vco_div_selection == FPGA_VCO_DIV_4)
+ sys_per = PERIOD_50_00MHZ;
+ if (vco_div_selection == FPGA_VCO_DIV_6)
+ sys_per = PERIOD_33_33MHZ;
+ }
+ if (fb_div_selection == FPGA_FB_DIV_10) {
+ if (vco_div_selection == FPGA_VCO_DIV_4)
+ sys_per = PERIOD_83_33MHZ;
+ if (vco_div_selection == FPGA_VCO_DIV_10)
+ sys_per = PERIOD_33_33MHZ;
+ }
+ if (fb_div_selection == FPGA_FB_DIV_12) {
+ if (vco_div_selection == FPGA_VCO_DIV_4)
+ sys_per = PERIOD_100_00MHZ;
+ if (vco_div_selection == FPGA_VCO_DIV_6)
+ sys_per = PERIOD_66_66MHZ;
+ if (vco_div_selection == FPGA_VCO_DIV_8)
+ sys_per = PERIOD_50_00MHZ;
+ }
+ break;
+ case PERIOD_50_00MHZ:
+ if (fb_div_selection == FPGA_FB_DIV_6) {
+ if (vco_div_selection == FPGA_VCO_DIV_4)
+ sys_per = PERIOD_75_00MHZ;
+ if (vco_div_selection == FPGA_VCO_DIV_6)
+ sys_per = PERIOD_50_00MHZ;
+ }
+ if (fb_div_selection == FPGA_FB_DIV_10) {
+ if (vco_div_selection == FPGA_VCO_DIV_6)
+ sys_per = PERIOD_83_33MHZ;
+ if (vco_div_selection == FPGA_VCO_DIV_10)
+ sys_per = PERIOD_50_00MHZ;
+ }
+ if (fb_div_selection == FPGA_FB_DIV_12) {
+ if (vco_div_selection == FPGA_VCO_DIV_6)
+ sys_per = PERIOD_100_00MHZ;
+ if (vco_div_selection == FPGA_VCO_DIV_8)
+ sys_per = PERIOD_75_00MHZ;
+ }
+ break;
+ case PERIOD_66_66MHZ:
+ if (fb_div_selection == FPGA_FB_DIV_6) {
+ if (vco_div_selection == FPGA_VCO_DIV_4)
+ sys_per = PERIOD_100_00MHZ;
+ if (vco_div_selection == FPGA_VCO_DIV_6)
+ sys_per = PERIOD_66_66MHZ;
+ if (vco_div_selection == FPGA_VCO_DIV_8)
+ sys_per = PERIOD_50_00MHZ;
+ }
+ if (fb_div_selection == FPGA_FB_DIV_10) {
+ if (vco_div_selection == FPGA_VCO_DIV_8)
+ sys_per = PERIOD_83_33MHZ;
+ if (vco_div_selection == FPGA_VCO_DIV_10)
+ sys_per = PERIOD_66_66MHZ;
+ }
+ if (fb_div_selection == FPGA_FB_DIV_12) {
+ if (vco_div_selection == FPGA_VCO_DIV_8)
+ sys_per = PERIOD_100_00MHZ;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (sys_per == 0) {
+ /* Other combinations are not supported */
+ DEBUGF ("%s[%d] *** sys period compute failed ***\n", __FUNCTION__,__LINE__);
+ hang();
+ }
+ } else {
+ /* calcul system clock without cheking */
+ /* if engineering option clock no check is selected */
+ /* sys_per = master_clock_per * vco_div_selection / fb_div_selection */
+ sys_per = (master_clock_per/fb_div_selection) * vco_div_selection;
+ }
+
+ return(sys_per);
+
+}
+
+/*-------------------------------------------------------------------------+
+| determine_pci_clock_per.
++-------------------------------------------------------------------------*/
+unsigned long determine_pci_clock_per(void)
+{
+ unsigned long pci_clock_selection, pci_period;
+
+ /*-------------------------------------------------------------------------+
+ | Read FPGA reg 6 to get PCI 0 FPGA reg information
+ +-------------------------------------------------------------------------*/
+ pci_clock_selection = in16(FPGA_REG16); /* was reg6 averifier */
+
+
+ pci_clock_selection = pci_clock_selection & FPGA_REG16_PCI0_CLK_MASK;
+
+ switch (pci_clock_selection) {
+ case FPGA_REG16_PCI0_CLK_133_33:
+ pci_period = PERIOD_133_33MHZ;
+ break;
+ case FPGA_REG16_PCI0_CLK_100:
+ pci_period = PERIOD_100_00MHZ;
+ break;
+ case FPGA_REG16_PCI0_CLK_66_66:
+ pci_period = PERIOD_66_66MHZ;
+ break;
+ default:
+ pci_period = PERIOD_33_33MHZ;;
+ break;
+ }
+
+ return(pci_period);
}
#endif
diff --git a/cpu/ppc4xx/start.S b/cpu/ppc4xx/start.S
index 647088f..f37c1d6 100644
--- a/cpu/ppc4xx/start.S
+++ b/cpu/ppc4xx/start.S
@@ -155,6 +155,11 @@
/**************************************************************************/
_start_440:
+ /*----------------------------------------------------------------+
+ | Core bug fix. Clear the esr
+ +-----------------------------------------------------------------*/
+ addi r0,r0,0x0000
+ mtspr esr,r0
/*----------------------------------------------------------------*/
/* Clear and set up some registers. */
/*----------------------------------------------------------------*/
@@ -166,7 +171,7 @@ _start_440:
mtspr srr1,r0
mtspr csrr0,r0
mtspr csrr1,r0
-#if defined(CONFIG_440GX) || defined(CONFIG_440SP) /* NOTE: 440GX adds machine check status regs */
+#if defined(CONFIG_440GX) || defined(CONFIG_440SP) || defined(CONFIG_440SPE) /* NOTE: 440GX adds machine check status regs */
mtspr mcsrr0,r0
mtspr mcsrr1,r0
mfspr r1, mcsr
@@ -200,6 +205,33 @@ _start_440:
ori r1,r1,0x6000 /* cache touch */
mtspr ccr0,r1
+#if defined (CONFIG_440SPE)
+ /*----------------------------------------------------------------+
+ | Initialize Core Configuration Reg1.
+ | a. ICDPEI: Record even parity. Normal operation.
+ | b. ICTPEI: Record even parity. Normal operation.
+ | c. DCTPEI: Record even parity. Normal operation.
+ | d. DCDPEI: Record even parity. Normal operation.
+ | e. DCUPEI: Record even parity. Normal operation.
+ | f. DCMPEI: Record even parity. Normal operation.
+ | g. FCOM: Normal operation
+ | h. MMUPEI: Record even parity. Normal operation.
+ | i. FFF: Flush only as much data as necessary.
+ | j. TCS: Timebase increments from externally supplied clock
+ +-----------------------------------------------------------------*/
+ addis r0, r0, 0x0000
+ ori r0, r0, 0x0080
+ mtspr ccr1, r0
+
+ /*----------------------------------------------------------------+
+ | Reset the timebase.
+ | The previous write to CCR1 sets the timebase source.
+ +-----------------------------------------------------------------*/
+ addi r0, r0, 0x0000
+ mtspr tbl, r0
+ mtspr tbu, r0
+#endif
+
/*----------------------------------------------------------------*/
/* Setup interrupt vectors */
/*----------------------------------------------------------------*/
@@ -261,15 +293,26 @@ _start_440:
mtspr ivlim,r1
mtspr dvlim,r1
+ /*----------------------------------------------------------------+
+ |Initialize MMUCR[STID] = 0.
+ +-----------------------------------------------------------------*/
+ mfspr r0,mmucr
+ addis r1,0,0xFFFF
+ ori r1,r1,0xFF00
+ and r0,r0,r1
+ mtspr mmucr,r0
+
/*----------------------------------------------------------------*/
/* Clear all TLB entries -- TID = 0, TS = 0 */
/*----------------------------------------------------------------*/
- mtspr mmucr,r0
+ addis r0,0,0x0000
li r1,0x003f /* 64 TLB entries */
mtctr r1
-0: tlbwe r0,r1,0x0000 /* Invalidate all entries (V=0)*/
+rsttlb: tlbwe r0,r1,0x0000 /* Invalidate all entries (V=0)*/
+ tlbwe r0,r1,0x0001
+ tlbwe r0,r1,0x0002
subi r1,r1,0x0001
- bdnz 0b
+ bdnz rsttlb
/*----------------------------------------------------------------*/
/* TLB entry setup -- step thru tlbtab */
@@ -377,7 +420,7 @@ _start:
addi r3,r3,32
bdnz ..d_ag
#else
-#if defined (CONFIG_440GX) || defined(CONFIG_440SP)
+#if defined (CONFIG_440GX) || defined(CONFIG_440SP) || defined(CONFIG_440SPE)
mtdcr l2_cache_cfg,r0 /* Ensure L2 Cache is off */
#endif
mtdcr isram0_sb1cr,r0 /* Disable bank 1 */
@@ -404,6 +447,19 @@ _start:
lis r1, 0x8003
ori r1,r1, 0x0980 /* fourth 64k */
mtdcr isram0_sb3cr,r1
+#elif defined(CONFIG_440SPE)
+ lis r1,0x0000 /* BAS = 0000_0000 */
+ ori r1,r1,0x0984 /* first 64k */
+ mtdcr isram0_sb0cr,r1
+ lis r1,0x0001
+ ori r1,r1,0x0984 /* second 64k */
+ mtdcr isram0_sb1cr,r1
+ lis r1, 0x0002
+ ori r1,r1, 0x0984 /* third 64k */
+ mtdcr isram0_sb2cr,r1
+ lis r1, 0x0003
+ ori r1,r1, 0x0984 /* fourth 64k */
+ mtdcr isram0_sb3cr,r1
#else
ori r1,r1,0x0380 /* 8k rw */
mtdcr isram0_sb0cr,r1
@@ -1197,7 +1253,7 @@ ppcSync:
*/
.globl relocate_code
relocate_code:
-#if defined(CONFIG_440EP) || defined(CONFIG_440GR)
+#if defined(CONFIG_440EP) || defined(CONFIG_440GR) || defined(CONFIG_440SPE)
/*
* On some 440er platforms the cache is enabled in the first TLB (Boot-CS)
* to speed up the boot process. Now this cache needs to be disabled.
@@ -1412,7 +1468,7 @@ trap_init:
cmplw 0, r7, r8
blt 4b
-#if !defined(CONFIG_440_GX)
+#if !defined(CONFIG_440_GX) && !defined(CONFIG_440SPE)
addi r7,r0,0x1000 /* set ME bit (Machine Exceptions) */
oris r7,r7,0x0002 /* set CE bit (Critical Exceptions) */
mtmsr r7 /* change MSR */
diff --git a/cpu/ppc4xx/vecnum.h b/cpu/ppc4xx/vecnum.h
index cbfe41d..93cef02 100644
--- a/cpu/ppc4xx/vecnum.h
+++ b/cpu/ppc4xx/vecnum.h
@@ -31,7 +31,48 @@
#ifndef _VECNUMS_H_
#define _VECNUMS_H_
-#if defined(CONFIG_440SP)
+#if defined(CONFIG_440SPE)
+/* UIC 0 */
+#define VECNUM_U0 0 /* UART0 */
+#define VECNUM_U1 1 /* UART1 */
+#define VECNUM_IIC0 2 /* IIC0 */
+#define VECNUM_IIC1 3 /* IIC1 */
+#define VECNUM_PIM 4 /* PCI inbound message */
+#define VECNUM_PCRW 5 /* PCI command reg write */
+#define VECNUM_PPM 6 /* PCI power management */
+#define VECNUM_MSI0 7 /* PCI MSI level 0 */
+#define VECNUM_MSI1 8 /* PCI MSI level 0 */
+#define VECNUM_MSI2 9 /* PCI MSI level 0 */
+#define VECNUM_D0 12 /* DMA channel 0 */
+#define VECNUM_D1 13 /* DMA channel 1 */
+#define VECNUM_D2 14 /* DMA channel 2 */
+#define VECNUM_D3 15 /* DMA channel 3 */
+#define VECNUM_UIC1NC 30 /* UIC1 non-critical interrupt */
+#define VECNUM_UIC1C 31 /* UIC1 critical interrupt */
+
+/* UIC 1 */
+#define VECNUM_MS (32 + 1 ) /* MAL SERR */
+#define VECNUM_TXDE (32 + 2 ) /* MAL TXDE */
+#define VECNUM_RXDE (32 + 3 ) /* MAL RXDE */
+#define VECNUM_MTE (32 + 6 ) /* MAL Tx EOB */
+#define VECNUM_MRE (32 + 7 ) /* MAL Rx EOB */
+#define VECNUM_CT0 (32 + 12 ) /* GPT compare timer 0 */
+#define VECNUM_CT1 (32 + 13 ) /* GPT compare timer 1 */
+#define VECNUM_CT2 (32 + 14 ) /* GPT compare timer 2 */
+#define VECNUM_CT3 (32 + 15 ) /* GPT compare timer 3 */
+#define VECNUM_CT4 (32 + 16 ) /* GPT compare timer 4 */
+#define VECNUM_ETH0 (32 + 28) /* Ethernet interrupt status */
+#define VECNUM_EWU0 (32 + 29) /* Emac wakeup */
+
+/* UIC 2 */
+#define VECNUM_EIR5 (62 + 24) /* External interrupt 5 */
+#define VECNUM_EIR4 (62 + 25) /* External interrupt 4 */
+#define VECNUM_EIR3 (62 + 26) /* External interrupt 3 */
+#define VECNUM_EIR2 (62 + 27) /* External interrupt 2 */
+#define VECNUM_EIR1 (62 + 28) /* External interrupt 1 */
+#define VECNUM_EIR0 (62 + 29) /* External interrupt 0 */
+
+#elif defined(CONFIG_440SP)
/* UIC 0 */
#define VECNUM_U0 0 /* UART0 */