net: phy: add genphy_read_abilities
authorHeiner Kallweit <hkallweit1@gmail.com>
Wed, 27 Mar 2019 20:58:44 +0000 (21:58 +0100)
committerDavid S. Miller <davem@davemloft.net>
Tue, 2 Apr 2019 20:09:55 +0000 (13:09 -0700)
Similar to genphy_c45_pma_read_abilities() add a function to dynamically
detect the abilities of a Clause 22 PHY. This is mainly copied from
genphy_config_init().

Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/phy/phy_device.c
include/linux/phy.h

index de2b6333e7ea548f54330031bbe776164668d1f8..0af66f32d36390725a3aa89f5c65f802d64a41e9 100644 (file)
@@ -1880,6 +1880,54 @@ int genphy_config_init(struct phy_device *phydev)
 }
 EXPORT_SYMBOL(genphy_config_init);
 
+/**
+ * genphy_read_abilities - read PHY abilities from Clause 22 registers
+ * @phydev: target phy_device struct
+ *
+ * Description: Reads the PHY's abilities and populates
+ * phydev->supported accordingly.
+ *
+ * Returns: 0 on success, < 0 on failure
+ */
+int genphy_read_abilities(struct phy_device *phydev)
+{
+       int val;
+
+       linkmode_set_bit_array(phy_basic_ports_array,
+                              ARRAY_SIZE(phy_basic_ports_array),
+                              phydev->supported);
+
+       val = phy_read(phydev, MII_BMSR);
+       if (val < 0)
+               return val;
+
+       linkmode_mod_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->supported,
+                        val & BMSR_ANEGCAPABLE);
+
+       linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, phydev->supported,
+                        val & BMSR_100FULL);
+       linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT, phydev->supported,
+                        val & BMSR_100HALF);
+       linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT, phydev->supported,
+                        val & BMSR_10FULL);
+       linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT, phydev->supported,
+                        val & BMSR_10HALF);
+
+       if (val & BMSR_ESTATEN) {
+               val = phy_read(phydev, MII_ESTATUS);
+               if (val < 0)
+                       return val;
+
+               linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
+                                phydev->supported, val & ESTATUS_1000_TFULL);
+               linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
+                                phydev->supported, val & ESTATUS_1000_THALF);
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(genphy_read_abilities);
+
 /* This is used for the phy device which doesn't support the MMD extended
  * register access, but it does have side effect when we are trying to access
  * the MMD register via indirect method.
index 34084892a466d6350984b69d07bd39cc9ecdb938..ad88f063e50f473616833a427f6211415923dc73 100644 (file)
@@ -1075,6 +1075,7 @@ void phy_attached_info(struct phy_device *phydev);
 
 /* Clause 22 PHY */
 int genphy_config_init(struct phy_device *phydev);
+int genphy_read_abilities(struct phy_device *phydev);
 int genphy_setup_forced(struct phy_device *phydev);
 int genphy_restart_aneg(struct phy_device *phydev);
 int genphy_config_eee_advert(struct phy_device *phydev);