[openwrt/openwrt] realtek: pcs: rtl93xx: fix SerDes polarity configuration for RTL931X

LEDE Commits lede-commits at lists.infradead.org
Sat Nov 15 02:16:23 PST 2025


robimarko pushed a commit to openwrt/openwrt.git, branch main:
https://git.openwrt.org/203b8886bd6f6abc73ec0c861fba3cf4adfec918

commit 203b8886bd6f6abc73ec0c861fba3cf4adfec918
Author: Jonas Jelonek <jelonek.jonas at gmail.com>
AuthorDate: Thu Nov 13 11:25:44 2025 +0000

    realtek: pcs: rtl93xx: fix SerDes polarity configuration for RTL931X
    
    Commit 56e9a73d0b added support for configuring the SerDes polarity for
    both RTL930X and RTL931X. Based on the code in the Realtek SDK in [1]
    and [2], in both cases the same register bits are set. Thus, a common
    implementation was provided which worked with e.g. USXGMII or 10GBase-R
    configured SerDes.
    
    However, after further tests, a strange issue occured where it didn't
    work that well for all SerDes configurations. While running fine for
    10GBase-R links on two adjacent SerDes, it didn't for 1000Base-X links
    on one of two adjacent SerDes with the link not being detected as a
    symptom.
    
    Diving into the SDK again revealed that the referenced implementation of
    polarity configuration is (by accident or by purpose) misleading. While
    [1] and [3] for RTL930X match, [2] and [4] for RTL931X actually don't.
    [4] writes the bits for the 1G polarity setting on different background
    SerDes, thus in another frontend page.
    
    Split implementations for RTL930X and RTL931X again and adjust the one
    for RTL931X according to [4]. This resolves the issues with 1000Base-X
    behavior.
    
    [1] https://github.com/plappermaul/realtek-doc/blob/69d2890a2e2d7a03df6e40e2cd2c32ff5b074dcf/sources/rtk-xgs1210/src/hal/phy/phy_rtl9300.c#L1384
    [2] https://github.com/plappermaul/realtek-doc/blob/69d2890a2e2d7a03df6e40e2cd2c32ff5b074dcf/sources/rtk-xgs1210/src/hal/phy/phy_rtl9310.c#L3479
    [3] https://github.com/plappermaul/realtek-doc/blob/69d2890a2e2d7a03df6e40e2cd2c32ff5b074dcf/sources/rtk-xgs1210/src/dal/longan/dal_longan_construct.c#L2246
    [4] https://github.com/plappermaul/realtek-doc/blob/69d2890a2e2d7a03df6e40e2cd2c32ff5b074dcf/sources/rtk-xgs1210/src/dal/mango/dal_mango_construct.c#L1550
    
    Fixes: 56e9a73d0b ("realtek: pcs: rtl93xx: provide proper SerDes polarity
    configuration")
    Signed-off-by: Jonas Jelonek <jelonek.jonas at gmail.com>
    Link: https://github.com/openwrt/openwrt/pull/20767
    Signed-off-by: Robert Marko <robimarko at gmail.com>
---
 .../files-6.12/drivers/net/pcs/pcs-rtl-otto.c      | 67 ++++++++++++++--------
 1 file changed, 44 insertions(+), 23 deletions(-)

diff --git a/target/linux/realtek/files-6.12/drivers/net/pcs/pcs-rtl-otto.c b/target/linux/realtek/files-6.12/drivers/net/pcs/pcs-rtl-otto.c
index 50addac503..57d6ed9899 100644
--- a/target/linux/realtek/files-6.12/drivers/net/pcs/pcs-rtl-otto.c
+++ b/target/linux/realtek/files-6.12/drivers/net/pcs/pcs-rtl-otto.c
@@ -213,27 +213,6 @@ static struct rtpcs_link *rtpcs_phylink_pcs_to_link(struct phylink_pcs *pcs)
 
 /* Variant-specific functions */
 
-/* RTL93XX */
-
-static int rtpcs_93xx_sds_set_polarity(struct rtpcs_ctrl *ctrl, u32 sds,
-				       bool tx_inv, bool rx_inv)
-{
-	u8 rx_val = rx_inv ? 1 : 0;
-	u8 tx_val = tx_inv ? 1 : 0;
-	u32 val;
-	int ret;
-
-	/* 10GR */
-	val = (tx_val << 1) | rx_val;
-	ret = rtpcs_sds_write_bits(ctrl, sds, 0x6, 0x2, 14, 13, val);
-	if (ret)
-		return ret;
-
-	/* 1G */
-	val = (rx_val << 1) | tx_val;
-	return rtpcs_sds_write_bits(ctrl, sds, 0x0, 0x0, 9, 8, val);
-}
-
 /* RTL930X */
 
 /* The access registers for SDS_MODE_SEL and the LSB for each SDS within */
@@ -1645,6 +1624,25 @@ static int rtpcs_930x_sds_10g_idle(struct rtpcs_ctrl *ctrl, int sds_num)
 	return -EIO;
 }
 
+static int rtpcs_930x_sds_set_polarity(struct rtpcs_ctrl *ctrl, u32 sds,
+				       bool tx_inv, bool rx_inv)
+{
+	u8 rx_val = rx_inv ? 1 : 0;
+	u8 tx_val = tx_inv ? 1 : 0;
+	u32 val;
+	int ret;
+
+	/* 10GR */
+	val = (tx_val << 1) | rx_val;
+	ret = rtpcs_sds_write_bits(ctrl, sds, 0x6, 0x2, 14, 13, val);
+	if (ret)
+		return ret;
+
+	/* 1G */
+	val = (rx_val << 1) | tx_val;
+	return rtpcs_sds_write_bits(ctrl, sds, 0x0, 0x0, 9, 8, val);
+}
+
 static const sds_config rtpcs_930x_sds_cfg_10gr_even[] =
 {
 	/* 1G */
@@ -1917,7 +1915,7 @@ static int rtpcs_930x_setup_serdes(struct rtpcs_ctrl *ctrl, int sds,
 	pr_info("%s: Configuring RTL9300 SERDES %d\n", __func__, sds);
 
 	/* Set SDS polarity */
-	rtpcs_93xx_sds_set_polarity(ctrl, sds, ctrl->tx_pol_inv[sds],
+	rtpcs_930x_sds_set_polarity(ctrl, sds, ctrl->tx_pol_inv[sds],
 				    ctrl->rx_pol_inv[sds]);
 
 	/* Enable SDS in desired mode */
@@ -2275,6 +2273,29 @@ static int rtpcs_931x_sds_link_sts_get(struct rtpcs_ctrl *ctrl, u32 sds)
 	return sts1;
 }
 
+static int rtpcs_931x_sds_set_polarity(struct rtpcs_ctrl *ctrl, u32 sds,
+				       bool tx_inv, bool rx_inv)
+{
+	u8 rx_val = rx_inv ? 1 : 0;
+	u8 tx_val = tx_inv ? 1 : 0;
+	u32 val;
+	int ret;
+
+	/* 10gr_*_inv */
+	val = (tx_val << 1) | rx_val;
+	ret = rtpcs_sds_write_bits(ctrl, sds, 0x6, 0x2, 14, 13, val);
+	if (ret)
+		return ret;
+
+	/* xsg_*_inv */
+	val = (rx_val << 1) | tx_val;
+	ret = rtpcs_sds_write_bits(ctrl, sds, 0x40, 0x0, 9, 8, val);
+	if (ret)
+		return ret;
+
+	return rtpcs_sds_write_bits(ctrl, sds, 0x80, 0x0, 9, 8, val);
+}
+
 static sds_config sds_config_10p3125g_type1[] = {
 	{ 0x2E, 0x00, 0x0107 }, { 0x2E, 0x01, 0x01A3 }, { 0x2E, 0x02, 0x6A24 },
 	{ 0x2E, 0x03, 0xD10D }, { 0x2E, 0x04, 0x8000 }, { 0x2E, 0x05, 0xA17E },
@@ -2497,7 +2518,7 @@ static int rtpcs_931x_setup_serdes(struct rtpcs_ctrl *ctrl, int sds,
 		}
 	}
 
-	rtpcs_93xx_sds_set_polarity(ctrl, sds, ctrl->tx_pol_inv[sds],
+	rtpcs_931x_sds_set_polarity(ctrl, sds, ctrl->tx_pol_inv[sds],
 				    ctrl->rx_pol_inv[sds]);
 
 	val = ori & ~BIT(sds);




More information about the lede-commits mailing list