Skip to content

Commit 4223dbf

Browse files
Patrick Tranthamdavem330
authored andcommitted
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, (b629820), 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: Patrick Trantham <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent f191a1d commit 4223dbf

File tree

1 file changed

+43
-26
lines changed

1 file changed

+43
-26
lines changed

drivers/net/phy/smsc.c

Lines changed: 43 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -56,35 +56,52 @@ static int smsc_phy_config_init(struct phy_device *phydev)
5656
return smsc_phy_ack_interrupt (phydev);
5757
}
5858

59-
static int lan87xx_config_init(struct phy_device *phydev)
59+
static int lan911x_config_init(struct phy_device *phydev)
6060
{
61-
/*
62-
* Make sure the EDPWRDOWN bit is NOT set. Setting this bit on
63-
* LAN8710/LAN8720 PHY causes the PHY to misbehave, likely due
64-
* to a bug on the chip.
65-
*
66-
* When the system is powered on with the network cable being
67-
* disconnected all the way until after ifconfig ethX up is
68-
* issued for the LAN port with this PHY, connecting the cable
69-
* afterwards does not cause LINK change detection, while the
70-
* expected behavior is the Link UP being detected.
71-
*/
72-
int rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
73-
if (rc < 0)
74-
return rc;
75-
76-
rc &= ~MII_LAN83C185_EDPWRDOWN;
77-
78-
rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS, rc);
79-
if (rc < 0)
80-
return rc;
81-
8261
return smsc_phy_ack_interrupt(phydev);
8362
}
8463

85-
static int lan911x_config_init(struct phy_device *phydev)
64+
/*
65+
* The LAN8710/LAN8720 requires a minimum of 2 link pulses within 64ms of each
66+
* other in order to set the ENERGYON bit and exit EDPD mode. If a link partner
67+
* does send the pulses within this interval, the PHY will remained powered
68+
* down.
69+
*
70+
* This workaround will manually toggle the PHY on/off upon calls to read_status
71+
* in order to generate link test pulses if the link is down. If a link partner
72+
* is present, it will respond to the pulses, which will cause the ENERGYON bit
73+
* to be set and will cause the EDPD mode to be exited.
74+
*/
75+
static int lan87xx_read_status(struct phy_device *phydev)
8676
{
87-
return smsc_phy_ack_interrupt(phydev);
77+
int err = genphy_read_status(phydev);
78+
79+
if (!phydev->link) {
80+
/* Disable EDPD to wake up PHY */
81+
int rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
82+
if (rc < 0)
83+
return rc;
84+
85+
rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS,
86+
rc & ~MII_LAN83C185_EDPWRDOWN);
87+
if (rc < 0)
88+
return rc;
89+
90+
/* Sleep 64 ms to allow ~5 link test pulses to be sent */
91+
msleep(64);
92+
93+
/* Re-enable EDPD */
94+
rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
95+
if (rc < 0)
96+
return rc;
97+
98+
rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS,
99+
rc | MII_LAN83C185_EDPWRDOWN);
100+
if (rc < 0)
101+
return rc;
102+
}
103+
104+
return err;
88105
}
89106

90107
static struct phy_driver smsc_phy_driver[] = {
@@ -187,8 +204,8 @@ static struct phy_driver smsc_phy_driver[] = {
187204

188205
/* basic functions */
189206
.config_aneg = genphy_config_aneg,
190-
.read_status = genphy_read_status,
191-
.config_init = lan87xx_config_init,
207+
.read_status = lan87xx_read_status,
208+
.config_intr = smsc_phy_config_intr,
192209

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

0 commit comments

Comments
 (0)