net: fec_mxc: add PHYLIB support

Surround non PHYLIB routines miiphy_restart_aneg
and miiphy_wait_aneg with ifndef CONFIG_PHYLIB.
When later PHYLIB is required it is easy to delete
the non-PHYLIB code. This separation idea
came from Andy Fleming.

fec_miiphy_read, and fec_miiphy_write changed to
fec_phy_read, and fec_phy_write with argument changes.

Deprecated miiphy_register is no longer used. Both
old and new PHYLIB code now use mdio_register.

Cleanup some debug prints.

Inline function fec_miiphy_fec_to_eth is no longer necessary.
Moved to the single call location.

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
This commit is contained in:
Troy Kisky 2012-02-07 14:08:47 +00:00 committed by Albert ARIBAUD
parent 28774cbaac
commit 13947f43c9
2 changed files with 101 additions and 48 deletions

View File

@ -69,35 +69,16 @@ static void swap_packet(uint32_t *packet, int length)
} }
#endif #endif
/*
* The i.MX28 has two ethernet interfaces, but they are not equal.
* Only the first one can access the MDIO bus.
*/
#ifdef CONFIG_MX28
static inline struct ethernet_regs *fec_miiphy_fec_to_eth(struct fec_priv *fec)
{
return (struct ethernet_regs *)MXS_ENET0_BASE;
}
#else
static inline struct ethernet_regs *fec_miiphy_fec_to_eth(struct fec_priv *fec)
{
return fec->eth;
}
#endif
/* /*
* MII-interface related functions * MII-interface related functions
*/ */
static int fec_miiphy_read(const char *dev, uint8_t phyAddr, uint8_t regAddr, static int fec_mdio_read(struct ethernet_regs *eth, uint8_t phyAddr,
uint16_t *retVal) 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_miiphy_fec_to_eth(fec);
uint32_t reg; /* convenient holder for the PHY register */ uint32_t reg; /* convenient holder for the PHY register */
uint32_t phy; /* convenient holder for the PHY */ uint32_t phy; /* convenient holder for the PHY */
uint32_t start; uint32_t start;
int val;
/* /*
* reading from any PHY's register is done by properly * reading from any PHY's register is done by properly
@ -129,10 +110,10 @@ static int fec_miiphy_read(const char *dev, uint8_t phyAddr, uint8_t regAddr,
/* /*
* it's now safe to read the PHY's register * it's now safe to read the PHY's register
*/ */
*retVal = readl(&eth->mii_data); val = (unsigned short)readl(&eth->mii_data);
debug("fec_miiphy_read: phy: %02x reg:%02x val:%#x\n", phyAddr, debug("%s: phy: %02x reg:%02x val:%#x\n", __func__, phyAddr,
regAddr, *retVal); regAddr, val);
return 0; return val;
} }
static void fec_mii_setspeed(struct fec_priv *fec) static void fec_mii_setspeed(struct fec_priv *fec)
@ -143,16 +124,12 @@ static void fec_mii_setspeed(struct fec_priv *fec)
*/ */
writel((((imx_get_fecclk() / 1000000) + 2) / 5) << 1, writel((((imx_get_fecclk() / 1000000) + 2) / 5) << 1,
&fec->eth->mii_speed); &fec->eth->mii_speed);
debug("fec_init: mii_speed %08x\n", debug("%s: mii_speed %08x\n", __func__, readl(&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)
{
struct eth_device *edev = eth_get_dev_by_name(dev);
struct fec_priv *fec = (struct fec_priv *)edev->priv;
struct ethernet_regs *eth = fec_miiphy_fec_to_eth(fec);
static int fec_mdio_write(struct ethernet_regs *eth, uint8_t phyAddr,
uint8_t regAddr, uint16_t data)
{
uint32_t reg; /* convenient holder for the PHY register */ uint32_t reg; /* convenient holder for the PHY register */
uint32_t phy; /* convenient holder for the PHY */ uint32_t phy; /* convenient holder for the PHY */
uint32_t start; uint32_t start;
@ -178,15 +155,28 @@ static int fec_miiphy_write(const char *dev, uint8_t phyAddr, uint8_t regAddr,
* clear MII interrupt bit * clear MII interrupt bit
*/ */
writel(FEC_IEVENT_MII, &eth->ievent); writel(FEC_IEVENT_MII, &eth->ievent);
debug("fec_miiphy_write: phy: %02x reg:%02x val:%#x\n", phyAddr, debug("%s: phy: %02x reg:%02x val:%#x\n", __func__, phyAddr,
regAddr, data); regAddr, data);
return 0; return 0;
} }
int fec_phy_read(struct mii_dev *bus, int phyAddr, int dev_addr, int regAddr)
{
return fec_mdio_read(bus->priv, phyAddr, regAddr);
}
int fec_phy_write(struct mii_dev *bus, int phyAddr, int dev_addr, int regAddr,
u16 data)
{
return fec_mdio_write(bus->priv, phyAddr, regAddr, data);
}
#ifndef CONFIG_PHYLIB
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; struct fec_priv *fec = (struct fec_priv *)dev->priv;
struct ethernet_regs *eth = fec->bus->priv;
int ret = 0; int ret = 0;
/* /*
@ -194,19 +184,18 @@ static int miiphy_restart_aneg(struct eth_device *dev)
* Reset PHY, then delay 300ns * Reset PHY, then delay 300ns
*/ */
#ifdef CONFIG_MX27 #ifdef CONFIG_MX27
miiphy_write(dev->name, fec->phy_id, MII_DCOUNTER, 0x00FF); fec_mdio_write(eth, fec->phy_id, MII_DCOUNTER, 0x00FF);
#endif #endif
miiphy_write(dev->name, fec->phy_id, MII_BMCR, fec_mdio_write(eth, 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, fec->phy_id, MII_ADVERTISE, fec_mdio_write(eth, 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, fec->phy_id, MII_BMCR, fec_mdio_write(eth, fec->phy_id, MII_BMCR,
BMCR_ANENABLE | BMCR_ANRESTART); BMCR_ANENABLE | BMCR_ANRESTART);
if (fec->mii_postcall) if (fec->mii_postcall)
@ -218,8 +207,9 @@ static int miiphy_restart_aneg(struct eth_device *dev)
static int miiphy_wait_aneg(struct eth_device *dev) static int miiphy_wait_aneg(struct eth_device *dev)
{ {
uint32_t start; uint32_t start;
uint16_t status; int status;
struct fec_priv *fec = (struct fec_priv *)dev->priv; struct fec_priv *fec = (struct fec_priv *)dev->priv;
struct ethernet_regs *eth = fec->bus->priv;
/* /*
* Wait for AN completion * Wait for AN completion
@ -231,9 +221,9 @@ static int miiphy_wait_aneg(struct eth_device *dev)
return -1; return -1;
} }
if (miiphy_read(dev->name, fec->phy_id, status = fec_mdio_read(eth, fec->phy_id, MII_BMSR);
MII_BMSR, &status)) { if (status < 0) {
printf("%s: Autonegotiation failed. status: 0x%04x\n", printf("%s: Autonegotiation failed. status: %d\n",
dev->name, status); dev->name, status);
return -1; return -1;
} }
@ -241,6 +231,8 @@ static int miiphy_wait_aneg(struct eth_device *dev)
return 0; return 0;
} }
#endif
static int fec_rx_task_enable(struct fec_priv *fec) static int fec_rx_task_enable(struct fec_priv *fec)
{ {
writel(1 << 24, &fec->eth->r_des_active); writel(1 << 24, &fec->eth->r_des_active);
@ -372,6 +364,21 @@ static int fec_set_hwaddr(struct eth_device *dev)
return 0; return 0;
} }
static void fec_eth_phy_config(struct eth_device *dev)
{
#ifdef CONFIG_PHYLIB
struct fec_priv *fec = (struct fec_priv *)dev->priv;
struct phy_device *phydev;
phydev = phy_connect(fec->bus, fec->phy_id, dev,
PHY_INTERFACE_MODE_RGMII);
if (phydev) {
fec->phydev = phydev;
phy_config(phydev);
}
#endif
}
/** /**
* Start the FEC engine * Start the FEC engine
* @param[in] dev Our device to handle * @param[in] dev Our device to handle
@ -428,9 +435,21 @@ static int fec_open(struct eth_device *edev)
} }
#endif #endif
#ifdef CONFIG_PHYLIB
if (!fec->phydev)
fec_eth_phy_config(edev);
if (fec->phydev) {
/* Start up the PHY */
phy_startup(fec->phydev);
speed = fec->phydev->speed;
} else {
speed = _100BASET;
}
#else
miiphy_wait_aneg(edev); miiphy_wait_aneg(edev);
speed = miiphy_speed(edev->name, fec->phy_id); speed = miiphy_speed(edev->name, fec->phy_id);
miiphy_duplex(edev->name, fec->phy_id); miiphy_duplex(edev->name, fec->phy_id);
#endif
#ifdef FEC_QUIRK_ENET_MAC #ifdef FEC_QUIRK_ENET_MAC
{ {
@ -558,9 +577,10 @@ static int fec_init(struct eth_device *dev, bd_t* bd)
fec_tbd_init(fec); fec_tbd_init(fec);
#ifndef CONFIG_PHYLIB
if (fec->xcv_type != SEVENWIRE) if (fec->xcv_type != SEVENWIRE)
miiphy_restart_aneg(dev); miiphy_restart_aneg(dev);
#endif
fec_open(dev); fec_open(dev);
return 0; return 0;
} }
@ -762,6 +782,7 @@ 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; struct fec_priv *fec;
struct mii_dev *bus;
unsigned char ethaddr[6]; unsigned char ethaddr[6];
uint32_t start; uint32_t start;
int ret = 0; int ret = 0;
@ -836,15 +857,40 @@ static int fec_probe(bd_t *bd, int dev_id, int phy_id, uint32_t base_addr)
} }
fec->phy_id = phy_id; fec->phy_id = phy_id;
miiphy_register(edev->name, fec_miiphy_read, fec_miiphy_write); bus = mdio_alloc();
if (!bus) {
printf("mdio_alloc failed\n");
ret = -ENOMEM;
goto err3;
}
bus->read = fec_phy_read;
bus->write = fec_phy_write;
sprintf(bus->name, edev->name);
#ifdef CONFIG_MX28
/*
* The i.MX28 has two ethernet interfaces, but they are not equal.
* Only the first one can access the MDIO bus.
*/
bus->priv = (struct ethernet_regs *)MXS_ENET0_BASE;
#else
bus->priv = fec->eth;
#endif
ret = mdio_register(bus);
if (ret) {
printf("mdio_register failed\n");
free(bus);
ret = -ENOMEM;
goto err3;
}
fec->bus = bus;
eth_register(edev); eth_register(edev);
if (fec_get_hwaddr(edev, dev_id, ethaddr) == 0) { if (fec_get_hwaddr(edev, dev_id, ethaddr) == 0) {
debug("got MAC%d address from fuse: %pM\n", dev_id, ethaddr); debug("got MAC%d address from fuse: %pM\n", dev_id, ethaddr);
memcpy(edev->enetaddr, ethaddr, 6); memcpy(edev->enetaddr, ethaddr, 6);
} }
/* Configure phy */
fec_eth_phy_config(edev);
return ret; return ret;
err3: err3:
@ -877,9 +923,11 @@ int fecmxc_initialize_multi(bd_t *bd, int dev_id, int phy_id, uint32_t addr)
return lout; return lout;
} }
#ifndef CONFIG_PHYLIB
int fecmxc_register_mii_postcall(struct eth_device *dev, int (*cb)(int)) int fecmxc_register_mii_postcall(struct eth_device *dev, int (*cb)(int))
{ {
struct fec_priv *fec = (struct fec_priv *)dev->priv; struct fec_priv *fec = (struct fec_priv *)dev->priv;
fec->mii_postcall = cb; fec->mii_postcall = cb;
return 0; return 0;
} }
#endif

View File

@ -286,7 +286,12 @@ struct fec_priv {
void *base_ptr; void *base_ptr;
int dev_id; int dev_id;
int phy_id; int phy_id;
struct mii_dev *bus;
#ifdef CONFIG_PHYLIB
struct phy_device *phydev;
#else
int (*mii_postcall)(int); int (*mii_postcall)(int);
#endif
}; };
/** /**