]> git.ipfire.org Git - thirdparty/openwrt.git/commitdiff
realtek: pcs: adjust autoneg to fix RTL931x issue
authorJonas Jelonek <jelonek.jonas@gmail.com>
Wed, 11 Feb 2026 12:23:03 +0000 (12:23 +0000)
committerRobert Marko <robimarko@gmail.com>
Mon, 16 Feb 2026 14:43:20 +0000 (15:43 +0100)
The autonegotiation setting might not have been working for RTL931x the
whole time. While there weren't any reports about issues so far, these
issues might just have been hidden behind other circumstances.

While all other variants of the Otto family have the corresponding
settings in [page 0x2 register 0x0] of a SerDes, RTL931x has a special
Front/Background SerDes architecture and actually moved the
autonegotiation settings to a digital Background SerDes. Since we use a
special mapping to have a consistent view on these Background SerDes,
RTL931x needs to write the settings to another page.

To fix this, adjust the autonegotiation setting for all variants. The
generic implementation is kept but uses per-variant register field
definitions. Those are added for all variants here, with the differing
page for RTL931x.

Another static data definition is renamed since it conflicts with a
change introduced here.

Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
Link: https://github.com/openwrt/openwrt/pull/22013
Signed-off-by: Robert Marko <robimarko@gmail.com>
target/linux/realtek/files-6.12/drivers/net/pcs/pcs-rtl-otto.c

index 96dc3ab00f6cb777bc75964dfc81a4af00996d8b..9a1239f35138e9bb880cdbb28188790e45742dce 100644 (file)
@@ -334,7 +334,6 @@ static int rtpcs_sds_read_field(struct rtpcs_serdes *sds, const struct rtpcs_sds
        return sds->ops->read(sds, field->page, field->reg, field->msb, field->lsb);
 }
 
-__maybe_unused
 static int rtpcs_sds_write_field(struct rtpcs_serdes *sds, const struct rtpcs_sds_reg_field *field,
                                 u16 value)
 {
@@ -362,6 +361,7 @@ static int rtpcs_sds_xsg_write(struct rtpcs_serdes *sds, int page, int regnum, u
 
 /* Other helpers */
 
+__maybe_unused
 static int rtpcs_sds_modify(struct rtpcs_serdes *sds, int page, int regnum,
                            u16 mask, u16 set)
 {
@@ -371,15 +371,6 @@ static int rtpcs_sds_modify(struct rtpcs_serdes *sds, int page, int regnum,
                                  mmd_regnum, mask, set);
 }
 
-static int rtpcs_sds_modify_changed(struct rtpcs_serdes *sds, int page, int regnum,
-                                   u16 mask, u16 set)
-{
-       int mmd_regnum = rtpcs_sds_to_mmd(page, regnum);
-
-       return mdiobus_c45_modify_changed(sds->ctrl->bus, sds->id, MDIO_MMD_VEND1,
-                                         mmd_regnum, mask, set);
-}
-
 static struct rtpcs_serdes *rtpcs_sds_get_even(struct rtpcs_serdes *sds)
 {
        u32 even_sds = sds->id & ~1;
@@ -478,8 +469,8 @@ static int rtpcs_sds_determine_hw_mode(struct rtpcs_serdes *sds,
 static int rtpcs_generic_sds_set_autoneg(struct rtpcs_serdes *sds, unsigned int neg_mode,
                                         const unsigned long *advertising)
 {
-       u16 bmcr, adv;
-       bool changed = 0;
+       u16 bmcr, adv, adv_old;
+       bool changed = false;
        int ret;
 
        if ((sds->hw_mode == RTPCS_SDS_MODE_1000BASEX) ||
@@ -492,16 +483,21 @@ static int rtpcs_generic_sds_set_autoneg(struct rtpcs_serdes *sds, unsigned int
                                      advertising))
                        adv |= ADVERTISE_1000XPSE_ASYM;
 
-               ret = rtpcs_sds_modify_changed(sds, 0x2, MII_ADVERTISE,
-                                              0xffff, adv);
-               if (ret < 0)
-                       return ret;
-               changed = ret;
+               adv_old = rtpcs_sds_read_field(sds, &sds->regs->an_advertise);
+               if (adv_old < 0)
+                       return adv_old;
+
+               if (adv != adv_old) {
+                       changed = true;
+                       ret = rtpcs_sds_write_field(sds, &sds->regs->an_advertise, adv);
+                       if (ret < 0)
+                               return ret;
+               }
        }
 
-       bmcr = neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED ? BMCR_ANENABLE : 0;
+       bmcr = neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED ? 1 : 0;
 
-       ret = rtpcs_sds_modify(sds, 0x2, MII_BMCR, BMCR_ANENABLE, bmcr);
+       ret = rtpcs_sds_write_field(sds, &sds->regs->an_enable, bmcr);
        if (ret < 0)
                return ret;
 
@@ -510,7 +506,7 @@ static int rtpcs_generic_sds_set_autoneg(struct rtpcs_serdes *sds, unsigned int
 
 static void rtpcs_generic_sds_restart_autoneg(struct rtpcs_serdes *sds)
 {
-       rtpcs_sds_modify(sds, 0x2, MII_BMCR, BMCR_ANRESTART, BMCR_ANRESTART);
+       rtpcs_sds_write_field(sds, &sds->regs->an_restart, 0x1);
 }
 
 /* Variant-specific functions */
@@ -1143,13 +1139,13 @@ static int rtpcs_930x_sds_op_xsg_write(struct rtpcs_serdes *sds, int page, int r
                                     value);
 }
 
-static const u16 rtpcs_930x_sds_regs[] = {
+static const u16 rtpcs_930x_sds_mode_regs[] = {
        0x0194, 0x0194, 0x0194, 0x0194,         /* SDS_MODE_SEL_0 */
        0x02a0, 0x02a0, 0x02a0, 0x02a0,         /* SDS_MODE_SEL_1 */
        0x02a4, 0x02a4,                         /* SDS_MODE_SEL_2 */
        0x0198, 0x0198                          /* SDS_MODE_SEL_3 */
 };
-static const u8 rtpcs_930x_sds_lsb[]  = { 0, 6, 12, 18, 0, 6, 12, 18, 0, 6, 0, 6 };
+static const u8 rtpcs_930x_sds_mode_lsb[]  = { 0, 6, 12, 18, 0, 6, 12, 18, 0, 6, 0, 6 };
 
 static const u16 rtpcs_930x_sds_submode_regs[] = {
        0x1cc, 0x1cc,                           /* SDS_SUBMODE_CTRL0 */
@@ -1163,11 +1159,11 @@ static int __rtpcs_930x_sds_get_mac_mode(struct rtpcs_serdes *sds)
        u8 sds_id = sds->id;
        int mode_val, ret;
 
-       ret = regmap_read(sds->ctrl->map, rtpcs_930x_sds_regs[sds_id], &mode_val);
+       ret = regmap_read(sds->ctrl->map, rtpcs_930x_sds_mode_regs[sds_id], &mode_val);
        if (ret < 0)
                return ret;
 
-       mode_val >>= rtpcs_930x_sds_lsb[sds_id];
+       mode_val >>= rtpcs_930x_sds_mode_lsb[sds_id];
        return mode_val & RTPCS_930X_SDS_MASK;
 }
 
@@ -1176,9 +1172,9 @@ static int __rtpcs_930x_sds_set_mac_mode(struct rtpcs_serdes *sds, u32 mode)
        u8 sds_id = sds->id;
        int ret;
 
-       ret = regmap_write_bits(sds->ctrl->map, rtpcs_930x_sds_regs[sds_id],
-                               RTPCS_930X_SDS_MASK << rtpcs_930x_sds_lsb[sds_id],
-                               mode << rtpcs_930x_sds_lsb[sds_id]);
+       ret = regmap_write_bits(sds->ctrl->map, rtpcs_930x_sds_mode_regs[sds_id],
+                               RTPCS_930X_SDS_MASK << rtpcs_930x_sds_mode_lsb[sds_id],
+                               mode << rtpcs_930x_sds_mode_lsb[sds_id]);
        mdelay(10);
 
        return ret;
@@ -4089,6 +4085,12 @@ static const struct rtpcs_serdes_ops rtpcs_838x_sds_ops = {
        .restart_autoneg        = rtpcs_generic_sds_restart_autoneg,
 };
 
+static const struct rtpcs_sds_regs rtpcs_838x_sds_regs = {
+       .an_enable      = { .page = 0x2, .reg = MII_BMCR, .msb = 12, .lsb = 12 },
+       .an_restart     = { .page = 0x2, .reg = MII_BMCR, .msb = 9, .lsb = 9 },
+       .an_advertise   = { .page = 0x2, .reg = MII_ADVERTISE, .msb = 15, .lsb = 0 },
+};
+
 static const struct rtpcs_config rtpcs_838x_cfg = {
        .cpu_port               = RTPCS_838X_CPU_PORT,
        .mac_link_dup_sts       = RTPCS_838X_MAC_LINK_DUP_STS,
@@ -4100,6 +4102,7 @@ static const struct rtpcs_config rtpcs_838x_cfg = {
        .serdes_count           = RTPCS_838X_SERDES_CNT,
        .pcs_ops                = &rtpcs_838x_pcs_ops,
        .sds_ops                = &rtpcs_838x_sds_ops,
+       .sds_regs               = &rtpcs_838x_sds_regs,
        .init_serdes_common     = rtpcs_838x_init_serdes_common,
        .setup_serdes           = rtpcs_838x_setup_serdes,
 };
@@ -4117,6 +4120,12 @@ static const struct rtpcs_serdes_ops rtpcs_839x_sds_ops = {
        .restart_autoneg        = rtpcs_generic_sds_restart_autoneg,
 };
 
+static const struct rtpcs_sds_regs rtpcs_839x_sds_regs = {
+       .an_enable      = { .page = 0x2, .reg = MII_BMCR, .msb = 12, .lsb = 12 },
+       .an_restart     = { .page = 0x2, .reg = MII_BMCR, .msb = 9, .lsb = 9 },
+       .an_advertise   = { .page = 0x2, .reg = MII_ADVERTISE, .msb = 15, .lsb = 0 },
+};
+
 static const struct rtpcs_config rtpcs_839x_cfg = {
        .cpu_port               = RTPCS_839X_CPU_PORT,
        .mac_link_dup_sts       = RTPCS_839X_MAC_LINK_DUP_STS,
@@ -4128,6 +4137,7 @@ static const struct rtpcs_config rtpcs_839x_cfg = {
        .serdes_count           = RTPCS_839X_SERDES_CNT,
        .pcs_ops                = &rtpcs_839x_pcs_ops,
        .sds_ops                = &rtpcs_839x_sds_ops,
+       .sds_regs               = &rtpcs_839x_sds_regs,
        .init_serdes_common     = rtpcs_839x_init_serdes_common,
        .setup_serdes           = rtpcs_839x_setup_serdes,
 };
@@ -4146,6 +4156,12 @@ static const struct rtpcs_serdes_ops rtpcs_930x_sds_ops = {
        .restart_autoneg        = rtpcs_generic_sds_restart_autoneg,
 };
 
+static const struct rtpcs_sds_regs rtpcs_930x_sds_regs = {
+       .an_enable      = { .page = 0x2, .reg = MII_BMCR, .msb = 12, .lsb = 12 },
+       .an_restart     = { .page = 0x2, .reg = MII_BMCR, .msb = 9, .lsb = 9 },
+       .an_advertise   = { .page = 0x2, .reg = MII_ADVERTISE, .msb = 15, .lsb = 0 },
+};
+
 static const struct rtpcs_config rtpcs_930x_cfg = {
        .cpu_port               = RTPCS_930X_CPU_PORT,
        .mac_link_dup_sts       = RTPCS_930X_MAC_LINK_DUP_STS,
@@ -4157,6 +4173,7 @@ static const struct rtpcs_config rtpcs_930x_cfg = {
        .serdes_count           = RTPCS_930X_SERDES_CNT,
        .pcs_ops                = &rtpcs_930x_pcs_ops,
        .sds_ops                = &rtpcs_930x_sds_ops,
+       .sds_regs               = &rtpcs_930x_sds_regs,
        .init_serdes_common     = rtpcs_93xx_init_serdes_common,
        .setup_serdes           = rtpcs_930x_setup_serdes,
 };
@@ -4175,6 +4192,12 @@ static const struct rtpcs_serdes_ops rtpcs_931x_sds_ops = {
        .restart_autoneg        = rtpcs_generic_sds_restart_autoneg,
 };
 
+static const struct rtpcs_sds_regs rtpcs_931x_sds_regs = {
+       .an_enable      = { .page = 0x42, .reg = MII_BMCR, .msb = 12, .lsb = 12 },
+       .an_restart     = { .page = 0x42, .reg = MII_BMCR, .msb = 9, .lsb = 9 },
+       .an_advertise   = { .page = 0x42, .reg = MII_ADVERTISE, .msb = 15, .lsb = 0 },
+};
+
 static const struct rtpcs_config rtpcs_931x_cfg = {
        .cpu_port               = RTPCS_931X_CPU_PORT,
        .mac_link_dup_sts       = RTPCS_931X_MAC_LINK_DUP_STS,
@@ -4186,6 +4209,7 @@ static const struct rtpcs_config rtpcs_931x_cfg = {
        .serdes_count           = RTPCS_931X_SERDES_CNT,
        .pcs_ops                = &rtpcs_931x_pcs_ops,
        .sds_ops                = &rtpcs_931x_sds_ops,
+       .sds_regs               = &rtpcs_931x_sds_regs,
        .init_serdes_common     = rtpcs_93xx_init_serdes_common,
        .setup_serdes           = rtpcs_931x_setup_serdes,
 };