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

Commit 4223dbff authored by Patrick Trantham's avatar Patrick Trantham Committed by David S. Miller
Browse files

net: phy: smsc: Re-enable EDPD mode for LAN87xx



This patch re-enables Energy Detect Power Down (EDPD) mode for the
LAN8710/LAN8720.  EDPD mode was disabled in a previous commit,
(b629820d), because it was causing the
PHY to not be able to detect a link when cold started without a cable
connected.

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.

Signed-off-by: default avatarPatrick Trantham <patrick.trantham@fuel7.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent f191a1d1
Loading
Loading
Loading
Loading
+43 −26
Original line number Original line Diff line number Diff line
@@ -56,35 +56,52 @@ static int smsc_phy_config_init(struct phy_device *phydev)
	return smsc_phy_ack_interrupt (phydev);
	return smsc_phy_ack_interrupt (phydev);
}
}


static int lan87xx_config_init(struct phy_device *phydev)
static int lan911x_config_init(struct phy_device *phydev)
{
{
	return smsc_phy_ack_interrupt(phydev);
}

/*
/*
	 * Make sure the EDPWRDOWN bit is NOT set. Setting this bit on
 * The LAN8710/LAN8720 requires a minimum of 2 link pulses within 64ms of each
	 * LAN8710/LAN8720 PHY causes the PHY to misbehave, likely due
 * other in order to set the ENERGYON bit and exit EDPD mode.  If a link partner
	 * to a bug on the chip.
 * does send the pulses within this interval, the PHY will remained powered
 * down.
 *
 *
	 * When the system is powered on with the network cable being
 * This workaround will manually toggle the PHY on/off upon calls to read_status
	 * disconnected all the way until after ifconfig ethX up is
 * in order to generate link test pulses if the link is down.  If a link partner
	 * issued for the LAN port with this PHY, connecting the cable
 * is present, it will respond to the pulses, which will cause the ENERGYON bit
	 * afterwards does not cause LINK change detection, while the
 * to be set and will cause the EDPD mode to be exited.
	 * expected behavior is the Link UP being detected.
 */
 */
static int lan87xx_read_status(struct phy_device *phydev)
{
	int err = genphy_read_status(phydev);

	if (!phydev->link) {
		/* Disable EDPD to wake up PHY */
		int rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
		int rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
		if (rc < 0)
		if (rc < 0)
			return rc;
			return rc;


	rc &= ~MII_LAN83C185_EDPWRDOWN;
		rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS,
			       rc & ~MII_LAN83C185_EDPWRDOWN);
		if (rc < 0)
			return rc;

		/* Sleep 64 ms to allow ~5 link test pulses to be sent */
		msleep(64);


	rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS, rc);
		/* Re-enable EDPD */
		rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
		if (rc < 0)
		if (rc < 0)
			return rc;
			return rc;


	return smsc_phy_ack_interrupt(phydev);
		rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS,
			       rc | MII_LAN83C185_EDPWRDOWN);
		if (rc < 0)
			return rc;
	}
	}


static int lan911x_config_init(struct phy_device *phydev)
	return err;
{
	return smsc_phy_ack_interrupt(phydev);
}
}


static struct phy_driver smsc_phy_driver[] = {
static struct phy_driver smsc_phy_driver[] = {
@@ -187,8 +204,8 @@ 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	= lan87xx_config_init,
	.config_intr	= smsc_phy_config_intr,


	/* IRQ related */
	/* IRQ related */
	.ack_interrupt	= smsc_phy_ack_interrupt,
	.ack_interrupt	= smsc_phy_ack_interrupt,