This adds support for the integrated 2.5Gbps PHY in Realtek RTL8125. Advertisement of 2.5Gbps mode is done via a vendor-specific register. Same applies to reading NBase-T link partner advertisement. Unfortunately this 2.5Gbps PHY shares the PHY ID with the integrated 1Gbps PHY's in other Realtek network chips and so far no method is known to differentiate them. This means we can't autodetect 2.5Gbps support and the network driver has to add 2.5Gbps to the supported and advertised modes.
Signed-off-by: Heiner Kallweit <hkallwe...@gmail.com> --- drivers/net/phy/realtek.c | 48 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c index a669945eb..35c981476 100644 --- a/drivers/net/phy/realtek.c +++ b/drivers/net/phy/realtek.c @@ -39,6 +39,11 @@ #define RTL8366RB_POWER_SAVE 0x15 #define RTL8366RB_POWER_SAVE_ON BIT(12) +#define RTL_ADV_2500FULL BIT(7) +#define RTL_LPADV_10000FULL BIT(11) +#define RTL_LPADV_5000FULL BIT(6) +#define RTL_LPADV_2500FULL BIT(5) + MODULE_DESCRIPTION("Realtek PHY driver"); MODULE_AUTHOR("Johnson Leung"); MODULE_LICENSE("GPL"); @@ -256,6 +261,47 @@ static int rtl8366rb_config_init(struct phy_device *phydev) return ret; } +static int rtlgen_config_aneg(struct phy_device *phydev) +{ + int ret = 0; + + if (linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, + phydev->supported) && phydev->autoneg == AUTONEG_ENABLE) { + u16 adv2500 = 0; + + if (linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, + phydev->advertising)) + adv2500 = RTL_ADV_2500FULL; + + ret = phy_modify_paged_changed(phydev, 0xa5d, 0x12, + RTL_ADV_2500FULL, adv2500); + if (ret < 0) + return ret; + } + + return __genphy_config_aneg(phydev, ret); +} + +static int rtlgen_read_status(struct phy_device *phydev) +{ + if (linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, + phydev->supported) && phydev->autoneg == AUTONEG_ENABLE) { + int lpadv = phy_read_paged(phydev, 0xa5d, 0x13); + + if (lpadv < 0) + return lpadv; + + linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT, + phydev->lp_advertising, lpadv & RTL_LPADV_10000FULL); + linkmode_mod_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT, + phydev->lp_advertising, lpadv & RTL_LPADV_5000FULL); + linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, + phydev->lp_advertising, lpadv & RTL_LPADV_2500FULL); + } + + return genphy_read_status(phydev); +} + static struct phy_driver realtek_drvs[] = { { PHY_ID_MATCH_EXACT(0x00008201), @@ -328,6 +374,8 @@ static struct phy_driver realtek_drvs[] = { }, { PHY_ID_MATCH_EXACT(0x001cc800), .name = "Generic Realtek PHY", + .config_aneg = rtlgen_config_aneg, + .read_status = rtlgen_read_status, .suspend = genphy_suspend, .resume = genphy_resume, .read_page = rtl821x_read_page, -- 2.22.0