From 23f04f6af8be45159b6946409b094906fc6e0cbf Mon Sep 17 00:00:00 2001 From: Jonas Jelonek Date: Thu, 23 Apr 2026 11:07:24 +0000 Subject: [PATCH] realtek: pcs: rtl931x: enable USXGMII submode selection USXGMII submode (10GSX vs 10GQX) is selected through a dedicated register at 0x13e8, independent of the MAC and IP mode registers. Without programming it, USXGMII-QX ports initialise as single-lane SX and fail to link up correctly; MAC and IP mode alone are insufficient for a working USXGMII setup. The register packs 12 x 5-bit entries for SerDes 2..13, six per 32-bit word, non-straddling (bits 0..29 used, 30..31 padded). This matches the available register dumps and the SDK's reg_array_field_write() non-CROSS_REGISTERS path, which derives the bit position as ((index - larray) % (32 / width)) * width and accesses only a single 32-bit word. The submode values are identical to RTL930x, so the shared RTPCS_93XX_SDS_USXGMII_SUBMODE_* defines are reused. Allocate the regmap_field at probe time with coordinates computed from the SerDes ID; the regular packing needs no lookup table. Call rtpcs_93xx_sds_apply_usxgmii_submode() from the set_mode dispatcher after set_ip_mode - the helper's null-guard and mode filter leave non-USXGMII paths unchanged. Signed-off-by: Jonas Jelonek Link: https://github.com/openwrt/openwrt/pull/23120 Signed-off-by: Robert Marko --- .../files-6.18/drivers/net/pcs/pcs-rtl-otto.c | 31 +++++++++++++++++-- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c b/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c index e042076604..6514e4cc5c 100644 --- a/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c +++ b/target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c @@ -97,6 +97,7 @@ #define RTPCS_931X_MAC_GROUP6_7_CTRL (0x13b4) #define RTPCS_931X_MAC_GROUP8_11_CTRL (0x13b8) #define RTPCS_931X_SERDES_MODE_CTRL (0x13cc) +#define RTPCS_931X_SDS_USXGMII_SUBMODE (0x13e8) #define RTPCS_931X_PS_SERDES_OFF_MODE_CTRL_ADDR (0x13F4) #define RTPCS_931X_MAC_SERDES_MODE_CTRL(sds) (0x136C + (((sds) << 2))) #define RTPCS_931X_ISR_SERDES_RXIDLE (0x12f8) @@ -3268,10 +3269,16 @@ static int rtpcs_931x_sds_set_ip_mode(struct rtpcs_serdes *sds, static int rtpcs_931x_sds_set_mode(struct rtpcs_serdes *sds, enum rtpcs_sds_mode hw_mode) { + int ret; + if (hw_mode == RTPCS_SDS_MODE_XSGMII) return rtpcs_93xx_sds_set_mac_mode(sds, hw_mode); - return rtpcs_931x_sds_set_ip_mode(sds, hw_mode); + ret = rtpcs_931x_sds_set_ip_mode(sds, hw_mode); + if (ret) + return ret; + + return rtpcs_93xx_sds_apply_usxgmii_submode(sds, hw_mode); } static void rtpcs_931x_sds_reset(struct rtpcs_serdes *sds) @@ -3943,8 +3950,26 @@ static int rtpcs_931x_sds_probe(struct rtpcs_serdes *sds) if (ret) return ret; - return rtpcs_sds_alloc_field(sds, &sds->swcore_regs.mac_mode_force, - base, lsb + 7, lsb + 7); + ret = rtpcs_sds_alloc_field(sds, &sds->swcore_regs.mac_mode_force, + base, lsb + 7, lsb + 7); + if (ret) + return ret; + + /* + * USXGMII submode is packed at 5 bits per SerDes for IDs 2..13, + * six entries per 32-bit word, non-straddling. + */ + if (sds->type == RTPCS_SDS_TYPE_10G) { + u8 submode_lsb = ((sds->id - 2) % 6) * 5; + + ret = rtpcs_sds_alloc_field(sds, &sds->swcore_regs.usxgmii_submode, + RTPCS_931X_SDS_USXGMII_SUBMODE + ((sds->id - 2) / 6) * 4, + submode_lsb, submode_lsb + 4); + if (ret) + return ret; + } + + return 0; } static int rtpcs_931x_init(struct rtpcs_ctrl *ctrl)