diff options
author | Russell King (Oracle) <rmk+kernel@armlinux.org.uk> | 2022-01-11 12:07:23 +0000 |
---|---|---|
committer | Russell King (Oracle) <rmk+kernel@armlinux.org.uk> | 2022-01-18 10:17:09 +0000 |
commit | dac82e4b99b6e496e44709945e280af792b918e9 (patch) | |
tree | 216d34bed0a0ae1365aa4666729c200f8da3090c /drivers | |
parent | 94876bfc95688ce7f9197eda96350902b7d40c22 (diff) |
net: dsa: mv88e6xxx: update 88e6390 workaround
Add a modify() helper, and use this to deal with the work around for the
88e6390, including powering the Serdes PHY down. This is necessary as we
will be removing the serdes_power implementation in a later patch.
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/dsa/mv88e6xxx/serdes.c | 36 |
1 files changed, 24 insertions, 12 deletions
diff --git a/drivers/net/dsa/mv88e6xxx/serdes.c b/drivers/net/dsa/mv88e6xxx/serdes.c index 2c1707af082a..1f6ce4cc5520 100644 --- a/drivers/net/dsa/mv88e6xxx/serdes.c +++ b/drivers/net/dsa/mv88e6xxx/serdes.c @@ -49,6 +49,22 @@ static int mv88e6390_serdes_write(struct mv88e6xxx_chip *chip, return mv88e6xxx_phy_write(chip, lane, reg_c45, val); } +static int mv88e6390_serdes_modify(struct mv88e6xxx_chip *chip, int lane, + int device, int reg, u16 mask, u16 set) +{ + int reg_c45 = MII_ADDR_C45 | device << 16 | reg; + int err; + u16 val; + + err = mv88e6xxx_phy_read(chip, lane, reg_c45, &val); + if (err) + return err; + + val = (val & ~mask) | set; + + return mv88e6xxx_phy_write(chip, lane, reg_c45, val); +} + static int mv88e6xxx_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, u16 bmsr, u16 lpa, u16 status, struct phylink_link_state *state) @@ -1340,7 +1356,6 @@ static int mv88e6393x_serdes_power_lane(struct mv88e6xxx_chip *chip, int lane, static int mv88e6393x_serdes_erratum_4_6(struct mv88e6xxx_chip *chip, int lane) { - u16 reg; int err; /* mv88e6393x family errata 4.6: @@ -1351,20 +1366,17 @@ static int mv88e6393x_serdes_erratum_4_6(struct mv88e6xxx_chip *chip, int lane) * It seems that after this workaround the SERDES is automatically * powered up (the bit is cleared), so power it down. */ - err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, - MV88E6393X_SERDES_POC, ®); + err = mv88e6390_serdes_modify(chip, lane, MDIO_MMD_PHYXS, + MV88E6393X_SERDES_POC, + MV88E6393X_SERDES_POC_PDOWN | + MV88E6393X_SERDES_POC_RESET, + MV88E6393X_SERDES_POC_RESET); if (err) return err; - reg &= ~MV88E6393X_SERDES_POC_PDOWN; - reg |= MV88E6393X_SERDES_POC_RESET; - - err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, - MV88E6393X_SERDES_POC, reg); - if (err) - return err; - - err = mv88e6390_serdes_power_sgmii(chip, lane, false); + err = mv88e6390_serdes_modify(chip, lane, MDIO_MMD_PHYXS, + MV88E6390_SGMII_BMCR, + BMCR_PDOWN, BMCR_PDOWN); if (err) return err; |