net: phy: workaround for buggy cable detection by LAN8700 after cable plugging
* Due to HW bug, LAN8700 sometimes does not detect presence of energy in the Ethernet cable in Energy Detect Power-Down mode (e.g while EDPWRDOWN bit is set, the ENERGYON bit does not asserted sometimes). This is a common bug of LAN87xx family of PHY chips. * The lan87xx_read_status() was improved to acquire ENERGYON bit. Its previous algorythm still not reliable on 100 % and sometimes skip cable plugging. Signed-off-by: Igor Plyatov <plyatov@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
a27cc68b9b
commit
776829de90
|
@ -91,19 +91,18 @@ static int lan911x_config_init(struct phy_device *phydev)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The LAN8710/LAN8720 requires a minimum of 2 link pulses within 64ms of each
|
* The LAN87xx suffers from rare absence of the ENERGYON-bit when Ethernet cable
|
||||||
* other in order to set the ENERGYON bit and exit EDPD mode. If a link partner
|
* plugs in while LAN87xx is in Energy Detect Power-Down mode. This leads to
|
||||||
* does send the pulses within this interval, the PHY will remained powered
|
* unstable detection of plugging in Ethernet cable.
|
||||||
* down.
|
* This workaround disables Energy Detect Power-Down mode and waiting for
|
||||||
*
|
* response on link pulses to detect presence of plugged Ethernet cable.
|
||||||
* This workaround will manually toggle the PHY on/off upon calls to read_status
|
* The Energy Detect Power-Down mode is enabled again in the end of procedure to
|
||||||
* in order to generate link test pulses if the link is down. If a link partner
|
* save approximately 220 mW of power if cable is unplugged.
|
||||||
* is present, it will respond to the pulses, which will cause the ENERGYON bit
|
|
||||||
* to be set and will cause the EDPD mode to be exited.
|
|
||||||
*/
|
*/
|
||||||
static int lan87xx_read_status(struct phy_device *phydev)
|
static int lan87xx_read_status(struct phy_device *phydev)
|
||||||
{
|
{
|
||||||
int err = genphy_read_status(phydev);
|
int err = genphy_read_status(phydev);
|
||||||
|
int i;
|
||||||
|
|
||||||
if (!phydev->link) {
|
if (!phydev->link) {
|
||||||
/* Disable EDPD to wake up PHY */
|
/* Disable EDPD to wake up PHY */
|
||||||
|
@ -116,8 +115,16 @@ static int lan87xx_read_status(struct phy_device *phydev)
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
/* Sleep 64 ms to allow ~5 link test pulses to be sent */
|
/* Wait max 640 ms to detect energy */
|
||||||
msleep(64);
|
for (i = 0; i < 64; i++) {
|
||||||
|
/* Sleep to allow link test pulses to be sent */
|
||||||
|
msleep(10);
|
||||||
|
rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
|
||||||
|
if (rc < 0)
|
||||||
|
return rc;
|
||||||
|
if (rc & MII_LAN83C185_ENERGYON)
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
/* Re-enable EDPD */
|
/* Re-enable EDPD */
|
||||||
rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
|
rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
|
||||||
|
@ -191,7 +198,7 @@ static struct phy_driver smsc_phy_driver[] = {
|
||||||
|
|
||||||
/* basic functions */
|
/* basic functions */
|
||||||
.config_aneg = genphy_config_aneg,
|
.config_aneg = genphy_config_aneg,
|
||||||
.read_status = genphy_read_status,
|
.read_status = lan87xx_read_status,
|
||||||
.config_init = smsc_phy_config_init,
|
.config_init = smsc_phy_config_init,
|
||||||
.soft_reset = smsc_phy_reset,
|
.soft_reset = smsc_phy_reset,
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue