]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
net: phy: realtek: implement configuring in-band an
authorDaniel Golle <daniel@makrotopia.org>
Mon, 5 Jan 2026 16:38:12 +0000 (16:38 +0000)
committerPaolo Abeni <pabeni@redhat.com>
Thu, 8 Jan 2026 12:18:26 +0000 (13:18 +0100)
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@makrotopia.org>
Link: https://patch.msgid.link/82a78a06d67be19e856d646cf880b2021ea9d837.1767630451.git.daniel@makrotopia.org
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
drivers/net/phy/realtek/realtek_main.c

index e42c5efbfa5ef6c2463a81230c91c80e7b5e24bb..0653a9d8fcb6f4c8334bd98d7f3ad3a2716c2f37 100644 (file)
 #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,