diff --git a/drivers/net/designware.c b/drivers/net/designware.c index 8f22e00ddd..326d550c1f 100644 --- a/drivers/net/designware.c +++ b/drivers/net/designware.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #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); + /* Print dot all 1s to show progress */ + if ((get_timer(start) % 1000) == 0) + putc('.'); + + /* Try again after 1msec */ + udelay(1000); }; - 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; + if (!(bmsr & BMSR_ANEGCOMPLETE)) + puts(" TIMEOUT!\n"); + else + puts(" done\n"); #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; - - if (ctrl & BMCR_SPEED1000) - priv->speed = SPEED_1000M; - else if (ctrl & BMCR_SPEED100) - priv->speed = SPEED_100M; - else - priv->speed = SPEED_10M; -#endif 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 40020bf26b..d668f8fbf0 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 36c2a8b165..a6d1cfbcb0 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)