summaryrefslogtreecommitdiff
path: root/cpu/ppc4xx/440gx_enet.c
diff options
context:
space:
mode:
Diffstat (limited to 'cpu/ppc4xx/440gx_enet.c')
-rw-r--r--cpu/ppc4xx/440gx_enet.c166
1 files changed, 114 insertions, 52 deletions
diff --git a/cpu/ppc4xx/440gx_enet.c b/cpu/ppc4xx/440gx_enet.c
index 871f83b96e0..d0b6c158644 100644
--- a/cpu/ppc4xx/440gx_enet.c
+++ b/cpu/ppc4xx/440gx_enet.c
@@ -167,13 +167,15 @@ static void ppc_440x_eth_halt (struct eth_device *dev)
/* EMAC RESET */
out32 (EMAC_M0 + hw_p->hw_addr, EMAC_M0_SRST);
+ hw_p->print_speed = 1; /* print speed message again next time */
+
return;
}
extern int phy_setup_aneg (unsigned char addr);
extern int miiphy_reset (unsigned char addr);
-#if defined (CONFIG_440_GX)
+#if defined (CONFIG_440GX)
int ppc_440x_eth_setup_bridge(int devnum, bd_t * bis)
{
unsigned long pfc1;
@@ -267,7 +269,7 @@ int ppc_440x_eth_setup_bridge(int devnum, bd_t * bis)
static int ppc_440x_eth_init (struct eth_device *dev, bd_t * bis)
{
- int i;
+ int i, j;
unsigned long reg;
unsigned long msr;
unsigned long speed;
@@ -277,7 +279,9 @@ static int ppc_440x_eth_init (struct eth_device *dev, bd_t * bis)
unsigned short devnum;
unsigned short reg_short;
sys_info_t sysinfo;
+#if defined(CONFIG_440GX)
int ethgroup;
+#endif
EMAC_440GX_HW_PST hw_p = dev->priv;
@@ -289,7 +293,6 @@ static int ppc_440x_eth_init (struct eth_device *dev, bd_t * bis)
/* Need to get the OPB frequency so we can access the PHY */
get_sys_info (&sysinfo);
-
msr = mfmsr ();
mtmsr (msr & ~(MSR_EE)); /* disable interrupts */
@@ -320,7 +323,12 @@ static int ppc_440x_eth_init (struct eth_device *dev, bd_t * bis)
/* MAL Channel RESET */
/* 1st reset MAL channel */
/* Note: writing a 0 to a channel has no effect */
+#if defined(CONFIG_440EP) || defined(CONFIG_440GR)
+ mtdcr (maltxcarr, (MAL_TXRX_CASR >> (hw_p->devnum*2)));
+#else
mtdcr (maltxcarr, (MAL_TXRX_CASR >> hw_p->devnum));
+#endif
+
mtdcr (malrxcarr, (MAL_TXRX_CASR >> hw_p->devnum));
/* wait for reset */
@@ -354,7 +362,9 @@ static int ppc_440x_eth_init (struct eth_device *dev, bd_t * bis)
out32 (ZMII_FER, 0);
udelay (100);
-#if defined(CONFIG_440_GX)
+#if defined(CONFIG_440EP) || defined(CONFIG_440GR)
+ out32 (ZMII_FER, (ZMII_FER_RMII | ZMII_FER_MDI) << ZMII_FER_V (devnum));
+#elif defined(CONFIG_440GX)
ethgroup = ppc_440x_eth_setup_bridge(devnum, bis);
#else
if ((devnum == 0) || (devnum == 1)) {
@@ -365,8 +375,8 @@ static int ppc_440x_eth_init (struct eth_device *dev, bd_t * bis)
out32 (RGMII_FER, ((RGMII_FER_RGMII << RGMII_FER_V (2)) |
(RGMII_FER_RGMII << RGMII_FER_V (3))));
}
-
#endif
+
out32 (ZMII_SSR, ZMII_SSR_SP << ZMII_SSR_V(devnum));
__asm__ volatile ("eieio");
@@ -381,6 +391,7 @@ static int ppc_440x_eth_init (struct eth_device *dev, bd_t * bis)
failsafe--;
}
+#if defined(CONFIG_440GX)
/* Whack the M1 register */
mode_reg = 0x0;
mode_reg &= ~0x00000038;
@@ -395,7 +406,7 @@ static int ppc_440x_eth_init (struct eth_device *dev, bd_t * bis)
mode_reg |= EMAC_M1_OBCI_GT100;
out32 (EMAC_M1 + hw_p->hw_addr, mode_reg);
-
+#endif /* defined(CONFIG_440GX) */
/* wait for PHY to complete auto negotiation */
reg_short = 0;
@@ -407,7 +418,7 @@ static int ppc_440x_eth_init (struct eth_device *dev, bd_t * bis)
case 1:
reg = CONFIG_PHY1_ADDR;
break;
-#if defined (CONFIG_440_GX)
+#if defined (CONFIG_440GX)
case 2:
reg = CONFIG_PHY2_ADDR;
break;
@@ -422,6 +433,7 @@ static int ppc_440x_eth_init (struct eth_device *dev, bd_t * bis)
bis->bi_phynum[devnum] = reg;
+#ifndef CONFIG_NO_PHY_RESET
/*
* Reset the phy, only if its the first time through
* otherwise, just check the speeds & feeds
@@ -429,37 +441,42 @@ static int ppc_440x_eth_init (struct eth_device *dev, bd_t * bis)
if (hw_p->first_init == 0) {
miiphy_reset (reg);
-#if defined(CONFIG_440_GX)
+#if defined(CONFIG_440GX)
#if defined(CONFIG_CIS8201_PHY)
- /*
- * Cicada 8201 PHY needs to have an extended register whacked
- * for RGMII mode.
- */
- if ( ((devnum == 2) || (devnum ==3)) && (4 == ethgroup) ) {
- miiphy_write (reg, 23, 0x1200);
/*
- * Vitesse VSC8201/Cicada CIS8201 errata:
- * Interoperability problem with Intel 82547EI phys
- * This work around (provided by Vitesse) changes
- * the default timer convergence from 8ms to 12ms
+ * Cicada 8201 PHY needs to have an extended register whacked
+ * for RGMII mode.
*/
- miiphy_write (reg, 0x1f, 0x2a30);
- miiphy_write (reg, 0x08, 0x0200);
- miiphy_write (reg, 0x1f, 0x52b5);
- miiphy_write (reg, 0x02, 0x0004);
- miiphy_write (reg, 0x01, 0x0671);
- miiphy_write (reg, 0x00, 0x8fae);
- miiphy_write (reg, 0x1f, 0x2a30);
- miiphy_write (reg, 0x08, 0x0000);
- miiphy_write (reg, 0x1f, 0x0000);
- /* end Vitesse/Cicada errata */
- }
+ if ( ((devnum == 2) || (devnum ==3)) && (4 == ethgroup) ) {
+#if defined(CONFIG_CIS8201_SHORT_ETCH)
+ miiphy_write (reg, 23, 0x1300);
+#else
+ miiphy_write (reg, 23, 0x1000);
+#endif
+ /*
+ * Vitesse VSC8201/Cicada CIS8201 errata:
+ * Interoperability problem with Intel 82547EI phys
+ * This work around (provided by Vitesse) changes
+ * the default timer convergence from 8ms to 12ms
+ */
+ miiphy_write (reg, 0x1f, 0x2a30);
+ miiphy_write (reg, 0x08, 0x0200);
+ miiphy_write (reg, 0x1f, 0x52b5);
+ miiphy_write (reg, 0x02, 0x0004);
+ miiphy_write (reg, 0x01, 0x0671);
+ miiphy_write (reg, 0x00, 0x8fae);
+ miiphy_write (reg, 0x1f, 0x2a30);
+ miiphy_write (reg, 0x08, 0x0000);
+ miiphy_write (reg, 0x1f, 0x0000);
+ /* end Vitesse/Cicada errata */
+ }
#endif
#endif
/* Start/Restart autonegotiation */
phy_setup_aneg (reg);
udelay (1000);
}
+#endif /* CONFIG_NO_PHY_RESET */
miiphy_read (reg, PHY_BMSR, &reg_short);
@@ -499,13 +516,22 @@ static int ppc_440x_eth_init (struct eth_device *dev, bd_t * bis)
(int) speed, (duplex == HALF) ? "HALF" : "FULL");
}
+#if defined(CONFIG_440EP) || defined(CONFIG_440GR)
+ mfsdr(sdr_mfr, reg);
+ if (speed == 100) {
+ reg = (reg & ~SDR0_MFR_ZMII_MODE_MASK) | SDR0_MFR_ZMII_MODE_RMII_100M;
+ } else {
+ reg = (reg & ~SDR0_MFR_ZMII_MODE_MASK) | SDR0_MFR_ZMII_MODE_RMII_10M;
+ }
+ mtsdr(sdr_mfr, reg);
+#endif
+
/* Set ZMII/RGMII speed according to the phy link speed */
reg = in32 (ZMII_SSR);
if ( (speed == 100) || (speed == 1000) )
out32 (ZMII_SSR, reg | (ZMII_SSR_SP << ZMII_SSR_V (devnum)));
else
- out32 (ZMII_SSR,
- reg & (~(ZMII_SSR_SP << ZMII_SSR_V (devnum))));
+ out32 (ZMII_SSR, reg & (~(ZMII_SSR_SP << ZMII_SSR_V (devnum))));
if ((devnum == 2) || (devnum == 3)) {
if (speed == 1000)
@@ -519,14 +545,16 @@ static int ppc_440x_eth_init (struct eth_device *dev, bd_t * bis)
}
/* set the Mal configuration reg */
+#if defined(CONFIG_440GX)
+ mtdcr (malmcr, MAL_CR_PLBB | MAL_CR_OPBBL | MAL_CR_LEA |
+ MAL_CR_PLBLT_DEFAULT | MAL_CR_EOPIE | 0x00330000);
+#else
+ mtdcr (malmcr, MAL_CR_PLBB | MAL_CR_OPBBL | MAL_CR_LEA | MAL_CR_PLBLT_DEFAULT);
/* Errata 1.12: MAL_1 -- Disable MAL bursting */
- if (get_pvr () == PVR_440GP_RB)
- mtdcr (malmcr,
- MAL_CR_OPBBL | MAL_CR_LEA | MAL_CR_PLBLT_DEFAULT);
- else
- mtdcr (malmcr,
- MAL_CR_PLBB | MAL_CR_OPBBL | MAL_CR_LEA |
- MAL_CR_PLBLT_DEFAULT | MAL_CR_EOPIE | 0x00330000);
+ if (get_pvr() == PVR_440GP_RB) {
+ mtdcr (malmcr, mfdcr(malmcr) & ~MAL_CR_PLBB);
+ }
+#endif
/* Free "old" buffers */
if (hw_p->alloc_tx_buf)
@@ -543,6 +571,8 @@ static int ppc_440x_eth_init (struct eth_device *dev, bd_t * bis)
hw_p->alloc_tx_buf =
(mal_desc_t *) malloc ((sizeof (mal_desc_t) * NUM_TX_BUFF) +
((2 * CFG_CACHELINE_SIZE) - 2));
+ if (NULL == hw_p->alloc_tx_buf)
+ return -1;
if (((int) hw_p->alloc_tx_buf & CACHELINE_MASK) != 0) {
hw_p->tx =
(mal_desc_t *) ((int) hw_p->alloc_tx_buf +
@@ -556,6 +586,12 @@ static int ppc_440x_eth_init (struct eth_device *dev, bd_t * bis)
hw_p->alloc_rx_buf =
(mal_desc_t *) malloc ((sizeof (mal_desc_t) * NUM_RX_BUFF) +
((2 * CFG_CACHELINE_SIZE) - 2));
+ if (NULL == hw_p->alloc_rx_buf) {
+ free(hw_p->alloc_tx_buf);
+ hw_p->alloc_tx_buf = NULL;
+ return -1;
+ }
+
if (((int) hw_p->alloc_rx_buf & CACHELINE_MASK) != 0) {
hw_p->rx =
(mal_desc_t *) ((int) hw_p->alloc_rx_buf +
@@ -569,9 +605,20 @@ static int ppc_440x_eth_init (struct eth_device *dev, bd_t * bis)
for (i = 0; i < NUM_TX_BUFF; i++) {
hw_p->tx[i].ctrl = 0;
hw_p->tx[i].data_len = 0;
- if (hw_p->first_init == 0)
+ if (hw_p->first_init == 0) {
hw_p->txbuf_ptr =
(char *) malloc (ENET_MAX_MTU_ALIGNED);
+ if (NULL == hw_p->txbuf_ptr) {
+ free(hw_p->alloc_rx_buf);
+ free(hw_p->alloc_tx_buf);
+ hw_p->alloc_rx_buf = NULL;
+ hw_p->alloc_tx_buf = NULL;
+ for(j = 0; j < i; j++) {
+ free(hw_p->tx[i].data_ptr);
+ hw_p->tx[i].data_ptr = NULL;
+ }
+ }
+ }
hw_p->tx[i].data_ptr = hw_p->txbuf_ptr;
if ((NUM_TX_BUFF - 1) == i)
hw_p->tx[i].ctrl |= MAL_TX_CTRL_WRAP;
@@ -618,14 +665,18 @@ static int ppc_440x_eth_init (struct eth_device *dev, bd_t * bis)
switch (devnum) {
case 1:
/* setup MAL tx & rx channel pointers */
- mtdcr (maltxbattr, 0x0);
+#if defined (CONFIG_440EP) || defined (CONFIG_440GR)
+ mtdcr (maltxctp2r, hw_p->tx);
+#else
mtdcr (maltxctp1r, hw_p->tx);
+#endif
+ mtdcr (maltxbattr, 0x0);
mtdcr (malrxbattr, 0x0);
mtdcr (malrxctp1r, hw_p->rx);
/* set RX buffer size */
mtdcr (malrcbs1, ENET_MAX_MTU_ALIGNED / 16);
break;
-#if defined (CONFIG_440_GX)
+#if defined (CONFIG_440GX)
case 2:
/* setup MAL tx & rx channel pointers */
mtdcr (maltxbattr, 0x0);
@@ -644,7 +695,7 @@ static int ppc_440x_eth_init (struct eth_device *dev, bd_t * bis)
/* set RX buffer size */
mtdcr (malrcbs3, ENET_MAX_MTU_ALIGNED / 16);
break;
-#endif /*CONFIG_440_GX */
+#endif /* CONFIG_440GX */
case 0:
default:
/* setup MAL tx & rx channel pointers */
@@ -658,7 +709,11 @@ static int ppc_440x_eth_init (struct eth_device *dev, bd_t * bis)
}
/* Enable MAL transmit and receive channels */
+#if defined(CONFIG_440EP) || defined(CONFIG_440GR)
+ mtdcr (maltxcasr, (MAL_TXRX_CASR >> (hw_p->devnum*2)));
+#else
mtdcr (maltxcasr, (MAL_TXRX_CASR >> hw_p->devnum));
+#endif
mtdcr (malrxcasr, (MAL_TXRX_CASR >> hw_p->devnum));
/* set transmit enable & receive enable */
@@ -804,7 +859,7 @@ int enetInt (struct eth_device *dev)
unsigned long mal_rx_eob;
unsigned long my_uic0msr, my_uic1msr;
-#if defined(CONFIG_440_GX)
+#if defined(CONFIG_440GX)
unsigned long my_uic2msr;
#endif
EMAC_440GX_HW_PST hw_p;
@@ -824,7 +879,7 @@ int enetInt (struct eth_device *dev)
my_uic0msr = mfdcr (uic0msr);
my_uic1msr = mfdcr (uic1msr);
-#if defined(CONFIG_440_GX)
+#if defined(CONFIG_440GX)
my_uic2msr = mfdcr (uic2msr);
#endif
if (!(my_uic0msr & (UIC_MRE | UIC_MTE))
@@ -834,7 +889,7 @@ int enetInt (struct eth_device *dev)
/* not for us */
return (rc);
}
-#if defined (CONFIG_440_GX)
+#if defined (CONFIG_440GX)
if (!(my_uic0msr & (UIC_MRE | UIC_MTE))
&& !(my_uic2msr & (UIC_ETH2 | UIC_ETH3))) {
/* not for us */
@@ -890,7 +945,7 @@ int enetInt (struct eth_device *dev)
return (rc); /* we had errors so get out */
}
}
-#if defined (CONFIG_440_GX)
+#if defined (CONFIG_440GX)
if (hw_p->devnum == 2) {
if (UIC_ETH2 & my_uic2msr) { /* look for EMAC errors */
emac_isr = in32 (EMAC_ISR + hw_p->hw_addr);
@@ -926,7 +981,7 @@ int enetInt (struct eth_device *dev)
return (rc); /* we had errors so get out */
}
}
-#endif /* CONFIG_440_GX */
+#endif /* CONFIG_440GX */
/* handle MAX TX EOB interrupt from a tx */
if (my_uic0msr & UIC_MTE) {
mal_rx_eob = mfdcr (maltxeobisr);
@@ -955,14 +1010,14 @@ int enetInt (struct eth_device *dev)
case 1:
mtdcr (uic1sr, UIC_ETH1);
break;
-#if defined (CONFIG_440_GX)
+#if defined (CONFIG_440GX)
case 2:
mtdcr (uic2sr, UIC_ETH2);
break;
case 3:
mtdcr (uic2sr, UIC_ETH3);
break;
-#endif /* CONFIG_440_GX */
+#endif /* CONFIG_440GX */
default:
break;
}
@@ -1148,19 +1203,24 @@ static int ppc_440x_eth_rx (struct eth_device *dev)
int ppc_440x_eth_initialize (bd_t * bis)
{
static int virgin = 0;
- unsigned long pfc1;
struct eth_device *dev;
int eth_num = 0;
-
EMAC_440GX_HW_PST hw = NULL;
+#if defined(CONFIG_440GX)
+ unsigned long pfc1;
+
mfsdr (sdr_pfc1, pfc1);
pfc1 &= ~(0x01e00000);
pfc1 |= 0x01200000;
mtsdr (sdr_pfc1, pfc1);
+#endif
/* set phy num and mode */
bis->bi_phynum[0] = CONFIG_PHY_ADDR;
+#if defined(CONFIG_PHY1_ADDR)
bis->bi_phynum[1] = CONFIG_PHY1_ADDR;
+#endif
+#if defined(CONFIG_440GX)
bis->bi_phynum[2] = CONFIG_PHY2_ADDR;
bis->bi_phynum[3] = CONFIG_PHY3_ADDR;
bis->bi_phymode[0] = 0;
@@ -1168,9 +1228,10 @@ int ppc_440x_eth_initialize (bd_t * bis)
bis->bi_phymode[2] = 2;
bis->bi_phymode[3] = 2;
-#if defined (CONFIG_440_GX)
+#if defined (CONFIG_440GX)
ppc_440x_eth_setup_bridge(0, bis);
#endif
+#endif
for (eth_num = 0; eth_num < EMAC_NUM_DEV; eth_num++) {
@@ -1256,6 +1317,7 @@ int ppc_440x_eth_initialize (bd_t * bis)
}
hw->devnum = eth_num;
+ hw->print_speed = 1;
sprintf (dev->name, "ppc_440x_eth%d", eth_num);
dev->priv = (void *) hw;