mirror of
https://github.com/brain-hackers/u-boot-brain
synced 2024-09-30 08:30:50 +09:00
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:
parent
28774cbaac
commit
13947f43c9
@ -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(ð->mii_data);
|
val = (unsigned short)readl(ð->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, ð->ievent);
|
writel(FEC_IEVENT_MII, ð->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
|
||||||
|
@ -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
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user