* Patch by Travis Sawyer, 01 Mar 2004:

Ocotea:
  - Add IBM PPC440GX Ref Platform support (Ocotea)
    Original code by Paul Reynolds <PaulReynolds@lhsolutions.com>
    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
This commit is contained in:
wdenk
2004-03-14 00:07:33 +00:00
parent c40b295682
commit 0e6d798cb3
17 changed files with 2467 additions and 101 deletions

View File

@@ -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, &reg_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)) {

View File

@@ -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;