[openwrt/openwrt] kernel: rtl8261n: add support for Serdes TX swap

LEDE Commits lede-commits at lists.infradead.org
Mon Sep 29 03:00:28 PDT 2025


ansuel pushed a commit to openwrt/openwrt.git, branch main:
https://git.openwrt.org/ddb0cd276cff667267c10e13d5ad0506e9d4ec22

commit ddb0cd276cff667267c10e13d5ad0506e9d4ec22
Author: Christian Marangi <ansuelsmth at gmail.com>
AuthorDate: Sun Sep 28 20:24:28 2025 +0200

    kernel: rtl8261n: add support for Serdes TX swap
    
    Add support for swapping the Serdes TX line on RTL8261N PHYs.
    This is used on an Arcadyan Mozart board where the Serdes TX is swapped
    on the PHY (instead of on the Soc) to permit support of SFP module by
    using toggling the integrated MUX.
    
    Link: https://github.com/openwrt/openwrt/pull/20227
    Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
---
 .../linux/generic/files/drivers/net/phy/rtl8261n/rtk_phy.c  | 13 +++++++++++++
 .../generic/files/drivers/net/phy/rtl8261n/rtk_phylib.h     |  4 ++++
 2 files changed, 17 insertions(+)

diff --git a/target/linux/generic/files/drivers/net/phy/rtl8261n/rtk_phy.c b/target/linux/generic/files/drivers/net/phy/rtl8261n/rtk_phy.c
index 23916a89ef..7d2a38740d 100644
--- a/target/linux/generic/files/drivers/net/phy/rtl8261n/rtk_phy.c
+++ b/target/linux/generic/files/drivers/net/phy/rtl8261n/rtk_phy.c
@@ -6,6 +6,7 @@
 
 #include <linux/module.h>
 #include <linux/phy.h>
+#include <linux/property.h>
 
 #include "phy_rtl826xb_patch.h"
 #include "rtk_phylib_rtl826xb.h"
@@ -15,6 +16,10 @@
 #define REALTEK_PHY_ID_RTL8264B         0x001CC813
 #define REALTEK_PHY_ID_RTL8264          0x001CCAF2
 
+#define REALTEK_SERDES_GLOBAL_CFG       0x1c
+#define   REALTEK_HSO_INV               BIT(7)
+#define   REALTEK_HSI_INV               BIT(6)
+
 static int rtl826xb_get_features(struct phy_device *phydev)
 {
     int ret;
@@ -41,6 +46,7 @@ static int rtl826xb_get_features(struct phy_device *phydev)
 
 static int rtl826xb_probe(struct phy_device *phydev)
 {
+    struct device *dev = &phydev->mdio.dev;
     struct rtk_phy_priv *priv = NULL;
 
     priv = devm_kzalloc(&phydev->mdio.dev, sizeof(struct rtk_phy_priv), GFP_KERNEL);
@@ -55,6 +61,7 @@ static int rtl826xb_probe(struct phy_device *phydev)
 
     priv->phytype = (phydev->drv->phy_id == REALTEK_PHY_ID_RTL8261N) ? (RTK_PHYLIB_RTL8261N) : (RTK_PHYLIB_RTL8264B);
     priv->isBasePort = (phydev->drv->phy_id == REALTEK_PHY_ID_RTL8261N) ? (1) : (((phydev->mdio.addr % 4) == 0) ? (1) : (0));
+    priv->pnswap_tx = device_property_read_bool(dev, "realtek,pnswap-tx");
     phydev->priv = priv;
 
     return 0;
@@ -62,6 +69,7 @@ static int rtl826xb_probe(struct phy_device *phydev)
 
 static int rtkphy_config_init(struct phy_device *phydev)
 {
+    struct rtk_phy_priv *priv = phydev->priv;
     int ret = 0;
     switch (phydev->drv->phy_id)
     {
@@ -117,6 +125,11 @@ static int rtkphy_config_init(struct phy_device *phydev)
             }
           #endif
 
+            if (priv->pnswap_tx)
+                phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
+                                 REALTEK_SERDES_GLOBAL_CFG,
+                                 REALTEK_HSO_INV);
+
             break;
         default:
             phydev_err(phydev, "%s:%u Unknow phy_id: 0x%X\n", __FUNCTION__, __LINE__, phydev->drv->phy_id);
diff --git a/target/linux/generic/files/drivers/net/phy/rtl8261n/rtk_phylib.h b/target/linux/generic/files/drivers/net/phy/rtl8261n/rtk_phylib.h
index 70eb8e48ed..c94e9cb966 100644
--- a/target/linux/generic/files/drivers/net/phy/rtl8261n/rtk_phylib.h
+++ b/target/linux/generic/files/drivers/net/phy/rtl8261n/rtk_phylib.h
@@ -8,6 +8,8 @@
 #define __RTK_PHYLIB_H
 
 #if defined(RTK_PHYDRV_IN_LINUX)
+  #include <linux/types.h>
+
   #include "type.h"
   #include "rtk_phylib_def.h"
 #else
@@ -48,6 +50,8 @@ struct rtk_phy_priv {
     rtk_phylib_phy_t phytype;
     uint8 isBasePort;
     rt_phy_patch_db_t *patch;
+
+    bool pnswap_tx;
 };
 
 #if defined(RTK_PHYDRV_IN_LINUX)




More information about the lede-commits mailing list