* [PATCH v2 0/5] net: mediatek: mt7988: various fixup + MDIO detach
@ 2025-09-20 16:09 Christian Marangi
2025-09-20 16:09 ` [PATCH v2 1/5] net: mediatek: mt7531/7988: fix broken PHY turn ON/OFF Christian Marangi
` (4 more replies)
0 siblings, 5 replies; 7+ messages in thread
From: Christian Marangi @ 2025-09-20 16:09 UTC (permalink / raw)
To: Tom Rini, Joe Hershberger, Ramon Fried, Weijie Gao,
Christian Marangi, u-boot
This series is really required for Airoha AN7581 to provide support
for the MMIO MDIO bus. But to accomplish this, rework is needed
to the current MT7531 driver to prevent additional code duplication.
While at it also multiple BUG were notice on the MT7988 driver.
The additional MDIO MMIO driver expose an internal variant
to access the function directly from a manually crafted mii_bus
but also provide DM support used by AN7581.
Changes v2:
- Replace patch 1 with actual fix
Christian Marangi (5):
net: mediatek: mt7531/7988: fix broken PHY turn ON/OFF
net: mediatek: mt7988: restore PHY page on PHY setting exit
net: mediatek: mt7988: free allocated MDIO bus on cleanup
net: mediatek: move MT7531 MMIO MDIO to dedicated driver
net: airoha: bind MDIO controller on Ethernet load
drivers/net/Kconfig | 4 +
drivers/net/Makefile | 1 +
drivers/net/airoha_eth.c | 26 +++++
drivers/net/mdio-mt7531-mmio.c | 168 +++++++++++++++++++++++++++++++++
drivers/net/mdio-mt7531-mmio.h | 9 ++
drivers/net/mtk_eth/Kconfig | 1 +
drivers/net/mtk_eth/mt7531.c | 20 ++--
drivers/net/mtk_eth/mt7988.c | 92 +++++++++++++++---
8 files changed, 294 insertions(+), 27 deletions(-)
create mode 100644 drivers/net/mdio-mt7531-mmio.c
create mode 100644 drivers/net/mdio-mt7531-mmio.h
--
2.51.0
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v2 1/5] net: mediatek: mt7531/7988: fix broken PHY turn ON/OFF
2025-09-20 16:09 [PATCH v2 0/5] net: mediatek: mt7988: various fixup + MDIO detach Christian Marangi
@ 2025-09-20 16:09 ` Christian Marangi
2025-09-20 16:09 ` [PATCH v2 2/5] net: mediatek: mt7988: restore PHY page on PHY setting exit Christian Marangi
` (3 subsequent siblings)
4 siblings, 0 replies; 7+ messages in thread
From: Christian Marangi @ 2025-09-20 16:09 UTC (permalink / raw)
To: Tom Rini, Joe Hershberger, Ramon Fried, Weijie Gao,
Christian Marangi, u-boot
The PHY for MT7531/MT7988 are never actully turned ON/OFF for the
affected PHY as we are read/writing to the wrong PHY address.
This is caused by the fact that we use the MT753X_PHY_ADDR macro 2
times offsetting the address multiple times.
One in the _setup() function and one in the mt7531_mii_read/write.
Drop the additional usage of MT753X_PHY_ADDR in setup() to correctly
set the PHY.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
drivers/net/mtk_eth/mt7531.c | 20 +++++++-------------
drivers/net/mtk_eth/mt7988.c | 12 +++++-------
2 files changed, 12 insertions(+), 20 deletions(-)
diff --git a/drivers/net/mtk_eth/mt7531.c b/drivers/net/mtk_eth/mt7531.c
index 32d6bebbbdb..965bc3cb7e9 100644
--- a/drivers/net/mtk_eth/mt7531.c
+++ b/drivers/net/mtk_eth/mt7531.c
@@ -22,17 +22,13 @@
static int mt7531_core_reg_read(struct mt753x_switch_priv *priv, u32 reg)
{
- u8 phy_addr = MT753X_PHY_ADDR(priv->phy_base, 0);
-
- return mt7531_mmd_read(priv, phy_addr, 0x1f, reg);
+ return mt7531_mmd_read(priv, 0, 0x1f, reg);
}
static void mt7531_core_reg_write(struct mt753x_switch_priv *priv, u32 reg,
u32 val)
{
- u8 phy_addr = MT753X_PHY_ADDR(priv->phy_base, 0);
-
- mt7531_mmd_write(priv, phy_addr, 0x1f, reg, val);
+ mt7531_mmd_write(priv, 0, 0x1f, reg, val);
}
static void mt7531_core_pll_setup(struct mt753x_switch_priv *priv)
@@ -171,7 +167,7 @@ static int mt7531_setup(struct mtk_eth_switch_priv *swpriv)
{
struct mt753x_switch_priv *priv = (struct mt753x_switch_priv *)swpriv;
u32 i, val, pmcr, port5_sgmii;
- u16 phy_addr, phy_val;
+ u16 phy_val;
priv->smi_addr = MT753X_DFL_SMI_ADDR;
priv->phy_base = (priv->smi_addr + 1) & MT753X_SMI_ADDR_MASK;
@@ -180,10 +176,9 @@ static int mt7531_setup(struct mtk_eth_switch_priv *swpriv)
/* Turn off PHYs */
for (i = 0; i < MT753X_NUM_PHYS; i++) {
- phy_addr = MT753X_PHY_ADDR(priv->phy_base, i);
- phy_val = mt7531_mii_read(priv, phy_addr, MII_BMCR);
+ phy_val = mt7531_mii_read(priv, i, MII_BMCR);
phy_val |= BMCR_PDOWN;
- mt7531_mii_write(priv, phy_addr, MII_BMCR, phy_val);
+ mt7531_mii_write(priv, i, MII_BMCR, phy_val);
}
/* Force MAC link down before reset */
@@ -239,10 +234,9 @@ static int mt7531_setup(struct mtk_eth_switch_priv *swpriv)
/* Turn on PHYs */
for (i = 0; i < MT753X_NUM_PHYS; i++) {
- phy_addr = MT753X_PHY_ADDR(priv->phy_base, i);
- phy_val = mt7531_mii_read(priv, phy_addr, MII_BMCR);
+ phy_val = mt7531_mii_read(priv, i, MII_BMCR);
phy_val &= ~BMCR_PDOWN;
- mt7531_mii_write(priv, phy_addr, MII_BMCR, phy_val);
+ mt7531_mii_write(priv, i, MII_BMCR, phy_val);
}
mt7531_phy_setting(priv);
diff --git a/drivers/net/mtk_eth/mt7988.c b/drivers/net/mtk_eth/mt7988.c
index a416d87840c..87b6ed30cd0 100644
--- a/drivers/net/mtk_eth/mt7988.c
+++ b/drivers/net/mtk_eth/mt7988.c
@@ -61,7 +61,7 @@ static void mt7988_mac_control(struct mtk_eth_switch_priv *swpriv, bool enable)
static int mt7988_setup(struct mtk_eth_switch_priv *swpriv)
{
struct mt753x_switch_priv *priv = (struct mt753x_switch_priv *)swpriv;
- u16 phy_addr, phy_val;
+ u16 phy_val;
u32 pmcr;
int i;
@@ -72,10 +72,9 @@ static int mt7988_setup(struct mtk_eth_switch_priv *swpriv)
/* Turn off PHYs */
for (i = 0; i < MT753X_NUM_PHYS; i++) {
- phy_addr = MT753X_PHY_ADDR(priv->phy_base, i);
- phy_val = mt7531_mii_read(priv, phy_addr, MII_BMCR);
+ phy_val = mt7531_mii_read(priv, i, MII_BMCR);
phy_val |= BMCR_PDOWN;
- mt7531_mii_write(priv, phy_addr, MII_BMCR, phy_val);
+ mt7531_mii_write(priv, i, MII_BMCR, phy_val);
}
switch (priv->epriv.phy_interface) {
@@ -128,10 +127,9 @@ static int mt7988_setup(struct mtk_eth_switch_priv *swpriv)
/* Turn on PHYs */
for (i = 0; i < MT753X_NUM_PHYS; i++) {
- phy_addr = MT753X_PHY_ADDR(priv->phy_base, i);
- phy_val = mt7531_mii_read(priv, phy_addr, MII_BMCR);
+ phy_val = mt7531_mii_read(priv, i, MII_BMCR);
phy_val &= ~BMCR_PDOWN;
- mt7531_mii_write(priv, phy_addr, MII_BMCR, phy_val);
+ mt7531_mii_write(priv, i, MII_BMCR, phy_val);
}
mt7988_phy_setting(priv);
--
2.51.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v2 2/5] net: mediatek: mt7988: restore PHY page on PHY setting exit
2025-09-20 16:09 [PATCH v2 0/5] net: mediatek: mt7988: various fixup + MDIO detach Christian Marangi
2025-09-20 16:09 ` [PATCH v2 1/5] net: mediatek: mt7531/7988: fix broken PHY turn ON/OFF Christian Marangi
@ 2025-09-20 16:09 ` Christian Marangi
2025-09-20 16:09 ` [PATCH v2 3/5] net: mediatek: mt7988: free allocated MDIO bus on cleanup Christian Marangi
` (2 subsequent siblings)
4 siblings, 0 replies; 7+ messages in thread
From: Christian Marangi @ 2025-09-20 16:09 UTC (permalink / raw)
To: Tom Rini, Joe Hershberger, Ramon Fried, Weijie Gao,
Christian Marangi, u-boot
On exiting the phy_setting function for MT7988, the PHY page is never
restored to Page 0. This can cause all kind of problem with reading the
status of the PHY at runtime.
Correctly restore PHY page on exiting the PHY setting function.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
drivers/net/mtk_eth/mt7988.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/net/mtk_eth/mt7988.c b/drivers/net/mtk_eth/mt7988.c
index 87b6ed30cd0..06bbe049da3 100644
--- a/drivers/net/mtk_eth/mt7988.c
+++ b/drivers/net/mtk_eth/mt7988.c
@@ -34,8 +34,10 @@ static void mt7988_phy_setting(struct mt753x_switch_priv *priv)
u32 i;
for (i = 0; i < MT753X_NUM_PHYS; i++) {
- /* Enable HW auto downshift */
+ /* Set PHY to PHY page 1 */
mt7531_mii_write(priv, i, 0x1f, 0x1);
+
+ /* Enable HW auto downshift */
val = mt7531_mii_read(priv, i, PHY_EXT_REG_14);
val |= PHY_EN_DOWN_SHFIT;
mt7531_mii_write(priv, i, PHY_EXT_REG_14, val);
@@ -44,6 +46,9 @@ static void mt7988_phy_setting(struct mt753x_switch_priv *priv)
val = mt7531_mii_read(priv, i, PHY_EXT_REG_17);
val |= PHY_LINKDOWN_POWER_SAVING_EN;
mt7531_mii_write(priv, i, PHY_EXT_REG_17, val);
+
+ /* Restore PHY to PHY page 0 */
+ mt7531_mii_write(priv, i, 0x1f, 0x0);
}
}
--
2.51.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v2 3/5] net: mediatek: mt7988: free allocated MDIO bus on cleanup
2025-09-20 16:09 [PATCH v2 0/5] net: mediatek: mt7988: various fixup + MDIO detach Christian Marangi
2025-09-20 16:09 ` [PATCH v2 1/5] net: mediatek: mt7531/7988: fix broken PHY turn ON/OFF Christian Marangi
2025-09-20 16:09 ` [PATCH v2 2/5] net: mediatek: mt7988: restore PHY page on PHY setting exit Christian Marangi
@ 2025-09-20 16:09 ` Christian Marangi
2025-09-20 16:09 ` [PATCH v2 4/5] net: mediatek: move MT7531 MMIO MDIO to dedicated driver Christian Marangi
2025-09-20 16:09 ` [PATCH v2 5/5] net: airoha: bind MDIO controller on Ethernet load Christian Marangi
4 siblings, 0 replies; 7+ messages in thread
From: Christian Marangi @ 2025-09-20 16:09 UTC (permalink / raw)
To: Tom Rini, Joe Hershberger, Ramon Fried, Weijie Gao,
Christian Marangi, u-boot
Correctly free the MDIO Bus on calling cleanup function. While at it
also fix a copy-paste error and rename the cleanup function name to the
more specific name.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
drivers/net/mtk_eth/mt7988.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/drivers/net/mtk_eth/mt7988.c b/drivers/net/mtk_eth/mt7988.c
index 06bbe049da3..b77660be55c 100644
--- a/drivers/net/mtk_eth/mt7988.c
+++ b/drivers/net/mtk_eth/mt7988.c
@@ -142,11 +142,13 @@ static int mt7988_setup(struct mtk_eth_switch_priv *swpriv)
return mt7531_mdio_register(priv);
}
-static int mt7531_cleanup(struct mtk_eth_switch_priv *swpriv)
+static int mt7988_cleanup(struct mtk_eth_switch_priv *swpriv)
{
struct mt753x_switch_priv *priv = (struct mt753x_switch_priv *)swpriv;
+ struct mii_dev *mdio_bus = priv->mdio_bus;
- mdio_unregister(priv->mdio_bus);
+ mdio_unregister(mdio_bus);
+ mdio_free(mdio_bus);
return 0;
}
@@ -158,6 +160,6 @@ MTK_ETH_SWITCH(mt7988) = {
.reset_wait_time = 50,
.setup = mt7988_setup,
- .cleanup = mt7531_cleanup,
+ .cleanup = mt7988_cleanup,
.mac_control = mt7988_mac_control,
};
--
2.51.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v2 4/5] net: mediatek: move MT7531 MMIO MDIO to dedicated driver
2025-09-20 16:09 [PATCH v2 0/5] net: mediatek: mt7988: various fixup + MDIO detach Christian Marangi
` (2 preceding siblings ...)
2025-09-20 16:09 ` [PATCH v2 3/5] net: mediatek: mt7988: free allocated MDIO bus on cleanup Christian Marangi
@ 2025-09-20 16:09 ` Christian Marangi
2025-09-20 16:09 ` [PATCH v2 5/5] net: airoha: bind MDIO controller on Ethernet load Christian Marangi
4 siblings, 0 replies; 7+ messages in thread
From: Christian Marangi @ 2025-09-20 16:09 UTC (permalink / raw)
To: Tom Rini, Joe Hershberger, Ramon Fried, Weijie Gao,
Christian Marangi, u-boot
In preparation for support of MDIO on AN7581, move the MT7531 MMIO logic
to a dedicated driver and permit usage of the mdio read/write function
to the mtk_eth driver.
This only affect MT7988 that can use MMIO operation to access the Switch
register. The MT7988 code is updated to make use of the external driver.
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@gmail.com>
---
drivers/net/Kconfig | 3 +
drivers/net/Makefile | 1 +
drivers/net/mdio-mt7531-mmio.c | 168 +++++++++++++++++++++++++++++++++
drivers/net/mdio-mt7531-mmio.h | 9 ++
drivers/net/mtk_eth/Kconfig | 1 +
drivers/net/mtk_eth/mt7988.c | 85 ++++++++++++++---
6 files changed, 254 insertions(+), 13 deletions(-)
create mode 100644 drivers/net/mdio-mt7531-mmio.c
create mode 100644 drivers/net/mdio-mt7531-mmio.h
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index d1cb69f85ad..cee4a3fc9bd 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_MMIO
+ bool
+
source "drivers/net/mtk_eth/Kconfig"
config HIFEMAC_ETH
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index f8f9a71f815..a3c3420898c 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -63,6 +63,7 @@ obj-$(CONFIG_MACB) += macb.o
obj-$(CONFIG_MCFFEC) += mcffec.o mcfmii.o
obj-$(CONFIG_MDIO_IPQ4019) += mdio-ipq4019.o
obj-$(CONFIG_MDIO_GPIO_BITBANG) += mdio_gpio.o
+obj-$(CONFIG_MDIO_MT7531_MMIO) += mdio-mt7531-mmio.o
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-mmio.c b/drivers/net/mdio-mt7531-mmio.c
new file mode 100644
index 00000000000..3e325ca58da
--- /dev/null
+++ b/drivers/net/mdio-mt7531-mmio.c
@@ -0,0 +1,168 @@
+// 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);
+}
+
+static int mt7531_mdio_read(struct mt7531_mdio_priv *priv, int addr, int devad, int reg)
+{
+ 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;
+}
+
+static int mt7531_mdio_write(struct mt7531_mdio_priv *priv, int addr, int devad,
+ int reg, u16 value)
+{
+ 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;
+}
+
+int mt7531_mdio_mmio_read(struct mii_dev *bus, int addr, int devad, int reg)
+{
+ struct mt7531_mdio_priv *priv = bus->priv;
+
+ return mt7531_mdio_read(priv, addr, devad, reg);
+}
+
+int mt7531_mdio_mmio_write(struct mii_dev *bus, int addr, int devad,
+ int reg, u16 value)
+{
+ struct mt7531_mdio_priv *priv = bus->priv;
+
+ return mt7531_mdio_write(priv, addr, devad, reg, value);
+}
+
+static int dm_mt7531_mdio_read(struct udevice *dev, int addr, int devad, int reg)
+{
+ struct mt7531_mdio_priv *priv = dev_get_priv(dev);
+
+ return mt7531_mdio_read(priv, addr, devad, reg);
+}
+
+static int dm_mt7531_mdio_write(struct udevice *dev, int addr, int devad,
+ int reg, u16 value)
+{
+ struct mt7531_mdio_priv *priv = dev_get_priv(dev);
+
+ return mt7531_mdio_write(priv, addr, devad, reg, value);
+}
+
+static const struct mdio_ops mt7531_mdio_ops = {
+ .read = dm_mt7531_mdio_read,
+ .write = dm_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-mmio",
+ .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-mmio.h b/drivers/net/mdio-mt7531-mmio.h
new file mode 100644
index 00000000000..f98102cb939
--- /dev/null
+++ b/drivers/net/mdio-mt7531-mmio.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+struct mt7531_mdio_mmio_priv {
+ phys_addr_t switch_regs;
+};
+
+int mt7531_mdio_mmio_read(struct mii_dev *bus, int addr, int devad, int reg);
+int mt7531_mdio_mmio_write(struct mii_dev *bus, int addr, int devad,
+ int reg, u16 value);
diff --git a/drivers/net/mtk_eth/Kconfig b/drivers/net/mtk_eth/Kconfig
index e8cdf408237..8716eb86064 100644
--- a/drivers/net/mtk_eth/Kconfig
+++ b/drivers/net/mtk_eth/Kconfig
@@ -30,6 +30,7 @@ config MTK_ETH_SWITCH_MT7531
config MTK_ETH_SWITCH_MT7988
bool "Support for MediaTek MT7988 built-in ethernet switch"
depends on TARGET_MT7988
+ select MDIO_MT7531_MMIO
default y
config MTK_ETH_SWITCH_AN8855
diff --git a/drivers/net/mtk_eth/mt7988.c b/drivers/net/mtk_eth/mt7988.c
index b77660be55c..29b6363cbd7 100644
--- a/drivers/net/mtk_eth/mt7988.c
+++ b/drivers/net/mtk_eth/mt7988.c
@@ -6,6 +6,7 @@
* Author: Mark Lee <mark-mc.lee@mediatek.com>
*/
+#include <malloc.h>
#include <miiphy.h>
#include <linux/delay.h>
#include <linux/mdio.h>
@@ -14,6 +15,8 @@
#include "mtk_eth.h"
#include "mt753x.h"
+#include "../mdio-mt7531-mmio.h"
+
static int mt7988_reg_read(struct mt753x_switch_priv *priv, u32 reg, u32 *data)
{
*data = readl(priv->epriv.ethsys_base + GSW_BASE + reg);
@@ -30,25 +33,34 @@ static int mt7988_reg_write(struct mt753x_switch_priv *priv, u32 reg, u32 data)
static void mt7988_phy_setting(struct mt753x_switch_priv *priv)
{
+ struct mii_dev *mdio_bus = priv->mdio_bus;
u16 val;
u32 i;
for (i = 0; i < MT753X_NUM_PHYS; i++) {
+ u16 addr = MT753X_PHY_ADDR(priv->phy_base, i);
+
/* Set PHY to PHY page 1 */
- mt7531_mii_write(priv, i, 0x1f, 0x1);
+ mt7531_mdio_mmio_write(mdio_bus, addr, MDIO_DEVAD_NONE,
+ 0x1f, 0x1);
/* Enable HW auto downshift */
- val = mt7531_mii_read(priv, i, PHY_EXT_REG_14);
+ val = mt7531_mdio_mmio_read(mdio_bus, addr, MDIO_DEVAD_NONE,
+ PHY_EXT_REG_14);
val |= PHY_EN_DOWN_SHFIT;
- mt7531_mii_write(priv, i, PHY_EXT_REG_14, val);
+ mt7531_mdio_mmio_write(mdio_bus, addr, MDIO_DEVAD_NONE,
+ PHY_EXT_REG_14, val);
/* PHY link down power saving enable */
- val = mt7531_mii_read(priv, i, PHY_EXT_REG_17);
+ val = mt7531_mdio_mmio_read(mdio_bus, addr, MDIO_DEVAD_NONE,
+ PHY_EXT_REG_17);
val |= PHY_LINKDOWN_POWER_SAVING_EN;
- mt7531_mii_write(priv, i, PHY_EXT_REG_17, val);
+ mt7531_mdio_mmio_write(mdio_bus, addr, MDIO_DEVAD_NONE,
+ PHY_EXT_REG_17, val);
/* Restore PHY to PHY page 0 */
- mt7531_mii_write(priv, i, 0x1f, 0x0);
+ mt7531_mdio_mmio_write(mdio_bus, addr, MDIO_DEVAD_NONE,
+ 0x1f, 0x0);
}
}
@@ -63,23 +75,66 @@ static void mt7988_mac_control(struct mtk_eth_switch_priv *swpriv, bool enable)
mt7988_reg_write(priv, PMCR_REG(6), pmcr);
}
+static int mt7988_mdio_register(struct mt753x_switch_priv *priv)
+{
+ struct mt7531_mdio_mmio_priv *mdio_priv;
+ struct mii_dev *mdio_bus = mdio_alloc();
+ int ret;
+
+ if (!mdio_bus)
+ return -ENOMEM;
+
+ mdio_priv = malloc(sizeof(*mdio_priv));
+ if (!mdio_priv)
+ return -ENOMEM;
+
+ mdio_priv->switch_regs = (phys_addr_t)priv->epriv.ethsys_base + GSW_BASE;
+
+ mdio_bus->read = mt7531_mdio_mmio_read;
+ mdio_bus->write = mt7531_mdio_mmio_write;
+ snprintf(mdio_bus->name, sizeof(mdio_bus->name), priv->epriv.sw->name);
+
+ mdio_bus->priv = mdio_priv;
+
+ ret = mdio_register(mdio_bus);
+ if (ret) {
+ free(mdio_bus->priv);
+ mdio_free(mdio_bus);
+ return ret;
+ }
+
+ priv->mdio_bus = mdio_bus;
+
+ return 0;
+}
+
static int mt7988_setup(struct mtk_eth_switch_priv *swpriv)
{
struct mt753x_switch_priv *priv = (struct mt753x_switch_priv *)swpriv;
- u16 phy_val;
+ struct mii_dev *mdio_bus;
+ u16 phy_addr, phy_val;
+ int ret, i;
u32 pmcr;
- int i;
priv->smi_addr = MT753X_DFL_SMI_ADDR;
priv->phy_base = (priv->smi_addr + 1) & MT753X_SMI_ADDR_MASK;
priv->reg_read = mt7988_reg_read;
priv->reg_write = mt7988_reg_write;
+ ret = mt7988_mdio_register(priv);
+ if (ret)
+ return ret;
+
+ mdio_bus = priv->mdio_bus;
+
/* Turn off PHYs */
for (i = 0; i < MT753X_NUM_PHYS; i++) {
- phy_val = mt7531_mii_read(priv, i, MII_BMCR);
+ phy_addr = MT753X_PHY_ADDR(priv->phy_base, i);
+ phy_val = mt7531_mdio_mmio_read(mdio_bus, phy_addr,
+ MDIO_DEVAD_NONE, MII_BMCR);
phy_val |= BMCR_PDOWN;
- mt7531_mii_write(priv, i, MII_BMCR, phy_val);
+ mt7531_mdio_mmio_write(mdio_bus, phy_addr, MDIO_DEVAD_NONE,
+ MII_BMCR, phy_val);
}
switch (priv->epriv.phy_interface) {
@@ -132,14 +187,17 @@ static int mt7988_setup(struct mtk_eth_switch_priv *swpriv)
/* Turn on PHYs */
for (i = 0; i < MT753X_NUM_PHYS; i++) {
- phy_val = mt7531_mii_read(priv, i, MII_BMCR);
+ phy_addr = MT753X_PHY_ADDR(priv->phy_base, i);
+ phy_val = mt7531_mdio_mmio_read(mdio_bus, phy_addr,
+ MDIO_DEVAD_NONE, MII_BMCR);
phy_val &= ~BMCR_PDOWN;
- mt7531_mii_write(priv, i, MII_BMCR, phy_val);
+ mt7531_mdio_mmio_write(mdio_bus, phy_addr, MDIO_DEVAD_NONE,
+ MII_BMCR, phy_val);
}
mt7988_phy_setting(priv);
- return mt7531_mdio_register(priv);
+ return 0;
}
static int mt7988_cleanup(struct mtk_eth_switch_priv *swpriv)
@@ -148,6 +206,7 @@ static int mt7988_cleanup(struct mtk_eth_switch_priv *swpriv)
struct mii_dev *mdio_bus = priv->mdio_bus;
mdio_unregister(mdio_bus);
+ free(mdio_bus->priv);
mdio_free(mdio_bus);
return 0;
--
2.51.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v2 5/5] net: airoha: bind MDIO controller on Ethernet load
2025-09-20 16:09 [PATCH v2 0/5] net: mediatek: mt7988: various fixup + MDIO detach Christian Marangi
` (3 preceding siblings ...)
2025-09-20 16:09 ` [PATCH v2 4/5] net: mediatek: move MT7531 MMIO MDIO to dedicated driver Christian Marangi
@ 2025-09-20 16:09 ` Christian Marangi
2025-10-22 13:42 ` Jerome Forissier
4 siblings, 1 reply; 7+ messages in thread
From: Christian Marangi @ 2025-09-20 16:09 UTC (permalink / raw)
To: Tom Rini, Joe Hershberger, Ramon Fried, Weijie Gao,
Christian Marangi, u-boot
Bind MDIO controller on Ethernet Controller load. The Airoha AN7581 SoC
have an integrated Switch based on MT7531 (or more saying MT7988).
Attach it to the switch node to support scanning for MDIO devices on the
BUS.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
drivers/net/Kconfig | 1 +
drivers/net/airoha_eth.c | 26 ++++++++++++++++++++++++++
2 files changed, 27 insertions(+)
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index cee4a3fc9bd..ce7c7e6297e 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -126,6 +126,7 @@ config AIROHA_ETH
depends on ARCH_AIROHA
select PHYLIB
select DM_RESET
+ select MDIO_MT7531
help
This Driver support Airoha Ethernet QDMA Driver
Say Y to enable support for the Airoha Ethernet QDMA.
diff --git a/drivers/net/airoha_eth.c b/drivers/net/airoha_eth.c
index 6588eb3a806..6be6ec2845b 100644
--- a/drivers/net/airoha_eth.c
+++ b/drivers/net/airoha_eth.c
@@ -971,6 +971,31 @@ static int arht_eth_write_hwaddr(struct udevice *dev)
return 0;
}
+static int airoha_eth_bind(struct udevice *dev)
+{
+ struct airoha_eth_soc_data *data = (void *)dev_get_driver_data(dev);
+ struct udevice *mdio_dev;
+ ofnode switch_node;
+ int ret = 0;
+
+ if (!CONFIG_IS_ENABLED(MDIO_MT7531))
+ return 0;
+
+ switch_node = ofnode_by_compatible(ofnode_null(),
+ "airoha,en7581-switch");
+ if (!ofnode_valid(switch_node)) {
+ debug("Warning: missing switch node\n");
+ return 0;
+ }
+
+ ret = device_bind_driver_to_node(dev, "mt7531-mdio", "mdio",
+ switch_node, &mdio_dev);
+ if (ret)
+ debug("Warning: failed to bind mdio controller\n");
+
+ return 0;
+}
+
static const struct udevice_id airoha_eth_ids[] = {
{ .compatible = "airoha,en7581-eth" },
{ }
@@ -990,6 +1015,7 @@ U_BOOT_DRIVER(airoha_eth) = {
.id = UCLASS_ETH,
.of_match = airoha_eth_ids,
.probe = airoha_eth_probe,
+ .bind = airoha_eth_bind,
.ops = &airoha_eth_ops,
.priv_auto = sizeof(struct airoha_eth),
.plat_auto = sizeof(struct eth_pdata),
--
2.51.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v2 5/5] net: airoha: bind MDIO controller on Ethernet load
2025-09-20 16:09 ` [PATCH v2 5/5] net: airoha: bind MDIO controller on Ethernet load Christian Marangi
@ 2025-10-22 13:42 ` Jerome Forissier
0 siblings, 0 replies; 7+ messages in thread
From: Jerome Forissier @ 2025-10-22 13:42 UTC (permalink / raw)
To: Christian Marangi
Cc: Tom Rini, Ramon Fried, Joe Hershberger, Weijie Gao, u-boot
Hi Christian,
On 9/20/25 18:09, Christian Marangi wrote:
> Bind MDIO controller on Ethernet Controller load. The Airoha AN7581 SoC
> have an integrated Switch based on MT7531 (or more saying MT7988).
>
> Attach it to the switch node to support scanning for MDIO devices on the
> BUS.
>
> Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
> ---
> drivers/net/Kconfig | 1 +
> drivers/net/airoha_eth.c | 26 ++++++++++++++++++++++++++
> 2 files changed, 27 insertions(+)
>
> diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
> index cee4a3fc9bd..ce7c7e6297e 100644
> --- a/drivers/net/Kconfig
> +++ b/drivers/net/Kconfig
> @@ -126,6 +126,7 @@ config AIROHA_ETH
> depends on ARCH_AIROHA
> select PHYLIB
> select DM_RESET
> + select MDIO_MT7531
> help
> This Driver support Airoha Ethernet QDMA Driver
> Say Y to enable support for the Airoha Ethernet QDMA.
> diff --git a/drivers/net/airoha_eth.c b/drivers/net/airoha_eth.c
> index 6588eb3a806..6be6ec2845b 100644
> --- a/drivers/net/airoha_eth.c
> +++ b/drivers/net/airoha_eth.c
> @@ -971,6 +971,31 @@ static int arht_eth_write_hwaddr(struct udevice *dev)
> return 0;
> }
>
> +static int airoha_eth_bind(struct udevice *dev)
> +{
> + struct airoha_eth_soc_data *data = (void *)dev_get_driver_data(dev);
data is unused and causes a build warning which is an error in CI.
> + struct udevice *mdio_dev;
> + ofnode switch_node;
> + int ret = 0;
> +
> + if (!CONFIG_IS_ENABLED(MDIO_MT7531))
> + return 0;
> +
> + switch_node = ofnode_by_compatible(ofnode_null(),
> + "airoha,en7581-switch");
> + if (!ofnode_valid(switch_node)) {
> + debug("Warning: missing switch node\n");
> + return 0;
> + }
> +
> + ret = device_bind_driver_to_node(dev, "mt7531-mdio", "mdio",
> + switch_node, &mdio_dev);
This needs #include <dm/lists.h> AFAICT
> + if (ret)
> + debug("Warning: failed to bind mdio controller\n");
> +
> + return 0;
> +}
> +
> static const struct udevice_id airoha_eth_ids[] = {
> { .compatible = "airoha,en7581-eth" },
> { }
> @@ -990,6 +1015,7 @@ U_BOOT_DRIVER(airoha_eth) = {
> .id = UCLASS_ETH,
> .of_match = airoha_eth_ids,
> .probe = airoha_eth_probe,
> + .bind = airoha_eth_bind,
> .ops = &airoha_eth_ops,
> .priv_auto = sizeof(struct airoha_eth),
> .plat_auto = sizeof(struct eth_pdata),
I have picked up the four other patches in this series [1]. Please fix
and resend only that one.
[1] https://source.denx.de/u-boot/custodians/u-boot-net/-/commits/net-20251022
Thanks,
--
Jerome
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2025-10-22 13:42 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-09-20 16:09 [PATCH v2 0/5] net: mediatek: mt7988: various fixup + MDIO detach Christian Marangi
2025-09-20 16:09 ` [PATCH v2 1/5] net: mediatek: mt7531/7988: fix broken PHY turn ON/OFF Christian Marangi
2025-09-20 16:09 ` [PATCH v2 2/5] net: mediatek: mt7988: restore PHY page on PHY setting exit Christian Marangi
2025-09-20 16:09 ` [PATCH v2 3/5] net: mediatek: mt7988: free allocated MDIO bus on cleanup Christian Marangi
2025-09-20 16:09 ` [PATCH v2 4/5] net: mediatek: move MT7531 MMIO MDIO to dedicated driver Christian Marangi
2025-09-20 16:09 ` [PATCH v2 5/5] net: airoha: bind MDIO controller on Ethernet load Christian Marangi
2025-10-22 13:42 ` Jerome Forissier
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox