Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 776829de authored by Igor Plyatov's avatar Igor Plyatov Committed by David S. Miller
Browse files

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: default avatarIgor Plyatov <plyatov@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a27cc68b
Loading
Loading
Loading
Loading
+19 −12
Original line number Diff line number Diff line
@@ -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
 * other in order to set the ENERGYON bit and exit EDPD mode.  If a link partner
 * does send the pulses within this interval, the PHY will remained powered
 * down.
 *
 * This workaround will manually toggle the PHY on/off upon calls to read_status
 * in order to generate link test pulses if the link is down.  If a link partner
 * 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.
 * The LAN87xx suffers from rare absence of the ENERGYON-bit when Ethernet cable
 * plugs in while LAN87xx is in Energy Detect Power-Down mode. This leads to
 * unstable detection of plugging in Ethernet cable.
 * This workaround disables Energy Detect Power-Down mode and waiting for
 * response on link pulses to detect presence of plugged Ethernet cable.
 * The Energy Detect Power-Down mode is enabled again in the end of procedure to
 * save approximately 220 mW of power if cable is unplugged.
 */
static int lan87xx_read_status(struct phy_device *phydev)
{
	int err = genphy_read_status(phydev);
	int i;

	if (!phydev->link) {
		/* Disable EDPD to wake up PHY */
@@ -116,8 +115,16 @@ static int lan87xx_read_status(struct phy_device *phydev)
		if (rc < 0)
			return rc;

		/* Sleep 64 ms to allow ~5 link test pulses to be sent */
		msleep(64);
		/* Wait max 640 ms to detect energy */
		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 */
		rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
@@ -191,7 +198,7 @@ static struct phy_driver smsc_phy_driver[] = {

	/* basic functions */
	.config_aneg	= genphy_config_aneg,
	.read_status	= genphy_read_status,
	.read_status	= lan87xx_read_status,
	.config_init	= smsc_phy_config_init,
	.soft_reset	= smsc_phy_reset,