#include <linux/list.h>
 #include <linux/mdio.h>
 #include <linux/module.h>
+#include <linux/of_mdio.h>
 #include <linux/netdevice.h>
 #include <linux/gpio/consumer.h>
 #include <linux/phy.h>
        int i;
 
        ps->ds = ds;
+       ds->slave_mii_bus = ps->mdio_bus;
 
        if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_EEPROM))
                mutex_init(&ps->eeprom_mutex);
 
-       if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_PPU))
-               mv88e6xxx_ppu_state_init(ps);
-
        mutex_lock(&ps->smi_mutex);
 
        err = mv88e6xxx_switch_reset(ps);
        return -EINVAL;
 }
 
-static int mv88e6xxx_mdio_read(struct dsa_switch *ds, int port, int regnum)
+static int mv88e6xxx_mdio_read(struct mii_bus *bus, int port, int regnum)
 {
-       struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+       struct mv88e6xxx_priv_state *ps = bus->priv;
        int addr = mv88e6xxx_port_to_mdio_addr(ps, port);
        int ret;
 
        return ret;
 }
 
-static int mv88e6xxx_mdio_write(struct dsa_switch *ds, int port, int regnum,
+static int mv88e6xxx_mdio_write(struct mii_bus *bus, int port, int regnum,
                                u16 val)
 {
-       struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
+       struct mv88e6xxx_priv_state *ps = bus->priv;
        int addr = mv88e6xxx_port_to_mdio_addr(ps, port);
        int ret;
 
        return ret;
 }
 
+static int mv88e6xxx_mdio_register(struct mv88e6xxx_priv_state *ps,
+                                  struct device_node *np)
+{
+       static int index;
+       struct mii_bus *bus;
+       int err;
+
+       if (mv88e6xxx_has(ps, MV88E6XXX_FLAG_PPU))
+               mv88e6xxx_ppu_state_init(ps);
+
+       if (np)
+               ps->mdio_np = of_get_child_by_name(np, "mdio");
+
+       bus = devm_mdiobus_alloc(ps->dev);
+       if (!bus)
+               return -ENOMEM;
+
+       bus->priv = (void *)ps;
+       if (np) {
+               bus->name = np->full_name;
+               snprintf(bus->id, MII_BUS_ID_SIZE, "%s", np->full_name);
+       } else {
+               bus->name = "mv88e6xxx SMI";
+               snprintf(bus->id, MII_BUS_ID_SIZE, "mv88e6xxx-%d", index++);
+       }
+
+       bus->read = mv88e6xxx_mdio_read;
+       bus->write = mv88e6xxx_mdio_write;
+       bus->parent = ps->dev;
+
+       if (ps->mdio_np)
+               err = of_mdiobus_register(bus, ps->mdio_np);
+       else
+               err = mdiobus_register(bus);
+       if (err) {
+               dev_err(ps->dev, "Cannot register MDIO bus (%d)\n", err);
+               goto out;
+       }
+       ps->mdio_bus = bus;
+
+       return 0;
+
+out:
+       if (ps->mdio_np)
+               of_node_put(ps->mdio_np);
+
+       return err;
+}
+
+static void mv88e6xxx_mdio_unregister(struct mv88e6xxx_priv_state *ps)
+
+{
+       struct mii_bus *bus = ps->mdio_bus;
+
+       mdiobus_unregister(bus);
+
+       if (ps->mdio_np)
+               of_node_put(ps->mdio_np);
+}
+
 #ifdef CONFIG_NET_DSA_HWMON
 
 static int mv88e61xx_get_temp(struct dsa_switch *ds, int *temp)
        struct mii_bus *bus;
        const char *name;
        int id, prod_num, rev;
+       int err;
 
        bus = dsa_host_dev_to_mii_bus(host_dev);
        if (!bus)
        ps->bus = bus;
        ps->sw_addr = sw_addr;
        ps->info = info;
+       ps->dev = dsa_dev;
        mutex_init(&ps->smi_mutex);
 
+       err = mv88e6xxx_mdio_register(ps, NULL);
+       if (err)
+               return NULL;
+
        *priv = ps;
 
        dev_info(&ps->bus->dev, "switch 0x%x probed: %s, revision %u\n",
        .probe                  = mv88e6xxx_drv_probe,
        .setup                  = mv88e6xxx_setup,
        .set_addr               = mv88e6xxx_set_addr,
-       .phy_read               = mv88e6xxx_mdio_read,
-       .phy_write              = mv88e6xxx_mdio_write,
        .adjust_link            = mv88e6xxx_adjust_link,
        .get_strings            = mv88e6xxx_get_strings,
        .get_ethtool_stats      = mv88e6xxx_get_ethtool_stats,
            !of_property_read_u32(np, "eeprom-length", &eeprom_len))
                ps->eeprom_len = eeprom_len;
 
+       err = mv88e6xxx_mdio_register(ps, mdiodev->dev.of_node);
+       if (err)
+               return err;
+
+       ds->slave_mii_bus = ps->mdio_bus;
+
        dev_set_drvdata(dev, ds);
 
        dev_info(dev, "switch 0x%x probed: %s, revision %u\n",
        struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
 
        put_device(&ps->bus->dev);
+
+       mv88e6xxx_mdio_unregister(ps);
 }
 
 static const struct of_device_id mv88e6xxx_of_match[] = {