generic: net: phy: realtek: don't disable MDIO address 0 for PHY in SFP module

At least the XikeStor SKT-2.5G-100M SFP module seems to internally use
MDIO address 0 to access the PHY. This module allows accessing PHY
registers using Rollball protocol on address 0x51, and also provides
read-only C22 access on address 0x56. However, after disabling the
PHYAD0 configuration bit, only 0xffff can be read via both methods
(except for MMD device 30 which can still be accessed).

Since having MDIO address 0 enabled shouldn't do any harm on SFP modules
just leave the configuration bit alone in that case.

Signed-off-by: Jan Hoffmann <jan@3e8.eu>
Link: https://github.com/openwrt/openwrt/pull/23065
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
This commit is contained in:
Jan Hoffmann 2026-04-23 16:58:40 +02:00 committed by Hauke Mehrtens
parent a4a6a06c9f
commit 45633073fe
8 changed files with 45 additions and 17 deletions

View File

@ -21,13 +21,27 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
#define RTL8366RB_POWER_SAVE 0x15
#define RTL8366RB_POWER_SAVE_ON BIT(12)
@@ -1358,7 +1359,8 @@ static int rtl822x_init_phycr1(struct ph
@@ -1351,14 +1352,21 @@ static int rtl822xb_write_mmd(struct phy
static int rtl822x_init_phycr1(struct phy_device *phydev, bool no_aldps)
{
struct rtl822x_priv *priv = phydev->priv;
+ u16 mask = RTL8221B_PHYCR1_ALDPS_EN | RTL8221B_PHYCR1_ALDPS_XTAL_OFF_EN;
u16 val = 0;
+ /* The controller in some SFP modules uses MDIO address 0 to access the
+ * PHY. Leave the MDIO broadcast configuration bit alone for SFP
+ * modules, as it won't cause any issues there anyways.
+ */
+ if (!phydev->is_on_sfp_module)
+ mask |= RTL8221B_PHYCR1_PHYAD_0_EN;
+
if (priv->enable_aldps && !no_aldps)
val = RTL8221B_PHYCR1_ALDPS_EN | RTL8221B_PHYCR1_ALDPS_XTAL_OFF_EN;
return phy_modify_mmd_changed(phydev, MDIO_MMD_VEND2, RTL8221B_PHYCR1,
RTL8221B_PHYCR1_ALDPS_EN |
- RTL8221B_PHYCR1_ALDPS_EN |
- RTL8221B_PHYCR1_ALDPS_XTAL_OFF_EN, val);
+ RTL8221B_PHYCR1_ALDPS_XTAL_OFF_EN |
+ RTL8221B_PHYCR1_PHYAD_0_EN, val);
+ mask, val);
}
static int rtl822x_set_serdes_option_mode(struct phy_device *phydev, bool gen1)

View File

@ -11,7 +11,7 @@ interface mode if the PHY is connected using Clause-45 MDIO.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
--- a/drivers/net/phy/realtek/realtek_main.c
+++ b/drivers/net/phy/realtek/realtek_main.c
@@ -1387,7 +1387,7 @@ static int rtl822x_set_serdes_option_mod
@@ -1393,7 +1393,7 @@ static int rtl822x_set_serdes_option_mod
return 0;
/* determine SerDes option mode */

View File

@ -21,13 +21,27 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
#define RTL8366RB_POWER_SAVE 0x15
#define RTL8366RB_POWER_SAVE_ON BIT(12)
@@ -1358,7 +1359,8 @@ static int rtl822x_init_phycr1(struct ph
@@ -1351,14 +1352,21 @@ static int rtl822xb_write_mmd(struct phy
static int rtl822x_init_phycr1(struct phy_device *phydev, bool no_aldps)
{
struct rtl822x_priv *priv = phydev->priv;
+ u16 mask = RTL8221B_PHYCR1_ALDPS_EN | RTL8221B_PHYCR1_ALDPS_XTAL_OFF_EN;
u16 val = 0;
+ /* The controller in some SFP modules uses MDIO address 0 to access the
+ * PHY. Leave the MDIO broadcast configuration bit alone for SFP
+ * modules, as it won't cause any issues there anyways.
+ */
+ if (!phydev->is_on_sfp_module)
+ mask |= RTL8221B_PHYCR1_PHYAD_0_EN;
+
if (priv->enable_aldps && !no_aldps)
val = RTL8221B_PHYCR1_ALDPS_EN | RTL8221B_PHYCR1_ALDPS_XTAL_OFF_EN;
return phy_modify_mmd_changed(phydev, MDIO_MMD_VEND2, RTL8221B_PHYCR1,
RTL8221B_PHYCR1_ALDPS_EN |
- RTL8221B_PHYCR1_ALDPS_EN |
- RTL8221B_PHYCR1_ALDPS_XTAL_OFF_EN, val);
+ RTL8221B_PHYCR1_ALDPS_XTAL_OFF_EN |
+ RTL8221B_PHYCR1_PHYAD_0_EN, val);
+ mask, val);
}
static int rtl822x_set_serdes_option_mode(struct phy_device *phydev, bool gen1)

View File

@ -11,7 +11,7 @@ interface mode if the PHY is connected using Clause-45 MDIO.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
--- a/drivers/net/phy/realtek/realtek_main.c
+++ b/drivers/net/phy/realtek/realtek_main.c
@@ -1387,7 +1387,7 @@ static int rtl822x_set_serdes_option_mod
@@ -1393,7 +1393,7 @@ static int rtl822x_set_serdes_option_mod
return 0;
/* determine SerDes option mode */

View File

@ -54,7 +54,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
#define RTL8366RB_POWER_SAVE 0x15
#define RTL8366RB_POWER_SAVE_ON BIT(12)
@@ -1865,6 +1868,66 @@ static int rtl8224_cable_test_get_status
@@ -1871,6 +1874,66 @@ static int rtl8224_cable_test_get_status
return rtl8224_cable_test_report(phydev, finished);
}
@ -121,7 +121,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
static bool rtlgen_supports_2_5gbps(struct phy_device *phydev)
{
int val;
@@ -2466,6 +2529,8 @@ static struct phy_driver realtek_drvs[]
@@ -2472,6 +2535,8 @@ static struct phy_driver realtek_drvs[]
PHY_ID_MATCH_EXACT(0x001ccad0),
.name = "RTL8224 2.5Gbps PHY",
.flags = PHY_POLL_CABLE_TEST,

View File

@ -32,7 +32,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
#define RTL8366RB_POWER_SAVE 0x15
#define RTL8366RB_POWER_SAVE_ON BIT(12)
@@ -1916,9 +1917,40 @@ static int rtl8224_mdi_config_order(stru
@@ -1922,9 +1923,40 @@ static int rtl8224_mdi_config_order(stru
order ? BIT(port_offset) : 0);
}

View File

@ -30,7 +30,7 @@ Signed-off-by: Jan Hoffmann <jan@3e8.eu>
--- a/drivers/net/phy/realtek/realtek_main.c
+++ b/drivers/net/phy/realtek/realtek_main.c
@@ -1490,6 +1490,148 @@ static unsigned int rtl822x_inband_caps(
@@ -1496,6 +1496,148 @@ static unsigned int rtl822x_inband_caps(
}
}
@ -179,7 +179,7 @@ Signed-off-by: Jan Hoffmann <jan@3e8.eu>
static int rtl822xb_get_rate_matching(struct phy_device *phydev,
phy_interface_t iface)
{
@@ -2453,7 +2595,7 @@ static struct phy_driver realtek_drvs[]
@@ -2459,7 +2601,7 @@ static struct phy_driver realtek_drvs[]
.soft_reset = rtl822x_c45_soft_reset,
.get_features = rtl822x_c45_get_features,
.config_aneg = rtl822x_c45_config_aneg,

View File

@ -42,7 +42,7 @@
#define RTL8221B_PHYCR1 0xa430
#define RTL8221B_PHYCR1_ALDPS_EN BIT(2)
#define RTL8221B_PHYCR1_ALDPS_XTAL_OFF_EN BIT(12)
@@ -2034,6 +2069,147 @@ exit:
@@ -2040,6 +2075,147 @@ exit:
return ret;
}
@ -190,7 +190,7 @@
static int rtl8224_mdi_config_order(struct phy_device *phydev)
{
struct device_node *np = phydev->mdio.dev.of_node;
@@ -2088,6 +2264,10 @@ static int rtl8224_config_init(struct ph
@@ -2094,6 +2270,10 @@ static int rtl8224_config_init(struct ph
{
int ret;