diff options
author | Wolfgang Denk <wd@denx.de> | 2012-04-09 17:10:01 +0200 |
---|---|---|
committer | Wolfgang Denk <wd@denx.de> | 2012-04-09 17:10:01 +0200 |
commit | 2c734cd932b53b46e9f89e4f5db9360afc459ae6 (patch) | |
tree | c8992dba1b7bfc79ed7248b692d50facbe1b2dc3 /drivers/net/designware.c | |
parent | 691288e14dc5cccc9ff1219765554981f73a7c14 (diff) | |
parent | cafabe1995af20d02a000a984ae38693a6f9b900 (diff) | |
download | u-boot-imx-2c734cd932b53b46e9f89e4f5db9360afc459ae6.zip u-boot-imx-2c734cd932b53b46e9f89e4f5db9360afc459ae6.tar.gz u-boot-imx-2c734cd932b53b46e9f89e4f5db9360afc459ae6.tar.bz2 |
Merge branch 'master' of git://git.denx.de/u-boot-net
* 'master' of git://git.denx.de/u-boot-net:
net/designware: Change timeout loop implementation
net/designware: Set ANAR to 0x1e1
net/designware: Program phy registers when auto-negotiation is ON
net/designware: Try configuring phy on each dw_eth_init
net/designware: Consecutive writes must have delay
net/designware: Phy address fix
net/designware: Fix the max frame length size
net/designware: Fix to restore hw mac address
microblaze: Wire up LL_TEMAC driver initialization
microblaze: Add faked LL_TEMAC driver configuration
microblaze: Enable several ethernet driver compilation
net: ll_temac: Add LL TEMAC driver to u-boot
Update net subsystem maintainer in doc/git-mailrc
net/eth.c: fix eth_write_hwaddr() to use dev->enetaddr as fall back
mvgbe: remove warning for unused methods
Diffstat (limited to 'drivers/net/designware.c')
-rw-r--r-- | drivers/net/designware.c | 128 |
1 files changed, 90 insertions, 38 deletions
diff --git a/drivers/net/designware.c b/drivers/net/designware.c index 1e34436..e8e669b 100644 --- a/drivers/net/designware.c +++ b/drivers/net/designware.c @@ -32,6 +32,8 @@ #include <asm/io.h> #include "designware.h" +static int configure_phy(struct eth_device *dev); + static void tx_descs_init(struct eth_device *dev) { struct dw_eth_dev *priv = dev->priv; @@ -106,16 +108,20 @@ static int mac_reset(struct eth_device *dev) struct eth_mac_regs *mac_p = priv->mac_regs_p; struct eth_dma_regs *dma_p = priv->dma_regs_p; + ulong start; int timeout = CONFIG_MACRESET_TIMEOUT; writel(DMAMAC_SRST, &dma_p->busmode); writel(MII_PORTSELECT, &mac_p->conf); - do { + start = get_timer(0); + while (get_timer(start) < timeout) { if (!(readl(&dma_p->busmode) & DMAMAC_SRST)) return 0; - udelay(1000); - } while (timeout--); + + /* Try again after 10usec */ + udelay(10); + }; return -1; } @@ -144,10 +150,16 @@ static int dw_eth_init(struct eth_device *dev, bd_t *bis) struct eth_dma_regs *dma_p = priv->dma_regs_p; u32 conf; + if (priv->phy_configured != 1) + configure_phy(dev); + /* Reset ethernet hardware */ if (mac_reset(dev) < 0) return -1; + /* Resore the HW MAC address as it has been lost during MAC reset */ + dw_write_hwaddr(dev); + writel(FIXEDBURST | PRIORXTX_41 | BURST_16, &dma_p->busmode); @@ -172,8 +184,7 @@ static int dw_eth_init(struct eth_device *dev, bd_t *bis) writel(readl(&dma_p->opmode) | RXSTART, &dma_p->opmode); writel(readl(&dma_p->opmode) | TXSTART, &dma_p->opmode); - writel(readl(&mac_p->conf) | RXENABLE, &mac_p->conf); - writel(readl(&mac_p->conf) | TXENABLE, &mac_p->conf); + writel(readl(&mac_p->conf) | RXENABLE | TXENABLE, &mac_p->conf); return 0; } @@ -266,6 +277,7 @@ static int eth_mdio_read(struct eth_device *dev, u8 addr, u8 reg, u16 *val) { struct dw_eth_dev *priv = dev->priv; struct eth_mac_regs *mac_p = priv->mac_regs_p; + ulong start; u32 miiaddr; int timeout = CONFIG_MDIO_TIMEOUT; @@ -274,13 +286,16 @@ static int eth_mdio_read(struct eth_device *dev, u8 addr, u8 reg, u16 *val) writel(miiaddr | MII_CLKRANGE_150_250M | MII_BUSY, &mac_p->miiaddr); - do { + start = get_timer(0); + while (get_timer(start) < timeout) { if (!(readl(&mac_p->miiaddr) & MII_BUSY)) { *val = readl(&mac_p->miidata); return 0; } - udelay(1000); - } while (timeout--); + + /* Try again after 10usec */ + udelay(10); + }; return -1; } @@ -289,6 +304,7 @@ static int eth_mdio_write(struct eth_device *dev, u8 addr, u8 reg, u16 val) { struct dw_eth_dev *priv = dev->priv; struct eth_mac_regs *mac_p = priv->mac_regs_p; + ulong start; u32 miiaddr; int ret = -1, timeout = CONFIG_MDIO_TIMEOUT; u16 value; @@ -299,11 +315,16 @@ static int eth_mdio_write(struct eth_device *dev, u8 addr, u8 reg, u16 val) writel(miiaddr | MII_CLKRANGE_150_250M | MII_BUSY, &mac_p->miiaddr); - do { - if (!(readl(&mac_p->miiaddr) & MII_BUSY)) + start = get_timer(0); + while (get_timer(start) < timeout) { + if (!(readl(&mac_p->miiaddr) & MII_BUSY)) { ret = 0; - udelay(1000); - } while (timeout--); + break; + } + + /* Try again after 10usec */ + udelay(10); + }; /* Needed as a fix for ST-Phy */ eth_mdio_read(dev, addr, reg, &value); @@ -344,18 +365,23 @@ static int dw_reset_phy(struct eth_device *dev) { struct dw_eth_dev *priv = dev->priv; u16 ctrl; + ulong start; int timeout = CONFIG_PHYRESET_TIMEOUT; u32 phy_addr = priv->address; eth_mdio_write(dev, phy_addr, MII_BMCR, BMCR_RESET); - do { + + start = get_timer(0); + while (get_timer(start) < timeout) { eth_mdio_read(dev, phy_addr, MII_BMCR, &ctrl); if (!(ctrl & BMCR_RESET)) break; - udelay(1000); - } while (timeout--); - if (timeout < 0) + /* Try again after 10usec */ + udelay(10); + }; + + if (get_timer(start) >= CONFIG_PHYRESET_TIMEOUT) return -1; #ifdef CONFIG_PHY_RESET_DELAY @@ -372,6 +398,7 @@ static int configure_phy(struct eth_device *dev) #if defined(CONFIG_DW_AUTONEG) u16 bmsr; u32 timeout; + ulong start; u16 anlpar, btsr; #else u16 ctrl; @@ -379,7 +406,7 @@ static int configure_phy(struct eth_device *dev) #if defined(CONFIG_DW_SEARCH_PHY) phy_addr = find_phy(dev); - if (phy_addr > 0) + if (phy_addr >= 0) priv->address = phy_addr; else return -1; @@ -390,8 +417,10 @@ static int configure_phy(struct eth_device *dev) return -1; #if defined(CONFIG_DW_AUTONEG) - bmcr = BMCR_ANENABLE | BMCR_ANRESTART | BMCR_SPEED100 | \ - BMCR_FULLDPLX | BMCR_SPEED1000; + /* Set Auto-Neg Advertisement capabilities to 10/100 half/full */ + eth_mdio_write(dev, phy_addr, MII_ADVERTISE, 0x1E1); + + bmcr = BMCR_ANENABLE | BMCR_ANRESTART; #else bmcr = BMCR_SPEED100 | BMCR_FULLDPLX; @@ -408,33 +437,56 @@ static int configure_phy(struct eth_device *dev) /* Read the phy status register and populate priv structure */ #if defined(CONFIG_DW_AUTONEG) timeout = CONFIG_AUTONEG_TIMEOUT; - do { + start = get_timer(0); + + while (get_timer(start) < timeout) { eth_mdio_read(dev, phy_addr, MII_BMSR, &bmsr); if (bmsr & BMSR_ANEGCOMPLETE) break; - udelay(1000); - } while (timeout--); + + /* 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 (btsr & (PHY_1000BTSR_1000FD | PHY_1000BTSR_1000HD)) { - priv->speed = SPEED_1000M; - if (btsr & PHY_1000BTSR_1000FD) + if (bmsr & BMSR_ANEGCOMPLETE) { + if (btsr & PHY_1000BTSR_1000FD) { + priv->speed = SPEED_1000M; + bmcr |= BMCR_SPEED1000; priv->duplex = FULL_DUPLEX; - else + bmcr |= BMCR_FULLDPLX; + } else if (btsr & PHY_1000BTSR_1000HD) { + priv->speed = SPEED_1000M; + bmcr |= BMCR_SPEED1000; priv->duplex = HALF_DUPLEX; - } else { - if (anlpar & LPA_100) + bmcr &= ~BMCR_FULLDPLX; + } else if (anlpar & LPA_100FULL) { priv->speed = SPEED_100M; - else - priv->speed = SPEED_10M; - - if (anlpar & (LPA_10FULL | LPA_100FULL)) + bmcr |= BMCR_SPEED100; priv->duplex = FULL_DUPLEX; - else + 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; @@ -451,6 +503,8 @@ static int configure_phy(struct eth_device *dev) else priv->speed = SPEED_10M; #endif + priv->phy_configured = 1; + return 0; } @@ -511,14 +565,12 @@ int designware_initialize(u32 id, ulong base_addr, u32 phy_addr) priv->dma_regs_p = (struct eth_dma_regs *)(base_addr + DW_DMA_BASE_OFFSET); priv->address = phy_addr; + priv->phy_configured = 0; if (mac_reset(dev) < 0) return -1; - if (configure_phy(dev) < 0) { - printf("Phy could not be configured\n"); - return -1; - } + configure_phy(dev); dev->init = dw_eth_init; dev->send = dw_eth_send; |