[U-Boot] [PATCH 00/11] Support for both FEC interfaces on i.MX28

This patchset introduces support for both FEC ethernet interfaces on the i.MX28 CPU and clears most of the FIXME's the the driver.
Marek Vasut (11): FEC: Use proper accessor to read register in debug call FEC: Use defined constant instead of magic number FEC: Kill mode select FIXME's FEC: Add RMII mode support FEC: Allow selection of MII mode via CONFIG_FEC_XCV_TYPE FEC: Abstract access to fec->eth in MII operations FEC: Allow multiple FECes FEC: Allow registering MII postconfiguration callback FEC: Add timeout for chip reset FEC: Squish "got MAC from fuse" message, make it debug() FEC: Move imx_get_mac_from_fuse() definition to fec_mxc.h
arch/arm/include/asm/arch-mx25/imx-regs.h | 1 - arch/arm/include/asm/arch-mx27/imx-regs.h | 1 - arch/arm/include/asm/arch-mx35/imx-regs.h | 2 - arch/arm/include/asm/arch-mx5/imx-regs.h | 2 - drivers/net/fec_mxc.c | 170 +++++++++++++++++++---------- drivers/net/fec_mxc.h | 9 ++- include/netdev.h | 7 +- 7 files changed, 128 insertions(+), 64 deletions(-)

Signed-off-by: Marek Vasut marek.vasut@gmail.com Cc: Ben Warren biggerbadderben@gmail.com Cc: Stefano Babic sbabic@denx.de Cc: Wolfgang Denk wd@denx.de Cc: Detlev Zundel dzu@denx.de --- drivers/net/fec_mxc.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c index ab90afa..82fe1e4 100644 --- a/drivers/net/fec_mxc.c +++ b/drivers/net/fec_mxc.c @@ -117,7 +117,7 @@ static void fec_mii_setspeed(struct fec_priv *fec) writel((((imx_get_fecclk() / 1000000) + 2) / 5) << 1, &fec->eth->mii_speed); debug("fec_init: mii_speed %#lx\n", - fec->eth->mii_speed); + readl(&fec->eth->mii_speed)); } static int fec_miiphy_write(const char *dev, uint8_t phyAddr, uint8_t regAddr, uint16_t data)

Signed-off-by: Marek Vasut marek.vasut@gmail.com Cc: Ben Warren biggerbadderben@gmail.com Cc: Stefano Babic sbabic@denx.de Cc: Wolfgang Denk wd@denx.de Cc: Detlev Zundel dzu@denx.de --- drivers/net/fec_mxc.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c index 82fe1e4..8e0d30a 100644 --- a/drivers/net/fec_mxc.c +++ b/drivers/net/fec_mxc.c @@ -712,7 +712,7 @@ static int fec_probe(bd_t *bd)
/* Reset chip. */ writel(readl(&fec->eth->ecntrl) | FEC_ECNTRL_RESET, &fec->eth->ecntrl); - while (readl(&fec->eth->ecntrl) & 1) + while (readl(&fec->eth->ecntrl) & FEC_ECNTRL_RESET) udelay(10);
/*

Signed-off-by: Marek Vasut marek.vasut@gmail.com Cc: Ben Warren biggerbadderben@gmail.com Cc: Stefano Babic sbabic@denx.de Cc: Wolfgang Denk wd@denx.de Cc: Detlev Zundel dzu@denx.de --- drivers/net/fec_mxc.c | 26 ++++++++++++++------------ 1 files changed, 14 insertions(+), 12 deletions(-)
diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c index 8e0d30a..bd76f97 100644 --- a/drivers/net/fec_mxc.c +++ b/drivers/net/fec_mxc.c @@ -400,6 +400,7 @@ static int fec_init(struct eth_device *dev, bd_t* bd) { uint32_t base; struct fec_priv *fec = (struct fec_priv *)dev->priv; + uint32_t rcntrl;
/* Initialize MAC address */ fec_set_hwaddr(dev); @@ -442,19 +443,19 @@ static int fec_init(struct eth_device *dev, bd_t* bd) /* * Set FEC-Lite receive control register(R_CNTRL): */ - if (fec->xcv_type == SEVENWIRE) { - /* - * Frame length=1518; 7-wire mode - */ - writel(0x05ee0020, &fec->eth->r_cntrl); /* FIXME 0x05ee0000 */ - } else { - /* - * Frame length=1518; MII mode; - */ - writel(0x05ee0024, &fec->eth->r_cntrl); /* FIXME 0x05ee0004 */
+ /* Start with frame length = 1518, common for all modes. */ + rcntrl = 1518 << FEC_RCNTRL_MAX_FL_SHIFT; + if (fec->xcv_type == SEVENWIRE) + rcntrl |= FEC_RCNTRL_FCE; + else /* MII mode */ + rcntrl |= FEC_RCNTRL_FCE | FEC_RCNTRL_MII_MODE; + + writel(rcntrl, &fec->eth->r_cntrl); + + if (fec->xcv_type == MII10 || fec->xcv_type == MII100) fec_mii_setspeed(fec); - } + /* * Set Opcode/Pause Duration Register */ @@ -731,7 +732,8 @@ static int fec_probe(bd_t *bd) /* * Frame length=1518; MII mode; */ - writel(0x05ee0024, &fec->eth->r_cntrl); /* FIXME 0x05ee0004 */ + writel((1518 << FEC_RCNTRL_MAX_FL_SHIFT) | FEC_RCNTRL_FCE | + FEC_RCNTRL_MII_MODE, &fec->eth->r_cntrl); fec_mii_setspeed(fec);
sprintf(edev->name, "FEC");

On Friday, September 09, 2011 02:48:13 AM Mike Frysinger wrote:
On Thursday, September 08, 2011 16:37:14 Marek Vasut wrote:
- /* Start with frame length = 1518, common for all modes. */
- rcntrl = 1518 << FEC_RCNTRL_MAX_FL_SHIFT;
you mean PKTSIZE ? ;) -mike
Fixed internally ... if there's anything else, let me know. I'll roll out the new series then.

Signed-off-by: Marek Vasut marek.vasut@gmail.com Cc: Ben Warren biggerbadderben@gmail.com Cc: Stefano Babic sbabic@denx.de Cc: Wolfgang Denk wd@denx.de Cc: Detlev Zundel dzu@denx.de --- drivers/net/fec_mxc.c | 2 ++ drivers/net/fec_mxc.h | 4 +++- 2 files changed, 5 insertions(+), 1 deletions(-)
diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c index bd76f97..2b269d6 100644 --- a/drivers/net/fec_mxc.c +++ b/drivers/net/fec_mxc.c @@ -448,6 +448,8 @@ static int fec_init(struct eth_device *dev, bd_t* bd) rcntrl = 1518 << FEC_RCNTRL_MAX_FL_SHIFT; if (fec->xcv_type == SEVENWIRE) rcntrl |= FEC_RCNTRL_FCE; + else if (fec->xcv_type == RMII) + rcntrl |= FEC_RCNTRL_RMII; else /* MII mode */ rcntrl |= FEC_RCNTRL_FCE | FEC_RCNTRL_MII_MODE;
diff --git a/drivers/net/fec_mxc.h b/drivers/net/fec_mxc.h index 1ba5161..f16f9db 100644 --- a/drivers/net/fec_mxc.h +++ b/drivers/net/fec_mxc.h @@ -194,6 +194,7 @@ struct ethernet_regs { #define FEC_RCNTRL_PROM 0x00000008 #define FEC_RCNTRL_BC_REJ 0x00000010 #define FEC_RCNTRL_FCE 0x00000020 +#define FEC_RCNTRL_RMII 0x00000100
#define FEC_TCNTRL_GTS 0x00000001 #define FEC_TCNTRL_HBC 0x00000002 @@ -257,7 +258,8 @@ struct fec_bd { enum xceiver_type { SEVENWIRE, /* 7-wire */ MII10, /* MII 10Mbps */ - MII100 /* MII 100Mbps */ + MII100, /* MII 100Mbps */ + RMII /* RMII */ };
/**

The default is MII100, which was hardcoded previously in the driver.
Signed-off-by: Marek Vasut marek.vasut@gmail.com Cc: Ben Warren biggerbadderben@gmail.com Cc: Stefano Babic sbabic@denx.de Cc: Wolfgang Denk wd@denx.de Cc: Detlev Zundel dzu@denx.de --- drivers/net/fec_mxc.c | 6 +++++- 1 files changed, 5 insertions(+), 1 deletions(-)
diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c index 2b269d6..d75f40c 100644 --- a/drivers/net/fec_mxc.c +++ b/drivers/net/fec_mxc.c @@ -38,6 +38,10 @@ DECLARE_GLOBAL_DATA_PTR; #error "CONFIG_MII has to be defined!" #endif
+#ifndef CONFIG_FEC_XCV_TYPE +#define CONFIG_FEC_XCV_TYPE MII100 +#endif + #undef DEBUG
struct nbuf { @@ -711,7 +715,7 @@ static int fec_probe(bd_t *bd) fec->eth = (struct ethernet_regs *)IMX_FEC_BASE; fec->bd = bd;
- fec->xcv_type = MII100; + fec->xcv_type = CONFIG_FEC_XCV_TYPE;
/* Reset chip. */ writel(readl(&fec->eth->ecntrl) | FEC_ECNTRL_RESET, &fec->eth->ecntrl);

On Thursday, September 08, 2011 16:37:16 Marek Vasut wrote:
--- a/drivers/net/fec_mxc.c +++ b/drivers/net/fec_mxc.c @@ -38,6 +38,10 @@ DECLARE_GLOBAL_DATA_PTR; #error "CONFIG_MII has to be defined!" #endif
+#ifndef CONFIG_FEC_XCV_TYPE +#define CONFIG_FEC_XCV_TYPE MII100 +#endif
#undef DEBUG
struct nbuf { @@ -711,7 +715,7 @@ static int fec_probe(bd_t *bd) fec->eth = (struct ethernet_regs *)IMX_FEC_BASE; fec->bd = bd;
- fec->xcv_type = MII100;
- fec->xcv_type = CONFIG_FEC_XCV_TYPE;
shouldnt this be a parameter to fec_probe() ? -mike

On Friday, September 09, 2011 02:48:46 AM Mike Frysinger wrote:
On Thursday, September 08, 2011 16:37:16 Marek Vasut wrote:
--- a/drivers/net/fec_mxc.c +++ b/drivers/net/fec_mxc.c @@ -38,6 +38,10 @@ DECLARE_GLOBAL_DATA_PTR;
#error "CONFIG_MII has to be defined!" #endif
+#ifndef CONFIG_FEC_XCV_TYPE +#define CONFIG_FEC_XCV_TYPE MII100 +#endif
#undef DEBUG
struct nbuf {
@@ -711,7 +715,7 @@ static int fec_probe(bd_t *bd)
fec->eth = (struct ethernet_regs *)IMX_FEC_BASE; fec->bd = bd;
- fec->xcv_type = MII100;
- fec->xcv_type = CONFIG_FEC_XCV_TYPE;
shouldnt this be a parameter to fec_probe() ? -mike
We plan to add a driver model eventually. Until then, let's not polute this more than necessary.

Signed-off-by: Marek Vasut marek.vasut@gmail.com Cc: Ben Warren biggerbadderben@gmail.com Cc: Stefano Babic sbabic@denx.de Cc: Wolfgang Denk wd@denx.de Cc: Detlev Zundel dzu@denx.de --- drivers/net/fec_mxc.c | 18 ++++++++++-------- 1 files changed, 10 insertions(+), 8 deletions(-)
diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c index d75f40c..6f56a7a 100644 --- a/drivers/net/fec_mxc.c +++ b/drivers/net/fec_mxc.c @@ -71,6 +71,7 @@ static int fec_miiphy_read(const char *dev, uint8_t phyAddr, uint8_t regAddr, { struct eth_device *edev = eth_get_dev_by_name(dev); struct fec_priv *fec = (struct fec_priv *)edev->priv; + struct ethernet_regs *eth = fec->eth;
uint32_t reg; /* convenient holder for the PHY register */ uint32_t phy; /* convenient holder for the PHY */ @@ -80,18 +81,18 @@ static int fec_miiphy_read(const char *dev, uint8_t phyAddr, uint8_t regAddr, * reading from any PHY's register is done by properly * programming the FEC's MII data register. */ - writel(FEC_IEVENT_MII, &fec->eth->ievent); + writel(FEC_IEVENT_MII, ð->ievent); reg = regAddr << FEC_MII_DATA_RA_SHIFT; phy = phyAddr << FEC_MII_DATA_PA_SHIFT;
writel(FEC_MII_DATA_ST | FEC_MII_DATA_OP_RD | FEC_MII_DATA_TA | - phy | reg, &fec->eth->mii_data); + phy | reg, ð->mii_data);
/* * wait for the related interrupt */ start = get_timer(0); - while (!(readl(&fec->eth->ievent) & FEC_IEVENT_MII)) { + while (!(readl(ð->ievent) & FEC_IEVENT_MII)) { if (get_timer(start) > (CONFIG_SYS_HZ / 1000)) { printf("Read MDIO failed...\n"); return -1; @@ -101,12 +102,12 @@ static int fec_miiphy_read(const char *dev, uint8_t phyAddr, uint8_t regAddr, /* * clear mii interrupt bit */ - writel(FEC_IEVENT_MII, &fec->eth->ievent); + writel(FEC_IEVENT_MII, ð->ievent);
/* * it's now safe to read the PHY's register */ - *retVal = readl(&fec->eth->mii_data); + *retVal = readl(ð->mii_data); debug("fec_miiphy_read: phy: %02x reg:%02x val:%#x\n", phyAddr, regAddr, *retVal); return 0; @@ -128,6 +129,7 @@ static int fec_miiphy_write(const char *dev, uint8_t phyAddr, uint8_t regAddr, { struct eth_device *edev = eth_get_dev_by_name(dev); struct fec_priv *fec = (struct fec_priv *)edev->priv; + struct ethernet_regs *eth = fec->eth;
uint32_t reg; /* convenient holder for the PHY register */ uint32_t phy; /* convenient holder for the PHY */ @@ -137,13 +139,13 @@ static int fec_miiphy_write(const char *dev, uint8_t phyAddr, uint8_t regAddr, phy = phyAddr << FEC_MII_DATA_PA_SHIFT;
writel(FEC_MII_DATA_ST | FEC_MII_DATA_OP_WR | - FEC_MII_DATA_TA | phy | reg | data, &fec->eth->mii_data); + FEC_MII_DATA_TA | phy | reg | data, ð->mii_data);
/* * wait for the MII interrupt */ start = get_timer(0); - while (!(readl(&fec->eth->ievent) & FEC_IEVENT_MII)) { + while (!(readl(ð->ievent) & FEC_IEVENT_MII)) { if (get_timer(start) > (CONFIG_SYS_HZ / 1000)) { printf("Write MDIO failed...\n"); return -1; @@ -153,7 +155,7 @@ static int fec_miiphy_write(const char *dev, uint8_t phyAddr, uint8_t regAddr, /* * clear MII interrupt bit */ - writel(FEC_IEVENT_MII, &fec->eth->ievent); + writel(FEC_IEVENT_MII, ð->ievent); debug("fec_miiphy_write: phy: %02x reg:%02x val:%#x\n", phyAddr, regAddr, data);

This patch allows user to register multiple FEC controllers. To preserve compatibility with older boards, the mxcfec_register() call is still in place. To use multiple controllers, new macro is in place, the mxcfec_register_multi(), which takes more arguments. The syntax is:
mxcfec_register_multi(bd, FEC ID, FEC PHY ID on the MII bus, base address);
To disable the fecmxc_register() compatibility stuff, define the macro CONFIG_FEC_MXC_MULTI. This will remove the requirement for defining IMX_FEC_BASE and CONFIG_FEC_MXC_PHYADDR.
Signed-off-by: Marek Vasut marek.vasut@gmail.com Cc: Ben Warren biggerbadderben@gmail.com Cc: Stefano Babic sbabic@denx.de Cc: Wolfgang Denk wd@denx.de Cc: Detlev Zundel dzu@denx.de --- drivers/net/fec_mxc.c | 79 ++++++++++++++++++++++++++++++------------------ drivers/net/fec_mxc.h | 2 + include/netdev.h | 2 +- 3 files changed, 52 insertions(+), 31 deletions(-)
diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c index 6f56a7a..44b7919 100644 --- a/drivers/net/fec_mxc.c +++ b/drivers/net/fec_mxc.c @@ -51,18 +51,6 @@ struct nbuf { uint8_t head[16]; /**< MAC header(6 + 6 + 2) + 2(aligned) */ };
-struct fec_priv gfec = { - .eth = (struct ethernet_regs *)IMX_FEC_BASE, - .xcv_type = MII100, - .rbd_base = NULL, - .rbd_index = 0, - .tbd_base = NULL, - .tbd_index = 0, - .bd = NULL, - .rdb_ptr = NULL, - .base_ptr = NULL, -}; - /* * MII-interface related functions */ @@ -164,26 +152,27 @@ static int fec_miiphy_write(const char *dev, uint8_t phyAddr, uint8_t regAddr,
static int miiphy_restart_aneg(struct eth_device *dev) { + struct fec_priv *fec = (struct fec_priv *)dev->priv; + /* * Wake up from sleep if necessary * Reset PHY, then delay 300ns */ #ifdef CONFIG_MX27 - miiphy_write(dev->name, CONFIG_FEC_MXC_PHYADDR, MII_DCOUNTER, 0x00FF); + miiphy_write(dev->name, fec->phy_id, MII_DCOUNTER, 0x00FF); #endif - miiphy_write(dev->name, CONFIG_FEC_MXC_PHYADDR, MII_BMCR, + miiphy_write(dev->name, fec->phy_id, MII_BMCR, BMCR_RESET); udelay(1000);
/* * Set the auto-negotiation advertisement register bits */ - miiphy_write(dev->name, CONFIG_FEC_MXC_PHYADDR, MII_ADVERTISE, + miiphy_write(dev->name, fec->phy_id, MII_ADVERTISE, LPA_100FULL | LPA_100HALF | LPA_10FULL | LPA_10HALF | PHY_ANLPAR_PSB_802_3); - miiphy_write(dev->name, CONFIG_FEC_MXC_PHYADDR, MII_BMCR, + miiphy_write(dev->name, fec->phy_id, MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART); - return 0; }
@@ -191,6 +180,7 @@ static int miiphy_wait_aneg(struct eth_device *dev) { uint32_t start; uint16_t status; + struct fec_priv *fec = (struct fec_priv *)dev->priv;
/* * Wait for AN completion @@ -202,7 +192,7 @@ static int miiphy_wait_aneg(struct eth_device *dev) return -1; }
- if (miiphy_read(dev->name, CONFIG_FEC_MXC_PHYADDR, + if (miiphy_read(dev->name, fec->phy_id, MII_BMSR, &status)) { printf("%s: Autonegotiation failed. status: 0x%04x\n", dev->name, status); @@ -390,8 +380,8 @@ static int fec_open(struct eth_device *edev) #endif
miiphy_wait_aneg(edev); - miiphy_speed(edev->name, CONFIG_FEC_MXC_PHYADDR); - miiphy_duplex(edev->name, CONFIG_FEC_MXC_PHYADDR); + miiphy_speed(edev->name, fec->phy_id); + miiphy_duplex(edev->name, fec->phy_id);
/* * Enable SmartDMA receive task @@ -406,7 +396,9 @@ static int fec_init(struct eth_device *dev, bd_t* bd) { uint32_t base; struct fec_priv *fec = (struct fec_priv *)dev->priv; + uint32_t mib_ptr = (uint32_t)&fec->eth->rmon_t_drop; uint32_t rcntrl; + int i;
/* Initialize MAC address */ fec_set_hwaddr(dev); @@ -477,9 +469,8 @@ static int fec_init(struct eth_device *dev, bd_t* bd)
/* clear MIB RAM */ - long *mib_ptr = (long *)(IMX_FEC_BASE + 0x200); - while (mib_ptr <= (long *)(IMX_FEC_BASE + 0x2FC)) - *mib_ptr++ = 0; + for (i = mib_ptr; i <= mib_ptr + 0xfc; i += 4) + writel(0, i);
/* FIFO receive start register */ writel(0x520, &fec->eth->r_fstart); @@ -513,7 +504,7 @@ static int fec_init(struct eth_device *dev, bd_t* bd) */ static void fec_halt(struct eth_device *dev) { - struct fec_priv *fec = &gfec; + struct fec_priv *fec = (struct fec_priv *)dev->priv; int counter = 0xffff;
/* @@ -694,19 +685,28 @@ static int fec_recv(struct eth_device *dev) return len; }
-static int fec_probe(bd_t *bd) +static int fec_probe(bd_t *bd, int dev_id, int phy_id, uint32_t base_addr) { struct eth_device *edev; - struct fec_priv *fec = &gfec; + struct fec_priv *fec; unsigned char ethaddr[6];
/* create and fill edev struct */ edev = (struct eth_device *)malloc(sizeof(struct eth_device)); if (!edev) { - puts("fec_mxc: not enough malloc memory\n"); + puts("fec_mxc: not enough malloc memory for eth_device\n"); + return -ENOMEM; + } + + fec = (struct fec_priv *)malloc(sizeof(struct fec_priv)); + if (!fec) { + puts("fec_mxc: not enough malloc memory for fec_priv\n"); return -ENOMEM; } + memset(edev, 0, sizeof(*edev)); + memset(fec, 0, sizeof(*fec)); + edev->priv = fec; edev->init = fec_init; edev->send = fec_send; @@ -714,7 +714,7 @@ static int fec_probe(bd_t *bd) edev->halt = fec_halt; edev->write_hwaddr = fec_set_hwaddr;
- fec->eth = (struct ethernet_regs *)IMX_FEC_BASE; + fec->eth = (struct ethernet_regs *)base_addr; fec->bd = bd;
fec->xcv_type = CONFIG_FEC_XCV_TYPE; @@ -744,7 +744,14 @@ static int fec_probe(bd_t *bd) FEC_RCNTRL_MII_MODE, &fec->eth->r_cntrl); fec_mii_setspeed(fec);
- sprintf(edev->name, "FEC"); + if (dev_id == -1) { + sprintf(edev->name, "FEC"); + fec->dev_id = 0; + } else { + sprintf(edev->name, "FEC%i", dev_id); + fec->dev_id = dev_id; + } + fec->phy_id = phy_id;
miiphy_register(edev->name, fec_miiphy_read, fec_miiphy_write);
@@ -758,12 +765,24 @@ static int fec_probe(bd_t *bd) return 0; }
+#ifndef CONFIG_FEC_MXC_MULTI int fecmxc_initialize(bd_t *bd) { int lout = 1;
debug("eth_init: fec_probe(bd)\n"); - lout = fec_probe(bd); + lout = fec_probe(bd, -1, CONFIG_FEC_MXC_PHYADDR, IMX_FEC_BASE); + + return lout; +} +#endif + +int fecmxc_initialize_multi(bd_t *bd, int dev_id, int phy_id, uint32_t addr) +{ + int lout = 1; + + debug("eth_init: fec_probe(bd, %i, %i) @ %08x\n", dev_id, phy_id, addr); + lout = fec_probe(bd, dev_id, phy_id, addr);
return lout; } diff --git a/drivers/net/fec_mxc.h b/drivers/net/fec_mxc.h index f16f9db..e436c22 100644 --- a/drivers/net/fec_mxc.h +++ b/drivers/net/fec_mxc.h @@ -275,6 +275,8 @@ struct fec_priv { bd_t *bd; void *rdb_ptr; void *base_ptr; + int dev_id; + int phy_id; };
/** diff --git a/include/netdev.h b/include/netdev.h index 6f0a971..6e70341 100644 --- a/include/netdev.h +++ b/include/netdev.h @@ -61,6 +61,7 @@ int ethoc_initialize(u8 dev_num, int base_addr); int eth_3com_initialize (bd_t * bis); int fec_initialize (bd_t *bis); int fecmxc_initialize (bd_t *bis); +int fecmxc_initialize_multi(bd_t *bis, int dev_id, int phy_id, uint32_t addr); int ftgmac100_initialize(bd_t *bits); int ftmac100_initialize(bd_t *bits); int greth_initialize(bd_t *bis); @@ -93,7 +94,6 @@ int uli526x_initialize(bd_t *bis); int xilinx_emaclite_initialize (bd_t *bis, int base_addr); int sh_eth_initialize(bd_t *bis); int dm9000_initialize(bd_t *bis); -int fecmxc_initialize(bd_t *bis);
/* Boards with PCI network controllers can call this from their board_eth_init() * function to initialize whatever's on board.

Signed-off-by: Marek Vasut marek.vasut@gmail.com Cc: Ben Warren biggerbadderben@gmail.com Cc: Stefano Babic sbabic@denx.de Cc: Wolfgang Denk wd@denx.de Cc: Detlev Zundel dzu@denx.de --- drivers/net/fec_mxc.c | 14 +++++++++++++- drivers/net/fec_mxc.h | 1 + include/netdev.h | 5 +++++ 3 files changed, 19 insertions(+), 1 deletions(-)
diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c index 44b7919..989e7b4 100644 --- a/drivers/net/fec_mxc.c +++ b/drivers/net/fec_mxc.c @@ -153,6 +153,7 @@ static int fec_miiphy_write(const char *dev, uint8_t phyAddr, uint8_t regAddr, static int miiphy_restart_aneg(struct eth_device *dev) { struct fec_priv *fec = (struct fec_priv *)dev->priv; + int ret = 0;
/* * Wake up from sleep if necessary @@ -173,7 +174,11 @@ static int miiphy_restart_aneg(struct eth_device *dev) LPA_10HALF | PHY_ANLPAR_PSB_802_3); miiphy_write(dev->name, fec->phy_id, MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART); - return 0; + + if (fec->mii_postcall) + ret = fec->mii_postcall(fec->phy_id); + + return ret; }
static int miiphy_wait_aneg(struct eth_device *dev) @@ -786,3 +791,10 @@ int fecmxc_initialize_multi(bd_t *bd, int dev_id, int phy_id, uint32_t addr)
return lout; } + +int fecmxc_register_mii_postcall(struct eth_device *dev, int (*cb)(int)) +{ + struct fec_priv *fec = (struct fec_priv *)dev->priv; + fec->mii_postcall = cb; + return 0; +} diff --git a/drivers/net/fec_mxc.h b/drivers/net/fec_mxc.h index e436c22..1a20388 100644 --- a/drivers/net/fec_mxc.h +++ b/drivers/net/fec_mxc.h @@ -277,6 +277,7 @@ struct fec_priv { void *base_ptr; int dev_id; int phy_id; + int (*mii_postcall)(int); };
/** diff --git a/include/netdev.h b/include/netdev.h index 6e70341..1e7f5c1 100644 --- a/include/netdev.h +++ b/include/netdev.h @@ -184,4 +184,9 @@ struct mv88e61xx_config { int mv88e61xx_switch_initialize(struct mv88e61xx_config *swconfig); #endif /* CONFIG_MV88E61XX_SWITCH */
+/* + * Allow FEC to fine-tune MII configuration on boards which require this. + */ +int fecmxc_register_mii_postcall(struct eth_device *dev, int (*cb)(int)); + #endif /* _NETDEV_H_ */

Signed-off-by: Marek Vasut marek.vasut@gmail.com Cc: Ben Warren biggerbadderben@gmail.com Cc: Stefano Babic sbabic@denx.de Cc: Wolfgang Denk wd@denx.de Cc: Detlev Zundel dzu@denx.de --- drivers/net/fec_mxc.c | 25 +++++++++++++++++++++---- 1 files changed, 21 insertions(+), 4 deletions(-)
diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c index 989e7b4..4518457 100644 --- a/drivers/net/fec_mxc.c +++ b/drivers/net/fec_mxc.c @@ -695,18 +695,22 @@ static int fec_probe(bd_t *bd, int dev_id, int phy_id, uint32_t base_addr) struct eth_device *edev; struct fec_priv *fec; unsigned char ethaddr[6]; + uint32_t start; + int ret = 0;
/* create and fill edev struct */ edev = (struct eth_device *)malloc(sizeof(struct eth_device)); if (!edev) { puts("fec_mxc: not enough malloc memory for eth_device\n"); - return -ENOMEM; + ret = -ENOMEM; + goto err1; }
fec = (struct fec_priv *)malloc(sizeof(struct fec_priv)); if (!fec) { puts("fec_mxc: not enough malloc memory for fec_priv\n"); - return -ENOMEM; + ret = -ENOMEM; + goto err2; }
memset(edev, 0, sizeof(*edev)); @@ -726,8 +730,14 @@ static int fec_probe(bd_t *bd, int dev_id, int phy_id, uint32_t base_addr)
/* Reset chip. */ writel(readl(&fec->eth->ecntrl) | FEC_ECNTRL_RESET, &fec->eth->ecntrl); - while (readl(&fec->eth->ecntrl) & FEC_ECNTRL_RESET) + start = get_timer(0); + while (readl(&fec->eth->ecntrl) & FEC_ECNTRL_RESET) { + if (get_timer(start) > (CONFIG_SYS_HZ * 5)) { + printf("FEC MXC: Timeout reseting chip\n"); + goto err3; + } udelay(10); + }
/* * Set interrupt mask register @@ -767,7 +777,14 @@ static int fec_probe(bd_t *bd, int dev_id, int phy_id, uint32_t base_addr) memcpy(edev->enetaddr, ethaddr, 6); }
- return 0; + return ret; + +err3: + free(fec); +err2: + free(edev); +err1: + return ret; }
#ifndef CONFIG_FEC_MXC_MULTI

Signed-off-by: Marek Vasut marek.vasut@gmail.com Cc: Ben Warren biggerbadderben@gmail.com Cc: Stefano Babic sbabic@denx.de Cc: Wolfgang Denk wd@denx.de Cc: Detlev Zundel dzu@denx.de --- drivers/net/fec_mxc.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c index 4518457..fe0253e 100644 --- a/drivers/net/fec_mxc.c +++ b/drivers/net/fec_mxc.c @@ -773,7 +773,7 @@ static int fec_probe(bd_t *bd, int dev_id, int phy_id, uint32_t base_addr) eth_register(edev);
if (fec_get_hwaddr(edev, ethaddr) == 0) { - printf("got MAC address from fuse: %pM\n", ethaddr); + debug("got MAC address from fuse: %pM\n", ethaddr); memcpy(edev->enetaddr, ethaddr, 6); }

Signed-off-by: Marek Vasut marek.vasut@gmail.com Cc: Ben Warren biggerbadderben@gmail.com Cc: Stefano Babic sbabic@denx.de Cc: Wolfgang Denk wd@denx.de Cc: Detlev Zundel dzu@denx.de --- arch/arm/include/asm/arch-mx25/imx-regs.h | 1 - arch/arm/include/asm/arch-mx27/imx-regs.h | 1 - arch/arm/include/asm/arch-mx35/imx-regs.h | 2 -- arch/arm/include/asm/arch-mx5/imx-regs.h | 2 -- drivers/net/fec_mxc.h | 2 ++ 5 files changed, 2 insertions(+), 6 deletions(-)
diff --git a/arch/arm/include/asm/arch-mx25/imx-regs.h b/arch/arm/include/asm/arch-mx25/imx-regs.h index 9e30f7c..c6efca6 100644 --- a/arch/arm/include/asm/arch-mx25/imx-regs.h +++ b/arch/arm/include/asm/arch-mx25/imx-regs.h @@ -36,7 +36,6 @@ #ifndef __ASSEMBLY__ #ifdef CONFIG_FEC_MXC extern void mx25_fec_init_pins(void); -extern void imx_get_mac_from_fuse(unsigned char *mac); #endif
/* Clock Control Module (CCM) registers */ diff --git a/arch/arm/include/asm/arch-mx27/imx-regs.h b/arch/arm/include/asm/arch-mx27/imx-regs.h index b4b2fe6..83ab216 100644 --- a/arch/arm/include/asm/arch-mx27/imx-regs.h +++ b/arch/arm/include/asm/arch-mx27/imx-regs.h @@ -34,7 +34,6 @@ extern void mx27_uart1_init_pins(void);
#ifdef CONFIG_FEC_MXC extern void mx27_fec_init_pins(void); -extern void imx_get_mac_from_fuse(unsigned char *mac); #endif /* CONFIG_FEC_MXC */
#ifdef CONFIG_MXC_MMC diff --git a/arch/arm/include/asm/arch-mx35/imx-regs.h b/arch/arm/include/asm/arch-mx35/imx-regs.h index e741fb0..0c566f2 100644 --- a/arch/arm/include/asm/arch-mx35/imx-regs.h +++ b/arch/arm/include/asm/arch-mx35/imx-regs.h @@ -178,8 +178,6 @@ #if !(defined(__KERNEL_STRICT_NAMES) || defined(__ASSEMBLY__)) #include <asm/types.h>
-extern void imx_get_mac_from_fuse(unsigned char *mac); - enum mxc_main_clocks { CPU_CLK, AHB_CLK, diff --git a/arch/arm/include/asm/arch-mx5/imx-regs.h b/arch/arm/include/asm/arch-mx5/imx-regs.h index a4e680b..098c300 100644 --- a/arch/arm/include/asm/arch-mx5/imx-regs.h +++ b/arch/arm/include/asm/arch-mx5/imx-regs.h @@ -282,8 +282,6 @@ #if !(defined(__KERNEL_STRICT_NAMES) || defined(__ASSEMBLY__)) #include <asm/types.h>
-extern void imx_get_mac_from_fuse(unsigned char *mac); - #define __REG(x) (*((volatile u32 *)(x))) #define __REG16(x) (*((volatile u16 *)(x))) #define __REG8(x) (*((volatile u8 *)(x))) diff --git a/drivers/net/fec_mxc.h b/drivers/net/fec_mxc.h index 1a20388..8b26645 100644 --- a/drivers/net/fec_mxc.h +++ b/drivers/net/fec_mxc.h @@ -32,6 +32,8 @@ #ifndef __FEC_MXC_H #define __FEC_MXC_H
+void imx_get_mac_from_fuse(unsigned char *mac); + /** * Layout description of the FEC */
participants (2)
-
Marek Vasut
-
Mike Frysinger