1 diff --git a/drivers/net/dsa/mv88e6xxx/pcs-639x.c b/drivers/net/dsa/mv88e6xxx/pcs-639x.c 2 index c939cc4aa3dc..eaa01359e94e 100644 3 --- a/drivers/net/dsa/mv88e6xxx/pcs-639x.c 4 +++ b/drivers/net/dsa/mv88e6xxx/pcs-639x.c 5 @@ -85,6 +85,14 @@ mv88e639x_pcs_alloc(struct device *dev, struct mii_bus *bus, unsigned int addr, 6 return mpcs; 7 } 8 9 +static void mv88e639x_pcs_link_change(struct mv88e639x_pcs *mpcs, 10 + bool link_down) 11 +{ 12 + struct mv88e6xxx_port *port = mpcs->port; 13 + 14 + dsa_port_phylink_mac_change(port->chip->ds, port->port, !link_down); 15 +} 16 + 17 static irqreturn_t mv88e639x_pcs_handle_irq(int irq, void *dev_id) 18 { 19 struct mv88e639x_pcs *mpcs = dev_id; 20 @@ -131,14 +139,6 @@ void mv88e639x_pcs_teardown(struct mv88e6xxx_chip *chip, int port) 21 chip->ports[port].pcs_private = NULL; 22 } 23 24 -static void mv88e639x_pcs_link_change(struct mv88e639x_pcs *mpcs, 25 - bool link_down) 26 -{ 27 - struct mv88e6xxx_port *port = mpcs->port; 28 - 29 - dsa_port_phylink_mac_change(port->chip->ds, port->port, !link_down); 30 -} 31 - 32 static struct mv88e639x_pcs *sgmii_pcs_to_mv88e639x_pcs(struct phylink_pcs *pcs) 33 { 34 return container_of(pcs, struct mv88e639x_pcs, sgmii_pcs); 35 @@ -562,20 +562,13 @@ int mv88e6390_pcs_init(struct mv88e6xxx_chip *chip, int port) 36 37 /* Marvell 88E6393X Specific support */ 38 39 -static int mv88e6393x_power_lane_up(struct mv88e639x_pcs *mpcs) 40 +static int mv88e6393x_power_lane(struct mv88e639x_pcs *mpcs, bool enable) 41 { 42 - return mv88e639x_modify(mpcs, MV88E6393X_SERDES_CTRL1, 43 - MV88E6393X_SERDES_CTRL1_TX_PDOWN | 44 - MV88E6393X_SERDES_CTRL1_RX_PDOWN, 0); 45 -} 46 + u16 val = MV88E6393X_SERDES_CTRL1_TX_PDOWN | 47 + MV88E6393X_SERDES_CTRL1_RX_PDOWN; 48 49 -static int mv88e6393x_power_lane_down(struct mv88e639x_pcs *mpcs) 50 -{ 51 - return mv88e639x_modify(mpcs, MV88E6393X_SERDES_CTRL1, 52 - MV88E6393X_SERDES_CTRL1_TX_PDOWN | 53 - MV88E6393X_SERDES_CTRL1_RX_PDOWN, 54 - MV88E6393X_SERDES_CTRL1_TX_PDOWN | 55 - MV88E6393X_SERDES_CTRL1_RX_PDOWN); 56 + return mv88e639x_modify(mpcs, MV88E6393X_SERDES_CTRL1, val, 57 + enable ? 0 : val); 58 } 59 60 /* mv88e6393x family errata 4.6: 61 @@ -602,7 +595,11 @@ static int mv88e6393x_erratum_4_6(struct mv88e639x_pcs *mpcs) 62 if (err) 63 return err; 64 65 - return mv88e6393x_power_lane_down(mpcs); 66 + err = mv88e639x_sgmii_pcs_control_pwr(mpcs, false); 67 + if (err) 68 + return err; 69 + 70 + return mv88e6393x_power_lane(mpcs, false); 71 } 72 73 /* mv88e6393x family errata 4.8: 74 @@ -703,53 +700,66 @@ static int mv88e6393x_fix_2500basex_an(struct mv88e639x_pcs *mpcs, bool on) 75 mdiobus_c45_addr(MDIO_MMD_VEND1, 0x8000), 0x58); 76 } 77 78 -static void mv88e6393x_sgmii_pcs_disable(struct phylink_pcs *pcs) 79 +static int mv88e6393x_sgmii_apply_2500basex_an(struct mv88e639x_pcs *mpcs, 80 + phy_interface_t interface, 81 + bool enable) 82 { 83 - struct mv88e639x_pcs *mpcs = xg_pcs_to_mv88e639x_pcs(pcs); 84 int err; 85 86 - mv88e639x_sgmii_pcs_disable(pcs); 87 - mv88e6393x_power_lane_down(mpcs); 88 + if (interface != PHY_INTERFACE_MODE_2500BASEX) 89 + return 0; 90 91 - if (mpcs->interface == PHY_INTERFACE_MODE_2500BASEX) { 92 - err = mv88e6393x_fix_2500basex_an(mpcs, false); 93 - if (err) 94 - dev_err(mpcs->mdio.dev.parent, 95 - "failed to disable 2500basex fix: %pe\n", 96 - ERR_PTR(err)); 97 - } 98 + err = mv88e6393x_fix_2500basex_an(mpcs, enable); 99 + if (err) 100 + dev_err(mpcs->mdio.dev.parent, 101 + "failed to %s 2500basex fix: %pe\n", 102 + enable ? "enable" : "disable", ERR_PTR(err)); 103 + 104 + return err; 105 +} 106 + 107 +static void mv88e6393x_sgmii_pcs_disable(struct phylink_pcs *pcs) 108 +{ 109 + struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs); 110 + 111 + mv88e639x_sgmii_pcs_disable(pcs); 112 + mv88e6393x_power_lane(mpcs, false); 113 + mv88e6393x_sgmii_apply_2500basex_an(mpcs, mpcs->interface, false); 114 } 115 116 static void mv88e6393x_sgmii_pcs_pre_config(struct phylink_pcs *pcs, 117 phy_interface_t interface) 118 { 119 - mv88e6393x_sgmii_pcs_disable(pcs); 120 + struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs); 121 + 122 + mv88e639x_sgmii_pcs_pre_config(pcs, interface); 123 + mv88e6393x_power_lane(mpcs, false); 124 + mv88e6393x_sgmii_apply_2500basex_an(mpcs, mpcs->interface, false); 125 } 126 127 static int mv88e6393x_sgmii_pcs_post_config(struct phylink_pcs *pcs, 128 phy_interface_t interface) 129 { 130 - struct mv88e639x_pcs *mpcs = xg_pcs_to_mv88e639x_pcs(pcs); 131 + struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs); 132 int err; 133 134 err = mv88e6393x_erratum_4_8(mpcs); 135 if (err) 136 return err; 137 138 - if (interface == PHY_INTERFACE_MODE_2500BASEX) { 139 - err = mv88e6393x_fix_2500basex_an(mpcs, true); 140 - if (err) 141 - return err; 142 - } 143 + err = mv88e6393x_sgmii_apply_2500basex_an(mpcs, interface, true); 144 + if (err) 145 + return err; 146 147 - err = mv88e6393x_power_lane_up(mpcs); 148 + err = mv88e6393x_power_lane(mpcs, true); 149 if (err) 150 return err; 151 152 - return mv88e639x_sgmii_pcs_enable(pcs); 153 + return mv88e639x_sgmii_pcs_post_config(pcs, interface); 154 } 155 156 static const struct phylink_pcs_ops mv88e6393x_sgmii_pcs_ops = { 157 + .pcs_enable = mv88e639x_sgmii_pcs_enable, 158 .pcs_disable = mv88e6393x_sgmii_pcs_disable, 159 .pcs_pre_config = mv88e6393x_sgmii_pcs_pre_config, 160 .pcs_post_config = mv88e6393x_sgmii_pcs_post_config, 161 @@ -795,20 +805,32 @@ static int mv88e6393x_xg_control_irq(struct mv88e639x_pcs *mpcs, bool enable) 162 MV88E6393X_10G_INT_LINK_CHANGE, val); 163 } 164 165 +static int mv88e6393x_xg_pcs_enable(struct phylink_pcs *pcs) 166 +{ 167 + struct mv88e639x_pcs *mpcs = xg_pcs_to_mv88e639x_pcs(pcs); 168 + 169 + mpcs->handle_irq = mv88e6393x_xg_handle_irq; 170 + 171 + return mv88e6393x_xg_control_irq(mpcs, !!mpcs->irq); 172 +} 173 + 174 static void mv88e6393x_xg_pcs_disable(struct phylink_pcs *pcs) 175 { 176 struct mv88e639x_pcs *mpcs = xg_pcs_to_mv88e639x_pcs(pcs); 177 178 mv88e6393x_xg_control_irq(mpcs, false); 179 mv88e639x_xg_pcs_disable(mpcs); 180 - mv88e6393x_power_lane_down(mpcs); 181 + mv88e6393x_power_lane(mpcs, false); 182 } 183 184 /* The PCS has to be powered down while CMODE is changed */ 185 static void mv88e6393x_xg_pcs_pre_config(struct phylink_pcs *pcs, 186 phy_interface_t interface) 187 { 188 - mv88e6393x_xg_pcs_disable(pcs); 189 + struct mv88e639x_pcs *mpcs = xg_pcs_to_mv88e639x_pcs(pcs); 190 + 191 + mv88e639x_xg_pcs_disable(mpcs); 192 + mv88e6393x_power_lane(mpcs, false); 193 } 194 195 static int mv88e6393x_xg_pcs_post_config(struct phylink_pcs *pcs, 196 @@ -817,30 +839,21 @@ static int mv88e6393x_xg_pcs_post_config(struct phylink_pcs *pcs, 197 struct mv88e639x_pcs *mpcs = xg_pcs_to_mv88e639x_pcs(pcs); 198 int err; 199 200 - err = mv88e6393x_erratum_4_8(mpcs); 201 - if (err) 202 - return err; 203 - 204 if (interface == PHY_INTERFACE_MODE_10GBASER) { 205 err = mv88e6393x_erratum_5_2(mpcs); 206 if (err) 207 return err; 208 } 209 210 - err = mv88e6393x_power_lane_up(mpcs); 211 - if (err) 212 - return err; 213 - 214 - err = mv88e639x_xg_pcs_enable(mpcs); 215 + err = mv88e6393x_power_lane(mpcs, true); 216 if (err) 217 return err; 218 219 - mpcs->handle_irq = mv88e6393x_xg_handle_irq; 220 - 221 - return mv88e6393x_xg_control_irq(mpcs, !!mpcs->irq); 222 + return mv88e639x_xg_pcs_enable(mpcs); 223 } 224 225 static const struct phylink_pcs_ops mv88e6393x_xg_pcs_ops = { 226 + .pcs_enable = mv88e6393x_xg_pcs_enable, 227 .pcs_disable = mv88e6393x_xg_pcs_disable, 228 .pcs_pre_config = mv88e6393x_xg_pcs_pre_config, 229 .pcs_post_config = mv88e6393x_xg_pcs_post_config,