- interrupt-controller : Indicates the switch is itself an interrupt
                          controller. This is used for the PHY interrupts.
 #interrupt-cells = <2> : Controller uses two cells, number and flag
-- mdio                 : container of PHY and devices on the switches MDIO
-                         bus
+- mdio                 : Container of PHY and devices on the switches MDIO
+                         bus.
+- mdio?                        : Container of PHYs and devices on the external MDIO
+                         bus. The node must contains a compatible string of
+                         "marvell,mv88e6xxx-mdio-external"
+
 Example:
 
        mdio {
                        };
                };
        };
+
+       mdio {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               interrupt-parent = <&gpio0>;
+               interrupts = <27 IRQ_TYPE_LEVEL_LOW>;
+               interrupt-controller;
+               #interrupt-cells = <2>;
+
+               switch0: switch@0 {
+                       compatible = "marvell,mv88e6390";
+                       reg = <0>;
+                      reset-gpios = <&gpio5 1 GPIO_ACTIVE_LOW>;
+               };
+               mdio {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       switch1phy0: switch1phy0@0 {
+                               reg = <0>;
+                               interrupt-parent = <&switch0>;
+                               interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
+                       };
+               };
+
+               mdio1 {
+                       compatible = "marvell,mv88e6xxx-mdio-external";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       switch1phy9: switch1phy0@9 {
+                               reg = <9>;
+                       };
+               };
+       };
 
        return mv88e6xxx_write(chip, addr, reg, val);
 }
 
+static struct mii_bus *mv88e6xxx_default_mdio_bus(struct mv88e6xxx_chip *chip)
+{
+       struct mv88e6xxx_mdio_bus *mdio_bus;
+
+       mdio_bus = list_first_entry(&chip->mdios, struct mv88e6xxx_mdio_bus,
+                                   list);
+       if (!mdio_bus)
+               return NULL;
+
+       return mdio_bus->bus;
+}
+
 static int mv88e6xxx_phy_read(struct mv88e6xxx_chip *chip, int phy,
                              int reg, u16 *val)
 {
        int addr = phy; /* PHY devices addresses start at 0x0 */
-       struct mii_bus *bus = chip->mdio_bus;
+       struct mii_bus *bus;
 
-       if (!chip->info->ops->phy_read)
+       bus = mv88e6xxx_default_mdio_bus(chip);
+       if (!bus)
                return -EOPNOTSUPP;
 
-       if (!bus)
+       if (!chip->info->ops->phy_read)
                return -EOPNOTSUPP;
 
        return chip->info->ops->phy_read(chip, bus, addr, reg, val);
                               int reg, u16 val)
 {
        int addr = phy; /* PHY devices addresses start at 0x0 */
-       struct mii_bus *bus = chip->mdio_bus;
+       struct mii_bus *bus;
 
-       if (!chip->info->ops->phy_write)
+       bus = mv88e6xxx_default_mdio_bus(chip);
+       if (!bus)
                return -EOPNOTSUPP;
 
-       if (!bus)
+       if (!chip->info->ops->phy_write)
                return -EOPNOTSUPP;
 
        return chip->info->ops->phy_write(chip, bus, addr, reg, val);
        int i;
 
        chip->ds = ds;
-       ds->slave_mii_bus = chip->mdio_bus;
+       ds->slave_mii_bus = mv88e6xxx_default_mdio_bus(chip);
 
        mutex_lock(&chip->reg_lock);
 
 }
 
 static int mv88e6xxx_mdio_register(struct mv88e6xxx_chip *chip,
-                                  struct device_node *np)
+                                  struct device_node *np,
+                                  bool external)
 {
        static int index;
        struct mv88e6xxx_mdio_bus *mdio_bus;
        struct mii_bus *bus;
        int err;
 
-       if (np)
-               chip->mdio_np = of_get_child_by_name(np, "mdio");
-
        bus = devm_mdiobus_alloc_size(chip->dev, sizeof(*mdio_bus));
        if (!bus)
                return -ENOMEM;
 
        mdio_bus = bus->priv;
+       mdio_bus->bus = bus;
        mdio_bus->chip = chip;
+       INIT_LIST_HEAD(&mdio_bus->list);
+       mdio_bus->external = external;
 
        if (np) {
                bus->name = np->full_name;
        bus->write = mv88e6xxx_mdio_write;
        bus->parent = chip->dev;
 
-       if (chip->mdio_np)
-               err = of_mdiobus_register(bus, chip->mdio_np);
+       if (np)
+               err = of_mdiobus_register(bus, np);
        else
                err = mdiobus_register(bus);
        if (err) {
                dev_err(chip->dev, "Cannot register MDIO bus (%d)\n", err);
-               goto out;
+               return err;
        }
-       chip->mdio_bus = bus;
+
+       if (external)
+               list_add_tail(&mdio_bus->list, &chip->mdios);
+       else
+               list_add(&mdio_bus->list, &chip->mdios);
 
        return 0;
+}
 
-out:
-       if (chip->mdio_np)
-               of_node_put(chip->mdio_np);
+static const struct of_device_id mv88e6xxx_mdio_external_match[] = {
+       { .compatible = "marvell,mv88e6xxx-mdio-external",
+         .data = (void *)true },
+       { },
+};
 
-       return err;
+static int mv88e6xxx_mdios_register(struct mv88e6xxx_chip *chip,
+                                   struct device_node *np)
+{
+       const struct of_device_id *match;
+       struct device_node *child;
+       int err;
+
+       /* Always register one mdio bus for the internal/default mdio
+        * bus. This maybe represented in the device tree, but is
+        * optional.
+        */
+       child = of_get_child_by_name(np, "mdio");
+       err = mv88e6xxx_mdio_register(chip, child, false);
+       if (err)
+               return err;
+
+       /* Walk the device tree, and see if there are any other nodes
+        * which say they are compatible with the external mdio
+        * bus.
+        */
+       for_each_available_child_of_node(np, child) {
+               match = of_match_node(mv88e6xxx_mdio_external_match, child);
+               if (match) {
+                       err = mv88e6xxx_mdio_register(chip, child, true);
+                       if (err)
+                               return err;
+               }
+       }
+
+       return 0;
 }
 
-static void mv88e6xxx_mdio_unregister(struct mv88e6xxx_chip *chip)
+static void mv88e6xxx_mdios_unregister(struct mv88e6xxx_chip *chip)
 
 {
-       struct mii_bus *bus = chip->mdio_bus;
+       struct mv88e6xxx_mdio_bus *mdio_bus;
+       struct mii_bus *bus;
 
-       mdiobus_unregister(bus);
+       list_for_each_entry(mdio_bus, &chip->mdios, list) {
+               bus = mdio_bus->bus;
 
-       if (chip->mdio_np)
-               of_node_put(chip->mdio_np);
+               mdiobus_unregister(bus);
+       }
 }
 
 static int mv88e6xxx_get_eeprom_len(struct dsa_switch *ds)
        chip->dev = dev;
 
        mutex_init(&chip->reg_lock);
+       INIT_LIST_HEAD(&chip->mdios);
 
        return chip;
 }
 
        mv88e6xxx_phy_init(chip);
 
-       err = mv88e6xxx_mdio_register(chip, NULL);
+       err = mv88e6xxx_mdios_register(chip, NULL);
        if (err)
                goto free;
 
                }
        }
 
-       err = mv88e6xxx_mdio_register(chip, np);
+       err = mv88e6xxx_mdios_register(chip, np);
        if (err)
                goto out_g2_irq;
 
        return 0;
 
 out_mdio:
-       mv88e6xxx_mdio_unregister(chip);
+       mv88e6xxx_mdios_unregister(chip);
 out_g2_irq:
        if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_INT) && chip->irq > 0)
                mv88e6xxx_g2_irq_free(chip);
 
        mv88e6xxx_phy_destroy(chip);
        mv88e6xxx_unregister_switch(chip);
-       mv88e6xxx_mdio_unregister(chip);
+       mv88e6xxx_mdios_unregister(chip);
 
        if (chip->irq > 0) {
                if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_INT))