diff options
Diffstat (limited to 'cpu/ppc4xx/440gx_enet.c')
| -rw-r--r-- | cpu/ppc4xx/440gx_enet.c | 174 | 
1 files changed, 104 insertions, 70 deletions
| diff --git a/cpu/ppc4xx/440gx_enet.c b/cpu/ppc4xx/440gx_enet.c index ba7418a97..91cf240ac 100644 --- a/cpu/ppc4xx/440gx_enet.c +++ b/cpu/ppc4xx/440gx_enet.c @@ -175,6 +175,100 @@ static void ppc_440x_eth_halt (struct eth_device *dev)  extern int phy_setup_aneg (unsigned char addr);  extern int miiphy_reset (unsigned char addr); +#if defined (CONFIG_440_GX) +int ppc_440x_eth_setup_bridge(int devnum, bd_t * bis) +{ +	unsigned long pfc1; +	unsigned long zmiifer; +	unsigned long rmiifer; + +	mfsdr(sdr_pfc1, pfc1); +	pfc1 = SDR0_PFC1_EPS_DECODE(pfc1); + +	zmiifer = 0; +	rmiifer = 0; + +	switch (pfc1) { +	case 1: +		zmiifer |= ZMII_FER_RMII << ZMII_FER_V(0); +		zmiifer |= ZMII_FER_RMII << ZMII_FER_V(1); +		zmiifer |= ZMII_FER_RMII << ZMII_FER_V(2); +		zmiifer |= ZMII_FER_RMII << ZMII_FER_V(3); +		bis->bi_phymode[0] = BI_PHYMODE_ZMII; +		bis->bi_phymode[1] = BI_PHYMODE_ZMII; +		bis->bi_phymode[2] = BI_PHYMODE_ZMII; +		bis->bi_phymode[3] = BI_PHYMODE_ZMII; +		break; +	case 2: +		zmiifer = ZMII_FER_SMII << ZMII_FER_V(0); +		zmiifer = ZMII_FER_SMII << ZMII_FER_V(1); +		zmiifer = ZMII_FER_SMII << ZMII_FER_V(2); +		zmiifer = ZMII_FER_SMII << ZMII_FER_V(3); +		bis->bi_phymode[0] = BI_PHYMODE_ZMII; +		bis->bi_phymode[1] = BI_PHYMODE_ZMII; +		bis->bi_phymode[2] = BI_PHYMODE_ZMII; +		bis->bi_phymode[3] = BI_PHYMODE_ZMII; +		break; +	case 3: +		zmiifer |= ZMII_FER_RMII << ZMII_FER_V(0); +		rmiifer |= RGMII_FER_RGMII << RGMII_FER_V(2); +		bis->bi_phymode[0] = BI_PHYMODE_ZMII; +		bis->bi_phymode[1] = BI_PHYMODE_NONE; +		bis->bi_phymode[2] = BI_PHYMODE_RGMII; +		bis->bi_phymode[3] = BI_PHYMODE_NONE; +		break; +	case 4: +		zmiifer |= ZMII_FER_SMII << ZMII_FER_V(0); +		zmiifer |= ZMII_FER_SMII << ZMII_FER_V(1); +		rmiifer |= RGMII_FER_RGMII << RGMII_FER_V (2); +		rmiifer |= RGMII_FER_RGMII << RGMII_FER_V (3); +		bis->bi_phymode[0] = BI_PHYMODE_ZMII; +		bis->bi_phymode[1] = BI_PHYMODE_ZMII; +		bis->bi_phymode[2] = BI_PHYMODE_RGMII; +		bis->bi_phymode[3] = BI_PHYMODE_RGMII; +		break; +	case 5: +		zmiifer |= ZMII_FER_SMII << ZMII_FER_V (0); +		zmiifer |= ZMII_FER_SMII << ZMII_FER_V (1); +		zmiifer |= ZMII_FER_SMII << ZMII_FER_V (2); +		rmiifer |= RGMII_FER_RGMII << RGMII_FER_V(3); +		bis->bi_phymode[0] = BI_PHYMODE_ZMII; +		bis->bi_phymode[1] = BI_PHYMODE_ZMII; +		bis->bi_phymode[2] = BI_PHYMODE_ZMII; +		bis->bi_phymode[3] = BI_PHYMODE_RGMII; +		break; +	case 6: +		zmiifer |= ZMII_FER_SMII << ZMII_FER_V (0); +		zmiifer |= ZMII_FER_SMII << ZMII_FER_V (1); +		rmiifer |= RGMII_FER_RGMII << RGMII_FER_V(2); +		rmiifer |= RGMII_FER_RGMII << RGMII_FER_V(3); +		bis->bi_phymode[0] = BI_PHYMODE_ZMII; +		bis->bi_phymode[1] = BI_PHYMODE_ZMII; +		bis->bi_phymode[2] = BI_PHYMODE_RGMII; +		bis->bi_phymode[3] = BI_PHYMODE_RGMII; +		break; +	case 0: +	default: +		zmiifer = ZMII_FER_MII << ZMII_FER_V(devnum); +		rmiifer = 0x0; +		bis->bi_phymode[0] = BI_PHYMODE_ZMII; +		bis->bi_phymode[1] = BI_PHYMODE_ZMII; +		bis->bi_phymode[2] = BI_PHYMODE_ZMII; +		bis->bi_phymode[3] = BI_PHYMODE_ZMII; +		break; +	} + +	/* Ensure we setup mdio for this devnum and ONLY this devnum */ +	zmiifer |= (ZMII_FER_MDI) << ZMII_FER_V(devnum); + +	out32 (ZMII_FER, zmiifer); +	out32 (RGMII_FER, rmiifer); + +	return ((int)pfc1); + +} +#endif +  static int ppc_440x_eth_init (struct eth_device *dev, bd_t * bis)  {  	int i; @@ -187,11 +281,7 @@ 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 +	int ethgroup;  	EMAC_440GX_HW_PST hw_p = dev->priv; @@ -269,66 +359,7 @@ static int ppc_440x_eth_init (struct eth_device *dev, bd_t * bis)  	udelay (100);  #if defined(CONFIG_440_GX) -	mfsdr(sdr_pfc1, pfc1); -	pfc1 = SDR0_PFC1_EPS_DECODE(pfc1); - -	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); +	ethgroup = ppc_440x_eth_setup_bridge(devnum, bis);  #else  	if ((devnum == 0) || (devnum == 1)) {  		out32 (ZMII_FER, (ZMII_FER_SMII | ZMII_FER_MDI) << ZMII_FER_V (devnum)); @@ -338,6 +369,7 @@ 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"); @@ -397,16 +429,17 @@ static int ppc_440x_eth_init (struct eth_device *dev, bd_t * bis)  	/* Reset the phy */  	miiphy_reset (reg); +#if defined(CONFIG_440_GX)  #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) ) { +	if ( ((devnum == 2) || (devnum ==3)) && (4 == ethgroup) ) {  		miiphy_write (reg, 23, 0x1200);  	}  #endif - +#endif  	/* Start/Restart autonegotiation */  	phy_setup_aneg (reg);  	udelay (1000); @@ -451,7 +484,7 @@ static int ppc_440x_eth_init (struct eth_device *dev, bd_t * bis)  	/* Set ZMII/RGMII speed according to the phy link speed */  	reg = in32 (ZMII_SSR); -	if (speed == 100) +	if ( (speed == 100) || (speed == 1000) )  		out32 (ZMII_SSR, reg | (ZMII_SSR_SP << ZMII_SSR_V (devnum)));  	else  		out32 (ZMII_SSR, @@ -619,8 +652,9 @@ static int ppc_440x_eth_init (struct eth_device *dev, bd_t * bis)  	mode_reg |= EMAC_M1_RFS_4K | EMAC_M1_TX_FIFO_2K;  	/* set speed */ -	/* TBS: do 1GbE */ -	if (speed == _100BASET) +	if (speed == _1000BASET) +		mode_reg = mode_reg | EMAC_M1_MF_1000MBPS | EMAC_M1_IST; +	else if (speed == _100BASET)  		mode_reg = mode_reg | EMAC_M1_MF_100MBPS | EMAC_M1_IST;  	else  		mode_reg = mode_reg & ~0x00C00000;	/* 10 MBPS */ |