blob: 5a130b140f4739837d431c08bb0f46c81b398d2e [file] [log] [blame]
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;