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 <jelonek.jonas@gmail.com>
Link: https://github.com/openwrt/openwrt/pull/23120
Signed-off-by: Robert Marko <robimarko@gmail.com>
This commit is contained in:
Jonas Jelonek 2026-04-23 11:07:24 +00:00 committed by Robert Marko
parent 086fb1c067
commit 23f04f6af8

View File

@ -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)