diff options
author | Zeng Zhaoming <b32542@freescale.com> | 2011-06-23 07:52:37 +0800 |
---|---|---|
committer | Zeng Zhaoming <b32542@freescale.com> | 2011-06-27 02:07:35 +0800 |
commit | 3c5c5630bb6e55471d8279d6789ce9c6e851b589 (patch) | |
tree | 48989322df742df5bdf6ab1b010866ac6eb4bbb7 /drivers/net | |
parent | 15f996b62fb5d2709ff66fbca0f6d0ca376acd13 (diff) | |
download | u-boot-imx-3c5c5630bb6e55471d8279d6789ce9c6e851b589.zip u-boot-imx-3c5c5630bb6e55471d8279d6789ce9c6e851b589.tar.gz u-boot-imx-3c5c5630bb6e55471d8279d6789ce9c6e851b589.tar.bz2 |
ENGR00139198: iMX61 uBoot add ENET support
Add ENET and AR8031 PHY support to uboot.
To make it works on sabreauto, need do following changes:
1. rework phy to output 125M clock from CLK_25M signal,
and the 125M clock input to SoC as reference clock to generate
RGMII_TXC clock.
2. Enable TXC delay in PHY debug register.
3. set ENET working in RMII mode.
4. set ENET working at 1000M or 100M/10M.
5. set ENET TX fifo to maximum to avoid underrun error.
6. force AR8031 PHY working at 100M
Signed-off-by: Anson Huang <b20788@freescale.com>
Signed-off-by: Zeng Zhaoming <b32542@freescale.com>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/mxc_fec.c | 74 |
1 files changed, 69 insertions, 5 deletions
diff --git a/drivers/net/mxc_fec.c b/drivers/net/mxc_fec.c index a204a7e..bca2358 100644 --- a/drivers/net/mxc_fec.c +++ b/drivers/net/mxc_fec.c @@ -2,7 +2,7 @@ * (C) Copyright 2000-2004 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * - * (C) Copyright 2008-2010 Freescale Semiconductor, Inc. + * (C) Copyright 2008-2011 Freescale Semiconductor, Inc. * * See file CREDITS for list of people who contributed to this * project. @@ -311,6 +311,12 @@ static void setFecDuplexSpeed(volatile fec_t *fecp, unsigned char addr, default: val |= PHY_BMCR_AUTON | PHY_BMCR_RST_NEG; } + + /* force mx6 phy works at 100Mbits */ +#ifdef CONFIG_MX6Q + val = PHY_BMCR_100MB | PHY_BMCR_DPLX | PHY_BMCR_RESET; +#endif + ret |= __fec_mii_write(fecp, addr, PHY_BMCR, val); if (!ret && (val & PHY_BMCR_AUTON)) { @@ -325,7 +331,9 @@ static void setFecDuplexSpeed(volatile fec_t *fecp, unsigned char addr, }; } - if (__fec_mii_read(fecp, addr, PHY_BMSR, &val)) { + ret = __fec_mii_read(fecp, addr, PHY_BMSR, &val); + if (ret) { + /* set default speed and duplex */ dup_spd = _100BASET | (FULL << 16); } else { if (val & (PHY_BMSR_100TXF | PHY_BMSR_100TXH | PHY_BMSR_100T4)) @@ -358,12 +366,24 @@ static void setFecDuplexSpeed(volatile fec_t *fecp, unsigned char addr, fecp->tcr &= ~FEC_TCR_FDEN; } +#ifdef CONFIG_MX6Q + if ((dup_spd & 0xFFFF) == _1000BASET) { + fecp->ecr |= (0x1 << 5); + } else if ((dup_spd & 0xFFFF) == _100BASET) { + fecp->ecr &= ~(0x1 << 5); + } else { + fecp->ecr &= ~(0x1 << 5); + fecp->rcr |= (0x1 << 9); + } +#endif + #ifdef ET_DEBUG - if ((dup_spd & 0xFFFF) == _100BASET) { + if ((dup_spd & 0xFFFF) == _1000BASET) + printf("1000Mbps\n"); + else if ((dup_spd & 0xFFFF) == _100BASET) printf("100Mbps\n"); - } else { + else printf("10Mbps\n"); - } #endif } @@ -473,6 +493,8 @@ int fec_send(struct eth_device *dev, volatile void *packet, int length) if (j >= FEC_MAX_TIMEOUT) printf("TX timeout packet at %p\n", packet); + fecp->eir &= fecp->eir; + #ifdef ET_DEBUG printf("%s[%d] %s: cycles: %d status: %x retry cnt: %d\n", __FILE__, __LINE__, __func__, j, @@ -510,6 +532,7 @@ int fec_recv(struct eth_device *dev) __func__, __LINE__, info->rxbd[info->rxIdx].cbd_sc); #endif + fecp->eir &= fecp->eir; } else { length -= 4; #ifdef CONFIG_MX28 @@ -730,6 +753,31 @@ void dbgFecRegs(struct eth_device *dev) } #endif +#ifdef CONFIG_MX6Q_SABREAUTO +static int mx6_rgmii_rework(fec_t *fecp, int addr) +{ + unsigned short val; + + /* To enable AR8031 ouput a 125MHz clk from CLK_25M */ + __fec_mii_write(fecp, addr, 0xd, 0x7); + __fec_mii_write(fecp, addr, 0xe, 0x8016); + __fec_mii_write(fecp, addr, 0xd, 0x4007); + __fec_mii_read(fecp, addr, 0xe, &val); + + val &= 0xffe3; + val |= 0x18; + __fec_mii_write(fecp, addr, 0xe, val); + + /* introduce tx clock delay */ + __fec_mii_write(fecp, addr, 0x1d, 0x5); + __fec_mii_read(fecp, addr, 0x1e, &val); + val |= 0x0100; + __fec_mii_write(fecp, addr, 0x1e, val); + + return 0; +} +#endif + int fec_init(struct eth_device *dev, bd_t *bd) { struct fec_info_s *info = dev->priv; @@ -745,6 +793,10 @@ int fec_init(struct eth_device *dev, bd_t *bd) defined (CONFIG_DISCOVER_PHY) mxc_fec_mii_init(fecp); +#ifdef CONFIG_MX6Q_SABREAUTO + mx6_rgmii_rework((fec_t *)fecp, info->phy_addr); +#endif + #ifdef CONFIG_DISCOVER_PHY if (info->phy_addr < 0 || info->phy_addr > 0x1F) info->phy_addr = mxc_fec_mii_discover_phy(dev); @@ -779,6 +831,10 @@ int fec_init(struct eth_device *dev, bd_t *bd) /* Set maximum receive buffer size. */ fecp->emrbr = PKT_MAXBLR_SIZE; +#ifdef CONFIG_MX6Q + fecp->rcr &= ~(0x100); + fecp->rcr |= 0x44; +#endif /* * Setup Buffers and Buffer Desriptors */ @@ -828,6 +884,14 @@ int fec_init(struct eth_device *dev, bd_t *bd) fecp->etdsr = (uint)(&info->txbd[0]); #endif +#ifdef CONFIG_MX6Q + /* Enable Swap to support little-endian device */ + fecp->ecr |= FEC_ECR_DBSWP; + + /* set transmit fifo buffer to 0x1111 */ + fecp->tfwr |= 0x3f; +#endif + /* Now enable the transmit and receive processing */ fecp->ecr |= FEC_ECR_ETHER_EN; |