From f95dbe3575bc844c79c226c0a9d6ece808522ff1 Mon Sep 17 00:00:00 2001 From: Jonas Jelonek Date: Wed, 15 Apr 2026 09:05:16 +0000 Subject: [PATCH] realtek: pcs: replace various SerDes range checks The whole driver often does some range checks of the SerDes ID to restrict some functionality to a group of SerDes. However, having these open-coded checks everywhere is rather confusing because it's not obvious what it actually means. Luckily, those checks give a good picture of what SerDes types we have: - 5G: RTL838x, RTL839x (0-7, 10, 11), RTL930x (0, 1) - 10G: RTL839x (8, 9, 12, 13), RTL930x (2-9), RTL931x (2-13) - unknown: RTL930x (10, 11), RTL931x (0, 1) Add a new enum and field in rtpcs_serdes for the type of a SerDes we have. This is filled during SerDes probe, making use of the stub implementations for that hook.. All SerDes ID range checks related to this are replaced with corresponding checks of the SerDes type. Signed-off-by: Jonas Jelonek Link: https://github.com/openwrt/openwrt/pull/22941 Signed-off-by: Robert Marko --- .../files-6.18/drivers/net/pcs/pcs-rtl-otto.c | 51 ++++++++++++++----- 1 file changed, 38 insertions(+), 13 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 02cd0b70f3..c8429b4596 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 @@ -109,6 +109,12 @@ #define RTPCS_931X_SDS_MAIN_AMP_MASK GENMASK(9, 5) #define RTPCS_931X_SDS_POST_AMP_MASK GENMASK(14, 10) +enum rtpcs_sds_type { + RTPCS_SDS_TYPE_UNKNOWN, + RTPCS_SDS_TYPE_5G, + RTPCS_SDS_TYPE_10G, +}; + enum rtpcs_sds_mode { RTPCS_SDS_MODE_OFF = 0, @@ -201,6 +207,7 @@ struct rtpcs_serdes { struct rtpcs_ctrl *ctrl; const struct rtpcs_sds_ops *ops; const struct rtpcs_sds_regs *regs; + enum rtpcs_sds_type type; enum rtpcs_sds_mode hw_mode; u8 id; u8 num_of_links; @@ -838,6 +845,7 @@ static int rtpcs_838x_sds_patch(struct rtpcs_serdes *sds, static int rtpcs_838x_sds_probe(struct rtpcs_serdes *sds) { + sds->type = RTPCS_SDS_TYPE_5G; return 0; } @@ -902,17 +910,14 @@ static void rtpcs_839x_sds_reset(struct rtpcs_serdes *sds) struct rtpcs_serdes *even_sds = rtpcs_sds_get_even(sds); struct rtpcs_serdes *odd_sds = rtpcs_sds_get_odd(sds); - bool is_10g_sds = (sds->id == 8 || sds->id == 9 || sds->id == 12 || - sds->id == 13); - /* FIXME: The reset sequence seems to break some of the 5G SerDes * though the SDK is calling it for all SerDes during init. Until * this is solved, skip reset. */ - if (!is_10g_sds) + if (sds->type == RTPCS_SDS_TYPE_5G) return; - if (is_10g_sds) { + if (sds->type == RTPCS_SDS_TYPE_10G) { rtpcs_sds_write_bits(odd_sds, 0x2f, 0x1d, 3, 0, 0x5); msleep(500); rtpcs_sds_write_bits(odd_sds, 0x2f, 0x1d, 3, 0, 0xf); @@ -977,14 +982,19 @@ static int rtpcs_839x_sds_probe(struct rtpcs_serdes *sds) { bool is_even = sds->id % 2 == 0; + if (sds->id == 8 || sds->id == 9 || sds->id == 12 || sds->id == 13) + sds->type = RTPCS_SDS_TYPE_10G; + else + sds->type = RTPCS_SDS_TYPE_5G; + /* * This function is quite "mystic". It has been taken over from the vendor SDK function * rtl839x_serdes_patch_init(). There is not much documentation about it but one could * lookup the fields from the field headers. The 5G SerDes seem to work out of the box * so only setup the 10G SerDes for now. */ - if (sds->id != 8 && sds->id != 9 && sds->id != 12 && sds->id != 13) - return; + if (sds->type == RTPCS_SDS_TYPE_5G) + return 0; /* Part 1: register setup */ rtpcs_sds_write(sds, 0x2e, 0x0, 0x5800); @@ -1086,10 +1096,13 @@ static int rtpcs_839x_sds_probe(struct rtpcs_serdes *sds) rtpcs_sds_write_bits(sds, 0x2e, 0x13, 9, 9, 0x0000); rtpcs_sds_write_bits(sds, 0x2e, 0x13, 3, 0, 0x0008); rtpcs_sds_write_bits(sds, 0x2e, 0x13, 8, 5, 0x0008); + + return 0; } static int rtpcs_839x_init(struct rtpcs_ctrl *ctrl) { + /* reset all SerDes once after patching has been applied before */ for (int sds_id = 0; sds_id < ctrl->cfg->serdes_count; sds_id++) rtpcs_839x_sds_reset(&ctrl->serdes[sds_id]); @@ -1105,7 +1118,7 @@ static int rtpcs_839x_setup_serdes(struct rtpcs_serdes *sds, * at startup for QSGMII. Thus, connected PHYs should work out * of the box. */ - if (sds->id != 8 && sds->id != 9 && sds->id != 12 && sds->id != 13) + if (sds->type == RTPCS_SDS_TYPE_5G) return 0; ret = rtpcs_839x_sds_set_mode(sds, hw_mode); @@ -1458,7 +1471,7 @@ static int __rtpcs_930x_sds_get_usxgmii_submode(struct rtpcs_serdes *sds) u8 sds_id = sds->id; int submode, ret; - if (sds_id < 2 || sds_id > 9) { + if (sds->type != RTPCS_SDS_TYPE_10G) { pr_err("%s: SerDes %u doesn't support USXGMII submode\n", __func__, sds_id); return -ENOTSUPP; } @@ -1475,7 +1488,7 @@ static int __rtpcs_930x_sds_set_usxgmii_submode(struct rtpcs_serdes *sds, u32 su { u8 sds_id = sds->id; - if (sds_id < 2 || sds_id > 9) { + if (sds->type != RTPCS_SDS_TYPE_10G) { pr_err("%s: SerDes %u doesn't support USXGMII submode\n", __func__, sds_id); return -ENOTSUPP; } @@ -2844,7 +2857,7 @@ static int rtpcs_930x_sds_config_hw_mode(struct rtpcs_serdes *sds, enum rtpcs_sd apply_fn = is_xsgmii ? rtpcs_sds_apply_config_xsg : rtpcs_sds_apply_config; if (hw_mode == RTPCS_SDS_MODE_QSGMII) { - if (sds->id >= 2) + if (sds->type != RTPCS_SDS_TYPE_5G) return -ENOTSUPP; return rtpcs_sds_apply_config(sds, rtpcs_930x_sds_cfg_5g_qsgmii, @@ -3036,6 +3049,13 @@ skip_cali: static int rtpcs_930x_sds_probe(struct rtpcs_serdes *sds) { + if (sds->id < 2) + sds->type = RTPCS_SDS_TYPE_5G; + else if (sds->id <= 9) + sds->type = RTPCS_SDS_TYPE_10G; + else + sds->type = RTPCS_SDS_TYPE_UNKNOWN; + return 0; } @@ -3304,7 +3324,7 @@ static void rtpcs_931x_sds_reset(struct rtpcs_serdes *sds) static void rtpcs_931x_sds_rx_reset(struct rtpcs_serdes *sds) { - if (sds->id < 2) + if (sds->type != RTPCS_SDS_TYPE_10G) return; rtpcs_sds_write(sds, 0x2e, 0x12, 0x2740); @@ -3602,7 +3622,7 @@ static int rtpcs_931x_sds_config_tx(struct rtpcs_serdes *sds, { const struct rtpcs_sds_tx_config *tx_cfg; - if (sds->id < 2) + if (sds->type != RTPCS_SDS_TYPE_10G) return 0; switch (sds_media) { @@ -3930,6 +3950,11 @@ static int rtpcs_931x_init_mac_groups(struct rtpcs_ctrl *ctrl) static int rtpcs_931x_sds_probe(struct rtpcs_serdes *sds) { + if (sds->id >= 2) + sds->type = RTPCS_SDS_TYPE_10G; + else + sds->type = RTPCS_SDS_TYPE_UNKNOWN; + return 0; }