diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/tsec.c | 66 | ||||
-rw-r--r-- | drivers/tsec.h | 5 |
2 files changed, 61 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; diff --git a/drivers/tsec.h b/drivers/tsec.h index 15961d73d5..c26fcc0e73 100644 --- a/drivers/tsec.h +++ b/drivers/tsec.h @@ -40,6 +40,8 @@ #define TSEC_TIMEOUT 1000 #define TOUT_LOOP 1000000 +#define PHY_AUTONEGOTIATE_TIMEOUT 5000 /* in ms */ + /* MAC register bits */ #define MACCFG1_SOFT_RESET 0x80000000 #define MACCFG1_RESET_RX_MC 0x00080000 @@ -77,6 +79,7 @@ #define MIIM_CONTROL 0x00 #define MIIM_CONTROL_RESET 0x00009140 #define MIIM_CONTROL_INIT 0x00001140 +#define MIIM_CONTROL_RESTART 0x00001340 #define MIIM_ANEN 0x00001000 #define MIIM_CR 0x00 @@ -86,6 +89,8 @@ #define MIIM_STATUS 0x1 #define MIIM_STATUS_AN_DONE 0x00000020 #define MIIM_STATUS_LINK 0x0004 +#define PHY_BMSR_AUTN_ABLE 0x0008 +#define PHY_BMSR_AUTN_COMP 0x0020 #define MIIM_PHYIR1 0x2 #define MIIM_PHYIR2 0x3 |