diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 4d1013c984..d77bb221e0 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -57,6 +57,12 @@ config MDIO_MUX_SANDBOX
 
 	  This driver is used for testing in test/dm/mdio.c
 
+config DM_ETH_PHY
+	bool "Enable Driver Model for Ethernet Generic PHY drivers"
+	depends on DM
+	help
+	  Enable driver model for Ethernet Generic PHY .
+
 menuconfig NETDEVICES
 	bool "Network device support"
 	depends on NET
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 6e0a68834d..f6c5ae4fe7 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_ETH_DESIGNWARE) += designware.o
 obj-$(CONFIG_ETH_DESIGNWARE_SOCFPGA) += dwmac_socfpga.o
 obj-$(CONFIG_DRIVER_DM9000) += dm9000x.o
 obj-$(CONFIG_DNET) += dnet.o
+obj-$(CONFIG_DM_ETH_PHY) += eth-phy-uclass.o
 obj-$(CONFIG_E1000) += e1000.o
 obj-$(CONFIG_E1000_SPI) += e1000_spi.o
 obj-$(CONFIG_EEPRO100) += eepro100.o
diff --git a/drivers/net/eth-phy-uclass.c b/drivers/net/eth-phy-uclass.c
new file mode 100644
index 0000000000..e87c7aee80
--- /dev/null
+++ b/drivers/net/eth-phy-uclass.c
@@ -0,0 +1,122 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2020 NXP
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <net.h>
+#include <dm/device-internal.h>
+#include <dm/uclass-internal.h>
+#include <dm/lists.h>
+
+struct eth_phy_device_priv {
+	struct mii_dev *mdio_bus;
+};
+
+int eth_phy_binds_nodes(struct udevice *eth_dev)
+{
+	ofnode mdio_node, phy_node;
+	const char *node_name;
+	int ret;
+
+	mdio_node = dev_read_subnode(eth_dev, "mdio");
+	if (!ofnode_valid(mdio_node)) {
+		debug("%s: %s mdio subnode not found!", __func__,
+		      eth_dev->name);
+		return -ENXIO;
+	}
+
+	ofnode_for_each_subnode(phy_node, mdio_node) {
+		node_name = ofnode_get_name(phy_node);
+
+		debug("* Found child node: '%s'\n", node_name);
+
+		ret = device_bind_driver_to_node(eth_dev,
+						 "eth_phy_generic_drv",
+						 node_name, phy_node, NULL);
+		if (ret) {
+			debug("  - Eth phy binding error: %d\n", ret);
+			continue;
+		}
+
+		debug("  - bound phy device: '%s'\n", node_name);
+	}
+
+	return 0;
+}
+
+int eth_phy_set_mdio_bus(struct udevice *eth_dev, struct mii_dev *mdio_bus)
+{
+	struct udevice *dev;
+	struct eth_phy_device_priv *uc_priv;
+
+	for (uclass_first_device(UCLASS_ETH_PHY, &dev); dev;
+	     uclass_next_device(&dev)) {
+		if (dev->parent == eth_dev) {
+			uc_priv = (struct eth_phy_device_priv *)(dev->uclass_priv);
+
+			if (!uc_priv->mdio_bus)
+				uc_priv->mdio_bus = mdio_bus;
+		}
+	}
+
+	return 0;
+}
+
+struct mii_dev *eth_phy_get_mdio_bus(struct udevice *eth_dev)
+{
+	int ret;
+	struct udevice *phy_dev;
+	struct eth_phy_device_priv *uc_priv;
+
+	/* Will probe the parent of phy device, then phy device */
+	ret = uclass_get_device_by_phandle(UCLASS_ETH_PHY, eth_dev,
+					   "phy-handle", &phy_dev);
+	if (!ret) {
+		if (eth_dev != phy_dev->parent) {
+			/*
+			 * phy_dev is shared and controlled by
+			 * other eth controller
+			 */
+			uc_priv = (struct eth_phy_device_priv *)(phy_dev->uclass_priv);
+			if (uc_priv->mdio_bus)
+				printf("Get shared mii bus on %s\n", eth_dev->name);
+			else
+				printf("Can't get shared mii bus on %s\n", eth_dev->name);
+
+			return uc_priv->mdio_bus;
+		}
+	} else {
+		printf("FEC: can't find phy-handle\n");
+	}
+
+	return NULL;
+}
+
+int eth_phy_get_addr(struct udevice *dev)
+{
+	struct ofnode_phandle_args phandle_args;
+	int reg;
+
+	if (dev_read_phandle_with_args(dev, "phy-handle", NULL, 0, 0,
+				       &phandle_args)) {
+		debug("Failed to find phy-handle");
+		return -ENODEV;
+	}
+
+	reg = ofnode_read_u32_default(phandle_args.node, "reg", 0);
+
+	return reg;
+}
+
+UCLASS_DRIVER(eth_phy_generic) = {
+	.id		= UCLASS_ETH_PHY,
+	.name		= "eth_phy_generic",
+	.per_device_auto_alloc_size = sizeof(struct eth_phy_device_priv),
+};
+
+U_BOOT_DRIVER(eth_phy_generic_drv) = {
+	.name		= "eth_phy_generic_drv",
+	.id		= UCLASS_ETH_PHY,
+};
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 37ada51f9f..7837d459f1 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -47,6 +47,7 @@ enum uclass_id {
 	UCLASS_DMA,		/* Direct Memory Access */
 	UCLASS_EFI,		/* EFI managed devices */
 	UCLASS_ETH,		/* Ethernet device */
+	UCLASS_ETH_PHY,		/* Ethernet PHY device */
 	UCLASS_FIRMWARE,	/* Firmware */
 	UCLASS_FS_FIRMWARE_LOADER,		/* Generic loader */
 	UCLASS_GPIO,		/* Bank of general-purpose I/O pins */
diff --git a/include/eth_phy.h b/include/eth_phy.h
new file mode 100644
index 0000000000..50c496ff42
--- /dev/null
+++ b/include/eth_phy.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2020 NXP
+ */
+
+#ifndef _eth_phy_h_
+#define _eth_phy_h_
+
+#include <dm.h>
+#include <phy.h>
+
+int eth_phy_binds_nodes(struct udevice *eth_dev);
+int eth_phy_set_mdio_bus(struct udevice *eth_dev, struct mii_dev *mdio_bus);
+struct mii_dev *eth_phy_get_mdio_bus(struct udevice *eth_dev);
+int eth_phy_get_addr(struct udevice *dev);
+
+#endif
diff --git a/net/eth-uclass.c b/net/eth-uclass.c
index 950a48d520..48560d59f6 100644
--- a/net/eth-uclass.c
+++ b/net/eth-uclass.c
@@ -13,6 +13,7 @@
 #include <dm/uclass-internal.h>
 #include <net/pcap.h>
 #include "eth_internal.h"
+#include <eth_phy.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -461,6 +462,10 @@ static int eth_post_bind(struct udevice *dev)
 		return -EINVAL;
 	}
 
+#ifdef CONFIG_DM_ETH_PHY
+	eth_phy_binds_nodes(dev);
+#endif
+
 	return 0;
 }
 
