Skip to content

Commit 6149db4

Browse files
triha2workdavem330
authored andcommitted
net: phy: micrel: fix KSZ9477 PHY issues after suspend/resume
When the PHY is powered up after powered down most of the registers are reset, so the PHY setup code needs to be done again. In addition the interrupt register will need to be setup again so that link status indication works again. Fixes: 26dd297 ("net: phy: micrel: Move KSZ9477 errata fixes to PHY driver") Signed-off-by: Tristram Ha <tristram.ha@microchip.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 33700a0 commit 6149db4

File tree

1 file changed

+56
-6
lines changed

1 file changed

+56
-6
lines changed

drivers/net/phy/micrel.c

Lines changed: 56 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1939,7 +1939,7 @@ static const struct ksz9477_errata_write ksz9477_errata_writes[] = {
19391939
{0x1c, 0x20, 0xeeee},
19401940
};
19411941

1942-
static int ksz9477_config_init(struct phy_device *phydev)
1942+
static int ksz9477_phy_errata(struct phy_device *phydev)
19431943
{
19441944
int err;
19451945
int i;
@@ -1967,16 +1967,30 @@ static int ksz9477_config_init(struct phy_device *phydev)
19671967
return err;
19681968
}
19691969

1970+
err = genphy_restart_aneg(phydev);
1971+
if (err)
1972+
return err;
1973+
1974+
return err;
1975+
}
1976+
1977+
static int ksz9477_config_init(struct phy_device *phydev)
1978+
{
1979+
int err;
1980+
1981+
/* Only KSZ9897 family of switches needs this fix. */
1982+
if ((phydev->phy_id & 0xf) == 1) {
1983+
err = ksz9477_phy_errata(phydev);
1984+
if (err)
1985+
return err;
1986+
}
1987+
19701988
/* According to KSZ9477 Errata DS80000754C (Module 4) all EEE modes
19711989
* in this switch shall be regarded as broken.
19721990
*/
19731991
if (phydev->dev_flags & MICREL_NO_EEE)
19741992
phydev->eee_broken_modes = -1;
19751993

1976-
err = genphy_restart_aneg(phydev);
1977-
if (err)
1978-
return err;
1979-
19801994
return kszphy_config_init(phydev);
19811995
}
19821996

@@ -2085,6 +2099,42 @@ static int kszphy_resume(struct phy_device *phydev)
20852099
return 0;
20862100
}
20872101

2102+
static int ksz9477_resume(struct phy_device *phydev)
2103+
{
2104+
int ret;
2105+
2106+
/* No need to initialize registers if not powered down. */
2107+
ret = phy_read(phydev, MII_BMCR);
2108+
if (ret < 0)
2109+
return ret;
2110+
if (!(ret & BMCR_PDOWN))
2111+
return 0;
2112+
2113+
genphy_resume(phydev);
2114+
2115+
/* After switching from power-down to normal mode, an internal global
2116+
* reset is automatically generated. Wait a minimum of 1 ms before
2117+
* read/write access to the PHY registers.
2118+
*/
2119+
usleep_range(1000, 2000);
2120+
2121+
/* Only KSZ9897 family of switches needs this fix. */
2122+
if ((phydev->phy_id & 0xf) == 1) {
2123+
ret = ksz9477_phy_errata(phydev);
2124+
if (ret)
2125+
return ret;
2126+
}
2127+
2128+
/* Enable PHY Interrupts */
2129+
if (phy_interrupt_is_valid(phydev)) {
2130+
phydev->interrupts = PHY_INTERRUPT_ENABLED;
2131+
if (phydev->drv->config_intr)
2132+
phydev->drv->config_intr(phydev);
2133+
}
2134+
2135+
return 0;
2136+
}
2137+
20882138
static int kszphy_probe(struct phy_device *phydev)
20892139
{
20902140
const struct kszphy_type *type = phydev->drv->driver_data;
@@ -5493,7 +5543,7 @@ static struct phy_driver ksphy_driver[] = {
54935543
.config_intr = kszphy_config_intr,
54945544
.handle_interrupt = kszphy_handle_interrupt,
54955545
.suspend = genphy_suspend,
5496-
.resume = genphy_resume,
5546+
.resume = ksz9477_resume,
54975547
.get_features = ksz9477_get_features,
54985548
} };
54995549

0 commit comments

Comments
 (0)