diff --git a/drivers/net/designware.c b/drivers/net/designware.c
index 8f22e00ddd88885ed0260db1d0d41b45e2becdc3..326d550c1f26c7f72e6234ec6774dbc8c0b4a739 100644
--- a/drivers/net/designware.c
+++ b/drivers/net/designware.c
@@ -28,6 +28,7 @@
 #include <common.h>
 #include <miiphy.h>
 #include <malloc.h>
+#include <linux/compiler.h>
 #include <linux/err.h>
 #include <asm/io.h>
 #include "designware.h"
@@ -153,6 +154,13 @@ static int dw_eth_init(struct eth_device *dev, bd_t *bis)
 	if (priv->phy_configured != 1)
 		configure_phy(dev);
 
+	/* Print link status only once */
+	if (!priv->link_printed) {
+		printf("ENET Speed is %d Mbps - %s duplex connection\n",
+		       priv->speed, (priv->duplex == HALF) ? "HALF" : "FULL");
+		priv->link_printed = 1;
+	}
+
 	/* Reset ethernet hardware */
 	if (mac_reset(dev) < 0)
 		return -1;
@@ -168,17 +176,17 @@ static int dw_eth_init(struct eth_device *dev, bd_t *bis)
 
 	conf = FRAMEBURSTENABLE | DISABLERXOWN;
 
-	if (priv->speed != SPEED_1000M)
+	if (priv->speed != 1000)
 		conf |= MII_PORTSELECT;
 
 	if ((priv->interface != PHY_INTERFACE_MODE_MII) &&
 		(priv->interface != PHY_INTERFACE_MODE_GMII)) {
 
-		if (priv->speed == SPEED_100M)
+		if (priv->speed == 100)
 			conf |= FES_100;
 	}
 
-	if (priv->duplex == FULL_DUPLEX)
+	if (priv->duplex == FULL)
 		conf |= FULLDPLXMODE;
 
 	writel(conf, &mac_p->conf);
@@ -396,6 +404,16 @@ static int dw_reset_phy(struct eth_device *dev)
 	return 0;
 }
 
+/*
+ * Add weak default function for board specific PHY configuration
+ */
+int __weak designware_board_phy_init(struct eth_device *dev, int phy_addr,
+		int (*mii_write)(struct eth_device *, u8, u8, u16),
+		int dw_reset_phy(struct eth_device *))
+{
+	return 0;
+}
+
 static int configure_phy(struct eth_device *dev)
 {
 	struct dw_eth_dev *priv = dev->priv;
@@ -405,9 +423,6 @@ static int configure_phy(struct eth_device *dev)
 	u16 bmsr;
 	u32 timeout;
 	ulong start;
-	u16 anlpar, btsr;
-#else
-	u16 ctrl;
 #endif
 
 #if defined(CONFIG_DW_SEARCH_PHY)
@@ -419,6 +434,16 @@ static int configure_phy(struct eth_device *dev)
 #else
 	phy_addr = priv->address;
 #endif
+
+	/*
+	 * Some boards need board specific PHY initialization. This is
+	 * after the main driver init code but before the auto negotiation
+	 * is run.
+	 */
+	if (designware_board_phy_init(dev, phy_addr,
+				      eth_mdio_write, dw_reset_phy) < 0)
+		return -1;
+
 	if (dw_reset_phy(dev) < 0)
 		return -1;
 
@@ -444,72 +469,32 @@ static int configure_phy(struct eth_device *dev)
 #if defined(CONFIG_DW_AUTONEG)
 	timeout = CONFIG_AUTONEG_TIMEOUT;
 	start = get_timer(0);
-
+	puts("Waiting for PHY auto negotiation to complete");
 	while (get_timer(start) < timeout) {
 		eth_mdio_read(dev, phy_addr, MII_BMSR, &bmsr);
-		if (bmsr & BMSR_ANEGCOMPLETE)
+		if (bmsr & BMSR_ANEGCOMPLETE) {
+			priv->phy_configured = 1;
 			break;
-
-		/* Try again after 10usec */
-		udelay(10);
-	};
-
-	eth_mdio_read(dev, phy_addr, MII_LPA, &anlpar);
-	eth_mdio_read(dev, phy_addr, MII_STAT1000, &btsr);
-
-	if (bmsr & BMSR_ANEGCOMPLETE) {
-		if (btsr & PHY_1000BTSR_1000FD) {
-			priv->speed = SPEED_1000M;
-			bmcr |= BMCR_SPEED1000;
-			priv->duplex = FULL_DUPLEX;
-			bmcr |= BMCR_FULLDPLX;
-		} else if (btsr & PHY_1000BTSR_1000HD) {
-			priv->speed = SPEED_1000M;
-			bmcr |= BMCR_SPEED1000;
-			priv->duplex = HALF_DUPLEX;
-			bmcr &= ~BMCR_FULLDPLX;
-		} else if (anlpar & LPA_100FULL) {
-			priv->speed = SPEED_100M;
-			bmcr |= BMCR_SPEED100;
-			priv->duplex = FULL_DUPLEX;
-			bmcr |= BMCR_FULLDPLX;
-		} else if (anlpar & LPA_100HALF) {
-			priv->speed = SPEED_100M;
-			bmcr |= BMCR_SPEED100;
-			priv->duplex = HALF_DUPLEX;
-			bmcr &= ~BMCR_FULLDPLX;
-		} else if (anlpar & LPA_10FULL) {
-			priv->speed = SPEED_10M;
-			bmcr &= ~BMCR_SPEED100;
-			priv->duplex = FULL_DUPLEX;
-			bmcr |= BMCR_FULLDPLX;
-		} else {
-				priv->speed = SPEED_10M;
-				bmcr &= ~BMCR_SPEED100;
-				priv->duplex = HALF_DUPLEX;
-				bmcr &= ~BMCR_FULLDPLX;
 		}
-		if (eth_mdio_write(dev, phy_addr, MII_BMCR, bmcr) < 0)
-			return -1;
-	} else
-		return -1;
-#else
-	if (eth_mdio_read(dev, phy_addr, MII_BMCR, &ctrl) < 0)
-		return -1;
 
-	if (ctrl & BMCR_FULLDPLX)
-		priv->duplex = FULL_DUPLEX;
-	else
-		priv->duplex = HALF_DUPLEX;
+		/* Print dot all 1s to show progress */
+		if ((get_timer(start) % 1000) == 0)
+			putc('.');
+
+		/* Try again after 1msec */
+		udelay(1000);
+	};
 
-	if (ctrl & BMCR_SPEED1000)
-		priv->speed = SPEED_1000M;
-	else if (ctrl & BMCR_SPEED100)
-		priv->speed = SPEED_100M;
+	if (!(bmsr & BMSR_ANEGCOMPLETE))
+		puts(" TIMEOUT!\n");
 	else
-		priv->speed = SPEED_10M;
-#endif
+		puts(" done\n");
+#else
 	priv->phy_configured = 1;
+#endif
+
+	priv->speed = miiphy_speed(dev->name, phy_addr);
+	priv->duplex = miiphy_duplex(dev->name, phy_addr);
 
 	return 0;
 }
@@ -574,11 +559,6 @@ int designware_initialize(u32 id, ulong base_addr, u32 phy_addr, u32 interface)
 	priv->phy_configured = 0;
 	priv->interface = interface;
 
-	if (mac_reset(dev) < 0)
-		return -1;
-
-	configure_phy(dev);
-
 	dev->init = dw_eth_init;
 	dev->send = dw_eth_send;
 	dev->recv = dw_eth_recv;
diff --git a/drivers/net/designware.h b/drivers/net/designware.h
index 40020bf26b8f6f4092d19920b9dc0c08ab0a1fbe..d668f8fbf0eab14a79b90fbd2d316c2a407e9df8 100644
--- a/drivers/net/designware.h
+++ b/drivers/net/designware.h
@@ -240,6 +240,7 @@ struct dw_eth_dev {
 	u32 tx_currdescnum;
 	u32 rx_currdescnum;
 	u32 phy_configured;
+	int link_printed;
 	u32 padding;
 
 	struct dmamacdescr tx_mac_descrtable[CONFIG_TX_DESCR_NUM];
diff --git a/include/configs/spear-common.h b/include/configs/spear-common.h
index 36c2a8b1654c908e5a23c7e0d2616d8c2b58974d..a6d1cfbcb0e74961551c8704ca9190210c88f60e 100644
--- a/include/configs/spear-common.h
+++ b/include/configs/spear-common.h
@@ -38,6 +38,7 @@
 #define CONFIG_NET_MULTI
 #define CONFIG_PHY_RESET_DELAY			10000		/* in usec */
 #define CONFIG_DW_AUTONEG
+#define CONFIG_PHY_GIGE			/* Include GbE speed/duplex detection */
 
 /* USBD driver configuration */
 #if defined(CONFIG_SPEAR_USBTTY)