Fix autonegotiation in tsec ethernet driver
authorStefan Roese <sr@denx.de>
Wed, 21 Sep 2005 16:20:22 +0000 (18:20 +0200)
committerStefan Roese <sr@denx.de>
Wed, 21 Sep 2005 16:20:22 +0000 (18:20 +0200)
Patch by Stefan Roese, 21 Sep 2005

drivers/tsec.c
drivers/tsec.h
include/configs/TQM8540.h
include/configs/TQM8560.h

index 0c8b0de58778942b663883fd7366bc948d70fa6e..ddca901856651b9b933d6da6f987fcac58dfff5c 100644 (file)
@@ -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;
index 15961d73d55390fb6ae6ccfcb37b5b78d0b575f8..c26fcc0e732fe656a9d000bc4339d928490fe085 100644 (file)
@@ -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
index 1f54383629ee712706acb86b953e6692dcc545c8..a44135fda223b2f02382776eaaff6fc88c492338 100644 (file)
                                CFG_CMD_DATE    | \
                                CFG_CMD_EEPROM  | \
                                CFG_CMD_DTT     | \
+                               CFG_CMD_MII     | \
                                CFG_CMD_PING    )
 #include <cmd_confdefs.h>
 
index f8e3be98dff1909f7d7afd734b097e78e1019a53..780b11552310da14c0aaa9a41cb64db54cffdaef 100644 (file)
@@ -48,6 +48,7 @@
  * please disable the PCI support for now. sr@denx.de, 15-09-2005
  */
 #define CONFIG_PCI
+#undef CONFIG_PCI /* test-only !!!!!!!!!!!!!!!! */
 #define CONFIG_TSEC_ENET               /* tsec ethernet support */
 #undef CONFIG_DDR_ECC                  /* only for ECC DDR module */
 #define CONFIG_DDR_DLL                 /* possible DLL fix needed */
                                CFG_CMD_DATE    | \
                                CFG_CMD_EEPROM  | \
                                CFG_CMD_DTT     | \
+                               CFG_CMD_MII     | \
                                CFG_CMD_PING    )
 #include <cmd_confdefs.h>