summaryrefslogtreecommitdiff
path: root/drivers/tsec.c
diff options
context:
space:
mode:
authorStefan Roese <sr@denx.de>2005-09-21 18:20:22 +0200
committerStefan Roese <sr@denx.de>2005-09-21 18:20:22 +0200
commit5810dc3a2e4f5f9075f4a1818317b41e552843e5 (patch)
treea4f29c8c820a92c507efa054d2a26907c17646e9 /drivers/tsec.c
parent1806c75959c5a207b1b43885da818b2b77f31ac8 (diff)
downloadu-boot-imx-5810dc3a2e4f5f9075f4a1818317b41e552843e5.zip
u-boot-imx-5810dc3a2e4f5f9075f4a1818317b41e552843e5.tar.gz
u-boot-imx-5810dc3a2e4f5f9075f4a1818317b41e552843e5.tar.bz2
Fix autonegotiation in tsec ethernet driver
Patch by Stefan Roese, 21 Sep 2005
Diffstat (limited to 'drivers/tsec.c')
-rw-r--r--drivers/tsec.c66
1 files changed, 56 insertions, 10 deletions
diff --git a/drivers/tsec.c b/drivers/tsec.c
index 0c8b0de..ddca901 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;