From 0e6d798cb313580acd06ba01626687a557c5159f Mon Sep 17 00:00:00 2001 From: wdenk Date: Sun, 14 Mar 2004 00:07:33 +0000 Subject: * Patch by Travis Sawyer, 01 Mar 2004: Ocotea: - Add IBM PPC440GX Ref Platform support (Ocotea) Original code by Paul Reynolds Adapted to U-Boot and 440GX port 440gx_enet.c: - Add gracious handling of all Ethernet Pin Selections for 440GX - Add RGMII selection for Cicada CIS8201 Gigabit PHY ppc440.h: - Add needed bit definitions - Fix formatting * Patch by Carl Riechers, 1 Mar 2004: Add PPC440GX prbdv0 divider to fix memory clock calculation. * Patch by Stephan Linz, 27 Feb 2004 - avoid problems for targets without NFS download support --- cpu/ppc4xx/440gx_enet.c | 98 +++++++++++++++++++++++++++++++++++++++++++++---- cpu/ppc4xx/speed.c | 5 ++- 2 files changed, 93 insertions(+), 10 deletions(-) (limited to 'cpu') diff --git a/cpu/ppc4xx/440gx_enet.c b/cpu/ppc4xx/440gx_enet.c index c8259b1..ba7418a 100644 --- a/cpu/ppc4xx/440gx_enet.c +++ b/cpu/ppc4xx/440gx_enet.c @@ -187,6 +187,11 @@ 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_440_GX) + unsigned long pfc1; + unsigned long zmiifer; + unsigned long rmiifer; +#endif EMAC_440GX_HW_PST hw_p = dev->priv; @@ -262,17 +267,84 @@ static int ppc_440x_eth_init (struct eth_device *dev, bd_t * bis) reg = 0; out32 (ZMII_FER, 0); udelay (100); - out32 (ZMII_FER, ZMII_FER_MDI << ZMII_FER_V (devnum)); - out32 (ZMII_SSR, 0x11110000); - /* reset emac so we have access to the phy */ - __asm__ volatile ("eieio"); - out32 (EMAC_M0 + hw_p->hw_addr, EMAC_M0_SRST); - __asm__ volatile ("eieio"); +#if defined(CONFIG_440_GX) + mfsdr(sdr_pfc1, pfc1); + pfc1 = SDR0_PFC1_EPS_DECODE(pfc1); - if ((devnum == 2) || (devnum == 3)) + switch (pfc1) { + case 1: + zmiifer = (ZMII_FER_MDI | ZMII_FER_RMII) << ZMII_FER_V(devnum); + rmiifer = 0x0; + break; + case 2: + zmiifer = (ZMII_FER_MDI | ZMII_FER_SMII) << ZMII_FER_V(devnum); + rmiifer = 0x0; + break; + case 3: + if (devnum == 0) { + zmiifer = (ZMII_FER_MDI | ZMII_FER_RMII) << ZMII_FER_V(devnum); + rmiifer = 0x0; + } else if (devnum == 2) { + zmiifer = (ZMII_FER_MDI | ZMII_FER_RMII) << ZMII_FER_V(devnum); + rmiifer = RGMII_FER_RGMII << RGMII_FER_V(devnum); + } else { /* invalid case */ + zmiifer = 0x0; + rmiifer = 0x0; + } + break; + case 4: + if ((devnum == 0) || (devnum == 1)) { + zmiifer = (ZMII_FER_MDI | ZMII_FER_SMII) << ZMII_FER_V (devnum); + rmiifer = 0x0; + } else { /* ((devnum == 2) || (devnum == 3)) */ + zmiifer = (ZMII_FER_MDI/* | ZMII_FER_RMII */) << ZMII_FER_V (devnum); + rmiifer = RGMII_FER_RGMII << RGMII_FER_V (devnum); + } + break; + case 5: + if ((devnum == 0) || (devnum == 1) || (devnum == 2)) { + zmiifer = (ZMII_FER_MDI | ZMII_FER_SMII) << ZMII_FER_V (devnum); + rmiifer = 0x0; + } else { + zmiifer = (ZMII_FER_MDI | ZMII_FER_RMII) << ZMII_FER_V(devnum); + rmiifer = RGMII_FER_RGMII << RGMII_FER_V(devnum); + } + break; + case 6: + if ((devnum == 0) || (devnum == 1)) { + zmiifer = (ZMII_FER_MDI | ZMII_FER_SMII) << ZMII_FER_V (devnum); + rmiifer = 0x0; + } else { + zmiifer = (ZMII_FER_MDI | ZMII_FER_RMII) << ZMII_FER_V(devnum); + rmiifer = RGMII_FER_RGMII << RGMII_FER_V(devnum); + } + break; + case 0: + default: + zmiifer = (ZMII_FER_MDI | ZMII_FER_MII) << ZMII_FER_V(devnum); + rmiifer = 0x0; + break; + } + + out32 (ZMII_FER, zmiifer); + out32 (RGMII_FER, rmiifer); +#else + if ((devnum == 0) || (devnum == 1)) { + out32 (ZMII_FER, (ZMII_FER_SMII | ZMII_FER_MDI) << ZMII_FER_V (devnum)); + } + else { /* ((devnum == 2) || (devnum == 3)) */ + out32 (ZMII_FER, ZMII_FER_MDI << ZMII_FER_V (devnum)); 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"); + + /* reset emac so we have access to the phy */ + + out32 (EMAC_M0 + hw_p->hw_addr, EMAC_M0_SRST); __asm__ volatile ("eieio"); failsafe = 1000; @@ -325,6 +397,16 @@ static int ppc_440x_eth_init (struct eth_device *dev, bd_t * bis) /* Reset the phy */ miiphy_reset (reg); +#if defined(CONFIG_CIS8201_PHY) + /* + * Cicada 8201 PHY needs to have an extended register whacked + * for RGMII mode. + */ + if ( ((devnum == 2) || (devnum ==3)) && (4 == pfc1) ) { + miiphy_write (reg, 23, 0x1200); + } +#endif + /* Start/Restart autonegotiation */ phy_setup_aneg (reg); udelay (1000); @@ -332,7 +414,7 @@ static int ppc_440x_eth_init (struct eth_device *dev, bd_t * bis) miiphy_read (reg, PHY_BMSR, ®_short); /* - * Wait if PHY is able of autonegotiation and autonegotiation is not complete + * Wait if PHY is capable of autonegotiation and autonegotiation is not complete */ if ((reg_short & PHY_BMSR_AUTN_ABLE) && !(reg_short & PHY_BMSR_AUTN_COMP)) { diff --git a/cpu/ppc4xx/speed.c b/cpu/ppc4xx/speed.c index e776050..7172fe3 100644 --- a/cpu/ppc4xx/speed.c +++ b/cpu/ppc4xx/speed.c @@ -247,7 +247,7 @@ void get_sys_info (sys_info_t * sysInfo) unsigned long temp1; unsigned long lfdiv; unsigned long m; - + unsigned long prbdv0; /* Extract configured divisors */ mfsdr( sdr_sdstp0,strp0 ); @@ -263,6 +263,7 @@ void get_sys_info (sys_info_t * sysInfo) sysInfo->pllOpbDiv = temp ? temp : 4; temp = (strp1 & PLLSYS1_PERCLK_DIV_MASK) >> 24; sysInfo->pllExtBusDiv = temp ? temp : 4; + prbdv0 = (strp0 >> 2) & 0x7; /* Calculate 'M' based on feedback source */ temp = (strp0 & PLLSYS0_SEL_MASK) >> 27; @@ -284,7 +285,7 @@ void get_sys_info (sys_info_t * sysInfo) /* Now calculate the individual clocks */ sysInfo->freqVCOMhz = (m * CONFIG_SYS_CLK_FREQ) + (m>>1); sysInfo->freqProcessor = sysInfo->freqVCOMhz/sysInfo->pllFwdDivA; - sysInfo->freqPLB = sysInfo->freqVCOMhz/sysInfo->pllFwdDivB; + sysInfo->freqPLB = sysInfo->freqVCOMhz/sysInfo->pllFwdDivB/prbdv0; sysInfo->freqOPB = sysInfo->freqPLB/sysInfo->pllOpbDiv; sysInfo->freqEPB = sysInfo->freqOPB/sysInfo->pllExtBusDiv; -- cgit v1.1