net: phy: dp83822: use BMCR_ANENABLE instead of BMSR_ANEGCAPABLE for DP83620
authorAlvaro Gamez Machado <alvaro.gamez@hazent.com>
Fri, 8 Jun 2018 10:23:39 +0000 (12:23 +0200)
committerDavid S. Miller <davem@davemloft.net>
Sun, 10 Jun 2018 19:38:03 +0000 (12:38 -0700)
DP83620 register set is compatible with the DP83848, but it also supports
100base-FX. When the hardware is configured such as that fiber mode is
enabled, autonegotiation is not possible.

The chip, however, doesn't expose this information via BMSR_ANEGCAPABLE.
Instead, this bit is always set high, even if the particular hardware
configuration makes it so that auto negotiation is not possible [1]. Under
these circumstances, the phy subsystem keeps trying for autonegotiation to
happen, without success.

Hereby, we inspect BMCR_ANENABLE bit after genphy_config_init, which on
reset is set to 0 when auto negotiation is disabled, and so we use this
value instead of BMSR_ANEGCAPABLE.

[1] https://e2e.ti.com/support/interface/ethernet/f/903/p/697165/2571170

Signed-off-by: Alvaro Gamez Machado <alvaro.gamez@hazent.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/phy/dp83848.c

index cd09c3af21179fb14af0925f252d308897519cab..6e8e42361fd5406e7d345bd9aefbc00e950f2cc5 100644 (file)
@@ -74,6 +74,25 @@ static int dp83848_config_intr(struct phy_device *phydev)
        return phy_write(phydev, DP83848_MICR, control);
 }
 
+static int dp83848_config_init(struct phy_device *phydev)
+{
+       int err;
+       int val;
+
+       err = genphy_config_init(phydev);
+       if (err < 0)
+               return err;
+
+       /* DP83620 always reports Auto Negotiation Ability on BMSR. Instead,
+        * we check initial value of BMCR Auto negotiation enable bit
+        */
+       val = phy_read(phydev, MII_BMCR);
+       if (!(val & BMCR_ANENABLE))
+               phydev->autoneg = AUTONEG_DISABLE;
+
+       return 0;
+}
+
 static struct mdio_device_id __maybe_unused dp83848_tbl[] = {
        { TI_DP83848C_PHY_ID, 0xfffffff0 },
        { NS_DP83848C_PHY_ID, 0xfffffff0 },
@@ -83,7 +102,7 @@ static struct mdio_device_id __maybe_unused dp83848_tbl[] = {
 };
 MODULE_DEVICE_TABLE(mdio, dp83848_tbl);
 
-#define DP83848_PHY_DRIVER(_id, _name)                         \
+#define DP83848_PHY_DRIVER(_id, _name, _config_init)           \
        {                                                       \
                .phy_id         = _id,                          \
                .phy_id_mask    = 0xfffffff0,                   \
@@ -92,7 +111,7 @@ MODULE_DEVICE_TABLE(mdio, dp83848_tbl);
                .flags          = PHY_HAS_INTERRUPT,            \
                                                                \
                .soft_reset     = genphy_soft_reset,            \
-               .config_init    = genphy_config_init,           \
+               .config_init    = _config_init,                 \
                .suspend        = genphy_suspend,               \
                .resume         = genphy_resume,                \
                                                                \
@@ -102,10 +121,14 @@ MODULE_DEVICE_TABLE(mdio, dp83848_tbl);
        }
 
 static struct phy_driver dp83848_driver[] = {
-       DP83848_PHY_DRIVER(TI_DP83848C_PHY_ID, "TI DP83848C 10/100 Mbps PHY"),
-       DP83848_PHY_DRIVER(NS_DP83848C_PHY_ID, "NS DP83848C 10/100 Mbps PHY"),
-       DP83848_PHY_DRIVER(TI_DP83620_PHY_ID, "TI DP83620 10/100 Mbps PHY"),
-       DP83848_PHY_DRIVER(TLK10X_PHY_ID, "TI TLK10X 10/100 Mbps PHY"),
+       DP83848_PHY_DRIVER(TI_DP83848C_PHY_ID, "TI DP83848C 10/100 Mbps PHY",
+                          genphy_config_init),
+       DP83848_PHY_DRIVER(NS_DP83848C_PHY_ID, "NS DP83848C 10/100 Mbps PHY",
+                          genphy_config_init),
+       DP83848_PHY_DRIVER(TI_DP83620_PHY_ID, "TI DP83620 10/100 Mbps PHY",
+                          dp83848_config_init),
+       DP83848_PHY_DRIVER(TLK10X_PHY_ID, "TI TLK10X 10/100 Mbps PHY",
+                          genphy_config_init),
 };
 module_phy_driver(dp83848_driver);