From 50326b48f0cfbd9324668c5d2e08b39b59dc199f Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Mon, 5 Jan 2026 16:37:54 +0000 Subject: [PATCH 1/5] net: phy: realtek: fix whitespace in struct phy_driver initializers Consistently use tabs instead of spaces in struct phy_driver initializers. Signed-off-by: Daniel Golle Reviewed-by: Maxime Chevallier Link: https://patch.msgid.link/42b0fac53c5c5646707ce3f3a6dacd2bc082a5b2.1767630451.git.daniel@makrotopia.org Signed-off-by: Paolo Abeni --- drivers/net/phy/realtek/realtek_main.c | 146 ++++++++++++------------- 1 file changed, 73 insertions(+), 73 deletions(-) diff --git a/drivers/net/phy/realtek/realtek_main.c b/drivers/net/phy/realtek/realtek_main.c index 6ff0385201a5..e42c5efbfa5e 100644 --- a/drivers/net/phy/realtek/realtek_main.c +++ b/drivers/net/phy/realtek/realtek_main.c @@ -1976,7 +1976,7 @@ static irqreturn_t rtl8221b_handle_interrupt(struct phy_device *phydev) static struct phy_driver realtek_drvs[] = { { PHY_ID_MATCH_EXACT(0x00008201), - .name = "RTL8201CP Ethernet", + .name = "RTL8201CP Ethernet", .read_page = rtl821x_read_page, .write_page = rtl821x_write_page, }, { @@ -2102,7 +2102,7 @@ static struct phy_driver realtek_drvs[] = { .name = "RTL8226B_RTL8221B 2.5Gbps PHY", .get_features = rtl822x_get_features, .config_aneg = rtl822x_config_aneg, - .config_init = rtl822xb_config_init, + .config_init = rtl822xb_config_init, .get_rate_matching = rtl822xb_get_rate_matching, .read_status = rtl822xb_read_status, .suspend = genphy_suspend, @@ -2111,112 +2111,112 @@ static struct phy_driver realtek_drvs[] = { .write_page = rtl821x_write_page, }, { PHY_ID_MATCH_EXACT(0x001cc838), - .name = "RTL8226-CG 2.5Gbps PHY", - .soft_reset = rtl822x_c45_soft_reset, - .get_features = rtl822x_c45_get_features, - .config_aneg = rtl822x_c45_config_aneg, - .config_init = rtl822x_config_init, - .read_status = rtl822xb_c45_read_status, - .suspend = genphy_c45_pma_suspend, - .resume = rtlgen_c45_resume, + .name = "RTL8226-CG 2.5Gbps PHY", + .soft_reset = rtl822x_c45_soft_reset, + .get_features = rtl822x_c45_get_features, + .config_aneg = rtl822x_c45_config_aneg, + .config_init = rtl822x_config_init, + .read_status = rtl822xb_c45_read_status, + .suspend = genphy_c45_pma_suspend, + .resume = rtlgen_c45_resume, }, { PHY_ID_MATCH_EXACT(0x001cc848), - .name = "RTL8226B-CG_RTL8221B-CG 2.5Gbps PHY", - .get_features = rtl822x_get_features, - .config_aneg = rtl822x_config_aneg, - .config_init = rtl822xb_config_init, + .name = "RTL8226B-CG_RTL8221B-CG 2.5Gbps PHY", + .get_features = rtl822x_get_features, + .config_aneg = rtl822x_config_aneg, + .config_init = rtl822xb_config_init, .get_rate_matching = rtl822xb_get_rate_matching, - .read_status = rtl822xb_read_status, - .suspend = genphy_suspend, - .resume = rtlgen_resume, - .read_page = rtl821x_read_page, - .write_page = rtl821x_write_page, + .read_status = rtl822xb_read_status, + .suspend = genphy_suspend, + .resume = rtlgen_resume, + .read_page = rtl821x_read_page, + .write_page = rtl821x_write_page, }, { .match_phy_device = rtl8221b_vb_cg_c22_match_phy_device, - .name = "RTL8221B-VB-CG 2.5Gbps PHY (C22)", + .name = "RTL8221B-VB-CG 2.5Gbps PHY (C22)", .probe = rtl822x_probe, - .get_features = rtl822x_get_features, - .config_aneg = rtl822x_config_aneg, - .config_init = rtl822xb_config_init, + .get_features = rtl822x_get_features, + .config_aneg = rtl822x_config_aneg, + .config_init = rtl822xb_config_init, .get_rate_matching = rtl822xb_get_rate_matching, - .read_status = rtl822xb_read_status, - .suspend = genphy_suspend, - .resume = rtlgen_resume, - .read_page = rtl821x_read_page, - .write_page = rtl821x_write_page, + .read_status = rtl822xb_read_status, + .suspend = genphy_suspend, + .resume = rtlgen_resume, + .read_page = rtl821x_read_page, + .write_page = rtl821x_write_page, }, { .match_phy_device = rtl8221b_vb_cg_c45_match_phy_device, - .name = "RTL8221B-VB-CG 2.5Gbps PHY (C45)", + .name = "RTL8221B-VB-CG 2.5Gbps PHY (C45)", .config_intr = rtl8221b_config_intr, .handle_interrupt = rtl8221b_handle_interrupt, .probe = rtl822x_probe, - .config_init = rtl822xb_config_init, + .config_init = rtl822xb_config_init, .get_rate_matching = rtl822xb_get_rate_matching, - .get_features = rtl822x_c45_get_features, - .config_aneg = rtl822x_c45_config_aneg, - .read_status = rtl822xb_c45_read_status, - .suspend = genphy_c45_pma_suspend, - .resume = rtlgen_c45_resume, + .get_features = rtl822x_c45_get_features, + .config_aneg = rtl822x_c45_config_aneg, + .read_status = rtl822xb_c45_read_status, + .suspend = genphy_c45_pma_suspend, + .resume = rtlgen_c45_resume, }, { .match_phy_device = rtl8221b_vm_cg_c22_match_phy_device, - .name = "RTL8221B-VM-CG 2.5Gbps PHY (C22)", + .name = "RTL8221B-VM-CG 2.5Gbps PHY (C22)", .probe = rtl822x_probe, - .get_features = rtl822x_get_features, - .config_aneg = rtl822x_config_aneg, - .config_init = rtl822xb_config_init, + .get_features = rtl822x_get_features, + .config_aneg = rtl822x_config_aneg, + .config_init = rtl822xb_config_init, .get_rate_matching = rtl822xb_get_rate_matching, - .read_status = rtl822xb_read_status, - .suspend = genphy_suspend, - .resume = rtlgen_resume, - .read_page = rtl821x_read_page, - .write_page = rtl821x_write_page, + .read_status = rtl822xb_read_status, + .suspend = genphy_suspend, + .resume = rtlgen_resume, + .read_page = rtl821x_read_page, + .write_page = rtl821x_write_page, }, { .match_phy_device = rtl8221b_vm_cg_c45_match_phy_device, - .name = "RTL8221B-VM-CG 2.5Gbps PHY (C45)", + .name = "RTL8221B-VM-CG 2.5Gbps PHY (C45)", .config_intr = rtl8221b_config_intr, .handle_interrupt = rtl8221b_handle_interrupt, .probe = rtl822x_probe, - .config_init = rtl822xb_config_init, + .config_init = rtl822xb_config_init, .get_rate_matching = rtl822xb_get_rate_matching, - .get_features = rtl822x_c45_get_features, - .config_aneg = rtl822x_c45_config_aneg, - .read_status = rtl822xb_c45_read_status, - .suspend = genphy_c45_pma_suspend, - .resume = rtlgen_c45_resume, + .get_features = rtl822x_c45_get_features, + .config_aneg = rtl822x_c45_config_aneg, + .read_status = rtl822xb_c45_read_status, + .suspend = genphy_c45_pma_suspend, + .resume = rtlgen_c45_resume, }, { .match_phy_device = rtl8251b_c45_match_phy_device, - .name = "RTL8251B 5Gbps PHY", + .name = "RTL8251B 5Gbps PHY", .probe = rtl822x_probe, - .get_features = rtl822x_get_features, - .config_aneg = rtl822x_config_aneg, - .read_status = rtl822x_read_status, - .suspend = genphy_suspend, - .resume = rtlgen_resume, - .read_page = rtl821x_read_page, - .write_page = rtl821x_write_page, + .get_features = rtl822x_get_features, + .config_aneg = rtl822x_config_aneg, + .read_status = rtl822x_read_status, + .suspend = genphy_suspend, + .resume = rtlgen_resume, + .read_page = rtl821x_read_page, + .write_page = rtl821x_write_page, }, { .match_phy_device = rtl_internal_nbaset_match_phy_device, - .name = "Realtek Internal NBASE-T PHY", + .name = "Realtek Internal NBASE-T PHY", .flags = PHY_IS_INTERNAL, .probe = rtl822x_probe, - .get_features = rtl822x_get_features, - .config_aneg = rtl822x_config_aneg, - .read_status = rtl822x_read_status, - .suspend = genphy_suspend, - .resume = rtlgen_resume, - .read_page = rtl821x_read_page, - .write_page = rtl821x_write_page, + .get_features = rtl822x_get_features, + .config_aneg = rtl822x_config_aneg, + .read_status = rtl822x_read_status, + .suspend = genphy_suspend, + .resume = rtlgen_resume, + .read_page = rtl821x_read_page, + .write_page = rtl821x_write_page, .read_mmd = rtl822x_read_mmd, .write_mmd = rtl822x_write_mmd, }, { PHY_ID_MATCH_EXACT(0x001ccad0), .name = "RTL8224 2.5Gbps PHY", .flags = PHY_POLL_CABLE_TEST, - .get_features = rtl822x_c45_get_features, - .config_aneg = rtl822x_c45_config_aneg, - .read_status = rtl822x_c45_read_status, - .suspend = genphy_c45_pma_suspend, - .resume = rtlgen_c45_resume, + .get_features = rtl822x_c45_get_features, + .config_aneg = rtl822x_c45_config_aneg, + .read_status = rtl822x_c45_read_status, + .suspend = genphy_c45_pma_suspend, + .resume = rtlgen_c45_resume, .cable_test_start = rtl8224_cable_test_start, .cable_test_get_status = rtl8224_cable_test_get_status, }, { @@ -2235,7 +2235,7 @@ static struct phy_driver realtek_drvs[] = { }, { PHY_ID_MATCH_EXACT(0x001ccb00), .name = "RTL9000AA_RTL9000AN Ethernet", - .features = PHY_BASIC_T1_FEATURES, + .features = PHY_BASIC_T1_FEATURES, .config_init = rtl9000a_config_init, .config_aneg = rtl9000a_config_aneg, .read_status = rtl9000a_read_status, From 10fbd71fc5f9bef5018a35103d493307683ddca1 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Mon, 5 Jan 2026 16:38:12 +0000 Subject: [PATCH 2/5] net: phy: realtek: implement configuring in-band an Implement the inband_caps() and config_inband() PHY driver methods to allow configuring the use of in-band-status with SGMII and 2500Base-X on RTL8226 and RTL8221B 2.5GE PHYs. Signed-off-by: Daniel Golle Link: https://patch.msgid.link/82a78a06d67be19e856d646cf880b2021ea9d837.1767630451.git.daniel@makrotopia.org Signed-off-by: Paolo Abeni --- drivers/net/phy/realtek/realtek_main.c | 67 ++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/drivers/net/phy/realtek/realtek_main.c b/drivers/net/phy/realtek/realtek_main.c index e42c5efbfa5e..0653a9d8fcb6 100644 --- a/drivers/net/phy/realtek/realtek_main.c +++ b/drivers/net/phy/realtek/realtek_main.c @@ -131,6 +131,15 @@ #define RTL822X_VND1_SERDES_CTRL3_MODE_SGMII 0x02 #define RTL822X_VND1_SERDES_CTRL3_MODE_2500BASEX 0x16 +#define RTL822X_VND1_SERDES_CMD 0x7587 +#define RTL822X_VND1_SERDES_CMD_WRITE BIT(1) +#define RTL822X_VND1_SERDES_CMD_BUSY BIT(0) +#define RTL822X_VND1_SERDES_ADDR 0x7588 +#define RTL822X_VND1_SERDES_ADDR_AUTONEG 0x2 +#define RTL822X_VND1_SERDES_INBAND_DISABLE 0x71d0 +#define RTL822X_VND1_SERDES_INBAND_ENABLE 0x70d0 +#define RTL822X_VND1_SERDES_DATA 0x7589 + /* RTL822X_VND2_XXXXX registers are only accessible when phydev->is_c45 * is set, they cannot be accessed by C45-over-C22. */ @@ -1308,6 +1317,50 @@ static int rtl822xb_config_init(struct phy_device *phydev) return rtl822x_set_serdes_option_mode(phydev, false); } +static int rtl822x_serdes_write(struct phy_device *phydev, u16 reg, u16 val) +{ + int ret, poll; + + ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, RTL822X_VND1_SERDES_ADDR, reg); + if (ret < 0) + return ret; + + ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, RTL822X_VND1_SERDES_DATA, val); + if (ret < 0) + return ret; + + ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, RTL822X_VND1_SERDES_CMD, + RTL822X_VND1_SERDES_CMD_WRITE | + RTL822X_VND1_SERDES_CMD_BUSY); + if (ret < 0) + return ret; + + return phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1, + RTL822X_VND1_SERDES_CMD, poll, + !(poll & RTL822X_VND1_SERDES_CMD_BUSY), + 500, 100000, false); +} + +static int rtl822x_config_inband(struct phy_device *phydev, unsigned int modes) +{ + return rtl822x_serdes_write(phydev, RTL822X_VND1_SERDES_ADDR_AUTONEG, + (modes != LINK_INBAND_DISABLE) ? + RTL822X_VND1_SERDES_INBAND_ENABLE : + RTL822X_VND1_SERDES_INBAND_DISABLE); +} + +static unsigned int rtl822x_inband_caps(struct phy_device *phydev, + phy_interface_t interface) +{ + switch (interface) { + case PHY_INTERFACE_MODE_2500BASEX: + case PHY_INTERFACE_MODE_SGMII: + return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE; + default: + return 0; + } +} + static int rtl822xb_get_rate_matching(struct phy_device *phydev, phy_interface_t iface) { @@ -2103,6 +2156,8 @@ static struct phy_driver realtek_drvs[] = { .get_features = rtl822x_get_features, .config_aneg = rtl822x_config_aneg, .config_init = rtl822xb_config_init, + .inband_caps = rtl822x_inband_caps, + .config_inband = rtl822x_config_inband, .get_rate_matching = rtl822xb_get_rate_matching, .read_status = rtl822xb_read_status, .suspend = genphy_suspend, @@ -2116,6 +2171,8 @@ static struct phy_driver realtek_drvs[] = { .get_features = rtl822x_c45_get_features, .config_aneg = rtl822x_c45_config_aneg, .config_init = rtl822x_config_init, + .inband_caps = rtl822x_inband_caps, + .config_inband = rtl822x_config_inband, .read_status = rtl822xb_c45_read_status, .suspend = genphy_c45_pma_suspend, .resume = rtlgen_c45_resume, @@ -2125,6 +2182,8 @@ static struct phy_driver realtek_drvs[] = { .get_features = rtl822x_get_features, .config_aneg = rtl822x_config_aneg, .config_init = rtl822xb_config_init, + .inband_caps = rtl822x_inband_caps, + .config_inband = rtl822x_config_inband, .get_rate_matching = rtl822xb_get_rate_matching, .read_status = rtl822xb_read_status, .suspend = genphy_suspend, @@ -2138,6 +2197,8 @@ static struct phy_driver realtek_drvs[] = { .get_features = rtl822x_get_features, .config_aneg = rtl822x_config_aneg, .config_init = rtl822xb_config_init, + .inband_caps = rtl822x_inband_caps, + .config_inband = rtl822x_config_inband, .get_rate_matching = rtl822xb_get_rate_matching, .read_status = rtl822xb_read_status, .suspend = genphy_suspend, @@ -2151,6 +2212,8 @@ static struct phy_driver realtek_drvs[] = { .handle_interrupt = rtl8221b_handle_interrupt, .probe = rtl822x_probe, .config_init = rtl822xb_config_init, + .inband_caps = rtl822x_inband_caps, + .config_inband = rtl822x_config_inband, .get_rate_matching = rtl822xb_get_rate_matching, .get_features = rtl822x_c45_get_features, .config_aneg = rtl822x_c45_config_aneg, @@ -2164,6 +2227,8 @@ static struct phy_driver realtek_drvs[] = { .get_features = rtl822x_get_features, .config_aneg = rtl822x_config_aneg, .config_init = rtl822xb_config_init, + .inband_caps = rtl822x_inband_caps, + .config_inband = rtl822x_config_inband, .get_rate_matching = rtl822xb_get_rate_matching, .read_status = rtl822xb_read_status, .suspend = genphy_suspend, @@ -2177,6 +2242,8 @@ static struct phy_driver realtek_drvs[] = { .handle_interrupt = rtl8221b_handle_interrupt, .probe = rtl822x_probe, .config_init = rtl822xb_config_init, + .inband_caps = rtl822x_inband_caps, + .config_inband = rtl822x_config_inband, .get_rate_matching = rtl822xb_get_rate_matching, .get_features = rtl822x_c45_get_features, .config_aneg = rtl822x_c45_config_aneg, From 65de36f5eae1c540115bf8f705f853718e9b6451 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Mon, 5 Jan 2026 16:38:29 +0000 Subject: [PATCH 3/5] net: phy: move mmd_phy_read and mmd_phy_write to phylib.h Helper functions mmd_phy_read and mmd_phy_write are useful for PHYs which require custom MMD access functions for some but not all MMDs. Move mmd_phy_read and mmd_phy_write function prototypes from phylib-internal.h to phylib.h to make them available for PHY drivers. Signed-off-by: Daniel Golle Reviewed-by: Andrew Lunn Link: https://patch.msgid.link/79169cd624a3572d426e42c7b13cd2654a35d0cb.1767630451.git.daniel@makrotopia.org Signed-off-by: Paolo Abeni --- drivers/net/phy/phylib-internal.h | 6 ------ drivers/net/phy/phylib.h | 5 +++++ 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/net/phy/phylib-internal.h b/drivers/net/phy/phylib-internal.h index ebda74eb60a5..dc9592c6bb8e 100644 --- a/drivers/net/phy/phylib-internal.h +++ b/drivers/net/phy/phylib-internal.h @@ -7,7 +7,6 @@ #define __PHYLIB_INTERNAL_H struct phy_device; -struct mii_bus; /* * phy_supported_speeds - return all speeds currently supported by a PHY device @@ -21,11 +20,6 @@ void of_set_phy_timing_role(struct phy_device *phydev); int phy_speed_down_core(struct phy_device *phydev); void phy_check_downshift(struct phy_device *phydev); -int mmd_phy_read(struct mii_bus *bus, int phy_addr, bool is_c45, - int devad, u32 regnum); -int mmd_phy_write(struct mii_bus *bus, int phy_addr, bool is_c45, - int devad, u32 regnum, u16 val); - int genphy_c45_read_eee_adv(struct phy_device *phydev, unsigned long *adv); #endif /* __PHYLIB_INTERNAL_H */ diff --git a/drivers/net/phy/phylib.h b/drivers/net/phy/phylib.h index c15484a805b3..0fba245f9745 100644 --- a/drivers/net/phy/phylib.h +++ b/drivers/net/phy/phylib.h @@ -8,6 +8,7 @@ struct device_node; struct phy_device; +struct mii_bus; struct device_node *phy_package_get_node(struct phy_device *phydev); void *phy_package_get_priv(struct phy_device *phydev); @@ -30,5 +31,9 @@ int devm_phy_package_join(struct device *dev, struct phy_device *phydev, int base_addr, size_t priv_size); int devm_of_phy_package_join(struct device *dev, struct phy_device *phydev, size_t priv_size); +int mmd_phy_read(struct mii_bus *bus, int phy_addr, bool is_c45, + int devad, u32 regnum); +int mmd_phy_write(struct mii_bus *bus, int phy_addr, bool is_c45, + int devad, u32 regnum, u16 val); #endif /* __PHYLIB_H */ From 1850ec20d6e71218c02329e5975591075dc972d3 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Mon, 5 Jan 2026 16:38:59 +0000 Subject: [PATCH 4/5] net: phy: realtek: use paged access for MDIO_MMD_VEND2 in C22 mode RTL822x cannot access MDIO_MMD_VEND2 via MII_MMD_CTRL/MII_MMD_DATA. A mapping to use paged access needs to be used instead. All other MMD devices can be accessed as usual. Implement phy_read_mmd and phy_write_mmd using paged access for MDIO_MMD_VEND2 in Clause-22 mode instead of relying on MII_MMD_CTRL/MII_MMD_DATA. This allows eg. rtl822x_config_aneg to work as expected in case the MDIO bus doesn't support Clause-45 access. Suggested-by: Bevan Weiss Signed-off-by: Daniel Golle Reviewed-by: Maxime Chevallier Link: https://patch.msgid.link/25aab7f02dac7c6022171455523e3db1435b0881.1767630451.git.daniel@makrotopia.org Signed-off-by: Paolo Abeni --- drivers/net/phy/realtek/realtek_main.c | 91 +++++++++++++++++++++++++- 1 file changed, 88 insertions(+), 3 deletions(-) diff --git a/drivers/net/phy/realtek/realtek_main.c b/drivers/net/phy/realtek/realtek_main.c index 0653a9d8fcb6..d1c7935a13ac 100644 --- a/drivers/net/phy/realtek/realtek_main.c +++ b/drivers/net/phy/realtek/realtek_main.c @@ -18,6 +18,7 @@ #include #include +#include "../phylib.h" #include "realtek.h" #define RTL8201F_IER 0x13 @@ -140,9 +141,8 @@ #define RTL822X_VND1_SERDES_INBAND_ENABLE 0x70d0 #define RTL822X_VND1_SERDES_DATA 0x7589 -/* RTL822X_VND2_XXXXX registers are only accessible when phydev->is_c45 - * is set, they cannot be accessed by C45-over-C22. - */ +#define RTL822X_VND2_TO_PAGE(reg) ((reg) >> 4) +#define RTL822X_VND2_TO_PAGE_REG(reg) (16 + (((reg) & GENMASK(3, 0)) >> 1)) #define RTL822X_VND2_C22_REG(reg) (0xa400 + 2 * (reg)) #define RTL8221B_VND2_INER 0xa4d2 @@ -1247,6 +1247,79 @@ static int rtl822x_probe(struct phy_device *phydev) return 0; } +/* RTL822x cannot access MDIO_MMD_VEND2 via MII_MMD_CTRL/MII_MMD_DATA. + * A mapping to use paged access needs to be used instead. + * All other MMD devices can be accessed as usual. + */ +static int rtl822xb_read_mmd(struct phy_device *phydev, int devnum, u16 reg) +{ + int oldpage, ret, read_ret; + u16 page; + + /* Use default method for all MMDs except MDIO_MMD_VEND2 or in case + * Clause-45 access is available + */ + if (devnum != MDIO_MMD_VEND2 || phydev->is_c45) + return mmd_phy_read(phydev->mdio.bus, phydev->mdio.addr, + phydev->is_c45, devnum, reg); + + /* Use paged access for MDIO_MMD_VEND2 over Clause-22 */ + page = RTL822X_VND2_TO_PAGE(reg); + oldpage = __phy_read(phydev, RTL821x_PAGE_SELECT); + if (oldpage < 0) + return oldpage; + + if (oldpage != page) { + ret = __phy_write(phydev, RTL821x_PAGE_SELECT, page); + if (ret < 0) + return ret; + } + + read_ret = __phy_read(phydev, RTL822X_VND2_TO_PAGE_REG(reg)); + if (oldpage != page) { + ret = __phy_write(phydev, RTL821x_PAGE_SELECT, oldpage); + if (ret < 0) + return ret; + } + + return read_ret; +} + +static int rtl822xb_write_mmd(struct phy_device *phydev, int devnum, u16 reg, + u16 val) +{ + int oldpage, ret, write_ret; + u16 page; + + /* Use default method for all MMDs except MDIO_MMD_VEND2 or in case + * Clause-45 access is available + */ + if (devnum != MDIO_MMD_VEND2 || phydev->is_c45) + return mmd_phy_write(phydev->mdio.bus, phydev->mdio.addr, + phydev->is_c45, devnum, reg, val); + + /* Use paged access for MDIO_MMD_VEND2 over Clause-22 */ + page = RTL822X_VND2_TO_PAGE(reg); + oldpage = __phy_read(phydev, RTL821x_PAGE_SELECT); + if (oldpage < 0) + return oldpage; + + if (oldpage != page) { + ret = __phy_write(phydev, RTL821x_PAGE_SELECT, page); + if (ret < 0) + return ret; + } + + write_ret = __phy_write(phydev, RTL822X_VND2_TO_PAGE_REG(reg), val); + if (oldpage != page) { + ret = __phy_write(phydev, RTL821x_PAGE_SELECT, oldpage); + if (ret < 0) + return ret; + } + + return write_ret; +} + static int rtl822x_set_serdes_option_mode(struct phy_device *phydev, bool gen1) { bool has_2500, has_sgmii; @@ -2150,6 +2223,8 @@ static struct phy_driver realtek_drvs[] = { .resume = rtlgen_resume, .read_page = rtl821x_read_page, .write_page = rtl821x_write_page, + .read_mmd = rtl822xb_read_mmd, + .write_mmd = rtl822xb_write_mmd, }, { .match_phy_device = rtl8221b_match_phy_device, .name = "RTL8226B_RTL8221B 2.5Gbps PHY", @@ -2164,6 +2239,8 @@ static struct phy_driver realtek_drvs[] = { .resume = rtlgen_resume, .read_page = rtl821x_read_page, .write_page = rtl821x_write_page, + .read_mmd = rtl822xb_read_mmd, + .write_mmd = rtl822xb_write_mmd, }, { PHY_ID_MATCH_EXACT(0x001cc838), .name = "RTL8226-CG 2.5Gbps PHY", @@ -2176,6 +2253,8 @@ static struct phy_driver realtek_drvs[] = { .read_status = rtl822xb_c45_read_status, .suspend = genphy_c45_pma_suspend, .resume = rtlgen_c45_resume, + .read_mmd = rtl822xb_read_mmd, + .write_mmd = rtl822xb_write_mmd, }, { PHY_ID_MATCH_EXACT(0x001cc848), .name = "RTL8226B-CG_RTL8221B-CG 2.5Gbps PHY", @@ -2190,6 +2269,8 @@ static struct phy_driver realtek_drvs[] = { .resume = rtlgen_resume, .read_page = rtl821x_read_page, .write_page = rtl821x_write_page, + .read_mmd = rtl822xb_read_mmd, + .write_mmd = rtl822xb_write_mmd, }, { .match_phy_device = rtl8221b_vb_cg_c22_match_phy_device, .name = "RTL8221B-VB-CG 2.5Gbps PHY (C22)", @@ -2205,6 +2286,8 @@ static struct phy_driver realtek_drvs[] = { .resume = rtlgen_resume, .read_page = rtl821x_read_page, .write_page = rtl821x_write_page, + .read_mmd = rtl822xb_read_mmd, + .write_mmd = rtl822xb_write_mmd, }, { .match_phy_device = rtl8221b_vb_cg_c45_match_phy_device, .name = "RTL8221B-VB-CG 2.5Gbps PHY (C45)", @@ -2235,6 +2318,8 @@ static struct phy_driver realtek_drvs[] = { .resume = rtlgen_resume, .read_page = rtl821x_read_page, .write_page = rtl821x_write_page, + .read_mmd = rtl822xb_read_mmd, + .write_mmd = rtl822xb_write_mmd, }, { .match_phy_device = rtl8221b_vm_cg_c45_match_phy_device, .name = "RTL8221B-VM-CG 2.5Gbps PHY (C45)", From d8489935f5979b72e73de585037fe6fde7088bc3 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Mon, 5 Jan 2026 16:39:26 +0000 Subject: [PATCH 5/5] net: phy: realtek: get rid of magic number in rtlgen_read_status() Use newly introduced helper macros RTL822X_VND2_TO_PAGE and RTL822X_VND2_TO_PAGE_REG to access RTL_VEND2_PHYSR register over Clause-22 paged access instead of using magic numbers. Signed-off-by: Daniel Golle Reviewed-by: Maxime Chevallier Link: https://patch.msgid.link/a53d4577335fdda4d363db9bc4bf614fd3a56c9b.1767630451.git.daniel@makrotopia.org Signed-off-by: Paolo Abeni --- drivers/net/phy/realtek/realtek_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/phy/realtek/realtek_main.c b/drivers/net/phy/realtek/realtek_main.c index d1c7935a13ac..eb5b540ada0e 100644 --- a/drivers/net/phy/realtek/realtek_main.c +++ b/drivers/net/phy/realtek/realtek_main.c @@ -1154,7 +1154,8 @@ static int rtlgen_read_status(struct phy_device *phydev) if (!phydev->link) return 0; - val = phy_read_paged(phydev, 0xa43, 0x12); + val = phy_read_paged(phydev, RTL822X_VND2_TO_PAGE(RTL_VND2_PHYSR), + RTL822X_VND2_TO_PAGE_REG(RTL_VND2_PHYSR)); if (val < 0) return val;