summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Kicinski <kuba@kernel.org>2026-01-18 03:12:18 +0300
committerJakub Kicinski <kuba@kernel.org>2026-01-18 03:12:18 +0300
commitba4550d5d724b693b142812af435b0984fbb9da0 (patch)
treeed9d36c88f289a23efaebfd4876b9ed516493c1e
parent5ccde4c81e843ab6b3a324c8e2aa96d9b1270a1a (diff)
parent650e55f224a575cdb18c984b95036109519502d1 (diff)
downloadlinux-ba4550d5d724b693b142812af435b0984fbb9da0.tar.xz
Merge branch 'net-phy-realtek-simplify-and-reunify-c22-c45-drivers'
Daniel Golle says: ==================== net: phy: realtek: simplify and reunify C22/C45 drivers The RTL8221B PHY variants (VB-CG and VM-CG) were previously split into separate C22 and C45 driver instances to support copper SFP modules using the RollBall MDIO-over-I2C protocol, which only supports Clause-45 access. However, this split created significant code duplication and complexity. Commit 8af2136e77989 ("net: phy: realtek: add helper RTL822X_VND2_C22_REG") exposed that RealTek PHYs map all standard Clause-22 registers into MDIO_MMD_VEND2 at offset 0xa400. With commit 1850ec20d6e71 ("net: phy: realtek: use paged access for MDIO_MMD_VEND2 in C22 mode") it is now possible to access all MMD registers transparently, regardless of whether the PHY is accessed via C22 or C45 MDIO. Further improve the translation logic for this register mapping, so a single unified driver works efficiently with both access methods, reducing code duplication. The series also includes cleanup to remove unnecessary paged operations on registers that aren't actually affected by page selection. Testing was done on RTL8211F and RTL8221B-VB-CG (the latter in both C22 and C45 modes). ==================== Link: https://patch.msgid.link/cover.1768275364.git.daniel@makrotopia.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
-rw-r--r--drivers/net/phy/realtek/realtek_main.c124
1 files changed, 48 insertions, 76 deletions
diff --git a/drivers/net/phy/realtek/realtek_main.c b/drivers/net/phy/realtek/realtek_main.c
index 7b7a48e5082a..75565fbdbf6d 100644
--- a/drivers/net/phy/realtek/realtek_main.c
+++ b/drivers/net/phy/realtek/realtek_main.c
@@ -68,7 +68,6 @@
#define RTL8211E_DELAY_MASK GENMASK(13, 11)
/* RTL8211F PHY configuration */
-#define RTL8211F_PHYCR_PAGE 0xa43
#define RTL8211F_PHYCR1 0x18
#define RTL8211F_ALDPS_PLL_OFF BIT(1)
#define RTL8211F_ALDPS_ENABLE BIT(2)
@@ -78,7 +77,6 @@
#define RTL8211F_CLKOUT_EN BIT(0)
#define RTL8211F_PHYCR2_PHY_EEE_ENABLE BIT(5)
-#define RTL8211F_INSR_PAGE 0xa43
#define RTL8211F_INSR 0x1d
/* RTL8211F LED configuration */
@@ -144,6 +142,7 @@
#define RTL822X_VND2_TO_PAGE(reg) ((reg) >> 4)
#define RTL822X_VND2_TO_PAGE_REG(reg) (16 + (((reg) & GENMASK(3, 0)) >> 1))
+#define RTL822X_VND2_TO_C22_REG(reg) (((reg) - 0xa400) / 2)
#define RTL822X_VND2_C22_REG(reg) (0xa400 + 2 * (reg))
#define RTL8221B_VND2_INER 0xa4d2
@@ -178,12 +177,12 @@
#define RTL9000A_GINMR 0x14
#define RTL9000A_GINMR_LINK_STATUS BIT(4)
-#define RTL_VND2_PHYSR 0xa434
-#define RTL_VND2_PHYSR_DUPLEX BIT(3)
-#define RTL_VND2_PHYSR_SPEEDL GENMASK(5, 4)
-#define RTL_VND2_PHYSR_SPEEDH GENMASK(10, 9)
-#define RTL_VND2_PHYSR_MASTER BIT(11)
-#define RTL_VND2_PHYSR_SPEED_MASK (RTL_VND2_PHYSR_SPEEDL | RTL_VND2_PHYSR_SPEEDH)
+#define RTL_PHYSR MII_RESV2
+#define RTL_PHYSR_DUPLEX BIT(3)
+#define RTL_PHYSR_SPEEDL GENMASK(5, 4)
+#define RTL_PHYSR_SPEEDH GENMASK(10, 9)
+#define RTL_PHYSR_MASTER BIT(11)
+#define RTL_PHYSR_SPEED_MASK (RTL_PHYSR_SPEEDL | RTL_PHYSR_SPEEDH)
#define RTL_MDIO_PCS_EEE_ABLE 0xa5c4
#define RTL_MDIO_AN_EEE_ADV 0xa5d0
@@ -332,7 +331,7 @@ static int rtl8211f_ack_interrupt(struct phy_device *phydev)
{
int err;
- err = phy_read_paged(phydev, RTL8211F_INSR_PAGE, RTL8211F_INSR);
+ err = phy_read(phydev, RTL8211F_INSR);
return (err < 0) ? err : 0;
}
@@ -478,7 +477,7 @@ static irqreturn_t rtl8211f_handle_interrupt(struct phy_device *phydev)
{
int irq_status;
- irq_status = phy_read_paged(phydev, RTL8211F_INSR_PAGE, RTL8211F_INSR);
+ irq_status = phy_read(phydev, RTL8211F_INSR);
if (irq_status < 0) {
phy_error(phydev);
return IRQ_NONE;
@@ -669,8 +668,8 @@ static int rtl8211f_config_clk_out(struct phy_device *phydev)
RTL8211FVD_CLKOUT_REG,
RTL8211FVD_CLKOUT_EN, 0);
else
- ret = phy_modify_paged(phydev, RTL8211F_PHYCR_PAGE,
- RTL8211F_PHYCR2, RTL8211F_CLKOUT_EN, 0);
+ ret = phy_modify(phydev, RTL8211F_PHYCR2, RTL8211F_CLKOUT_EN,
+ 0);
if (ret)
return ret;
@@ -695,15 +694,14 @@ static int rtl8211f_config_aldps(struct phy_device *phydev)
if (!priv->enable_aldps)
return 0;
- return phy_modify_paged(phydev, RTL8211F_PHYCR_PAGE, RTL8211F_PHYCR1,
- mask, mask);
+ return phy_modify(phydev, RTL8211F_PHYCR1, mask, mask);
}
static int rtl8211f_config_phy_eee(struct phy_device *phydev)
{
/* Disable PHY-mode EEE so LPI is passed to the MAC */
- return phy_modify_paged(phydev, RTL8211F_PHYCR_PAGE, RTL8211F_PHYCR2,
- RTL8211F_PHYCR2_PHY_EEE_ENABLE, 0);
+ return phy_modify(phydev, RTL8211F_PHYCR2,
+ RTL8211F_PHYCR2_PHY_EEE_ENABLE, 0);
}
static int rtl8211f_config_init(struct phy_device *phydev)
@@ -769,7 +767,7 @@ static int rtl8211f_suspend(struct phy_device *phydev)
goto err;
/* Read the INSR to clear any pending interrupt */
- phy_read_paged(phydev, RTL8211F_INSR_PAGE, RTL8211F_INSR);
+ phy_read(phydev, RTL8211F_INSR);
/* Reset the WoL to ensure that an event is picked up.
* Unless we do this, even if we receive another packet,
@@ -1102,12 +1100,12 @@ static void rtlgen_decode_physr(struct phy_device *phydev, int val)
* 0: Half Duplex
* 1: Full Duplex
*/
- if (val & RTL_VND2_PHYSR_DUPLEX)
+ if (val & RTL_PHYSR_DUPLEX)
phydev->duplex = DUPLEX_FULL;
else
phydev->duplex = DUPLEX_HALF;
- switch (val & RTL_VND2_PHYSR_SPEED_MASK) {
+ switch (val & RTL_PHYSR_SPEED_MASK) {
case 0x0000:
phydev->speed = SPEED_10;
break;
@@ -1135,7 +1133,7 @@ static void rtlgen_decode_physr(struct phy_device *phydev, int val)
* 1: Master Mode
*/
if (phydev->speed >= 1000) {
- if (val & RTL_VND2_PHYSR_MASTER)
+ if (val & RTL_PHYSR_MASTER)
phydev->master_slave_state = MASTER_SLAVE_STATE_MASTER;
else
phydev->master_slave_state = MASTER_SLAVE_STATE_SLAVE;
@@ -1155,8 +1153,7 @@ static int rtlgen_read_status(struct phy_device *phydev)
if (!phydev->link)
return 0;
- val = phy_read_paged(phydev, RTL822X_VND2_TO_PAGE(RTL_VND2_PHYSR),
- RTL822X_VND2_TO_PAGE_REG(RTL_VND2_PHYSR));
+ val = phy_read(phydev, RTL_PHYSR);
if (val < 0)
return val;
@@ -1265,6 +1262,11 @@ static int rtl822xb_read_mmd(struct phy_device *phydev, int devnum, u16 reg)
return mmd_phy_read(phydev->mdio.bus, phydev->mdio.addr,
phydev->is_c45, devnum, reg);
+ /* Simplify access to C22-registers addressed inside MDIO_MMD_VEND2 */
+ if (reg >= RTL822X_VND2_C22_REG(0) &&
+ reg <= RTL822X_VND2_C22_REG(30))
+ return __phy_read(phydev, RTL822X_VND2_TO_C22_REG(reg));
+
/* Use paged access for MDIO_MMD_VEND2 over Clause-22 */
page = RTL822X_VND2_TO_PAGE(reg);
oldpage = __phy_read(phydev, RTL821x_PAGE_SELECT);
@@ -1300,6 +1302,11 @@ static int rtl822xb_write_mmd(struct phy_device *phydev, int devnum, u16 reg,
return mmd_phy_write(phydev->mdio.bus, phydev->mdio.addr,
phydev->is_c45, devnum, reg, val);
+ /* Simplify access to C22-registers addressed inside MDIO_MMD_VEND2 */
+ if (reg >= RTL822X_VND2_C22_REG(0) &&
+ reg <= RTL822X_VND2_C22_REG(30))
+ return __phy_write(phydev, RTL822X_VND2_TO_C22_REG(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);
@@ -1613,7 +1620,8 @@ static int rtl822x_c45_read_status(struct phy_device *phydev)
}
/* Read actual speed from vendor register. */
- val = phy_read_mmd(phydev, MDIO_MMD_VEND2, RTL_VND2_PHYSR);
+ val = phy_read_mmd(phydev, MDIO_MMD_VEND2,
+ RTL822X_VND2_C22_REG(RTL_PHYSR));
if (val < 0)
return val;
@@ -1870,28 +1878,18 @@ static int rtl8221b_match_phy_device(struct phy_device *phydev,
return phydev->phy_id == RTL_8221B && rtlgen_supports_mmd(phydev);
}
-static int rtl8221b_vb_cg_c22_match_phy_device(struct phy_device *phydev,
- const struct phy_driver *phydrv)
-{
- return rtlgen_is_c45_match(phydev, RTL_8221B_VB_CG, false);
-}
-
-static int rtl8221b_vb_cg_c45_match_phy_device(struct phy_device *phydev,
- const struct phy_driver *phydrv)
-{
- return rtlgen_is_c45_match(phydev, RTL_8221B_VB_CG, true);
-}
-
-static int rtl8221b_vm_cg_c22_match_phy_device(struct phy_device *phydev,
- const struct phy_driver *phydrv)
+static int rtl8221b_vb_cg_match_phy_device(struct phy_device *phydev,
+ const struct phy_driver *phydrv)
{
- return rtlgen_is_c45_match(phydev, RTL_8221B_VM_CG, false);
+ return rtlgen_is_c45_match(phydev, RTL_8221B_VB_CG, true) ||
+ rtlgen_is_c45_match(phydev, RTL_8221B_VB_CG, false);
}
-static int rtl8221b_vm_cg_c45_match_phy_device(struct phy_device *phydev,
- const struct phy_driver *phydrv)
+static int rtl8221b_vm_cg_match_phy_device(struct phy_device *phydev,
+ const struct phy_driver *phydrv)
{
- return rtlgen_is_c45_match(phydev, RTL_8221B_VM_CG, true);
+ return rtlgen_is_c45_match(phydev, RTL_8221B_VM_CG, true) ||
+ rtlgen_is_c45_match(phydev, RTL_8221B_VM_CG, false);
}
static int rtl_internal_nbaset_match_phy_device(struct phy_device *phydev,
@@ -2127,7 +2125,7 @@ static int rtlgen_sfp_read_status(struct phy_device *phydev)
if (!phydev->link)
return 0;
- val = rtlgen_read_vend2(phydev, RTL_VND2_PHYSR);
+ val = phy_read(phydev, RTL_PHYSR);
if (val < 0)
return val;
@@ -2314,25 +2312,8 @@ static struct phy_driver realtek_drvs[] = {
.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)",
- .probe = rtl822x_probe,
- .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,
- .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)",
+ .match_phy_device = rtl8221b_vb_cg_match_phy_device,
+ .name = "RTL8221B-VB-CG 2.5Gbps PHY",
.config_intr = rtl8221b_config_intr,
.handle_interrupt = rtl8221b_handle_interrupt,
.probe = rtl822x_probe,
@@ -2345,26 +2326,13 @@ static struct phy_driver realtek_drvs[] = {
.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)",
- .probe = rtl822x_probe,
- .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,
- .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)",
+ .match_phy_device = rtl8221b_vm_cg_match_phy_device,
+ .name = "RTL8221B-VM-CG 2.5Gbps PHY",
.config_intr = rtl8221b_config_intr,
.handle_interrupt = rtl8221b_handle_interrupt,
.probe = rtl822x_probe,
@@ -2377,6 +2345,10 @@ static struct phy_driver realtek_drvs[] = {
.read_status = rtl822xb_c45_read_status,
.suspend = genphy_c45_pma_suspend,
.resume = rtlgen_c45_resume,
+ .read_page = rtl821x_read_page,
+ .write_page = rtl821x_write_page,
+ .read_mmd = rtl822xb_read_mmd,
+ .write_mmd = rtl822xb_write_mmd,
}, {
.match_phy_device = rtl8251b_c45_match_phy_device,
.name = "RTL8251B 5Gbps PHY",