diff options
author | Heiner Kallweit <hkallweit1@gmail.com> | 2019-03-27 23:58:44 +0300 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2019-04-02 23:09:55 +0300 |
commit | 045925e3fe5b98e402337a176d154252c56cef2e (patch) | |
tree | 6597b18b92201126a5795cba6b372a320d6c5d2e | |
parent | 6d670497e01803b486aa72cc1a718401ab986896 (diff) | |
download | linux-045925e3fe5b98e402337a176d154252c56cef2e.tar.xz |
net: phy: add genphy_read_abilities
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>
-rw-r--r-- | drivers/net/phy/phy_device.c | 48 | ||||
-rw-r--r-- | include/linux/phy.h | 1 |
2 files changed, 49 insertions, 0 deletions
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index de2b6333e7ea..0af66f32d363 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -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. diff --git a/include/linux/phy.h b/include/linux/phy.h index 34084892a466..ad88f063e50f 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -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); |