Merge branch 'master' of git://git.denx.de/u-boot-net
diff --git a/arch/arm/dts/dra72-evm-revc.dts b/arch/arm/dts/dra72-evm-revc.dts
index 5a1bb34..bc814f1 100644
--- a/arch/arm/dts/dra72-evm-revc.dts
+++ b/arch/arm/dts/dra72-evm-revc.dts
@@ -67,7 +67,7 @@
 		ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_25_NS>;
 		ti,tx-internal-delay = <DP83867_RGMIIDCTL_250_PS>;
 		ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_8_B_NIB>;
-		ti,min-output-imepdance;
+		ti,min-output-impedance;
 	};
 
 	dp83867_1: ethernet-phy@3 {
@@ -75,6 +75,6 @@
 		ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_25_NS>;
 		ti,tx-internal-delay = <DP83867_RGMIIDCTL_250_PS>;
 		ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_8_B_NIB>;
-		ti,min-output-imepdance;
+		ti,min-output-impedance;
 	};
 };
diff --git a/common/fdt_support.c b/common/fdt_support.c
index a57a575..55d4d6f 100644
--- a/common/fdt_support.c
+++ b/common/fdt_support.c
@@ -473,7 +473,7 @@
 	char *tmp, *end;
 	char mac[16];
 	const char *path;
-	unsigned char mac_addr[6];
+	unsigned char mac_addr[ARP_HLEN];
 	int offset;
 
 	if (fdt_path_offset(fdt, "/aliases") < 0)
diff --git a/configs/am335x_evm_defconfig b/configs/am335x_evm_defconfig
index ab7b9aa..73df55d 100644
--- a/configs/am335x_evm_defconfig
+++ b/configs/am335x_evm_defconfig
@@ -58,3 +58,4 @@
 CONFIG_G_DNL_PRODUCT_NUM=0xd022
 CONFIG_RSA=y
 CONFIG_SPL_OF_LIBFDT=y
+CONFIG_PHY_MSCC=y
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index f52629f..078d5a8 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -1,3 +1,5 @@
+source "drivers/net/phy/Kconfig"
+
 config DM_ETH
 	bool "Enable Driver Model for Ethernet drivers"
 	depends on DM
@@ -8,32 +10,6 @@
 	  This is currently implemented in net/eth.c
 	  Look in include/net.h for details.
 
-config PHYLIB
-	bool "Ethernet PHY (physical media interface) support"
-	help
-	  Enable Ethernet PHY (physical media interface) support.
-
-config RTL8211X_PHY_FORCE_MASTER
-	bool "Ethernet PHY RTL8211x: force 1000BASE-T master mode"
-	depends on PHYLIB
-	help
-	  Force master mode for 1000BASE-T on RTl8211x PHYs (except for RTL8211F).
-	  This can work around link stability and data corruption issues on gigabit
-	  links which can occur in slave mode on certain PHYs, e.g. on the
-	  RTL8211C(L).
-
-	  Please note that two directly connected devices (i.e. via crossover cable)
-	  will not be able to establish a link between each other if they both force
-	  master mode. Multiple devices forcing master mode when connected by a
-	  network switch do not pose a problem as the switch configures its affected
-	  ports into slave mode.
-
-	  This option only affects gigabit links. If you must establish a direct
-	  connection between two devices which both force master mode, try forcing
-	  the link speed to 100MBit/s.
-
-	  If unsure, say N.
-
 menuconfig NETDEVICES
 	bool "Network device support"
 	depends on NET
@@ -155,6 +131,16 @@
 	  This driver supports the network interface units in the
 	  Marvell ARMADA 375 SoC.
 
+config MACB
+	bool "Cadence MACB/GEM Ethernet Interface"
+	depends on DM_ETH
+	select PHYLIB
+	help
+	  The Cadence MACB ethernet interface is found on many Atmel
+	  AT91 and SAMA5 parts.  This driver also supports the Cadence
+	  GEM (Gigabit Ethernet MAC) found in some ARM SoC devices.
+	  Say Y to include support for the MACB/GEM chip.
+
 config PCH_GBE
 	bool "Intel Platform Controller Hub EG20T GMAC driver"
 	depends on DM_ETH && DM_PCI
diff --git a/drivers/net/designware.c b/drivers/net/designware.c
index eee4e09..f9fb8e0 100644
--- a/drivers/net/designware.c
+++ b/drivers/net/designware.c
@@ -764,6 +764,7 @@
 	{ .compatible = "allwinner,sun7i-a20-gmac" },
 	{ .compatible = "altr,socfpga-stmmac" },
 	{ .compatible = "amlogic,meson6-dwmac" },
+	{ .compatible = "amlogic,meson-gx-dwmac" },
 	{ .compatible = "st,stm32-dwmac" },
 	{ }
 };
diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c
index 5f34c8f..910879b 100644
--- a/drivers/net/fec_mxc.c
+++ b/drivers/net/fec_mxc.c
@@ -1240,7 +1240,6 @@
 	}
 
 	fec_reg_setup(priv);
-	fec_set_dev_name((char *)dev->name, dev_id);
 	priv->dev_id = (dev_id == -1) ? 0 : dev_id;
 
 	return 0;
diff --git a/drivers/net/macb.c b/drivers/net/macb.c
index 452fc3e..1c4bef9 100644
--- a/drivers/net/macb.c
+++ b/drivers/net/macb.c
@@ -4,6 +4,7 @@
  * SPDX-License-Identifier:	GPL-2.0+
  */
 #include <common.h>
+#include <clk.h>
 #include <dm.h>
 
 /*
@@ -112,6 +113,7 @@
 	struct mii_dev		*bus;
 
 #ifdef CONFIG_DM_ETH
+	unsigned long		pclk_rate;
 	phy_interface_t		phy_interface;
 #endif
 };
@@ -754,7 +756,11 @@
 static u32 macb_mdc_clk_div(int id, struct macb_device *macb)
 {
 	u32 config;
+#ifdef CONFIG_DM_ETH
+	unsigned long macb_hz = macb->pclk_rate;
+#else
 	unsigned long macb_hz = get_macb_pclk_rate(id);
+#endif
 
 	if (macb_hz < 20000000)
 		config = MACB_BF(CLK, MACB_CLK_DIV8);
@@ -771,7 +777,12 @@
 static u32 gem_mdc_clk_div(int id, struct macb_device *macb)
 {
 	u32 config;
+
+#ifdef CONFIG_DM_ETH
+	unsigned long macb_hz = macb->pclk_rate;
+#else
 	unsigned long macb_hz = get_macb_pclk_rate(id);
+#endif
 
 	if (macb_hz < 20000000)
 		config = GEM_BF(CLK, GEM_CLK_DIV8);
@@ -991,13 +1002,36 @@
 	.write_hwaddr	= macb_write_hwaddr,
 };
 
+static int macb_enable_clk(struct udevice *dev)
+{
+	struct macb_device *macb = dev_get_priv(dev);
+	struct clk clk;
+	ulong clk_rate;
+	int ret;
+
+	ret = clk_get_by_index(dev, 0, &clk);
+	if (ret)
+		return -EINVAL;
+
+	ret = clk_enable(&clk);
+	if (ret)
+		return ret;
+
+	clk_rate = clk_get_rate(&clk);
+	if (!clk_rate)
+		return -EINVAL;
+
+	macb->pclk_rate = clk_rate;
+
+	return 0;
+}
+
 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;
+	int ret;
 
 	phy_mode = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "phy-mode",
 			       NULL);
@@ -1007,11 +1041,15 @@
 		debug("%s: Invalid PHY interface '%s'\n", __func__, phy_mode);
 		return -EINVAL;
 	}
-#endif
 
 	macb->regs = (void *)pdata->iobase;
 
+	ret = macb_enable_clk(dev);
+	if (ret)
+		return ret;
+
 	_macb_eth_initialize(macb);
+
 #if defined(CONFIG_CMD_MII) || defined(CONFIG_PHYLIB)
 	int retval;
 	struct mii_dev *mdiodev = mdio_alloc();
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
new file mode 100644
index 0000000..1d514e9
--- /dev/null
+++ b/drivers/net/phy/Kconfig
@@ -0,0 +1,93 @@
+
+config BITBANGMII
+	bool "Bit-banged ethernet MII management channel support"
+
+config MV88E6352_SWITCH
+	bool "Marvell 88E6352 switch support"
+
+menuconfig PHYLIB
+	bool "Ethernet PHY (physical media interface) support"
+	help
+	  Enable Ethernet PHY (physical media interface) support.
+
+if PHYLIB
+
+config MV88E61XX_SWITCH
+	bool "Marvel MV88E61xx Ethernet switch PHY support."
+
+config PHYLIB_10G
+	bool "Generic 10G PHY support"
+
+config PHY_AQUANTIA
+	bool "Aquantia Ethernet PHYs support"
+
+config PHY_ATHEROS
+	bool "Atheros Ethernet PHYs support"
+
+config PHY_BROADCOM
+	bool "Broadcom Ethernet PHYs support"
+
+config PHY_CORTINA
+	bool "Cortina Ethernet PHYs support"
+
+config PHY_DAVICOM
+	bool "Davicom Ethernet PHYs support"
+
+config PHY_ET1011C
+	bool "LSI TruePHY ET1011C support"
+
+config PHY_LXT
+	bool "LXT971 Ethernet PHY support"
+
+config PHY_MARVELL
+	bool "Marvell Ethernet PHYs support"
+
+config PHY_MICREL
+	bool "Micrel Ethernet PHYs support"
+
+config PHY_MSCC
+	bool "Microsemi Corp Ethernet PHYs support"
+
+config PHY_NATSEMI
+	bool "National Semiconductor Ethernet PHYs support"
+
+config PHY_REALTEK
+	bool "Realtek Ethernet PHYs support"
+
+config RTL8211X_PHY_FORCE_MASTER
+	bool "Ethernet PHY RTL8211x: force 1000BASE-T master mode"
+	depends on PHY_REALTEK
+	help
+	  Force master mode for 1000BASE-T on RTl8211x PHYs (except for RTL8211F).
+	  This can work around link stability and data corruption issues on gigabit
+	  links which can occur in slave mode on certain PHYs, e.g. on the
+	  RTL8211C(L).
+
+	  Please note that two directly connected devices (i.e. via crossover cable)
+	  will not be able to establish a link between each other if they both force
+	  master mode. Multiple devices forcing master mode when connected by a
+	  network switch do not pose a problem as the switch configures its affected
+	  ports into slave mode.
+
+	  This option only affects gigabit links. If you must establish a direct
+	  connection between two devices which both force master mode, try forcing
+	  the link speed to 100MBit/s.
+
+	  If unsure, say N.
+
+config PHY_SMSC
+	bool  "Microchip(SMSC) Ethernet PHYs support"
+
+config PHY_TERANETICS
+	bool "Teranetics Ethernet PHYs support"
+
+config PHY_TI
+	bool "Texas Instruments Ethernet PHYs support"
+
+config PHY_VITESSE
+	bool "Vitesse Ethernet PHYs support"
+
+config PHY_XILINX
+	bool "Xilinx Ethernet PHYs support"
+
+endif #PHYLIB
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index 1e299b9..d372971 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -27,3 +27,4 @@
 obj-$(CONFIG_PHY_TI) += ti.o
 obj-$(CONFIG_PHY_XILINX) += xilinx_phy.o
 obj-$(CONFIG_PHY_VITESSE) += vitesse.o
+obj-$(CONFIG_PHY_MSCC) += mscc.o
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
index c3058a4..ab0c443 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c
@@ -82,6 +82,21 @@
 #define MIIM_88E1310_PHY_RGMII_CTRL	21
 #define MIIM_88E1310_PHY_PAGE		22
 
+/* 88E151x PHY defines */
+/* Page 3 registers */
+#define MIIM_88E151x_LED_FUNC_CTRL	16
+#define MIIM_88E151x_LED_FLD_SZ		4
+#define MIIM_88E151x_LED0_OFFS		(0 * MIIM_88E151x_LED_FLD_SZ)
+#define MIIM_88E151x_LED1_OFFS		(1 * MIIM_88E151x_LED_FLD_SZ)
+#define MIIM_88E151x_LED0_ACT		3
+#define MIIM_88E151x_LED1_100_1000_LINK	6
+#define MIIM_88E151x_LED_TIMER_CTRL	18
+#define MIIM_88E151x_INT_EN_OFFS	7
+/* Page 18 registers */
+#define MIIM_88E151x_GENERAL_CTRL	20
+#define MIIM_88E151x_MODE_SGMII		1
+#define MIIM_88E151x_RESET_OFFS		15
+
 /* Marvell 88E1011S */
 static int m88e1011s_config(struct phy_device *phydev)
 {
@@ -177,10 +192,7 @@
 {
 	int reg;
 
-	if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) ||
-			(phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) ||
-			(phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) ||
-			(phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)) {
+	if (phy_interface_is_rgmii(phydev)) {
 		reg = phy_read(phydev,
 			MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_CR);
 		if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) ||
@@ -289,7 +301,7 @@
 	 */
 
 	/* EEE initialization */
-	phy_write(phydev, MDIO_DEVAD_NONE, 22, 0x00ff);
+	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x00ff);
 	phy_write(phydev, MDIO_DEVAD_NONE, 17, 0x214B);
 	phy_write(phydev, MDIO_DEVAD_NONE, 16, 0x2144);
 	phy_write(phydev, MDIO_DEVAD_NONE, 17, 0x0C28);
@@ -298,21 +310,23 @@
 	phy_write(phydev, MDIO_DEVAD_NONE, 16, 0x214D);
 	phy_write(phydev, MDIO_DEVAD_NONE, 17, 0xCC0C);
 	phy_write(phydev, MDIO_DEVAD_NONE, 16, 0x2159);
-	phy_write(phydev, MDIO_DEVAD_NONE, 22, 0x0000);
+	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x0000);
 
 	/* SGMII-to-Copper mode initialization */
 	if (phydev->interface == PHY_INTERFACE_MODE_SGMII) {
 		/* Select page 18 */
-		phy_write(phydev, MDIO_DEVAD_NONE, 22, 18);
+		phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 18);
 
 		/* In reg 20, write MODE[2:0] = 0x1 (SGMII to Copper) */
-		m88e1518_phy_writebits(phydev, 20, 0, 3, 1);
+		m88e1518_phy_writebits(phydev, MIIM_88E151x_GENERAL_CTRL,
+				       0, 3, MIIM_88E151x_MODE_SGMII);
 
 		/* PHY reset is necessary after changing MODE[2:0] */
-		m88e1518_phy_writebits(phydev, 20, 15, 1, 1);
+		m88e1518_phy_writebits(phydev, MIIM_88E151x_GENERAL_CTRL,
+				       MIIM_88E151x_RESET_OFFS, 1, 1);
 
 		/* Reset page selection */
-		phy_write(phydev, MDIO_DEVAD_NONE, 22, 0);
+		phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0);
 
 		udelay(100);
 	}
@@ -324,17 +338,25 @@
 static int m88e1510_config(struct phy_device *phydev)
 {
 	/* Select page 3 */
-	phy_write(phydev, MDIO_DEVAD_NONE, 22, 3);
+	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE,
+		  MIIM_88E1118_PHY_LED_PAGE);
 
 	/* Enable INTn output on LED[2] */
-	m88e1518_phy_writebits(phydev, 18, 7, 1, 1);
+	m88e1518_phy_writebits(phydev, MIIM_88E151x_LED_TIMER_CTRL,
+			       MIIM_88E151x_INT_EN_OFFS, 1, 1);
 
 	/* Configure LEDs */
-	m88e1518_phy_writebits(phydev, 16, 0, 4, 3); /* LED[0]:0011 (ACT) */
-	m88e1518_phy_writebits(phydev, 16, 4, 4, 6); /* LED[1]:0110 (LINK) */
+	/* LED[0]:0011 (ACT) */
+	m88e1518_phy_writebits(phydev, MIIM_88E151x_LED_FUNC_CTRL,
+			       MIIM_88E151x_LED0_OFFS, MIIM_88E151x_LED_FLD_SZ,
+			       MIIM_88E151x_LED0_ACT);
+	/* LED[1]:0110 (LINK 100/1000 Mbps) */
+	m88e1518_phy_writebits(phydev, MIIM_88E151x_LED_FUNC_CTRL,
+			       MIIM_88E151x_LED1_OFFS, MIIM_88E151x_LED_FLD_SZ,
+			       MIIM_88E151x_LED1_100_1000_LINK);
 
 	/* Reset page selection */
-	phy_write(phydev, MDIO_DEVAD_NONE, 22, 0);
+	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0);
 
 	return m88e1518_config(phydev);
 }
@@ -596,17 +618,22 @@
 static struct phy_driver M88E1510_driver = {
 	.name = "Marvell 88E1510",
 	.uid = 0x1410dd0,
-	.mask = 0xffffff0,
+	.mask = 0xfffffff,
 	.features = PHY_GBIT_FEATURES,
 	.config = &m88e1510_config,
 	.startup = &m88e1011s_startup,
 	.shutdown = &genphy_shutdown,
 };
 
+/*
+ * This supports:
+ *  88E1518, uid 0x1410dd1
+ *  88E1512, uid 0x1410dd4
+ */
 static struct phy_driver M88E1518_driver = {
 	.name = "Marvell 88E1518",
-	.uid = 0x1410dd1,
-	.mask = 0xffffff0,
+	.uid = 0x1410dd0,
+	.mask = 0xffffffa,
 	.features = PHY_GBIT_FEATURES,
 	.config = &m88e1518_config,
 	.startup = &m88e1011s_startup,
diff --git a/drivers/net/phy/mscc.c b/drivers/net/phy/mscc.c
new file mode 100644
index 0000000..439f5e3
--- /dev/null
+++ b/drivers/net/phy/mscc.c
@@ -0,0 +1,508 @@
+/*
+ * Microsemi PHY drivers
+ *
+ * SPDX-License-Identifier: The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Microsemi Corporation
+ *
+ * Author: John Haechten
+ *
+ */
+
+#include <miiphy.h>
+#include <bitfield.h>
+
+/* Microsemi PHY ID's */
+#define PHY_ID_VSC8530                  0x00070560
+#define PHY_ID_VSC8531                  0x00070570
+#define PHY_ID_VSC8540                  0x00070760
+#define PHY_ID_VSC8541                  0x00070770
+
+/* Microsemi VSC85xx PHY Register Pages */
+#define MSCC_EXT_PAGE_ACCESS            31     /* Page Access Register */
+#define MSCC_PHY_PAGE_STD		0x0000 /* Standard registers */
+#define MSCC_PHY_PAGE_EXT1		0x0001 /* Extended registers - page 1 */
+#define MSCC_PHY_PAGE_EXT2		0x0002 /* Extended registers - page 2 */
+#define MSCC_PHY_PAGE_EXT3		0x0003 /* Extended registers - page 3 */
+#define MSCC_PHY_PAGE_EXT4		0x0004 /* Extended registers - page 4 */
+#define MSCC_PHY_PAGE_GPIO		0x0010 /* GPIO registers */
+#define MSCC_PHY_PAGE_TEST		0x2A30 /* TEST Page registers */
+#define MSCC_PHY_PAGE_TR		0x52B5 /* Token Ring Page registers */
+
+/* Std Page Register 28 - PHY AUX Control/Status */
+#define MIIM_AUX_CNTRL_STAT_REG		28
+#define MIIM_AUX_CNTRL_STAT_ACTIPHY_TO	(0x0004)
+#define MIIM_AUX_CNTRL_STAT_F_DUPLEX	(0x0020)
+#define MIIM_AUX_CNTRL_STAT_SPEED_MASK	(0x0018)
+#define MIIM_AUX_CNTRL_STAT_SPEED_POS	(3)
+#define MIIM_AUX_CNTRL_STAT_SPEED_10M	(0x0)
+#define MIIM_AUX_CNTRL_STAT_SPEED_100M	(0x1)
+#define MIIM_AUX_CNTRL_STAT_SPEED_1000M	(0x2)
+
+/* Std Page Register 23 - Extended PHY CTRL_1 */
+#define MSCC_PHY_EXT_PHY_CNTL_1_REG	23
+#define MAC_IF_SELECTION_MASK		(0x1800)
+#define MAC_IF_SELECTION_GMII		(0)
+#define MAC_IF_SELECTION_RMII		(1)
+#define MAC_IF_SELECTION_RGMII		(2)
+#define MAC_IF_SELECTION_POS		(11)
+#define MAC_IF_SELECTION_WIDTH		(2)
+
+/* Extended Page 2 Register 20E2 */
+#define MSCC_PHY_RGMII_CNTL_REG		20
+#define VSC_FAST_LINK_FAIL2_ENA_MASK	(0x8000)
+#define RX_CLK_OUT_MASK			(0x0800)
+#define RX_CLK_OUT_POS			(11)
+#define RX_CLK_OUT_WIDTH		(1)
+#define RX_CLK_OUT_NORMAL		(0)
+#define RX_CLK_OUT_DISABLE		(1)
+#define RGMII_RX_CLK_DELAY_POS		(4)
+#define RGMII_RX_CLK_DELAY_WIDTH	(3)
+#define RGMII_RX_CLK_DELAY_MASK		(0x0070)
+#define RGMII_TX_CLK_DELAY_POS		(0)
+#define RGMII_TX_CLK_DELAY_WIDTH	(3)
+#define RGMII_TX_CLK_DELAY_MASK		(0x0007)
+
+/* Extended Page 2 Register 27E2 */
+#define MSCC_PHY_WOL_MAC_CONTROL	27
+#define EDGE_RATE_CNTL_POS		(5)
+#define EDGE_RATE_CNTL_WIDTH		(3)
+#define EDGE_RATE_CNTL_MASK		(0x00E0)
+#define RMII_CLK_OUT_ENABLE_POS		(4)
+#define RMII_CLK_OUT_ENABLE_WIDTH	(1)
+#define RMII_CLK_OUT_ENABLE_MASK	(0x10)
+
+/* Token Ring Page 0x52B5 Registers */
+#define MSCC_PHY_REG_TR_ADDR_16		16
+#define MSCC_PHY_REG_TR_DATA_17		17
+#define MSCC_PHY_REG_TR_DATA_18		18
+
+/* Token Ring - Read Value in */
+#define MSCC_PHY_TR_16_READ		(0xA000)
+/* Token Ring - Write Value out */
+#define MSCC_PHY_TR_16_WRITE		(0x8000)
+
+/* Token Ring Registers */
+#define MSCC_PHY_TR_LINKDETCTRL_POS	(3)
+#define MSCC_PHY_TR_LINKDETCTRL_WIDTH	(2)
+#define MSCC_PHY_TR_LINKDETCTRL_VAL	(3)
+#define MSCC_PHY_TR_LINKDETCTRL_MASK	(0x0018)
+#define MSCC_PHY_TR_LINKDETCTRL_ADDR	(0x07F8)
+
+#define MSCC_PHY_TR_VGATHRESH100_POS	(0)
+#define MSCC_PHY_TR_VGATHRESH100_WIDTH	(7)
+#define MSCC_PHY_TR_VGATHRESH100_VAL	(0x0018)
+#define MSCC_PHY_TR_VGATHRESH100_MASK	(0x007f)
+#define MSCC_PHY_TR_VGATHRESH100_ADDR	(0x0FA4)
+
+#define MSCC_PHY_TR_VGAGAIN10_U_POS	(0)
+#define MSCC_PHY_TR_VGAGAIN10_U_WIDTH	(1)
+#define MSCC_PHY_TR_VGAGAIN10_U_MASK	(0x0001)
+#define MSCC_PHY_TR_VGAGAIN10_U_VAL	(0)
+
+#define MSCC_PHY_TR_VGAGAIN10_L_POS	(12)
+#define MSCC_PHY_TR_VGAGAIN10_L_WIDTH	(4)
+#define MSCC_PHY_TR_VGAGAIN10_L_MASK	(0xf000)
+#define MSCC_PHY_TR_VGAGAIN10_L_VAL	(0x0001)
+#define MSCC_PHY_TR_VGAGAIN10_ADDR	(0x0F92)
+
+/* General Timeout Values */
+#define MSCC_PHY_RESET_TIMEOUT		(100)
+#define MSCC_PHY_MICRO_TIMEOUT		(500)
+
+/* RGMII/GMII Clock Delay (Skew) Options */ enum vsc_phy_rgmii_skew {
+	VSC_PHY_RGMII_DELAY_200_PS,
+	VSC_PHY_RGMII_DELAY_800_PS,
+	VSC_PHY_RGMII_DELAY_1100_PS,
+	VSC_PHY_RGMII_DELAY_1700_PS,
+	VSC_PHY_RGMII_DELAY_2000_PS,
+	VSC_PHY_RGMII_DELAY_2300_PS,
+	VSC_PHY_RGMII_DELAY_2600_PS,
+	VSC_PHY_RGMII_DELAY_3400_PS,
+};
+
+/* MAC i/f Clock Edge Rage Control (Slew), See Reg27E2  */ enum
+vsc_phy_clk_slew {
+	VSC_PHY_CLK_SLEW_RATE_0,
+	VSC_PHY_CLK_SLEW_RATE_1,
+	VSC_PHY_CLK_SLEW_RATE_2,
+	VSC_PHY_CLK_SLEW_RATE_3,
+	VSC_PHY_CLK_SLEW_RATE_4,
+	VSC_PHY_CLK_SLEW_RATE_5,
+	VSC_PHY_CLK_SLEW_RATE_6,
+	VSC_PHY_CLK_SLEW_RATE_7,
+};
+
+
+static int mscc_vsc8531_vsc8541_init_scripts(struct phy_device *phydev)
+{
+	u16	reg_val;
+
+	/* Set to Access Token Ring Registers */
+	phy_write(phydev, MDIO_DEVAD_NONE,
+		  MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_TR);
+
+	/* Update LinkDetectCtrl default to optimized values */
+	/* Determined during Silicon Validation Testing */
+	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
+		  (MSCC_PHY_TR_LINKDETCTRL_ADDR | MSCC_PHY_TR_16_READ));
+	reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17);
+	reg_val = bitfield_replace(reg_val, MSCC_PHY_TR_LINKDETCTRL_POS,
+				   MSCC_PHY_TR_LINKDETCTRL_WIDTH,
+				   MSCC_PHY_TR_LINKDETCTRL_VAL);
+
+	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17, reg_val);
+	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
+		  (MSCC_PHY_TR_LINKDETCTRL_ADDR | MSCC_PHY_TR_16_WRITE));
+
+	/* Update VgaThresh100 defaults to optimized values */
+	/* Determined during Silicon Validation Testing */
+	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
+		  (MSCC_PHY_TR_VGATHRESH100_ADDR | MSCC_PHY_TR_16_READ));
+
+	reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18);
+	reg_val = bitfield_replace(reg_val, MSCC_PHY_TR_VGATHRESH100_POS,
+				   MSCC_PHY_TR_VGATHRESH100_WIDTH,
+				   MSCC_PHY_TR_VGATHRESH100_VAL);
+
+	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18, reg_val);
+	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
+		  (MSCC_PHY_TR_VGATHRESH100_ADDR | MSCC_PHY_TR_16_WRITE));
+
+	/* Update VgaGain10 defaults to optimized values */
+	/* Determined during Silicon Validation Testing */
+	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
+		  (MSCC_PHY_TR_VGAGAIN10_ADDR | MSCC_PHY_TR_16_READ));
+
+	reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18);
+	reg_val = bitfield_replace(reg_val, MSCC_PHY_TR_VGAGAIN10_U_POS,
+				   MSCC_PHY_TR_VGAGAIN10_U_WIDTH,
+				   MSCC_PHY_TR_VGAGAIN10_U_VAL);
+
+	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18, reg_val);
+	reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17);
+	reg_val = bitfield_replace(reg_val, MSCC_PHY_TR_VGAGAIN10_L_POS,
+				   MSCC_PHY_TR_VGAGAIN10_L_WIDTH,
+				   MSCC_PHY_TR_VGAGAIN10_L_VAL);
+
+	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17, reg_val);
+	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
+		  (MSCC_PHY_TR_VGAGAIN10_ADDR | MSCC_PHY_TR_16_WRITE));
+
+	/* Set back to Access Standard Page Registers */
+	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
+		  MSCC_PHY_PAGE_STD);
+
+	return 0;
+}
+
+static int mscc_parse_status(struct phy_device *phydev)
+{
+	u16 speed;
+	u16 mii_reg;
+
+	mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_AUX_CNTRL_STAT_REG);
+
+	if (mii_reg & MIIM_AUX_CNTRL_STAT_F_DUPLEX)
+		phydev->duplex = DUPLEX_FULL;
+	else
+		phydev->duplex = DUPLEX_HALF;
+
+	speed = mii_reg & MIIM_AUX_CNTRL_STAT_SPEED_MASK;
+	speed = speed >> MIIM_AUX_CNTRL_STAT_SPEED_POS;
+
+	switch (speed) {
+	case MIIM_AUX_CNTRL_STAT_SPEED_1000M:
+		phydev->speed = SPEED_1000;
+		break;
+	case MIIM_AUX_CNTRL_STAT_SPEED_100M:
+		phydev->speed = SPEED_100;
+		break;
+	case MIIM_AUX_CNTRL_STAT_SPEED_10M:
+		phydev->speed = SPEED_10;
+		break;
+	default:
+		phydev->speed = SPEED_10;
+		break;
+	}
+
+	return 0;
+}
+
+static int mscc_startup(struct phy_device *phydev)
+{
+	int retval;
+
+	retval = genphy_update_link(phydev);
+
+	if (retval)
+		return retval;
+
+	return mscc_parse_status(phydev);
+}
+
+static int mscc_phy_soft_reset(struct phy_device *phydev)
+{
+	int     retval = 0;
+	u16     timeout = MSCC_PHY_RESET_TIMEOUT;
+	u16     reg_val = 0;
+
+	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
+		  MSCC_PHY_PAGE_STD);
+
+	reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
+	phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, (reg_val | BMCR_RESET));
+
+	reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
+
+	while ((reg_val & BMCR_RESET) && (timeout > 0)) {
+		reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
+		timeout--;
+		udelay(1000);   /* 1 ms */
+	}
+
+	if (timeout == 0) {
+		printf("MSCC PHY Soft_Reset Error: mac i/f = 0x%x\n",
+		       phydev->interface);
+		retval = -ETIME;
+	}
+
+	return retval;
+}
+
+static int vsc8531_vsc8541_mac_config(struct phy_device *phydev)
+{
+	u16	reg_val = 0;
+	u16	mac_if = 0;
+	u16	rx_clk_out = 0;
+
+	/* For VSC8530/31 the only MAC modes are RMII/RGMII. */
+	/* For VSC8540/41 the only MAC modes are (G)MII and RMII/RGMII. */
+	/* Setup MAC Configuration */
+	switch (phydev->interface) {
+	case PHY_INTERFACE_MODE_MII:
+	case PHY_INTERFACE_MODE_GMII:
+		/* Set Reg23.12:11=0 */
+		mac_if = MAC_IF_SELECTION_GMII;
+		/* Set Reg20E2.11=1 */
+		rx_clk_out = RX_CLK_OUT_DISABLE;
+		break;
+
+	case PHY_INTERFACE_MODE_RMII:
+		/* Set Reg23.12:11=1 */
+		mac_if = MAC_IF_SELECTION_RMII;
+		/* Set Reg20E2.11=0 */
+		rx_clk_out = RX_CLK_OUT_NORMAL;
+		break;
+
+	case PHY_INTERFACE_MODE_RGMII:
+		/* Set Reg23.12:11=2 */
+		mac_if = MAC_IF_SELECTION_RGMII;
+		/* Set Reg20E2.11=0 */
+		rx_clk_out = RX_CLK_OUT_NORMAL;
+		break;
+
+	default:
+		printf("MSCC PHY - INVALID MAC i/f Config: mac i/f = 0x%x\n",
+		       phydev->interface);
+		return -EINVAL;
+	}
+
+	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
+		  MSCC_PHY_PAGE_STD);
+
+	reg_val = phy_read(phydev, MDIO_DEVAD_NONE,
+			   MSCC_PHY_EXT_PHY_CNTL_1_REG);
+	/* Set MAC i/f bits Reg23.12:11 */
+	reg_val = bitfield_replace(reg_val, MAC_IF_SELECTION_POS,
+				   MAC_IF_SELECTION_WIDTH, mac_if);
+	/* Update Reg23.12:11 */
+	phy_write(phydev, MDIO_DEVAD_NONE,
+		  MSCC_PHY_EXT_PHY_CNTL_1_REG, reg_val);
+	/* Setup ExtPg_2 Register Access */
+	phy_write(phydev, MDIO_DEVAD_NONE,
+		  MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_EXT2);
+	/* Read Reg20E2 */
+	reg_val = phy_read(phydev, MDIO_DEVAD_NONE,
+			   MSCC_PHY_RGMII_CNTL_REG);
+	reg_val = bitfield_replace(reg_val, RX_CLK_OUT_POS,
+				   RX_CLK_OUT_WIDTH, rx_clk_out);
+	/* Update Reg20E2.11 */
+	phy_write(phydev, MDIO_DEVAD_NONE,
+		  MSCC_PHY_RGMII_CNTL_REG, reg_val);
+	/* Before leaving - Change back to Std Page Register Access */
+	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
+		  MSCC_PHY_PAGE_STD);
+
+	return 0;
+}
+
+static int vsc8531_config(struct phy_device *phydev)
+{
+	int  retval = -EINVAL;
+	u16  reg_val;
+	u16  rmii_clk_out;
+	enum vsc_phy_rgmii_skew  rx_clk_skew = VSC_PHY_RGMII_DELAY_1700_PS;
+	enum vsc_phy_rgmii_skew  tx_clk_skew = VSC_PHY_RGMII_DELAY_800_PS;
+	enum vsc_phy_clk_slew    edge_rate = VSC_PHY_CLK_SLEW_RATE_4;
+
+	/* For VSC8530/31 and VSC8540/41 the init scripts are the same */
+	mscc_vsc8531_vsc8541_init_scripts(phydev);
+
+	/* For VSC8530/31 the only MAC modes are RMII/RGMII. */
+	switch (phydev->interface) {
+	case PHY_INTERFACE_MODE_RMII:
+	case PHY_INTERFACE_MODE_RGMII:
+		retval = vsc8531_vsc8541_mac_config(phydev);
+		if (retval != 0)
+			return retval;
+
+		retval = mscc_phy_soft_reset(phydev);
+		if (retval != 0)
+			return retval;
+		break;
+	default:
+		printf("PHY 8530/31 MAC i/f Config Error: mac i/f = 0x%x\n",
+		       phydev->interface);
+		return -EINVAL;
+	}
+	/* Default RMII Clk Output to 0=OFF/1=ON  */
+	rmii_clk_out = 0;
+
+	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
+		  MSCC_PHY_PAGE_EXT2);
+	reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG);
+
+	/* Reg20E2 - Update RGMII RX_Clk Skews. */
+	reg_val = bitfield_replace(reg_val, RGMII_RX_CLK_DELAY_POS,
+				   RGMII_RX_CLK_DELAY_WIDTH, rx_clk_skew);
+	/* Reg20E2 - Update RGMII TX_Clk Skews. */
+	reg_val = bitfield_replace(reg_val, RGMII_TX_CLK_DELAY_POS,
+				   RGMII_TX_CLK_DELAY_WIDTH, tx_clk_skew);
+
+	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG, reg_val);
+
+	reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_WOL_MAC_CONTROL);
+	/* Reg27E2 - Update Clk Slew Rate. */
+	reg_val = bitfield_replace(reg_val, EDGE_RATE_CNTL_POS,
+				   EDGE_RATE_CNTL_WIDTH, edge_rate);
+	/* Reg27E2 - Update RMII Clk Out. */
+	reg_val = bitfield_replace(reg_val, RMII_CLK_OUT_ENABLE_POS,
+				   RMII_CLK_OUT_ENABLE_WIDTH, rmii_clk_out);
+	/* Update Reg27E2 */
+	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_WOL_MAC_CONTROL, reg_val);
+	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
+		  MSCC_PHY_PAGE_STD);
+
+	return genphy_config_aneg(phydev);
+}
+
+static int vsc8541_config(struct phy_device *phydev)
+{
+	int  retval = -EINVAL;
+	u16  reg_val;
+	u16  rmii_clk_out;
+	enum vsc_phy_rgmii_skew  rx_clk_skew = VSC_PHY_RGMII_DELAY_1700_PS;
+	enum vsc_phy_rgmii_skew  tx_clk_skew = VSC_PHY_RGMII_DELAY_800_PS;
+	enum vsc_phy_clk_slew    edge_rate = VSC_PHY_CLK_SLEW_RATE_4;
+
+	/* For VSC8530/31 and VSC8540/41 the init scripts are the same */
+	mscc_vsc8531_vsc8541_init_scripts(phydev);
+
+	/* For VSC8540/41 the only MAC modes are (G)MII and RMII/RGMII. */
+	switch (phydev->interface) {
+	case PHY_INTERFACE_MODE_MII:
+	case PHY_INTERFACE_MODE_GMII:
+	case PHY_INTERFACE_MODE_RMII:
+	case PHY_INTERFACE_MODE_RGMII:
+		retval = vsc8531_vsc8541_mac_config(phydev);
+		if (retval != 0)
+			return retval;
+
+		retval = mscc_phy_soft_reset(phydev);
+		if (retval != 0)
+			return retval;
+		break;
+	default:
+		printf("PHY 8541 MAC i/f config Error: mac i/f = 0x%x\n",
+		       phydev->interface);
+		return -EINVAL;
+	}
+	/* Default RMII Clk Output to 0=OFF/1=ON  */
+	rmii_clk_out = 0;
+
+	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
+		  MSCC_PHY_PAGE_EXT2);
+	reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG);
+	/* Reg20E2 - Update RGMII RX_Clk Skews. */
+	reg_val = bitfield_replace(reg_val, RGMII_RX_CLK_DELAY_POS,
+				   RGMII_RX_CLK_DELAY_WIDTH, rx_clk_skew);
+	/* Reg20E2 - Update RGMII TX_Clk Skews. */
+	reg_val = bitfield_replace(reg_val, RGMII_TX_CLK_DELAY_POS,
+				   RGMII_TX_CLK_DELAY_WIDTH, tx_clk_skew);
+	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG, reg_val);
+
+	reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_WOL_MAC_CONTROL);
+	/* Reg27E2 - Update Clk Slew Rate. */
+	reg_val = bitfield_replace(reg_val, EDGE_RATE_CNTL_POS,
+				   EDGE_RATE_CNTL_WIDTH, edge_rate);
+	/* Reg27E2 - Update RMII Clk Out. */
+	reg_val = bitfield_replace(reg_val, RMII_CLK_OUT_ENABLE_POS,
+				   RMII_CLK_OUT_ENABLE_WIDTH, rmii_clk_out);
+	/* Update Reg27E2 */
+	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_WOL_MAC_CONTROL, reg_val);
+	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
+		  MSCC_PHY_PAGE_STD);
+
+	return genphy_config_aneg(phydev);
+}
+
+static struct phy_driver VSC8530_driver = {
+	.name = "Microsemi VSC8530",
+	.uid = PHY_ID_VSC8530,
+	.mask = 0x000ffff0,
+	.features = PHY_BASIC_FEATURES,
+	.config = &vsc8531_config,
+	.startup = &mscc_startup,
+	.shutdown = &genphy_shutdown,
+};
+
+static struct phy_driver VSC8531_driver = {
+	.name = "Microsemi VSC8531",
+	.uid = PHY_ID_VSC8531,
+	.mask = 0x000ffff0,
+	.features = PHY_GBIT_FEATURES,
+	.config = &vsc8531_config,
+	.startup = &mscc_startup,
+	.shutdown = &genphy_shutdown,
+};
+
+static struct phy_driver VSC8540_driver = {
+	.name = "Microsemi VSC8540",
+	.uid = PHY_ID_VSC8540,
+	.mask = 0x000ffff0,
+	.features = PHY_BASIC_FEATURES,
+	.config = &vsc8541_config,
+	.startup = &mscc_startup,
+	.shutdown = &genphy_shutdown,
+};
+
+static struct phy_driver VSC8541_driver = {
+	.name = "Microsemi VSC8541",
+	.uid = PHY_ID_VSC8541,
+	.mask = 0x000ffff0,
+	.features = PHY_GBIT_FEATURES,
+	.config = &vsc8541_config,
+	.startup = &mscc_startup,
+	.shutdown = &genphy_shutdown,
+};
+
+int phy_mscc_init(void)
+{
+	phy_register(&VSC8530_driver);
+	phy_register(&VSC8531_driver);
+	phy_register(&VSC8540_driver);
+	phy_register(&VSC8541_driver);
+
+	return 0;
+}
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 80bdfb6..8db6574 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -512,6 +512,9 @@
 #ifdef CONFIG_PHY_XILINX
 	phy_xilinx_init();
 #endif
+#ifdef CONFIG_PHY_MSCC
+	phy_mscc_init();
+#endif
 
 	return 0;
 }
diff --git a/drivers/net/phy/ti.c b/drivers/net/phy/ti.c
index d1ce406..1d87080 100644
--- a/drivers/net/phy/ti.c
+++ b/drivers/net/phy/ti.c
@@ -27,6 +27,7 @@
 /* Extended Registers */
 #define DP83867_RGMIICTL	0x0032
 #define DP83867_RGMIIDCTL	0x0086
+#define DP83867_IO_MUX_CFG	0x0170
 
 #define DP83867_SW_RESET	BIT(15)
 #define DP83867_SW_RESTART	BIT(14)
@@ -84,10 +85,17 @@
 #define DEFAULT_TX_ID_DELAY	DP83867_RGMIIDCTL_2_75_NS
 #define DEFAULT_FIFO_DEPTH	DP83867_PHYCR_FIFO_DEPTH_4_B_NIB
 
+/* IO_MUX_CFG bits */
+#define DP83867_IO_MUX_CFG_IO_IMPEDANCE_CTRL	0x1f
+
+#define DP83867_IO_MUX_CFG_IO_IMPEDANCE_MAX	0x0
+#define DP83867_IO_MUX_CFG_IO_IMPEDANCE_MIN	0x1f
+
 struct dp83867_private {
 	int rx_id_delay;
 	int tx_id_delay;
 	int fifo_depth;
+	int io_impedance;
 };
 
 /**
@@ -166,6 +174,15 @@
 {
 	struct dp83867_private *dp83867 = phydev->priv;
 	struct udevice *dev = phydev->dev;
+	int node = dev->of_offset;
+	const void *fdt = gd->fdt_blob;
+
+	if (fdtdec_get_bool(fdt, node, "ti,max-output-impedance"))
+		dp83867->io_impedance = DP83867_IO_MUX_CFG_IO_IMPEDANCE_MAX;
+	else if (fdtdec_get_bool(fdt, node, "ti,min-output-impedance"))
+		dp83867->io_impedance = DP83867_IO_MUX_CFG_IO_IMPEDANCE_MIN;
+	else
+		dp83867->io_impedance = -EINVAL;
 
 	dp83867->rx_id_delay = fdtdec_get_uint(gd->fdt_blob, dev_of_offset(dev),
 				 "ti,rx-internal-delay", -1);
@@ -186,6 +203,7 @@
 	dp83867->rx_id_delay = DEFAULT_RX_ID_DELAY;
 	dp83867->tx_id_delay = DEFAULT_TX_ID_DELAY;
 	dp83867->fifo_depth = DEFAULT_FIFO_DEPTH;
+	dp83867->io_impedance = -EINVAL;
 
 	return 0;
 }
@@ -246,8 +264,7 @@
 		phy_write(phydev, MDIO_DEVAD_NONE, MII_DP83867_BISCR, 0x0);
 	}
 
-	if ((phydev->interface >= PHY_INTERFACE_MODE_RGMII_ID) &&
-	    (phydev->interface <= PHY_INTERFACE_MODE_RGMII_RXID)) {
+	if (phy_interface_is_rgmii(phydev)) {
 		val = phy_read_mmd_indirect(phydev, DP83867_RGMIICTL,
 					    DP83867_DEVADDR, phydev->addr);
 
@@ -269,6 +286,19 @@
 
 		phy_write_mmd_indirect(phydev, DP83867_RGMIIDCTL,
 				       DP83867_DEVADDR, phydev->addr, delay);
+
+		if (dp83867->io_impedance >= 0) {
+			val = phy_read_mmd_indirect(phydev,
+						    DP83867_IO_MUX_CFG,
+						    DP83867_DEVADDR,
+						    phydev->addr);
+			val &= ~DP83867_IO_MUX_CFG_IO_IMPEDANCE_CTRL;
+			val |= dp83867->io_impedance &
+			       DP83867_IO_MUX_CFG_IO_IMPEDANCE_CTRL;
+			phy_write_mmd_indirect(phydev, DP83867_IO_MUX_CFG,
+					       DP83867_DEVADDR, phydev->addr,
+					       val);
+		}
 	}
 
 	genphy_config_aneg(phydev);
diff --git a/drivers/net/phy/vitesse.c b/drivers/net/phy/vitesse.c
index a077b98..e5e9922 100644
--- a/drivers/net/phy/vitesse.c
+++ b/drivers/net/phy/vitesse.c
@@ -127,9 +127,7 @@
 
 	genphy_config_aneg(phydev);
 
-	if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) ||
-			(phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) ||
-			(phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID))
+	if (phy_interface_is_rgmii(phydev))
 		phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS8204_EPHY_CON,
 				MIIM_CIS8204_EPHYCON_INIT |
 				MIIM_CIS8204_EPHYCON_RGMII);
diff --git a/include/net.h b/include/net.h
index 1f4d947..ed5259a 100644
--- a/include/net.h
+++ b/include/net.h
@@ -38,6 +38,14 @@
 
 #define PKTALIGN	ARCH_DMA_MINALIGN
 
+/* ARP hardware address length */
+#define ARP_HLEN 6
+/*
+ * The size of a MAC address in string form, each digit requires two chars
+ * and five separator characters to form '00:00:00:00:00:00'.
+ */
+#define ARP_HLEN_ASCII (ARP_HLEN * 2) + (ARP_HLEN - 1)
+
 /* IPv4 addresses are always 32 bits in size */
 struct in_addr {
 	__be32 s_addr;
@@ -90,7 +98,7 @@
  */
 struct eth_pdata {
 	phys_addr_t iobase;
-	unsigned char enetaddr[6];
+	unsigned char enetaddr[ARP_HLEN];
 	int phy_interface;
 	int max_speed;
 };
@@ -160,8 +168,9 @@
 
 #ifndef CONFIG_DM_ETH
 struct eth_device {
-	char name[16];
-	unsigned char enetaddr[6];
+#define ETH_NAME_LEN 16
+	char name[ETH_NAME_LEN];
+	unsigned char enetaddr[ARP_HLEN];
 	phys_addr_t iobase;
 	int state;
 
@@ -300,9 +309,9 @@
  */
 
 struct ethernet_hdr {
-	u8		et_dest[6];	/* Destination node		*/
-	u8		et_src[6];	/* Source node			*/
-	u16		et_protlen;	/* Protocol or length		*/
+	u8		et_dest[ARP_HLEN];	/* Destination node	*/
+	u8		et_src[ARP_HLEN];	/* Source node		*/
+	u16		et_protlen;		/* Protocol or length	*/
 };
 
 /* Ethernet header size */
@@ -311,16 +320,16 @@
 #define ETH_FCS_LEN	4		/* Octets in the FCS		*/
 
 struct e802_hdr {
-	u8		et_dest[6];	/* Destination node		*/
-	u8		et_src[6];	/* Source node			*/
-	u16		et_protlen;	/* Protocol or length		*/
-	u8		et_dsap;	/* 802 DSAP			*/
-	u8		et_ssap;	/* 802 SSAP			*/
-	u8		et_ctl;		/* 802 control			*/
-	u8		et_snap1;	/* SNAP				*/
+	u8		et_dest[ARP_HLEN];	/* Destination node	*/
+	u8		et_src[ARP_HLEN];	/* Source node		*/
+	u16		et_protlen;		/* Protocol or length	*/
+	u8		et_dsap;		/* 802 DSAP		*/
+	u8		et_ssap;		/* 802 SSAP		*/
+	u8		et_ctl;			/* 802 control		*/
+	u8		et_snap1;		/* SNAP			*/
 	u8		et_snap2;
 	u8		et_snap3;
-	u16		et_prot;	/* 802 protocol			*/
+	u16		et_prot;		/* 802 protocol		*/
 };
 
 /* 802 + SNAP + ethernet header size */
@@ -330,11 +339,11 @@
  *	Virtual LAN Ethernet header
  */
 struct vlan_ethernet_hdr {
-	u8		vet_dest[6];	/* Destination node		*/
-	u8		vet_src[6];	/* Source node			*/
-	u16		vet_vlan_type;	/* PROT_VLAN			*/
-	u16		vet_tag;	/* TAG of VLAN			*/
-	u16		vet_type;	/* protocol type		*/
+	u8		vet_dest[ARP_HLEN];	/* Destination node	*/
+	u8		vet_src[ARP_HLEN];	/* Source node		*/
+	u16		vet_vlan_type;		/* PROT_VLAN		*/
+	u16		vet_tag;		/* TAG of VLAN		*/
+	u16		vet_type;		/* protocol type	*/
 };
 
 /* VLAN Ethernet header size */
@@ -405,7 +414,6 @@
 #   define ARP_ETHER	    1		/* Ethernet  hardware address	*/
 	u16		ar_pro;		/* Format of protocol address	*/
 	u8		ar_hln;		/* Length of hardware address	*/
-#   define ARP_HLEN	6
 	u8		ar_pln;		/* Length of protocol address	*/
 #   define ARP_PLEN	4
 	u16		ar_op;		/* Operation			*/
@@ -514,16 +522,16 @@
 extern char	net_hostname[32];	/* Our hostname */
 extern char	net_root_path[64];	/* Our root path */
 /** END OF BOOTP EXTENTIONS **/
-extern u8		net_ethaddr[6];		/* Our ethernet address */
-extern u8		net_server_ethaddr[6];	/* Boot server enet address */
+extern u8		net_ethaddr[ARP_HLEN];		/* Our ethernet address */
+extern u8		net_server_ethaddr[ARP_HLEN];	/* Boot server enet address */
 extern struct in_addr	net_ip;		/* Our    IP addr (0 = unknown) */
 extern struct in_addr	net_server_ip;	/* Server IP addr (0 = unknown) */
 extern uchar		*net_tx_packet;		/* THE transmit packet */
 extern uchar		*net_rx_packets[PKTBUFSRX]; /* Receive packets */
 extern uchar		*net_rx_packet;		/* Current receive packet */
 extern int		net_rx_packet_len;	/* Current rx packet length */
-extern const u8		net_bcast_ethaddr[6];	/* Ethernet broadcast address */
-extern const u8		net_null_ethaddr[6];
+extern const u8		net_bcast_ethaddr[ARP_HLEN];	/* Ethernet broadcast address */
+extern const u8		net_null_ethaddr[ARP_HLEN];
 
 #define VLAN_NONE	4095			/* untagged */
 #define VLAN_IDMASK	0x0fff			/* mask of valid vlan id */
@@ -562,9 +570,9 @@
  */
 static inline int is_cdp_packet(const uchar *ethaddr)
 {
-	extern const u8 net_cdp_ethaddr[6];
+	extern const u8 net_cdp_ethaddr[ARP_HLEN];
 
-	return memcmp(ethaddr, net_cdp_ethaddr, 6) == 0;
+	return memcmp(ethaddr, net_cdp_ethaddr, ARP_HLEN) == 0;
 }
 #endif
 
diff --git a/include/phy.h b/include/phy.h
index 268d9a1..5477496 100644
--- a/include/phy.h
+++ b/include/phy.h
@@ -266,6 +266,7 @@
 int phy_ti_init(void);
 int phy_vitesse_init(void);
 int phy_xilinx_init(void);
+int phy_mscc_init(void);
 
 int board_phy_config(struct phy_device *phydev);
 int get_phy_id(struct mii_dev *bus, int addr, int devad, u32 *phy_id);
diff --git a/include/u-boot/crc.h b/include/u-boot/crc.h
index 754ac72..6764d58 100644
--- a/include/u-boot/crc.h
+++ b/include/u-boot/crc.h
@@ -9,6 +9,9 @@
 #ifndef _UBOOT_CRC_H
 #define _UBOOT_CRC_H
 
+/* lib/crc8.c */
+unsigned int crc8(unsigned int crc_start, const unsigned char *vptr, int len);
+
 /* lib/crc32.c */
 uint32_t crc32 (uint32_t, const unsigned char *, uint);
 uint32_t crc32_wd (uint32_t, const unsigned char *, uint, uint);
diff --git a/net/eth-uclass.c b/net/eth-uclass.c
index 1d13011..c3cc315 100644
--- a/net/eth-uclass.c
+++ b/net/eth-uclass.c
@@ -230,7 +230,7 @@
 			eth_write_hwaddr(dev);
 			break;
 		case env_op_delete:
-			memset(pdata->enetaddr, 0, 6);
+			memset(pdata->enetaddr, 0, ARP_HLEN);
 		}
 	}
 
@@ -458,7 +458,7 @@
 {
 	struct eth_device_priv *priv = dev->uclass_priv;
 	struct eth_pdata *pdata = dev->platdata;
-	unsigned char env_enetaddr[6];
+	unsigned char env_enetaddr[ARP_HLEN];
 
 #if defined(CONFIG_NEEDS_MANUAL_RELOC)
 	struct eth_ops *ops = eth_get_ops(dev);
@@ -497,17 +497,17 @@
 	eth_getenv_enetaddr_by_index("eth", dev->seq, env_enetaddr);
 	if (!is_zero_ethaddr(env_enetaddr)) {
 		if (!is_zero_ethaddr(pdata->enetaddr) &&
-		    memcmp(pdata->enetaddr, env_enetaddr, 6)) {
+		    memcmp(pdata->enetaddr, env_enetaddr, ARP_HLEN)) {
 			printf("\nWarning: %s MAC addresses don't match:\n",
 			       dev->name);
-			printf("Address in SROM is         %pM\n",
+			printf("Address in ROM is          %pM\n",
 			       pdata->enetaddr);
 			printf("Address in environment is  %pM\n",
 			       env_enetaddr);
 		}
 
 		/* Override the ROM MAC address */
-		memcpy(pdata->enetaddr, env_enetaddr, 6);
+		memcpy(pdata->enetaddr, env_enetaddr, ARP_HLEN);
 	} else if (is_valid_ethaddr(pdata->enetaddr)) {
 		eth_setenv_enetaddr_by_index("eth", dev->seq, pdata->enetaddr);
 		printf("\nWarning: %s using MAC address from ROM\n",
@@ -535,7 +535,7 @@
 	eth_get_ops(dev)->stop(dev);
 
 	/* clear the MAC address */
-	memset(pdata->enetaddr, 0, 6);
+	memset(pdata->enetaddr, 0, ARP_HLEN);
 
 	return 0;
 }
diff --git a/net/eth_common.c b/net/eth_common.c
index 2880901..e9d3c66 100644
--- a/net/eth_common.c
+++ b/net/eth_common.c
@@ -32,7 +32,7 @@
 
 int eth_setenv_enetaddr(const char *name, const uchar *enetaddr)
 {
-	char buf[20];
+	char buf[ARP_HLEN_ASCII + 1];
 
 	sprintf(buf, "%pM", enetaddr);
 
diff --git a/net/eth_legacy.c b/net/eth_legacy.c
index 1354f49..e4bd0f4 100644
--- a/net/eth_legacy.c
+++ b/net/eth_legacy.c
@@ -121,7 +121,7 @@
 				eth_write_hwaddr(dev, "eth", dev->index);
 				break;
 			case env_op_delete:
-				memset(dev->enetaddr, 0, 6);
+				memset(dev->enetaddr, 0, ARP_HLEN);
 			}
 		}
 		dev = dev->next;
@@ -134,14 +134,14 @@
 int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
 		   int eth_number)
 {
-	unsigned char env_enetaddr[6];
+	unsigned char env_enetaddr[ARP_HLEN];
 	int ret = 0;
 
 	eth_getenv_enetaddr_by_index(base_name, eth_number, env_enetaddr);
 
 	if (!is_zero_ethaddr(env_enetaddr)) {
 		if (!is_zero_ethaddr(dev->enetaddr) &&
-		    memcmp(dev->enetaddr, env_enetaddr, 6)) {
+		    memcmp(dev->enetaddr, env_enetaddr, ARP_HLEN)) {
 			printf("\nWarning: %s MAC addresses don't match:\n",
 			       dev->name);
 			printf("Address in SROM is         %pM\n",
@@ -150,7 +150,7 @@
 			       env_enetaddr);
 		}
 
-		memcpy(dev->enetaddr, env_enetaddr, 6);
+		memcpy(dev->enetaddr, env_enetaddr, ARP_HLEN);
 	} else if (is_valid_ethaddr(dev->enetaddr)) {
 		eth_setenv_enetaddr_by_index(base_name, eth_number,
 					     dev->enetaddr);
@@ -299,7 +299,7 @@
  */
 int eth_mcast_join(struct in_addr mcast_ip, int join)
 {
-	u8 mcast_mac[6];
+	u8 mcast_mac[ARP_HLEN];
 	if (!eth_current || !eth_current->mcast)
 		return -1;
 	mcast_mac[5] = htonl(mcast_ip.s_addr) & 0xff;
diff --git a/tools/.gitignore b/tools/.gitignore
index cb1e722..0d1f076 100644
--- a/tools/.gitignore
+++ b/tools/.gitignore
@@ -6,6 +6,7 @@
 /fit_check_sign
 /fit_info
 /gen_eth_addr
+/gen_ethaddr_crc
 /ifdtool
 /img2srec
 /kwboot
diff --git a/tools/Makefile b/tools/Makefile
index cbccd4a..5000f4d 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -42,6 +42,10 @@
 hostprogs-$(CONFIG_CMD_NET) += gen_eth_addr
 HOSTCFLAGS_gen_eth_addr.o := -pedantic
 
+hostprogs-$(CONFIG_CMD_NET) += gen_ethaddr_crc
+gen_ethaddr_crc-objs := gen_ethaddr_crc.o lib/crc8.o
+HOSTCFLAGS_gen_ethaddr_crc.o := -pedantic
+
 hostprogs-$(CONFIG_CMD_LOADS) += img2srec
 HOSTCFLAGS_img2srec.o := -pedantic
 
@@ -195,6 +199,7 @@
 # that won't build on some weird host compiler -- though there are lots of
 # exceptions for files that aren't complaint.
 HOSTCFLAGS_crc32.o := -pedantic
+HOSTCFLAGS_crc8.o := -pedantic
 HOSTCFLAGS_md5.o := -pedantic
 HOSTCFLAGS_sha1.o := -pedantic
 HOSTCFLAGS_sha256.o := -pedantic
diff --git a/tools/gen_ethaddr_crc.c b/tools/gen_ethaddr_crc.c
new file mode 100644
index 0000000..fe9896d
--- /dev/null
+++ b/tools/gen_ethaddr_crc.c
@@ -0,0 +1,75 @@
+/*
+ * (C) Copyright 2016
+ * Olliver Schinagl <oliver@schinagl.nl>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <ctype.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <u-boot/crc.h>
+
+#define ARP_HLEN 6 /* Length of hardware address */
+#define ARP_HLEN_ASCII (ARP_HLEN * 2) + (ARP_HLEN - 1) /* with separators */
+#define ARP_HLEN_LAZY (ARP_HLEN * 2) /* separatorless hardware address length */
+
+uint8_t nibble_to_hex(const char *nibble, bool lo)
+{
+	return (strtol(nibble, NULL, 16) << (lo ? 0 : 4)) & (lo ? 0x0f : 0xf0);
+}
+
+int process_mac(const char *mac_address)
+{
+	uint8_t ethaddr[ARP_HLEN + 1] = { 0x00 };
+	uint_fast8_t i = 0;
+
+	while (*mac_address != '\0') {
+		char nibble[2] = { 0x00, '\n' }; /* for strtol */
+
+		nibble[0] = *mac_address++;
+		if (isxdigit(nibble[0])) {
+			if (isupper(nibble[0]))
+				nibble[0] = tolower(nibble[0]);
+			ethaddr[i >> 1] |= nibble_to_hex(nibble, (i % 2) != 0);
+			i++;
+		}
+	}
+
+	for (i = 0; i < ARP_HLEN; i++)
+		printf("%.2x", ethaddr[i]);
+	printf("%.2x\n", crc8(0, ethaddr, ARP_HLEN));
+
+	return 0;
+}
+
+void print_usage(char *cmdname)
+{
+	printf("Usage: %s <mac_address>\n", cmdname);
+	puts("<mac_address> may be with or without separators.");
+	puts("Valid seperators are ':' and '-'.");
+	puts("<mac_address> digits are in base 16.\n");
+}
+
+int main(int argc, char *argv[])
+{
+	if (argc < 2) {
+		print_usage(argv[0]);
+		return 1;
+	}
+
+	if (!((strlen(argv[1]) == ARP_HLEN_ASCII) || (strlen(argv[1]) == ARP_HLEN_LAZY))) {
+		puts("The MAC address is not valid.\n");
+		print_usage(argv[0]);
+		return 1;
+	}
+
+	if (process_mac(argv[1])) {
+		puts("Failed to calculate the MAC's checksum.");
+		return 1;
+	}
+
+	return 0;
+}