Index: linux-5.4.203/drivers/net/dsa/mt7530.c
===================================================================
--- linux-5.4.203.orig/drivers/net/dsa/mt7530.c
+++ linux-5.4.203/drivers/net/dsa/mt7530.c
@@ -847,6 +847,132 @@ mt7531_ind_phy_write(struct dsa_switch *
 	return ret;
 }

+static int mt753x_mdio_read(struct mii_bus *bus, int addr, int regnum)
+{
+	struct mt7530_priv *priv = bus->priv;
+	struct mt7530_dummy_poll p;
+	int ret;
+	u32 val;
+
+	INIT_MT7530_DUMMY_POLL(&p, priv, MT7531_PHY_IAC);
+
+	mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED);
+
+	ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val,
+				 !(val & MT7531_PHY_ACS_ST), 20, 100000);
+	if (ret < 0) {
+		dev_err(priv->dev, "poll timeout\n");
+		goto out;
+	}
+
+	val = MT7531_MDIO_CL22_READ | MT7531_MDIO_PHY_ADDR(addr) |
+		  MT7531_MDIO_REG_ADDR(regnum);
+
+	mt7530_mii_write(priv, MT7531_PHY_IAC, val | MT7531_PHY_ACS_ST);
+
+	ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val,
+				 !(val & MT7531_PHY_ACS_ST), 20, 100000);
+	if (ret < 0) {
+		dev_err(priv->dev, "poll timeout\n");
+		goto out;
+	}
+
+	ret = val & MT7531_MDIO_RW_DATA_MASK;
+out:
+	mutex_unlock(&priv->bus->mdio_lock);
+
+	return ret;
+}
+
+static int mt753x_mdio_write(struct mii_bus *bus, int addr, int regnum, u16 val)
+{
+	struct mt7530_priv *priv = bus->priv;
+	struct mt7530_dummy_poll p;
+	int ret;
+	u32 reg;
+
+	INIT_MT7530_DUMMY_POLL(&p, priv, MT7531_PHY_IAC);
+
+	mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED);
+
+	ret = readx_poll_timeout(_mt7530_unlocked_read, &p, reg,
+				 !(reg & MT7531_PHY_ACS_ST), 20, 100000);
+	if (ret < 0) {
+		dev_err(priv->dev, "poll timeout\n");
+		goto out;
+	}
+
+	reg = MT7531_MDIO_CL22_WRITE | MT7531_MDIO_PHY_ADDR(addr) |
+		  MT7531_MDIO_REG_ADDR(regnum) | val;
+
+	mt7530_mii_write(priv, MT7531_PHY_IAC, reg | MT7531_PHY_ACS_ST);
+
+	ret = readx_poll_timeout(_mt7530_unlocked_read, &p, reg,
+				 !(reg & MT7531_PHY_ACS_ST), 20, 100000);
+	if (ret < 0) {
+		dev_err(priv->dev, "poll timeout\n");
+		goto out;
+	}
+
+out:
+	mutex_unlock(&priv->bus->mdio_lock);
+
+	return ret;
+}
+
+static int mt753x_mdio_init(struct mt7530_priv *priv)
+{
+	struct device_node *dn;
+	struct device_node *mii_np;
+	int ret;
+
+	dn = priv->dev->of_node;
+
+	mii_np = of_get_child_by_name(dn, "mdio-bus");
+	if (!mii_np) {
+		ret = -ENODEV;
+		goto err_put_node;
+	}
+
+	if (!of_device_is_available(mii_np)) {
+		ret = -ENODEV;
+		goto err_put_node;
+	}
+
+	priv->gbus = devm_mdiobus_alloc(priv->dev);
+	if (!priv->gbus) {
+		ret = -ENOMEM;
+		goto err_put_node;
+	}
+	priv->gbus->name = "mt753x_mdio";
+	priv->gbus->read = mt753x_mdio_read;
+	priv->gbus->write = mt753x_mdio_write;
+	priv->gbus->priv = priv;
+	priv->gbus->parent = priv->dev;
+
+	if(snprintf(priv->gbus->id, MII_BUS_ID_SIZE, "%s@%s", mii_np->name, dn->name) < 0) {
+		ret = -ENOMEM;
+		goto err_put_node;
+	}
+
+	ret = of_mdiobus_register(priv->gbus, mii_np);
+	if (ret)
+		priv->gbus = NULL;
+
+err_put_node:
+	of_node_put(mii_np);
+
+	return ret;
+}
+
+static void mt753x_mdio_exit(struct mt7530_priv *priv)
+{
+	if (!priv->gbus)
+		return;
+
+	mdiobus_unregister(priv->gbus);
+}
+
 static void
 mt7530_get_strings(struct dsa_switch *ds, int port, u32 stringset,
 		   uint8_t *data)
@@ -2892,6 +3018,7 @@ mt7530_probe(struct mdio_device *mdiodev
 		return ret;
 	}
 	mt7530_nl_init(&priv);
+	mt753x_mdio_init(priv);

 	return 0;
 }
@@ -2919,6 +3046,7 @@ mt7530_remove(struct mdio_device *mdiode
 		iounmap(priv->base);

 	mt7530_nl_exit();
+	mt753x_mdio_exit(priv);
 }

 static struct mdio_driver mt7530_mdio_driver = {
Index: linux-5.4.203/drivers/net/dsa/mt7530.h
===================================================================
--- linux-5.4.203.orig/drivers/net/dsa/mt7530.h
+++ linux-5.4.203/drivers/net/dsa/mt7530.h
@@ -730,6 +730,7 @@ struct mt7530_priv {
 	struct device		*dev;
 	struct dsa_switch	*ds;
 	struct mii_bus		*bus;
+	struct mii_bus		*gbus;
 	struct reset_control	*rstc;
 	struct regulator	*core_pwr;
 	struct regulator	*io_pwr;
