]> git.ipfire.org Git - thirdparty/openwrt.git/commitdiff
realtek: pcs: replace various SerDes range checks 22941/head
authorJonas Jelonek <jelonek.jonas@gmail.com>
Wed, 15 Apr 2026 09:05:16 +0000 (09:05 +0000)
committerRobert Marko <robimarko@gmail.com>
Mon, 20 Apr 2026 09:10:54 +0000 (11:10 +0200)
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 <jelonek.jonas@gmail.com>
Link: https://github.com/openwrt/openwrt/pull/22941
Signed-off-by: Robert Marko <robimarko@gmail.com>
target/linux/realtek/files-6.18/drivers/net/pcs/pcs-rtl-otto.c

index 02cd0b70f3471a850b460b51c8b7163e7c8d84ba..c8429b45961be0bad24e8245ba7ec0620fddf486 100644 (file)
 #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;
 }