diff --git a/board/ti/am335x/board.c b/board/ti/am335x/board.c
index 0ed16ca15ae79d696a49e4e23e3830a3f2a25210..fc1353ae3b2c63d747beb61bbc19f84158d39635 100644
--- a/board/ti/am335x/board.c
+++ b/board/ti/am335x/board.c
@@ -47,11 +47,19 @@ DECLARE_GLOBAL_DATA_PTR;
 #define GPIO_MUX_MII_CTRL	GPIO_TO_PIN(3, 10)
 #define GPIO_FET_SWITCH_CTRL	GPIO_TO_PIN(0, 7)
 #define GPIO_PHY_RESET		GPIO_TO_PIN(2, 5)
+#define GPIO_ETH0_MODE		GPIO_TO_PIN(0, 11)
+#define GPIO_ETH1_MODE		GPIO_TO_PIN(1, 26)
 
-#if defined(CONFIG_SPL_BUILD) || \
-	(defined(CONFIG_DRIVER_TI_CPSW) && !defined(CONFIG_DM_ETH))
 static struct ctrl_dev *cdev = (struct ctrl_dev *)CTRL_DEVICE_BASE;
-#endif
+
+#define GPIO0_RISINGDETECT	(AM33XX_GPIO0_BASE + OMAP_GPIO_RISINGDETECT)
+#define GPIO1_RISINGDETECT	(AM33XX_GPIO1_BASE + OMAP_GPIO_RISINGDETECT)
+
+#define GPIO0_IRQSTATUS1	(AM33XX_GPIO0_BASE + OMAP_GPIO_IRQSTATUS1)
+#define GPIO1_IRQSTATUS1	(AM33XX_GPIO1_BASE + OMAP_GPIO_IRQSTATUS1)
+
+#define GPIO0_IRQSTATUSRAW	(AM33XX_GPIO0_BASE + 0x024)
+#define GPIO1_IRQSTATUSRAW	(AM33XX_GPIO1_BASE + 0x024)
 
 /*
  * Read header information from EEPROM into global structure.
@@ -492,9 +500,9 @@ void sdram_init(void)
 }
 #endif
 
-#if (defined(CONFIG_DRIVER_TI_CPSW) && !defined(CONFIG_SPL_BUILD)) || \
+#if !defined(CONFIG_SPL_BUILD) || \
 	(defined(CONFIG_SPL_ETH_SUPPORT) && defined(CONFIG_SPL_BUILD))
-static void request_and_set_gpio(int gpio, char *name)
+static void request_and_set_gpio(int gpio, char *name, int val)
 {
 	int ret;
 
@@ -510,7 +518,7 @@ static void request_and_set_gpio(int gpio, char *name)
 		goto err_free_gpio;
 	}
 
-	gpio_set_value(gpio, 1);
+	gpio_set_value(gpio, val);
 
 	return;
 
@@ -518,7 +526,8 @@ err_free_gpio:
 	gpio_free(gpio);
 }
 
-#define REQUEST_AND_SET_GPIO(N)	request_and_set_gpio(N, #N);
+#define REQUEST_AND_SET_GPIO(N)	request_and_set_gpio(N, #N, 1);
+#define REQUEST_AND_CLR_GPIO(N)	request_and_set_gpio(N, #N, 0);
 
 /**
  * RMII mode on ICEv2 board needs 50MHz clock. Given the clock
@@ -548,20 +557,76 @@ int board_init(void)
 #if defined(CONFIG_NOR) || defined(CONFIG_NAND)
 	gpmc_init();
 #endif
-#if (defined(CONFIG_DRIVER_TI_CPSW) && !defined(CONFIG_SPL_BUILD))
-	int rv;
 
+#if !defined(CONFIG_SPL_BUILD) || \
+	(defined(CONFIG_SPL_ETH_SUPPORT) && defined(CONFIG_SPL_BUILD))
 	if (board_is_icev2()) {
+		int rv;
+		u32 reg;
+
 		REQUEST_AND_SET_GPIO(GPIO_PR1_MII_CTRL);
-		REQUEST_AND_SET_GPIO(GPIO_MUX_MII_CTRL);
+		/* Make J19 status available on GPIO1_26 */
+		REQUEST_AND_CLR_GPIO(GPIO_MUX_MII_CTRL);
+
 		REQUEST_AND_SET_GPIO(GPIO_FET_SWITCH_CTRL);
+		/*
+		 * Both ports can be set as RMII-CPSW or MII-PRU-ETH using
+		 * jumpers near the port. Read the jumper value and set
+		 * the pinmux, external mux and PHY clock accordingly.
+		 * As jumper line is overridden by PHY RX_DV pin immediately
+		 * after bootstrap (power-up/reset), we need to sample
+		 * it during PHY reset using GPIO rising edge detection.
+		 */
 		REQUEST_AND_SET_GPIO(GPIO_PHY_RESET);
+		/* Enable rising edge IRQ on GPIO0_11 and GPIO 1_26 */
+		reg = readl(GPIO0_RISINGDETECT) | BIT(11);
+		writel(reg, GPIO0_RISINGDETECT);
+		reg = readl(GPIO1_RISINGDETECT) | BIT(26);
+		writel(reg, GPIO1_RISINGDETECT);
+		/* Reset PHYs to capture the Jumper setting */
+		gpio_set_value(GPIO_PHY_RESET, 0);
+		udelay(2);	/* PHY datasheet states 1uS min. */
+		gpio_set_value(GPIO_PHY_RESET, 1);
+
+		reg = readl(GPIO0_IRQSTATUSRAW) & BIT(11);
+		if (reg) {
+			writel(reg, GPIO0_IRQSTATUS1); /* clear irq */
+			/* RMII mode */
+			printf("ETH0, CPSW\n");
+		} else {
+			/* MII mode */
+			printf("ETH0, PRU\n");
+			cdce913_data.pdiv3 = 4;	/* 25MHz PHY clk */
+		}
+
+		reg = readl(GPIO1_IRQSTATUSRAW) & BIT(26);
+		if (reg) {
+			writel(reg, GPIO1_IRQSTATUS1); /* clear irq */
+			/* RMII mode */
+			printf("ETH1, CPSW\n");
+			gpio_set_value(GPIO_MUX_MII_CTRL, 1);
+		} else {
+			/* MII mode */
+			printf("ETH1, PRU\n");
+			cdce913_data.pdiv2 = 4;	/* 25MHz PHY clk */
+		}
+
+		/* disable rising edge IRQs */
+		reg = readl(GPIO0_RISINGDETECT) & ~BIT(11);
+		writel(reg, GPIO0_RISINGDETECT);
+		reg = readl(GPIO1_RISINGDETECT) & ~BIT(26);
+		writel(reg, GPIO1_RISINGDETECT);
 
 		rv = setup_clock_synthesizer(&cdce913_data);
 		if (rv) {
 			printf("Clock synthesizer setup failed %d\n", rv);
 			return rv;
 		}
+
+		/* reset PHYs */
+		gpio_set_value(GPIO_PHY_RESET, 0);
+		udelay(2);	/* PHY datasheet states 1uS min. */
+		gpio_set_value(GPIO_PHY_RESET, 1);
 	}
 #endif
 
@@ -571,6 +636,11 @@ int board_init(void)
 #ifdef CONFIG_BOARD_LATE_INIT
 int board_late_init(void)
 {
+#if !defined(CONFIG_SPL_BUILD)
+	uint8_t mac_addr[6];
+	uint32_t mac_hi, mac_lo;
+#endif
+
 #ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
 	int rc;
 	char *name = NULL;
@@ -584,6 +654,39 @@ int board_late_init(void)
 	set_board_info_env(name);
 #endif
 
+#if !defined(CONFIG_SPL_BUILD)
+	/* try reading mac address from efuse */
+	mac_lo = readl(&cdev->macid0l);
+	mac_hi = readl(&cdev->macid0h);
+	mac_addr[0] = mac_hi & 0xFF;
+	mac_addr[1] = (mac_hi & 0xFF00) >> 8;
+	mac_addr[2] = (mac_hi & 0xFF0000) >> 16;
+	mac_addr[3] = (mac_hi & 0xFF000000) >> 24;
+	mac_addr[4] = mac_lo & 0xFF;
+	mac_addr[5] = (mac_lo & 0xFF00) >> 8;
+
+	if (!getenv("ethaddr")) {
+		printf("<ethaddr> not set. Validating first E-fuse MAC\n");
+
+		if (is_valid_ethaddr(mac_addr))
+			eth_setenv_enetaddr("ethaddr", mac_addr);
+	}
+
+	mac_lo = readl(&cdev->macid1l);
+	mac_hi = readl(&cdev->macid1h);
+	mac_addr[0] = mac_hi & 0xFF;
+	mac_addr[1] = (mac_hi & 0xFF00) >> 8;
+	mac_addr[2] = (mac_hi & 0xFF0000) >> 16;
+	mac_addr[3] = (mac_hi & 0xFF000000) >> 24;
+	mac_addr[4] = mac_lo & 0xFF;
+	mac_addr[5] = (mac_lo & 0xFF00) >> 8;
+
+	if (!getenv("eth1addr")) {
+		if (is_valid_ethaddr(mac_addr))
+			eth_setenv_enetaddr("eth1addr", mac_addr);
+	}
+#endif
+
 	return 0;
 }
 #endif
@@ -652,11 +755,15 @@ static struct cpsw_platform_data cpsw_data = {
 int board_eth_init(bd_t *bis)
 {
 	int rv, n = 0;
+#if defined(CONFIG_USB_ETHER) && \
+	(!defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_USBETH_SUPPORT))
 	uint8_t mac_addr[6];
 	uint32_t mac_hi, mac_lo;
-	__maybe_unused struct ti_am_eeprom *header;
 
-	/* try reading mac address from efuse */
+	/*
+	 * use efuse mac address for USB ethernet as we know that
+	 * both CPSW and USB ethernet will never be active at the same time
+	 */
 	mac_lo = readl(&cdev->macid0l);
 	mac_hi = readl(&cdev->macid0h);
 	mac_addr[0] = mac_hi & 0xFF;
@@ -665,32 +772,13 @@ int board_eth_init(bd_t *bis)
 	mac_addr[3] = (mac_hi & 0xFF000000) >> 24;
 	mac_addr[4] = mac_lo & 0xFF;
 	mac_addr[5] = (mac_lo & 0xFF00) >> 8;
+#endif
+
 
 #if (defined(CONFIG_DRIVER_TI_CPSW) && !defined(CONFIG_SPL_BUILD)) || \
 	(defined(CONFIG_SPL_ETH_SUPPORT) && defined(CONFIG_SPL_BUILD))
-	if (!getenv("ethaddr")) {
-		printf("<ethaddr> not set. Validating first E-fuse MAC\n");
-
-		if (is_valid_ethaddr(mac_addr))
-			eth_setenv_enetaddr("ethaddr", mac_addr);
-	}
 
 #ifdef CONFIG_DRIVER_TI_CPSW
-
-	mac_lo = readl(&cdev->macid1l);
-	mac_hi = readl(&cdev->macid1h);
-	mac_addr[0] = mac_hi & 0xFF;
-	mac_addr[1] = (mac_hi & 0xFF00) >> 8;
-	mac_addr[2] = (mac_hi & 0xFF0000) >> 16;
-	mac_addr[3] = (mac_hi & 0xFF000000) >> 24;
-	mac_addr[4] = mac_lo & 0xFF;
-	mac_addr[5] = (mac_lo & 0xFF00) >> 8;
-
-	if (!getenv("eth1addr")) {
-		if (is_valid_ethaddr(mac_addr))
-			eth_setenv_enetaddr("eth1addr", mac_addr);
-	}
-
 	if (read_eeprom() < 0)
 		puts("Could not get board ID.\n");
 
diff --git a/cmd/net.c b/cmd/net.c
index b2f3c7b709bc59f7449b86a540faaf78d1cce292..bed76e4bcb0899e5c368d09ddd33ed6873a1b789 100644
--- a/cmd/net.c
+++ b/cmd/net.c
@@ -243,9 +243,6 @@ static int netboot_common(enum proto_t proto, cmd_tbl_t *cmdtp, int argc,
 		return CMD_RET_SUCCESS;
 	}
 
-	/* flush cache */
-	flush_cache(load_addr, size);
-
 	bootstage_mark(BOOTSTAGE_ID_NET_LOADED);
 
 	rcode = bootm_maybe_autostart(cmdtp, argv[0]);
diff --git a/drivers/net/cpsw.c b/drivers/net/cpsw.c
index d17505e08882c4bd46de3ab3a267639026d2e84c..d1f024e0eb3a8da51febb966511a348761d1e6c8 100644
--- a/drivers/net/cpsw.c
+++ b/drivers/net/cpsw.c
@@ -225,6 +225,18 @@ struct cpdma_chan {
 	void			*hdp, *cp, *rxfree;
 };
 
+/* AM33xx SoC specific definitions for the CONTROL port */
+#define AM33XX_GMII_SEL_MODE_MII	0
+#define AM33XX_GMII_SEL_MODE_RMII	1
+#define AM33XX_GMII_SEL_MODE_RGMII	2
+
+#define AM33XX_GMII_SEL_RGMII1_IDMODE	BIT(4)
+#define AM33XX_GMII_SEL_RGMII2_IDMODE	BIT(5)
+#define AM33XX_GMII_SEL_RMII1_IO_CLK_EN	BIT(6)
+#define AM33XX_GMII_SEL_RMII2_IO_CLK_EN	BIT(7)
+
+#define GMII_SEL_MODE_MASK		0x3
+
 #define desc_write(desc, fld, val)	__raw_writel((u32)(val), &(desc)->fld)
 #define desc_read(desc, fld)		__raw_readl(&(desc)->fld)
 #define desc_read_ptr(desc, fld)	((void *)__raw_readl(&(desc)->fld))
@@ -1150,12 +1162,129 @@ static inline fdt_addr_t cpsw_get_addr_by_node(const void *fdt, int node)
 						  false);
 }
 
+static void cpsw_gmii_sel_am3352(struct cpsw_priv *priv,
+				 phy_interface_t phy_mode)
+{
+	u32 reg;
+	u32 mask;
+	u32 mode = 0;
+	bool rgmii_id = false;
+	int slave = priv->data.active_slave;
+
+	reg = readl(priv->data.gmii_sel);
+
+	switch (phy_mode) {
+	case PHY_INTERFACE_MODE_RMII:
+		mode = AM33XX_GMII_SEL_MODE_RMII;
+		break;
+
+	case PHY_INTERFACE_MODE_RGMII:
+		mode = AM33XX_GMII_SEL_MODE_RGMII;
+		break;
+	case PHY_INTERFACE_MODE_RGMII_ID:
+	case PHY_INTERFACE_MODE_RGMII_RXID:
+	case PHY_INTERFACE_MODE_RGMII_TXID:
+		mode = AM33XX_GMII_SEL_MODE_RGMII;
+		rgmii_id = true;
+		break;
+
+	case PHY_INTERFACE_MODE_MII:
+	default:
+		mode = AM33XX_GMII_SEL_MODE_MII;
+		break;
+	};
+
+	mask = GMII_SEL_MODE_MASK << (slave * 2) | BIT(slave + 6);
+	mode <<= slave * 2;
+
+	if (priv->data.rmii_clock_external) {
+		if (slave == 0)
+			mode |= AM33XX_GMII_SEL_RMII1_IO_CLK_EN;
+		else
+			mode |= AM33XX_GMII_SEL_RMII2_IO_CLK_EN;
+	}
+
+	if (rgmii_id) {
+		if (slave == 0)
+			mode |= AM33XX_GMII_SEL_RGMII1_IDMODE;
+		else
+			mode |= AM33XX_GMII_SEL_RGMII2_IDMODE;
+	}
+
+	reg &= ~mask;
+	reg |= mode;
+
+	writel(reg, priv->data.gmii_sel);
+}
+
+static void cpsw_gmii_sel_dra7xx(struct cpsw_priv *priv,
+				 phy_interface_t phy_mode)
+{
+	u32 reg;
+	u32 mask;
+	u32 mode = 0;
+	int slave = priv->data.active_slave;
+
+	reg = readl(priv->data.gmii_sel);
+
+	switch (phy_mode) {
+	case PHY_INTERFACE_MODE_RMII:
+		mode = AM33XX_GMII_SEL_MODE_RMII;
+		break;
+
+	case PHY_INTERFACE_MODE_RGMII:
+	case PHY_INTERFACE_MODE_RGMII_ID:
+	case PHY_INTERFACE_MODE_RGMII_RXID:
+	case PHY_INTERFACE_MODE_RGMII_TXID:
+		mode = AM33XX_GMII_SEL_MODE_RGMII;
+		break;
+
+	case PHY_INTERFACE_MODE_MII:
+	default:
+		mode = AM33XX_GMII_SEL_MODE_MII;
+		break;
+	};
+
+	switch (slave) {
+	case 0:
+		mask = GMII_SEL_MODE_MASK;
+		break;
+	case 1:
+		mask = GMII_SEL_MODE_MASK << 4;
+		mode <<= 4;
+		break;
+	default:
+		dev_err(priv->dev, "invalid slave number...\n");
+		return;
+	}
+
+	if (priv->data.rmii_clock_external)
+		dev_err(priv->dev, "RMII External clock is not supported\n");
+
+	reg &= ~mask;
+	reg |= mode;
+
+	writel(reg, priv->data.gmii_sel);
+}
+
+static void cpsw_phy_sel(struct cpsw_priv *priv, const char *compat,
+			 phy_interface_t phy_mode)
+{
+	if (!strcmp(compat, "ti,am3352-cpsw-phy-sel"))
+		cpsw_gmii_sel_am3352(priv, phy_mode);
+	if (!strcmp(compat, "ti,am43xx-cpsw-phy-sel"))
+		cpsw_gmii_sel_am3352(priv, phy_mode);
+	else if (!strcmp(compat, "ti,dra7xx-cpsw-phy-sel"))
+		cpsw_gmii_sel_dra7xx(priv, phy_mode);
+}
+
 static int cpsw_eth_ofdata_to_platdata(struct udevice *dev)
 {
 	struct eth_pdata *pdata = dev_get_platdata(dev);
 	struct cpsw_priv *priv = dev_get_priv(dev);
 	struct gpio_desc *mode_gpios;
 	const char *phy_mode;
+	const char *phy_sel_compat = NULL;
 	const void *fdt = gd->fdt_blob;
 	int node = dev->of_offset;
 	int subnode;
@@ -1271,6 +1400,17 @@ static int cpsw_eth_ofdata_to_platdata(struct udevice *dev)
 				error("Not able to get gmii_sel reg address\n");
 				return -ENOENT;
 			}
+
+			if (fdt_get_property(fdt, subnode, "rmii-clock-ext",
+					     NULL))
+				priv->data.rmii_clock_external = true;
+
+			phy_sel_compat = fdt_getprop(fdt, subnode, "compatible",
+						     NULL);
+			if (!phy_sel_compat) {
+				error("Not able to get gmii_sel compatible\n");
+				return -ENOENT;
+			}
 		}
 	}
 
@@ -1293,20 +1433,9 @@ static int cpsw_eth_ofdata_to_platdata(struct udevice *dev)
 		debug("%s: Invalid PHY interface '%s'\n", __func__, phy_mode);
 		return -EINVAL;
 	}
-	switch (pdata->phy_interface) {
-	case PHY_INTERFACE_MODE_MII:
-		writel(MII_MODE_ENABLE, priv->data.gmii_sel);
-		break;
-	case PHY_INTERFACE_MODE_RMII:
-		writel(RMII_MODE_ENABLE, priv->data.gmii_sel);
-		break;
-	case PHY_INTERFACE_MODE_RGMII:
-	case PHY_INTERFACE_MODE_RGMII_ID:
-	case PHY_INTERFACE_MODE_RGMII_RXID:
-	case PHY_INTERFACE_MODE_RGMII_TXID:
-		writel(RGMII_MODE_ENABLE, priv->data.gmii_sel);
-		break;
-	}
+
+	/* Select phy interface in control module */
+	cpsw_phy_sel(priv, phy_sel_compat, pdata->phy_interface);
 
 	return 0;
 }
diff --git a/drivers/net/mvneta.c b/drivers/net/mvneta.c
index 51bb569a92d001c837dae0c9874b0d009c6c02e3..00f378f0826aebe1414a0e8139612b3371e92525 100644
--- a/drivers/net/mvneta.c
+++ b/drivers/net/mvneta.c
@@ -1619,7 +1619,7 @@ static int mvneta_probe(struct udevice *dev)
 	/*
 	 * Allocate buffer area for descs and rx_buffers. This is only
 	 * done once for all interfaces. As only one interface can
-	 * be active. Make this area DMA save by disabling the D-cache
+	 * be active. Make this area DMA safe by disabling the D-cache
 	 */
 	if (!buffer_loc.tx_descs) {
 		/* Align buffer area for descs and rx_buffers to 1MiB */
diff --git a/drivers/net/phy/atheros.c b/drivers/net/phy/atheros.c
index e57c4120a3e5b4a55f2b53e110bac70a857a39b8..b34cdd3d87dc02f8a01db2f10e895287790679fb 100644
--- a/drivers/net/phy/atheros.c
+++ b/drivers/net/phy/atheros.c
@@ -8,6 +8,15 @@
  */
 #include <phy.h>
 
+#define AR803x_PHY_DEBUG_ADDR_REG	0x1d
+#define AR803x_PHY_DEBUG_DATA_REG	0x1e
+
+#define AR803x_DEBUG_REG_5		0x5
+#define AR803x_RGMII_TX_CLK_DLY		0x100
+
+#define AR803x_DEBUG_REG_0		0x0
+#define AR803x_RGMII_RX_CLK_DLY		0x8000
+
 static int ar8021_config(struct phy_device *phydev)
 {
 	phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x05);
@@ -17,6 +26,32 @@ static int ar8021_config(struct phy_device *phydev)
 	return 0;
 }
 
+static int ar8031_config(struct phy_device *phydev)
+{
+	if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID ||
+	    phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) {
+		phy_write(phydev, MDIO_DEVAD_NONE, AR803x_PHY_DEBUG_ADDR_REG,
+			  AR803x_DEBUG_REG_5);
+		phy_write(phydev, MDIO_DEVAD_NONE, AR803x_PHY_DEBUG_DATA_REG,
+			  AR803x_RGMII_TX_CLK_DLY);
+	}
+
+	if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID ||
+	    phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) {
+		phy_write(phydev, MDIO_DEVAD_NONE, AR803x_PHY_DEBUG_ADDR_REG,
+			  AR803x_DEBUG_REG_0);
+		phy_write(phydev, MDIO_DEVAD_NONE, AR803x_PHY_DEBUG_DATA_REG,
+			  AR803x_RGMII_RX_CLK_DLY);
+	}
+
+	phydev->supported = phydev->drv->features;
+
+	genphy_config_aneg(phydev);
+	genphy_restart_aneg(phydev);
+
+	return 0;
+}
+
 static int ar8035_config(struct phy_device *phydev)
 {
 	int regval;
@@ -31,6 +66,22 @@ static int ar8035_config(struct phy_device *phydev)
 	regval = phy_read(phydev, MDIO_DEVAD_NONE, 0x1e);
 	phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, (regval|0x0100));
 
+	if ((phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) ||
+	    (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)) {
+		/* select debug reg 5 */
+		phy_write(phydev, MDIO_DEVAD_NONE, 0x1D, 0x5);
+		/* enable tx delay */
+		phy_write(phydev, MDIO_DEVAD_NONE, 0x1E, 0x0100);
+	}
+
+	if ((phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) ||
+	    (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)) {
+		/* select debug reg 0 */
+		phy_write(phydev, MDIO_DEVAD_NONE, 0x1D, 0x0);
+		/* enable rx delay */
+		phy_write(phydev, MDIO_DEVAD_NONE, 0x1E, 0x8000);
+	}
+
 	phydev->supported = phydev->drv->features;
 
 	genphy_config_aneg(phydev);
@@ -54,7 +105,7 @@ static struct phy_driver AR8031_driver =  {
 	.uid = 0x4dd074,
 	.mask = 0xffffffef,
 	.features = PHY_GBIT_FEATURES,
-	.config = ar8035_config,
+	.config = ar8031_config,
 	.startup = genphy_startup,
 	.shutdown = genphy_shutdown,
 };
diff --git a/drivers/net/phy/mv88e61xx.c b/drivers/net/phy/mv88e61xx.c
index 74d56098b5c9823dbdb89c163b3f6552e42cc3a6..a2fd1686fc3b8366aec9ddf7673fee4ee4b9f182 100644
--- a/drivers/net/phy/mv88e61xx.c
+++ b/drivers/net/phy/mv88e61xx.c
@@ -40,7 +40,7 @@
 
 #define PHY_AUTONEGOTIATE_TIMEOUT	5000
 
-#define PORT_COUNT			7
+#define PORT_COUNT			11
 #define PORT_MASK			((1 << PORT_COUNT) - 1)
 
 /* Device addresses */
@@ -103,8 +103,16 @@
 #define PORT_REG_STATUS_CMODE_1000BASE_X	0x9
 #define PORT_REG_STATUS_CMODE_SGMII		0xa
 
+#define PORT_REG_PHYS_CTRL_PCS_AN_EN	BIT(10)
+#define PORT_REG_PHYS_CTRL_PCS_AN_RST	BIT(9)
+#define PORT_REG_PHYS_CTRL_FC_VALUE	BIT(7)
+#define PORT_REG_PHYS_CTRL_FC_FORCE	BIT(6)
 #define PORT_REG_PHYS_CTRL_LINK_VALUE	BIT(5)
 #define PORT_REG_PHYS_CTRL_LINK_FORCE	BIT(4)
+#define PORT_REG_PHYS_CTRL_DUPLEX_VALUE	BIT(3)
+#define PORT_REG_PHYS_CTRL_DUPLEX_FORCE	BIT(2)
+#define PORT_REG_PHYS_CTRL_SPD1000	BIT(1)
+#define PORT_REG_PHYS_CTRL_SPD_MASK	(BIT(1) | BIT(0))
 
 #define PORT_REG_CTRL_PSTATE_SHIFT	0
 #define PORT_REG_CTRL_PSTATE_WIDTH	2
@@ -166,7 +174,17 @@
 #error Define CONFIG_MV88E61XX_CPU_PORT to the port the CPU is attached to
 #endif
 
+/*
+ *  These are ports without PHYs that may be wired directly
+ * to other serdes interfaces
+ */
+#ifndef CONFIG_MV88E61XX_FIXED_PORTS
+#define CONFIG_MV88E61XX_FIXED_PORTS 0
+#endif
+
 /* ID register values for different switch models */
+#define PORT_SWITCH_ID_6096		0x0980
+#define PORT_SWITCH_ID_6097		0x0990
 #define PORT_SWITCH_ID_6172		0x1720
 #define PORT_SWITCH_ID_6176		0x1760
 #define PORT_SWITCH_ID_6240		0x2400
@@ -580,7 +598,7 @@ static int mv88e61xx_port_enable(struct phy_device *phydev, u8 port)
 }
 
 static int mv88e61xx_port_set_vlan(struct phy_device *phydev, u8 port,
-							u8 mask)
+							u16 mask)
 {
 	int val;
 
@@ -791,6 +809,27 @@ static int mv88e61xx_phy_setup(struct phy_device *phydev, u8 phy)
 	return 0;
 }
 
+static int mv88e61xx_fixed_port_setup(struct phy_device *phydev, u8 port)
+{
+	int val;
+
+	val = mv88e61xx_port_read(phydev, port, PORT_REG_PHYS_CTRL);
+	if (val < 0)
+		return val;
+
+	val &= ~(PORT_REG_PHYS_CTRL_SPD_MASK |
+		 PORT_REG_PHYS_CTRL_FC_VALUE);
+	val |= PORT_REG_PHYS_CTRL_PCS_AN_EN |
+	       PORT_REG_PHYS_CTRL_PCS_AN_RST |
+	       PORT_REG_PHYS_CTRL_FC_FORCE |
+	       PORT_REG_PHYS_CTRL_DUPLEX_VALUE |
+	       PORT_REG_PHYS_CTRL_DUPLEX_FORCE |
+	       PORT_REG_PHYS_CTRL_SPD1000;
+
+	return mv88e61xx_port_write(phydev, port, PORT_REG_PHYS_CTRL,
+				   val);
+}
+
 static int mv88e61xx_phy_config_port(struct phy_device *phydev, u8 phy)
 {
 	int val;
@@ -909,6 +948,12 @@ static int mv88e61xx_phy_config(struct phy_device *phydev)
 
 			/* Return success if any PHY succeeds */
 			ret = 0;
+		} else if ((1 << i) & CONFIG_MV88E61XX_FIXED_PORTS) {
+			res = mv88e61xx_fixed_port_setup(phydev, i);
+			if (res < 0) {
+				printf("Error configuring port %i\n", i);
+				continue;
+			}
 		}
 	}
 
@@ -974,9 +1019,21 @@ static struct phy_driver mv88e61xx_driver = {
 	.shutdown = &genphy_shutdown,
 };
 
+static struct phy_driver mv88e609x_driver = {
+	.name = "Marvell MV88E609x",
+	.uid = 0x1410c89,
+	.mask = 0xfffffff0,
+	.features = PHY_GBIT_FEATURES,
+	.probe = mv88e61xx_probe,
+	.config = mv88e61xx_phy_config,
+	.startup = mv88e61xx_phy_startup,
+	.shutdown = &genphy_shutdown,
+};
+
 int phy_mv88e61xx_init(void)
 {
 	phy_register(&mv88e61xx_driver);
+	phy_register(&mv88e609x_driver);
 
 	return 0;
 }
diff --git a/drivers/net/rtl8169.c b/drivers/net/rtl8169.c
index 1cc0b40935c53bff2e4426a4282b7a7a28d8870e..a3f4423a20ca3d7196480b010cba2eb50f23f41f 100644
--- a/drivers/net/rtl8169.c
+++ b/drivers/net/rtl8169.c
@@ -629,11 +629,12 @@ static int rtl_send_common(pci_dev_t dev, unsigned long dev_iobase,
 	/* point to the current txb incase multiple tx_rings are used */
 	ptxb = tpc->Tx_skbuff[entry * MAX_ETH_FRAME_SIZE];
 	memcpy(ptxb, (char *)packet, (int)length);
-	rtl_flush_buffer(ptxb, length);
 
 	while (len < ETH_ZLEN)
 		ptxb[len++] = '\0';
 
+	rtl_flush_buffer(ptxb, ALIGN(len, RTL8169_ALIGN));
+
 	tpc->TxDescArray[entry].buf_Haddr = 0;
 #ifdef CONFIG_DM_ETH
 	tpc->TxDescArray[entry].buf_addr = cpu_to_le32(
diff --git a/drivers/usb/eth/smsc95xx.c b/drivers/usb/eth/smsc95xx.c
index 7d9abfda3be19cc763c232de01c78e9a930f2c83..d4c8ea4a98aa5a44af0956a3418820c1625c5939 100644
--- a/drivers/usb/eth/smsc95xx.c
+++ b/drivers/usb/eth/smsc95xx.c
@@ -519,9 +519,11 @@ static int smsc95xx_init_common(struct usb_device *udev, struct ueth_data *dev,
 		debug("timeout waiting for PHY Reset\n");
 		return -ETIMEDOUT;
 	}
+#ifndef CONFIG_DM_ETH
 	if (!priv->have_hwaddr && smsc95xx_init_mac_address(enetaddr, udev) ==
 			0)
 		priv->have_hwaddr = 1;
+#endif
 	if (!priv->have_hwaddr) {
 		puts("Error: SMSC95xx: No MAC address set - set usbethaddr\n");
 		return -EADDRNOTAVAIL;
@@ -1022,6 +1024,19 @@ int smsc95xx_write_hwaddr(struct udevice *dev)
 	return smsc95xx_write_hwaddr_common(udev, priv, pdata->enetaddr);
 }
 
+int smsc95xx_read_rom_hwaddr(struct udevice *dev)
+{
+	struct usb_device *udev = dev_get_parent_priv(dev);
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	int ret;
+
+	ret = smsc95xx_init_mac_address(pdata->enetaddr, udev);
+	if (ret)
+		memset(pdata->enetaddr, 0, 6);
+
+	return 0;
+}
+
 static int smsc95xx_eth_probe(struct udevice *dev)
 {
 	struct smsc95xx_private *priv = dev_get_priv(dev);
@@ -1037,6 +1052,7 @@ static const struct eth_ops smsc95xx_eth_ops = {
 	.free_pkt = smsc95xx_free_pkt,
 	.stop	= smsc95xx_eth_stop,
 	.write_hwaddr = smsc95xx_write_hwaddr,
+	.read_rom_hwaddr = smsc95xx_read_rom_hwaddr,
 };
 
 U_BOOT_DRIVER(smsc95xx_eth) = {
diff --git a/include/configs/am335x_evm.h b/include/configs/am335x_evm.h
index 272c71b76b6a73fe1e35bb5a5b2b307b2e2d2971..daa7dd8b9f23047f50d4ac42f806d983f694abe7 100644
--- a/include/configs/am335x_evm.h
+++ b/include/configs/am335x_evm.h
@@ -432,6 +432,8 @@
 #define CONFIG_PHY_GIGE
 #define CONFIG_PHYLIB
 #define CONFIG_PHY_SMSC
+/* Enable Atheros phy driver */
+#define CONFIG_PHY_ATHEROS
 
 /*
  * NOR Size = 16 MiB
diff --git a/include/cpsw.h b/include/cpsw.h
index 257d12a08d721eef149a31b466306cc2465774d6..f135e7bfe0cc6425aa567c61414e2d12d59aae80 100644
--- a/include/cpsw.h
+++ b/include/cpsw.h
@@ -48,6 +48,7 @@ struct cpsw_platform_data {
 	void	(*control)(int enabled);
 	u32	host_port_num;
 	u32	active_slave;
+	bool	rmii_clock_external;
 	u8	version;
 };
 
diff --git a/net/eth-uclass.c b/net/eth-uclass.c
index c15cc4d90bf47dffacdd1339077340b0c99dd36a..a32961e6ceaae8e819a247c1f30bac24b3bc370f 100644
--- a/net/eth-uclass.c
+++ b/net/eth-uclass.c
@@ -227,6 +227,7 @@ static int on_ethaddr(const char *name, const char *value, enum env_op op,
 		case env_op_create:
 		case env_op_overwrite:
 			eth_parse_enetaddr(value, pdata->enetaddr);
+			eth_write_hwaddr(dev);
 			break;
 		case env_op_delete:
 			memset(pdata->enetaddr, 0, 6);
diff --git a/test/py/tests/test_net.py b/test/py/tests/test_net.py
index 4ab58b44248a80c6144b3bd5b45374bbb765de4d..0884051614f05942bac58d72da668b977196f769 100644
--- a/test/py/tests/test_net.py
+++ b/test/py/tests/test_net.py
@@ -47,6 +47,15 @@ env__net_tftp_readable_file = {
     "size": 5058624,
     "crc32": "c2244b26",
 }
+
+# Details regarding a file that may be read from a NFS server. This variable
+# may be omitted or set to None if NFS testing is not possible or desired.
+env__net_nfs_readable_file = {
+    "fn": "ubtest-readable.bin",
+    "addr": 0x10000000,
+    "size": 5058624,
+    "crc32": "c2244b26",
+}
 """
 
 net_set_up = False
@@ -157,3 +166,43 @@ def test_net_tftpboot(u_boot_console):
 
     output = u_boot_console.run_command('crc32 %x $filesize' % addr)
     assert expected_crc in output
+
+@pytest.mark.buildconfigspec('cmd_nfs')
+def test_net_nfs(u_boot_console):
+    """Test the nfs command.
+
+    A file is downloaded from the NFS server, its size and optionally its
+    CRC32 are validated.
+
+    The details of the file to download are provided by the boardenv_* file;
+    see the comment at the beginning of this file.
+    """
+
+    if not net_set_up:
+        pytest.skip('Network not initialized')
+
+    f = u_boot_console.config.env.get('env__net_nfs_readable_file', None)
+    if not f:
+        pytest.skip('No NFS readable file to read')
+
+    addr = f.get('addr', None)
+    if not addr:
+        addr = u_boot_utils.find_ram_base(u_boot_console)
+
+    fn = f['fn']
+    output = u_boot_console.run_command('nfs %x %s' % (addr, fn))
+    expected_text = 'Bytes transferred = '
+    sz = f.get('size', None)
+    if sz:
+        expected_text += '%d' % sz
+    assert expected_text in output
+
+    expected_crc = f.get('crc32', None)
+    if not expected_crc:
+        return
+
+    if u_boot_console.config.buildconfig.get('config_cmd_crc32', 'n') != 'y':
+        return
+
+    output = u_boot_console.run_command('crc32 %x $filesize' % addr)
+    assert expected_crc in output