From 9e27e9dca14a3bca74a5dcc87231769bc6a7117f Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Fri, 16 Sep 2011 01:13:47 +0200 Subject: FEC: Allow multiple FECes 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 Cc: Ben Warren Cc: Stefano Babic Cc: Wolfgang Denk Cc: Detlev Zundel --- 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 d448496..3c593aa 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 5c5941c..e979cbd 100644 --- a/include/netdev.h +++ b/include/netdev.h @@ -61,8 +61,8 @@ int ep93xx_eth_initialize(u8 dev_num, int base_addr); int eth_3com_initialize (bd_t * bis); int ethoc_initialize(u8 dev_num, int base_addr); int fec_initialize (bd_t *bis); -int fecmxc_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); -- cgit v1.1