From: Daniel Golle Date: Sat, 22 Apr 2023 00:52:04 +0000 (+0100) Subject: kernel: net: phy: realtek: improve RealTek 2.5G PHY driver X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=998b9731577dedc7747dcfa412e4543dabaaa131;p=openwrt%2Fstaging%2Fnbd.git kernel: net: phy: realtek: improve RealTek 2.5G PHY driver * use interface mode switching only when operating in C45 mode Linux prevents switching the interface mode when using C22 MDIO, hence use rate-adapter mode in case the PHY controlled via C22. * use phy_read_paged where appropriate * use existing generic inline functions to handle 10GbE advertisements instead of redundantly defining register macros in realtek.c which are not actually vendor-specific. * make sure 10GbE advertisement is valid, preventing false-positive warning "Downshift occurred from negotiated speed 2.5Gbps to actual speed 1Gbps, check cabling!" with some link-partners using 1G mode. * Support Link Down Power Saving Mode (ALDPS) Signed-off-by: Daniel Golle --- diff --git a/target/linux/generic/pending-5.15/721-net-phy-realtek-rtl8221-allow-to-configure-SERDES-mo.patch b/target/linux/generic/pending-5.15/721-net-phy-realtek-rtl8221-allow-to-configure-SERDES-mo.patch index 703a0b8b72..c93fe42273 100644 --- a/target/linux/generic/pending-5.15/721-net-phy-realtek-rtl8221-allow-to-configure-SERDES-mo.patch +++ b/target/linux/generic/pending-5.15/721-net-phy-realtek-rtl8221-allow-to-configure-SERDES-mo.patch @@ -39,7 +39,7 @@ Signed-off-by: Alexander Couzens #define RTL8366RB_POWER_SAVE 0x15 #define RTL8366RB_POWER_SAVE_ON BIT(12) -@@ -841,6 +850,43 @@ static irqreturn_t rtl9000a_handle_inter +@@ -841,6 +850,48 @@ static irqreturn_t rtl9000a_handle_inter return IRQ_HANDLED; } @@ -48,8 +48,13 @@ Signed-off-by: Alexander Couzens + u16 option_mode; + + switch (phydev->interface) { -+ case PHY_INTERFACE_MODE_SGMII: + case PHY_INTERFACE_MODE_2500BASEX: ++ if (!phydev->is_c45) { ++ option_mode = RTL8221B_SERDES_OPTION_MODE_2500BASEX; ++ break; ++ } ++ fallthrough; ++ case PHY_INTERFACE_MODE_SGMII: + option_mode = RTL8221B_SERDES_OPTION_MODE_2500BASEX_SGMII; + break; + default: @@ -57,24 +62,24 @@ Signed-off-by: Alexander Couzens + } + + phy_write_mmd(phydev, RTL8221B_MMD_SERDES_CTRL, -+ 0x75f3, 0); ++ 0x75f3, 0); + + phy_modify_mmd_changed(phydev, RTL8221B_MMD_SERDES_CTRL, + RTL8221B_SERDES_OPTION, + RTL8221B_SERDES_OPTION_MODE_MASK, option_mode); + switch (option_mode) { -+ case RTL8221B_SERDES_OPTION_MODE_2500BASEX_SGMII: -+ case RTL8221B_SERDES_OPTION_MODE_2500BASEX: -+ phy_write_mmd(phydev, RTL8221B_MMD_SERDES_CTRL, 0x6a04, 0x0503); -+ phy_write_mmd(phydev, RTL8221B_MMD_SERDES_CTRL, 0x6f10, 0xd455); -+ phy_write_mmd(phydev, RTL8221B_MMD_SERDES_CTRL, 0x6f11, 0x8020); -+ break; -+ case RTL8221B_SERDES_OPTION_MODE_HISGMII_SGMII: -+ case RTL8221B_SERDES_OPTION_MODE_HISGMII: -+ phy_write_mmd(phydev, RTL8221B_MMD_SERDES_CTRL, 0x6a04, 0x0503); -+ phy_write_mmd(phydev, RTL8221B_MMD_SERDES_CTRL, 0x6f10, 0xd433); -+ phy_write_mmd(phydev, RTL8221B_MMD_SERDES_CTRL, 0x6f11, 0x8020); -+ break; ++ case RTL8221B_SERDES_OPTION_MODE_2500BASEX_SGMII: ++ case RTL8221B_SERDES_OPTION_MODE_2500BASEX: ++ phy_write_mmd(phydev, RTL8221B_MMD_SERDES_CTRL, 0x6a04, 0x0503); ++ phy_write_mmd(phydev, RTL8221B_MMD_SERDES_CTRL, 0x6f10, 0xd455); ++ phy_write_mmd(phydev, RTL8221B_MMD_SERDES_CTRL, 0x6f11, 0x8020); ++ break; ++ case RTL8221B_SERDES_OPTION_MODE_HISGMII_SGMII: ++ case RTL8221B_SERDES_OPTION_MODE_HISGMII: ++ phy_write_mmd(phydev, RTL8221B_MMD_SERDES_CTRL, 0x6a04, 0x0503); ++ phy_write_mmd(phydev, RTL8221B_MMD_SERDES_CTRL, 0x6f10, 0xd433); ++ phy_write_mmd(phydev, RTL8221B_MMD_SERDES_CTRL, 0x6f11, 0x8020); ++ break; + } + + return 0; @@ -83,19 +88,19 @@ Signed-off-by: Alexander Couzens static struct phy_driver realtek_drvs[] = { { PHY_ID_MATCH_EXACT(0x00008201), -@@ -981,6 +1027,7 @@ static struct phy_driver realtek_drvs[] +@@ -981,6 +1032,7 @@ static struct phy_driver realtek_drvs[] PHY_ID_MATCH_EXACT(0x001cc849), .name = "RTL8221B-VB-CG 2.5Gbps PHY", .get_features = rtl822x_get_features, -+ .config_init = rtl8221b_config_init, ++ .config_init = rtl8221b_config_init, .config_aneg = rtl822x_config_aneg, .read_status = rtl822x_read_status, .suspend = genphy_suspend, -@@ -992,6 +1039,7 @@ static struct phy_driver realtek_drvs[] +@@ -992,6 +1044,7 @@ static struct phy_driver realtek_drvs[] .name = "RTL8221B-VM-CG 2.5Gbps PHY", .get_features = rtl822x_get_features, .config_aneg = rtl822x_config_aneg, -+ .config_init = rtl8221b_config_init, ++ .config_init = rtl8221b_config_init, .read_status = rtl822x_read_status, .suspend = genphy_suspend, .resume = rtlgen_resume, diff --git a/target/linux/generic/pending-5.15/722-net-phy-realtek-support-switching-between-SGMII-and-.patch b/target/linux/generic/pending-5.15/722-net-phy-realtek-support-switching-between-SGMII-and-.patch index f4e87f52de..211a8ed297 100644 --- a/target/linux/generic/pending-5.15/722-net-phy-realtek-support-switching-between-SGMII-and-.patch +++ b/target/linux/generic/pending-5.15/722-net-phy-realtek-support-switching-between-SGMII-and-.patch @@ -52,7 +52,7 @@ Signed-off-by: Chukun Pan return ret; - return rtlgen_get_speed(phydev); -+ if (phydev->link) ++ if (phydev->is_c45 && phydev->link) + rtl822x_update_interface(phydev); + + return 0; diff --git a/target/linux/generic/pending-5.15/724-net-phy-realtek-use-genphy_soft_reset-for-2.5G-PHYs.patch b/target/linux/generic/pending-5.15/724-net-phy-realtek-use-genphy_soft_reset-for-2.5G-PHYs.patch index c803278835..6941818351 100644 --- a/target/linux/generic/pending-5.15/724-net-phy-realtek-use-genphy_soft_reset-for-2.5G-PHYs.patch +++ b/target/linux/generic/pending-5.15/724-net-phy-realtek-use-genphy_soft_reset-for-2.5G-PHYs.patch @@ -15,7 +15,7 @@ Signed-off-by: Daniel Golle --- a/drivers/net/phy/realtek.c +++ b/drivers/net/phy/realtek.c -@@ -1013,6 +1013,7 @@ static struct phy_driver realtek_drvs[] +@@ -1018,6 +1018,7 @@ static struct phy_driver realtek_drvs[] .write_page = rtl821x_write_page, .read_mmd = rtl822x_read_mmd, .write_mmd = rtl822x_write_mmd, @@ -23,7 +23,7 @@ Signed-off-by: Daniel Golle }, { PHY_ID_MATCH_EXACT(0x001cc840), .name = "RTL8226B_RTL8221B 2.5Gbps PHY", -@@ -1025,6 +1026,7 @@ static struct phy_driver realtek_drvs[] +@@ -1030,6 +1031,7 @@ static struct phy_driver realtek_drvs[] .write_page = rtl821x_write_page, .read_mmd = rtl822x_read_mmd, .write_mmd = rtl822x_write_mmd, @@ -31,7 +31,7 @@ Signed-off-by: Daniel Golle }, { PHY_ID_MATCH_EXACT(0x001cc838), .name = "RTL8226-CG 2.5Gbps PHY", -@@ -1035,6 +1037,7 @@ static struct phy_driver realtek_drvs[] +@@ -1040,6 +1042,7 @@ static struct phy_driver realtek_drvs[] .resume = rtlgen_resume, .read_page = rtl821x_read_page, .write_page = rtl821x_write_page, @@ -39,7 +39,7 @@ Signed-off-by: Daniel Golle }, { PHY_ID_MATCH_EXACT(0x001cc848), .name = "RTL8226B-CG_RTL8221B-CG 2.5Gbps PHY", -@@ -1045,6 +1048,7 @@ static struct phy_driver realtek_drvs[] +@@ -1050,6 +1053,7 @@ static struct phy_driver realtek_drvs[] .resume = rtlgen_resume, .read_page = rtl821x_read_page, .write_page = rtl821x_write_page, @@ -47,7 +47,7 @@ Signed-off-by: Daniel Golle }, { PHY_ID_MATCH_EXACT(0x001cc849), .name = "RTL8221B-VB-CG 2.5Gbps PHY", -@@ -1056,6 +1060,7 @@ static struct phy_driver realtek_drvs[] +@@ -1061,6 +1065,7 @@ static struct phy_driver realtek_drvs[] .resume = rtlgen_resume, .read_page = rtl821x_read_page, .write_page = rtl821x_write_page, @@ -55,7 +55,7 @@ Signed-off-by: Daniel Golle }, { PHY_ID_MATCH_EXACT(0x001cc84a), .name = "RTL8221B-VM-CG 2.5Gbps PHY", -@@ -1067,6 +1072,7 @@ static struct phy_driver realtek_drvs[] +@@ -1072,6 +1077,7 @@ static struct phy_driver realtek_drvs[] .resume = rtlgen_resume, .read_page = rtl821x_read_page, .write_page = rtl821x_write_page, diff --git a/target/linux/generic/pending-5.15/725-net-phy-realtek-disable-SGMII-in-band-AN-for-2-5G-PHYs.patch b/target/linux/generic/pending-5.15/725-net-phy-realtek-disable-SGMII-in-band-AN-for-2-5G-PHYs.patch index 7f2174e4d2..1370c6324b 100644 --- a/target/linux/generic/pending-5.15/725-net-phy-realtek-disable-SGMII-in-band-AN-for-2-5G-PHYs.patch +++ b/target/linux/generic/pending-5.15/725-net-phy-realtek-disable-SGMII-in-band-AN-for-2-5G-PHYs.patch @@ -26,17 +26,17 @@ Signed-off-by: Daniel Golle + int val; switch (phydev->interface) { - case PHY_INTERFACE_MODE_SGMII: -@@ -906,6 +907,13 @@ static int rtl8221b_config_init(struct p - break; + case PHY_INTERFACE_MODE_2500BASEX: +@@ -911,6 +912,13 @@ static int rtl8221b_config_init(struct p + break; } + /* Disable SGMII AN */ + phy_write_mmd(phydev, RTL8221B_MMD_SERDES_CTRL, 0x7588, 0x2); + phy_write_mmd(phydev, RTL8221B_MMD_SERDES_CTRL, 0x7589, 0x71d0); + phy_write_mmd(phydev, RTL8221B_MMD_SERDES_CTRL, 0x7587, 0x3); -+ phy_read_mmd_poll_timeout(phydev, RTL8221B_MMD_SERDES_CTRL, 0x7587, val, -+ !(val & BIT(0)), 500, 100000, false); ++ phy_read_mmd_poll_timeout(phydev, RTL8221B_MMD_SERDES_CTRL, 0x7587, ++ val, !(val & BIT(0)), 500, 100000, false); + return 0; } diff --git a/target/linux/generic/pending-5.15/726-net-phy-realtek-use-phy_read_paged-instead-of-open-c.patch b/target/linux/generic/pending-5.15/726-net-phy-realtek-use-phy_read_paged-instead-of-open-c.patch new file mode 100644 index 0000000000..250436ff39 --- /dev/null +++ b/target/linux/generic/pending-5.15/726-net-phy-realtek-use-phy_read_paged-instead-of-open-c.patch @@ -0,0 +1,27 @@ +From 934cdd67e7cf71f97a2a8aea2892e540af47dcdf Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Sat, 22 Apr 2023 01:21:14 +0100 +Subject: [PATCH 1/3] net: phy: realtek: use phy_read_paged instead of open + coding + +Instead of open coding a paged read, use the phy_read_paged function +in rtlgen_supports_2_5gbps. + +Signed-off-by: Daniel Golle +--- + drivers/net/phy/realtek.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +--- a/drivers/net/phy/realtek.c ++++ b/drivers/net/phy/realtek.c +@@ -727,9 +727,7 @@ static bool rtlgen_supports_2_5gbps(stru + { + int val; + +- phy_write(phydev, RTL821x_PAGE_SELECT, 0xa61); +- val = phy_read(phydev, 0x13); +- phy_write(phydev, RTL821x_PAGE_SELECT, 0); ++ val = phy_read_paged(phydev, 0xa61, 0x13); + + return val >= 0 && val & RTL_SUPPORTS_2500FULL; + } diff --git a/target/linux/generic/pending-5.15/727-net-phy-realtek-use-inline-functions-for-10GbE-adver.patch b/target/linux/generic/pending-5.15/727-net-phy-realtek-use-inline-functions-for-10GbE-adver.patch new file mode 100644 index 0000000000..a24b4dd79a --- /dev/null +++ b/target/linux/generic/pending-5.15/727-net-phy-realtek-use-inline-functions-for-10GbE-adver.patch @@ -0,0 +1,60 @@ +From 92c8b9d558160d94b981dd8a2b9c47657627ffdc Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Sat, 22 Apr 2023 01:23:08 +0100 +Subject: [PATCH 2/3] net: phy: realtek: use inline functions for 10GbE + advertisement + +Use existing generic inline functions to encode local advertisement +of 10GbE link modes as well as to decode link-partner advertisement. + +Signed-off-by: Daniel Golle +--- + drivers/net/phy/realtek.c | 22 +++++----------------- + 1 file changed, 5 insertions(+), 17 deletions(-) + +--- a/drivers/net/phy/realtek.c ++++ b/drivers/net/phy/realtek.c +@@ -68,10 +68,6 @@ + #define RTL_SUPPORTS_5000FULL BIT(14) + #define RTL_SUPPORTS_2500FULL BIT(13) + #define RTL_SUPPORTS_10000FULL BIT(0) +-#define RTL_ADV_2500FULL BIT(7) +-#define RTL_LPADV_10000FULL BIT(11) +-#define RTL_LPADV_5000FULL BIT(6) +-#define RTL_LPADV_2500FULL BIT(5) + + #define RTL9000A_GINMR 0x14 + #define RTL9000A_GINMR_LINK_STATUS BIT(4) +@@ -661,14 +657,11 @@ static int rtl822x_config_aneg(struct ph + int ret = 0; + + if (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); ++ MDIO_AN_10GBT_CTRL_ADV10G | ++ MDIO_AN_10GBT_CTRL_ADV5G | ++ MDIO_AN_10GBT_CTRL_ADV2_5G, ++ linkmode_adv_to_mii_10gbt_adv_t(phydev->advertising)); + if (ret < 0) + return ret; + } +@@ -705,12 +698,7 @@ static int rtl822x_read_status(struct ph + 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); ++ mii_10gbt_stat_mod_linkmode_lpa_t(phydev->lp_advertising, lpadv); + } + + ret = rtlgen_read_status(phydev); diff --git a/target/linux/generic/pending-5.15/728-net-phy-realtek-check-validity-of-10GbE-link-partner.patch b/target/linux/generic/pending-5.15/728-net-phy-realtek-check-validity-of-10GbE-link-partner.patch new file mode 100644 index 0000000000..084ee4b645 --- /dev/null +++ b/target/linux/generic/pending-5.15/728-net-phy-realtek-check-validity-of-10GbE-link-partner.patch @@ -0,0 +1,28 @@ +From 929bb4d3cfbc7878326c0771a01a636d49c54b40 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Sat, 22 Apr 2023 01:25:39 +0100 +Subject: [PATCH 3/3] net: phy: realtek: check validity of 10GbE link-partner + advertisement + +Only use link-partner advertisement bits for 10GbE modes if they are +actually valid. Check LOCALOK and REMOTEOK bits and clear 10GbE modes +unless both of them are set. + +Signed-off-by: Daniel Golle +--- + drivers/net/phy/realtek.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/net/phy/realtek.c ++++ b/drivers/net/phy/realtek.c +@@ -698,6 +698,10 @@ static int rtl822x_read_status(struct ph + if (lpadv < 0) + return lpadv; + ++ if (!(lpadv & MDIO_AN_10GBT_STAT_REMOK) || ++ !(lpadv & MDIO_AN_10GBT_STAT_LOCOK)) ++ lpadv = 0; ++ + mii_10gbt_stat_mod_linkmode_lpa_t(phydev->lp_advertising, lpadv); + } + diff --git a/target/linux/generic/pending-5.15/729-net-phy-realtek-introduce-rtl822x_probe.patch b/target/linux/generic/pending-5.15/729-net-phy-realtek-introduce-rtl822x_probe.patch new file mode 100644 index 0000000000..ae4a7dfa60 --- /dev/null +++ b/target/linux/generic/pending-5.15/729-net-phy-realtek-introduce-rtl822x_probe.patch @@ -0,0 +1,100 @@ +From 9155098547fb1172d4fa536f3f6bc9d42f59d08c Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Sat, 22 Apr 2023 03:26:01 +0100 +Subject: [PATCH] net: phy: realtek: setup ALDPS on RTL822x + +Setup Link Down Power Saving Mode according the DTS property +just like for RTL821x 1GE PHYs. + +Signed-off-by: Daniel Golle +--- + drivers/net/phy/realtek.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +--- a/drivers/net/phy/realtek.c ++++ b/drivers/net/phy/realtek.c +@@ -62,6 +62,10 @@ + #define RTL8221B_SERDES_OPTION_MODE_2500BASEX 2 + #define RTL8221B_SERDES_OPTION_MODE_HISGMII 3 + ++#define RTL8221B_PHYCR1 0xa430 ++#define RTL8221B_PHYCR1_ALDPS_EN BIT(2) ++#define RTL8221B_PHYCR1_ALDPS_XTAL_OFF_EN BIT(12) ++ + #define RTL8366RB_POWER_SAVE 0x15 + #define RTL8366RB_POWER_SAVE_ON BIT(12) + +@@ -736,6 +741,25 @@ static int rtl8226_match_phy_device(stru + rtlgen_supports_2_5gbps(phydev); + } + ++static int rtl822x_probe(struct phy_device *phydev) ++{ ++ struct device *dev = &phydev->mdio.dev; ++ int val; ++ ++ val = phy_read_mmd(phydev, RTL8221B_MMD_SERDES_CTRL, RTL8221B_PHYCR1); ++ if (val < 0) ++ return val; ++ ++ if (of_property_read_bool(dev->of_node, "realtek,aldps-enable")) ++ val |= RTL8221B_PHYCR1_ALDPS_EN | RTL8221B_PHYCR1_ALDPS_XTAL_OFF_EN; ++ else ++ val &= ~(RTL8221B_PHYCR1_ALDPS_EN | RTL8221B_PHYCR1_ALDPS_XTAL_OFF_EN); ++ ++ phy_write_mmd(phydev, RTL8221B_MMD_SERDES_CTRL, RTL8221B_PHYCR1, val); ++ ++ return 0; ++} ++ + static int rtlgen_resume(struct phy_device *phydev) + { + int ret = genphy_resume(phydev); +@@ -1009,6 +1030,7 @@ static struct phy_driver realtek_drvs[] + .match_phy_device = rtl8226_match_phy_device, + .get_features = rtl822x_get_features, + .config_aneg = rtl822x_config_aneg, ++ .probe = rtl822x_probe, + .read_status = rtl822x_read_status, + .suspend = genphy_suspend, + .resume = rtlgen_resume, +@@ -1022,6 +1044,7 @@ static struct phy_driver realtek_drvs[] + .name = "RTL8226B_RTL8221B 2.5Gbps PHY", + .get_features = rtl822x_get_features, + .config_aneg = rtl822x_config_aneg, ++ .probe = rtl822x_probe, + .read_status = rtl822x_read_status, + .suspend = genphy_suspend, + .resume = rtlgen_resume, +@@ -1035,6 +1058,7 @@ static struct phy_driver realtek_drvs[] + .name = "RTL8226-CG 2.5Gbps PHY", + .get_features = rtl822x_get_features, + .config_aneg = rtl822x_config_aneg, ++ .probe = rtl822x_probe, + .read_status = rtl822x_read_status, + .suspend = genphy_suspend, + .resume = rtlgen_resume, +@@ -1046,6 +1070,7 @@ static struct phy_driver realtek_drvs[] + .name = "RTL8226B-CG_RTL8221B-CG 2.5Gbps PHY", + .get_features = rtl822x_get_features, + .config_aneg = rtl822x_config_aneg, ++ .probe = rtl822x_probe, + .read_status = rtl822x_read_status, + .suspend = genphy_suspend, + .resume = rtlgen_resume, +@@ -1058,6 +1083,7 @@ static struct phy_driver realtek_drvs[] + .get_features = rtl822x_get_features, + .config_init = rtl8221b_config_init, + .config_aneg = rtl822x_config_aneg, ++ .probe = rtl822x_probe, + .read_status = rtl822x_read_status, + .suspend = genphy_suspend, + .resume = rtlgen_resume, +@@ -1070,6 +1096,7 @@ static struct phy_driver realtek_drvs[] + .get_features = rtl822x_get_features, + .config_aneg = rtl822x_config_aneg, + .config_init = rtl8221b_config_init, ++ .probe = rtl822x_probe, + .read_status = rtl822x_read_status, + .suspend = genphy_suspend, + .resume = rtlgen_resume,