diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2014-09-17 14:39:36 +0200 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2014-09-17 15:12:56 +0200 |
commit | e209158d5a566ddb0f2bb10f1fd10ff3ca0974ce (patch) | |
tree | acc298c41837c969a41a07677d21d83c8c3b0086 /drivers | |
parent | 5c0bd50319f20655b3c6e93ac9c7a72e44de7bd9 (diff) | |
download | barebox-e209158d5a566ddb0f2bb10f1fd10ff3ca0974ce.tar.gz barebox-e209158d5a566ddb0f2bb10f1fd10ff3ca0974ce.tar.xz |
net: phy: introduce phy_aneg_done
phy_wait_aneg_done() is directly called by the network code, so it
should not read phy registers directly. Introduce phy_aneg_done to
give phy drivers the chance to do something different to poll for
autonegotiation completion.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/phy/phy.c | 57 |
1 files changed, 46 insertions, 11 deletions
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index cad4cf5475..7604e1de33 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -31,6 +31,21 @@ static struct phy_driver genphy_driver; static int genphy_config_init(struct phy_device *phydev); +/** + * phy_aneg_done - return auto-negotiation status + * @phydev: target phy_device struct + * + * Description: Return the auto-negotiation status from this @phydev + * Returns > 0 on success or < 0 on error. 0 means that auto-negotiation + * is still pending. + */ +static int phy_aneg_done(struct phy_device *phydev) +{ + struct phy_driver *drv = to_phy_driver(phydev->dev.driver); + + return drv->aneg_done(phydev); +} + int phy_update_status(struct phy_device *dev) { struct phy_driver *drv = to_phy_driver(dev->dev.driver); @@ -477,25 +492,15 @@ int genphy_setup_forced(struct phy_device *phydev) int phy_wait_aneg_done(struct phy_device *phydev) { uint64_t start = get_time_ns(); - int ctl; if (phydev->autoneg == AUTONEG_DISABLE) return 0; while (!is_timeout(start, PHY_AN_TIMEOUT * SECOND)) { - ctl = phy_read(phydev, MII_BMSR); - if (ctl & BMSR_ANEGCOMPLETE) { + if (phy_aneg_done(phydev) > 0) { phydev->link = 1; return 0; } - - /* Restart auto-negotiation if remote fault */ - if (ctl & BMSR_RFAULT) { - puts("PHY remote fault detected\n" - "PHY restarting auto-negotiation\n"); - phy_write(phydev, MII_BMCR, - BMCR_ANENABLE | BMCR_ANRESTART); - } } phydev->link = 0; @@ -572,6 +577,33 @@ int genphy_config_aneg(struct phy_device *phydev) } /** + * genphy_aneg_done - return auto-negotiation status + * @phydev: target phy_device struct + * + * Description: Reads the status register and returns 0 either if + * auto-negotiation is incomplete, or if there was an error. + * Returns BMSR_ANEGCOMPLETE if auto-negotiation is done. + */ +int genphy_aneg_done(struct phy_device *phydev) +{ + int bmsr = phy_read(phydev, MII_BMSR); + + if (bmsr < 0) + return bmsr; + + /* Restart auto-negotiation if remote fault */ + if (bmsr & BMSR_RFAULT) { + puts("PHY remote fault detected\n" + "PHY restarting auto-negotiation\n"); + phy_write(phydev, MII_BMCR, + BMCR_ANENABLE | BMCR_ANRESTART); + } + + return bmsr & BMSR_ANEGCOMPLETE; +} +EXPORT_SYMBOL(genphy_aneg_done); + +/** * genphy_update_link - update link status in @phydev * @phydev: target phy_device struct * @@ -825,6 +857,9 @@ int phy_driver_register(struct phy_driver *phydrv) if (!phydrv->config_aneg) phydrv->config_aneg = genphy_config_aneg; + if (!phydrv->aneg_done) + phydrv->aneg_done = genphy_aneg_done; + if (!phydrv->read_status) phydrv->read_status = genphy_read_status; |