mirror of
https://github.com/Fishwaldo/u-boot.git
synced 2025-03-21 22:51:37 +00:00
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 <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>
This commit is contained in:
parent
d133b881b9
commit
9e27e9dca1
3 changed files with 52 additions and 31 deletions
|
@ -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,
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
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)
|
||||||
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)
|
||||||
#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)
|
||||||
{
|
{
|
||||||
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)
|
||||||
|
|
||||||
|
|
||||||
/* 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)
|
||||||
*/
|
*/
|
||||||
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)
|
||||||
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;
|
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(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)
|
||||||
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)
|
||||||
FEC_RCNTRL_MII_MODE, &fec->eth->r_cntrl);
|
FEC_RCNTRL_MII_MODE, &fec->eth->r_cntrl);
|
||||||
fec_mii_setspeed(fec);
|
fec_mii_setspeed(fec);
|
||||||
|
|
||||||
|
if (dev_id == -1) {
|
||||||
sprintf(edev->name, "FEC");
|
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)
|
||||||
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 {
|
||||||
bd_t *bd;
|
bd_t *bd;
|
||||||
void *rdb_ptr;
|
void *rdb_ptr;
|
||||||
void *base_ptr;
|
void *base_ptr;
|
||||||
|
int dev_id;
|
||||||
|
int phy_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -62,7 +62,7 @@ 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);
|
||||||
|
|
Loading…
Add table
Reference in a new issue