From: Jonas Jelonek Date: Thu, 13 Nov 2025 11:25:44 +0000 (+0000) Subject: realtek: pcs: rtl93xx: fix SerDes polarity configuration for RTL931X X-Git-Url: http://git.openwrt.org/?a=commitdiff_plain;h=203b8886bd6f6abc73ec0c861fba3cf4adfec918;p=openwrt%2Fstaging%2Fxback.git 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 Link: https://github.com/openwrt/openwrt/pull/20767 Signed-off-by: Robert Marko --- 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);