|
@@ -28,6 +28,7 @@
|
|
#include <common.h>
|
|
#include <common.h>
|
|
#include <miiphy.h>
|
|
#include <miiphy.h>
|
|
#include <malloc.h>
|
|
#include <malloc.h>
|
|
|
|
+#include <linux/compiler.h>
|
|
#include <linux/err.h>
|
|
#include <linux/err.h>
|
|
#include <asm/io.h>
|
|
#include <asm/io.h>
|
|
#include "designware.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)
|
|
if (priv->phy_configured != 1)
|
|
configure_phy(dev);
|
|
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 */
|
|
/* Reset ethernet hardware */
|
|
if (mac_reset(dev) < 0)
|
|
if (mac_reset(dev) < 0)
|
|
return -1;
|
|
return -1;
|
|
@@ -168,17 +176,17 @@ static int dw_eth_init(struct eth_device *dev, bd_t *bis)
|
|
|
|
|
|
conf = FRAMEBURSTENABLE | DISABLERXOWN;
|
|
conf = FRAMEBURSTENABLE | DISABLERXOWN;
|
|
|
|
|
|
- if (priv->speed != SPEED_1000M)
|
|
|
|
|
|
+ if (priv->speed != 1000)
|
|
conf |= MII_PORTSELECT;
|
|
conf |= MII_PORTSELECT;
|
|
|
|
|
|
if ((priv->interface != PHY_INTERFACE_MODE_MII) &&
|
|
if ((priv->interface != PHY_INTERFACE_MODE_MII) &&
|
|
(priv->interface != PHY_INTERFACE_MODE_GMII)) {
|
|
(priv->interface != PHY_INTERFACE_MODE_GMII)) {
|
|
|
|
|
|
- if (priv->speed == SPEED_100M)
|
|
|
|
|
|
+ if (priv->speed == 100)
|
|
conf |= FES_100;
|
|
conf |= FES_100;
|
|
}
|
|
}
|
|
|
|
|
|
- if (priv->duplex == FULL_DUPLEX)
|
|
|
|
|
|
+ if (priv->duplex == FULL)
|
|
conf |= FULLDPLXMODE;
|
|
conf |= FULLDPLXMODE;
|
|
|
|
|
|
writel(conf, &mac_p->conf);
|
|
writel(conf, &mac_p->conf);
|
|
@@ -396,6 +404,16 @@ static int dw_reset_phy(struct eth_device *dev)
|
|
return 0;
|
|
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)
|
|
static int configure_phy(struct eth_device *dev)
|
|
{
|
|
{
|
|
struct dw_eth_dev *priv = dev->priv;
|
|
struct dw_eth_dev *priv = dev->priv;
|
|
@@ -405,9 +423,6 @@ static int configure_phy(struct eth_device *dev)
|
|
u16 bmsr;
|
|
u16 bmsr;
|
|
u32 timeout;
|
|
u32 timeout;
|
|
ulong start;
|
|
ulong start;
|
|
- u16 anlpar, btsr;
|
|
|
|
-#else
|
|
|
|
- u16 ctrl;
|
|
|
|
#endif
|
|
#endif
|
|
|
|
|
|
#if defined(CONFIG_DW_SEARCH_PHY)
|
|
#if defined(CONFIG_DW_SEARCH_PHY)
|
|
@@ -419,6 +434,16 @@ static int configure_phy(struct eth_device *dev)
|
|
#else
|
|
#else
|
|
phy_addr = priv->address;
|
|
phy_addr = priv->address;
|
|
#endif
|
|
#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)
|
|
if (dw_reset_phy(dev) < 0)
|
|
return -1;
|
|
return -1;
|
|
|
|
|
|
@@ -444,72 +469,32 @@ static int configure_phy(struct eth_device *dev)
|
|
#if defined(CONFIG_DW_AUTONEG)
|
|
#if defined(CONFIG_DW_AUTONEG)
|
|
timeout = CONFIG_AUTONEG_TIMEOUT;
|
|
timeout = CONFIG_AUTONEG_TIMEOUT;
|
|
start = get_timer(0);
|
|
start = get_timer(0);
|
|
-
|
|
|
|
|
|
+ puts("Waiting for PHY auto negotiation to complete");
|
|
while (get_timer(start) < timeout) {
|
|
while (get_timer(start) < timeout) {
|
|
eth_mdio_read(dev, phy_addr, MII_BMSR, &bmsr);
|
|
eth_mdio_read(dev, phy_addr, MII_BMSR, &bmsr);
|
|
- if (bmsr & BMSR_ANEGCOMPLETE)
|
|
|
|
|
|
+ if (bmsr & BMSR_ANEGCOMPLETE) {
|
|
|
|
+ priv->phy_configured = 1;
|
|
break;
|
|
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
|
|
else
|
|
- priv->speed = SPEED_10M;
|
|
|
|
-#endif
|
|
|
|
|
|
+ puts(" done\n");
|
|
|
|
+#else
|
|
priv->phy_configured = 1;
|
|
priv->phy_configured = 1;
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+ priv->speed = miiphy_speed(dev->name, phy_addr);
|
|
|
|
+ priv->duplex = miiphy_duplex(dev->name, phy_addr);
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
@@ -574,11 +559,6 @@ int designware_initialize(u32 id, ulong base_addr, u32 phy_addr, u32 interface)
|
|
priv->phy_configured = 0;
|
|
priv->phy_configured = 0;
|
|
priv->interface = interface;
|
|
priv->interface = interface;
|
|
|
|
|
|
- if (mac_reset(dev) < 0)
|
|
|
|
- return -1;
|
|
|
|
-
|
|
|
|
- configure_phy(dev);
|
|
|
|
-
|
|
|
|
dev->init = dw_eth_init;
|
|
dev->init = dw_eth_init;
|
|
dev->send = dw_eth_send;
|
|
dev->send = dw_eth_send;
|
|
dev->recv = dw_eth_recv;
|
|
dev->recv = dw_eth_recv;
|