diff --git a/arch/m68k/include/asm/fec.h b/arch/m68k/include/asm/fec.h
index 6856aac82dfcdbf7dbb61d473451bd28d7511afc..2799293e9a9034090f1a29ae333b65125745ba7d 100644
--- a/arch/m68k/include/asm/fec.h
+++ b/arch/m68k/include/asm/fec.h
@@ -15,6 +15,8 @@
 #ifndef	fec_h
 #define	fec_h
 
+#include <phy.h>
+
 /* Buffer descriptors used FEC.
 */
 typedef struct cpm_buf_desc {
@@ -341,10 +343,9 @@ int fecpin_setclear(struct eth_device *dev, int setclear);
 void __mii_init(void);
 uint mii_send(uint mii_cmd);
 int mii_discover_phy(struct eth_device *dev);
-int mcffec_miiphy_read(const char *devname, unsigned char addr,
-		       unsigned char reg, unsigned short *value);
-int mcffec_miiphy_write(const char *devname, unsigned char addr,
-			unsigned char reg, unsigned short value);
+int mcffec_miiphy_read(struct mii_dev *bus, int addr, int devad, int reg);
+int mcffec_miiphy_write(struct mii_dev *bus, int addr, int devad, int reg,
+			u16 value);
 #endif
 
 #endif				/* fec_h */
diff --git a/arch/mips/mach-au1x00/au1x00_eth.c b/arch/mips/mach-au1x00/au1x00_eth.c
index 921686081ff2c5b80aba9b5b35f7db0e92df7e1c..67f495351583a72aa8c151caf1b69cec84e9f86f 100644
--- a/arch/mips/mach-au1x00/au1x00_eth.c
+++ b/arch/mips/mach-au1x00/au1x00_eth.c
@@ -73,9 +73,9 @@ mac_fifo_t mac_fifo[NO_OF_FIFOS];
 #define MAX_WAIT 1000
 
 #if defined(CONFIG_CMD_MII)
-int  au1x00_miiphy_read(const char *devname, unsigned char addr,
-		unsigned char reg, unsigned short * value)
+int au1x00_miiphy_read(struct mii_dev *bus, int addr, int devad, int reg)
 {
+	unsigned short value = 0;
 	volatile u32 *mii_control_reg = (volatile u32*)(ETH0_BASE+MAC_MII_CNTRL);
 	volatile u32 *mii_data_reg = (volatile u32*)(ETH0_BASE+MAC_MII_DATA);
 	u32 mii_control;
@@ -102,12 +102,12 @@ int  au1x00_miiphy_read(const char *devname, unsigned char addr,
 			return -1;
 		}
 	}
-	*value = *mii_data_reg;
-	return 0;
+	value = *mii_data_reg;
+	return value;
 }
 
-int  au1x00_miiphy_write(const char *devname, unsigned char addr,
-		unsigned char reg, unsigned short value)
+int au1x00_miiphy_write(struct mii_dev *bus, int addr, int devad, int reg,
+			u16 value)
 {
 	volatile u32 *mii_control_reg = (volatile u32*)(ETH0_BASE+MAC_MII_CNTRL);
 	volatile u32 *mii_data_reg = (volatile u32*)(ETH0_BASE+MAC_MII_DATA);
@@ -290,8 +290,17 @@ int au1x00_enet_initialize(bd_t *bis){
 	eth_register(dev);
 
 #if defined(CONFIG_CMD_MII)
-	miiphy_register(dev->name,
-		au1x00_miiphy_read, au1x00_miiphy_write);
+	int retval;
+	struct mii_dev *mdiodev = mdio_alloc();
+	if (!mdiodev)
+		return -ENOMEM;
+	strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+	mdiodev->read = au1x00_miiphy_read;
+	mdiodev->write = au1x00_miiphy_write;
+
+	retval = mdio_register(mdiodev);
+	if (retval < 0)
+		return retval;
 #endif
 
 	return 1;
diff --git a/arch/powerpc/cpu/mpc8260/ether_fcc.c b/arch/powerpc/cpu/mpc8260/ether_fcc.c
index a11ad1e9d06be650266fc48ee1d1402c853f15e8..072eb76150b7b6d60a28532db6c6476035d112eb 100644
--- a/arch/powerpc/cpu/mpc8260/ether_fcc.c
+++ b/arch/powerpc/cpu/mpc8260/ether_fcc.c
@@ -379,8 +379,17 @@ int fec_initialize(bd_t *bis)
 
 #if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII)) \
 		&& defined(CONFIG_BITBANGMII)
-		miiphy_register(dev->name,
-				bb_miiphy_read,	bb_miiphy_write);
+		int retval;
+		struct mii_dev *mdiodev = mdio_alloc();
+		if (!mdiodev)
+			return -ENOMEM;
+		strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+		mdiodev->read = bb_miiphy_read;
+		mdiodev->write = bb_miiphy_write;
+
+		retval = mdio_register(mdiodev);
+		if (retval < 0)
+			return retval;
 #endif
 	}
 
diff --git a/arch/powerpc/cpu/mpc85xx/ether_fcc.c b/arch/powerpc/cpu/mpc85xx/ether_fcc.c
index 51f1beef5196a21f70067b1c3ae8a06c844ed9f6..7708f059ca21a73ccfd215a1aa72bc0a093cae80 100644
--- a/arch/powerpc/cpu/mpc85xx/ether_fcc.c
+++ b/arch/powerpc/cpu/mpc85xx/ether_fcc.c
@@ -441,8 +441,17 @@ int fec_initialize(bd_t *bis)
 
 #if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII)) \
 		&& defined(CONFIG_BITBANGMII)
-		miiphy_register(dev->name,
-				bb_miiphy_read,	bb_miiphy_write);
+		int retval;
+		struct mii_dev *mdiodev = mdio_alloc();
+		if (!mdiodev)
+			return -ENOMEM;
+		strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+		mdiodev->read = bb_miiphy_read;
+		mdiodev->write = bb_miiphy_write;
+
+		retval = mdio_register(mdiodev);
+		if (retval < 0)
+			return retval;
 #endif
 	}
 
diff --git a/arch/powerpc/cpu/mpc8xx/fec.c b/arch/powerpc/cpu/mpc8xx/fec.c
index f1ae3584660b33c39fa9802d53537b577ecbafef..0940906b1d4b6ba6fa8674c6e38a319000165d6b 100644
--- a/arch/powerpc/cpu/mpc8xx/fec.c
+++ b/arch/powerpc/cpu/mpc8xx/fec.c
@@ -6,10 +6,12 @@
  */
 
 #include <common.h>
-#include <malloc.h>
+#include <command.h>
 #include <commproc.h>
+#include <malloc.h>
 #include <net.h>
-#include <command.h>
+
+#include <phy.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -47,10 +49,9 @@ DECLARE_GLOBAL_DATA_PTR;
 static int mii_discover_phy(struct eth_device *dev);
 #endif
 
-int fec8xx_miiphy_read(const char *devname, unsigned char addr,
-		unsigned char  reg, unsigned short *value);
-int fec8xx_miiphy_write(const char *devname, unsigned char  addr,
-		unsigned char  reg, unsigned short value);
+int fec8xx_miiphy_read(struct mii_dev *bus, int addr, int devad, int reg);
+int fec8xx_miiphy_write(struct mii_dev *bus, int addr, int devad, int reg,
+			u16 value);
 
 static struct ether_fcc_info_s
 {
@@ -170,8 +171,17 @@ int fec_initialize(bd_t *bis)
 		eth_register(dev);
 
 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
-		miiphy_register(dev->name,
-			fec8xx_miiphy_read, fec8xx_miiphy_write);
+		int retval;
+		struct mii_dev *mdiodev = mdio_alloc();
+		if (!mdiodev)
+			return -ENOMEM;
+		strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+		mdiodev->read = fec8xx_miiphy_read;
+		mdiodev->write = fec8xx_miiphy_write;
+
+		retval = mdio_register(mdiodev);
+		if (retval < 0)
+			return retval;
 #endif
 	}
 	return 1;
@@ -894,9 +904,9 @@ void mii_init (void)
  *	  Otherwise they hang in mii_send() !!! Sorry!
  *****************************************************************************/
 
-int fec8xx_miiphy_read(const char *devname, unsigned char addr,
-		unsigned char  reg, unsigned short *value)
+int fec8xx_miiphy_read(struct mii_dev *bus, int addr, int devad, int reg)
 {
+	unsigned short value = 0;
 	short rdreg;    /* register working value */
 
 #ifdef MII_DEBUG
@@ -904,15 +914,15 @@ int fec8xx_miiphy_read(const char *devname, unsigned char addr,
 #endif
 	rdreg = mii_send(mk_mii_read(addr, reg));
 
-	*value = rdreg;
+	value = rdreg;
 #ifdef MII_DEBUG
-	printf ("0x%04x\n", *value);
+	printf ("0x%04x\n", value);
 #endif
-	return 0;
+	return value;
 }
 
-int fec8xx_miiphy_write(const char *devname, unsigned char  addr,
-		unsigned char  reg, unsigned short value)
+int fec8xx_miiphy_write(struct mii_dev *bus, int addr, int devad, int reg,
+			u16 value)
 {
 #ifdef MII_DEBUG
 	printf ("miiphy_write(0x%x) @ 0x%x = ", reg, addr);
diff --git a/arch/powerpc/cpu/ppc4xx/miiphy.c b/arch/powerpc/cpu/ppc4xx/miiphy.c
index 10147de0897d7be956e014ce120759fe55144af3..f0fc098059e5c156c78a64a14858c63d29d82c65 100644
--- a/arch/powerpc/cpu/ppc4xx/miiphy.c
+++ b/arch/powerpc/cpu/ppc4xx/miiphy.c
@@ -318,8 +318,7 @@ static int emac_miiphy_command(u8 addr, u8 reg, int cmd, u16 value)
 	return 0;
 }
 
-int emac4xx_miiphy_read (const char *devname, unsigned char addr, unsigned char reg,
-			 unsigned short *value)
+int emac4xx_miiphy_read(struct mii_dev *bus, int addr, int devad, int reg)
 {
 	unsigned long sta_reg;
 	unsigned long emac_reg;
@@ -330,17 +329,15 @@ int emac4xx_miiphy_read (const char *devname, unsigned char addr, unsigned char
 		return -1;
 
 	sta_reg = in_be32((void *)EMAC0_STACR + emac_reg);
-	*value = sta_reg >> 16;
-
-	return 0;
+	return sta_reg >> 16;
 }
 
 /***********************************************************/
 /* write a phy reg and return the value with a rc	    */
 /***********************************************************/
 
-int emac4xx_miiphy_write (const char *devname, unsigned char addr, unsigned char reg,
-			  unsigned short value)
+int emac4xx_miiphy_write(struct mii_dev *bus, int addr, int devad, int reg,
+			 u16 value)
 {
 	return emac_miiphy_command(addr, reg, EMAC_STACR_WRITE, value);
 }
diff --git a/board/gdsys/405ep/io.c b/board/gdsys/405ep/io.c
index 03d796cdb89b1b09eb9662328ea862341629d3a9..81b49659ff85e5d5c7a9e17d59d5bfd9045e41c0 100644
--- a/board/gdsys/405ep/io.c
+++ b/board/gdsys/405ep/io.c
@@ -172,8 +172,17 @@ int last_stage_init(void)
 
 	print_fpga_info();
 
-	miiphy_register(CONFIG_SYS_GBIT_MII_BUSNAME,
-		bb_miiphy_read, bb_miiphy_write);
+	int retval;
+	struct mii_dev *mdiodev = mdio_alloc();
+	if (!mdiodev)
+		return -ENOMEM;
+	strncpy(mdiodev->name, CONFIG_SYS_GBIT_MII_BUSNAME, MDIO_NAME_LEN);
+	mdiodev->read = bb_miiphy_read;
+	mdiodev->write = bb_miiphy_write;
+
+	retval = mdio_register(mdiodev);
+	if (retval < 0)
+		return retval;
 
 	for (k = 0; k < 32; ++k)
 		configure_gbit_phy(k);
diff --git a/board/gdsys/405ep/iocon.c b/board/gdsys/405ep/iocon.c
index 7484624d13e14d5eefa42e401d15d9390fb0558f..7db0e29ea6c96c2ef3151dc25f29e5301792370f 100644
--- a/board/gdsys/405ep/iocon.c
+++ b/board/gdsys/405ep/iocon.c
@@ -405,8 +405,17 @@ int last_stage_init(void)
 	}
 
 	if (!legacy && (feature_carrier_speed == CARRIER_SPEED_1G)) {
-		miiphy_register(bb_miiphy_buses[0].name, bb_miiphy_read,
-				bb_miiphy_write);
+		int retval;
+		struct mii_dev *mdiodev = mdio_alloc();
+		if (!mdiodev)
+			return -ENOMEM;
+		strncpy(mdiodev->name, bb_miiphy_buses[0].name, MDIO_NAME_LEN);
+		mdiodev->read = bb_miiphy_read;
+		mdiodev->write = bb_miiphy_write;
+
+		retval = mdio_register(mdiodev);
+		if (retval < 0)
+			return retval;
 		for (mux_ch = 0; mux_ch < MAX_MUX_CHANNELS; ++mux_ch) {
 			if ((mux_ch == 1) && !ch0_rgmii2_present)
 				continue;
@@ -437,8 +446,18 @@ int last_stage_init(void)
 		print_fpga_info(k, false);
 		osd_probe(k);
 		if (feature_carrier_speed == CARRIER_SPEED_1G) {
-			miiphy_register(bb_miiphy_buses[k].name,
-					bb_miiphy_read, bb_miiphy_write);
+			int retval;
+			struct mii_dev *mdiodev = mdio_alloc();
+			if (!mdiodev)
+				return -ENOMEM;
+			strncpy(mdiodev->name, bb_miiphy_buses[k].name,
+				MDIO_NAME_LEN);
+			mdiodev->read = bb_miiphy_read;
+			mdiodev->write = bb_miiphy_write;
+
+			retval = mdio_register(mdiodev);
+			if (retval < 0)
+				return retval;
 			setup_88e1518(bb_miiphy_buses[k].name, 0);
 		}
 	}
diff --git a/board/gdsys/405ex/io64.c b/board/gdsys/405ex/io64.c
index 3a075c471f87d63df491120267367bed84702243..848cdde5e6bb1ae0e37bcaca2901cc2b3f3585ab 100644
--- a/board/gdsys/405ex/io64.c
+++ b/board/gdsys/405ex/io64.c
@@ -246,8 +246,17 @@ int last_stage_init(void)
 	/* setup Gbit PHYs */
 	puts("TRANS: ");
 	puts(str_phys);
-	miiphy_register(CONFIG_SYS_GBIT_MII_BUSNAME,
-		bb_miiphy_read, bb_miiphy_write);
+	int retval;
+	struct mii_dev *mdiodev = mdio_alloc();
+	if (!mdiodev)
+		return -ENOMEM;
+	strncpy(mdiodev->name, CONFIG_SYS_GBIT_MII_BUSNAME, MDIO_NAME_LEN);
+	mdiodev->read = bb_miiphy_read;
+	mdiodev->write = bb_miiphy_write;
+
+	retval = mdio_register(mdiodev);
+	if (retval < 0)
+		return retval;
 
 	for (k = 0; k < 32; ++k) {
 		configure_gbit_phy(CONFIG_SYS_GBIT_MII_BUSNAME, k);
@@ -255,8 +264,16 @@ int last_stage_init(void)
 		putc(slash[k % 8]);
 	}
 
-	miiphy_register(CONFIG_SYS_GBIT_MII1_BUSNAME,
-		bb_miiphy_read, bb_miiphy_write);
+	mdiodev = mdio_alloc();
+	if (!mdiodev)
+		return -ENOMEM;
+	strncpy(mdiodev->name, CONFIG_SYS_GBIT_MII1_BUSNAME, MDIO_NAME_LEN);
+	mdiodev->read = bb_miiphy_read;
+	mdiodev->write = bb_miiphy_write;
+
+	retval = mdio_register(mdiodev);
+	if (retval < 0)
+		return retval;
 
 	for (k = 0; k < 32; ++k) {
 		configure_gbit_phy(CONFIG_SYS_GBIT_MII1_BUSNAME, k);
diff --git a/board/gdsys/mpc8308/hrcon.c b/board/gdsys/mpc8308/hrcon.c
index 880b6387de29c9139d1792fc93754dd578678179..f55893f79c9ae3bb175b7d5c5fc86c91941b7109 100644
--- a/board/gdsys/mpc8308/hrcon.c
+++ b/board/gdsys/mpc8308/hrcon.c
@@ -162,8 +162,17 @@ int last_stage_init(void)
 	}
 
 	if (hw_type_cat) {
-		miiphy_register(bb_miiphy_buses[0].name, bb_miiphy_read,
-				bb_miiphy_write);
+		int retval;
+		struct mii_dev *mdiodev = mdio_alloc();
+		if (!mdiodev)
+			return -ENOMEM;
+		strncpy(mdiodev->name, bb_miiphy_buses[0].name, MDIO_NAME_LEN);
+		mdiodev->read = bb_miiphy_read;
+		mdiodev->write = bb_miiphy_write;
+
+		retval = mdio_register(mdiodev);
+		if (retval < 0)
+			return retval;
 		for (mux_ch = 0; mux_ch < MAX_MUX_CHANNELS; ++mux_ch) {
 			if ((mux_ch == 1) && !ch0_rgmii2_present)
 				continue;
@@ -199,8 +208,18 @@ int last_stage_init(void)
 		osd_probe(k + 4);
 #endif
 		if (hw_type_cat) {
-			miiphy_register(bb_miiphy_buses[k].name,
-					bb_miiphy_read, bb_miiphy_write);
+			int retval;
+			struct mii_dev *mdiodev = mdio_alloc();
+			if (!mdiodev)
+				return -ENOMEM;
+			strncpy(mdiodev->name, bb_miiphy_buses[k].name,
+				MDIO_NAME_LEN);
+			mdiodev->read = bb_miiphy_read;
+			mdiodev->write = bb_miiphy_write;
+
+			retval = mdio_register(mdiodev);
+			if (retval < 0)
+				return retval;
 			setup_88e1514(bb_miiphy_buses[k].name, 0);
 		}
 	}
diff --git a/board/gdsys/mpc8308/strider.c b/board/gdsys/mpc8308/strider.c
index 121977d315fae60fb5e69c0a70f1fc8063a65378..b8dde5f1bad6f6e74a6cb1cdea0bf1cd11795317 100644
--- a/board/gdsys/mpc8308/strider.c
+++ b/board/gdsys/mpc8308/strider.c
@@ -179,8 +179,17 @@ int last_stage_init(void)
 	}
 
 	if (hw_type_cat) {
-		miiphy_register(bb_miiphy_buses[0].name, bb_miiphy_read,
-				bb_miiphy_write);
+		int retval;
+		struct mii_dev *mdiodev = mdio_alloc();
+		if (!mdiodev)
+			return -ENOMEM;
+		strncpy(mdiodev->name, bb_miiphy_buses[0].name, MDIO_NAME_LEN);
+		mdiodev->read = bb_miiphy_read;
+		mdiodev->write = bb_miiphy_write;
+
+		retval = mdio_register(mdiodev);
+		if (retval < 0)
+			return retval;
 		for (mux_ch = 0; mux_ch < MAX_MUX_CHANNELS; ++mux_ch) {
 			if ((mux_ch == 1) && !ch0_sgmii2_present)
 				continue;
@@ -252,8 +261,18 @@ int last_stage_init(void)
 		dp501_probe(k, false);
 #endif
 		if (hw_type_cat) {
-			miiphy_register(bb_miiphy_buses[k].name,
-					bb_miiphy_read, bb_miiphy_write);
+			int retval;
+			struct mii_dev *mdiodev = mdio_alloc();
+			if (!mdiodev)
+				return -ENOMEM;
+			strncpy(mdiodev->name, bb_miiphy_buses[k].name,
+				MDIO_NAME_LEN);
+			mdiodev->read = bb_miiphy_read;
+			mdiodev->write = bb_miiphy_write;
+
+			retval = mdio_register(mdiodev);
+			if (retval < 0)
+				return retval;
 			setup_88e1514(bb_miiphy_buses[k].name, 0);
 		}
 	}
diff --git a/common/miiphyutil.c b/common/miiphyutil.c
index 7e41957185072123a81468309081ec4586730867..08aa854efe49bdea3ff3b1e4b948165ed93f21c6 100644
--- a/common/miiphyutil.c
+++ b/common/miiphyutil.c
@@ -65,79 +65,6 @@ void miiphy_init(void)
 	current_mii = NULL;
 }
 
-static int legacy_miiphy_read(struct mii_dev *bus, int addr, int devad, int reg)
-{
-	unsigned short val;
-	int ret;
-	struct legacy_mii_dev *ldev = bus->priv;
-
-	ret = ldev->read(bus->name, addr, reg, &val);
-
-	return ret ? -1 : (int)val;
-}
-
-static int legacy_miiphy_write(struct mii_dev *bus, int addr, int devad,
-				int reg, u16 val)
-{
-	struct legacy_mii_dev *ldev = bus->priv;
-
-	return ldev->write(bus->name, addr, reg, val);
-}
-
-/*****************************************************************************
- *
- * Register read and write MII access routines for the device <name>.
- * This API is now deprecated. Please use mdio_alloc and mdio_register, instead.
- */
-void miiphy_register(const char *name,
-		      int (*read)(const char *devname, unsigned char addr,
-				   unsigned char reg, unsigned short *value),
-		      int (*write)(const char *devname, unsigned char addr,
-				    unsigned char reg, unsigned short value))
-{
-	struct mii_dev *new_dev;
-	struct legacy_mii_dev *ldev;
-
-	BUG_ON(strlen(name) >= MDIO_NAME_LEN);
-
-	/* check if we have unique name */
-	new_dev = miiphy_get_dev_by_name(name);
-	if (new_dev) {
-		printf("miiphy_register: non unique device name '%s'\n", name);
-		return;
-	}
-
-	/* allocate memory */
-	new_dev = mdio_alloc();
-	ldev = malloc(sizeof(*ldev));
-
-	if (new_dev == NULL || ldev == NULL) {
-		printf("miiphy_register: cannot allocate memory for '%s'\n",
-			name);
-		free(ldev);
-		mdio_free(new_dev);
-		return;
-	}
-
-	/* initalize mii_dev struct fields */
-	new_dev->read = legacy_miiphy_read;
-	new_dev->write = legacy_miiphy_write;
-	strncpy(new_dev->name, name, MDIO_NAME_LEN);
-	new_dev->name[MDIO_NAME_LEN - 1] = 0;
-	ldev->read = read;
-	ldev->write = write;
-	new_dev->priv = ldev;
-
-	debug("miiphy_register: added '%s', read=0x%08lx, write=0x%08lx\n",
-	       new_dev->name, ldev->read, ldev->write);
-
-	/* add it to the list */
-	list_add_tail(&new_dev->link, &mii_devs);
-
-	if (!current_mii)
-		current_mii = new_dev;
-}
-
 struct mii_dev *mdio_alloc(void)
 {
 	struct mii_dev *bus;
diff --git a/configs/openrisc-generic_defconfig b/configs/openrisc-generic_defconfig
index 14923c09785b8d42dffebfa4b502e316962cd85a..5bc81cc980bed4899cd24ae17a69eb54207e3656 100644
--- a/configs/openrisc-generic_defconfig
+++ b/configs/openrisc-generic_defconfig
@@ -6,5 +6,7 @@ CONFIG_TARGET_OPENRISC_GENERIC=y
 CONFIG_CMD_DHCP=y
 CONFIG_CMD_MII=y
 CONFIG_CMD_PING=y
+CONFIG_NETDEVICES=y
+CONFIG_ETHOC=y
 CONFIG_SYS_NS16550=y
 # CONFIG_AUTOBOOT is not set
diff --git a/drivers/net/4xx_enet.c b/drivers/net/4xx_enet.c
index bc52ed35ccbb9ce863c2edc1e578be14511a40cc..b71848168a64732fde151815cc5d5b6f7c3be462 100644
--- a/drivers/net/4xx_enet.c
+++ b/drivers/net/4xx_enet.c
@@ -283,10 +283,9 @@ static void mal_err (struct eth_device *dev, unsigned long isr,
 static void emac_err (struct eth_device *dev, unsigned long isr);
 
 extern int phy_setup_aneg (char *devname, unsigned char addr);
-extern int emac4xx_miiphy_read (const char *devname, unsigned char addr,
-		unsigned char reg, unsigned short *value);
-extern int emac4xx_miiphy_write (const char *devname, unsigned char addr,
-		unsigned char reg, unsigned short value);
+int emac4xx_miiphy_read(struct mii_dev *bus, int addr, int devad, int reg);
+int emac4xx_miiphy_write(struct mii_dev *bus, int addr, int devad, int reg,
+			 u16 value);
 
 int board_emac_count(void);
 
@@ -2015,8 +2014,17 @@ int ppc_4xx_eth_initialize (bd_t * bis)
 		eth_register(dev);
 
 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
-		miiphy_register(dev->name,
-				emac4xx_miiphy_read, emac4xx_miiphy_write);
+		int retval;
+		struct mii_dev *mdiodev = mdio_alloc();
+		if (!mdiodev)
+			return -ENOMEM;
+		strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+		mdiodev->read = emac4xx_miiphy_read;
+		mdiodev->write = emac4xx_miiphy_write;
+
+		retval = mdio_register(mdiodev);
+		if (retval < 0)
+			return retval;
 #endif
 
 		if (0 == virgin) {
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 88d8e83906a10b314db1d4730b4e9be8e3dcf896..be3ed73e52219fbc9179c9d7553cf5887b86c407 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -124,6 +124,11 @@ config ETH_DESIGNWARE
 	  100Mbit and 1 Gbit operation. You must enable CONFIG_PHYLIB to
 	  provide the PHY (physical media interface).
 
+config ETHOC
+	bool "OpenCores 10/100 Mbps Ethernet MAC"
+	help
+	  This MAC is present in OpenRISC and Xtensa XTFPGA boards.
+
 config MVPP2
 	bool "Marvell Armada 375 network interface support"
 	depends on ARMADA_375
diff --git a/drivers/net/armada100_fec.c b/drivers/net/armada100_fec.c
index e6a62525be0bcfb8ded9c358727ba8b4f4439719..ba2cb1ad6db56f0ce7892bf5af22ecf54df7264f 100644
--- a/drivers/net/armada100_fec.c
+++ b/drivers/net/armada100_fec.c
@@ -57,18 +57,19 @@ static int armdfec_phy_timeout(u32 *reg, u32 flag, int cond)
 	return !timeout;
 }
 
-static int smi_reg_read(const char *devname, u8 phy_addr, u8 phy_reg,
-			u16 *value)
+static int smi_reg_read(struct mii_dev *bus, int phy_addr, int devad,
+			int phy_reg)
 {
-	struct eth_device *dev = eth_get_dev_by_name(devname);
+	u16 value = 0;
+	struct eth_device *dev = eth_get_dev_by_name(bus->name);
 	struct armdfec_device *darmdfec = to_darmdfec(dev);
 	struct armdfec_reg *regs = darmdfec->regs;
 	u32 val;
 
 	if (phy_addr == PHY_ADR_REQ && phy_reg == PHY_ADR_REQ) {
 		val = readl(&regs->phyadr);
-		*value = val & 0x1f;
-		return 0;
+		value = val & 0x1f;
+		return value;
 	}
 
 	/* check parameters */
@@ -99,15 +100,15 @@ static int smi_reg_read(const char *devname, u8 phy_addr, u8 phy_reg,
 		return -1;
 	}
 	val = readl(&regs->smi);
-	*value = val & 0xffff;
+	value = val & 0xffff;
 
-	return 0;
+	return value;
 }
 
-static int smi_reg_write(const char *devname,
-	 u8 phy_addr, u8 phy_reg, u16 value)
+static int smi_reg_write(struct mii_dev *bus, int phy_addr, int devad,
+			 int phy_reg, u16 value)
 {
-	struct eth_device *dev = eth_get_dev_by_name(devname);
+	struct eth_device *dev = eth_get_dev_by_name(bus->name);
 	struct armdfec_device *darmdfec = to_darmdfec(dev);
 	struct armdfec_reg *regs = darmdfec->regs;
 
@@ -711,7 +712,17 @@ int armada100_fec_register(unsigned long base_addr)
 	eth_register(dev);
 
 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
-	miiphy_register(dev->name, smi_reg_read, smi_reg_write);
+	int retval;
+	struct mii_dev *mdiodev = mdio_alloc();
+	if (!mdiodev)
+		return -ENOMEM;
+	strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+	mdiodev->read = smi_reg_read;
+	mdiodev->write = smi_reg_write;
+
+	retval = mdio_register(mdiodev);
+	if (retval < 0)
+		return retval;
 #endif
 	return 0;
 
diff --git a/drivers/net/at91_emac.c b/drivers/net/at91_emac.c
index 915160019098889dddbb2bb725fbc26f92d329c9..be3d82e67eaccb9dd76c111263856215bdccc665 100644
--- a/drivers/net/at91_emac.c
+++ b/drivers/net/at91_emac.c
@@ -159,23 +159,23 @@ at91_emac_t *get_emacbase_by_name(const char *devname)
 	return (at91_emac_t *) netdev->iobase;
 }
 
-int  at91emac_mii_read(const char *devname, unsigned char addr,
-		unsigned char reg, unsigned short *value)
+int at91emac_mii_read(struct mii_dev *bus, int addr, int devad, int reg)
 {
+	unsigned short value = 0;
 	at91_emac_t *emac;
 
-	emac = get_emacbase_by_name(devname);
-	at91emac_read(emac , addr, reg, value);
-	return 0;
+	emac = get_emacbase_by_name(bus->name);
+	at91emac_read(emac , addr, reg, &value);
+	return value;
 }
 
 
-int  at91emac_mii_write(const char *devname, unsigned char addr,
-		unsigned char reg, unsigned short value)
+int at91emac_mii_write(struct mii_dev *bus, int addr, int devad, int reg,
+		       u16 value)
 {
 	at91_emac_t *emac;
 
-	emac = get_emacbase_by_name(devname);
+	emac = get_emacbase_by_name(bus->name);
 	at91emac_write(emac, addr, reg, value);
 	return 0;
 }
@@ -502,7 +502,17 @@ int at91emac_register(bd_t *bis, unsigned long iobase)
 	eth_register(dev);
 
 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
-	miiphy_register(dev->name, at91emac_mii_read, at91emac_mii_write);
+	int retval;
+	struct mii_dev *mdiodev = mdio_alloc();
+	if (!mdiodev)
+		return -ENOMEM;
+	strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+	mdiodev->read = at91emac_mii_read;
+	mdiodev->write = at91emac_mii_write;
+
+	retval = mdio_register(mdiodev);
+	if (retval < 0)
+		return retval;
 #endif
 	return 1;
 }
diff --git a/drivers/net/bcm-sf2-eth-gmac.c b/drivers/net/bcm-sf2-eth-gmac.c
index 977feec3511cc0f80d8194a38c4e9d86611dd303..f2853cfad250715eeb21022eb55723bc55016ef5 100644
--- a/drivers/net/bcm-sf2-eth-gmac.c
+++ b/drivers/net/bcm-sf2-eth-gmac.c
@@ -596,12 +596,10 @@ bool gmac_mii_busywait(unsigned int timeout)
 	return tmp & (1 << GMAC_MII_BUSY_SHIFT);
 }
 
-int gmac_miiphy_read(const char *devname, unsigned char phyaddr,
-			unsigned char reg, unsigned short *value)
+int gmac_miiphy_read(struct mii_dev *bus, int phyaddr, int devad, int reg)
 {
 	uint32_t tmp = 0;
-
-	(void)devname;
+	u16 value = 0;
 
 	/* Busy wait timeout is 1ms */
 	if (gmac_mii_busywait(1000)) {
@@ -621,18 +619,16 @@ int gmac_miiphy_read(const char *devname, unsigned char phyaddr,
 		return -1;
 	}
 
-	*value = readl(GMAC_MII_DATA_ADDR) & 0xffff;
-	debug("MII read data 0x%x\n", *value);
-	return 0;
+	value = readl(GMAC_MII_DATA_ADDR) & 0xffff;
+	debug("MII read data 0x%x\n", value);
+	return value;
 }
 
-int gmac_miiphy_write(const char *devname, unsigned char phyaddr,
-			 unsigned char reg, unsigned short value)
+int gmac_miiphy_write(struct mii_dev *bus, int phyaddr, int devad, int reg,
+		      u16 value)
 {
 	uint32_t tmp = 0;
 
-	(void)devname;
-
 	/* Busy wait timeout is 1ms */
 	if (gmac_mii_busywait(1000)) {
 		error("%s: Prepare MII write: MII/MDIO busy\n", __func__);
diff --git a/drivers/net/bcm-sf2-eth.c b/drivers/net/bcm-sf2-eth.c
index eab4c1f9003258d3926318d69b60f8c061e53c76..e2747365a20b3d46389bb7384bc4c66e9de5c47c 100644
--- a/drivers/net/bcm-sf2-eth.c
+++ b/drivers/net/bcm-sf2-eth.c
@@ -244,7 +244,18 @@ int bcm_sf2_eth_register(bd_t *bis, u8 dev_num)
 	eth_register(dev);
 
 #ifdef CONFIG_CMD_MII
-	miiphy_register(dev->name, eth->miiphy_read, eth->miiphy_write);
+	int retval;
+	struct mii_dev *mdiodev = mdio_alloc();
+
+	if (!mdiodev)
+		return -ENOMEM;
+	strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+	mdiodev->read = eth->miiphy_read;
+	mdiodev->write = eth->miiphy_write;
+
+	retval = mdio_register(mdiodev);
+	if (retval < 0)
+		return retval;
 #endif
 
 	/* Initialization */
diff --git a/drivers/net/bcm-sf2-eth.h b/drivers/net/bcm-sf2-eth.h
index 49a58361326d84f83adc2e0545eefe6ac1ceefa1..6104affc51c226bad0c6339c45543f6d59a42131 100644
--- a/drivers/net/bcm-sf2-eth.h
+++ b/drivers/net/bcm-sf2-eth.h
@@ -54,10 +54,10 @@ struct eth_info {
 	struct phy_device *port[BCM_ETH_MAX_PORT_NUM];
 	int port_num;
 
-	int (*miiphy_read)(const char *devname, unsigned char phyaddr,
-			   unsigned char reg, unsigned short *value);
-	int (*miiphy_write)(const char *devname, unsigned char phyaddr,
-			    unsigned char reg, unsigned short value);
+	int (*miiphy_read)(struct mii_dev *bus, int phyaddr, int devad,
+			   int reg);
+	int (*miiphy_write)(struct mii_dev *bus, int phyaddr, int devad,
+			    int reg, u16 value);
 
 	int (*mac_init)(struct eth_device *dev);
 	int (*enable_mac)(void);
diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c
index 61cb1b0cdad79a23c46dbc8685f21b0e6ddf60c8..26a626b4cbd59eea4eef55886213bf6c3d2cde66 100644
--- a/drivers/net/bfin_mac.c
+++ b/drivers/net/bfin_mac.c
@@ -13,6 +13,7 @@
 #include <command.h>
 #include <malloc.h>
 #include <miiphy.h>
+#include <linux/mdio.h>
 #include <linux/mii.h>
 
 #include <asm/blackfin.h>
@@ -72,18 +73,20 @@ static int bfin_miiphy_wait(void)
 	return 0;
 }
 
-static int bfin_miiphy_read(const char *devname, uchar addr, uchar reg, ushort *val)
+static int bfin_miiphy_read(struct mii_dev *bus, int addr, int devad, int reg)
 {
+	ushort val = 0;
 	if (bfin_miiphy_wait())
 		return 1;
 	bfin_write_EMAC_STAADD(SET_PHYAD(addr) | SET_REGAD(reg) | STABUSY);
 	if (bfin_miiphy_wait())
 		return 1;
-	*val = bfin_read_EMAC_STADAT();
-	return 0;
+	val = bfin_read_EMAC_STADAT();
+	return val;
 }
 
-static int bfin_miiphy_write(const char *devname, uchar addr, uchar reg, ushort val)
+static int bfin_miiphy_write(struct mii_dev *bus, int addr, int devad,
+			     int reg, u16 val)
 {
 	if (bfin_miiphy_wait())
 		return 1;
@@ -113,7 +116,19 @@ int bfin_EMAC_initialize(bd_t *bis)
 	eth_register(dev);
 
 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
-	miiphy_register(dev->name, bfin_miiphy_read, bfin_miiphy_write);
+	int retval;
+	struct mii_dev *mdiodev = mdio_alloc();
+	if (!mdiodev)
+		return -ENOMEM;
+	strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+	mdiodev->read = bfin_miiphy_read;
+	mdiodev->write = bfin_miiphy_write;
+
+	retval = mdio_register(mdiodev);
+	if (retval < 0)
+		return retval;
+
+	dev->priv = mdiodev;
 #endif
 
 	return 0;
@@ -222,8 +237,9 @@ static int bfin_EMAC_recv(struct eth_device *dev)
 static int bfin_miiphy_init(struct eth_device *dev, int *opmode)
 {
 	const unsigned short pins[] = CONFIG_BFIN_MAC_PINS;
-	u16 phydat;
+	int phydat;
 	size_t count;
+	struct mii_dev *mdiodev = dev->priv;
 
 	/* Enable PHY output */
 	bfin_write_VR_CTL(bfin_read_VR_CTL() | CLKBUFOE);
@@ -236,12 +252,15 @@ static int bfin_miiphy_init(struct eth_device *dev, int *opmode)
 	bfin_write_EMAC_SYSCTL(RXDWA | RXCKS | SET_MDCDIV(MDC_FREQ_TO_DIV(CONFIG_PHY_CLOCK_FREQ)));
 
 	/* turn on auto-negotiation and wait for link to come up */
-	bfin_miiphy_write(dev->name, CONFIG_PHY_ADDR, MII_BMCR, BMCR_ANENABLE);
+	bfin_miiphy_write(mdiodev, CONFIG_PHY_ADDR, MDIO_DEVAD_NONE, MII_BMCR,
+			  BMCR_ANENABLE);
 	count = 0;
 	while (1) {
 		++count;
-		if (bfin_miiphy_read(dev->name, CONFIG_PHY_ADDR, MII_BMSR, &phydat))
-			return -1;
+		phydat = bfin_miiphy_read(mdiodev, CONFIG_PHY_ADDR,
+					  MDIO_DEVAD_NONE, MII_BMSR);
+		if (phydat < 0)
+			return phydat;
 		if (phydat & BMSR_LSTATUS)
 			break;
 		if (count > 30000) {
@@ -252,8 +271,10 @@ static int bfin_miiphy_init(struct eth_device *dev, int *opmode)
 	}
 
 	/* see what kind of link we have */
-	if (bfin_miiphy_read(dev->name, CONFIG_PHY_ADDR, MII_LPA, &phydat))
-		return -1;
+	phydat = bfin_miiphy_read(mdiodev, CONFIG_PHY_ADDR, MDIO_DEVAD_NONE,
+				  MII_LPA);
+	if (phydat < 0)
+		return phydat;
 	if (phydat & LPA_DUPLEX)
 		*opmode = FDMODE;
 	else
diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c
index b03049840286339384d4358fc46f15af66c78ac0..ca457b85d21ac082887a249df3d9bfc64f50a9d6 100644
--- a/drivers/net/davinci_emac.c
+++ b/drivers/net/davinci_emac.c
@@ -243,11 +243,10 @@ int davinci_eth_phy_read(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t *data)
 
 	if (tmp & MDIO_USERACCESS0_ACK) {
 		*data = tmp & 0xffff;
-		return(1);
+		return 0;
 	}
 
-	*data = -1;
-	return(0);
+	return -EIO;
 }
 
 /* Write to a PHY register via MDIO inteface. Blocks until operation is complete. */
@@ -268,7 +267,7 @@ int davinci_eth_phy_write(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t data)
 	while (readl(&adap_mdio->USERACCESS0) & MDIO_USERACCESS0_GO)
 		;
 
-	return(1);
+	return 0;
 }
 
 /* PHY functions for a generic PHY */
@@ -390,14 +389,20 @@ static int gen_auto_negotiate(int phy_addr)
 
 
 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
-static int davinci_mii_phy_read(const char *devname, unsigned char addr, unsigned char reg, unsigned short *value)
+static int davinci_mii_phy_read(struct mii_dev *bus, int addr, int devad,
+				int reg)
 {
-	return(davinci_eth_phy_read(addr, reg, value) ? 0 : 1);
+	unsigned short value = 0;
+	int retval = davinci_eth_phy_read(addr, reg, &value);
+	if (retval < 0)
+		return retval;
+	return value;
 }
 
-static int davinci_mii_phy_write(const char *devname, unsigned char addr, unsigned char reg, unsigned short value)
+static int davinci_mii_phy_write(struct mii_dev *bus, int addr, int devad,
+				 int reg, u16 value)
 {
-	return(davinci_eth_phy_write(addr, reg, value) ? 0 : 1);
+	return davinci_eth_phy_write(addr, reg, value);
 }
 #endif
 
@@ -883,8 +888,17 @@ int davinci_emac_initialize(void)
 
 		debug("Ethernet PHY: %s\n", phy[i].name);
 
-		miiphy_register(phy[i].name, davinci_mii_phy_read,
-						davinci_mii_phy_write);
+		int retval;
+		struct mii_dev *mdiodev = mdio_alloc();
+		if (!mdiodev)
+			return -ENOMEM;
+		strncpy(mdiodev->name, phy[i].name, MDIO_NAME_LEN);
+		mdiodev->read = davinci_mii_phy_read;
+		mdiodev->write = davinci_mii_phy_write;
+
+		retval = mdio_register(mdiodev);
+		if (retval < 0)
+			return retval;
 	}
 
 #if defined(CONFIG_DRIVER_TI_EMAC_USE_RMII) && \
diff --git a/drivers/net/e1000.c b/drivers/net/e1000.c
index 196989b3864f9b709f571e83e4959fef25e31eb0..3332ad95d467696edc201be8bf860a4b13891afb 100644
--- a/drivers/net/e1000.c
+++ b/drivers/net/e1000.c
@@ -5513,7 +5513,8 @@ static int do_e1000(cmd_tbl_t *cmdtp, int flag,
 	struct udevice *dev;
 	char name[30];
 	int ret;
-#else
+#endif
+#if !defined(CONFIG_DM_ETH) || defined(CONFIG_E1000_SPI)
 	struct e1000_hw *hw;
 #endif
 	int cardnum;
@@ -5549,6 +5550,9 @@ static int do_e1000(cmd_tbl_t *cmdtp, int flag,
 	}
 
 #ifdef CONFIG_E1000_SPI
+#ifdef CONFIG_DM_ETH
+	hw = dev_get_priv(dev);
+#endif
 	/* Handle the "SPI" subcommand */
 	if (!strcmp(argv[2], "spi"))
 		return do_e1000_spi(cmdtp, hw, argc - 3, argv + 3);
diff --git a/drivers/net/e1000_spi.c b/drivers/net/e1000_spi.c
index 576ddb8b24290f6a20220553b5cb2d60a4e97b26..cb5f93d652348f7c19c7860a57943f9cad8aac93 100644
--- a/drivers/net/e1000_spi.c
+++ b/drivers/net/e1000_spi.c
@@ -94,17 +94,17 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
 
 	/* Make sure it has an SPI chip */
 	if (hw->eeprom.type != e1000_eeprom_spi) {
-		E1000_ERR(hw->nic, "No attached SPI EEPROM found!\n");
+		E1000_ERR(hw, "No attached SPI EEPROM found!\n");
 		return NULL;
 	}
 
 	/* Argument sanity checks */
 	if (cs != 0) {
-		E1000_ERR(hw->nic, "No such SPI chip: %u\n", cs);
+		E1000_ERR(hw, "No such SPI chip: %u\n", cs);
 		return NULL;
 	}
 	if (mode != SPI_MODE_0) {
-		E1000_ERR(hw->nic, "Only SPI MODE-0 is supported!\n");
+		E1000_ERR(hw, "Only SPI MODE-0 is supported!\n");
 		return NULL;
 	}
 
@@ -124,7 +124,7 @@ int spi_claim_bus(struct spi_slave *spi)
 	struct e1000_hw *hw = e1000_hw_from_spi(spi);
 
 	if (e1000_acquire_eeprom(hw)) {
-		E1000_ERR(hw->nic, "EEPROM SPI cannot be acquired!\n");
+		E1000_ERR(hw, "EEPROM SPI cannot be acquired!\n");
 		return -1;
 	}
 
@@ -342,41 +342,41 @@ static int do_e1000_spi_show(cmd_tbl_t *cmdtp, struct e1000_hw *hw,
 
 	/* Extra sanity checks */
 	if (!length) {
-		E1000_ERR(hw->nic, "Requested zero-sized dump!\n");
+		E1000_ERR(hw, "Requested zero-sized dump!\n");
 		return 1;
 	}
 	if ((0x10000 < length) || (0x10000 - length < offset)) {
-		E1000_ERR(hw->nic, "Can't dump past 0xFFFF!\n");
+		E1000_ERR(hw, "Can't dump past 0xFFFF!\n");
 		return 1;
 	}
 
 	/* Allocate a buffer to hold stuff */
 	buffer = malloc(length);
 	if (!buffer) {
-		E1000_ERR(hw->nic, "Out of Memory!\n");
+		E1000_ERR(hw, "Out of Memory!\n");
 		return 1;
 	}
 
 	/* Acquire the EEPROM and perform the dump */
 	if (e1000_acquire_eeprom(hw)) {
-		E1000_ERR(hw->nic, "EEPROM SPI cannot be acquired!\n");
+		E1000_ERR(hw, "EEPROM SPI cannot be acquired!\n");
 		free(buffer);
 		return 1;
 	}
 	err = e1000_spi_eeprom_dump(hw, buffer, offset, length, true);
 	e1000_release_eeprom(hw);
 	if (err) {
-		E1000_ERR(hw->nic, "Interrupted!\n");
+		E1000_ERR(hw, "Interrupted!\n");
 		free(buffer);
 		return 1;
 	}
 
 	/* Now hexdump the result */
 	printf("%s: ===== Intel e1000 EEPROM (0x%04hX - 0x%04hX) =====",
-			hw->nic->name, offset, offset + length - 1);
+			hw->name, offset, offset + length - 1);
 	for (i = 0; i < length; i++) {
 		if ((i & 0xF) == 0)
-			printf("\n%s: %04hX: ", hw->nic->name, offset + i);
+			printf("\n%s: %04hX: ", hw->name, offset + i);
 		else if ((i & 0xF) == 0x8)
 			printf(" ");
 		printf(" %02hx", buffer[i]);
@@ -407,29 +407,29 @@ static int do_e1000_spi_dump(cmd_tbl_t *cmdtp, struct e1000_hw *hw,
 
 	/* Extra sanity checks */
 	if (!length) {
-		E1000_ERR(hw->nic, "Requested zero-sized dump!\n");
+		E1000_ERR(hw, "Requested zero-sized dump!\n");
 		return 1;
 	}
 	if ((0x10000 < length) || (0x10000 - length < offset)) {
-		E1000_ERR(hw->nic, "Can't dump past 0xFFFF!\n");
+		E1000_ERR(hw, "Can't dump past 0xFFFF!\n");
 		return 1;
 	}
 
 	/* Acquire the EEPROM */
 	if (e1000_acquire_eeprom(hw)) {
-		E1000_ERR(hw->nic, "EEPROM SPI cannot be acquired!\n");
+		E1000_ERR(hw, "EEPROM SPI cannot be acquired!\n");
 		return 1;
 	}
 
 	/* Perform the programming operation */
 	if (e1000_spi_eeprom_dump(hw, dest, offset, length, true) < 0) {
-		E1000_ERR(hw->nic, "Interrupted!\n");
+		E1000_ERR(hw, "Interrupted!\n");
 		e1000_release_eeprom(hw);
 		return 1;
 	}
 
 	e1000_release_eeprom(hw);
-	printf("%s: ===== EEPROM DUMP COMPLETE =====\n", hw->nic->name);
+	printf("%s: ===== EEPROM DUMP COMPLETE =====\n", hw->name);
 	return 0;
 }
 
@@ -452,19 +452,19 @@ static int do_e1000_spi_program(cmd_tbl_t *cmdtp, struct e1000_hw *hw,
 
 	/* Acquire the EEPROM */
 	if (e1000_acquire_eeprom(hw)) {
-		E1000_ERR(hw->nic, "EEPROM SPI cannot be acquired!\n");
+		E1000_ERR(hw, "EEPROM SPI cannot be acquired!\n");
 		return 1;
 	}
 
 	/* Perform the programming operation */
 	if (e1000_spi_eeprom_program(hw, source, offset, length, true) < 0) {
-		E1000_ERR(hw->nic, "Interrupted!\n");
+		E1000_ERR(hw, "Interrupted!\n");
 		e1000_release_eeprom(hw);
 		return 1;
 	}
 
 	e1000_release_eeprom(hw);
-	printf("%s: ===== EEPROM PROGRAMMED =====\n", hw->nic->name);
+	printf("%s: ===== EEPROM PROGRAMMED =====\n", hw->name);
 	return 0;
 }
 
@@ -488,19 +488,19 @@ static int do_e1000_spi_checksum(cmd_tbl_t *cmdtp, struct e1000_hw *hw,
 	length = sizeof(uint16_t) * (EEPROM_CHECKSUM_REG + 1);
 	buffer = malloc(length);
 	if (!buffer) {
-		E1000_ERR(hw->nic, "Unable to allocate EEPROM buffer!\n");
+		E1000_ERR(hw, "Unable to allocate EEPROM buffer!\n");
 		return 1;
 	}
 
 	/* Acquire the EEPROM */
 	if (e1000_acquire_eeprom(hw)) {
-		E1000_ERR(hw->nic, "EEPROM SPI cannot be acquired!\n");
+		E1000_ERR(hw, "EEPROM SPI cannot be acquired!\n");
 		return 1;
 	}
 
 	/* Read the EEPROM */
 	if (e1000_spi_eeprom_dump(hw, buffer, 0, length, true) < 0) {
-		E1000_ERR(hw->nic, "Interrupted!\n");
+		E1000_ERR(hw, "Interrupted!\n");
 		e1000_release_eeprom(hw);
 		return 1;
 	}
@@ -514,15 +514,15 @@ static int do_e1000_spi_checksum(cmd_tbl_t *cmdtp, struct e1000_hw *hw,
 	/* Verify it! */
 	if (checksum_reg == checksum) {
 		printf("%s: INFO: EEPROM checksum is correct! (0x%04hx)\n",
-				hw->nic->name, checksum);
+				hw->name, checksum);
 		e1000_release_eeprom(hw);
 		return 0;
 	}
 
 	/* Hrm, verification failed, print an error */
-	E1000_ERR(hw->nic, "EEPROM checksum is incorrect!\n");
-	E1000_ERR(hw->nic, "  ...register was 0x%04hx, calculated 0x%04hx\n",
-			checksum_reg, checksum);
+	E1000_ERR(hw, "EEPROM checksum is incorrect!\n");
+	E1000_ERR(hw, "  ...register was 0x%04hx, calculated 0x%04hx\n",
+		  checksum_reg, checksum);
 
 	/* If they didn't ask us to update it, just return an error */
 	if (!upd) {
@@ -531,11 +531,11 @@ static int do_e1000_spi_checksum(cmd_tbl_t *cmdtp, struct e1000_hw *hw,
 	}
 
 	/* Ok, correct it! */
-	printf("%s: Reprogramming the EEPROM checksum...\n", hw->nic->name);
+	printf("%s: Reprogramming the EEPROM checksum...\n", hw->name);
 	buffer[i] = cpu_to_le16(checksum);
 	if (e1000_spi_eeprom_program(hw, &buffer[i], i * sizeof(uint16_t),
 			sizeof(uint16_t), true)) {
-		E1000_ERR(hw->nic, "Interrupted!\n");
+		E1000_ERR(hw, "Interrupted!\n");
 		e1000_release_eeprom(hw);
 		return 1;
 	}
@@ -554,7 +554,8 @@ int do_e1000_spi(cmd_tbl_t *cmdtp, struct e1000_hw *hw,
 
 	/* Make sure it has an SPI chip */
 	if (hw->eeprom.type != e1000_eeprom_spi) {
-		E1000_ERR(hw->nic, "No attached SPI EEPROM found!\n");
+		E1000_ERR(hw, "No attached SPI EEPROM found (%d)!\n",
+			  hw->eeprom.type);
 		return 1;
 	}
 
diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c
index d4a6386810b6509bcfbcc5ef90556210129287ad..0f350cba53e6e8157770ea1f4b69f1f706efc472 100644
--- a/drivers/net/eepro100.c
+++ b/drivers/net/eepro100.c
@@ -334,34 +334,35 @@ static struct eth_device* verify_phyaddr (const char *devname,
 	return dev;
 }
 
-static int eepro100_miiphy_read(const char *devname, unsigned char addr,
-		unsigned char reg, unsigned short *value)
+static int eepro100_miiphy_read(struct mii_dev *bus, int addr, int devad,
+				int reg)
 {
+	unsigned short value = 0;
 	struct eth_device *dev;
 
-	dev = verify_phyaddr(devname, addr);
+	dev = verify_phyaddr(bus->name, addr);
 	if (dev == NULL)
 		return -1;
 
-	if (get_phyreg(dev, addr, reg, value) != 0) {
-		printf("%s: mii read timeout!\n", devname);
+	if (get_phyreg(dev, addr, reg, &value) != 0) {
+		printf("%s: mii read timeout!\n", bus->name);
 		return -1;
 	}
 
-	return 0;
+	return value;
 }
 
-static int eepro100_miiphy_write(const char *devname, unsigned char addr,
-		unsigned char reg, unsigned short value)
+static int eepro100_miiphy_write(struct mii_dev *bus, int addr, int devad,
+				 int reg, u16 value)
 {
 	struct eth_device *dev;
 
-	dev = verify_phyaddr(devname, addr);
+	dev = verify_phyaddr(bus->name, addr);
 	if (dev == NULL)
 		return -1;
 
 	if (set_phyreg(dev, addr, reg, value) != 0) {
-		printf("%s: mii write timeout!\n", devname);
+		printf("%s: mii write timeout!\n", bus->name);
 		return -1;
 	}
 
@@ -451,8 +452,17 @@ int eepro100_initialize (bd_t * bis)
 
 #if defined (CONFIG_MII) || defined(CONFIG_CMD_MII)
 		/* register mii command access routines */
-		miiphy_register(dev->name,
-				eepro100_miiphy_read, eepro100_miiphy_write);
+		int retval;
+		struct mii_dev *mdiodev = mdio_alloc();
+		if (!mdiodev)
+			return -ENOMEM;
+		strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+		mdiodev->read = eepro100_miiphy_read;
+		mdiodev->write = eepro100_miiphy_write;
+
+		retval = mdio_register(mdiodev);
+		if (retval < 0)
+			return retval;
 #endif
 
 		card_number++;
diff --git a/drivers/net/enc28j60.c b/drivers/net/enc28j60.c
index 611eabb5460f180818f2dc0de297a1f0d1671994..2fe323a85a5207379f597c98888fbe44987b2ba3 100644
--- a/drivers/net/enc28j60.c
+++ b/drivers/net/enc28j60.c
@@ -742,9 +742,10 @@ static int enc_initcheck(enc_dev_t *enc, const enum enc_initstate requiredstate)
  *
  * This function is registered with miiphy_register().
  */
-int enc_miiphy_read(const char *devname, u8 phy_adr, u8 reg, u16 *value)
+int enc_miiphy_read(struct mii_dev *bus, int phy_adr, int devad, int reg)
 {
-	struct eth_device *dev = eth_get_dev_by_name(devname);
+	u16 value = 0;
+	struct eth_device *dev = eth_get_dev_by_name(bus->name);
 	enc_dev_t *enc;
 
 	if (!dev || phy_adr != 0)
@@ -757,9 +758,9 @@ int enc_miiphy_read(const char *devname, u8 phy_adr, u8 reg, u16 *value)
 		enc_release_bus(enc);
 		return -1;
 	}
-	*value = enc_phy_read(enc, reg);
+	value = enc_phy_read(enc, reg);
 	enc_release_bus(enc);
-	return 0;
+	return value;
 }
 
 /*
@@ -767,9 +768,10 @@ int enc_miiphy_read(const char *devname, u8 phy_adr, u8 reg, u16 *value)
  *
  * This function is registered with miiphy_register().
  */
-int enc_miiphy_write(const char *devname, u8 phy_adr, u8 reg, u16 value)
+int enc_miiphy_write(struct mii_dev *bus, int phy_adr, int devad, int reg,
+		     u16 value)
 {
-	struct eth_device *dev = eth_get_dev_by_name(devname);
+	struct eth_device *dev = eth_get_dev_by_name(bus->name);
 	enc_dev_t *enc;
 
 	if (!dev || phy_adr != 0)
@@ -958,7 +960,17 @@ int enc28j60_initialize(unsigned int bus, unsigned int cs,
 	sprintf(dev->name, "enc%i.%i", bus, cs);
 	eth_register(dev);
 #if defined(CONFIG_CMD_MII)
-	miiphy_register(dev->name, enc_miiphy_read, enc_miiphy_write);
+	int retval;
+	struct mii_dev *mdiodev = mdio_alloc();
+	if (!mdiodev)
+		return -ENOMEM;
+	strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+	mdiodev->read = enc_miiphy_read;
+	mdiodev->write = enc_miiphy_write;
+
+	retval = mdio_register(mdiodev);
+	if (retval < 0)
+		return retval;
 #endif
 	return 0;
 }
diff --git a/drivers/net/ep93xx_eth.c b/drivers/net/ep93xx_eth.c
index a3721c5513c1b87a183077201d039b4903b5a27b..a94191b9e6715e3a685f6c172f3f45d85544b919 100644
--- a/drivers/net/ep93xx_eth.c
+++ b/drivers/net/ep93xx_eth.c
@@ -30,10 +30,10 @@
 #define GET_REGS(eth_dev)	(GET_PRIV(eth_dev)->regs)
 
 /* ep93xx_miiphy ops forward declarations */
-static int ep93xx_miiphy_read(const char * const dev, unsigned char const addr,
-			unsigned char const reg, unsigned short * const value);
-static int ep93xx_miiphy_write(const char * const dev, unsigned char const addr,
-			unsigned char const reg, unsigned short const value);
+static int ep93xx_miiphy_read(struct mii_dev *bus, int addr, int devad,
+			      int reg);
+static int ep93xx_miiphy_write(struct mii_dev *bus, int addr, int devad,
+			       int reg, u16 value);
 
 #if defined(EP93XX_MAC_DEBUG)
 /**
@@ -421,7 +421,17 @@ eth_send_out:
 #if defined(CONFIG_MII)
 int ep93xx_miiphy_initialize(bd_t * const bd)
 {
-	miiphy_register("ep93xx_eth0", ep93xx_miiphy_read, ep93xx_miiphy_write);
+	int retval;
+	struct mii_dev *mdiodev = mdio_alloc();
+	if (!mdiodev)
+		return -ENOMEM;
+	strncpy(mdiodev->name, "ep93xx_eth0", MDIO_NAME_LEN);
+	mdiodev->read = ep93xx_miiphy_read;
+	mdiodev->write = ep93xx_miiphy_write;
+
+	retval = mdio_register(mdiodev);
+	if (retval < 0)
+		return retval;
 	return 0;
 }
 #endif
@@ -542,9 +552,10 @@ eth_init_done:
 /**
  * Read a 16-bit value from an MII register.
  */
-static int ep93xx_miiphy_read(const char * const dev, unsigned char const addr,
-			unsigned char const reg, unsigned short * const value)
+static int ep93xx_miiphy_read(struct mii_dev *bus, int addr, int devad,
+			      int reg)
 {
+	unsigned short value = 0;
 	struct mac_regs *mac = (struct mac_regs *)MAC_BASE;
 	int ret = -1;
 	uint32_t self_ctl;
@@ -552,10 +563,9 @@ static int ep93xx_miiphy_read(const char * const dev, unsigned char const addr,
 	debug("+ep93xx_miiphy_read");
 
 	/* Parameter checks */
-	BUG_ON(dev == NULL);
+	BUG_ON(bus->name == NULL);
 	BUG_ON(addr > MII_ADDRESS_MAX);
 	BUG_ON(reg > MII_REGISTER_MAX);
-	BUG_ON(value == NULL);
 
 	/*
 	 * Save the current SelfCTL register value.  Set MAC to suppress
@@ -579,7 +589,7 @@ static int ep93xx_miiphy_read(const char * const dev, unsigned char const addr,
 	while (readl(&mac->miists) & MIISTS_BUSY)
 		; /* noop */
 
-	*value = (unsigned short)readl(&mac->miidata);
+	value = (unsigned short)readl(&mac->miidata);
 
 	/* Restore the saved SelfCTL value and return. */
 	writel(self_ctl, &mac->selfctl);
@@ -588,14 +598,16 @@ static int ep93xx_miiphy_read(const char * const dev, unsigned char const addr,
 	/* Fall through */
 
 	debug("-ep93xx_miiphy_read");
-	return ret;
+	if (ret < 0)
+		return ret;
+	return value;
 }
 
 /**
  * Write a 16-bit value to an MII register.
  */
-static int ep93xx_miiphy_write(const char * const dev, unsigned char const addr,
-			unsigned char const reg, unsigned short const value)
+static int ep93xx_miiphy_write(struct mii_dev *bus, int addr, int devad,
+			       int reg, u16 value)
 {
 	struct mac_regs *mac = (struct mac_regs *)MAC_BASE;
 	int ret = -1;
@@ -604,7 +616,7 @@ static int ep93xx_miiphy_write(const char * const dev, unsigned char const addr,
 	debug("+ep93xx_miiphy_write");
 
 	/* Parameter checks */
-	BUG_ON(dev == NULL);
+	BUG_ON(bus->name == NULL);
 	BUG_ON(addr > MII_ADDRESS_MAX);
 	BUG_ON(reg > MII_REGISTER_MAX);
 
diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c
index edb3c808fa18f8f3d6d02cbb2843ead23048c1c3..ad8c462a6099b62a4f6b2485564919b73499ea9c 100644
--- a/drivers/net/ethoc.c
+++ b/drivers/net/ethoc.c
@@ -5,19 +5,20 @@
  * Copyright (C) 2008-2009 Avionic Design GmbH
  *   Thierry Reding <thierry.reding@avionic-design.de>
  * Copyright (C) 2010 Thomas Chou <thomas@wytron.com.tw>
+ * Copyright (C) 2016 Cadence Design Systems Inc.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
+ * SPDX-License-Identifier:	GPL-2.0
  */
 
 #include <common.h>
-#include <command.h>
+#include <dm/device.h>
+#include <dm/platform_data/net_ethoc.h>
+#include <linux/io.h>
 #include <malloc.h>
 #include <net.h>
 #include <miiphy.h>
-#include <asm/io.h>
 #include <asm/cache.h>
+#include <wait_bit.h>
 
 /* register offsets */
 #define	MODER		0x00
@@ -162,6 +163,7 @@
 #define	ETHOC_BD_BASE		0x400
 #define	ETHOC_TIMEOUT		(HZ / 2)
 #define	ETHOC_MII_TIMEOUT	(1 + (HZ / 5))
+#define	ETHOC_IOSIZE		0x54
 
 /**
  * struct ethoc - driver-private device structure
@@ -177,6 +179,14 @@ struct ethoc {
 	u32 dty_tx;
 	u32 num_rx;
 	u32 cur_rx;
+	void __iomem *iobase;
+	void __iomem *packet;
+	phys_addr_t packet_phys;
+
+#ifdef CONFIG_PHYLIB
+	struct mii_dev *bus;
+	struct phy_device *phydev;
+#endif
 };
 
 /**
@@ -189,65 +199,68 @@ struct ethoc_bd {
 	u32 addr;
 };
 
-static inline u32 ethoc_read(struct eth_device *dev, size_t offset)
+static inline u32 *ethoc_reg(struct ethoc *priv, size_t offset)
 {
-	return readl(dev->iobase + offset);
+	return priv->iobase + offset;
 }
 
-static inline void ethoc_write(struct eth_device *dev, size_t offset, u32 data)
+static inline u32 ethoc_read(struct ethoc *priv, size_t offset)
 {
-	writel(data, dev->iobase + offset);
+	return readl(ethoc_reg(priv, offset));
 }
 
-static inline void ethoc_read_bd(struct eth_device *dev, int index,
+static inline void ethoc_write(struct ethoc *priv, size_t offset, u32 data)
+{
+	writel(data, ethoc_reg(priv, offset));
+}
+
+static inline void ethoc_read_bd(struct ethoc *priv, int index,
 				 struct ethoc_bd *bd)
 {
 	size_t offset = ETHOC_BD_BASE + (index * sizeof(struct ethoc_bd));
-	bd->stat = ethoc_read(dev, offset + 0);
-	bd->addr = ethoc_read(dev, offset + 4);
+	bd->stat = ethoc_read(priv, offset + 0);
+	bd->addr = ethoc_read(priv, offset + 4);
 }
 
-static inline void ethoc_write_bd(struct eth_device *dev, int index,
+static inline void ethoc_write_bd(struct ethoc *priv, int index,
 				  const struct ethoc_bd *bd)
 {
 	size_t offset = ETHOC_BD_BASE + (index * sizeof(struct ethoc_bd));
-	ethoc_write(dev, offset + 0, bd->stat);
-	ethoc_write(dev, offset + 4, bd->addr);
+	ethoc_write(priv, offset + 0, bd->stat);
+	ethoc_write(priv, offset + 4, bd->addr);
 }
 
-static int ethoc_set_mac_address(struct eth_device *dev)
+static int ethoc_write_hwaddr_common(struct ethoc *priv, u8 *mac)
 {
-	u8 *mac = dev->enetaddr;
-
-	ethoc_write(dev, MAC_ADDR0, (mac[2] << 24) | (mac[3] << 16) |
+	ethoc_write(priv, MAC_ADDR0, (mac[2] << 24) | (mac[3] << 16) |
 		    (mac[4] << 8) | (mac[5] << 0));
-	ethoc_write(dev, MAC_ADDR1, (mac[0] << 8) | (mac[1] << 0));
+	ethoc_write(priv, MAC_ADDR1, (mac[0] << 8) | (mac[1] << 0));
 	return 0;
 }
 
-static inline void ethoc_ack_irq(struct eth_device *dev, u32 mask)
+static inline void ethoc_ack_irq(struct ethoc *priv, u32 mask)
 {
-	ethoc_write(dev, INT_SOURCE, mask);
+	ethoc_write(priv, INT_SOURCE, mask);
 }
 
-static inline void ethoc_enable_rx_and_tx(struct eth_device *dev)
+static inline void ethoc_enable_rx_and_tx(struct ethoc *priv)
 {
-	u32 mode = ethoc_read(dev, MODER);
+	u32 mode = ethoc_read(priv, MODER);
 	mode |= MODER_RXEN | MODER_TXEN;
-	ethoc_write(dev, MODER, mode);
+	ethoc_write(priv, MODER, mode);
 }
 
-static inline void ethoc_disable_rx_and_tx(struct eth_device *dev)
+static inline void ethoc_disable_rx_and_tx(struct ethoc *priv)
 {
-	u32 mode = ethoc_read(dev, MODER);
+	u32 mode = ethoc_read(priv, MODER);
 	mode &= ~(MODER_RXEN | MODER_TXEN);
-	ethoc_write(dev, MODER, mode);
+	ethoc_write(priv, MODER, mode);
 }
 
-static int ethoc_init_ring(struct eth_device *dev)
+static int ethoc_init_ring(struct ethoc *priv)
 {
-	struct ethoc *priv = (struct ethoc *)dev->priv;
 	struct ethoc_bd bd;
+	phys_addr_t addr = priv->packet_phys;
 	int i;
 
 	priv->cur_tx = 0;
@@ -256,66 +269,92 @@ static int ethoc_init_ring(struct eth_device *dev)
 
 	/* setup transmission buffers */
 	bd.stat = TX_BD_IRQ | TX_BD_CRC;
+	bd.addr = 0;
 
 	for (i = 0; i < priv->num_tx; i++) {
+		if (addr) {
+			bd.addr = addr;
+			addr += PKTSIZE_ALIGN;
+		}
 		if (i == priv->num_tx - 1)
 			bd.stat |= TX_BD_WRAP;
 
-		ethoc_write_bd(dev, i, &bd);
+		ethoc_write_bd(priv, i, &bd);
 	}
 
 	bd.stat = RX_BD_EMPTY | RX_BD_IRQ;
 
 	for (i = 0; i < priv->num_rx; i++) {
-		bd.addr = (u32)net_rx_packets[i];
+		if (addr) {
+			bd.addr = addr;
+			addr += PKTSIZE_ALIGN;
+		} else {
+			bd.addr = virt_to_phys(net_rx_packets[i]);
+		}
 		if (i == priv->num_rx - 1)
 			bd.stat |= RX_BD_WRAP;
 
-		flush_dcache_range(bd.addr, bd.addr + PKTSIZE_ALIGN);
-		ethoc_write_bd(dev, priv->num_tx + i, &bd);
+		flush_dcache_range((ulong)net_rx_packets[i],
+				   (ulong)net_rx_packets[i] + PKTSIZE_ALIGN);
+		ethoc_write_bd(priv, priv->num_tx + i, &bd);
 	}
 
 	return 0;
 }
 
-static int ethoc_reset(struct eth_device *dev)
+static int ethoc_reset(struct ethoc *priv)
 {
 	u32 mode;
 
 	/* TODO: reset controller? */
 
-	ethoc_disable_rx_and_tx(dev);
+	ethoc_disable_rx_and_tx(priv);
 
 	/* TODO: setup registers */
 
 	/* enable FCS generation and automatic padding */
-	mode = ethoc_read(dev, MODER);
+	mode = ethoc_read(priv, MODER);
 	mode |= MODER_CRC | MODER_PAD;
-	ethoc_write(dev, MODER, mode);
+	ethoc_write(priv, MODER, mode);
 
 	/* set full-duplex mode */
-	mode = ethoc_read(dev, MODER);
+	mode = ethoc_read(priv, MODER);
 	mode |= MODER_FULLD;
-	ethoc_write(dev, MODER, mode);
-	ethoc_write(dev, IPGT, 0x15);
+	ethoc_write(priv, MODER, mode);
+	ethoc_write(priv, IPGT, 0x15);
 
-	ethoc_ack_irq(dev, INT_MASK_ALL);
-	ethoc_enable_rx_and_tx(dev);
+	ethoc_ack_irq(priv, INT_MASK_ALL);
+	ethoc_enable_rx_and_tx(priv);
 	return 0;
 }
 
-static int ethoc_init(struct eth_device *dev, bd_t * bd)
+static int ethoc_init_common(struct ethoc *priv)
 {
-	struct ethoc *priv = (struct ethoc *)dev->priv;
-	printf("ethoc\n");
+	int ret = 0;
 
 	priv->num_tx = 1;
 	priv->num_rx = PKTBUFSRX;
-	ethoc_write(dev, TX_BD_NUM, priv->num_tx);
-	ethoc_init_ring(dev);
-	ethoc_reset(dev);
+	ethoc_write(priv, TX_BD_NUM, priv->num_tx);
+	ethoc_init_ring(priv);
+	ethoc_reset(priv);
+
+#ifdef CONFIG_PHYLIB
+	ret = phy_startup(priv->phydev);
+	if (ret) {
+		printf("Could not initialize PHY %s\n",
+		       priv->phydev->dev->name);
+		return ret;
+	}
+#endif
+	return ret;
+}
 
-	return 0;
+static void ethoc_stop_common(struct ethoc *priv)
+{
+	ethoc_disable_rx_and_tx(priv);
+#ifdef CONFIG_PHYLIB
+	phy_shutdown(priv->phydev);
+#endif
 }
 
 static int ethoc_update_rx_stats(struct ethoc_bd *bd)
@@ -353,37 +392,46 @@ static int ethoc_update_rx_stats(struct ethoc_bd *bd)
 	return ret;
 }
 
-static int ethoc_rx(struct eth_device *dev, int limit)
+static int ethoc_rx_common(struct ethoc *priv, uchar **packetp)
 {
-	struct ethoc *priv = (struct ethoc *)dev->priv;
-	int count;
-
-	for (count = 0; count < limit; ++count) {
-		u32 entry;
-		struct ethoc_bd bd;
-
-		entry = priv->num_tx + (priv->cur_rx % priv->num_rx);
-		ethoc_read_bd(dev, entry, &bd);
-		if (bd.stat & RX_BD_EMPTY)
-			break;
+	struct ethoc_bd bd;
+	u32 i = priv->cur_rx % priv->num_rx;
+	u32 entry = priv->num_tx + i;
+
+	ethoc_read_bd(priv, entry, &bd);
+	if (bd.stat & RX_BD_EMPTY)
+		return -EAGAIN;
+
+	debug("%s(): RX buffer %d, %x received\n",
+	      __func__, priv->cur_rx, bd.stat);
+	if (ethoc_update_rx_stats(&bd) == 0) {
+		int size = bd.stat >> 16;
+
+		size -= 4;	/* strip the CRC */
+		if (priv->packet)
+			*packetp = priv->packet + entry * PKTSIZE_ALIGN;
+		else
+			*packetp = net_rx_packets[i];
+		return size;
+	} else {
+		return 0;
+	}
+}
 
-		debug("%s(): RX buffer %d, %x received\n",
-		      __func__, priv->cur_rx, bd.stat);
-		if (ethoc_update_rx_stats(&bd) == 0) {
-			int size = bd.stat >> 16;
-			size -= 4;	/* strip the CRC */
-			net_process_received_packet((void *)bd.addr, size);
-		}
+static int ethoc_is_new_packet_received(struct ethoc *priv)
+{
+	u32 pending;
 
-		/* clear the buffer descriptor so it can be reused */
-		flush_dcache_range(bd.addr, bd.addr + PKTSIZE_ALIGN);
-		bd.stat &= ~RX_BD_STATS;
-		bd.stat |= RX_BD_EMPTY;
-		ethoc_write_bd(dev, entry, &bd);
-		priv->cur_rx++;
+	pending = ethoc_read(priv, INT_SOURCE);
+	ethoc_ack_irq(priv, pending);
+	if (pending & INT_MASK_BUSY)
+		debug("%s(): packet dropped\n", __func__);
+	if (pending & INT_MASK_RX) {
+		debug("%s(): rx irq\n", __func__);
+		return 1;
 	}
 
-	return count;
+	return 0;
 }
 
 static int ethoc_update_tx_stats(struct ethoc_bd *bd)
@@ -403,52 +451,57 @@ static int ethoc_update_tx_stats(struct ethoc_bd *bd)
 	return 0;
 }
 
-static void ethoc_tx(struct eth_device *dev)
+static void ethoc_tx(struct ethoc *priv)
 {
-	struct ethoc *priv = (struct ethoc *)dev->priv;
 	u32 entry = priv->dty_tx % priv->num_tx;
 	struct ethoc_bd bd;
 
-	ethoc_read_bd(dev, entry, &bd);
+	ethoc_read_bd(priv, entry, &bd);
 	if ((bd.stat & TX_BD_READY) == 0)
 		(void)ethoc_update_tx_stats(&bd);
 }
 
-static int ethoc_send(struct eth_device *dev, void *packet, int length)
+static int ethoc_send_common(struct ethoc *priv, void *packet, int length)
 {
-	struct ethoc *priv = (struct ethoc *)dev->priv;
 	struct ethoc_bd bd;
 	u32 entry;
 	u32 pending;
 	int tmo;
 
 	entry = priv->cur_tx % priv->num_tx;
-	ethoc_read_bd(dev, entry, &bd);
+	ethoc_read_bd(priv, entry, &bd);
 	if (unlikely(length < ETHOC_ZLEN))
 		bd.stat |= TX_BD_PAD;
 	else
 		bd.stat &= ~TX_BD_PAD;
-	bd.addr = (u32)packet;
 
-	flush_dcache_range(bd.addr, bd.addr + length);
+	if (priv->packet) {
+		void *p = priv->packet + entry * PKTSIZE_ALIGN;
+
+		memcpy(p, packet, length);
+		packet = p;
+	} else {
+		bd.addr = virt_to_phys(packet);
+	}
+	flush_dcache_range((ulong)packet, (ulong)packet + length);
 	bd.stat &= ~(TX_BD_STATS | TX_BD_LEN_MASK);
 	bd.stat |= TX_BD_LEN(length);
-	ethoc_write_bd(dev, entry, &bd);
+	ethoc_write_bd(priv, entry, &bd);
 
 	/* start transmit */
 	bd.stat |= TX_BD_READY;
-	ethoc_write_bd(dev, entry, &bd);
+	ethoc_write_bd(priv, entry, &bd);
 
 	/* wait for transfer to succeed */
 	tmo = get_timer(0) + 5 * CONFIG_SYS_HZ;
 	while (1) {
-		pending = ethoc_read(dev, INT_SOURCE);
-		ethoc_ack_irq(dev, pending & ~INT_MASK_RX);
+		pending = ethoc_read(priv, INT_SOURCE);
+		ethoc_ack_irq(priv, pending & ~INT_MASK_RX);
 		if (pending & INT_MASK_BUSY)
 			debug("%s(): packet dropped\n", __func__);
 
 		if (pending & INT_MASK_TX) {
-			ethoc_tx(dev);
+			ethoc_tx(priv);
 			break;
 		}
 		if (get_timer(0) >= tmo) {
@@ -461,24 +514,290 @@ static int ethoc_send(struct eth_device *dev, void *packet, int length)
 	return 0;
 }
 
+static int ethoc_free_pkt_common(struct ethoc *priv)
+{
+	struct ethoc_bd bd;
+	u32 i = priv->cur_rx % priv->num_rx;
+	u32 entry = priv->num_tx + i;
+	void *src;
+
+	ethoc_read_bd(priv, entry, &bd);
+
+	if (priv->packet)
+		src = priv->packet + entry * PKTSIZE_ALIGN;
+	else
+		src = net_rx_packets[i];
+	/* clear the buffer descriptor so it can be reused */
+	flush_dcache_range((ulong)src,
+			   (ulong)src + PKTSIZE_ALIGN);
+	bd.stat &= ~RX_BD_STATS;
+	bd.stat |= RX_BD_EMPTY;
+	ethoc_write_bd(priv, entry, &bd);
+	priv->cur_rx++;
+
+	return 0;
+}
+
+#ifdef CONFIG_PHYLIB
+
+static int ethoc_mdio_read(struct mii_dev *bus, int addr, int devad, int reg)
+{
+	struct ethoc *priv = bus->priv;
+	int rc;
+
+	ethoc_write(priv, MIIADDRESS, MIIADDRESS_ADDR(addr, reg));
+	ethoc_write(priv, MIICOMMAND, MIICOMMAND_READ);
+
+	rc = wait_for_bit(__func__, ethoc_reg(priv, MIISTATUS),
+			  MIISTATUS_BUSY, false, CONFIG_SYS_HZ, false);
+
+	if (rc == 0) {
+		u32 data = ethoc_read(priv, MIIRX_DATA);
+
+		/* reset MII command register */
+		ethoc_write(priv, MIICOMMAND, 0);
+		return data;
+	}
+	return rc;
+}
+
+static int ethoc_mdio_write(struct mii_dev *bus, int addr, int devad, int reg,
+			    u16 val)
+{
+	struct ethoc *priv = bus->priv;
+	int rc;
+
+	ethoc_write(priv, MIIADDRESS, MIIADDRESS_ADDR(addr, reg));
+	ethoc_write(priv, MIITX_DATA, val);
+	ethoc_write(priv, MIICOMMAND, MIICOMMAND_WRITE);
+
+	rc = wait_for_bit(__func__, ethoc_reg(priv, MIISTATUS),
+			  MIISTATUS_BUSY, false, CONFIG_SYS_HZ, false);
+
+	if (rc == 0) {
+		/* reset MII command register */
+		ethoc_write(priv, MIICOMMAND, 0);
+	}
+	return rc;
+}
+
+static int ethoc_mdio_init(const char *name, struct ethoc *priv)
+{
+	struct mii_dev *bus = mdio_alloc();
+	int ret;
+
+	if (!bus) {
+		printf("Failed to allocate MDIO bus\n");
+		return -ENOMEM;
+	}
+
+	bus->read = ethoc_mdio_read;
+	bus->write = ethoc_mdio_write;
+	snprintf(bus->name, sizeof(bus->name), "%s", name);
+	bus->priv = priv;
+
+	ret = mdio_register(bus);
+	if (ret < 0)
+		return ret;
+
+	priv->bus = miiphy_get_dev_by_name(name);
+	return 0;
+}
+
+static int ethoc_phy_init(struct ethoc *priv, void *dev)
+{
+	struct phy_device *phydev;
+	int mask = 0xffffffff;
+
+#ifdef CONFIG_PHY_ADDR
+	mask = 1 << CONFIG_PHY_ADDR;
+#endif
+
+	phydev = phy_find_by_mask(priv->bus, mask, PHY_INTERFACE_MODE_MII);
+	if (!phydev)
+		return -ENODEV;
+
+	phy_connect_dev(phydev, dev);
+
+	phydev->supported &= PHY_BASIC_FEATURES;
+	phydev->advertising = phydev->supported;
+
+	priv->phydev = phydev;
+	phy_config(phydev);
+
+	return 0;
+}
+
+#else
+
+static inline int ethoc_mdio_init(const char *name, struct ethoc *priv)
+{
+	return 0;
+}
+
+static inline int ethoc_phy_init(struct ethoc *priv, void *dev)
+{
+	return 0;
+}
+
+#endif
+
+#ifdef CONFIG_DM_ETH
+
+static int ethoc_write_hwaddr(struct udevice *dev)
+{
+	struct ethoc_eth_pdata *pdata = dev_get_platdata(dev);
+	struct ethoc *priv = dev_get_priv(dev);
+	u8 *mac = pdata->eth_pdata.enetaddr;
+
+	return ethoc_write_hwaddr_common(priv, mac);
+}
+
+static int ethoc_send(struct udevice *dev, void *packet, int length)
+{
+	return ethoc_send_common(dev_get_priv(dev), packet, length);
+}
+
+static int ethoc_free_pkt(struct udevice *dev, uchar *packet, int length)
+{
+	return ethoc_free_pkt_common(dev_get_priv(dev));
+}
+
+static int ethoc_recv(struct udevice *dev, int flags, uchar **packetp)
+{
+	struct ethoc *priv = dev_get_priv(dev);
+
+	if (flags & ETH_RECV_CHECK_DEVICE)
+		if (!ethoc_is_new_packet_received(priv))
+			return -EAGAIN;
+
+	return ethoc_rx_common(priv, packetp);
+}
+
+static int ethoc_start(struct udevice *dev)
+{
+	return ethoc_init_common(dev_get_priv(dev));
+}
+
+static void ethoc_stop(struct udevice *dev)
+{
+	ethoc_stop_common(dev_get_priv(dev));
+}
+
+static int ethoc_ofdata_to_platdata(struct udevice *dev)
+{
+	struct ethoc_eth_pdata *pdata = dev_get_platdata(dev);
+	fdt_addr_t addr;
+
+	pdata->eth_pdata.iobase = dev_get_addr(dev);
+	addr = dev_get_addr_index(dev, 1);
+	if (addr != FDT_ADDR_T_NONE)
+		pdata->packet_base = addr;
+	return 0;
+}
+
+static int ethoc_probe(struct udevice *dev)
+{
+	struct ethoc_eth_pdata *pdata = dev_get_platdata(dev);
+	struct ethoc *priv = dev_get_priv(dev);
+
+	priv->iobase = ioremap(pdata->eth_pdata.iobase, ETHOC_IOSIZE);
+	if (pdata->packet_base) {
+		priv->packet_phys = pdata->packet_base;
+		priv->packet = ioremap(pdata->packet_base,
+				       (1 + PKTBUFSRX) * PKTSIZE_ALIGN);
+	}
+
+	ethoc_mdio_init(dev->name, priv);
+	ethoc_phy_init(priv, dev);
+
+	return 0;
+}
+
+static int ethoc_remove(struct udevice *dev)
+{
+	struct ethoc *priv = dev_get_priv(dev);
+
+#ifdef CONFIG_PHYLIB
+	free(priv->phydev);
+	mdio_unregister(priv->bus);
+	mdio_free(priv->bus);
+#endif
+	iounmap(priv->iobase);
+	return 0;
+}
+
+static const struct eth_ops ethoc_ops = {
+	.start		= ethoc_start,
+	.stop		= ethoc_stop,
+	.send		= ethoc_send,
+	.recv		= ethoc_recv,
+	.free_pkt	= ethoc_free_pkt,
+	.write_hwaddr	= ethoc_write_hwaddr,
+};
+
+static const struct udevice_id ethoc_ids[] = {
+	{ .compatible = "opencores,ethoc" },
+	{ }
+};
+
+U_BOOT_DRIVER(ethoc) = {
+	.name				= "ethoc",
+	.id				= UCLASS_ETH,
+	.of_match			= ethoc_ids,
+	.ofdata_to_platdata		= ethoc_ofdata_to_platdata,
+	.probe				= ethoc_probe,
+	.remove				= ethoc_remove,
+	.ops				= &ethoc_ops,
+	.priv_auto_alloc_size		= sizeof(struct ethoc),
+	.platdata_auto_alloc_size	= sizeof(struct ethoc_eth_pdata),
+};
+
+#else
+
+static int ethoc_init(struct eth_device *dev, bd_t *bd)
+{
+	struct ethoc *priv = (struct ethoc *)dev->priv;
+
+	return ethoc_init_common(priv);
+}
+
+static int ethoc_write_hwaddr(struct eth_device *dev)
+{
+	struct ethoc *priv = (struct ethoc *)dev->priv;
+	u8 *mac = dev->enetaddr;
+
+	return ethoc_write_hwaddr_common(priv, mac);
+}
+
+static int ethoc_send(struct eth_device *dev, void *packet, int length)
+{
+	return ethoc_send_common(dev->priv, packet, length);
+}
+
 static void ethoc_halt(struct eth_device *dev)
 {
-	ethoc_disable_rx_and_tx(dev);
+	ethoc_disable_rx_and_tx(dev->priv);
 }
 
 static int ethoc_recv(struct eth_device *dev)
 {
-	u32 pending;
+	struct ethoc *priv = (struct ethoc *)dev->priv;
+	int count;
 
-	pending = ethoc_read(dev, INT_SOURCE);
-	ethoc_ack_irq(dev, pending);
-	if (pending & INT_MASK_BUSY)
-		debug("%s(): packet dropped\n", __func__);
-	if (pending & INT_MASK_RX) {
-		debug("%s(): rx irq\n", __func__);
-		ethoc_rx(dev, PKTBUFSRX);
-	}
+	if (!ethoc_is_new_packet_received(priv))
+		return 0;
+
+	for (count = 0; count < PKTBUFSRX; ++count) {
+		uchar *packetp;
+		int size = ethoc_rx_common(priv, &packetp);
 
+		if (size < 0)
+			break;
+		if (size > 0)
+			net_process_received_packet(packetp, size);
+		ethoc_free_pkt_common(priv);
+	}
 	return 0;
 }
 
@@ -503,9 +822,16 @@ int ethoc_initialize(u8 dev_num, int base_addr)
 	dev->halt = ethoc_halt;
 	dev->send = ethoc_send;
 	dev->recv = ethoc_recv;
-	dev->write_hwaddr = ethoc_set_mac_address;
+	dev->write_hwaddr = ethoc_write_hwaddr;
 	sprintf(dev->name, "%s-%hu", "ETHOC", dev_num);
+	priv->iobase = ioremap(dev->iobase, ETHOC_IOSIZE);
 
 	eth_register(dev);
+
+	ethoc_mdio_init(dev->name, priv);
+	ethoc_phy_init(priv, dev);
+
 	return 1;
 }
+
+#endif
diff --git a/drivers/net/fsl_mcdmafec.c b/drivers/net/fsl_mcdmafec.c
index 792534b13956fb522bf48f6f7eb0c2935a273fe4..15a3ce03ae3402f89335e0bc6aa422dae38afb08 100644
--- a/drivers/net/fsl_mcdmafec.c
+++ b/drivers/net/fsl_mcdmafec.c
@@ -556,8 +556,17 @@ int mcdmafec_initialize(bd_t * bis)
 		eth_register(dev);
 
 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
-		miiphy_register(dev->name,
-				mcffec_miiphy_read, mcffec_miiphy_write);
+		int retval;
+		struct mii_dev *mdiodev = mdio_alloc();
+		if (!mdiodev)
+			return -ENOMEM;
+		strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+		mdiodev->read = mcffec_miiphy_read;
+		mdiodev->write = mcffec_miiphy_write;
+
+		retval = mdio_register(mdiodev);
+		if (retval < 0)
+			return retval;
 #endif
 
 		if (i > 0)
diff --git a/drivers/net/ftmac110.c b/drivers/net/ftmac110.c
index 4f17015bc593edece051b70e6a508e7812740f32..8fa767a1fe7def46923bd6f12de79df31529515a 100644
--- a/drivers/net/ftmac110.c
+++ b/drivers/net/ftmac110.c
@@ -364,32 +364,35 @@ static int ftmac110_recv(struct eth_device *dev)
 
 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
 
-static int ftmac110_mdio_read(
-	const char *devname, uint8_t addr, uint8_t reg, uint16_t *value)
+static int ftmac110_mdio_read(struct mii_dev *bus, int addr, int devad,
+			      int reg)
 {
+	uint16_t value = 0;
 	int ret = 0;
 	struct eth_device *dev;
 
-	dev = eth_get_dev_by_name(devname);
+	dev = eth_get_dev_by_name(bus->name);
 	if (dev == NULL) {
-		printf("%s: no such device\n", devname);
+		printf("%s: no such device\n", bus->name);
 		ret = -1;
 	} else {
-		*value = mdio_read(dev, addr, reg);
+		value = mdio_read(dev, addr, reg);
 	}
 
-	return ret;
+	if (ret < 0)
+		return ret;
+	return value;
 }
 
-static int ftmac110_mdio_write(
-	const char *devname, uint8_t addr, uint8_t reg, uint16_t value)
+static int ftmac110_mdio_write(struct mii_dev *bus, int addr, int devad,
+			       int reg, u16 value)
 {
 	int ret = 0;
 	struct eth_device *dev;
 
-	dev = eth_get_dev_by_name(devname);
+	dev = eth_get_dev_by_name(bus->name);
 	if (dev == NULL) {
-		printf("%s: no such device\n", devname);
+		printf("%s: no such device\n", bus->name);
 		ret = -1;
 	} else {
 		mdio_write(dev, addr, reg, value);
@@ -468,7 +471,17 @@ int ftmac110_initialize(bd_t *bis)
 	eth_register(dev);
 
 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
-	miiphy_register(dev->name, ftmac110_mdio_read, ftmac110_mdio_write);
+	int retval;
+	struct mii_dev *mdiodev = mdio_alloc();
+	if (!mdiodev)
+		return -ENOMEM;
+	strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+	mdiodev->read = ftmac110_mdio_read;
+	mdiodev->write = ftmac110_mdio_write;
+
+	retval = mdio_register(mdiodev);
+	if (retval < 0)
+		return retval;
 #endif
 
 	card_nr++;
diff --git a/drivers/net/lpc32xx_eth.c b/drivers/net/lpc32xx_eth.c
index 6cc273c33c81f046b1ce4f555d590213eddaa77a..2dd69f3816e2a6dc7e9cbec85394ab6891621962 100644
--- a/drivers/net/lpc32xx_eth.c
+++ b/drivers/net/lpc32xx_eth.c
@@ -226,9 +226,11 @@ DECLARE_GLOBAL_DATA_PTR;
  *
  * Returns 16bit phy register value, or 0xffff on error
  */
-static int mii_reg_read(const char *devname, u8 phy_adr, u8 reg_ofs, u16 *data)
+static int mii_reg_read(struct mii_dev *bus, int phy_adr, int devad,
+			int reg_ofs)
 {
-	struct eth_device *dev = eth_get_dev_by_name(devname);
+	u16 data = 0;
+	struct eth_device *dev = eth_get_dev_by_name(bus->name);
 	struct lpc32xx_eth_device *dlpc32xx_eth = to_lpc32xx_eth(dev);
 	struct lpc32xx_eth_registers *regs = dlpc32xx_eth->regs;
 	u32 mind_reg;
@@ -270,12 +272,12 @@ static int mii_reg_read(const char *devname, u8 phy_adr, u8 reg_ofs, u16 *data)
 		return -EFAULT;
 	}
 
-	*data = (u16) readl(&regs->mrdd);
+	data = (u16) readl(&regs->mrdd);
 
 	debug("%s:(adr %d, off %d) => %04x\n", __func__, phy_adr,
-	      reg_ofs, *data);
+	      reg_ofs, data);
 
-	return 0;
+	return data;
 }
 
 /*
@@ -284,9 +286,10 @@ static int mii_reg_read(const char *devname, u8 phy_adr, u8 reg_ofs, u16 *data)
  * Returns 0 if write succeed, -EINVAL on bad parameters
  * -ETIME on timeout
  */
-static int mii_reg_write(const char *devname, u8 phy_adr, u8 reg_ofs, u16 data)
+static int mii_reg_write(struct mii_dev *bus, int phy_adr, int devad,
+			 int reg_ofs, u16 data)
 {
-	struct eth_device *dev = eth_get_dev_by_name(devname);
+	struct eth_device *dev = eth_get_dev_by_name(bus->name);
 	struct lpc32xx_eth_device *dlpc32xx_eth = to_lpc32xx_eth(dev);
 	struct lpc32xx_eth_registers *regs = dlpc32xx_eth->regs;
 	u32 mind_reg;
@@ -333,25 +336,6 @@ static int mii_reg_write(const char *devname, u8 phy_adr, u8 reg_ofs, u16 data)
 }
 #endif
 
-#if defined(CONFIG_PHYLIB)
-int lpc32xx_eth_phy_read(struct mii_dev *bus, int phy_addr, int dev_addr,
-	int reg_addr)
-{
-	u16 data;
-	int ret;
-	ret = mii_reg_read(bus->name, phy_addr, reg_addr, &data);
-	if (ret)
-		return ret;
-	return data;
-}
-
-int lpc32xx_eth_phy_write(struct mii_dev *bus, int phy_addr, int dev_addr,
-	int reg_addr, u16 data)
-{
-	return mii_reg_write(bus->name, phy_addr, reg_addr, data);
-}
-#endif
-
 /*
  * Provide default Ethernet buffers base address if target did not.
  * Locate buffers in SRAM at 0x00001000 to avoid cache issues and
@@ -580,8 +564,8 @@ int lpc32xx_eth_phylib_init(struct eth_device *dev, int phyid)
 		printf("mdio_alloc failed\n");
 		return -ENOMEM;
 	}
-	bus->read = lpc32xx_eth_phy_read;
-	bus->write = lpc32xx_eth_phy_write;
+	bus->read = mii_reg_read;
+	bus->write = mii_reg_write;
 	strcpy(bus->name, dev->name);
 
 	ret = mdio_register(bus);
@@ -645,7 +629,17 @@ int lpc32xx_eth_initialize(bd_t *bis)
 #if defined(CONFIG_PHYLIB)
 	lpc32xx_eth_phylib_init(dev, CONFIG_PHY_ADDR);
 #elif defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
-	miiphy_register(dev->name, mii_reg_read, mii_reg_write);
+	int retval;
+	struct mii_dev *mdiodev = mdio_alloc();
+	if (!mdiodev)
+		return -ENOMEM;
+	strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+	mdiodev->read = mii_reg_read;
+	mdiodev->write = mii_reg_write;
+
+	retval = mdio_register(mdiodev);
+	if (retval < 0)
+		return retval;
 #endif
 
 	return 0;
diff --git a/drivers/net/macb.c b/drivers/net/macb.c
index 0835fdc306088e097e6b2509f8b0ddb83b1f76ff..921537f8a436ec4c42b255283895da158e520ed1 100644
--- a/drivers/net/macb.c
+++ b/drivers/net/macb.c
@@ -43,6 +43,8 @@
 
 #include "macb.h"
 
+DECLARE_GLOBAL_DATA_PTR;
+
 #define MACB_RX_BUFFER_SIZE		4096
 #define MACB_RX_RING_SIZE		(MACB_RX_BUFFER_SIZE / 128)
 #define MACB_TX_RING_SIZE		16
@@ -108,6 +110,10 @@ struct macb_device {
 #endif
 	unsigned short		phy_addr;
 	struct mii_dev		*bus;
+
+#ifdef CONFIG_DM_ETH
+	phy_interface_t		phy_interface;
+#endif
 };
 #ifndef CONFIG_DM_ETH
 #define to_macb(_nd) container_of(_nd, struct macb_device, netdev)
@@ -199,39 +205,41 @@ void __weak arch_get_mdio_control(const char *name)
 
 #if defined(CONFIG_CMD_MII) || defined(CONFIG_PHYLIB)
 
-int macb_miiphy_read(const char *devname, u8 phy_adr, u8 reg, u16 *value)
+int macb_miiphy_read(struct mii_dev *bus, int phy_adr, int devad, int reg)
 {
+	u16 value = 0;
 #ifdef CONFIG_DM_ETH
-	struct udevice *dev = eth_get_dev_by_name(devname);
+	struct udevice *dev = eth_get_dev_by_name(bus->name);
 	struct macb_device *macb = dev_get_priv(dev);
 #else
-	struct eth_device *dev = eth_get_dev_by_name(devname);
+	struct eth_device *dev = eth_get_dev_by_name(bus->name);
 	struct macb_device *macb = to_macb(dev);
 #endif
 
 	if (macb->phy_addr != phy_adr)
 		return -1;
 
-	arch_get_mdio_control(devname);
-	*value = macb_mdio_read(macb, reg);
+	arch_get_mdio_control(bus->name);
+	value = macb_mdio_read(macb, reg);
 
-	return 0;
+	return value;
 }
 
-int macb_miiphy_write(const char *devname, u8 phy_adr, u8 reg, u16 value)
+int macb_miiphy_write(struct mii_dev *bus, int phy_adr, int devad, int reg,
+		      u16 value)
 {
 #ifdef CONFIG_DM_ETH
-	struct udevice *dev = eth_get_dev_by_name(devname);
+	struct udevice *dev = eth_get_dev_by_name(bus->name);
 	struct macb_device *macb = dev_get_priv(dev);
 #else
-	struct eth_device *dev = eth_get_dev_by_name(devname);
+	struct eth_device *dev = eth_get_dev_by_name(bus->name);
 	struct macb_device *macb = to_macb(dev);
 #endif
 
 	if (macb->phy_addr != phy_adr)
 		return -1;
 
-	arch_get_mdio_control(devname);
+	arch_get_mdio_control(bus->name);
 	macb_mdio_write(macb, reg, value);
 
 	return 0;
@@ -434,7 +442,7 @@ static void macb_phy_reset(struct macb_device *macb, const char *name)
 }
 
 #ifdef CONFIG_MACB_SEARCH_PHY
-static int macb_phy_find(struct macb_device *macb)
+static int macb_phy_find(struct macb_device *macb, const char *name)
 {
 	int i;
 	u16 phy_id;
@@ -444,21 +452,27 @@ static int macb_phy_find(struct macb_device *macb)
 		macb->phy_addr = i;
 		phy_id = macb_mdio_read(macb, MII_PHYSID1);
 		if (phy_id != 0xffff) {
-			printf("%s: PHY present at %d\n", macb->netdev.name, i);
+			printf("%s: PHY present at %d\n", name, i);
 			return 1;
 		}
 	}
 
 	/* PHY isn't up to snuff */
-	printf("%s: PHY not found\n", macb->netdev.name);
+	printf("%s: PHY not found\n", name);
 
 	return 0;
 }
 #endif /* CONFIG_MACB_SEARCH_PHY */
 
-
+#ifdef CONFIG_DM_ETH
+static int macb_phy_init(struct udevice *dev, const char *name)
+#else
 static int macb_phy_init(struct macb_device *macb, const char *name)
+#endif
 {
+#ifdef CONFIG_DM_ETH
+	struct macb_device *macb = dev_get_priv(dev);
+#endif
 #ifdef CONFIG_PHYLIB
 	struct phy_device *phydev;
 #endif
@@ -470,7 +484,7 @@ static int macb_phy_init(struct macb_device *macb, const char *name)
 	arch_get_mdio_control(name);
 #ifdef CONFIG_MACB_SEARCH_PHY
 	/* Auto-detect phy_addr */
-	if (!macb_phy_find(macb))
+	if (!macb_phy_find(macb, name))
 		return 0;
 #endif /* CONFIG_MACB_SEARCH_PHY */
 
@@ -482,9 +496,14 @@ static int macb_phy_init(struct macb_device *macb, const char *name)
 	}
 
 #ifdef CONFIG_PHYLIB
+#ifdef CONFIG_DM_ETH
+	phydev = phy_connect(macb->bus, macb->phy_addr, dev,
+			     macb->phy_interface);
+#else
 	/* need to consider other phy interface mode */
 	phydev = phy_connect(macb->bus, macb->phy_addr, &macb->netdev,
 			     PHY_INTERFACE_MODE_RGMII);
+#endif
 	if (!phydev) {
 		printf("phy_connect failed\n");
 		return -ENODEV;
@@ -585,8 +604,15 @@ static int gmac_init_multi_queues(struct macb_device *macb)
 	return 0;
 }
 
+#ifdef CONFIG_DM_ETH
+static int _macb_init(struct udevice *dev, const char *name)
+#else
 static int _macb_init(struct macb_device *macb, const char *name)
+#endif
 {
+#ifdef CONFIG_DM_ETH
+	struct macb_device *macb = dev_get_priv(dev);
+#endif
 	unsigned long paddr;
 	int i;
 
@@ -634,13 +660,35 @@ static int _macb_init(struct macb_device *macb, const char *name)
 		 * When the GMAC IP without GE feature, this bit is used
 		 * to select interface between RMII and MII.
 		 */
+#ifdef CONFIG_DM_ETH
+		if (macb->phy_interface == PHY_INTERFACE_MODE_RMII)
+			gem_writel(macb, UR, GEM_BIT(RGMII));
+		else
+			gem_writel(macb, UR, 0);
+#else
 #if defined(CONFIG_RGMII) || defined(CONFIG_RMII)
 		gem_writel(macb, UR, GEM_BIT(RGMII));
 #else
 		gem_writel(macb, UR, 0);
+#endif
 #endif
 	} else {
 	/* choose RMII or MII mode. This depends on the board */
+#ifdef CONFIG_DM_ETH
+#ifdef CONFIG_AT91FAMILY
+		if (macb->phy_interface == PHY_INTERFACE_MODE_RMII) {
+			macb_writel(macb, USRIO,
+				    MACB_BIT(RMII) | MACB_BIT(CLKEN));
+		} else {
+			macb_writel(macb, USRIO, MACB_BIT(CLKEN));
+		}
+#else
+		if (macb->phy_interface == PHY_INTERFACE_MODE_RMII)
+			macb_writel(macb, USRIO, 0);
+		else
+			macb_writel(macb, USRIO, MACB_BIT(MII));
+#endif
+#else
 #ifdef CONFIG_RMII
 #ifdef CONFIG_AT91FAMILY
 	macb_writel(macb, USRIO, MACB_BIT(RMII) | MACB_BIT(CLKEN));
@@ -654,9 +702,14 @@ static int _macb_init(struct macb_device *macb, const char *name)
 	macb_writel(macb, USRIO, MACB_BIT(MII));
 #endif
 #endif /* CONFIG_RMII */
+#endif
 	}
 
+#ifdef CONFIG_DM_ETH
+	if (!macb_phy_init(dev, name))
+#else
 	if (!macb_phy_init(macb, name))
+#endif
 		return -1;
 
 	/* Enable TX and RX */
@@ -862,7 +915,17 @@ int macb_eth_initialize(int id, void *regs, unsigned int phy_addr)
 	eth_register(netdev);
 
 #if defined(CONFIG_CMD_MII) || defined(CONFIG_PHYLIB)
-	miiphy_register(netdev->name, macb_miiphy_read, macb_miiphy_write);
+	int retval;
+	struct mii_dev *mdiodev = mdio_alloc();
+	if (!mdiodev)
+		return -ENOMEM;
+	strncpy(mdiodev->name, netdev->name, MDIO_NAME_LEN);
+	mdiodev->read = macb_miiphy_read;
+	mdiodev->write = macb_miiphy_write;
+
+	retval = mdio_register(mdiodev);
+	if (retval < 0)
+		return retval;
 	macb->bus = miiphy_get_dev_by_name(netdev->name);
 #endif
 	return 0;
@@ -873,9 +936,7 @@ int macb_eth_initialize(int id, void *regs, unsigned int phy_addr)
 
 static int macb_start(struct udevice *dev)
 {
-	struct macb_device *macb = dev_get_priv(dev);
-
-	return _macb_init(macb, dev->name);
+	return _macb_init(dev, dev->name);
 }
 
 static int macb_send(struct udevice *dev, void *packet, int length)
@@ -933,11 +994,33 @@ static int macb_eth_probe(struct udevice *dev)
 	struct eth_pdata *pdata = dev_get_platdata(dev);
 	struct macb_device *macb = dev_get_priv(dev);
 
+#ifdef CONFIG_DM_ETH
+	const char *phy_mode;
+
+	phy_mode = fdt_getprop(gd->fdt_blob, dev->of_offset, "phy-mode", NULL);
+	if (phy_mode)
+		macb->phy_interface = phy_get_interface_by_name(phy_mode);
+	if (macb->phy_interface == -1) {
+		debug("%s: Invalid PHY interface '%s'\n", __func__, phy_mode);
+		return -EINVAL;
+	}
+#endif
+
 	macb->regs = (void *)pdata->iobase;
 
 	_macb_eth_initialize(macb);
 #if defined(CONFIG_CMD_MII) || defined(CONFIG_PHYLIB)
-	miiphy_register(dev->name, macb_miiphy_read, macb_miiphy_write);
+	int retval;
+	struct mii_dev *mdiodev = mdio_alloc();
+	if (!mdiodev)
+		return -ENOMEM;
+	strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+	mdiodev->read = macb_miiphy_read;
+	mdiodev->write = macb_miiphy_write;
+
+	retval = mdio_register(mdiodev);
+	if (retval < 0)
+		return retval;
 	macb->bus = miiphy_get_dev_by_name(dev->name);
 #endif
 
diff --git a/drivers/net/mcffec.c b/drivers/net/mcffec.c
index fd7309937104407935fada5839769bbcb7eb8381..e1b06b25d7c01257c3a9cb169eb8bff1a359965e 100644
--- a/drivers/net/mcffec.c
+++ b/drivers/net/mcffec.c
@@ -595,8 +595,17 @@ int mcffec_initialize(bd_t * bis)
 		eth_register(dev);
 
 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
-		miiphy_register(dev->name,
-				mcffec_miiphy_read, mcffec_miiphy_write);
+		int retval;
+		struct mii_dev *mdiodev = mdio_alloc();
+		if (!mdiodev)
+			return -ENOMEM;
+		strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+		mdiodev->read = mcffec_miiphy_read;
+		mdiodev->write = mcffec_miiphy_write;
+
+		retval = mdio_register(mdiodev);
+		if (retval < 0)
+			return retval;
 #endif
 		if (i > 0)
 			fec_info[i - 1].next = &fec_info[i];
diff --git a/drivers/net/mcfmii.c b/drivers/net/mcfmii.c
index 17a780c854d8fbb8f6f393bd50083d37a92fa7d9..103e36512291b30fad1b0329f35b9fe451d0f462 100644
--- a/drivers/net/mcfmii.c
+++ b/drivers/net/mcfmii.c
@@ -277,8 +277,7 @@ void __mii_init(void)
  *	  Otherwise they hang in mii_send() !!! Sorry!
  */
 
-int mcffec_miiphy_read(const char *devname, unsigned char addr, unsigned char reg,
-		       unsigned short *value)
+int mcffec_miiphy_read(struct mii_dev *bus, int addr, int devad, int reg)
 {
 	short rdreg;		/* register working value */
 
@@ -287,28 +286,22 @@ int mcffec_miiphy_read(const char *devname, unsigned char addr, unsigned char re
 #endif
 	rdreg = mii_send(mk_mii_read(addr, reg));
 
-	*value = rdreg;
-
 #ifdef MII_DEBUG
-	printf("0x%04x\n", *value);
+	printf("0x%04x\n", rdreg);
 #endif
 
-	return 0;
+	return rdreg;
 }
 
-int mcffec_miiphy_write(const char *devname, unsigned char addr, unsigned char reg,
-			unsigned short value)
+int mcffec_miiphy_write(struct mii_dev *bus, int addr, int devad, int reg,
+			u16 value)
 {
 #ifdef MII_DEBUG
-	printf("miiphy_write(0x%x) @ 0x%x = ", reg, addr);
+	printf("miiphy_write(0x%x) @ 0x%x = 0x%04x\n", reg, addr, value);
 #endif
 
 	mii_send(mk_mii_write(addr, reg, value));
 
-#ifdef MII_DEBUG
-	printf("0x%04x\n", value);
-#endif
-
 	return 0;
 }
 
diff --git a/drivers/net/mpc512x_fec.c b/drivers/net/mpc512x_fec.c
index e850672a4ffbd16af02924ae3e90abb2d23d0285..b3746fbb9a95ecba0d8773e1b0c43f31a1417148 100644
--- a/drivers/net/mpc512x_fec.c
+++ b/drivers/net/mpc512x_fec.c
@@ -22,8 +22,10 @@ DECLARE_GLOBAL_DATA_PTR;
 #error "CONFIG_MII has to be defined!"
 #endif
 
-int fec512x_miiphy_read(const char *devname, u8 phyAddr, u8 regAddr, u16 * retVal);
-int fec512x_miiphy_write(const char *devname, u8 phyAddr, u8 regAddr, u16 data);
+int fec512x_miiphy_read(struct mii_dev *bus, int phyAddr, int devad,
+			int regAddr);
+int fec512x_miiphy_write(struct mii_dev *bus, int phyAddr, int devad,
+			 int regAddr, u16 data);
 int mpc512x_fec_init_phy(struct eth_device *dev, bd_t * bis);
 
 static uchar rx_buff[FEC_BUFFER_SIZE];
@@ -639,8 +641,17 @@ int mpc512x_fec_initialize (bd_t * bis)
 	eth_register (dev);
 
 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
-	miiphy_register (dev->name,
-			fec512x_miiphy_read, fec512x_miiphy_write);
+	int retval;
+	struct mii_dev *mdiodev = mdio_alloc();
+	if (!mdiodev)
+		return -ENOMEM;
+	strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+	mdiodev->read = fec512x_miiphy_read;
+	mdiodev->write = fec512x_miiphy_write;
+
+	retval = mdio_register(mdiodev);
+	if (retval < 0)
+		return retval;
 #endif
 
 	/* Clean up space FEC's MIB and FIFO RAM ...*/
@@ -670,8 +681,10 @@ int mpc512x_fec_initialize (bd_t * bis)
 
 /* MII-interface related functions */
 /********************************************************************/
-int fec512x_miiphy_read(const char *devname, u8 phyAddr, u8 regAddr, u16 *retVal)
+int fec512x_miiphy_read(struct mii_dev *bus, int phyAddr, int devad,
+			int regAddr)
 {
+	u16 retVal = 0;
 	volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
 	volatile fec512x_t *eth = &im->fec;
 	u32 reg;		/* convenient holder for the PHY register */
@@ -711,13 +724,14 @@ int fec512x_miiphy_read(const char *devname, u8 phyAddr, u8 regAddr, u16 *retVal
 	/*
 	 * it's now safe to read the PHY's register
 	 */
-	*retVal = (u16) in_be32(&eth->mii_data);
+	retVal = (u16) in_be32(&eth->mii_data);
 
-	return 0;
+	return retVal;
 }
 
 /********************************************************************/
-int fec512x_miiphy_write(const char *devname, u8 phyAddr, u8 regAddr, u16 data)
+int fec512x_miiphy_write(struct mii_dev *bus, int phyAddr, int devad,
+			 int regAddr, u16 data)
 {
 	volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
 	volatile fec512x_t *eth = &im->fec;
diff --git a/drivers/net/mpc5xxx_fec.c b/drivers/net/mpc5xxx_fec.c
index e13b4cf32b4b91a02c76f9d760426ed30de3842a..d75e858a3826d6fc6416cacb0625758fc409e1d5 100644
--- a/drivers/net/mpc5xxx_fec.c
+++ b/drivers/net/mpc5xxx_fec.c
@@ -35,8 +35,10 @@ typedef struct {
     uint8 head[16];             /* MAC header(6 + 6 + 2) + 2(aligned) */
 } NBUF;
 
-int fec5xxx_miiphy_read(const char *devname, uint8 phyAddr, uint8 regAddr, uint16 *retVal);
-int fec5xxx_miiphy_write(const char *devname, uint8 phyAddr, uint8 regAddr, uint16 data);
+int fec5xxx_miiphy_read(struct mii_dev *bus, int phyAddr, int devad,
+			int regAddr);
+int fec5xxx_miiphy_write(struct mii_dev *bus, int phyAddr, int devad,
+			 int regAddr, u16 data);
 
 static int mpc5xxx_fec_init_phy(struct eth_device *dev, bd_t * bis);
 
@@ -917,8 +919,17 @@ int mpc5xxx_fec_initialize(bd_t * bis)
 	eth_register(dev);
 
 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
-	miiphy_register (dev->name,
-			fec5xxx_miiphy_read, fec5xxx_miiphy_write);
+	int retval;
+	struct mii_dev *mdiodev = mdio_alloc();
+	if (!mdiodev)
+		return -ENOMEM;
+	strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+	mdiodev->read = fec5xxx_miiphy_read;
+	mdiodev->write = fec5xxx_miiphy_write;
+
+	retval = mdio_register(mdiodev);
+	if (retval < 0)
+		return retval;
 #endif
 
 	/*
@@ -941,8 +952,10 @@ int mpc5xxx_fec_initialize(bd_t * bis)
 
 /* MII-interface related functions */
 /********************************************************************/
-int fec5xxx_miiphy_read(const char *devname, uint8 phyAddr, uint8 regAddr, uint16 * retVal)
+int fec5xxx_miiphy_read(struct mii_dev *bus, int phyAddr, int devad,
+			int regAddr)
 {
+	uint16 retVal = 0;
 	ethernet_regs *eth = (ethernet_regs *)MPC5XXX_FEC;
 	uint32 reg;		/* convenient holder for the PHY register */
 	uint32 phy;		/* convenient holder for the PHY */
@@ -977,13 +990,14 @@ int fec5xxx_miiphy_read(const char *devname, uint8 phyAddr, uint8 regAddr, uint1
 	/*
 	 * it's now safe to read the PHY's register
 	 */
-	*retVal = (uint16) eth->mii_data;
+	retVal = (uint16) eth->mii_data;
 
-	return 0;
+	return retVal;
 }
 
 /********************************************************************/
-int fec5xxx_miiphy_write(const char *devname, uint8 phyAddr, uint8 regAddr, uint16 data)
+int fec5xxx_miiphy_write(struct mii_dev *bus, int phyAddr, int devad,
+			 int regAddr, u16 data)
 {
 	ethernet_regs *eth = (ethernet_regs *)MPC5XXX_FEC;
 	uint32 reg;		/* convenient holder for the PHY register */
diff --git a/drivers/net/mvgbe.c b/drivers/net/mvgbe.c
index b16be9214289dd976e02cd9737e135264a3a51ae..a1c7ea054c16d2b2cb9c0a8367ceed8cc616b529 100644
--- a/drivers/net/mvgbe.c
+++ b/drivers/net/mvgbe.c
@@ -48,9 +48,11 @@ DECLARE_GLOBAL_DATA_PTR;
  *
  * Returns 16bit phy register value, or 0xffff on error
  */
-static int smi_reg_read(const char *devname, u8 phy_adr, u8 reg_ofs, u16 * data)
+static int smi_reg_read(struct mii_dev *bus, int phy_adr, int devad,
+			int reg_ofs)
 {
-	struct eth_device *dev = eth_get_dev_by_name(devname);
+	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;
@@ -60,8 +62,8 @@ static int smi_reg_read(const char *devname, u8 phy_adr, u8 reg_ofs, u16 * data)
 	if (phy_adr == MV_PHY_ADR_REQUEST &&
 			reg_ofs == MV_PHY_ADR_REQUEST) {
 		/* */
-		*data = (u16) (MVGBE_REG_RD(regs->phyadr) & PHYADR_MASK);
-		return 0;
+		data = (u16) (MVGBE_REG_RD(regs->phyadr) & PHYADR_MASK);
+		return data;
 	}
 	/* check parameters */
 	if (phy_adr > PHYADR_MASK) {
@@ -111,12 +113,12 @@ static int smi_reg_read(const char *devname, u8 phy_adr, u8 reg_ofs, u16 * data)
 	for (timeout = 0; timeout < MVGBE_PHY_SMI_TIMEOUT; timeout++)
 		;
 
-	*data = (u16) (MVGBE_REG_RD(MVGBE_SMI_REG) & MVGBE_PHY_SMI_DATA_MASK);
+	data = (u16) (MVGBE_REG_RD(MVGBE_SMI_REG) & MVGBE_PHY_SMI_DATA_MASK);
 
 	debug("%s:(adr %d, off %d) value= %04x\n", __func__, phy_adr, reg_ofs,
-	      *data);
+	      data);
 
-	return 0;
+	return data;
 }
 
 /*
@@ -125,9 +127,10 @@ static int smi_reg_read(const char *devname, u8 phy_adr, u8 reg_ofs, u16 * data)
  * Returns 0 if write succeed, -EINVAL on bad parameters
  * -ETIME on timeout
  */
-static int smi_reg_write(const char *devname, u8 phy_adr, u8 reg_ofs, u16 data)
+static int smi_reg_write(struct mii_dev *bus, int phy_adr, int devad,
+			 int reg_ofs, u16 data)
 {
-	struct eth_device *dev = eth_get_dev_by_name(devname);
+	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;
@@ -785,7 +788,17 @@ error1:
 #if defined(CONFIG_PHYLIB)
 		mvgbe_phylib_init(dev, PHY_BASE_ADR + devnum);
 #elif defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
-		miiphy_register(dev->name, smi_reg_read, smi_reg_write);
+		int retval;
+		struct mii_dev *mdiodev = mdio_alloc();
+		if (!mdiodev)
+			return -ENOMEM;
+		strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+		mdiodev->read = smi_reg_read;
+		mdiodev->write = smi_reg_write;
+
+		retval = mdio_register(mdiodev);
+		if (retval < 0)
+			return retval;
 		/* Set phy address of the port */
 		miiphy_write(dev->name, MV_PHY_ADR_REQUEST,
 				MV_PHY_ADR_REQUEST, PHY_BASE_ADR + devnum);
diff --git a/drivers/net/phy/miiphybb.c b/drivers/net/phy/miiphybb.c
index 5cda0b84692b9a7203fd493d424b6f18fd69cfc5..af676b9baeec956f3c85d61bf1141a860cc7c274 100644
--- a/drivers/net/phy/miiphybb.c
+++ b/drivers/net/phy/miiphybb.c
@@ -230,24 +230,18 @@ static void miiphy_pre(struct bb_miiphy_bus *bus, char read,
  * Returns:
  *   0 on success
  */
-int bb_miiphy_read(const char *devname, unsigned char addr,
-		   unsigned char reg, unsigned short *value)
+int bb_miiphy_read(struct mii_dev *miidev, int addr, int devad, int reg)
 {
 	short rdreg; /* register working value */
 	int v;
 	int j; /* counter */
 	struct bb_miiphy_bus *bus;
 
-	bus = bb_miiphy_getbus(devname);
+	bus = bb_miiphy_getbus(miidev->name);
 	if (bus == NULL) {
 		return -1;
 	}
 
-	if (value == NULL) {
-		puts("NULL value pointer\n");
-		return -1;
-	}
-
 	miiphy_pre (bus, 1, addr, reg);
 
 	/* tri-state our MDIO I/O pin so we can read */
@@ -267,8 +261,7 @@ int bb_miiphy_read(const char *devname, unsigned char addr,
 			bus->set_mdc(bus, 1);
 			bus->delay(bus);
 		}
-		/* There is no PHY, set value to 0xFFFF and return */
-		*value = 0xFFFF;
+		/* There is no PHY, return */
 		return -1;
 	}
 
@@ -294,13 +287,11 @@ int bb_miiphy_read(const char *devname, unsigned char addr,
 	bus->set_mdc(bus, 1);
 	bus->delay(bus);
 
-	*value = rdreg;
-
 #ifdef DEBUG
-	printf ("miiphy_read(0x%x) @ 0x%x = 0x%04x\n", reg, addr, *value);
+	printf("miiphy_read(0x%x) @ 0x%x = 0x%04x\n", reg, addr, rdreg);
 #endif
 
-	return 0;
+	return rdreg;
 }
 
 
@@ -311,13 +302,13 @@ int bb_miiphy_read(const char *devname, unsigned char addr,
  * Returns:
  *   0 on success
  */
-int bb_miiphy_write (const char *devname, unsigned char addr,
-		     unsigned char reg, unsigned short value)
+int bb_miiphy_write(struct mii_dev *miidev, int addr, int devad, int reg,
+		    u16 value)
 {
 	struct bb_miiphy_bus *bus;
 	int j;			/* counter */
 
-	bus = bb_miiphy_getbus(devname);
+	bus = bb_miiphy_getbus(miidev->name);
 	if (bus == NULL) {
 		/* Bus not found! */
 		return -1;
diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c
index 2fa2016cdd7d79efcafc3b3380e75f5f5078baf2..79c1db2c83a5ba6e8fb7864f01db85737e3c2fa5 100644
--- a/drivers/net/sh_eth.c
+++ b/drivers/net/sh_eth.c
@@ -566,7 +566,17 @@ int sh_eth_initialize(bd_t *bd)
 	eth_register(dev);
 
 	bb_miiphy_buses[0].priv = eth;
-	miiphy_register(dev->name, bb_miiphy_read, bb_miiphy_write);
+	int retval;
+	struct mii_dev *mdiodev = mdio_alloc();
+	if (!mdiodev)
+		return -ENOMEM;
+	strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+	mdiodev->read = bb_miiphy_read;
+	mdiodev->write = bb_miiphy_write;
+
+	retval = mdio_register(mdiodev);
+	if (retval < 0)
+		return retval;
 
 	if (!eth_getenv_enetaddr("ethaddr", dev->enetaddr))
 		puts("Please set MAC address\n");
diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c
index c85a178cd89a0ec7db1a619e49f1832f505ced94..feae8c09cf168117db9a9ab6d4ddbb95f147b691 100644
--- a/drivers/net/smc911x.c
+++ b/drivers/net/smc911x.c
@@ -219,20 +219,27 @@ static int smc911x_rx(struct eth_device *dev)
 
 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
 /* wrapper for smc911x_eth_phy_read */
-static int smc911x_miiphy_read(const char *devname, u8 phy, u8 reg, u16 *val)
+static int smc911x_miiphy_read(struct mii_dev *bus, int phy, int devad,
+			       int reg)
 {
-	struct eth_device *dev = eth_get_dev_by_name(devname);
-	if (dev)
-		return smc911x_eth_phy_read(dev, phy, reg, val);
-	return -1;
+	u16 val = 0;
+	struct eth_device *dev = eth_get_dev_by_name(bus->name);
+	if (dev) {
+		int retval = smc911x_eth_phy_read(dev, phy, reg, &val);
+		if (retval < 0)
+			return retval;
+		return val;
+	}
+	return -ENODEV;
 }
 /* wrapper for smc911x_eth_phy_write */
-static int smc911x_miiphy_write(const char *devname, u8 phy, u8 reg, u16 val)
+static int smc911x_miiphy_write(struct mii_dev *bus, int phy, int devad,
+				int reg, u16 val)
 {
-	struct eth_device *dev = eth_get_dev_by_name(devname);
+	struct eth_device *dev = eth_get_dev_by_name(bus->name);
 	if (dev)
 		return smc911x_eth_phy_write(dev, phy, reg, val);
-	return -1;
+	return -ENODEV;
 }
 #endif
 
@@ -276,7 +283,17 @@ int smc911x_initialize(u8 dev_num, int base_addr)
 	eth_register(dev);
 
 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
-	miiphy_register(dev->name, smc911x_miiphy_read, smc911x_miiphy_write);
+	int retval;
+	struct mii_dev *mdiodev = mdio_alloc();
+	if (!mdiodev)
+		return -ENOMEM;
+	strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+	mdiodev->read = smc911x_miiphy_read;
+	mdiodev->write = smc911x_miiphy_write;
+
+	retval = mdio_register(mdiodev);
+	if (retval < 0)
+		return retval;
 #endif
 
 	return 1;
diff --git a/drivers/qe/uec.c b/drivers/qe/uec.c
index 40cccc2406be00fb5fcfdd75b593fb7c644820b4..468c92ebced50feb0c991824a404b72fc6f93afb 100644
--- a/drivers/qe/uec.c
+++ b/drivers/qe/uec.c
@@ -623,20 +623,20 @@ static int uec_miiphy_find_dev_by_name(const char *devname)
  * Returns:
  *  0 on success
  */
-static int uec_miiphy_read(const char *devname, unsigned char addr,
-			    unsigned char reg, unsigned short *value)
+static int uec_miiphy_read(struct mii_dev *bus, int addr, int devad, int reg)
 {
+	unsigned short value = 0;
 	int devindex = 0;
 
-	if (devname == NULL || value == NULL) {
+	if (bus->name == NULL) {
 		debug("%s: NULL pointer given\n", __FUNCTION__);
 	} else {
-		devindex = uec_miiphy_find_dev_by_name(devname);
+		devindex = uec_miiphy_find_dev_by_name(bus->name);
 		if (devindex >= 0) {
-			*value = uec_read_phy_reg(devlist[devindex], addr, reg);
+			value = uec_read_phy_reg(devlist[devindex], addr, reg);
 		}
 	}
-	return 0;
+	return value;
 }
 
 /*
@@ -645,15 +645,15 @@ static int uec_miiphy_read(const char *devname, unsigned char addr,
  * Returns:
  *  0 on success
  */
-static int uec_miiphy_write(const char *devname, unsigned char addr,
-			     unsigned char reg, unsigned short value)
+static int uec_miiphy_write(struct mii_dev *bus, int addr, int devad, int reg,
+			    u16 value)
 {
 	int devindex = 0;
 
-	if (devname == NULL) {
+	if (bus->name == NULL) {
 		debug("%s: NULL pointer given\n", __FUNCTION__);
 	} else {
-		devindex = uec_miiphy_find_dev_by_name(devname);
+		devindex = uec_miiphy_find_dev_by_name(bus->name);
 		if (devindex >= 0) {
 			uec_write_phy_reg(devlist[devindex], addr, reg, value);
 		}
@@ -1399,7 +1399,17 @@ int uec_initialize(bd_t *bis, uec_info_t *uec_info)
 	}
 
 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
-	miiphy_register(dev->name, uec_miiphy_read, uec_miiphy_write);
+	int retval;
+	struct mii_dev *mdiodev = mdio_alloc();
+	if (!mdiodev)
+		return -ENOMEM;
+	strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
+	mdiodev->read = uec_miiphy_read;
+	mdiodev->write = uec_miiphy_write;
+
+	retval = mdio_register(mdiodev);
+	if (retval < 0)
+		return retval;
 #endif
 
 	return 1;
diff --git a/drivers/usb/eth/smsc95xx.c b/drivers/usb/eth/smsc95xx.c
index 08eaed5c2e03736a3df040e41ceb7bbdf8c11eae..7d9abfda3be19cc763c232de01c78e9a930f2c83 100644
--- a/drivers/usb/eth/smsc95xx.c
+++ b/drivers/usb/eth/smsc95xx.c
@@ -391,8 +391,8 @@ static int smsc95xx_write_hwaddr_common(struct usb_device *udev,
 					struct smsc95xx_private *priv,
 					unsigned char *enetaddr)
 {
-	u32 addr_lo = __get_unaligned_le32(&enetaddr[0]);
-	u32 addr_hi = __get_unaligned_le16(&enetaddr[4]);
+	u32 addr_lo = get_unaligned_le32(&enetaddr[0]);
+	u32 addr_hi = get_unaligned_le16(&enetaddr[4]);
 	int ret;
 
 	/* set hardware address */
diff --git a/include/configs/corvus.h b/include/configs/corvus.h
index e6a811af03f835641039e4763d365f4f0081113c..28ea15b596ac328e2ea6cb50e8028f5ea534b47f 100644
--- a/include/configs/corvus.h
+++ b/include/configs/corvus.h
@@ -95,6 +95,7 @@
 
 /* Ethernet */
 #define CONFIG_MACB
+#define CONFIG_PHYLIB
 #define CONFIG_RMII
 #define CONFIG_NET_RETRY_COUNT		20
 #define CONFIG_AT91_WANTS_COMMON_PHY
diff --git a/include/configs/openrisc-generic.h b/include/configs/openrisc-generic.h
index 913256a02bd0bb8de49a2d09254f2c9a7573da3b..227c0ca84bc1f4afb308a5b0829adbf8e2a23008 100644
--- a/include/configs/openrisc-generic.h
+++ b/include/configs/openrisc-generic.h
@@ -44,7 +44,6 @@
 /*
  * Ethernet
  */
-#define CONFIG_ETHOC
 #define CONFIG_SYS_ETHOC_BASE		0x92000000
 
 #define CONFIG_BOOTFILE			"boot.img"
diff --git a/include/configs/smartweb.h b/include/configs/smartweb.h
index 6add3916fa873a7d2c51f226d0f64742c202b7c9..076a5ce2992f5b9426db31df176d51154b1fb030 100644
--- a/include/configs/smartweb.h
+++ b/include/configs/smartweb.h
@@ -122,6 +122,7 @@
  *
  */
 #define CONFIG_MACB
+#define CONFIG_PHYLIB
 #define CONFIG_USB_HOST_ETHER
 #define CONFIG_USB_ETHER_ASIX
 #define CONFIG_USB_ETHER_MCS7830
diff --git a/include/configs/snapper9g45.h b/include/configs/snapper9g45.h
index fd6c70e110fbea52a1ecd285e037eec79967280c..c91ab7186ce43f230a72e3172577b2feeeba7126 100644
--- a/include/configs/snapper9g45.h
+++ b/include/configs/snapper9g45.h
@@ -56,6 +56,7 @@
 
 /* Ethernet */
 #define CONFIG_MACB
+#define CONFIG_PHYLIB
 #define CONFIG_RMII
 #define CONFIG_NET_RETRY_COUNT		20
 #define CONFIG_RESET_PHY_R
diff --git a/include/configs/taurus.h b/include/configs/taurus.h
index 882a4e5dbffff4aa59ca87a61548f1e0df224da1..2d091db07d97e974f5d2d082548be71e8392a2aa 100644
--- a/include/configs/taurus.h
+++ b/include/configs/taurus.h
@@ -99,6 +99,7 @@
 
 /* Ethernet */
 #define CONFIG_MACB
+#define CONFIG_PHYLIB
 #define CONFIG_RMII
 #define CONFIG_AT91_WANTS_COMMON_PHY
 
diff --git a/include/dm/platform_data/net_ethoc.h b/include/dm/platform_data/net_ethoc.h
new file mode 100644
index 0000000000000000000000000000000000000000..3f94bde7b26295413c03b4d998988763819061a7
--- /dev/null
+++ b/include/dm/platform_data/net_ethoc.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2016 Cadence Design Systems Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#ifndef _ETHOC_H
+#define _ETHOC_H
+
+#include <net.h>
+
+#ifdef CONFIG_DM_ETH
+
+struct ethoc_eth_pdata {
+	struct eth_pdata eth_pdata;
+	phys_addr_t packet_base;
+};
+
+#endif
+
+#endif /* _ETHOC_H */
diff --git a/include/miiphy.h b/include/miiphy.h
index af12274c81df2d7febbe257ee940f46be5aaed08..83141b4a6ae17cae9a2655dbd230defa18aadac1 100644
--- a/include/miiphy.h
+++ b/include/miiphy.h
@@ -21,13 +21,6 @@
 #include <net.h>
 #include <phy.h>
 
-struct legacy_mii_dev {
-	int (*read)(const char *devname, unsigned char addr,
-		     unsigned char reg, unsigned short *value);
-	int (*write)(const char *devname, unsigned char addr,
-		      unsigned char reg, unsigned short value);
-};
-
 int miiphy_read(const char *devname, unsigned char addr, unsigned char reg,
 		 unsigned short *value);
 int miiphy_write(const char *devname, unsigned char addr, unsigned char reg,
@@ -44,12 +37,6 @@ int miiphy_link(const char *devname, unsigned char addr);
 
 void miiphy_init(void);
 
-void miiphy_register(const char *devname,
-		      int (*read)(const char *devname, unsigned char addr,
-				   unsigned char reg, unsigned short *value),
-		      int (*write)(const char *devname, unsigned char addr,
-				    unsigned char reg, unsigned short value));
-
 int miiphy_set_current_dev(const char *devname);
 const char *miiphy_get_current_dev(void);
 struct mii_dev *mdio_get_current_dev(void);
@@ -86,10 +73,9 @@ extern struct bb_miiphy_bus bb_miiphy_buses[];
 extern int bb_miiphy_buses_num;
 
 void bb_miiphy_init(void);
-int bb_miiphy_read(const char *devname, unsigned char addr,
-		    unsigned char reg, unsigned short *value);
-int bb_miiphy_write(const char *devname, unsigned char addr,
-		     unsigned char reg, unsigned short value);
+int bb_miiphy_read(struct mii_dev *miidev, int addr, int devad, int reg);
+int bb_miiphy_write(struct mii_dev *miidev, int addr, int devad, int reg,
+		    u16 value);
 #endif
 
 /* phy seed setup */
diff --git a/scripts/coccinelle/net/mdio_register.cocci b/scripts/coccinelle/net/mdio_register.cocci
new file mode 100644
index 0000000000000000000000000000000000000000..100f10293610950cdc484c6d1457e427ca7790d0
--- /dev/null
+++ b/scripts/coccinelle/net/mdio_register.cocci
@@ -0,0 +1,142 @@
+/// Use mdio_alloc and mdio_register instead of miiphy_register
+///
+//# Stop using the oldest mii interface in drivers
+//
+// Confidence: High
+// Copyright: (C) 2016 Joe Hershberger.  GPLv2.
+// Comments:
+// Options: --include-headers --recursive-includes --local-includes -I include
+
+@ mii_reg @
+expression devname;
+identifier readfunc, writefunc;
+@@
+
++ int retval;
+- miiphy_register(devname, readfunc, writefunc);
++ struct mii_dev *mdiodev = mdio_alloc();
++ if (!mdiodev) return -ENOMEM;
++ strncpy(mdiodev->name, devname, MDIO_NAME_LEN);
++ mdiodev->read = readfunc;
++ mdiodev->write = writefunc;
++ 
++ retval = mdio_register(mdiodev);
++ if (retval < 0) return retval;
+
+@ update_read_sig @
+identifier mii_reg.readfunc;
+identifier name0, addr0, reg0, output;
+type addrT, outputT;
+@@
+
+- readfunc (
+- 	const char *name0,
+- 	addrT addr0,
+- 	addrT reg0,
+- 	outputT *output
+- )
++ readfunc (
++ 	struct mii_dev *bus,
++ 	int addr0,
++ 	int devad,
++ 	int reg0
++ )
+  {
+  ...
+  }
+
+@ update_read_impl @
+identifier mii_reg.readfunc;
+identifier update_read_sig.output;
+type update_read_sig.outputT;
+constant c;
+identifier retvar;
+expression E;
+@@
+
+  readfunc (...)
+  {
++ outputT output = 0;
+  ...
+(
+- return 0;
++ return *output;
+|
+  return c;
+|
+- return retvar;
++ if (retvar < 0)
++ 	return retvar;
++ return *output;
+|
+- return E;
++ int retval = E;
++ if (retval < 0)
++ 	return retval;
++ return *output;
+)
+  }
+
+@ update_read_impl2 @
+identifier mii_reg.readfunc;
+identifier update_read_sig.output;
+@@
+
+  readfunc (...)
+  {
+  <...
+(
+- *output
++ output
+|
+- output
++ &output
+)
+  ...>
+  }
+
+@ update_read_name @
+identifier mii_reg.readfunc;
+identifier update_read_sig.name0;
+@@
+  readfunc (...) {
+  <...
+- name0
++ bus->name
+  ...>
+  }
+
+@ update_write_sig @
+identifier mii_reg.writefunc;
+identifier name0, addr0, reg0, value0;
+type addrT, valueT;
+typedef u16;
+@@
+
+- writefunc (
+- 	const char *name0,
+- 	addrT addr0,
+- 	addrT reg0,
+- 	valueT value0
+- )
++ writefunc (
++ 	struct mii_dev *bus,
++ 	int addr0,
++ 	int devad,
++ 	int reg0,
++ 	u16 value0
++ )
+  {
+  ...
+  }
+
+@ update_write_name @
+identifier mii_reg.writefunc;
+identifier update_write_sig.name0;
+@@
+  writefunc (...) {
+  <...
+- name0
++ bus->name
+  ...>
+  }