diff options
Diffstat (limited to 'drivers/net/phy/marvell.c')
-rw-r--r-- | drivers/net/phy/marvell.c | 53 |
1 files changed, 52 insertions, 1 deletions
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index 2702faf7b0f6..d777c8851ed6 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c @@ -961,7 +961,21 @@ static int m88e1111_config_init(struct phy_device *phydev) if (err < 0) return err; - return genphy_soft_reset(phydev); + err = genphy_soft_reset(phydev); + if (err < 0) + return err; + + if (phydev->interface == PHY_INTERFACE_MODE_SGMII) { + /* If the HWCFG_MODE was changed from another mode (such as + * 1000BaseX) to SGMII, the state of the support bits may have + * also changed now that the PHY has been reset. + * Update the PHY abilities accordingly. + */ + err = genphy_read_abilities(phydev); + linkmode_or(phydev->advertising, phydev->advertising, + phydev->supported); + } + return err; } static int m88e1111_get_downshift(struct phy_device *phydev, u8 *data) @@ -1177,7 +1191,44 @@ static int m88e1318_config_init(struct phy_device *phydev) static int m88e1510_config_init(struct phy_device *phydev) { + static const struct { + u16 reg17, reg16; + } errata_vals[] = { + { 0x214b, 0x2144 }, + { 0x0c28, 0x2146 }, + { 0xb233, 0x214d }, + { 0xcc0c, 0x2159 }, + }; int err; + int i; + + /* As per Marvell Release Notes - Alaska 88E1510/88E1518/88E1512/ + * 88E1514 Rev A0, Errata Section 5.1: + * If EEE is intended to be used, the following register writes + * must be done once after every hardware reset. + */ + err = marvell_set_page(phydev, 0x00FF); + if (err < 0) + return err; + + for (i = 0; i < ARRAY_SIZE(errata_vals); ++i) { + err = phy_write(phydev, 17, errata_vals[i].reg17); + if (err) + return err; + err = phy_write(phydev, 16, errata_vals[i].reg16); + if (err) + return err; + } + + err = marvell_set_page(phydev, 0x00FB); + if (err < 0) + return err; + err = phy_write(phydev, 07, 0xC00D); + if (err < 0) + return err; + err = marvell_set_page(phydev, MII_MARVELL_COPPER_PAGE); + if (err < 0) + return err; /* SGMII-to-Copper mode initialization */ if (phydev->interface == PHY_INTERFACE_MODE_SGMII) { |