[RFC PATCH 1/5] net: mediatek: move MT7531 mdio to dedicated driver

Christian Marangi ansuelsmth at gmail.com
Sat Aug 23 01:29:15 CEST 2025


In preparation for support of MDIO on AN7581, move the MT7531 logic to a
dedicated driver and permit usage of the mdio read/write function to the
mtk_eth driver.

Minor changes are required to mtk_eth for this change as the dedicated
MDIO driver only needs info of the GSW register and nothing else.

This permits Airoha driver to make use of DM_MDIO to bind for the MT7531
driver that have the same exact register.

Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
---
 drivers/net/Kconfig          |   3 +
 drivers/net/Makefile         |   4 +
 drivers/net/mdio-mt7531.c    | 140 +++++++++++++++++++++++++++++++++++
 drivers/net/mdio-mt7531.h    |   9 +++
 drivers/net/mtk_eth/Kconfig  |   1 +
 drivers/net/mtk_eth/mt753x.c |  29 +++-----
 drivers/net/mtk_eth/mt753x.h |   3 +
 7 files changed, 169 insertions(+), 20 deletions(-)
 create mode 100644 drivers/net/mdio-mt7531.c
 create mode 100644 drivers/net/mdio-mt7531.h

diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index d1cb69f85ad..9ac9bee46c9 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -966,6 +966,9 @@ config TSEC_ENET
 	  This driver implements support for the (Enhanced) Three-Speed
 	  Ethernet Controller found on Freescale SoCs.
 
+config MDIO_MT7531
+	bool
+
 source "drivers/net/mtk_eth/Kconfig"
 
 config HIFEMAC_ETH
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index f8f9a71f815..beb7864adc2 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -62,7 +62,11 @@ obj-$(CONFIG_LITEETH) += liteeth.o
 obj-$(CONFIG_MACB) += macb.o
 obj-$(CONFIG_MCFFEC) += mcffec.o mcfmii.o
 obj-$(CONFIG_MDIO_IPQ4019) += mdio-ipq4019.o
+<<<<<<< HEAD
 obj-$(CONFIG_MDIO_GPIO_BITBANG) += mdio_gpio.o
+=======
+obj-$(CONFIG_MDIO_MT7531) += mdio-mt7531.o
+>>>>>>> net: mediatek: move MT7531 mdio to dedicated driver
 obj-$(CONFIG_MDIO_MUX_I2CREG) += mdio_mux_i2creg.o
 obj-$(CONFIG_MDIO_MUX_MESON_G12A) += mdio_mux_meson_g12a.o
 obj-$(CONFIG_MDIO_MUX_MESON_GXL) += mdio_mux_meson_gxl.o
diff --git a/drivers/net/mdio-mt7531.c b/drivers/net/mdio-mt7531.c
new file mode 100644
index 00000000000..4772c9b5407
--- /dev/null
+++ b/drivers/net/mdio-mt7531.c
@@ -0,0 +1,140 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include <asm/io.h>
+#include <dm.h>
+#include <linux/bitfield.h>
+#include <linux/iopoll.h>
+#include <miiphy.h>
+
+#define MT7531_PHY_IAC			0x701c
+#define   MT7531_PHY_ACS_ST		BIT(31)
+#define   MT7531_MDIO_REG_ADDR_CL22	GENMASK(29, 25)
+#define   MT7531_MDIO_DEV_ADDR		MT7531_MDIO_REG_ADDR_CL22
+#define   MT7531_MDIO_PHY_ADDR		GENMASK(24, 20)
+#define   MT7531_MDIO_CMD		GENMASK(19, 18)
+#define   MT7531_MDIO_CMD_READ_CL45	FIELD_PREP_CONST(MT7531_MDIO_CMD, 0x3)
+#define   MT7531_MDIO_CMD_READ_CL22	FIELD_PREP_CONST(MT7531_MDIO_CMD, 0x2)
+#define   MT7531_MDIO_CMD_WRITE		FIELD_PREP_CONST(MT7531_MDIO_CMD, 0x1)
+#define   MT7531_MDIO_CMD_ADDR		FIELD_PREP_CONST(MT7531_MDIO_CMD, 0x0)
+#define   MT7531_MDIO_ST		GENMASK(17, 16)
+#define   MT7531_MDIO_ST_CL22		FIELD_PREP_CONST(MT7531_MDIO_ST, 0x1)
+#define   MT7531_MDIO_ST_CL45		FIELD_PREP_CONST(MT7531_MDIO_ST, 0x0)
+#define   MT7531_MDIO_RW_DATA		GENMASK(15, 0)
+#define   MT7531_MDIO_REG_ADDR_CL45	MT7531_MDIO_RW_DATA
+
+#define MT7531_MDIO_TIMEOUT		100000
+#define MT7531_MDIO_SLEEP		20
+
+struct mt7531_mdio_priv {
+	phys_addr_t switch_regs;
+};
+
+static int mt7531_mdio_wait_busy(struct mt7531_mdio_priv *priv)
+{
+	unsigned int busy;
+
+	return readl_poll_sleep_timeout(priv->switch_regs + MT7531_PHY_IAC,
+					busy, (busy & MT7531_PHY_ACS_ST) == 0,
+					MT7531_MDIO_SLEEP, MT7531_MDIO_TIMEOUT);
+}
+
+int mt7531_mdio_read(struct udevice *dev, int addr, int devad, int reg)
+{
+	struct mt7531_mdio_priv *priv = dev_get_priv(dev);
+	u32 val;
+
+	if (devad != MDIO_DEVAD_NONE) {
+		if (mt7531_mdio_wait_busy(priv))
+			return -ETIMEDOUT;
+
+		val = MT7531_PHY_ACS_ST |
+		      MT7531_MDIO_ST_CL45 | MT7531_MDIO_CMD_ADDR |
+		      FIELD_PREP(MT7531_MDIO_PHY_ADDR, addr) |
+		      FIELD_PREP(MT7531_MDIO_DEV_ADDR, devad) |
+		      FIELD_PREP(MT7531_MDIO_REG_ADDR_CL45, reg);
+
+		writel(val, priv->switch_regs + MT7531_PHY_IAC);
+	}
+
+	if (mt7531_mdio_wait_busy(priv))
+		return -ETIMEDOUT;
+
+	val = MT7531_PHY_ACS_ST | FIELD_PREP(MT7531_MDIO_PHY_ADDR, addr);
+	if (devad != MDIO_DEVAD_NONE)
+		val |= MT7531_MDIO_ST_CL45 | MT7531_MDIO_CMD_READ_CL45 |
+		       FIELD_PREP(MT7531_MDIO_DEV_ADDR, devad);
+	else
+		val |= MT7531_MDIO_ST_CL22 | MT7531_MDIO_CMD_READ_CL22 |
+		       FIELD_PREP(MT7531_MDIO_REG_ADDR_CL22, reg);
+
+	writel(val, priv->switch_regs + MT7531_PHY_IAC);
+
+	if (mt7531_mdio_wait_busy(priv))
+		return -ETIMEDOUT;
+
+	val = readl(priv->switch_regs + MT7531_PHY_IAC);
+	return val & MT7531_MDIO_RW_DATA;
+}
+
+int mt7531_mdio_write(struct udevice *dev, int addr, int devad,
+		      int reg, u16 value)
+{
+	struct mt7531_mdio_priv *priv = dev_get_priv(dev);
+	u32 val;
+
+	if (devad != MDIO_DEVAD_NONE) {
+		if (mt7531_mdio_wait_busy(priv))
+			return -ETIMEDOUT;
+
+		val = MT7531_PHY_ACS_ST |
+		      MT7531_MDIO_ST_CL45 | MT7531_MDIO_CMD_ADDR |
+		      FIELD_PREP(MT7531_MDIO_PHY_ADDR, addr) |
+		      FIELD_PREP(MT7531_MDIO_DEV_ADDR, devad) |
+		      FIELD_PREP(MT7531_MDIO_REG_ADDR_CL45, reg);
+
+		writel(val, priv->switch_regs + MT7531_PHY_IAC);
+	}
+
+	if (mt7531_mdio_wait_busy(priv))
+		return -ETIMEDOUT;
+
+	val = MT7531_PHY_ACS_ST | FIELD_PREP(MT7531_MDIO_PHY_ADDR, addr) |
+	      MT7531_MDIO_CMD_WRITE | FIELD_PREP(MT7531_MDIO_RW_DATA, value);
+	if (devad != MDIO_DEVAD_NONE)
+		val |= MT7531_MDIO_ST_CL45 |
+		       FIELD_PREP(MT7531_MDIO_DEV_ADDR, devad);
+	else
+		val |= MT7531_MDIO_ST_CL22 |
+		       FIELD_PREP(MT7531_MDIO_REG_ADDR_CL22, reg);
+
+	writel(val, priv->switch_regs + MT7531_PHY_IAC);
+
+	if (mt7531_mdio_wait_busy(priv))
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
+static const struct mdio_ops mt7531_mdio_ops = {
+	.read = mt7531_mdio_read,
+	.write = mt7531_mdio_write,
+};
+
+static int mt7531_mdio_probe(struct udevice *dev)
+{
+	struct mt7531_mdio_priv *priv = dev_get_priv(dev);
+
+	priv->switch_regs = dev_read_addr(dev);
+	if (priv->switch_regs == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	return 0;
+}
+
+U_BOOT_DRIVER(mt7531_mdio) = {
+	.name           = "mt7531-mdio",
+	.id             = UCLASS_MDIO,
+	.probe          = mt7531_mdio_probe,
+	.ops            = &mt7531_mdio_ops,
+	.priv_auto	  = sizeof(struct mt7531_mdio_priv),
+};
diff --git a/drivers/net/mdio-mt7531.h b/drivers/net/mdio-mt7531.h
new file mode 100644
index 00000000000..ee096112f92
--- /dev/null
+++ b/drivers/net/mdio-mt7531.h
@@ -0,0 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+struct mt7531_mdio_priv {
+	phys_addr_t switch_regs;
+};
+
+int mt7531_mdio_read(struct udevice *dev, int addr, int devad, int reg);
+int mt7531_mdio_write(struct udevice *dev, int addr, int devad,
+		      int reg, u16 value);
diff --git a/drivers/net/mtk_eth/Kconfig b/drivers/net/mtk_eth/Kconfig
index e8cdf408237..67b2b612b1a 100644
--- a/drivers/net/mtk_eth/Kconfig
+++ b/drivers/net/mtk_eth/Kconfig
@@ -4,6 +4,7 @@ config MEDIATEK_ETH
 	select PHYLIB
 	select DM_GPIO
 	select DM_RESET
+	select MDIO_MT7531
 	help
 	  This Driver support MediaTek Ethernet GMAC
 	  Say Y to enable support for the MediaTek Ethernet GMAC.
diff --git a/drivers/net/mtk_eth/mt753x.c b/drivers/net/mtk_eth/mt753x.c
index cdd52f3ff1b..cf643f336d6 100644
--- a/drivers/net/mtk_eth/mt753x.c
+++ b/drivers/net/mtk_eth/mt753x.c
@@ -138,8 +138,8 @@ int mt7531_mii_read(struct mt753x_switch_priv *priv, u8 phy, u8 reg)
 
 	phy_addr = MT753X_PHY_ADDR(priv->phy_base, phy);
 
-	return mt7531_mii_rw(priv, phy_addr, reg, 0, MDIO_CMD_READ,
-			     MDIO_ST_C22);
+	return mt7531_mdio_read(&priv->mdio_priv, phy_addr, MDIO_DEVAD_NONE,
+				reg);
 }
 
 int mt7531_mii_write(struct mt753x_switch_priv *priv, u8 phy, u8 reg, u16 val)
@@ -151,48 +151,36 @@ int mt7531_mii_write(struct mt753x_switch_priv *priv, u8 phy, u8 reg, u16 val)
 
 	phy_addr = MT753X_PHY_ADDR(priv->phy_base, phy);
 
-	return mt7531_mii_rw(priv, phy_addr, reg, val, MDIO_CMD_WRITE,
-			     MDIO_ST_C22);
+	return mt7531_mdio_write(&priv->mdio_priv, phy_addr, MDIO_DEVAD_NONE,
+				 reg, val);
 }
 
 int mt7531_mmd_read(struct mt753x_switch_priv *priv, u8 addr, u8 devad,
 		    u16 reg)
 {
 	u8 phy_addr;
-	int ret;
 
 	if (addr >= MT753X_NUM_PHYS)
 		return -EINVAL;
 
 	phy_addr = MT753X_PHY_ADDR(priv->phy_base, addr);
 
-	ret = mt7531_mii_rw(priv, phy_addr, devad, reg, MDIO_CMD_ADDR,
-			    MDIO_ST_C45);
-	if (ret)
-		return ret;
-
-	return mt7531_mii_rw(priv, phy_addr, devad, 0, MDIO_CMD_READ_C45,
-			     MDIO_ST_C45);
+	return mt7531_mdio_read(&priv->mdio_priv, phy_addr, devad,
+				reg);
 }
 
 int mt7531_mmd_write(struct mt753x_switch_priv *priv, u8 addr, u8 devad,
 		     u16 reg, u16 val)
 {
 	u8 phy_addr;
-	int ret;
 
 	if (addr >= MT753X_NUM_PHYS)
 		return 0;
 
 	phy_addr = MT753X_PHY_ADDR(priv->phy_base, addr);
 
-	ret = mt7531_mii_rw(priv, phy_addr, devad, reg, MDIO_CMD_ADDR,
-			    MDIO_ST_C45);
-	if (ret)
-		return ret;
-
-	return mt7531_mii_rw(priv, phy_addr, devad, val, MDIO_CMD_WRITE,
-			     MDIO_ST_C45);
+	return mt7531_mdio_write(&priv->mdio_priv, phy_addr, devad,
+				 reg, val);
 }
 
 static int mt7531_mdio_read(struct mii_dev *bus, int addr, int devad, int reg)
@@ -224,6 +212,7 @@ int mt7531_mdio_register(struct mt753x_switch_priv *priv)
 	if (!mdio_bus)
 		return -ENOMEM;
 
+	priv->mdio_priv.switch_regs = priv->epriv.ethsys_base + GSW_BASE;
 	mdio_bus->read = mt7531_mdio_read;
 	mdio_bus->write = mt7531_mdio_write;
 	snprintf(mdio_bus->name, sizeof(mdio_bus->name), priv->epriv.sw->name);
diff --git a/drivers/net/mtk_eth/mt753x.h b/drivers/net/mtk_eth/mt753x.h
index 65046a1421c..cd128ad39fe 100644
--- a/drivers/net/mtk_eth/mt753x.h
+++ b/drivers/net/mtk_eth/mt753x.h
@@ -14,6 +14,8 @@
 #include <linux/bitops.h>
 #include <linux/bitfield.h>
 
+#include "../mdio-mt7531.h"
+
 struct mtk_eth_priv;
 
 #define MT753X_NUM_PHYS		5
@@ -254,6 +256,7 @@ struct mtk_eth_priv;
 
 struct mt753x_switch_priv {
 	struct mtk_eth_switch_priv epriv;
+	struct mt7531_mdio_priv mdio_priv;
 	struct mii_dev *mdio_bus;
 	u32 smi_addr;
 	u32 phy_base;
-- 
2.50.0



More information about the U-Boot mailing list