]> git.ipfire.org Git - people/ms/u-boot.git/blobdiff - drivers/net/phy/phy.c
net: phy: ensure Gigabit features are masked off if requested
[people/ms/u-boot.git] / drivers / net / phy / phy.c
index ef9f13bd46f4523d4abf846f0c3488b76d68e9fd..aac9aa33f839a47e9bce9ed2492f1b4886ef0f2b 100644 (file)
@@ -38,16 +38,16 @@ DECLARE_GLOBAL_DATA_PTR;
 static int genphy_config_advert(struct phy_device *phydev)
 {
        u32 advertise;
-       int oldadv, adv;
+       int oldadv, adv, bmsr;
        int err, changed = 0;
 
-       /* Only allow advertising what
-        * this PHY supports */
+       /* Only allow advertising what this PHY supports */
        phydev->advertising &= phydev->supported;
        advertise = phydev->advertising;
 
        /* Setup standard advertisement */
-       oldadv = adv = phy_read(phydev, MDIO_DEVAD_NONE, MII_ADVERTISE);
+       adv = phy_read(phydev, MDIO_DEVAD_NONE, MII_ADVERTISE);
+       oldadv = adv;
 
        if (adv < 0)
                return adv;
@@ -79,29 +79,40 @@ static int genphy_config_advert(struct phy_device *phydev)
                changed = 1;
        }
 
+       bmsr = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMSR);
+       if (bmsr < 0)
+               return bmsr;
+
+       /* Per 802.3-2008, Section 22.2.4.2.16 Extended status all
+        * 1000Mbits/sec capable PHYs shall have the BMSR_ESTATEN bit set to a
+        * logical 1.
+        */
+       if (!(bmsr & BMSR_ESTATEN))
+               return changed;
+
        /* Configure gigabit if it's supported */
-       if (phydev->supported & (SUPPORTED_1000baseT_Half |
-                               SUPPORTED_1000baseT_Full)) {
-               oldadv = adv = phy_read(phydev, MDIO_DEVAD_NONE, MII_CTRL1000);
+       adv = phy_read(phydev, MDIO_DEVAD_NONE, MII_CTRL1000);
+       oldadv = adv;
+
+       if (adv < 0)
+               return adv;
 
-               if (adv < 0)
-                       return adv;
+       adv &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
 
-               adv &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
+       if (phydev->supported & (SUPPORTED_1000baseT_Half |
+                               SUPPORTED_1000baseT_Full)) {
                if (advertise & SUPPORTED_1000baseT_Half)
                        adv |= ADVERTISE_1000HALF;
                if (advertise & SUPPORTED_1000baseT_Full)
                        adv |= ADVERTISE_1000FULL;
+       }
 
-               if (adv != oldadv) {
-                       err = phy_write(phydev, MDIO_DEVAD_NONE, MII_CTRL1000,
-                                       adv);
+       if (adv != oldadv)
+               changed = 1;
 
-                       if (err < 0)
-                               return err;
-                       changed = 1;
-               }
-       }
+       err = phy_write(phydev, MDIO_DEVAD_NONE, MII_CTRL1000, adv);
+       if (err < 0)
+               return err;
 
        return changed;
 }