M. Feser KBS GmbH
Date: 29.01.2018

This patch disables the LAN87xx powerdown mode which might prevent
link detection
-------------------------------------------------------------------------
diff -ruPN a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c
--- a/drivers/net/phy/smsc.c	2017-11-02 09:40:50.000000000 +0100
+++ b/drivers/net/phy/smsc.c	2018-01-29 13:06:17.687017933 +0100
@@ -66,6 +66,32 @@
 	return smsc_phy_ack_interrupt(phydev);
 }
 
+static int lan87xx_config_init(struct phy_device *phydev)
+{
+	/*
+	 * Make sure the EDPWRDOWN bit is NOT set. Setting this bit on
+	 * LAN8710/LAN8720 PHY causes the PHY to misbehave, likely due
+	 * to a bug on the chip.
+	 *
+	 * When the system is powered on with the network cable being
+	 * disconnected all the way until after ifconfig ethX up is
+	 * issued for the LAN port with this PHY, connecting the cable
+	 * afterwards does not cause LINK change detection, while the
+	 * expected behavior is the Link UP being detected.
+	 */
+	int rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
+	if (rc < 0)
+		return rc;
+
+	rc &= ~MII_LAN83C185_EDPWRDOWN;
+
+	rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS, rc);
+	if (rc < 0)
+		return rc;
+
+ return smsc_phy_ack_interrupt(phydev);
+}
+
 static int smsc_phy_reset(struct phy_device *phydev)
 {
 	int rc = phy_read(phydev, MII_LAN83C185_SPECIAL_MODES);
@@ -99,56 +125,6 @@
 	return smsc_phy_ack_interrupt(phydev);
 }
 
-/*
- * 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 */
-		int rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
-		if (rc < 0)
-			return rc;
-
-		rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS,
-			       rc & ~MII_LAN83C185_EDPWRDOWN);
-		if (rc < 0)
-			return rc;
-
-		/* 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);
-		if (rc < 0)
-			return rc;
-
-		rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS,
-			       rc | MII_LAN83C185_EDPWRDOWN);
-		if (rc < 0)
-			return rc;
-	}
-
-	return err;
-}
-
 static struct phy_driver smsc_phy_driver[] = {
 {
 	.phy_id		= 0x0007c0a0, /* OUI=0x00800f, Model#=0x0a */
@@ -207,8 +183,8 @@
 
 	/* basic functions */
 	.config_aneg	= genphy_config_aneg,
-	.read_status	= lan87xx_read_status,
-	.config_init	= smsc_phy_config_init,
+	.read_status	= genphy_read_status,
+	.config_init	= lan87xx_config_init,
 	.soft_reset	= smsc_phy_reset,
 
 	/* IRQ related */
@@ -252,8 +228,8 @@
 
 	/* basic functions */
 	.config_aneg	= genphy_config_aneg,
-	.read_status	= lan87xx_read_status,
-	.config_init	= smsc_phy_config_init,
+	.read_status	= genphy_read_status,
+	.config_init	= lan87xx_config_init,
 	.soft_reset	= smsc_phy_reset,
 
 	/* IRQ related */
