diff options
author | Stefan Roese <sr@denx.de> | 2005-09-21 18:20:22 +0200 |
---|---|---|
committer | Stefan Roese <sr@denx.de> | 2005-09-21 18:20:22 +0200 |
commit | 5810dc3a2e4f5f9075f4a1818317b41e552843e5 (patch) | |
tree | a4f29c8c820a92c507efa054d2a26907c17646e9 /drivers/tsec.c | |
parent | 1806c75959c5a207b1b43885da818b2b77f31ac8 (diff) |
Fix autonegotiation in tsec ethernet driver
Patch by Stefan Roese, 21 Sep 2005
Diffstat (limited to 'drivers/tsec.c')
-rw-r--r-- | drivers/tsec.c | 66 |
1 files changed, 56 insertions, 10 deletions
diff --git a/drivers/tsec.c b/drivers/tsec.c index 0c8b0de587..ddca901856 100644 --- a/drivers/tsec.c +++ b/drivers/tsec.c @@ -338,16 +338,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; - - if(mii_reg & MIIM_STATUS_LINK) - priv->link = 1; - else - priv->link = 0; + /* + * 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; + + 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 +379,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 +973,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; |