diff options
Diffstat (limited to 'drivers/tsec.c')
| -rw-r--r-- | drivers/tsec.c | 92 | 
1 files changed, 76 insertions, 16 deletions
| diff --git a/drivers/tsec.c b/drivers/tsec.c index 0c8b0de58..f860dae8b 100644 --- a/drivers/tsec.c +++ b/drivers/tsec.c @@ -21,8 +21,9 @@  #if defined(CONFIG_TSEC_ENET)  #include "tsec.h" +#include "miiphy.h" -#define TX_BUF_CNT 2 +#define TX_BUF_CNT		2  static uint rxIdx;	/* index of the current RX buffer */  static uint txIdx;	/* index of the current TX buffer */ @@ -120,6 +121,10 @@ struct phy_info * get_phy_info(struct eth_device *dev);  void phy_run_commands(struct tsec_private *priv, struct phy_cmd *cmd);  static void adjust_link(struct eth_device *dev);  static void relocate_cmds(void); +static int tsec_miiphy_write(char *devname, unsigned char addr, +		unsigned char reg, unsigned short value); +static int tsec_miiphy_read(char *devname, unsigned char addr, +		unsigned char reg, unsigned short *value);  /* Initialize device structure. Returns success if PHY   * initialization succeeded (i.e. if it recognizes the PHY) @@ -169,6 +174,11 @@ int tsec_initialize(bd_t *bis, int index, char *devname)  	priv->regs->maccfg1 |= MACCFG1_SOFT_RESET;  	priv->regs->maccfg1 &= ~(MACCFG1_SOFT_RESET); +#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII) \ +	&& !defined(BITBANGMII) +	miiphy_register(dev->name, tsec_miiphy_read, tsec_miiphy_write); +#endif +  	/* Try to initialize PHY here, and return */  	return init_phy(dev);  } @@ -200,11 +210,11 @@ int tsec_init(struct eth_device* dev, bd_t * bd)  	for(i=0;i<MAC_ADDR_LEN;i++) {  		tmpbuf[MAC_ADDR_LEN - 1 - i] = dev->enetaddr[i];  	} -	(uint)(regs->macstnaddr1) = *((uint *)(tmpbuf)); +	regs->macstnaddr1 = *((uint *)(tmpbuf));  	tempval = *((uint *)(tmpbuf +4)); -	(uint)(regs->macstnaddr2) = tempval; +	regs->macstnaddr2 = tempval;  	/* reset the indices to zero */  	rxIdx = 0; @@ -338,16 +348,35 @@ uint mii_cr_init(uint mii_reg, struct tsec_private *priv)   * auto-negotiation */  uint mii_parse_sr(uint mii_reg, struct tsec_private *priv)  { -	uint timeout = TSEC_TIMEOUT; +	/* +	 * Wait if PHY is capable of autonegotiation and autonegotiation is not complete +	 */ +	mii_reg = read_phy_reg(priv, MIIM_STATUS); +	if ((mii_reg & PHY_BMSR_AUTN_ABLE) && !(mii_reg & PHY_BMSR_AUTN_COMP)) { +		int i = 0; -	if(mii_reg & MIIM_STATUS_LINK) -		priv->link = 1; -	else -		priv->link = 0; +		puts ("Waiting for PHY auto negotiation to complete"); +		while (!((mii_reg & PHY_BMSR_AUTN_COMP) && (mii_reg & MIIM_STATUS_LINK))) { +			/* +			 * Timeout reached ? +			 */ +			if (i > PHY_AUTONEGOTIATE_TIMEOUT) { +				puts (" TIMEOUT !\n"); +				priv->link = 0; +				break; +			} -	if(priv->link) { -		while((!(mii_reg & MIIM_STATUS_AN_DONE)) && timeout--) +			if ((i++ % 1000) == 0) { +				putc ('.'); +			} +			udelay (1000);	/* 1 ms */  			mii_reg = read_phy_reg(priv, MIIM_STATUS); +		} +		puts (" done\n"); +		priv->link = 1; +		udelay (500000);	/* another 500 ms (results in faster booting) */ +	} else { +		priv->link = 1;  	}  	return 0; @@ -360,6 +389,34 @@ uint mii_parse_88E1011_psr(uint mii_reg, struct tsec_private *priv)  {  	uint speed; +	mii_reg = read_phy_reg(priv, MIIM_88E1011_PHY_STATUS); + +	if (!((mii_reg & MIIM_88E1011_PHYSTAT_SPDDONE) && +	      (mii_reg & MIIM_88E1011_PHYSTAT_LINK))) { +		int i = 0; + +		puts ("Waiting for PHY realtime link"); +		while (!((mii_reg & MIIM_88E1011_PHYSTAT_SPDDONE) && +			 (mii_reg & MIIM_88E1011_PHYSTAT_LINK))) { +			/* +			 * Timeout reached ? +			 */ +			if (i > PHY_AUTONEGOTIATE_TIMEOUT) { +				puts (" TIMEOUT !\n"); +				priv->link = 0; +				break; +			} + +			if ((i++ % 1000) == 0) { +				putc ('.'); +			} +			udelay (1000);	/* 1 ms */ +			mii_reg = read_phy_reg(priv, MIIM_88E1011_PHY_STATUS); +		} +		puts (" done\n"); +		udelay (500000);	/* another 500 ms (results in faster booting) */ +	} +  	if(mii_reg & MIIM_88E1011_PHYSTAT_DUPLEX)  		priv->duplexity = 1;  	else @@ -926,8 +983,7 @@ struct phy_info * get_phy_info(struct eth_device *dev)  		printf("%s: PHY id %x is not supported!\n", dev->name, phy_ID);  		return NULL;  	} else { -		printf("%s: PHY is %s (%x)\n", dev->name, theInfo->name, -				phy_ID); +		debug("%s: PHY is %s (%x)\n", dev->name, theInfo->name, phy_ID);  	}  	return theInfo; @@ -1012,7 +1068,8 @@ static void relocate_cmds(void)  } -#ifndef CONFIG_BITBANGMII +#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII) \ +	&& !defined(BITBANGMII)  struct tsec_private * get_priv_for_phy(unsigned char phyaddr)  { @@ -1032,7 +1089,8 @@ struct tsec_private * get_priv_for_phy(unsigned char phyaddr)   * Returns:   *  0 on success   */ -int miiphy_read(unsigned char addr, unsigned char reg, unsigned short *value) +static int tsec_miiphy_read(char *devname, unsigned char addr, +		unsigned char reg, unsigned short *value)  {  	unsigned short ret;  	struct tsec_private *priv = get_priv_for_phy(addr); @@ -1054,7 +1112,8 @@ int miiphy_read(unsigned char addr, unsigned char reg, unsigned short *value)   * Returns:   *  0 on success   */ -int miiphy_write(unsigned char addr, unsigned char reg, unsigned short value) +static int tsec_miiphy_write(char *devname, unsigned char addr, +		unsigned char reg, unsigned short value)  {  	struct tsec_private *priv = get_priv_for_phy(addr); @@ -1068,6 +1127,7 @@ int miiphy_write(unsigned char addr, unsigned char reg, unsigned short value)  	return 0;  } -#endif /* CONFIG_BITBANGMII */ +#endif /* defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII) +		&& !defined(BITBANGMII) */  #endif /* CONFIG_TSEC_ENET */ |