realtek: pcs: allow to configure SerDes polarity
authorJonas Jelonek <[email protected]>
Tue, 28 Oct 2025 22:18:34 +0000 (22:18 +0000)
committerHauke Mehrtens <[email protected]>
Sun, 9 Nov 2025 16:48:10 +0000 (17:48 +0100)
Allow to configure SerDes polarity in device tree. To achieve this, add
new device tree properties that can be set in the device tree definition
of the SerDes, are read by the PCS driver during probe and are applied
upon SerDes setup.

This may be required for supporting new devices as the SerDes polarity
is usually subject to the vendors board design and defined in the
hardware profile (HWP) in the SDK. Most importantly, it is quite an
important step towards being able to setup everything on our own instead
of relying on the bootloader.

Signed-off-by: Jonas Jelonek <[email protected]>
Link: https://github.com/openwrt/openwrt/pull/20648
Signed-off-by: Hauke Mehrtens <[email protected]>
target/linux/realtek/files-6.12/drivers/net/pcs/pcs-rtl-otto.c

index bad34c046b15521bd7ef701a0fe637e2eee40852..50addac503199eae5d0bb0203c5bebc8eb450844 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/phylink.h>
 #include <linux/regmap.h>
 
+#define RTPCS_SDS_CNT                          14
 #define RTPCS_PORT_CNT                         57
 
 #define RTPCS_SPEED_10                         0
@@ -100,6 +101,8 @@ struct rtpcs_ctrl {
        struct mii_bus *bus;
        const struct rtpcs_config *cfg;
        struct rtpcs_link *link[RTPCS_PORT_CNT];
+       bool rx_pol_inv[RTPCS_SDS_CNT];
+       bool tx_pol_inv[RTPCS_SDS_CNT];
        struct mutex lock;
 };
 
@@ -1914,7 +1917,8 @@ 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, false, false);
+       rtpcs_93xx_sds_set_polarity(ctrl, sds, ctrl->tx_pol_inv[sds],
+                                   ctrl->rx_pol_inv[sds]);
 
        /* Enable SDS in desired mode */
        rtpcs_930x_sds_mode_set(ctrl, sds, phy_mode);
@@ -2493,7 +2497,8 @@ static int rtpcs_931x_setup_serdes(struct rtpcs_ctrl *ctrl, int sds,
                }
        }
 
-       rtpcs_93xx_sds_set_polarity(ctrl, sds, false, false);
+       rtpcs_93xx_sds_set_polarity(ctrl, sds, ctrl->tx_pol_inv[sds],
+                                   ctrl->rx_pol_inv[sds]);
 
        val = ori & ~BIT(sds);
        regmap_write(ctrl->map, RTL931X_PS_SERDES_OFF_MODE_CTRL_ADDR, val);
@@ -2729,7 +2734,10 @@ static int rtpcs_probe(struct platform_device *pdev)
 {
        struct device_node *np = pdev->dev.of_node;
        struct device *dev = &pdev->dev;
+       struct device_node *child;
        struct rtpcs_ctrl *ctrl;
+       u32 sds;
+       int ret;
 
        ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL);
        if (!ctrl)
@@ -2746,6 +2754,18 @@ static int rtpcs_probe(struct platform_device *pdev)
        ctrl->bus = rtpcs_probe_serdes_bus(ctrl);
        if (IS_ERR(ctrl->bus))
                return PTR_ERR(ctrl->bus);
+
+       for_each_child_of_node(dev->of_node, child) {
+               ret = of_property_read_u32(child, "reg", &sds);
+               if (ret)
+                       return ret;
+               if (sds >= RTPCS_SDS_CNT)
+                       return -EINVAL;
+
+               ctrl->rx_pol_inv[sds] = of_property_read_bool(child, "realtek,pnswap-rx");
+               ctrl->tx_pol_inv[sds] = of_property_read_bool(child, "realtek,pnswap-tx");
+       }
+
        /*
         * rtpcs_create() relies on that fact that data is attached to the platform device to
         * determine if the driver is ready. Do this after everything is initialized properly.