Skip to content

Commit 0a8d3f2

Browse files
triha2workdavem330
authored andcommitted
net: phy: Micrel KSZ8061: fix errata solution not taking effect problem
KSZ8061 needs to write to a MMD register at driver initialization to fix an errata. This worked in 5.0 kernel but not in newer kernels. The issue is the main phylib code no longer resets PHY at the very beginning. Calling phy resuming code later will reset the chip if it is already powered down at the beginning. This wipes out the MMD register write. Solution is to implement a phy resume function for KSZ8061 to take care of this problem. Fixes: 232ba3a ("net: phy: Micrel KSZ8061: link failure after cable connect") Signed-off-by: Tristram Ha <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent fb0aa07 commit 0a8d3f2

File tree

1 file changed

+41
-1
lines changed

1 file changed

+41
-1
lines changed

drivers/net/phy/micrel.c

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -866,6 +866,17 @@ static int ksz8061_config_init(struct phy_device *phydev)
866866
{
867867
int ret;
868868

869+
/* Chip can be powered down by the bootstrap code. */
870+
ret = phy_read(phydev, MII_BMCR);
871+
if (ret < 0)
872+
return ret;
873+
if (ret & BMCR_PDOWN) {
874+
ret = phy_write(phydev, MII_BMCR, ret & ~BMCR_PDOWN);
875+
if (ret < 0)
876+
return ret;
877+
usleep_range(1000, 2000);
878+
}
879+
869880
ret = phy_write_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_DEVID1, 0xB61A);
870881
if (ret)
871882
return ret;
@@ -2135,6 +2146,35 @@ static int ksz9477_resume(struct phy_device *phydev)
21352146
return 0;
21362147
}
21372148

2149+
static int ksz8061_resume(struct phy_device *phydev)
2150+
{
2151+
int ret;
2152+
2153+
/* This function can be called twice when the Ethernet device is on. */
2154+
ret = phy_read(phydev, MII_BMCR);
2155+
if (ret < 0)
2156+
return ret;
2157+
if (!(ret & BMCR_PDOWN))
2158+
return 0;
2159+
2160+
genphy_resume(phydev);
2161+
usleep_range(1000, 2000);
2162+
2163+
/* Re-program the value after chip is reset. */
2164+
ret = phy_write_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_DEVID1, 0xB61A);
2165+
if (ret)
2166+
return ret;
2167+
2168+
/* Enable PHY Interrupts */
2169+
if (phy_interrupt_is_valid(phydev)) {
2170+
phydev->interrupts = PHY_INTERRUPT_ENABLED;
2171+
if (phydev->drv->config_intr)
2172+
phydev->drv->config_intr(phydev);
2173+
}
2174+
2175+
return 0;
2176+
}
2177+
21382178
static int kszphy_probe(struct phy_device *phydev)
21392179
{
21402180
const struct kszphy_type *type = phydev->drv->driver_data;
@@ -5389,7 +5429,7 @@ static struct phy_driver ksphy_driver[] = {
53895429
.config_intr = kszphy_config_intr,
53905430
.handle_interrupt = kszphy_handle_interrupt,
53915431
.suspend = kszphy_suspend,
5392-
.resume = kszphy_resume,
5432+
.resume = ksz8061_resume,
53935433
}, {
53945434
.phy_id = PHY_ID_KSZ9021,
53955435
.phy_id_mask = 0x000ffffe,

0 commit comments

Comments
 (0)