diff --git a/arch/arm/cpu/armv8/fsl-layerscape/cpu.c b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c
index 40c2c3a1cfe229bfb8f76195ba5c97fb8152f73e..052e0708d4547791f12fba11b077a997005ee859 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/cpu.c
+++ b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c
@@ -9,6 +9,7 @@
 #include <asm/io.h>
 #include <linux/errno.h>
 #include <asm/system.h>
+#include <fm_eth.h>
 #include <asm/armv8/mmu.h>
 #include <asm/io.h>
 #include <asm/arch/fsl_serdes.h>
@@ -18,7 +19,6 @@
 #include <fsl_immap.h>
 #include <asm/arch/mp.h>
 #include <efi_loader.h>
-#include <fm_eth.h>
 #include <fsl-mc/fsl_mc.h>
 #ifdef CONFIG_FSL_ESDHC
 #include <fsl_esdhc.h>
diff --git a/arch/sandbox/cpu/eth-raw-os.c b/arch/sandbox/cpu/eth-raw-os.c
index e054a0702a69b3cadbdea9854b9d2e42a19759ce..75bfaa4c90a759d218a243dafafc43212f2e4b1e 100644
--- a/arch/sandbox/cpu/eth-raw-os.c
+++ b/arch/sandbox/cpu/eth-raw-os.c
@@ -1,9 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * Copyright (c) 2015 National Instruments
- *
- * (C) Copyright 2015
- * Joe Hershberger <joe.hershberger@ni.com>
+ * Copyright (c) 2015-2018 National Instruments
+ * Copyright (c) 2015-2018 Joe Hershberger <joe.hershberger@ni.com>
  */
 
 #include <asm/eth-raw-os.h>
@@ -25,8 +23,46 @@
 #include <linux/if_ether.h>
 #include <linux/if_packet.h>
 
-static int _raw_packet_start(const char *ifname, unsigned char *ethmac,
-			    struct eth_sandbox_raw_priv *priv)
+struct sandbox_eth_raw_if_nameindex *sandbox_eth_raw_if_nameindex(void)
+{
+	return (struct sandbox_eth_raw_if_nameindex *)if_nameindex();
+}
+
+void sandbox_eth_raw_if_freenameindex(struct sandbox_eth_raw_if_nameindex *ptr)
+{
+	if_freenameindex((struct if_nameindex *)ptr);
+}
+
+int sandbox_eth_raw_os_is_local(const char *ifname)
+{
+	int fd = socket(AF_INET, SOCK_DGRAM, 0);
+	struct ifreq ifr;
+	int ret = 0;
+
+	if (fd < 0)
+		return -errno;
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
+	ret = ioctl(fd, SIOCGIFFLAGS, &ifr);
+	if (ret < 0) {
+		ret = -errno;
+		goto out;
+	}
+	ret = !!(ifr.ifr_flags & IFF_LOOPBACK);
+out:
+	close(fd);
+	return ret;
+}
+
+int sandbox_eth_raw_os_idx_to_name(struct eth_sandbox_raw_priv *priv)
+{
+	if (!if_indextoname(priv->host_ifindex, priv->host_ifname))
+		return -errno;
+	return 0;
+}
+
+static int _raw_packet_start(struct eth_sandbox_raw_priv *priv,
+			     unsigned char *ethmac)
 {
 	struct sockaddr_ll *device;
 	struct packet_mreq mr;
@@ -34,12 +70,14 @@ static int _raw_packet_start(const char *ifname, unsigned char *ethmac,
 	int flags;
 
 	/* Prepare device struct */
+	priv->local_bind_sd = -1;
 	priv->device = malloc(sizeof(struct sockaddr_ll));
 	if (priv->device == NULL)
 		return -ENOMEM;
 	device = priv->device;
 	memset(device, 0, sizeof(struct sockaddr_ll));
-	device->sll_ifindex = if_nametoindex(ifname);
+	device->sll_ifindex = if_nametoindex(priv->host_ifname);
+	priv->host_ifindex = device->sll_ifindex;
 	device->sll_family = AF_PACKET;
 	memcpy(device->sll_addr, ethmac, 6);
 	device->sll_halen = htons(6);
@@ -52,11 +90,11 @@ static int _raw_packet_start(const char *ifname, unsigned char *ethmac,
 		return -errno;
 	}
 	/* Bind to the specified interface */
-	ret = setsockopt(priv->sd, SOL_SOCKET, SO_BINDTODEVICE, ifname,
-		   strlen(ifname) + 1);
+	ret = setsockopt(priv->sd, SOL_SOCKET, SO_BINDTODEVICE,
+			 priv->host_ifname, strlen(priv->host_ifname) + 1);
 	if (ret < 0) {
-		printf("Failed to bind to '%s': %d %s\n", ifname, errno,
-		       strerror(errno));
+		printf("Failed to bind to '%s': %d %s\n", priv->host_ifname,
+		       errno, strerror(errno));
 		return -errno;
 	}
 
@@ -75,11 +113,12 @@ static int _raw_packet_start(const char *ifname, unsigned char *ethmac,
 		printf("Failed to set promiscuous mode: %d %s\n"
 		       "Falling back to the old \"flags\" way...\n",
 			errno, strerror(errno));
-		if (strlen(ifname) >= IFNAMSIZ) {
-			printf("Interface name %s is too long.\n", ifname);
+		if (strlen(priv->host_ifname) >= IFNAMSIZ) {
+			printf("Interface name %s is too long.\n",
+			       priv->host_ifname);
 			return -EINVAL;
 		}
-		strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
+		strncpy(ifr.ifr_name, priv->host_ifname, IFNAMSIZ);
 		if (ioctl(priv->sd, SIOCGIFFLAGS, &ifr) < 0) {
 			printf("Failed to read flags: %d %s\n", errno,
 			       strerror(errno));
@@ -103,6 +142,8 @@ static int _local_inet_start(struct eth_sandbox_raw_priv *priv)
 	int one = 1;
 
 	/* Prepare device struct */
+	priv->local_bind_sd = -1;
+	priv->local_bind_udp_port = 0;
 	priv->device = malloc(sizeof(struct sockaddr_in));
 	if (priv->device == NULL)
 		return -ENOMEM;
@@ -136,18 +177,16 @@ static int _local_inet_start(struct eth_sandbox_raw_priv *priv)
 		       strerror(errno));
 		return -errno;
 	}
-	priv->local_bind_sd = -1;
-	priv->local_bind_udp_port = 0;
 	return 0;
 }
 
-int sandbox_eth_raw_os_start(const char *ifname, unsigned char *ethmac,
-			    struct eth_sandbox_raw_priv *priv)
+int sandbox_eth_raw_os_start(struct eth_sandbox_raw_priv *priv,
+			     unsigned char *ethmac)
 {
 	if (priv->local)
 		return _local_inet_start(priv);
 	else
-		return _raw_packet_start(ifname, ethmac, priv);
+		return _raw_packet_start(priv, ethmac);
 }
 
 int sandbox_eth_raw_os_send(void *packet, int length,
@@ -156,7 +195,7 @@ int sandbox_eth_raw_os_send(void *packet, int length,
 	int retval;
 	struct udphdr *udph = packet + sizeof(struct iphdr);
 
-	if (!priv->sd || !priv->device)
+	if (priv->sd < 0 || !priv->device)
 		return -EINVAL;
 
 	/*
@@ -221,7 +260,7 @@ int sandbox_eth_raw_os_recv(void *packet, int *length,
 	int retval;
 	int saddr_size;
 
-	if (!priv->sd || !priv->device)
+	if (priv->sd < 0 || !priv->device)
 		return -EINVAL;
 	saddr_size = sizeof(struct sockaddr);
 	retval = recvfrom(priv->sd, packet, 1536, 0,
diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts
index 0ea2452742d33ee039b4e014dfd41072c34db7b1..9f444c96a9ecead08d1745d2e82089e19eea3498 100644
--- a/arch/sandbox/dts/sandbox.dts
+++ b/arch/sandbox/dts/sandbox.dts
@@ -8,7 +8,6 @@
 	model = "sandbox";
 
 	aliases {
-		eth5 = "/eth@90000000";
 		i2c0 = &i2c_0;
 		pci0 = &pci;
 		rtc0 = &rtc_0;
@@ -47,24 +46,17 @@
 		};
 	};
 
+	ethrawbus {
+		compatible = "sandbox,eth-raw-bus";
+		skip-localhost = <0>;
+	};
+
 	eth@10002000 {
 		compatible = "sandbox,eth";
 		reg = <0x10002000 0x1000>;
 		fake-host-hwaddr = [00 00 66 44 22 00];
 	};
 
-	eth@80000000 {
-		compatible = "sandbox,eth-raw";
-		reg = <0x80000000 0x1000>;
-		host-raw-interface = "eth0";
-	};
-
-	eth@90000000 {
-		compatible = "sandbox,eth-raw";
-		reg = <0x90000000 0x1000>;
-		host-raw-interface = "lo";
-	};
-
 	gpio_a: gpios@0 {
 		gpio-controller;
 		compatible = "sandbox,gpio";
diff --git a/arch/sandbox/dts/sandbox64.dts b/arch/sandbox/dts/sandbox64.dts
index 48e420e721ee6e1ec3985eaf4ef2842aa7f0efe8..9e65d2fda3d3eadfff3a303801ee17bb1b0854d9 100644
--- a/arch/sandbox/dts/sandbox64.dts
+++ b/arch/sandbox/dts/sandbox64.dts
@@ -8,7 +8,6 @@
 	model = "sandbox";
 
 	aliases {
-		eth5 = "/eth@90000000";
 		i2c0 = &i2c_0;
 		pci0 = &pci;
 		rtc0 = &rtc_0;
@@ -47,24 +46,17 @@
 		};
 	};
 
+	ethrawbus {
+		compatible = "sandbox,eth-raw-bus";
+		skip-localhost = <1>;
+	};
+
 	eth@10002000 {
 		compatible = "sandbox,eth";
 		reg = <0x0 0x10002000 0x0 0x1000>;
 		fake-host-hwaddr = [00 00 66 44 22 00];
 	};
 
-	eth@80000000 {
-		compatible = "sandbox,eth-raw";
-		reg = <0x0 0x80000000 0x0 0x1000>;
-		host-raw-interface = "eth0";
-	};
-
-	eth@90000000 {
-		compatible = "sandbox,eth-raw";
-		reg = <0x0 0x90000000 0x0 0x1000>;
-		host-raw-interface = "lo";
-	};
-
 	gpio_a: gpios@0 {
 		gpio-controller;
 		compatible = "sandbox,gpio";
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 01e6bc03670ebf495db13d98566f41e1428a159c..137679abea9ccbc54de8d49e11277fd9810b486f 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -155,25 +155,25 @@
 	eth@10002000 {
 		compatible = "sandbox,eth";
 		reg = <0x10002000 0x1000>;
-		fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x00>;
+		fake-host-hwaddr = [00 00 66 44 22 00];
 	};
 
 	eth_5: eth@10003000 {
 		compatible = "sandbox,eth";
 		reg = <0x10003000 0x1000>;
-		fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x11>;
+		fake-host-hwaddr = [00 00 66 44 22 11];
 	};
 
 	eth_3: sbe5 {
 		compatible = "sandbox,eth";
 		reg = <0x10005000 0x1000>;
-		fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x33>;
+		fake-host-hwaddr = [00 00 66 44 22 33];
 	};
 
 	eth@10004000 {
 		compatible = "sandbox,eth";
 		reg = <0x10004000 0x1000>;
-		fake-host-hwaddr = <0x00 0x00 0x66 0x44 0x22 0x22>;
+		fake-host-hwaddr = [00 00 66 44 22 22];
 	};
 
 	gpio_a: base-gpios {
diff --git a/arch/sandbox/include/asm/eth-raw-os.h b/arch/sandbox/include/asm/eth-raw-os.h
index f986d3142dcf1f818dfbad44c061e62a191d64c1..0b511db70c39c210076bff68ee246db406a1d948 100644
--- a/arch/sandbox/include/asm/eth-raw-os.h
+++ b/arch/sandbox/include/asm/eth-raw-os.h
@@ -9,10 +9,14 @@
 #ifndef __ETH_RAW_OS_H
 #define __ETH_RAW_OS_H
 
+#define	IFNAMSIZ	16
+
 /**
  * struct eth_sandbox_raw_priv - raw socket session
  *
  * sd: socket descriptor - the open socket during a session
+ * host_ifname: interface name on the host to use for sending our packets
+ * host_ifindex: interface index number on the host
  * device: struct sockaddr_ll - the host interface packets move to/from
  * local: 1 or 0 to select the local interface ('lo') or not
  * local_bindsd: socket descriptor to prevent the kernel from sending
@@ -22,14 +26,44 @@
  */
 struct eth_sandbox_raw_priv {
 	int sd;
+	char host_ifname[IFNAMSIZ];
+	unsigned int host_ifindex;
 	void *device;
 	int local;
 	int local_bind_sd;
 	unsigned short local_bind_udp_port;
 };
 
-int sandbox_eth_raw_os_start(const char *ifname, unsigned char *ethmac,
-			    struct eth_sandbox_raw_priv *priv);
+/* A struct to mimic if_nameindex but that does not depend on Linux headers */
+struct sandbox_eth_raw_if_nameindex {
+	unsigned int if_index; /* Index of interface (1, 2, ...) */
+	char        *if_name;  /* Null-terminated name ("eth0", etc.) */
+};
+
+/* Enumerate host network interfaces */
+struct sandbox_eth_raw_if_nameindex *sandbox_eth_raw_if_nameindex(void);
+/* Free the data structure of enumerated network interfaces */
+void sandbox_eth_raw_if_freenameindex(struct sandbox_eth_raw_if_nameindex *ptr);
+
+/*
+ * Check if the interface named "ifname" is a localhost interface or not.
+ * ifname - the interface name on the host to check
+ *
+ * returns - 0 if real interface, 1 if local, negative if error
+ */
+int sandbox_eth_raw_os_is_local(const char *ifname);
+
+/*
+ * Look up the name of the interface based on the ifindex populated in priv.
+ *
+ * Overwrite the host_ifname member in priv based on looking up host_ifindex
+ *
+ * returns - 0 if success, negative if error
+ */
+int sandbox_eth_raw_os_idx_to_name(struct eth_sandbox_raw_priv *priv);
+
+int sandbox_eth_raw_os_start(struct eth_sandbox_raw_priv *priv,
+			     unsigned char *ethmac);
 int sandbox_eth_raw_os_send(void *packet, int length,
 			    struct eth_sandbox_raw_priv *priv);
 int sandbox_eth_raw_os_recv(void *packet, int *length,
diff --git a/cmd/net.c b/cmd/net.c
index eca6dd8918ec07c49111b6b278e3b7547359df63..89721b8f8be9aa4f26c3485558440e1311f9737f 100644
--- a/cmd/net.c
+++ b/cmd/net.c
@@ -192,6 +192,9 @@ static int netboot_common(enum proto_t proto, cmd_tbl_t *cmdtp, int argc,
 
 	switch (argc) {
 	case 1:
+		/* refresh bootfile name from env */
+		copy_filename(net_boot_file_name, env_get("bootfile"),
+			      sizeof(net_boot_file_name));
 		break;
 
 	case 2:	/*
@@ -203,6 +206,9 @@ static int netboot_common(enum proto_t proto, cmd_tbl_t *cmdtp, int argc,
 		addr = simple_strtoul(argv[1], &end, 16);
 		if (end == (argv[1] + strlen(argv[1]))) {
 			load_addr = addr;
+			/* refresh bootfile name from env */
+			copy_filename(net_boot_file_name, env_get("bootfile"),
+				      sizeof(net_boot_file_name));
 		} else {
 			net_boot_file_name_explicit = true;
 			copy_filename(net_boot_file_name, argv[1],
diff --git a/common/console.c b/common/console.c
index 2ba33dc5740240092e04883c5393f6b731ad51ad..7aa58d0a63674c21df6ad3ac89445599e498b512 100644
--- a/common/console.c
+++ b/common/console.c
@@ -196,20 +196,21 @@ static int console_tstc(int file)
 {
 	int i, ret;
 	struct stdio_dev *dev;
+	int prev;
 
-	disable_ctrlc(1);
+	prev = disable_ctrlc(1);
 	for (i = 0; i < cd_count[file]; i++) {
 		dev = console_devices[file][i];
 		if (dev->tstc != NULL) {
 			ret = dev->tstc(dev);
 			if (ret > 0) {
 				tstcdev = dev;
-				disable_ctrlc(0);
+				disable_ctrlc(prev);
 				return ret;
 			}
 		}
 	}
-	disable_ctrlc(0);
+	disable_ctrlc(prev);
 
 	return 0;
 }
@@ -603,7 +604,6 @@ static int ctrlc_disabled = 0;	/* see disable_ctrl() */
 static int ctrlc_was_pressed = 0;
 int ctrlc(void)
 {
-#ifndef CONFIG_SANDBOX
 	if (!ctrlc_disabled && gd->have_console) {
 		if (tstc()) {
 			switch (getc()) {
@@ -615,7 +615,6 @@ int ctrlc(void)
 			}
 		}
 	}
-#endif
 
 	return 0;
 }
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index e88f056d8448c42f411f4a69ba148511e72093da..f762b0898d71a9bf21dbda6594d2840f70faf503 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -7,8 +7,8 @@ config DM_ETH
 	help
 	  Enable driver model for Ethernet.
 
-	  The eth_*() interface will be implemented by the UC_ETH class
-	  This is currently implemented in net/eth.c
+	  The eth_*() interface will be implemented by the UCLASS_ETH class
+	  This is currently implemented in net/eth-uclass.c
 	  Look in include/net.h for details.
 
 config DRIVER_TI_CPSW
@@ -181,6 +181,7 @@ config FTMAC100
 config MVGBE
 	bool "Marvell Orion5x/Kirkwood network interface support"
 	depends on KIRKWOOD || ORION5X
+	select PHYLIB if DM_ETH
 	help
 	  This driver supports the network interface units in the
 	  Marvell Orion5x and Kirkwood SoCs
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 058dd0076886259db7997ffcbbe72851c1d93efb..c1ed44e21f15cf30c60c4ba97c9f38b23ade1088 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -50,6 +50,7 @@ obj-$(CONFIG_RTL8139) += rtl8139.o
 obj-$(CONFIG_RTL8169) += rtl8169.o
 obj-$(CONFIG_ETH_SANDBOX) += sandbox.o
 obj-$(CONFIG_ETH_SANDBOX_RAW) += sandbox-raw.o
+obj-$(CONFIG_ETH_SANDBOX_RAW) += sandbox-raw-bus.o
 obj-$(CONFIG_SH_ETHER) += sh_eth.o
 obj-$(CONFIG_RENESAS_RAVB) += ravb.o
 obj-$(CONFIG_SMC91111) += smc91111.o
diff --git a/drivers/net/cpsw.c b/drivers/net/cpsw.c
index 9919d3919fafda77a0bcc399cfe670a5e5215fcf..c31695eba9dd4c97df4bf704edaf532724570770 100644
--- a/drivers/net/cpsw.c
+++ b/drivers/net/cpsw.c
@@ -999,7 +999,7 @@ static int cpsw_phy_init(struct cpsw_priv *priv, struct cpsw_slave *slave)
 
 #ifdef CONFIG_DM_ETH
 	if (slave->data->phy_of_handle)
-		dev_set_of_offset(phydev->dev, slave->data->phy_of_handle);
+		phydev->node = offset_to_ofnode(slave->data->phy_of_handle);
 #endif
 
 	priv->phydev = phydev;
diff --git a/drivers/net/mvgbe.c b/drivers/net/mvgbe.c
index e6585ef8b3e72643d45bdfbaa87bd3c959f15721..74fed7abd83772a2697f1188b36e1e306a215110 100644
--- a/drivers/net/mvgbe.c
+++ b/drivers/net/mvgbe.c
@@ -12,6 +12,7 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <net.h>
 #include <malloc.h>
 #include <miiphy.h>
@@ -55,20 +56,13 @@ static int smi_wait_ready(struct mvgbe_device *dmvgbe)
 	return 0;
 }
 
-/*
- * smi_reg_read - miiphy_read callback function.
- *
- * Returns 16bit phy register value, or -EFAULT on error
- */
-static int smi_reg_read(struct mii_dev *bus, int phy_adr, int devad,
-			int reg_ofs)
+static int __mvgbe_mdio_read(struct mvgbe_device *dmvgbe, int phy_adr,
+			     int devad, int reg_ofs)
 {
-	u16 data = 0;
-	struct eth_device *dev = eth_get_dev_by_name(bus->name);
-	struct mvgbe_device *dmvgbe = to_mvgbe(dev);
 	struct mvgbe_registers *regs = dmvgbe->regs;
 	u32 smi_reg;
 	u32 timeout;
+	u16 data = 0;
 
 	/* Phyadr read request */
 	if (phy_adr == MV_PHY_ADR_REQUEST &&
@@ -127,15 +121,26 @@ static int smi_reg_read(struct mii_dev *bus, int phy_adr, int devad,
 }
 
 /*
- * smi_reg_write - miiphy_write callback function.
+ * smi_reg_read - miiphy_read callback function.
  *
- * Returns 0 if write succeed, -EFAULT on error
+ * Returns 16bit phy register value, or -EFAULT on error
  */
-static int smi_reg_write(struct mii_dev *bus, int phy_adr, int devad,
-			 int reg_ofs, u16 data)
+static int smi_reg_read(struct mii_dev *bus, int phy_adr, int devad,
+			int reg_ofs)
 {
+#ifdef CONFIG_DM_ETH
+	struct mvgbe_device *dmvgbe = bus->priv;
+#else
 	struct eth_device *dev = eth_get_dev_by_name(bus->name);
 	struct mvgbe_device *dmvgbe = to_mvgbe(dev);
+#endif
+
+	return __mvgbe_mdio_read(dmvgbe, phy_adr, devad, reg_ofs);
+}
+
+static int __mvgbe_mdio_write(struct mvgbe_device *dmvgbe, int phy_adr,
+			      int devad, int reg_ofs, u16 data)
+{
 	struct mvgbe_registers *regs = dmvgbe->regs;
 	u32 smi_reg;
 
@@ -171,6 +176,24 @@ static int smi_reg_write(struct mii_dev *bus, int phy_adr, int devad,
 
 	return 0;
 }
+
+/*
+ * smi_reg_write - miiphy_write callback function.
+ *
+ * Returns 0 if write succeed, -EFAULT on error
+ */
+static int smi_reg_write(struct mii_dev *bus, int phy_adr, int devad,
+			 int reg_ofs, u16 data)
+{
+#ifdef CONFIG_DM_ETH
+	struct mvgbe_device *dmvgbe = bus->priv;
+#else
+	struct eth_device *dev = eth_get_dev_by_name(bus->name);
+	struct mvgbe_device *dmvgbe = to_mvgbe(dev);
+#endif
+
+	return __mvgbe_mdio_write(dmvgbe, phy_adr, devad, reg_ofs, data);
+}
 #endif
 
 /* Stop and checks all queues */
@@ -357,8 +380,9 @@ static int port_uc_addr(struct mvgbe_registers *regs, u8 uc_nibble,
 /*
  * port_uc_addr_set - This function Set the port Unicast address.
  */
-static void port_uc_addr_set(struct mvgbe_registers *regs, u8 * p_addr)
+static void port_uc_addr_set(struct mvgbe_device *dmvgbe, u8 *p_addr)
 {
+	struct mvgbe_registers *regs = dmvgbe->regs;
 	u32 mac_h;
 	u32 mac_l;
 
@@ -400,12 +424,13 @@ static void mvgbe_init_rx_desc_ring(struct mvgbe_device *dmvgbe)
 	dmvgbe->p_rxdesc_curr = dmvgbe->p_rxdesc;
 }
 
-static int mvgbe_init(struct eth_device *dev)
+static int __mvgbe_init(struct mvgbe_device *dmvgbe, u8 *enetaddr,
+			const char *name)
 {
-	struct mvgbe_device *dmvgbe = to_mvgbe(dev);
 	struct mvgbe_registers *regs = dmvgbe->regs;
 #if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII)) &&  \
 	!defined(CONFIG_PHYLIB) &&			 \
+	!defined(CONFIG_DM_ETH) &&			 \
 	defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN)
 	int i;
 #endif
@@ -422,7 +447,7 @@ static int mvgbe_init(struct eth_device *dev)
 
 	set_dram_access(regs);
 	port_init_mac_tables(regs);
-	port_uc_addr_set(regs, dmvgbe->dev.enetaddr);
+	port_uc_addr_set(dmvgbe, enetaddr);
 
 	/* Assign port configuration and command. */
 	MVGBE_REG_WR(regs->pxc, PRT_CFG_VAL);
@@ -459,28 +484,37 @@ static int mvgbe_init(struct eth_device *dev)
 
 #if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII)) && \
 	!defined(CONFIG_PHYLIB) && \
+	!defined(CONFIG_DM_ETH) && \
 	defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN)
 	/* Wait up to 5s for the link status */
 	for (i = 0; i < 5; i++) {
 		u16 phyadr;
 
-		miiphy_read(dev->name, MV_PHY_ADR_REQUEST,
+		miiphy_read(name, MV_PHY_ADR_REQUEST,
 				MV_PHY_ADR_REQUEST, &phyadr);
 		/* Return if we get link up */
-		if (miiphy_link(dev->name, phyadr))
+		if (miiphy_link(name, phyadr))
 			return 0;
 		udelay(1000000);
 	}
 
-	printf("No link on %s\n", dev->name);
+	printf("No link on %s\n", name);
 	return -1;
 #endif
 	return 0;
 }
 
-static int mvgbe_halt(struct eth_device *dev)
+#ifndef CONFIG_DM_ETH
+static int mvgbe_init(struct eth_device *dev)
 {
 	struct mvgbe_device *dmvgbe = to_mvgbe(dev);
+
+	return __mvgbe_init(dmvgbe, dmvgbe->dev.enetaddr, dmvgbe->dev.name);
+}
+#endif
+
+static void __mvgbe_halt(struct mvgbe_device *dmvgbe)
+{
 	struct mvgbe_registers *regs = dmvgbe->regs;
 
 	/* Disable all gigE address decoder */
@@ -502,23 +536,42 @@ static int mvgbe_halt(struct eth_device *dev)
 	MVGBE_REG_WR(regs->ice, 0);
 	MVGBE_REG_WR(regs->pim, 0);
 	MVGBE_REG_WR(regs->peim, 0);
+}
+
+#ifndef CONFIG_DM_ETH
+static int mvgbe_halt(struct eth_device *dev)
+{
+	struct mvgbe_device *dmvgbe = to_mvgbe(dev);
+
+	__mvgbe_halt(dmvgbe);
 
 	return 0;
 }
+#endif
+
+#ifdef CONFIG_DM_ETH
+static int mvgbe_write_hwaddr(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev_get_platdata(dev);
 
+	port_uc_addr_set(dev_get_priv(dev), pdata->enetaddr);
+
+	return 0;
+}
+#else
 static int mvgbe_write_hwaddr(struct eth_device *dev)
 {
 	struct mvgbe_device *dmvgbe = to_mvgbe(dev);
-	struct mvgbe_registers *regs = dmvgbe->regs;
 
 	/* Programs net device MAC address after initialization */
-	port_uc_addr_set(regs, dmvgbe->dev.enetaddr);
+	port_uc_addr_set(dmvgbe, dmvgbe->dev.enetaddr);
 	return 0;
 }
+#endif
 
-static int mvgbe_send(struct eth_device *dev, void *dataptr, int datasize)
+static int __mvgbe_send(struct mvgbe_device *dmvgbe, void *dataptr,
+			int datasize)
 {
-	struct mvgbe_device *dmvgbe = to_mvgbe(dev);
 	struct mvgbe_registers *regs = dmvgbe->regs;
 	struct mvgbe_txdesc *p_txdesc = dmvgbe->p_txdesc;
 	void *p = (void *)dataptr;
@@ -571,13 +624,25 @@ static int mvgbe_send(struct eth_device *dev, void *dataptr, int datasize)
 	return 0;
 }
 
-static int mvgbe_recv(struct eth_device *dev)
+#ifndef CONFIG_DM_ETH
+static int mvgbe_send(struct eth_device *dev, void *dataptr, int datasize)
 {
 	struct mvgbe_device *dmvgbe = to_mvgbe(dev);
+
+	return __mvgbe_send(dmvgbe, dataptr, datasize);
+}
+#endif
+
+static int __mvgbe_recv(struct mvgbe_device *dmvgbe, uchar **packetp)
+{
 	struct mvgbe_rxdesc *p_rxdesc_curr = dmvgbe->p_rxdesc_curr;
 	u32 cmd_sts;
 	u32 timeout = 0;
 	u32 rxdesc_curr_addr;
+	unsigned char *data;
+	int rx_bytes = 0;
+
+	*packetp = NULL;
 
 	/* wait untill rx packet available or timeout */
 	do {
@@ -621,11 +686,11 @@ static int mvgbe_recv(struct eth_device *dev)
 		      " upper layer (net_process_received_packet)\n",
 		      __func__);
 
-		/* let the upper layer handle the packet */
-		net_process_received_packet((p_rxdesc_curr->buf_ptr +
-					     RX_BUF_OFFSET),
-					    (int)(p_rxdesc_curr->byte_cnt -
-						  RX_BUF_OFFSET));
+		data = (p_rxdesc_curr->buf_ptr + RX_BUF_OFFSET);
+		rx_bytes = (int)(p_rxdesc_curr->byte_cnt -
+						  RX_BUF_OFFSET);
+
+		*packetp = data;
 	}
 	/*
 	 * free these descriptors and point next in the ring
@@ -638,10 +703,59 @@ static int mvgbe_recv(struct eth_device *dev)
 	rxdesc_curr_addr = (u32)&dmvgbe->p_rxdesc_curr;
 	writel((unsigned)p_rxdesc_curr->nxtdesc_p, rxdesc_curr_addr);
 
+	return rx_bytes;
+}
+
+#ifndef CONFIG_DM_ETH
+static int mvgbe_recv(struct eth_device *dev)
+{
+	struct mvgbe_device *dmvgbe = to_mvgbe(dev);
+	uchar *packet;
+	int ret;
+
+	ret = __mvgbe_recv(dmvgbe, &packet);
+	if (ret < 0)
+		return ret;
+
+	net_process_received_packet(packet, ret);
+
 	return 0;
 }
+#endif
 
-#if defined(CONFIG_PHYLIB)
+#if defined(CONFIG_PHYLIB) || defined(CONFIG_DM_ETH)
+#if defined(CONFIG_DM_ETH)
+static struct phy_device *__mvgbe_phy_init(struct udevice *dev,
+					   struct mii_dev *bus,
+					   phy_interface_t phy_interface,
+					   int phyid)
+#else
+static struct phy_device *__mvgbe_phy_init(struct eth_device *dev,
+					   struct mii_dev *bus,
+					   phy_interface_t phy_interface,
+					   int phyid)
+#endif
+{
+	struct phy_device *phydev;
+
+	/* Set phy address of the port */
+	miiphy_write(dev->name, MV_PHY_ADR_REQUEST, MV_PHY_ADR_REQUEST,
+		     phyid);
+
+	phydev = phy_connect(bus, phyid, dev, phy_interface);
+	if (!phydev) {
+		printf("phy_connect failed\n");
+		return NULL;
+	}
+
+	phy_config(phydev);
+	phy_startup(phydev);
+
+	return phydev;
+}
+#endif /* CONFIG_PHYLIB || CONFIG_DM_ETH */
+
+#if defined(CONFIG_PHYLIB) && !defined(CONFIG_DM_ETH)
 int mvgbe_phylib_init(struct eth_device *dev, int phyid)
 {
 	struct mii_dev *bus;
@@ -664,27 +778,53 @@ int mvgbe_phylib_init(struct eth_device *dev, int phyid)
 		return -ENOMEM;
 	}
 
-	/* Set phy address of the port */
-	smi_reg_write(bus, MV_PHY_ADR_REQUEST, 0, MV_PHY_ADR_REQUEST, phyid);
-
-	phydev = phy_connect(bus, phyid, dev, PHY_INTERFACE_MODE_RGMII);
-	if (!phydev) {
-		printf("phy_connect failed\n");
+	phydev = __mvgbe_phy_init(dev, bus, PHY_INTERFACE_MODE_RGMII, phyid);
+	if (!phydev)
 		return -ENODEV;
-	}
-
-	phy_config(phydev);
-	phy_startup(phydev);
 
 	return 0;
 }
 #endif
 
+static int mvgbe_alloc_buffers(struct mvgbe_device *dmvgbe)
+{
+	dmvgbe->p_rxdesc = memalign(PKTALIGN,
+				    MV_RXQ_DESC_ALIGNED_SIZE * RINGSZ + 1);
+	if (!dmvgbe->p_rxdesc)
+		goto error1;
+
+	dmvgbe->p_rxbuf = memalign(PKTALIGN,
+				   RINGSZ * PKTSIZE_ALIGN + 1);
+	if (!dmvgbe->p_rxbuf)
+		goto error2;
+
+	dmvgbe->p_aligned_txbuf = memalign(8, PKTSIZE_ALIGN);
+	if (!dmvgbe->p_aligned_txbuf)
+		goto error3;
+
+	dmvgbe->p_txdesc = memalign(PKTALIGN, sizeof(struct mvgbe_txdesc) + 1);
+	if (!dmvgbe->p_txdesc)
+		goto error4;
+
+	return 0;
+
+error4:
+	free(dmvgbe->p_aligned_txbuf);
+error3:
+	free(dmvgbe->p_rxbuf);
+error2:
+	free(dmvgbe->p_rxdesc);
+error1:
+	return -ENOMEM;
+}
+
+#ifndef CONFIG_DM_ETH
 int mvgbe_initialize(bd_t *bis)
 {
 	struct mvgbe_device *dmvgbe;
 	struct eth_device *dev;
 	int devnum;
+	int ret;
 	u8 used_ports[MAX_MVGBE_DEVS] = CONFIG_MVGBE_PORTS;
 
 	for (devnum = 0; devnum < MAX_MVGBE_DEVS; devnum++) {
@@ -693,45 +833,16 @@ int mvgbe_initialize(bd_t *bis)
 			continue;
 
 		dmvgbe = malloc(sizeof(struct mvgbe_device));
-
 		if (!dmvgbe)
-			goto error1;
+			return -ENOMEM;
 
 		memset(dmvgbe, 0, sizeof(struct mvgbe_device));
-
-		dmvgbe->p_rxdesc =
-			(struct mvgbe_rxdesc *)memalign(PKTALIGN,
-			MV_RXQ_DESC_ALIGNED_SIZE*RINGSZ + 1);
-
-		if (!dmvgbe->p_rxdesc)
-			goto error2;
-
-		dmvgbe->p_rxbuf = (u8 *) memalign(PKTALIGN,
-			RINGSZ*PKTSIZE_ALIGN + 1);
-
-		if (!dmvgbe->p_rxbuf)
-			goto error3;
-
-		dmvgbe->p_aligned_txbuf = memalign(8, PKTSIZE_ALIGN);
-
-		if (!dmvgbe->p_aligned_txbuf)
-			goto error4;
-
-		dmvgbe->p_txdesc = (struct mvgbe_txdesc *) memalign(
-			PKTALIGN, sizeof(struct mvgbe_txdesc) + 1);
-
-		if (!dmvgbe->p_txdesc) {
-			free(dmvgbe->p_aligned_txbuf);
-error4:
-			free(dmvgbe->p_rxbuf);
-error3:
-			free(dmvgbe->p_rxdesc);
-error2:
-			free(dmvgbe);
-error1:
+		ret = mvgbe_alloc_buffers(dmvgbe);
+		if (ret) {
 			printf("Err.. %s Failed to allocate memory\n",
 				__func__);
-			return -1;
+			free(dmvgbe);
+			return ret;
 		}
 
 		dev = &dmvgbe->dev;
@@ -783,3 +894,154 @@ error1:
 	}
 	return 0;
 }
+#endif
+
+#ifdef CONFIG_DM_ETH
+static int mvgbe_port_is_fixed_link(struct mvgbe_device *dmvgbe)
+{
+	return dmvgbe->phyaddr > PHY_MAX_ADDR;
+}
+
+static int mvgbe_start(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	struct mvgbe_device *dmvgbe = dev_get_priv(dev);
+	int ret;
+
+	ret = __mvgbe_init(dmvgbe, pdata->enetaddr, dev->name);
+	if (ret)
+		return ret;
+
+	if (!mvgbe_port_is_fixed_link(dmvgbe)) {
+		dmvgbe->phydev = __mvgbe_phy_init(dev, dmvgbe->bus,
+						  dmvgbe->phy_interface,
+						  dmvgbe->phyaddr);
+		if (!dmvgbe->phydev)
+			return -ENODEV;
+	}
+
+	return 0;
+}
+
+static int mvgbe_send(struct udevice *dev, void *packet, int length)
+{
+	struct mvgbe_device *dmvgbe = dev_get_priv(dev);
+
+	return __mvgbe_send(dmvgbe, packet, length);
+}
+
+static int mvgbe_recv(struct udevice *dev, int flags, uchar **packetp)
+{
+	struct mvgbe_device *dmvgbe = dev_get_priv(dev);
+
+	return __mvgbe_recv(dmvgbe, packetp);
+}
+
+static void mvgbe_stop(struct udevice *dev)
+{
+	struct mvgbe_device *dmvgbe = dev_get_priv(dev);
+
+	__mvgbe_halt(dmvgbe);
+}
+
+static int mvgbe_probe(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	struct mvgbe_device *dmvgbe = dev_get_priv(dev);
+	struct mii_dev *bus;
+	int ret;
+
+	ret = mvgbe_alloc_buffers(dmvgbe);
+	if (ret)
+		return ret;
+
+	dmvgbe->regs = (void __iomem *)pdata->iobase;
+
+	bus  = mdio_alloc();
+	if (!bus) {
+		printf("Failed to allocate MDIO bus\n");
+		return -ENOMEM;
+	}
+
+	bus->read = smi_reg_read;
+	bus->write = smi_reg_write;
+	snprintf(bus->name, sizeof(bus->name), dev->name);
+	bus->priv = dmvgbe;
+	dmvgbe->bus = bus;
+
+	ret = mdio_register(bus);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static const struct eth_ops mvgbe_ops = {
+	.start		= mvgbe_start,
+	.send		= mvgbe_send,
+	.recv		= mvgbe_recv,
+	.stop		= mvgbe_stop,
+	.write_hwaddr	= mvgbe_write_hwaddr,
+};
+
+static int mvgbe_ofdata_to_platdata(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	struct mvgbe_device *dmvgbe = dev_get_priv(dev);
+	void *blob = (void *)gd->fdt_blob;
+	int node = dev_of_offset(dev);
+	const char *phy_mode;
+	int fl_node;
+	int pnode;
+	unsigned long addr;
+
+	pdata->iobase = devfdt_get_addr(dev);
+	pdata->phy_interface = -1;
+
+	pnode = fdt_node_offset_by_compatible(blob, node,
+					      "marvell,kirkwood-eth-port");
+
+	/* Get phy-mode / phy_interface from DT */
+	phy_mode = fdt_getprop(gd->fdt_blob, pnode, "phy-mode", NULL);
+	if (phy_mode)
+		pdata->phy_interface = phy_get_interface_by_name(phy_mode);
+	if (pdata->phy_interface == -1) {
+		debug("%s: Invalid PHY interface '%s'\n", __func__, phy_mode);
+		return -EINVAL;
+	}
+
+	dmvgbe->phy_interface = pdata->phy_interface;
+
+	/* fetch 'fixed-link' property */
+	fl_node = fdt_subnode_offset(blob, pnode, "fixed-link");
+	if (fl_node != -FDT_ERR_NOTFOUND) {
+		/* set phy_addr to invalid value for fixed link */
+		dmvgbe->phyaddr = PHY_MAX_ADDR + 1;
+		dmvgbe->duplex = fdtdec_get_bool(blob, fl_node, "full-duplex");
+		dmvgbe->speed = fdtdec_get_int(blob, fl_node, "speed", 0);
+	} else {
+		/* Now read phyaddr from DT */
+		addr = fdtdec_lookup_phandle(blob, pnode, "phy-handle");
+		if (addr > 0)
+			dmvgbe->phyaddr = fdtdec_get_int(blob, addr, "reg", 0);
+	}
+
+	return 0;
+}
+
+static const struct udevice_id mvgbe_ids[] = {
+	{ .compatible = "marvell,kirkwood-eth" },
+	{ }
+};
+
+U_BOOT_DRIVER(mvgbe) = {
+	.name	= "mvgbe",
+	.id	= UCLASS_ETH,
+	.of_match = mvgbe_ids,
+	.ofdata_to_platdata = mvgbe_ofdata_to_platdata,
+	.probe	= mvgbe_probe,
+	.ops	= &mvgbe_ops,
+	.priv_auto_alloc_size = sizeof(struct mvgbe_device),
+	.platdata_auto_alloc_size = sizeof(struct eth_pdata),
+};
+#endif /* CONFIG_DM_ETH */
diff --git a/drivers/net/mvgbe.h b/drivers/net/mvgbe.h
index 1dc9bbea2f424ab23cece511f32abc0105045e02..44541c0a85e302fb87b4024268615d70048a789d 100644
--- a/drivers/net/mvgbe.h
+++ b/drivers/net/mvgbe.h
@@ -30,7 +30,9 @@
 #define RXUQ	0 /* Used Rx queue */
 #define TXUQ	0 /* Used Rx queue */
 
+#ifndef CONFIG_DM_ETH
 #define to_mvgbe(_d) container_of(_d, struct mvgbe_device, dev)
+#endif
 #define MVGBE_REG_WR(adr, val)		writel(val, &adr)
 #define MVGBE_REG_RD(adr)		readl(&adr)
 #define MVGBE_REG_BITS_RESET(adr, val)	writel(readl(&adr) & ~(val), &adr)
@@ -479,13 +481,27 @@ struct mvgbe_txdesc {
 
 /* port device data struct */
 struct mvgbe_device {
+#ifndef CONFIG_DM_ETH
 	struct eth_device dev;
+#endif
 	struct mvgbe_registers *regs;
 	struct mvgbe_txdesc *p_txdesc;
 	struct mvgbe_rxdesc *p_rxdesc;
 	struct mvgbe_rxdesc *p_rxdesc_curr;
 	u8 *p_rxbuf;
 	u8 *p_aligned_txbuf;
+
+#ifdef CONFIG_DM_ETH
+	phy_interface_t phy_interface;
+	unsigned int link;
+	unsigned int duplex;
+	unsigned int speed;
+
+	int init;
+	int phyaddr;
+	struct phy_device *phydev;
+	struct mii_dev *bus;
+#endif
 };
 
 #endif /* __MVGBE_H__ */
diff --git a/drivers/net/phy/atheros.c b/drivers/net/phy/atheros.c
index 79f68af14c0c262dab89bf0ea323d848a72fcd04..3783d155e79cf8dd753fc94de8f7e9d10150464a 100644
--- a/drivers/net/phy/atheros.c
+++ b/drivers/net/phy/atheros.c
@@ -5,6 +5,7 @@
  * Copyright 2011, 2013 Freescale Semiconductor, Inc.
  * author Andy Fleming
  */
+#include <common.h>
 #include <phy.h>
 
 #define AR803x_PHY_DEBUG_ADDR_REG	0x1d
diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c
index 202e3dd487fdc6c0f52d89d3c327c08a74512b51..3399fd236625727a5f120158f0dad6494aa44c57 100644
--- a/drivers/net/phy/broadcom.c
+++ b/drivers/net/phy/broadcom.c
@@ -5,7 +5,6 @@
  * Copyright 2010-2011 Freescale Semiconductor, Inc.
  * author Andy Fleming
  */
-#include <config.h>
 #include <common.h>
 #include <phy.h>
 
diff --git a/drivers/net/phy/davicom.c b/drivers/net/phy/davicom.c
index 27c7788493d802854da52548a7011d8d88fd0bc7..4666497d44f324ce0197918995276db6de83b7be 100644
--- a/drivers/net/phy/davicom.c
+++ b/drivers/net/phy/davicom.c
@@ -5,6 +5,7 @@
  * Copyright 2010-2011 Freescale Semiconductor, Inc.
  * author Andy Fleming
  */
+#include <common.h>
 #include <phy.h>
 
 #define MIIM_DM9161_SCR                0x10
diff --git a/drivers/net/phy/generic_10g.c b/drivers/net/phy/generic_10g.c
index 1024d7db7b9889035ad3c29eb5a81839a8937d54..b4384e1f7818dcb2c9434a0475e2ccf2fd944673 100644
--- a/drivers/net/phy/generic_10g.c
+++ b/drivers/net/phy/generic_10g.c
@@ -7,8 +7,6 @@
  *
  * Based loosely off of Linux's PHY Lib
  */
-
-#include <config.h>
 #include <common.h>
 #include <miiphy.h>
 #include <phy.h>
diff --git a/drivers/net/phy/lxt.c b/drivers/net/phy/lxt.c
index 5942664f1c39f3396459f2c23d90d354f3d18fea..2618deb009600114c5c9fabe4a2941af3de413e1 100644
--- a/drivers/net/phy/lxt.c
+++ b/drivers/net/phy/lxt.c
@@ -5,6 +5,7 @@
  * Copyright 2010-2011 Freescale Semiconductor, Inc.
  * author Andy Fleming
  */
+#include <common.h>
 #include <phy.h>
 
 /* LXT971 Status 2 registers */
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
index 436ff572feacc281d8b4c91d32ce02c0862827f0..efbbd31ff71ba1df73a07b2be1469d58768316ca 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c
@@ -5,7 +5,6 @@
  * Copyright 2010-2011 Freescale Semiconductor, Inc.
  * author Andy Fleming
  */
-#include <config.h>
 #include <common.h>
 #include <errno.h>
 #include <phy.h>
diff --git a/drivers/net/phy/micrel_ksz8xxx.c b/drivers/net/phy/micrel_ksz8xxx.c
index c70c0364b86266395599e7363ed5a60acdd7932c..3411150ab9dbfcfd705c0238a070c6de29566378 100644
--- a/drivers/net/phy/micrel_ksz8xxx.c
+++ b/drivers/net/phy/micrel_ksz8xxx.c
@@ -6,7 +6,6 @@
  * author Andy Fleming
  * (C) 2012 NetModule AG, David Andrey, added KSZ9031
  */
-#include <config.h>
 #include <common.h>
 #include <dm.h>
 #include <errno.h>
diff --git a/drivers/net/phy/micrel_ksz90x1.c b/drivers/net/phy/micrel_ksz90x1.c
index 5462532be63ce82c73e94696e2d254575f17bfca..3951535bf1ff1b23c93bc55521019e5935adfce6 100644
--- a/drivers/net/phy/micrel_ksz90x1.c
+++ b/drivers/net/phy/micrel_ksz90x1.c
@@ -8,8 +8,6 @@
  * (C) Copyright 2017 Adaptrum, Inc.
  * Written by Alexandru Gagniuc <alex.g@adaptrum.com> for Adaptrum, Inc.
  */
-
-#include <config.h>
 #include <common.h>
 #include <dm.h>
 #include <errno.h>
diff --git a/drivers/net/phy/natsemi.c b/drivers/net/phy/natsemi.c
index 05c7e7c089002f31019a11e599c8bb6a0cee501c..efde4574deb8c6020ed2586c9aac0a4fa0186d8e 100644
--- a/drivers/net/phy/natsemi.c
+++ b/drivers/net/phy/natsemi.c
@@ -5,6 +5,7 @@
  * Copyright 2010-2011 Freescale Semiconductor, Inc.
  * author Andy Fleming
  */
+#include <common.h>
 #include <phy.h>
 
 /* NatSemi DP83630 */
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 4e610bf054b1a9c6dc8427c2cf6944dcd1fa1917..e837eb7688cc0e70623971bcb9bec2c7572c2a8d 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -7,8 +7,6 @@
  *
  * Based loosely off of Linux's PHY Lib
  */
-
-#include <config.h>
 #include <common.h>
 #include <console.h>
 #include <dm.h>
@@ -644,6 +642,10 @@ static struct phy_device *phy_device_create(struct mii_dev *bus, int addr,
 	dev->link = 0;
 	dev->interface = interface;
 
+#ifdef CONFIG_DM_ETH
+	dev->node = ofnode_null();
+#endif
+
 	dev->autoneg = AUTONEG_ENABLE;
 
 	dev->addr = addr;
diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c
index b0867af22062baf888899c0eb2f111519bf61aa4..b3e6578df9acbf26878dd00ba9a95cebc3c7ce86 100644
--- a/drivers/net/phy/realtek.c
+++ b/drivers/net/phy/realtek.c
@@ -6,7 +6,6 @@
  * author Andy Fleming
  * Copyright 2016 Karsten Merker <merker@debian.org>
  */
-#include <config.h>
 #include <common.h>
 #include <linux/bitops.h>
 #include <phy.h>
diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c
index 2f92957a5a7823bef6c913f04d654eba68677c0b..7740a2510d2b1b8c3ae6e512d65f5a163fb6d720 100644
--- a/drivers/net/phy/smsc.c
+++ b/drivers/net/phy/smsc.c
@@ -9,6 +9,7 @@
  * Some code copied from linux kernel
  * Copyright (c) 2006 Herbert Valerio Riedel <hvr@gnu.org>
  */
+#include <common.h>
 #include <miiphy.h>
 
 /* This code does not check the partner abilities. */
diff --git a/drivers/net/phy/teranetics.c b/drivers/net/phy/teranetics.c
index d674e8f8574473e327a1b8334c9b7f6899f0a3f2..49d6a1ad901e9f2c7d759662026a894574a37a58 100644
--- a/drivers/net/phy/teranetics.c
+++ b/drivers/net/phy/teranetics.c
@@ -5,7 +5,6 @@
  * Copyright 2010-2011 Freescale Semiconductor, Inc.
  * author Andy Fleming
  */
-#include <config.h>
 #include <common.h>
 #include <phy.h>
 
diff --git a/drivers/net/phy/ti.c b/drivers/net/phy/ti.c
index 8f3ed8a9833dddb0d82d94c613e3e80540f0d6b1..f870e6d66206ec52e976d03d956b7667faea5470 100644
--- a/drivers/net/phy/ti.c
+++ b/drivers/net/phy/ti.c
@@ -8,11 +8,9 @@
 #include <linux/compat.h>
 #include <malloc.h>
 
-#include <fdtdec.h>
 #include <dm.h>
 #include <dt-bindings/net/ti-dp83867.h>
 
-DECLARE_GLOBAL_DATA_PTR;
 
 /* TI DP83867 */
 #define DP83867_DEVADDR		0x1f
@@ -24,6 +22,7 @@ DECLARE_GLOBAL_DATA_PTR;
 #define DP83867_CTRL		0x1f
 
 /* Extended Registers */
+#define DP83867_CFG4		0x0031
 #define DP83867_RGMIICTL	0x0032
 #define DP83867_RGMIIDCTL	0x0086
 #define DP83867_IO_MUX_CFG	0x0170
@@ -95,6 +94,7 @@ struct dp83867_private {
 	int tx_id_delay;
 	int fifo_depth;
 	int io_impedance;
+	bool rxctrl_strap_quirk;
 };
 
 /**
@@ -172,25 +172,31 @@ void phy_write_mmd_indirect(struct phy_device *phydev, int prtad,
 static int dp83867_of_init(struct phy_device *phydev)
 {
 	struct dp83867_private *dp83867 = phydev->priv;
-	struct udevice *dev = phydev->dev;
-	int node = dev_of_offset(dev);
-	const void *fdt = gd->fdt_blob;
+	ofnode node;
 
-	if (fdtdec_get_bool(fdt, node, "ti,max-output-impedance"))
+	node = phy_get_ofnode(phydev);
+	if (!ofnode_valid(node))
+		return -EINVAL;
+
+	if (ofnode_read_bool(node, "ti,max-output-impedance"))
 		dp83867->io_impedance = DP83867_IO_MUX_CFG_IO_IMPEDANCE_MAX;
-	else if (fdtdec_get_bool(fdt, node, "ti,min-output-impedance"))
+	else if (ofnode_read_bool(node, "ti,min-output-impedance"))
 		dp83867->io_impedance = DP83867_IO_MUX_CFG_IO_IMPEDANCE_MIN;
 	else
 		dp83867->io_impedance = -EINVAL;
 
-	dp83867->rx_id_delay = fdtdec_get_uint(gd->fdt_blob, dev_of_offset(dev),
-				 "ti,rx-internal-delay", -1);
+	if (ofnode_read_bool(node, "ti,dp83867-rxctrl-strap-quirk"))
+		dp83867->rxctrl_strap_quirk = true;
+	dp83867->rx_id_delay = ofnode_read_u32_default(node,
+						       "ti,rx-internal-delay",
+						       -1);
 
-	dp83867->tx_id_delay = fdtdec_get_uint(gd->fdt_blob, dev_of_offset(dev),
-				 "ti,tx-internal-delay", -1);
+	dp83867->tx_id_delay = ofnode_read_u32_default(node,
+						       "ti,tx-internal-delay",
+						       -1);
 
-	dp83867->fifo_depth = fdtdec_get_uint(gd->fdt_blob, dev_of_offset(dev),
-				 "ti,fifo-depth", -1);
+	dp83867->fifo_depth = ofnode_read_u32_default(node, "ti,fifo-depth",
+						      -1);
 
 	return 0;
 }
@@ -232,6 +238,15 @@ static int dp83867_config(struct phy_device *phydev)
 	phy_write(phydev, MDIO_DEVAD_NONE, DP83867_CTRL,
 		  val | DP83867_SW_RESTART);
 
+	/* Mode 1 or 2 workaround */
+	if (dp83867->rxctrl_strap_quirk) {
+		val = phy_read_mmd_indirect(phydev, DP83867_CFG4,
+					    DP83867_DEVADDR, phydev->addr);
+		val &= ~BIT(7);
+		phy_write_mmd_indirect(phydev, DP83867_CFG4,
+				       DP83867_DEVADDR, phydev->addr, val);
+	}
+
 	if (phy_interface_is_rgmii(phydev)) {
 		ret = phy_write(phydev, MDIO_DEVAD_NONE, MII_DP83867_PHYCTRL,
 			(DP83867_MDI_CROSSOVER_AUTO << DP83867_MDI_CROSSOVER) |
diff --git a/drivers/net/phy/vitesse.c b/drivers/net/phy/vitesse.c
index 9df4a3fae5c5593dd75d180d57a5527d41b6fe46..eca26c989389112592ffdeedb724d8d8901a19dd 100644
--- a/drivers/net/phy/vitesse.c
+++ b/drivers/net/phy/vitesse.c
@@ -6,6 +6,7 @@
  * Original Author: Andy Fleming
  * Add vsc8662 phy support - Priyanka Jain
  */
+#include <common.h>
 #include <miiphy.h>
 
 /* Cicada Auxiliary Control/Status Register */
diff --git a/drivers/net/phy/xilinx_phy.c b/drivers/net/phy/xilinx_phy.c
index 004cfcf6472494dfea7c1f81b32a7564a23270b5..3aa8891efe45c9faa27a4f65acac4a402cd9b110 100644
--- a/drivers/net/phy/xilinx_phy.c
+++ b/drivers/net/phy/xilinx_phy.c
@@ -10,8 +10,6 @@
 #include <phy.h>
 #include <dm.h>
 
-DECLARE_GLOBAL_DATA_PTR;
-
 #define MII_PHY_STATUS_SPD_MASK		0x0C00
 #define MII_PHY_STATUS_FULLDUPLEX	0x1000
 #define MII_PHY_STATUS_1000		0x0800
@@ -101,10 +99,14 @@ static int xilinxphy_startup(struct phy_device *phydev)
 static int xilinxphy_of_init(struct phy_device *phydev)
 {
 	u32 phytype;
+	ofnode node;
 
 	debug("%s\n", __func__);
-	phytype = fdtdec_get_int(gd->fdt_blob, dev_of_offset(phydev->dev),
-				 "xlnx,phy-type", -1);
+	node = phy_get_ofnode(phydev);
+	if (!ofnode_valid(node))
+		return -EINVAL;
+
+	phytype = ofnode_read_u32_default(node, "xlnx,phy-type", -1);
 	if (phytype == XAE_PHY_TYPE_1000BASE_X)
 		phydev->flags |= XAE_PHY_TYPE_1000BASE_X;
 
diff --git a/drivers/net/sandbox-raw-bus.c b/drivers/net/sandbox-raw-bus.c
new file mode 100644
index 0000000000000000000000000000000000000000..76d65afe6c87a8215de48f3468dd6677c84bca68
--- /dev/null
+++ b/drivers/net/sandbox-raw-bus.c
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2018 National Instruments
+ * Copyright (c) 2018 Joe Hershberger <joe.hershberger@ni.com>
+ */
+
+#include <common.h>
+#include <asm/eth-raw-os.h>
+#include <dm.h>
+#include <errno.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+
+static int eth_raw_bus_post_bind(struct udevice *dev)
+{
+	struct sandbox_eth_raw_if_nameindex *ni, *i;
+	struct udevice *child;
+	struct eth_sandbox_raw_priv *priv;
+	char *ub_ifname;
+	static const char ub_ifname_pfx[] = "host_";
+	u32 skip_localhost = 0;
+
+	ni = sandbox_eth_raw_if_nameindex();
+	if (!ni)
+		return -EINVAL;
+
+	dev_read_u32(dev, "skip-localhost", &skip_localhost);
+	for (i = ni; !(i->if_index == 0 && !i->if_name); i++) {
+		int local = sandbox_eth_raw_os_is_local(i->if_name);
+
+		if (local < 0)
+			continue;
+		if (skip_localhost && local)
+			continue;
+
+		ub_ifname = calloc(IFNAMSIZ + sizeof(ub_ifname_pfx), 1);
+		strcpy(ub_ifname, ub_ifname_pfx);
+		strncat(ub_ifname, i->if_name, IFNAMSIZ);
+		device_bind_driver(dev, "eth_sandbox_raw", ub_ifname, &child);
+
+		device_set_name_alloced(child);
+		device_probe(child);
+		priv = dev_get_priv(child);
+		if (priv) {
+			memcpy(priv->host_ifname, i->if_name, IFNAMSIZ);
+			priv->host_ifindex = i->if_index;
+			priv->local = local;
+		}
+	}
+
+	sandbox_eth_raw_if_freenameindex(ni);
+
+	return 0;
+}
+
+static const struct udevice_id sandbox_eth_raw_bus_ids[] = {
+	{ .compatible = "sandbox,eth-raw-bus" },
+	{ }
+};
+
+U_BOOT_DRIVER(sandbox_eth_raw_bus) = {
+	.name       = "sb_eth_raw_bus",
+	.id         = UCLASS_SIMPLE_BUS,
+	.of_match   = sandbox_eth_raw_bus_ids,
+	.bind       = eth_raw_bus_post_bind,
+};
diff --git a/drivers/net/sandbox-raw.c b/drivers/net/sandbox-raw.c
index 3f8020f629d6359f68632c644d23b053b3216d56..09cc678ebde72657c3f6e51b631c8dcad2b8bd57 100644
--- a/drivers/net/sandbox-raw.c
+++ b/drivers/net/sandbox-raw.c
@@ -21,21 +21,18 @@ static int sb_eth_raw_start(struct udevice *dev)
 {
 	struct eth_sandbox_raw_priv *priv = dev_get_priv(dev);
 	struct eth_pdata *pdata = dev_get_platdata(dev);
-	const char *interface;
+	int ret;
 
 	debug("eth_sandbox_raw: Start\n");
 
-	interface = fdt_getprop(gd->fdt_blob, dev_of_offset(dev),
-					    "host-raw-interface", NULL);
-	if (interface == NULL)
-		return -EINVAL;
-
-	if (strcmp(interface, "lo") == 0) {
-		priv->local = 1;
+	ret = sandbox_eth_raw_os_start(priv, pdata->enetaddr);
+	if (priv->local) {
 		env_set("ipaddr", "127.0.0.1");
 		env_set("serverip", "127.0.0.1");
+		net_ip = string_to_ip("127.0.0.1");
+		net_server_ip = net_ip;
 	}
-	return sandbox_eth_raw_os_start(interface, pdata->enetaddr, priv);
+	return ret;
 }
 
 static int sb_eth_raw_send(struct udevice *dev, void *packet, int length)
@@ -133,18 +130,54 @@ static void sb_eth_raw_stop(struct udevice *dev)
 	sandbox_eth_raw_os_stop(priv);
 }
 
+static int sb_eth_raw_read_rom_hwaddr(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+
+	net_random_ethaddr(pdata->enetaddr);
+
+	return 0;
+}
+
 static const struct eth_ops sb_eth_raw_ops = {
 	.start			= sb_eth_raw_start,
 	.send			= sb_eth_raw_send,
 	.recv			= sb_eth_raw_recv,
 	.stop			= sb_eth_raw_stop,
+	.read_rom_hwaddr	= sb_eth_raw_read_rom_hwaddr,
 };
 
 static int sb_eth_raw_ofdata_to_platdata(struct udevice *dev)
 {
 	struct eth_pdata *pdata = dev_get_platdata(dev);
+	struct eth_sandbox_raw_priv *priv = dev_get_priv(dev);
+	const char *ifname;
+	u32 local;
+	int ret;
+
+	pdata->iobase = dev_read_addr(dev);
+
+	ifname = dev_read_string(dev, "host-raw-interface");
+	if (ifname) {
+		strncpy(priv->host_ifname, ifname, IFNAMSIZ);
+		printf(": Using %s from DT\n", priv->host_ifname);
+	}
+	if (dev_read_u32(dev, "host-raw-interface-idx",
+			 &priv->host_ifindex) < 0) {
+		priv->host_ifindex = 0;
+	} else {
+		ret = sandbox_eth_raw_os_idx_to_name(priv);
+		if (ret < 0)
+			return ret;
+		printf(": Using interface index %d from DT (%s)\n",
+		       priv->host_ifindex, priv->host_ifname);
+	}
+
+	local = sandbox_eth_raw_os_is_local(priv->host_ifname);
+	if (local < 0)
+		return local;
+	priv->local = local;
 
-	pdata->iobase = devfdt_get_addr(dev);
 	return 0;
 }
 
diff --git a/drivers/net/sandbox.c b/drivers/net/sandbox.c
index b34712bd06f1f490111d36ddf2435e24747ea26e..b71c8f88d94f7abe7090e644a69b34486dfc1127 100644
--- a/drivers/net/sandbox.c
+++ b/drivers/net/sandbox.c
@@ -59,10 +59,8 @@ static int sb_eth_start(struct udevice *dev)
 
 	debug("eth_sandbox: Start\n");
 
-	fdtdec_get_byte_array(gd->fdt_blob, dev_of_offset(dev),
-			      "fake-host-hwaddr", priv->fake_host_hwaddr,
-			      ARP_HLEN);
 	priv->recv_packet_buffer = net_rx_packets[0];
+
 	return 0;
 }
 
@@ -203,8 +201,18 @@ static int sb_eth_remove(struct udevice *dev)
 static int sb_eth_ofdata_to_platdata(struct udevice *dev)
 {
 	struct eth_pdata *pdata = dev_get_platdata(dev);
+	struct eth_sandbox_priv *priv = dev_get_priv(dev);
+	const u8 *mac;
+
+	pdata->iobase = dev_read_addr(dev);
+
+	mac = dev_read_u8_array_ptr(dev, "fake-host-hwaddr", ARP_HLEN);
+	if (!mac) {
+		printf("'fake-host-hwaddr' is missing from the DT\n");
+		return -EINVAL;
+	}
+	memcpy(priv->fake_host_hwaddr, mac, ARP_HLEN);
 
-	pdata->iobase = devfdt_get_addr(dev);
 	return 0;
 }
 
diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c
index d1138fe0903df9745811917d38526b04c96c4bb3..68d1c2fceaffa0758020e540d6b4e12e265e0928 100644
--- a/drivers/net/zynq_gem.c
+++ b/drivers/net/zynq_gem.c
@@ -178,7 +178,7 @@ struct zynq_gem_priv {
 	struct zynq_gem_regs *iobase;
 	phy_interface_t interface;
 	struct phy_device *phydev;
-	int phy_of_handle;
+	ofnode phy_of_node;
 	struct mii_dev *bus;
 	struct clk clk;
 	u32 max_speed;
@@ -348,9 +348,7 @@ static int zynq_phy_init(struct udevice *dev)
 	}
 
 	priv->phydev->advertising = priv->phydev->supported;
-
-	if (priv->phy_of_handle > 0)
-		dev_set_of_offset(priv->phydev->dev, priv->phy_of_handle);
+	priv->phydev->node = priv->phy_of_node;
 
 	return phy_config(priv->phydev);
 }
@@ -693,21 +691,23 @@ static int zynq_gem_ofdata_to_platdata(struct udevice *dev)
 {
 	struct eth_pdata *pdata = dev_get_platdata(dev);
 	struct zynq_gem_priv *priv = dev_get_priv(dev);
-	int node = dev_of_offset(dev);
+	struct ofnode_phandle_args phandle_args;
 	const char *phy_mode;
 
-	pdata->iobase = (phys_addr_t)devfdt_get_addr(dev);
+	pdata->iobase = (phys_addr_t)dev_read_addr(dev);
 	priv->iobase = (struct zynq_gem_regs *)pdata->iobase;
 	/* Hardcode for now */
 	priv->phyaddr = -1;
 
-	priv->phy_of_handle = fdtdec_lookup_phandle(gd->fdt_blob, node,
-						    "phy-handle");
-	if (priv->phy_of_handle > 0)
-		priv->phyaddr = fdtdec_get_int(gd->fdt_blob,
-					priv->phy_of_handle, "reg", -1);
+	if (dev_read_phandle_with_args(dev, "phy-handle", NULL, 0, 0,
+				       &phandle_args)) {
+		debug("phy-handle does not exist %s\n", dev->name);
+		return -ENOENT;
+	}
 
-	phy_mode = fdt_getprop(gd->fdt_blob, node, "phy-mode", NULL);
+	priv->phyaddr = ofnode_read_u32_default(phandle_args.node, "reg", -1);
+	priv->phy_of_node = phandle_args.node;
+	phy_mode = dev_read_prop(dev, "phy-mode", NULL);
 	if (phy_mode)
 		pdata->phy_interface = phy_get_interface_by_name(phy_mode);
 	if (pdata->phy_interface == -1) {
@@ -716,10 +716,8 @@ static int zynq_gem_ofdata_to_platdata(struct udevice *dev)
 	}
 	priv->interface = pdata->phy_interface;
 
-	priv->max_speed = fdtdec_get_uint(gd->fdt_blob, priv->phy_of_handle,
-					  "max-speed", SPEED_1000);
-	priv->int_pcs = fdtdec_get_bool(gd->fdt_blob, node,
-					"is-internal-pcspma");
+	priv->max_speed = dev_read_u32_default(dev, "max-speed", SPEED_1000);
+	priv->int_pcs = dev_read_bool(dev, "is-internal-pcspma");
 
 	printf("ZYNQ GEM: %lx, phyaddr %x, interface %s\n", (ulong)priv->iobase,
 	       priv->phyaddr, phy_string_for_interface(priv->interface));
diff --git a/drivers/serial/sandbox.c b/drivers/serial/sandbox.c
index d2e007284c4bb30d4f8a00ea6535bd8fbc2cdb47..a60dabe58835648027ed53d29a715431bea753cd 100644
--- a/drivers/serial/sandbox.c
+++ b/drivers/serial/sandbox.c
@@ -10,6 +10,7 @@
  */
 
 #include <common.h>
+#include <console.h>
 #include <dm.h>
 #include <fdtdec.h>
 #include <lcd.h>
@@ -69,6 +70,9 @@ static int sandbox_serial_probe(struct udevice *dev)
 		os_tty_raw(0, state->term_raw == STATE_TERM_RAW_WITH_SIGS);
 	priv->start_of_line = 0;
 
+	if (state->term_raw != STATE_TERM_RAW)
+		disable_ctrlc(1);
+
 	return 0;
 }
 
diff --git a/include/exports.h b/include/exports.h
index ebe81d914cb226256730bece027cc6fceb28dc68..a4b862f19178d561db3d1eda7d27ae5da937bc82 100644
--- a/include/exports.h
+++ b/include/exports.h
@@ -3,8 +3,7 @@
 
 #ifndef __ASSEMBLY__
 #ifdef CONFIG_PHY_AQUANTIA
-#include <miiphy.h>
-#include <phy.h>
+#include <phy_interface.h>
 #endif
 
 struct spi_slave;
diff --git a/include/net.h b/include/net.h
index f9984ae86ca5614f275e427b2eeba6015b585f37..62f82c4dca72c5f1d64a1bdf7386e03bfab7a7bc 100644
--- a/include/net.h
+++ b/include/net.h
@@ -839,6 +839,20 @@ ushort env_get_vlan(char *);
 /* copy a filename (allow for "..." notation, limit length) */
 void copy_filename(char *dst, const char *src, int size);
 
+/* check if serverip is specified in filename from the command line */
+int is_serverip_in_cmd(void);
+
+/**
+ * net_parse_bootfile - Parse the bootfile env var / cmd line param
+ *
+ * @param ipaddr - a pointer to the ipaddr to populate if included in bootfile
+ * @param filename - a pointer to the string to save the filename part
+ * @param max_len - The longest - 1 that the filename part can be
+ *
+ * return 1 if parsed, 0 if bootfile is empty
+ */
+int net_parse_bootfile(struct in_addr *ipaddr, char *filename, int max_len);
+
 /* get a random source port */
 unsigned int random_port(void);
 
diff --git a/include/phy.h b/include/phy.h
index 7c3fc5ce40cce94f21ad79da6a8ebcc1e6f84fe8..d6a83150cf688237010ec7d7db4a5b5f83b09605 100644
--- a/include/phy.h
+++ b/include/phy.h
@@ -9,10 +9,12 @@
 #ifndef _PHY_H
 #define _PHY_H
 
+#include <dm.h>
 #include <linux/list.h>
 #include <linux/mii.h>
 #include <linux/ethtool.h>
 #include <linux/mdio.h>
+#include <phy_interface.h>
 
 #define PHY_FIXED_ID		0xa5a55a5a
 
@@ -48,60 +50,6 @@
 #endif
 
 
-typedef enum {
-	PHY_INTERFACE_MODE_MII,
-	PHY_INTERFACE_MODE_GMII,
-	PHY_INTERFACE_MODE_SGMII,
-	PHY_INTERFACE_MODE_SGMII_2500,
-	PHY_INTERFACE_MODE_QSGMII,
-	PHY_INTERFACE_MODE_TBI,
-	PHY_INTERFACE_MODE_RMII,
-	PHY_INTERFACE_MODE_RGMII,
-	PHY_INTERFACE_MODE_RGMII_ID,
-	PHY_INTERFACE_MODE_RGMII_RXID,
-	PHY_INTERFACE_MODE_RGMII_TXID,
-	PHY_INTERFACE_MODE_RTBI,
-	PHY_INTERFACE_MODE_XGMII,
-	PHY_INTERFACE_MODE_XAUI,
-	PHY_INTERFACE_MODE_RXAUI,
-	PHY_INTERFACE_MODE_SFI,
-	PHY_INTERFACE_MODE_INTERNAL,
-	PHY_INTERFACE_MODE_NONE,	/* Must be last */
-
-	PHY_INTERFACE_MODE_COUNT,
-} phy_interface_t;
-
-static const char *phy_interface_strings[] = {
-	[PHY_INTERFACE_MODE_MII]		= "mii",
-	[PHY_INTERFACE_MODE_GMII]		= "gmii",
-	[PHY_INTERFACE_MODE_SGMII]		= "sgmii",
-	[PHY_INTERFACE_MODE_SGMII_2500]		= "sgmii-2500",
-	[PHY_INTERFACE_MODE_QSGMII]		= "qsgmii",
-	[PHY_INTERFACE_MODE_TBI]		= "tbi",
-	[PHY_INTERFACE_MODE_RMII]		= "rmii",
-	[PHY_INTERFACE_MODE_RGMII]		= "rgmii",
-	[PHY_INTERFACE_MODE_RGMII_ID]		= "rgmii-id",
-	[PHY_INTERFACE_MODE_RGMII_RXID]		= "rgmii-rxid",
-	[PHY_INTERFACE_MODE_RGMII_TXID]		= "rgmii-txid",
-	[PHY_INTERFACE_MODE_RTBI]		= "rtbi",
-	[PHY_INTERFACE_MODE_XGMII]		= "xgmii",
-	[PHY_INTERFACE_MODE_XAUI]		= "xaui",
-	[PHY_INTERFACE_MODE_RXAUI]		= "rxaui",
-	[PHY_INTERFACE_MODE_SFI]		= "sfi",
-	[PHY_INTERFACE_MODE_INTERNAL]		= "internal",
-	[PHY_INTERFACE_MODE_NONE]		= "",
-};
-
-static inline const char *phy_string_for_interface(phy_interface_t i)
-{
-	/* Default to unknown */
-	if (i > PHY_INTERFACE_MODE_NONE)
-		i = PHY_INTERFACE_MODE_NONE;
-
-	return phy_interface_strings[i];
-}
-
-
 struct phy_device;
 
 #define MDIO_NAME_LEN 32
@@ -165,6 +113,7 @@ struct phy_device {
 
 #ifdef CONFIG_DM_ETH
 	struct udevice *dev;
+	ofnode node;
 #else
 	struct eth_device *dev;
 #endif
@@ -235,11 +184,22 @@ void phy_connect_dev(struct phy_device *phydev, struct udevice *dev);
 struct phy_device *phy_connect(struct mii_dev *bus, int addr,
 				struct udevice *dev,
 				phy_interface_t interface);
+static inline ofnode phy_get_ofnode(struct phy_device *phydev)
+{
+	if (ofnode_valid(phydev->node))
+		return phydev->node;
+	else
+		return dev_ofnode(phydev->dev);
+}
 #else
 void phy_connect_dev(struct phy_device *phydev, struct eth_device *dev);
 struct phy_device *phy_connect(struct mii_dev *bus, int addr,
 				struct eth_device *dev,
 				phy_interface_t interface);
+static inline ofnode phy_get_ofnode(struct phy_device *phydev)
+{
+	return ofnode_null();
+}
 #endif
 int phy_startup(struct phy_device *phydev);
 int phy_config(struct phy_device *phydev);
diff --git a/include/phy_interface.h b/include/phy_interface.h
new file mode 100644
index 0000000000000000000000000000000000000000..0760d65de518f1a900b3002b15fb8fb88348ffb6
--- /dev/null
+++ b/include/phy_interface.h
@@ -0,0 +1,65 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ *	Andy Fleming <afleming@gmail.com>
+ *
+ * This file pretty much stolen from Linux's mii.h/ethtool.h/phy.h
+ */
+
+#ifndef _PHY_INTERFACE_H
+#define _PHY_INTERFACE_H
+
+typedef enum {
+	PHY_INTERFACE_MODE_MII,
+	PHY_INTERFACE_MODE_GMII,
+	PHY_INTERFACE_MODE_SGMII,
+	PHY_INTERFACE_MODE_SGMII_2500,
+	PHY_INTERFACE_MODE_QSGMII,
+	PHY_INTERFACE_MODE_TBI,
+	PHY_INTERFACE_MODE_RMII,
+	PHY_INTERFACE_MODE_RGMII,
+	PHY_INTERFACE_MODE_RGMII_ID,
+	PHY_INTERFACE_MODE_RGMII_RXID,
+	PHY_INTERFACE_MODE_RGMII_TXID,
+	PHY_INTERFACE_MODE_RTBI,
+	PHY_INTERFACE_MODE_XGMII,
+	PHY_INTERFACE_MODE_XAUI,
+	PHY_INTERFACE_MODE_RXAUI,
+	PHY_INTERFACE_MODE_SFI,
+	PHY_INTERFACE_MODE_INTERNAL,
+	PHY_INTERFACE_MODE_NONE,	/* Must be last */
+
+	PHY_INTERFACE_MODE_COUNT,
+} phy_interface_t;
+
+static const char * const phy_interface_strings[] = {
+	[PHY_INTERFACE_MODE_MII]		= "mii",
+	[PHY_INTERFACE_MODE_GMII]		= "gmii",
+	[PHY_INTERFACE_MODE_SGMII]		= "sgmii",
+	[PHY_INTERFACE_MODE_SGMII_2500]		= "sgmii-2500",
+	[PHY_INTERFACE_MODE_QSGMII]		= "qsgmii",
+	[PHY_INTERFACE_MODE_TBI]		= "tbi",
+	[PHY_INTERFACE_MODE_RMII]		= "rmii",
+	[PHY_INTERFACE_MODE_RGMII]		= "rgmii",
+	[PHY_INTERFACE_MODE_RGMII_ID]		= "rgmii-id",
+	[PHY_INTERFACE_MODE_RGMII_RXID]		= "rgmii-rxid",
+	[PHY_INTERFACE_MODE_RGMII_TXID]		= "rgmii-txid",
+	[PHY_INTERFACE_MODE_RTBI]		= "rtbi",
+	[PHY_INTERFACE_MODE_XGMII]		= "xgmii",
+	[PHY_INTERFACE_MODE_XAUI]		= "xaui",
+	[PHY_INTERFACE_MODE_RXAUI]		= "rxaui",
+	[PHY_INTERFACE_MODE_SFI]		= "sfi",
+	[PHY_INTERFACE_MODE_INTERNAL]		= "internal",
+	[PHY_INTERFACE_MODE_NONE]		= "",
+};
+
+static inline const char *phy_string_for_interface(phy_interface_t i)
+{
+	/* Default to unknown */
+	if (i > PHY_INTERFACE_MODE_NONE)
+		i = PHY_INTERFACE_MODE_NONE;
+
+	return phy_interface_strings[i];
+}
+
+#endif /* _PHY_INTERFACE_H */
diff --git a/lib/efi_loader/efi_net.c b/lib/efi_loader/efi_net.c
index e1139501d1fbd59833384c3ca98d821a97d478aa..5a3d7be86cf41dea93ade9a2c8d6b3b4a181e55e 100644
--- a/lib/efi_loader/efi_net.c
+++ b/lib/efi_loader/efi_net.c
@@ -361,6 +361,7 @@ efi_status_t efi_net_register(void)
 	memcpy(netobj->net_mode.current_address.mac_addr, eth_get_ethaddr(), 6);
 	netobj->net_mode.hwaddr_size = ARP_HLEN;
 	netobj->net_mode.max_packet_size = PKTSIZE;
+	netobj->net_mode.if_type = ARP_ETHER;
 
 	netobj->pxe.mode = &netobj->pxe_mode;
 	if (dhcp_ack)
diff --git a/net/eth-uclass.c b/net/eth-uclass.c
index e4b49229e38d02936f668ed18b2fa53bceee3191..fa3f5497a2902577f2bbb84947d918836b7bcbab 100644
--- a/net/eth-uclass.c
+++ b/net/eth-uclass.c
@@ -307,7 +307,7 @@ void eth_halt(void)
 	struct eth_device_priv *priv;
 
 	current = eth_get_dev();
-	if (!current || !device_active(current))
+	if (!current || !eth_is_active(current))
 		return;
 
 	eth_get_ops(current)->stop(current);
diff --git a/net/net.c b/net/net.c
index f35695b4fc9f0b62ffd8189c4cc9693c9dc41f87..31cf306ae71e11cf0f5ad65e992a1380d84faeba 100644
--- a/net/net.c
+++ b/net/net.c
@@ -216,26 +216,6 @@ int __maybe_unused net_busy_flag;
 
 /**********************************************************************/
 
-static int on_bootfile(const char *name, const char *value, enum env_op op,
-	int flags)
-{
-	if (flags & H_PROGRAMMATIC)
-		return 0;
-
-	switch (op) {
-	case env_op_create:
-	case env_op_overwrite:
-		copy_filename(net_boot_file_name, value,
-			      sizeof(net_boot_file_name));
-		break;
-	default:
-		break;
-	}
-
-	return 0;
-}
-U_BOOT_ENV_CALLBACK(bootfile, on_bootfile);
-
 static int on_ipaddr(const char *name, const char *value, enum env_op op,
 	int flags)
 {
@@ -332,6 +312,16 @@ void net_auto_load(void)
 	const char *s = env_get("autoload");
 
 	if (s != NULL && strcmp(s, "NFS") == 0) {
+		if (net_check_prereq(NFS)) {
+/* We aren't expecting to get a serverip, so just accept the assigned IP */
+#ifdef CONFIG_BOOTP_SERVERIP
+			net_set_state(NETLOOP_SUCCESS);
+#else
+			printf("Cannot autoload with NFS\n");
+			net_set_state(NETLOOP_FAIL);
+#endif
+			return;
+		}
 		/*
 		 * Use NFS to load the bootfile.
 		 */
@@ -347,6 +337,16 @@ void net_auto_load(void)
 		net_set_state(NETLOOP_SUCCESS);
 		return;
 	}
+	if (net_check_prereq(TFTPGET)) {
+/* We aren't expecting to get a serverip, so just accept the assigned IP */
+#ifdef CONFIG_BOOTP_SERVERIP
+		net_set_state(NETLOOP_SUCCESS);
+#else
+		printf("Cannot autoload with TFTPGET\n");
+		net_set_state(NETLOOP_FAIL);
+#endif
+		return;
+	}
 	tftp_start(TFTPGET);
 }
 
@@ -1341,7 +1341,7 @@ static int net_check_prereq(enum proto_t protocol)
 		/* Fall through */
 	case TFTPGET:
 	case TFTPPUT:
-		if (net_server_ip.s_addr == 0) {
+		if (net_server_ip.s_addr == 0 && !is_serverip_in_cmd()) {
 			puts("*** ERROR: `serverip' not set\n");
 			return 1;
 		}
@@ -1502,16 +1502,41 @@ void net_set_udp_header(uchar *pkt, struct in_addr dest, int dport, int sport,
 
 void copy_filename(char *dst, const char *src, int size)
 {
-	if (*src && (*src == '"')) {
+	if (src && *src && (*src == '"')) {
 		++src;
 		--size;
 	}
 
-	while ((--size > 0) && *src && (*src != '"'))
+	while ((--size > 0) && src && *src && (*src != '"'))
 		*dst++ = *src++;
 	*dst = '\0';
 }
 
+int is_serverip_in_cmd(void)
+{
+	return !!strchr(net_boot_file_name, ':');
+}
+
+int net_parse_bootfile(struct in_addr *ipaddr, char *filename, int max_len)
+{
+	char *colon;
+
+	if (net_boot_file_name[0] == '\0')
+		return 0;
+
+	colon = strchr(net_boot_file_name, ':');
+	if (colon) {
+		if (ipaddr)
+			*ipaddr = string_to_ip(net_boot_file_name);
+		strncpy(filename, colon + 1, max_len);
+	} else {
+		strncpy(filename, net_boot_file_name, max_len);
+	}
+	filename[max_len - 1] = '\0';
+
+	return 1;
+}
+
 #if	defined(CONFIG_CMD_NFS)		|| \
 	defined(CONFIG_CMD_SNTP)	|| \
 	defined(CONFIG_CMD_DNS)
diff --git a/net/nfs.c b/net/nfs.c
index 9a16765ba1574fea6f732652aa9d51ad9cf604c1..d6a7f8e827a1ce47712daca250f45c1ccc24c531 100644
--- a/net/nfs.c
+++ b/net/nfs.c
@@ -533,7 +533,7 @@ static int nfs_lookup_reply(uchar *pkt, unsigned len)
 			switch (ntohl(rpc_pkt.u.reply.data[0])) {
 			/* Minimal supported NFS version */
 			case 3:
-				debug("*** Waring: NFS version not supported: Requested: V%d, accepted: min V%d - max V%d\n",
+				debug("*** Warning: NFS version not supported: Requested: V%d, accepted: min V%d - max V%d\n",
 				      (supported_nfs_versions & NFSV2_FLAG) ?
 						2 : 3,
 				      ntohl(rpc_pkt.u.reply.data[0]),
@@ -855,40 +855,29 @@ void nfs_start(void)
 
 	if (nfs_path == NULL) {
 		net_set_state(NETLOOP_FAIL);
-		debug("*** ERROR: Fail allocate memory\n");
+		printf("*** ERROR: Fail allocate memory\n");
 		return;
 	}
 
-	if (net_boot_file_name[0] == '\0') {
+	if (!net_parse_bootfile(&nfs_server_ip, nfs_path,
+				sizeof(nfs_path_buff))) {
 		sprintf(nfs_path, "/nfsroot/%02X%02X%02X%02X.img",
 			net_ip.s_addr & 0xFF,
 			(net_ip.s_addr >>  8) & 0xFF,
 			(net_ip.s_addr >> 16) & 0xFF,
 			(net_ip.s_addr >> 24) & 0xFF);
 
-		debug("*** Warning: no boot file name; using '%s'\n",
-		      nfs_path);
-	} else {
-		char *p = net_boot_file_name;
-
-		p = strchr(p, ':');
-
-		if (p != NULL) {
-			nfs_server_ip = string_to_ip(net_boot_file_name);
-			++p;
-			strcpy(nfs_path, p);
-		} else {
-			strcpy(nfs_path, net_boot_file_name);
-		}
+		printf("*** Warning: no boot file name; using '%s'\n",
+		       nfs_path);
 	}
 
 	nfs_filename = basename(nfs_path);
 	nfs_path     = dirname(nfs_path);
 
-	debug("Using %s device\n", eth_get_name());
+	printf("Using %s device\n", eth_get_name());
 
-	debug("File transfer via NFS from server %pI4; our IP address is %pI4",
-	      &nfs_server_ip, &net_ip);
+	printf("File transfer via NFS from server %pI4; our IP address is %pI4",
+	       &nfs_server_ip, &net_ip);
 
 	/* Check if we need to send across this subnet */
 	if (net_gateway.s_addr && net_netmask.s_addr) {
@@ -896,19 +885,19 @@ void nfs_start(void)
 		struct in_addr server_net;
 
 		our_net.s_addr = net_ip.s_addr & net_netmask.s_addr;
-		server_net.s_addr = net_server_ip.s_addr & net_netmask.s_addr;
+		server_net.s_addr = nfs_server_ip.s_addr & net_netmask.s_addr;
 		if (our_net.s_addr != server_net.s_addr)
-			debug("; sending through gateway %pI4",
-			      &net_gateway);
+			printf("; sending through gateway %pI4",
+			       &net_gateway);
 	}
-	debug("\nFilename '%s/%s'.", nfs_path, nfs_filename);
+	printf("\nFilename '%s/%s'.", nfs_path, nfs_filename);
 
 	if (net_boot_file_expected_size_in_blocks) {
-		debug(" Size is 0x%x Bytes = ",
-		      net_boot_file_expected_size_in_blocks << 9);
+		printf(" Size is 0x%x Bytes = ",
+		       net_boot_file_expected_size_in_blocks << 9);
 		print_size(net_boot_file_expected_size_in_blocks << 9, "");
 	}
-	debug("\nLoad address: 0x%lx\nLoading: *\b", load_addr);
+	printf("\nLoad address: 0x%lx\nLoading: *\b", load_addr);
 
 	net_set_timeout_handler(nfs_timeout, nfs_timeout_handler);
 	net_set_udp_handler(nfs_handler);
diff --git a/net/nfs.h b/net/nfs.h
index 6359cd2848e56abe7bdd39afbdea7c6aa7eaae3e..a377c90088388b94e77cf23226e38a47ffd2021b 100644
--- a/net/nfs.h
+++ b/net/nfs.h
@@ -42,6 +42,7 @@
  * case, most NFS servers are optimized for a power of 2.
  */
 #define NFS_READ_SIZE	1024	/* biggest power of two that fits Ether frame */
+#define NFS_MAX_ATTRS	26
 
 /* Values for Accept State flag on RPC answers (See: rfc1831) */
 enum rpc_accept_stat {
@@ -55,7 +56,8 @@ enum rpc_accept_stat {
 
 struct rpc_t {
 	union {
-		uint8_t data[2048];
+		uint8_t data[NFS_READ_SIZE + (6 + NFS_MAX_ATTRS) *
+			sizeof(uint32_t)];
 		struct {
 			uint32_t id;
 			uint32_t type;
@@ -72,7 +74,8 @@ struct rpc_t {
 			uint32_t verifier;
 			uint32_t v2;
 			uint32_t astatus;
-			uint32_t data[NFS_READ_SIZE];
+			uint32_t data[NFS_READ_SIZE / sizeof(uint32_t) +
+				NFS_MAX_ATTRS];
 		} reply;
 	} u;
 } __attribute__((packed));
diff --git a/net/tftp.c b/net/tftp.c
index 6671b1f7ca726acf44b6f18f41f9f017c10fd1ec..68ffd814146c8ded1ec8c613980f4c2d45ba8f2c 100644
--- a/net/tftp.c
+++ b/net/tftp.c
@@ -735,7 +735,7 @@ void tftp_start(enum proto_t protocol)
 	      tftp_block_size_option, timeout_ms);
 
 	tftp_remote_ip = net_server_ip;
-	if (net_boot_file_name[0] == '\0') {
+	if (!net_parse_bootfile(&tftp_remote_ip, tftp_filename, MAX_LEN)) {
 		sprintf(default_filename, "%02X%02X%02X%02X.img",
 			net_ip.s_addr & 0xFF,
 			(net_ip.s_addr >>  8) & 0xFF,
@@ -747,17 +747,6 @@ void tftp_start(enum proto_t protocol)
 
 		printf("*** Warning: no boot file name; using '%s'\n",
 		       tftp_filename);
-	} else {
-		char *p = strchr(net_boot_file_name, ':');
-
-		if (p == NULL) {
-			strncpy(tftp_filename, net_boot_file_name, MAX_LEN);
-			tftp_filename[MAX_LEN - 1] = 0;
-		} else {
-			tftp_remote_ip = string_to_ip(net_boot_file_name);
-			strncpy(tftp_filename, p + 1, MAX_LEN);
-			tftp_filename[MAX_LEN - 1] = 0;
-		}
 	}
 
 	printf("Using %s device\n", eth_get_name());