[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <82a78a06d67be19e856d646cf880b2021ea9d837.1767630451.git.daniel@makrotopia.org>
Date: Mon, 5 Jan 2026 16:38:12 +0000
From: Daniel Golle <daniel@...rotopia.org>
To: Andrew Lunn <andrew@...n.ch>, Heiner Kallweit <hkallweit1@...il.com>,
Russell King <linux@...linux.org.uk>,
"David S. Miller" <davem@...emloft.net>,
Eric Dumazet <edumazet@...gle.com>,
Jakub Kicinski <kuba@...nel.org>, Paolo Abeni <pabeni@...hat.com>,
Vladimir Oltean <vladimir.oltean@....com>,
Michael Klein <michael@...sekall.de>,
Daniel Golle <daniel@...rotopia.org>,
Aleksander Jan Bajkowski <olek2@...pl>,
Bevan Weiss <bevan.weiss@...il.com>, netdev@...r.kernel.org,
linux-kernel@...r.kernel.org
Subject: [PATCH net-next v2 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 <daniel@...rotopia.org>
---
v2: no changes
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 e42c5efbfa5ef..0653a9d8fcb6f 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,
--
2.52.0
Powered by blists - more mailing lists