Commit 9e27e9dc authored by Marek Vasut's avatar Marek Vasut Committed by Albert ARIBAUD

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: default avatarMarek 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>
parent d133b881
...@@ -51,18 +51,6 @@ struct nbuf { ...@@ -51,18 +51,6 @@ struct nbuf {
uint8_t head[16]; /**< MAC header(6 + 6 + 2) + 2(aligned) */ 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 * MII-interface related functions
*/ */
...@@ -164,26 +152,27 @@ static int fec_miiphy_write(const char *dev, uint8_t phyAddr, uint8_t regAddr, ...@@ -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) static int miiphy_restart_aneg(struct eth_device *dev)
{ {
struct fec_priv *fec = (struct fec_priv *)dev->priv;
/* /*
* Wake up from sleep if necessary * Wake up from sleep if necessary
* Reset PHY, then delay 300ns * Reset PHY, then delay 300ns
*/ */
#ifdef CONFIG_MX27 #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 #endif
miiphy_write(dev->name, CONFIG_FEC_MXC_PHYADDR, MII_BMCR, miiphy_write(dev->name, fec->phy_id, MII_BMCR,
BMCR_RESET); BMCR_RESET);
udelay(1000); udelay(1000);
/* /*
* Set the auto-negotiation advertisement register bits * 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_100FULL | LPA_100HALF | LPA_10FULL |
LPA_10HALF | PHY_ANLPAR_PSB_802_3); 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); BMCR_ANENABLE | BMCR_ANRESTART);
return 0; return 0;
} }
...@@ -191,6 +180,7 @@ static int miiphy_wait_aneg(struct eth_device *dev) ...@@ -191,6 +180,7 @@ static int miiphy_wait_aneg(struct eth_device *dev)
{ {
uint32_t start; uint32_t start;
uint16_t status; uint16_t status;
struct fec_priv *fec = (struct fec_priv *)dev->priv;
/* /*
* Wait for AN completion * Wait for AN completion
...@@ -202,7 +192,7 @@ static int miiphy_wait_aneg(struct eth_device *dev) ...@@ -202,7 +192,7 @@ static int miiphy_wait_aneg(struct eth_device *dev)
return -1; return -1;
} }
if (miiphy_read(dev->name, CONFIG_FEC_MXC_PHYADDR, if (miiphy_read(dev->name, fec->phy_id,
MII_BMSR, &status)) { MII_BMSR, &status)) {
printf("%s: Autonegotiation failed. status: 0x%04x\n", printf("%s: Autonegotiation failed. status: 0x%04x\n",
dev->name, status); dev->name, status);
...@@ -390,8 +380,8 @@ static int fec_open(struct eth_device *edev) ...@@ -390,8 +380,8 @@ static int fec_open(struct eth_device *edev)
#endif #endif
miiphy_wait_aneg(edev); miiphy_wait_aneg(edev);
miiphy_speed(edev->name, CONFIG_FEC_MXC_PHYADDR); miiphy_speed(edev->name, fec->phy_id);
miiphy_duplex(edev->name, CONFIG_FEC_MXC_PHYADDR); miiphy_duplex(edev->name, fec->phy_id);
/* /*
* Enable SmartDMA receive task * Enable SmartDMA receive task
...@@ -406,7 +396,9 @@ static int fec_init(struct eth_device *dev, bd_t* bd) ...@@ -406,7 +396,9 @@ static int fec_init(struct eth_device *dev, bd_t* bd)
{ {
uint32_t base; uint32_t base;
struct fec_priv *fec = (struct fec_priv *)dev->priv; struct fec_priv *fec = (struct fec_priv *)dev->priv;
uint32_t mib_ptr = (uint32_t)&fec->eth->rmon_t_drop;
uint32_t rcntrl; uint32_t rcntrl;
int i;
/* Initialize MAC address */ /* Initialize MAC address */
fec_set_hwaddr(dev); fec_set_hwaddr(dev);
...@@ -477,9 +469,8 @@ static int fec_init(struct eth_device *dev, bd_t* bd) ...@@ -477,9 +469,8 @@ static int fec_init(struct eth_device *dev, bd_t* bd)
/* clear MIB RAM */ /* clear MIB RAM */
long *mib_ptr = (long *)(IMX_FEC_BASE + 0x200); for (i = mib_ptr; i <= mib_ptr + 0xfc; i += 4)
while (mib_ptr <= (long *)(IMX_FEC_BASE + 0x2FC)) writel(0, i);
*mib_ptr++ = 0;
/* FIFO receive start register */ /* FIFO receive start register */
writel(0x520, &fec->eth->r_fstart); writel(0x520, &fec->eth->r_fstart);
...@@ -513,7 +504,7 @@ static int fec_init(struct eth_device *dev, bd_t* bd) ...@@ -513,7 +504,7 @@ static int fec_init(struct eth_device *dev, bd_t* bd)
*/ */
static void fec_halt(struct eth_device *dev) 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; int counter = 0xffff;
/* /*
...@@ -694,19 +685,28 @@ static int fec_recv(struct eth_device *dev) ...@@ -694,19 +685,28 @@ static int fec_recv(struct eth_device *dev)
return len; 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 eth_device *edev;
struct fec_priv *fec = &gfec; struct fec_priv *fec;
unsigned char ethaddr[6]; unsigned char ethaddr[6];
/* create and fill edev struct */ /* create and fill edev struct */
edev = (struct eth_device *)malloc(sizeof(struct eth_device)); edev = (struct eth_device *)malloc(sizeof(struct eth_device));
if (!edev) { 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; return -ENOMEM;
} }
memset(edev, 0, sizeof(*edev)); memset(edev, 0, sizeof(*edev));
memset(fec, 0, sizeof(*fec));
edev->priv = fec; edev->priv = fec;
edev->init = fec_init; edev->init = fec_init;
edev->send = fec_send; edev->send = fec_send;
...@@ -714,7 +714,7 @@ static int fec_probe(bd_t *bd) ...@@ -714,7 +714,7 @@ static int fec_probe(bd_t *bd)
edev->halt = fec_halt; edev->halt = fec_halt;
edev->write_hwaddr = fec_set_hwaddr; 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->bd = bd;
fec->xcv_type = CONFIG_FEC_XCV_TYPE; fec->xcv_type = CONFIG_FEC_XCV_TYPE;
...@@ -744,7 +744,14 @@ static int fec_probe(bd_t *bd) ...@@ -744,7 +744,14 @@ static int fec_probe(bd_t *bd)
FEC_RCNTRL_MII_MODE, &fec->eth->r_cntrl); FEC_RCNTRL_MII_MODE, &fec->eth->r_cntrl);
fec_mii_setspeed(fec); 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); miiphy_register(edev->name, fec_miiphy_read, fec_miiphy_write);
...@@ -758,12 +765,24 @@ static int fec_probe(bd_t *bd) ...@@ -758,12 +765,24 @@ static int fec_probe(bd_t *bd)
return 0; return 0;
} }
#ifndef CONFIG_FEC_MXC_MULTI
int fecmxc_initialize(bd_t *bd) int fecmxc_initialize(bd_t *bd)
{ {
int lout = 1; int lout = 1;
debug("eth_init: fec_probe(bd)\n"); 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; return lout;
} }
...@@ -275,6 +275,8 @@ struct fec_priv { ...@@ -275,6 +275,8 @@ struct fec_priv {
bd_t *bd; bd_t *bd;
void *rdb_ptr; void *rdb_ptr;
void *base_ptr; void *base_ptr;
int dev_id;
int phy_id;
}; };
/** /**
......
...@@ -61,8 +61,8 @@ int ep93xx_eth_initialize(u8 dev_num, int base_addr); ...@@ -61,8 +61,8 @@ int ep93xx_eth_initialize(u8 dev_num, int base_addr);
int eth_3com_initialize (bd_t * bis); int eth_3com_initialize (bd_t * bis);
int ethoc_initialize(u8 dev_num, int base_addr); int ethoc_initialize(u8 dev_num, int base_addr);
int fec_initialize (bd_t *bis); int fec_initialize (bd_t *bis);
int fecmxc_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 ftgmac100_initialize(bd_t *bits);
int ftmac100_initialize(bd_t *bits); int ftmac100_initialize(bd_t *bits);
int greth_initialize(bd_t *bis); int greth_initialize(bd_t *bis);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment