From a3bfb67072a70e8720326b7e1527d55f8439b54c Mon Sep 17 00:00:00 2001 From: Markus Stockhausen Date: Mon, 21 Jul 2025 08:34:54 -0400 Subject: [PATCH] realtek: mdio: RTL838x: move functions over to bus The mdio bus functions are still split between ethernet and dsa driver. Before moving everthing out to a separate mdio driver we decided to collect everything in the ethernet driver with the rtmdio prefix. Take over the remaining RTL838x functions. Remark: This is more or less a copy/paste with function renaming. As there are still some consumers in the DSA driver the definitions and inclusions must be flipped. Signed-off-by: Markus Stockhausen Link: https://github.com/openwrt/openwrt/pull/19484 Signed-off-by: Hauke Mehrtens --- .../drivers/net/dsa/rtl83xx/common.c | 7 +- .../drivers/net/dsa/rtl83xx/rtl838x.c | 163 ---------------- .../drivers/net/ethernet/rtl838x_eth.c | 180 +++++++++++++++++- .../drivers/net/ethernet/rtl838x_eth.h | 3 + 4 files changed, 179 insertions(+), 174 deletions(-) diff --git a/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/common.c b/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/common.c index 411ee7f5e3f..5c15824d00c 100644 --- a/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/common.c +++ b/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/common.c @@ -29,6 +29,9 @@ extern const struct dsa_switch_ops rtl930x_switch_ops; extern const struct phylink_pcs_ops rtl83xx_pcs_ops; extern const struct phylink_pcs_ops rtl93xx_pcs_ops; +extern int rtmdio_838x_read_phy(u32 port, u32 page, u32 reg, u32 *val); +extern int rtmdio_838x_write_phy(u32 port, u32 page, u32 reg, u32 val); + DEFINE_MUTEX(smi_lock); int rtl83xx_port_get_stp_state(struct rtl838x_switch_priv *priv, int port) @@ -244,7 +247,7 @@ int read_phy(u32 port, u32 page, u32 reg, u32 *val) { switch (soc_info.family) { case RTL8380_FAMILY_ID: - return rtl838x_read_phy(port, page, reg, val); + return rtmdio_838x_read_phy(port, page, reg, val); case RTL8390_FAMILY_ID: return rtl839x_read_phy(port, page, reg, val); case RTL9300_FAMILY_ID: @@ -260,7 +263,7 @@ int write_phy(u32 port, u32 page, u32 reg, u32 val) { switch (soc_info.family) { case RTL8380_FAMILY_ID: - return rtl838x_write_phy(port, page, reg, val); + return rtmdio_838x_write_phy(port, page, reg, val); case RTL8390_FAMILY_ID: return rtl839x_write_phy(port, page, reg, val); case RTL9300_FAMILY_ID: diff --git a/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl838x.c b/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl838x.c index fafdca62166..ac4b9623181 100644 --- a/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl838x.c +++ b/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl838x.c @@ -1768,169 +1768,6 @@ irqreturn_t rtl838x_switch_irq(int irq, void *dev_id) return IRQ_HANDLED; } -int rtl838x_smi_wait_op(int timeout) -{ - int ret = 0; - u32 val; - - ret = readx_poll_timeout(sw_r32, RTL838X_SMI_ACCESS_PHY_CTRL_1, - val, !(val & 0x1), 20, timeout); - if (ret) - pr_err("%s: timeout\n", __func__); - - return ret; -} - -/* Reads a register in a page from the PHY */ -int rtl838x_read_phy(u32 port, u32 page, u32 reg, u32 *val) -{ - u32 v, park_page = 0x1f << 15; - int err; - - if (port > 31) { - *val = 0xffff; - return 0; - } - - if (page > 4095 || reg > 31) - return -ENOTSUPP; - - mutex_lock(&smi_lock); - - err = rtl838x_smi_wait_op(100000); - if (err) - goto errout; - - sw_w32_mask(0xffff0000, port << 16, RTL838X_SMI_ACCESS_PHY_CTRL_2); - - v = reg << 20 | page << 3; - sw_w32(v | park_page, RTL838X_SMI_ACCESS_PHY_CTRL_1); - sw_w32_mask(0, 1, RTL838X_SMI_ACCESS_PHY_CTRL_1); - - err = rtl838x_smi_wait_op(100000); - if (err) - goto errout; - - *val = sw_r32(RTL838X_SMI_ACCESS_PHY_CTRL_2) & 0xffff; - - err = 0; - -errout: - mutex_unlock(&smi_lock); - - return err; -} - -/* Write to a register in a page of the PHY */ -int rtl838x_write_phy(u32 port, u32 page, u32 reg, u32 val) -{ - u32 v, park_page = 0x1f << 15; - int err; - - val &= 0xffff; - if (port > 31 || page > 4095 || reg > 31) - return -ENOTSUPP; - - mutex_lock(&smi_lock); - err = rtl838x_smi_wait_op(100000); - if (err) - goto errout; - - sw_w32(BIT(port), RTL838X_SMI_ACCESS_PHY_CTRL_0); - mdelay(10); - - sw_w32_mask(0xffff0000, val << 16, RTL838X_SMI_ACCESS_PHY_CTRL_2); - - v = reg << 20 | page << 3 | 0x4; - sw_w32(v | park_page, RTL838X_SMI_ACCESS_PHY_CTRL_1); - sw_w32_mask(0, 1, RTL838X_SMI_ACCESS_PHY_CTRL_1); - - err = rtl838x_smi_wait_op(100000); - if (err) - goto errout; - - err = 0; - -errout: - mutex_unlock(&smi_lock); - - return err; -} - -/* Read an mmd register of a PHY */ -int rtl838x_read_mmd_phy(u32 port, u32 addr, u32 reg, u32 *val) -{ - int err; - u32 v; - - mutex_lock(&smi_lock); - - err = rtl838x_smi_wait_op(100000); - if (err) - goto errout; - - sw_w32(1 << port, RTL838X_SMI_ACCESS_PHY_CTRL_0); - mdelay(10); - - sw_w32_mask(0xffff0000, port << 16, RTL838X_SMI_ACCESS_PHY_CTRL_2); - - v = addr << 16 | reg; - sw_w32(v, RTL838X_SMI_ACCESS_PHY_CTRL_3); - - /* mmd-access | read | cmd-start */ - v = 1 << 1 | 0 << 2 | 1; - sw_w32(v, RTL838X_SMI_ACCESS_PHY_CTRL_1); - - err = rtl838x_smi_wait_op(100000); - if (err) - goto errout; - - *val = sw_r32(RTL838X_SMI_ACCESS_PHY_CTRL_2) & 0xffff; - - err = 0; - -errout: - mutex_unlock(&smi_lock); - - return err; -} - -/* Write to an mmd register of a PHY */ -int rtl838x_write_mmd_phy(u32 port, u32 addr, u32 reg, u32 val) -{ - int err; - u32 v; - - pr_debug("MMD write: port %d, dev %d, reg %d, val %x\n", port, addr, reg, val); - val &= 0xffff; - mutex_lock(&smi_lock); - - err = rtl838x_smi_wait_op(100000); - if (err) - goto errout; - - sw_w32(1 << port, RTL838X_SMI_ACCESS_PHY_CTRL_0); - mdelay(10); - - sw_w32_mask(0xffff0000, val << 16, RTL838X_SMI_ACCESS_PHY_CTRL_2); - - sw_w32_mask(0x1f << 16, addr << 16, RTL838X_SMI_ACCESS_PHY_CTRL_3); - sw_w32_mask(0xffff, reg, RTL838X_SMI_ACCESS_PHY_CTRL_3); - /* mmd-access | write | cmd-start */ - v = 1 << 1 | 1 << 2 | 1; - sw_w32(v, RTL838X_SMI_ACCESS_PHY_CTRL_1); - - err = rtl838x_smi_wait_op(100000); - if (err) - goto errout; - - err = 0; - -errout: - mutex_unlock(&smi_lock); - return err; -} - void rtl8380_get_version(struct rtl838x_switch_priv *priv) { u32 rw_save, info_save; diff --git a/target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.c b/target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.c index 91577ac7668..5c6d79d19b5 100644 --- a/target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.c +++ b/target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.c @@ -27,11 +27,6 @@ extern struct rtl83xx_soc_info soc_info; extern int rtl83xx_setup_tc(struct net_device *dev, enum tc_setup_type type, void *type_data); -extern int rtl838x_read_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 *val); -extern int rtl838x_read_phy(u32 port, u32 page, u32 reg, u32 *val); -extern int rtl838x_write_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 val); -extern int rtl838x_write_phy(u32 port, u32 page, u32 reg, u32 val); - extern int rtl839x_read_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 *val); extern int rtl839x_read_phy(u32 port, u32 page, u32 reg, u32 *val); extern int rtl839x_read_sds_phy(int phy_addr, int phy_reg); @@ -1640,6 +1635,8 @@ static int rtl838x_set_link_ksettings(struct net_device *ndev, * reimplemented. For now it should be sufficient. */ +DEFINE_MUTEX(rtmdio_lock); + struct rtmdio_bus_priv { u16 id; u16 family_id; @@ -1769,6 +1766,171 @@ static int rtmdio_838x_write_sds(int addr, int regnum, u16 val) return 0; } +/* RTL838x specific MDIO functions */ + +static int rtmdio_838x_smi_wait_op(int timeout) +{ + int ret = 0; + u32 val; + + ret = readx_poll_timeout(sw_r32, RTL838X_SMI_ACCESS_PHY_CTRL_1, + val, !(val & 0x1), 20, timeout); + if (ret) + pr_err("%s: timeout\n", __func__); + + return ret; +} + +/* Reads a register in a page from the PHY */ +int rtmdio_838x_read_phy(u32 port, u32 page, u32 reg, u32 *val) +{ + u32 v, park_page = 0x1f << 15; + int err; + + if (port > 31) { + *val = 0xffff; + return 0; + } + + if (page > 4095 || reg > 31) + return -ENOTSUPP; + + mutex_lock(&rtmdio_lock); + + err = rtmdio_838x_smi_wait_op(100000); + if (err) + goto errout; + + sw_w32_mask(0xffff0000, port << 16, RTL838X_SMI_ACCESS_PHY_CTRL_2); + + v = reg << 20 | page << 3; + sw_w32(v | park_page, RTL838X_SMI_ACCESS_PHY_CTRL_1); + sw_w32_mask(0, 1, RTL838X_SMI_ACCESS_PHY_CTRL_1); + + err = rtmdio_838x_smi_wait_op(100000); + if (err) + goto errout; + + *val = sw_r32(RTL838X_SMI_ACCESS_PHY_CTRL_2) & 0xffff; + + err = 0; + +errout: + mutex_unlock(&rtmdio_lock); + + return err; +} + +/* Write to a register in a page of the PHY */ +int rtmdio_838x_write_phy(u32 port, u32 page, u32 reg, u32 val) +{ + u32 v, park_page = 0x1f << 15; + int err; + + val &= 0xffff; + if (port > 31 || page > 4095 || reg > 31) + return -ENOTSUPP; + + mutex_lock(&rtmdio_lock); + err = rtmdio_838x_smi_wait_op(100000); + if (err) + goto errout; + + sw_w32(BIT(port), RTL838X_SMI_ACCESS_PHY_CTRL_0); + mdelay(10); + + sw_w32_mask(0xffff0000, val << 16, RTL838X_SMI_ACCESS_PHY_CTRL_2); + + v = reg << 20 | page << 3 | 0x4; + sw_w32(v | park_page, RTL838X_SMI_ACCESS_PHY_CTRL_1); + sw_w32_mask(0, 1, RTL838X_SMI_ACCESS_PHY_CTRL_1); + + err = rtmdio_838x_smi_wait_op(100000); + if (err) + goto errout; + + err = 0; + +errout: + mutex_unlock(&rtmdio_lock); + + return err; +} + +/* Read an mmd register of a PHY */ +static int rtmdio_838x_read_mmd_phy(u32 port, u32 addr, u32 reg, u32 *val) +{ + int err; + u32 v; + + mutex_lock(&rtmdio_lock); + + err = rtmdio_838x_smi_wait_op(100000); + if (err) + goto errout; + + sw_w32(1 << port, RTL838X_SMI_ACCESS_PHY_CTRL_0); + mdelay(10); + + sw_w32_mask(0xffff0000, port << 16, RTL838X_SMI_ACCESS_PHY_CTRL_2); + + v = addr << 16 | reg; + sw_w32(v, RTL838X_SMI_ACCESS_PHY_CTRL_3); + + /* mmd-access | read | cmd-start */ + v = 1 << 1 | 0 << 2 | 1; + sw_w32(v, RTL838X_SMI_ACCESS_PHY_CTRL_1); + + err = rtmdio_838x_smi_wait_op(100000); + if (err) + goto errout; + + *val = sw_r32(RTL838X_SMI_ACCESS_PHY_CTRL_2) & 0xffff; + + err = 0; + +errout: + mutex_unlock(&rtmdio_lock); + + return err; +} + +/* Write to an mmd register of a PHY */ +static int rtmdio_838x_write_mmd_phy(u32 port, u32 addr, u32 reg, u32 val) +{ + int err; + u32 v; + + pr_debug("MMD write: port %d, dev %d, reg %d, val %x\n", port, addr, reg, val); + val &= 0xffff; + mutex_lock(&rtmdio_lock); + + err = rtmdio_838x_smi_wait_op(100000); + if (err) + goto errout; + + sw_w32(1 << port, RTL838X_SMI_ACCESS_PHY_CTRL_0); + mdelay(10); + + sw_w32_mask(0xffff0000, val << 16, RTL838X_SMI_ACCESS_PHY_CTRL_2); + + sw_w32_mask(0x1f << 16, addr << 16, RTL838X_SMI_ACCESS_PHY_CTRL_3); + sw_w32_mask(0xffff, reg, RTL838X_SMI_ACCESS_PHY_CTRL_3); + /* mmd-access | write | cmd-start */ + v = 1 << 1 | 1 << 2 | 1; + sw_w32(v, RTL838X_SMI_ACCESS_PHY_CTRL_1); + + err = rtmdio_838x_smi_wait_op(100000); + if (err) + goto errout; + + err = 0; + +errout: + mutex_unlock(&rtmdio_lock); + return err; +} + /* These are the core functions of our new Realtek SoC MDIO bus. */ static int rtmdio_read_c45(struct mii_bus *bus, int addr, int devnum, int regnum) @@ -2215,10 +2377,10 @@ static int rtl838x_mdio_init(struct rtl838x_eth_priv *priv) priv->mii_bus->read = rtmdio_83xx_read; priv->mii_bus->write = rtmdio_83xx_write; priv->mii_bus->reset = rtmdio_838x_reset; - bus_priv->read_mmd_phy = rtl838x_read_mmd_phy; - bus_priv->write_mmd_phy = rtl838x_write_mmd_phy; - bus_priv->read_phy = rtl838x_read_phy; - bus_priv->write_phy = rtl838x_write_phy; + bus_priv->read_mmd_phy = rtmdio_838x_read_mmd_phy; + bus_priv->write_mmd_phy = rtmdio_838x_write_mmd_phy; + bus_priv->read_phy = rtmdio_838x_read_phy; + bus_priv->write_phy = rtmdio_838x_write_phy; bus_priv->cpu_port = RTL838X_CPU_PORT; bus_priv->rawpage = 0xfff; break; diff --git a/target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.h b/target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.h index e899467d133..720c22fdd39 100644 --- a/target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.h +++ b/target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.h @@ -453,4 +453,7 @@ int phy_package_write_paged(struct phy_device *phydev, int page, u32 regnum, u16 int phy_port_read_paged(struct phy_device *phydev, int port, int page, u32 regnum); int phy_port_write_paged(struct phy_device *phydev, int port, int page, u32 regnum, u16 val); +int rtmdio_838x_read_phy(u32 port, u32 page, u32 reg, u32 *val); +int rtmdio_838x_write_phy(u32 port, u32 page, u32 reg, u32 val); + #endif /* _RTL838X_ETH_H */ -- 2.47.2