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@gmail.com>
This commit is contained in:
Christian Marangi 2025-09-28 20:24:28 +02:00
parent 0147d213ff
commit ddb0cd276c
No known key found for this signature in database
GPG Key ID: AC001D09ADBFEAD7
2 changed files with 17 additions and 0 deletions

View File

@ -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);

View File

@ -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)