diff --git a/drivers/net/ethernet/marvell/Kconfig b/drivers/net/ethernet/marvell/Kconfig
index da6fb825afea..205bb7e683b7 100644
--- a/drivers/net/ethernet/marvell/Kconfig
+++ b/drivers/net/ethernet/marvell/Kconfig
@@ -35,9 +35,9 @@ config MVMDIO
 	depends on HAS_IOMEM
 	select PHYLIB
 	---help---
-	  This driver supports the MDIO interface found in the network
-	  interface units of the Marvell EBU SoCs (Kirkwood, Orion5x,
-	  Dove, Armada 370 and Armada XP).
+	  This driver supports the MDIO and xMDIO interfaces found in
+	  the network interface units of the Marvell EBU SoCs (Kirkwood,
+	  Orion5x, Dove, Armada 370, Armada XP, Armada 7k and Armada 8k).
 
 	  This driver is used by the MV643XX_ETH and MVNETA drivers.
 
diff --git a/drivers/net/ethernet/marvell/mvmdio.c b/drivers/net/ethernet/marvell/mvmdio.c
index 3cb3dd3331d8..13b198aca5c1 100644
--- a/drivers/net/ethernet/marvell/mvmdio.c
+++ b/drivers/net/ethernet/marvell/mvmdio.c
@@ -41,6 +41,15 @@
 #define  MVMDIO_ERR_INT_SMI_DONE	0x00000010
 #define MVMDIO_ERR_INT_MASK		0x0080
 
+#define MVMDIO_XSMI_MGNT_REG		0x0
+#define  MVMDIO_XSMI_READ_VALID		BIT(29)
+#define  MVMDIO_XSMI_BUSY		BIT(30)
+#define MVMDIO_XSMI_ADDR_REG		0x8
+#define  MVMDIO_XSMI_PHYADDR_SHIFT	16
+#define  MVMDIO_XSMI_DEVADDR_SHIFT	21
+#define  MVMDIO_XSMI_READ_OPERATION	(0x7 << 26)
+#define  MVMDIO_XSMI_WRITE_OPERATION	(0x5 << 27)
+
 /*
  * SMI Timeout measurements:
  * - Kirkwood 88F6281 (Globalscale Dreamplug): 45us to 95us (Interrupt)
@@ -50,6 +59,9 @@
 #define MVMDIO_SMI_POLL_INTERVAL_MIN	45
 #define MVMDIO_SMI_POLL_INTERVAL_MAX	55
 
+#define MVMDIO_XSMI_POLL_INTERVAL_MIN	150
+#define MVMDIO_XSMI_POLL_INTERVAL_MAX	160
+
 struct orion_mdio_dev {
 	struct mutex lock;
 	void __iomem *regs;
@@ -76,18 +88,19 @@ struct orion_mdio_ops {
 	void (*write)(struct orion_mdio_dev *, int, int, u16);
 };
 
-static int orion_mdio_smi_is_done(struct orion_mdio_dev *dev)
+/* smi */
+static int smi_is_done(struct orion_mdio_dev *dev)
 {
 	return !(readl(dev->regs) & MVMDIO_SMI_BUSY);
 }
 
-static int orion_mdio_smi_is_read_valid(struct orion_mdio_dev *dev)
+static int smi_is_read_valid(struct orion_mdio_dev *dev)
 {
 	return !(readl(dev->regs) & MVMDIO_SMI_READ_VALID);
 }
 
-static void orion_mdio_start_read_op(struct orion_mdio_dev *dev, int mii_id,
-				     int regnum)
+static void smi_start_read_op(struct orion_mdio_dev *dev, int mii_id,
+			      int regnum)
 {
 	writel(((mii_id << MVMDIO_SMI_PHY_ADDR_SHIFT) |
 		(regnum << MVMDIO_SMI_PHY_REG_SHIFT)  |
@@ -95,13 +108,13 @@ static void orion_mdio_start_read_op(struct orion_mdio_dev *dev, int mii_id,
 	       dev->regs);
 }
 
-static u16 orion_mdio_read_op(struct orion_mdio_dev *dev)
+static u16 smi_read_op(struct orion_mdio_dev *dev)
 {
 	return readl(dev->regs) & GENMASK(15,0);
 }
 
-static void orion_mdio_write_op(struct orion_mdio_dev *dev, int mii_id,
-				int regnum, u16 value)
+static void smi_write_op(struct orion_mdio_dev *dev, int mii_id,
+			 int regnum, u16 value)
 {
 	writel(((mii_id << MVMDIO_SMI_PHY_ADDR_SHIFT) |
 		(regnum << MVMDIO_SMI_PHY_REG_SHIFT)  |
@@ -110,6 +123,47 @@ static void orion_mdio_write_op(struct orion_mdio_dev *dev, int mii_id,
 	       dev->regs);
 }
 
+/* xsmi */
+static int xsmi_is_done(struct orion_mdio_dev *dev)
+{
+	return !(readl(dev->regs + MVMDIO_XSMI_MGNT_REG) & MVMDIO_XSMI_BUSY);
+}
+
+static int xsmi_is_read_valid(struct orion_mdio_dev *dev)
+{
+	return !(readl(dev->regs + MVMDIO_XSMI_MGNT_REG) &
+		 MVMDIO_XSMI_READ_VALID);
+}
+
+static void xsmi_start_read_op(struct orion_mdio_dev *dev, int mii_id,
+			      int regnum)
+{
+	u16 dev_addr = regnum >> 16;
+
+	writel(regnum & GENMASK(15,0), dev->regs + MVMDIO_XSMI_ADDR_REG);
+	writel((mii_id << MVMDIO_XSMI_PHYADDR_SHIFT) |
+	       (dev_addr << MVMDIO_XSMI_DEVADDR_SHIFT) |
+	       MVMDIO_XSMI_READ_OPERATION,
+	       dev->regs + MVMDIO_XSMI_MGNT_REG);
+}
+
+static u16 xsmi_read_op(struct orion_mdio_dev *dev)
+{
+	return readl(dev->regs + MVMDIO_XSMI_MGNT_REG) & GENMASK(15,0);
+}
+
+static void xsmi_write_op(struct orion_mdio_dev *dev, int mii_id,
+			 int regnum, u16 value)
+{
+	u16 dev_addr = regnum >> 16;
+
+	writel(regnum & GENMASK(15,0), dev->regs + MVMDIO_XSMI_ADDR_REG);
+	writel((mii_id << MVMDIO_XSMI_PHYADDR_SHIFT) |
+	       (dev_addr << MVMDIO_XSMI_DEVADDR_SHIFT) |
+	       MVMDIO_XSMI_WRITE_OPERATION | value,
+	       dev->regs + MVMDIO_XSMI_MGNT_REG);
+}
+
 /* Wait for the SMI unit to be ready for another operation
  */
 static int orion_mdio_wait_ready(struct mii_bus *bus)
@@ -213,12 +267,47 @@ static irqreturn_t orion_mdio_err_irq(int irq, void *dev_id)
 	return IRQ_NONE;
 }
 
+static int orion_mdio_populate_ops(struct platform_device *pdev,
+				   struct orion_mdio_dev *dev)
+{
+	struct orion_mdio_ops *ops;
+	struct device_node *np = pdev->dev.of_node;
+
+	ops = devm_kzalloc(&pdev->dev, sizeof(*ops), GFP_KERNEL);
+	if (!ops)
+		return -ENOMEM;
+
+	if (of_device_is_compatible(np, "marvell,orion-mdio")) {
+		ops->is_done = smi_is_done;
+		ops->is_read_valid = smi_is_read_valid;
+		ops->start_read = smi_start_read_op;
+		ops->read = smi_read_op;
+		ops->write = smi_write_op;
+
+		dev->poll_interval_min = MVMDIO_SMI_POLL_INTERVAL_MIN;
+		dev->poll_interval_max = MVMDIO_SMI_POLL_INTERVAL_MAX;
+	} else if (of_device_is_compatible(np, "marvell,xmdio")) {
+		ops->is_done = xsmi_is_done;
+		ops->is_read_valid = xsmi_is_read_valid;
+		ops->start_read = xsmi_start_read_op;
+		ops->read = xsmi_read_op;
+		ops->write = xsmi_write_op;
+
+		dev->poll_interval_min = MVMDIO_XSMI_POLL_INTERVAL_MIN;
+		dev->poll_interval_max = MVMDIO_XSMI_POLL_INTERVAL_MAX;
+	} else {
+		return -EINVAL;
+	}
+
+	dev->ops = ops;
+	return 0;
+}
+
 static int orion_mdio_probe(struct platform_device *pdev)
 {
 	struct resource *r;
 	struct mii_bus *bus;
 	struct orion_mdio_dev *dev;
-	struct orion_mdio_ops *ops;
 	int i, ret;
 
 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -278,18 +367,9 @@ static int orion_mdio_probe(struct platform_device *pdev)
 
 	mutex_init(&dev->lock);
 
-	ops = devm_kzalloc(&pdev->dev, sizeof(*ops), GFP_KERNEL);
-	if (!ops)
-		return -ENOMEM;
-
-	dev->poll_interval_min = MVMDIO_SMI_POLL_INTERVAL_MIN;
-	dev->poll_interval_max = MVMDIO_SMI_POLL_INTERVAL_MAX;
-	ops->is_done = orion_mdio_smi_is_done;
-	ops->is_read_valid = orion_mdio_smi_is_read_valid;
-	ops->start_read = orion_mdio_start_read_op;
-	ops->read = orion_mdio_read_op;
-	ops->write = orion_mdio_write_op;
-	dev->ops = ops;
+	ret = orion_mdio_populate_ops(pdev, dev);
+	if (ret)
+		return ret;
 
 	if (pdev->dev.of_node)
 		ret = of_mdiobus_register(bus, pdev->dev.of_node);
@@ -340,6 +420,7 @@ static int orion_mdio_remove(struct platform_device *pdev)
 
 static const struct of_device_id orion_mdio_match[] = {
 	{ .compatible = "marvell,orion-mdio" },
+	{ .compatible = "marvell,xmdio" },
 	{ }
 };
 MODULE_DEVICE_TABLE(of, orion_mdio_match);
