1 From 34a467c0a401adc514bb335ac0fc9f2197cc59a4 Mon Sep 17 00:00:00 2001 2 From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk> 3 Date: Mon, 10 Jan 2022 20:03:22 +0000 4 Subject: [PATCH] net: dsa: mv88e6xxx: convert 88e639x to phylink_pcs 5 6 Convert the 88E6390, 88E6390X, and 88E6393X family of switches to use 7 the phylink_pcs infrastructure. 8 9 Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk> 10 --- 11 drivers/net/dsa/mv88e6xxx/Makefile | 1 + 12 drivers/net/dsa/mv88e6xxx/chip.c | 98 +-- 13 drivers/net/dsa/mv88e6xxx/pcs-639x.c | 902 +++++++++++++++++++++++++++ 14 drivers/net/dsa/mv88e6xxx/serdes.c | 743 ---------------------- 15 drivers/net/dsa/mv88e6xxx/serdes.h | 36 +- 16 5 files changed, 941 insertions(+), 839 deletions(-) 17 create mode 100644 drivers/net/dsa/mv88e6xxx/pcs-639x.c 18 19 diff --git a/drivers/net/dsa/mv88e6xxx/Makefile b/drivers/net/dsa/mv88e6xxx/Makefile 20 index 03dd49d0c71f..e6062a2c1eaf 100644 21 --- a/drivers/net/dsa/mv88e6xxx/Makefile 22 +++ b/drivers/net/dsa/mv88e6xxx/Makefile 23 @@ -11,6 +11,7 @@ mv88e6xxx-objs += global2_scratch.o 24 mv88e6xxx-$(CONFIG_NET_DSA_MV88E6XXX_PTP) += hwtstamp.o 25 mv88e6xxx-objs += pcs-6185.o 26 mv88e6xxx-objs += pcs-6352.o 27 +mv88e6xxx-objs += pcs-639x.o 28 mv88e6xxx-objs += phy.o 29 mv88e6xxx-objs += port.o 30 mv88e6xxx-objs += port_hidden.o 31 diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c 32 index 4b4e27c4120c..0aa0519bab50 100644 33 --- a/drivers/net/dsa/mv88e6xxx/chip.c 34 +++ b/drivers/net/dsa/mv88e6xxx/chip.c 35 @@ -4349,16 +4349,11 @@ static const struct mv88e6xxx_ops mv88e6141_ops = { 36 .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, 37 .stu_getnext = mv88e6352_g1_stu_getnext, 38 .stu_loadpurge = mv88e6352_g1_stu_loadpurge, 39 - .serdes_power = mv88e6390_serdes_power, 40 + .pcs_init = mv88e6390_pcs_init, 41 + .pcs_teardown = mv88e639x_pcs_teardown, 42 + .pcs_select = mv88e639x_pcs_select, 43 .serdes_get_lane = mv88e6341_serdes_get_lane, 44 - /* Check status register pause & lpa register */ 45 - .serdes_pcs_get_state = mv88e6390_serdes_pcs_get_state, 46 - .serdes_pcs_config = mv88e6390_serdes_pcs_config, 47 - .serdes_pcs_an_restart = mv88e6390_serdes_pcs_an_restart, 48 - .serdes_pcs_link_up = mv88e6390_serdes_pcs_link_up, 49 .serdes_irq_mapping = mv88e6390_serdes_irq_mapping, 50 - .serdes_irq_enable = mv88e6390_serdes_irq_enable, 51 - .serdes_irq_status = mv88e6390_serdes_irq_status, 52 .gpio_ops = &mv88e6352_gpio_ops, 53 .serdes_get_sset_count = mv88e6390_serdes_get_sset_count, 54 .serdes_get_strings = mv88e6390_serdes_get_strings, 55 @@ -4733,16 +4728,11 @@ static const struct mv88e6xxx_ops mv88e6190_ops = { 56 .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge, 57 .stu_getnext = mv88e6390_g1_stu_getnext, 58 .stu_loadpurge = mv88e6390_g1_stu_loadpurge, 59 - .serdes_power = mv88e6390_serdes_power, 60 + .pcs_init = mv88e6390_pcs_init, 61 + .pcs_teardown = mv88e639x_pcs_teardown, 62 + .pcs_select = mv88e639x_pcs_select, 63 .serdes_get_lane = mv88e6390_serdes_get_lane, 64 - /* Check status register pause & lpa register */ 65 - .serdes_pcs_get_state = mv88e6390_serdes_pcs_get_state, 66 - .serdes_pcs_config = mv88e6390_serdes_pcs_config, 67 - .serdes_pcs_an_restart = mv88e6390_serdes_pcs_an_restart, 68 - .serdes_pcs_link_up = mv88e6390_serdes_pcs_link_up, 69 .serdes_irq_mapping = mv88e6390_serdes_irq_mapping, 70 - .serdes_irq_enable = mv88e6390_serdes_irq_enable, 71 - .serdes_irq_status = mv88e6390_serdes_irq_status, 72 .serdes_get_strings = mv88e6390_serdes_get_strings, 73 .serdes_get_stats = mv88e6390_serdes_get_stats, 74 .serdes_get_regs_len = mv88e6390_serdes_get_regs_len, 75 @@ -4796,16 +4786,11 @@ static const struct mv88e6xxx_ops mv88e6190x_ops = { 76 .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge, 77 .stu_getnext = mv88e6390_g1_stu_getnext, 78 .stu_loadpurge = mv88e6390_g1_stu_loadpurge, 79 - .serdes_power = mv88e6390_serdes_power, 80 + .pcs_init = mv88e6390_pcs_init, 81 + .pcs_teardown = mv88e639x_pcs_teardown, 82 + .pcs_select = mv88e639x_pcs_select, 83 .serdes_get_lane = mv88e6390x_serdes_get_lane, 84 - /* Check status register pause & lpa register */ 85 - .serdes_pcs_get_state = mv88e6390_serdes_pcs_get_state, 86 - .serdes_pcs_config = mv88e6390_serdes_pcs_config, 87 - .serdes_pcs_an_restart = mv88e6390_serdes_pcs_an_restart, 88 - .serdes_pcs_link_up = mv88e6390_serdes_pcs_link_up, 89 .serdes_irq_mapping = mv88e6390_serdes_irq_mapping, 90 - .serdes_irq_enable = mv88e6390_serdes_irq_enable, 91 - .serdes_irq_status = mv88e6390_serdes_irq_status, 92 .serdes_get_strings = mv88e6390_serdes_get_strings, 93 .serdes_get_stats = mv88e6390_serdes_get_stats, 94 .serdes_get_regs_len = mv88e6390_serdes_get_regs_len, 95 @@ -4857,16 +4842,11 @@ static const struct mv88e6xxx_ops mv88e6191_ops = { 96 .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge, 97 .stu_getnext = mv88e6390_g1_stu_getnext, 98 .stu_loadpurge = mv88e6390_g1_stu_loadpurge, 99 - .serdes_power = mv88e6390_serdes_power, 100 + .pcs_init = mv88e6390_pcs_init, 101 + .pcs_teardown = mv88e639x_pcs_teardown, 102 + .pcs_select = mv88e639x_pcs_select, 103 .serdes_get_lane = mv88e6390_serdes_get_lane, 104 - /* Check status register pause & lpa register */ 105 - .serdes_pcs_get_state = mv88e6390_serdes_pcs_get_state, 106 - .serdes_pcs_config = mv88e6390_serdes_pcs_config, 107 - .serdes_pcs_an_restart = mv88e6390_serdes_pcs_an_restart, 108 - .serdes_pcs_link_up = mv88e6390_serdes_pcs_link_up, 109 .serdes_irq_mapping = mv88e6390_serdes_irq_mapping, 110 - .serdes_irq_enable = mv88e6390_serdes_irq_enable, 111 - .serdes_irq_status = mv88e6390_serdes_irq_status, 112 .serdes_get_strings = mv88e6390_serdes_get_strings, 113 .serdes_get_stats = mv88e6390_serdes_get_stats, 114 .serdes_get_regs_len = mv88e6390_serdes_get_regs_len, 115 @@ -5018,16 +4998,11 @@ static const struct mv88e6xxx_ops mv88e6290_ops = { 116 .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge, 117 .stu_getnext = mv88e6390_g1_stu_getnext, 118 .stu_loadpurge = mv88e6390_g1_stu_loadpurge, 119 - .serdes_power = mv88e6390_serdes_power, 120 + .pcs_init = mv88e6390_pcs_init, 121 + .pcs_teardown = mv88e639x_pcs_teardown, 122 + .pcs_select = mv88e639x_pcs_select, 123 .serdes_get_lane = mv88e6390_serdes_get_lane, 124 - /* Check status register pause & lpa register */ 125 - .serdes_pcs_get_state = mv88e6390_serdes_pcs_get_state, 126 - .serdes_pcs_config = mv88e6390_serdes_pcs_config, 127 - .serdes_pcs_an_restart = mv88e6390_serdes_pcs_an_restart, 128 - .serdes_pcs_link_up = mv88e6390_serdes_pcs_link_up, 129 .serdes_irq_mapping = mv88e6390_serdes_irq_mapping, 130 - .serdes_irq_enable = mv88e6390_serdes_irq_enable, 131 - .serdes_irq_status = mv88e6390_serdes_irq_status, 132 .serdes_get_strings = mv88e6390_serdes_get_strings, 133 .serdes_get_stats = mv88e6390_serdes_get_stats, 134 .serdes_get_regs_len = mv88e6390_serdes_get_regs_len, 135 @@ -5171,16 +5146,11 @@ static const struct mv88e6xxx_ops mv88e6341_ops = { 136 .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, 137 .stu_getnext = mv88e6352_g1_stu_getnext, 138 .stu_loadpurge = mv88e6352_g1_stu_loadpurge, 139 - .serdes_power = mv88e6390_serdes_power, 140 + .pcs_init = mv88e6390_pcs_init, 141 + .pcs_teardown = mv88e639x_pcs_teardown, 142 + .pcs_select = mv88e639x_pcs_select, 143 .serdes_get_lane = mv88e6341_serdes_get_lane, 144 - /* Check status register pause & lpa register */ 145 - .serdes_pcs_get_state = mv88e6390_serdes_pcs_get_state, 146 - .serdes_pcs_config = mv88e6390_serdes_pcs_config, 147 - .serdes_pcs_an_restart = mv88e6390_serdes_pcs_an_restart, 148 - .serdes_pcs_link_up = mv88e6390_serdes_pcs_link_up, 149 .serdes_irq_mapping = mv88e6390_serdes_irq_mapping, 150 - .serdes_irq_enable = mv88e6390_serdes_irq_enable, 151 - .serdes_irq_status = mv88e6390_serdes_irq_status, 152 .gpio_ops = &mv88e6352_gpio_ops, 153 .avb_ops = &mv88e6390_avb_ops, 154 .ptp_ops = &mv88e6352_ptp_ops, 155 @@ -5389,16 +5359,11 @@ static const struct mv88e6xxx_ops mv88e6390_ops = { 156 .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge, 157 .stu_getnext = mv88e6390_g1_stu_getnext, 158 .stu_loadpurge = mv88e6390_g1_stu_loadpurge, 159 - .serdes_power = mv88e6390_serdes_power, 160 + .pcs_init = mv88e6390_pcs_init, 161 + .pcs_teardown = mv88e639x_pcs_teardown, 162 + .pcs_select = mv88e639x_pcs_select, 163 .serdes_get_lane = mv88e6390_serdes_get_lane, 164 - /* Check status register pause & lpa register */ 165 - .serdes_pcs_get_state = mv88e6390_serdes_pcs_get_state, 166 - .serdes_pcs_config = mv88e6390_serdes_pcs_config, 167 - .serdes_pcs_an_restart = mv88e6390_serdes_pcs_an_restart, 168 - .serdes_pcs_link_up = mv88e6390_serdes_pcs_link_up, 169 .serdes_irq_mapping = mv88e6390_serdes_irq_mapping, 170 - .serdes_irq_enable = mv88e6390_serdes_irq_enable, 171 - .serdes_irq_status = mv88e6390_serdes_irq_status, 172 .gpio_ops = &mv88e6352_gpio_ops, 173 .avb_ops = &mv88e6390_avb_ops, 174 .ptp_ops = &mv88e6352_ptp_ops, 175 @@ -5456,15 +5421,11 @@ static const struct mv88e6xxx_ops mv88e6390x_ops = { 176 .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge, 177 .stu_getnext = mv88e6390_g1_stu_getnext, 178 .stu_loadpurge = mv88e6390_g1_stu_loadpurge, 179 - .serdes_power = mv88e6390_serdes_power, 180 + .pcs_init = mv88e6390_pcs_init, 181 + .pcs_teardown = mv88e639x_pcs_teardown, 182 + .pcs_select = mv88e639x_pcs_select, 183 .serdes_get_lane = mv88e6390x_serdes_get_lane, 184 - .serdes_pcs_get_state = mv88e6390_serdes_pcs_get_state, 185 - .serdes_pcs_config = mv88e6390_serdes_pcs_config, 186 - .serdes_pcs_an_restart = mv88e6390_serdes_pcs_an_restart, 187 - .serdes_pcs_link_up = mv88e6390_serdes_pcs_link_up, 188 .serdes_irq_mapping = mv88e6390_serdes_irq_mapping, 189 - .serdes_irq_enable = mv88e6390_serdes_irq_enable, 190 - .serdes_irq_status = mv88e6390_serdes_irq_status, 191 .serdes_get_sset_count = mv88e6390_serdes_get_sset_count, 192 .serdes_get_strings = mv88e6390_serdes_get_strings, 193 .serdes_get_stats = mv88e6390_serdes_get_stats, 194 @@ -5478,7 +5439,6 @@ static const struct mv88e6xxx_ops mv88e6390x_ops = { 195 196 static const struct mv88e6xxx_ops mv88e6393x_ops = { 197 /* MV88E6XXX_FAMILY_6393 */ 198 - .setup_errata = mv88e6393x_serdes_setup_errata, 199 .irl_init_all = mv88e6390_g2_irl_init_all, 200 .get_eeprom = mv88e6xxx_g2_get_eeprom8, 201 .set_eeprom = mv88e6xxx_g2_set_eeprom8, 202 @@ -5526,15 +5486,11 @@ static const struct mv88e6xxx_ops mv88e6393x_ops = { 203 .vtu_loadpurge = mv88e6390_g1_vtu_loadpurge, 204 .stu_getnext = mv88e6390_g1_stu_getnext, 205 .stu_loadpurge = mv88e6390_g1_stu_loadpurge, 206 - .serdes_power = mv88e6393x_serdes_power, 207 + .pcs_init = mv88e6393x_pcs_init, 208 + .pcs_teardown = mv88e639x_pcs_teardown, 209 + .pcs_select = mv88e639x_pcs_select, 210 .serdes_get_lane = mv88e6393x_serdes_get_lane, 211 - .serdes_pcs_get_state = mv88e6393x_serdes_pcs_get_state, 212 - .serdes_pcs_config = mv88e6390_serdes_pcs_config, 213 - .serdes_pcs_an_restart = mv88e6390_serdes_pcs_an_restart, 214 - .serdes_pcs_link_up = mv88e6390_serdes_pcs_link_up, 215 .serdes_irq_mapping = mv88e6390_serdes_irq_mapping, 216 - .serdes_irq_enable = mv88e6393x_serdes_irq_enable, 217 - .serdes_irq_status = mv88e6393x_serdes_irq_status, 218 /* TODO: serdes stats */ 219 .gpio_ops = &mv88e6352_gpio_ops, 220 .avb_ops = &mv88e6390_avb_ops, 221 diff --git a/drivers/net/dsa/mv88e6xxx/pcs-639x.c b/drivers/net/dsa/mv88e6xxx/pcs-639x.c 222 new file mode 100644 223 index 000000000000..eaa01359e94e 224 --- /dev/null 225 +++ b/drivers/net/dsa/mv88e6xxx/pcs-639x.c 226 @@ -0,0 +1,902 @@ 227 +// SPDX-License-Identifier: GPL-2.0-or-later 228 +/* 229 + * Marvell 88E6352 family SERDES PCS support 230 + * 231 + * Copyright (c) 2008 Marvell Semiconductor 232 + * 233 + * Copyright (c) 2017 Andrew Lunn <andrew@lunn.ch> 234 + */ 235 +#include <linux/interrupt.h> 236 +#include <linux/irqdomain.h> 237 +#include <linux/mii.h> 238 + 239 +#include "chip.h" 240 +#include "global2.h" 241 +#include "phy.h" 242 +#include "port.h" 243 +#include "serdes.h" 244 + 245 +struct mv88e639x_pcs { 246 + struct mdio_device mdio; 247 + struct phylink_pcs sgmii_pcs; 248 + struct phylink_pcs xg_pcs; 249 + bool supports_5g; 250 + phy_interface_t interface; 251 + unsigned int irq; 252 + char name[64]; 253 + irqreturn_t (*handle_irq)(struct mv88e639x_pcs *mpcs); 254 + struct mv88e6xxx_port *port; 255 +}; 256 + 257 +static int mv88e639x_read(struct mv88e639x_pcs *mpcs, u16 regnum, u16 *val) 258 +{ 259 + u32 reg_c45 = mdiobus_c45_addr(MDIO_MMD_PHYXS, regnum); 260 + int err; 261 + 262 + err = mdiodev_read(&mpcs->mdio, reg_c45); 263 + if (err < 0) 264 + return err; 265 + 266 + *val = err; 267 + 268 + return 0; 269 +} 270 + 271 +static int mv88e639x_write(struct mv88e639x_pcs *mpcs, u16 regnum, u16 val) 272 +{ 273 + u32 reg_c45 = mdiobus_c45_addr(MDIO_MMD_PHYXS, regnum); 274 + 275 + return mdiodev_write(&mpcs->mdio, reg_c45, val); 276 +} 277 + 278 +static int mv88e639x_modify(struct mv88e639x_pcs *mpcs, u16 regnum, u16 mask, 279 + u16 val) 280 +{ 281 + u32 reg_c45 = mdiobus_c45_addr(MDIO_MMD_PHYXS, regnum); 282 + 283 + return mdiodev_modify(&mpcs->mdio, reg_c45, mask, val); 284 +} 285 + 286 +static int mv88e639x_modify_changed(struct mv88e639x_pcs *mpcs, u16 regnum, 287 + u16 mask, u16 set) 288 +{ 289 + u32 reg_c45 = mdiobus_c45_addr(MDIO_MMD_PHYXS, regnum); 290 + 291 + return mdiodev_modify_changed(&mpcs->mdio, reg_c45, mask, set); 292 +} 293 + 294 +static struct mv88e639x_pcs * 295 +mv88e639x_pcs_alloc(struct device *dev, struct mii_bus *bus, unsigned int addr, 296 + int port) 297 +{ 298 + struct mv88e639x_pcs *mpcs; 299 + 300 + mpcs = kzalloc(sizeof(*mpcs), GFP_KERNEL); 301 + if (!mpcs) 302 + return NULL; 303 + 304 + mpcs->mdio.dev.parent = dev; 305 + mpcs->mdio.bus = bus; 306 + mpcs->mdio.addr = addr; 307 + 308 + snprintf(mpcs->name, sizeof(mpcs->name), 309 + "mv88e6xxx-%s-serdes-%d", dev_name(dev), port); 310 + 311 + return mpcs; 312 +} 313 + 314 +static void mv88e639x_pcs_link_change(struct mv88e639x_pcs *mpcs, 315 + bool link_down) 316 +{ 317 + struct mv88e6xxx_port *port = mpcs->port; 318 + 319 + dsa_port_phylink_mac_change(port->chip->ds, port->port, !link_down); 320 +} 321 + 322 +static irqreturn_t mv88e639x_pcs_handle_irq(int irq, void *dev_id) 323 +{ 324 + struct mv88e639x_pcs *mpcs = dev_id; 325 + irqreturn_t (*handler)(struct mv88e639x_pcs *); 326 + 327 + handler = READ_ONCE(mpcs->handle_irq); 328 + if (!handler) 329 + return IRQ_NONE; 330 + 331 + return handler(mpcs); 332 +} 333 + 334 +static int mv88e639x_pcs_setup_irq(struct mv88e639x_pcs *mpcs, 335 + struct mv88e6xxx_chip *chip, int port) 336 +{ 337 + unsigned int irq; 338 + 339 + irq = mv88e6xxx_serdes_irq_mapping(chip, port); 340 + if (!irq) { 341 + /* Use polling mode */ 342 + mpcs->sgmii_pcs.poll = true; 343 + mpcs->xg_pcs.poll = true; 344 + return 0; 345 + } 346 + 347 + mpcs->irq = irq; 348 + 349 + return request_threaded_irq(irq, NULL, mv88e639x_pcs_handle_irq, 350 + IRQF_ONESHOT, mpcs->name, mpcs); 351 +} 352 + 353 +void mv88e639x_pcs_teardown(struct mv88e6xxx_chip *chip, int port) 354 +{ 355 + struct mv88e639x_pcs *mpcs = chip->ports[port].pcs_private; 356 + 357 + if (!mpcs) 358 + return; 359 + 360 + if (mpcs->irq) 361 + free_irq(mpcs->irq, mpcs); 362 + 363 + kfree(mpcs); 364 + 365 + chip->ports[port].pcs_private = NULL; 366 +} 367 + 368 +static struct mv88e639x_pcs *sgmii_pcs_to_mv88e639x_pcs(struct phylink_pcs *pcs) 369 +{ 370 + return container_of(pcs, struct mv88e639x_pcs, sgmii_pcs); 371 +} 372 + 373 +static irqreturn_t mv88e639x_sgmii_handle_irq(struct mv88e639x_pcs *mpcs) 374 +{ 375 + u16 int_status; 376 + bool link_down; 377 + int err; 378 + 379 + err = mv88e639x_read(mpcs, MV88E6390_SGMII_INT_STATUS, &int_status); 380 + if (err) 381 + return IRQ_NONE; 382 + 383 + if (int_status & (MV88E6390_SGMII_INT_LINK_DOWN | 384 + MV88E6390_SGMII_INT_LINK_UP)) { 385 + link_down = !!(int_status & MV88E6390_SGMII_INT_LINK_DOWN); 386 + 387 + mv88e639x_pcs_link_change(mpcs, link_down); 388 + 389 + return IRQ_HANDLED; 390 + } 391 + 392 + return IRQ_NONE; 393 +} 394 + 395 +static int mv88e639x_sgmii_pcs_control_irq(struct mv88e639x_pcs *mpcs, 396 + bool enable) 397 +{ 398 + u16 val = 0; 399 + 400 + if (enable) 401 + val |= MV88E6390_SGMII_INT_LINK_DOWN | 402 + MV88E6390_SGMII_INT_LINK_UP; 403 + 404 + return mv88e639x_modify(mpcs, MV88E6390_SGMII_INT_ENABLE, 405 + MV88E6390_SGMII_INT_LINK_DOWN | 406 + MV88E6390_SGMII_INT_LINK_UP, val); 407 +} 408 + 409 +static int mv88e639x_sgmii_pcs_control_pwr(struct mv88e639x_pcs *mpcs, 410 + bool enable) 411 +{ 412 + u16 mask, val; 413 + 414 + if (enable) { 415 + mask = BMCR_RESET | BMCR_LOOPBACK | BMCR_PDOWN; 416 + val = 0; 417 + } else { 418 + mask = val = BMCR_PDOWN; 419 + } 420 + 421 + return mv88e639x_modify(mpcs, MV88E6390_SGMII_BMCR, mask, val); 422 +} 423 + 424 +static int mv88e639x_sgmii_pcs_enable(struct phylink_pcs *pcs) 425 +{ 426 + struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs); 427 + 428 + /* power enable done in post_config */ 429 + mpcs->handle_irq = mv88e639x_sgmii_handle_irq; 430 + 431 + return mv88e639x_sgmii_pcs_control_irq(mpcs, !!mpcs->irq); 432 +} 433 + 434 +static void mv88e639x_sgmii_pcs_disable(struct phylink_pcs *pcs) 435 +{ 436 + struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs); 437 + 438 + mv88e639x_sgmii_pcs_control_irq(mpcs, false); 439 + mv88e639x_sgmii_pcs_control_pwr(mpcs, false); 440 +} 441 + 442 +static void mv88e639x_sgmii_pcs_pre_config(struct phylink_pcs *pcs, 443 + phy_interface_t interface) 444 +{ 445 + struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs); 446 + 447 + mv88e639x_sgmii_pcs_control_pwr(mpcs, false); 448 +} 449 + 450 +static int mv88e639x_sgmii_pcs_post_config(struct phylink_pcs *pcs, 451 + phy_interface_t interface) 452 +{ 453 + struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs); 454 + 455 + mv88e639x_sgmii_pcs_control_pwr(mpcs, true); 456 + 457 + return 0; 458 +} 459 + 460 +static void mv88e639x_sgmii_pcs_get_state(struct phylink_pcs *pcs, 461 + struct phylink_link_state *state) 462 +{ 463 + struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs); 464 + u16 bmsr, lpa, status; 465 + int err; 466 + 467 + err = mv88e639x_read(mpcs, MV88E6390_SGMII_BMSR, &bmsr); 468 + if (err) { 469 + dev_err(mpcs->mdio.dev.parent, 470 + "can't read Serdes PHY %s: %pe\n", 471 + "BMSR", ERR_PTR(err)); 472 + state->link = false; 473 + return; 474 + } 475 + 476 + err = mv88e639x_read(mpcs, MV88E6390_SGMII_LPA, &lpa); 477 + if (err) { 478 + dev_err(mpcs->mdio.dev.parent, 479 + "can't read Serdes PHY %s: %pe\n", 480 + "LPA", ERR_PTR(err)); 481 + state->link = false; 482 + return; 483 + } 484 + 485 + err = mv88e639x_read(mpcs, MV88E6390_SGMII_PHY_STATUS, &status); 486 + if (err) { 487 + dev_err(mpcs->mdio.dev.parent, 488 + "can't read Serdes PHY %s: %pe\n", 489 + "status", ERR_PTR(err)); 490 + state->link = false; 491 + return; 492 + } 493 + 494 + mv88e6xxx_pcs_decode_state(mpcs->mdio.dev.parent, bmsr, lpa, status, 495 + state); 496 +} 497 + 498 +static int mv88e639x_sgmii_pcs_config(struct phylink_pcs *pcs, 499 + unsigned int mode, 500 + phy_interface_t interface, 501 + const unsigned long *advertising, 502 + bool permit_pause_to_mac) 503 +{ 504 + struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs); 505 + u16 val, bmcr; 506 + bool changed; 507 + int adv, err; 508 + 509 + adv = phylink_mii_c22_pcs_encode_advertisement(interface, advertising); 510 + if (adv < 0) 511 + return 0; 512 + 513 + mpcs->interface = interface; 514 + 515 + err = mv88e639x_modify_changed(mpcs, MV88E6390_SGMII_ADVERTISE, 516 + 0xffff, adv); 517 + if (err < 0) 518 + return err; 519 + 520 + changed = err > 0; 521 + 522 + err = mv88e639x_read(mpcs, MV88E6390_SGMII_BMCR, &val); 523 + if (err) 524 + return err; 525 + 526 + if (phylink_autoneg_inband(mode)) 527 + bmcr = val | BMCR_ANENABLE; 528 + else 529 + bmcr = val & ~BMCR_ANENABLE; 530 + 531 + /* setting ANENABLE triggers a restart of negotiation */ 532 + if (bmcr == val) 533 + return changed; 534 + 535 + return mv88e639x_write(mpcs, MV88E6390_SGMII_BMCR, bmcr); 536 +} 537 + 538 +static void mv88e639x_sgmii_pcs_an_restart(struct phylink_pcs *pcs) 539 +{ 540 + struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs); 541 + 542 + mv88e639x_modify(mpcs, MV88E6390_SGMII_BMCR, 543 + BMCR_ANRESTART, BMCR_ANRESTART); 544 +} 545 + 546 +static void mv88e639x_sgmii_pcs_link_up(struct phylink_pcs *pcs, 547 + unsigned int mode, 548 + phy_interface_t interface, 549 + int speed, int duplex) 550 +{ 551 + struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs); 552 + u16 bmcr; 553 + int err; 554 + 555 + if (phylink_autoneg_inband(mode)) 556 + return; 557 + 558 + bmcr = mii_bmcr_encode_fixed(speed, duplex); 559 + 560 + err = mv88e639x_modify(mpcs, MV88E6390_SGMII_BMCR, 561 + BMCR_SPEED1000 | BMCR_SPEED100 | BMCR_FULLDPLX, 562 + bmcr); 563 + if (err) 564 + dev_err(mpcs->mdio.dev.parent, 565 + "can't access Serdes PHY %s: %pe\n", 566 + "BMCR", ERR_PTR(err)); 567 +} 568 + 569 +static const struct phylink_pcs_ops mv88e639x_sgmii_pcs_ops = { 570 + .pcs_enable = mv88e639x_sgmii_pcs_enable, 571 + .pcs_disable = mv88e639x_sgmii_pcs_disable, 572 + .pcs_pre_config = mv88e639x_sgmii_pcs_pre_config, 573 + .pcs_post_config = mv88e639x_sgmii_pcs_post_config, 574 + .pcs_get_state = mv88e639x_sgmii_pcs_get_state, 575 + .pcs_an_restart = mv88e639x_sgmii_pcs_an_restart, 576 + .pcs_config = mv88e639x_sgmii_pcs_config, 577 + .pcs_link_up = mv88e639x_sgmii_pcs_link_up, 578 +}; 579 + 580 +static struct mv88e639x_pcs *xg_pcs_to_mv88e639x_pcs(struct phylink_pcs *pcs) 581 +{ 582 + return container_of(pcs, struct mv88e639x_pcs, xg_pcs); 583 +} 584 + 585 +static int mv88e639x_xg_pcs_enable(struct mv88e639x_pcs *mpcs) 586 +{ 587 + return mv88e639x_modify(mpcs, MV88E6390_10G_CTRL1, 588 + MDIO_CTRL1_RESET | MDIO_PCS_CTRL1_LOOPBACK | 589 + MDIO_CTRL1_LPOWER, 0); 590 +} 591 + 592 +static void mv88e639x_xg_pcs_disable(struct mv88e639x_pcs *mpcs) 593 +{ 594 + mv88e639x_modify(mpcs, MV88E6390_10G_CTRL1, MDIO_CTRL1_LPOWER, 595 + MDIO_CTRL1_LPOWER); 596 +} 597 + 598 +static void mv88e639x_xg_pcs_get_state(struct phylink_pcs *pcs, 599 + struct phylink_link_state *state) 600 +{ 601 + struct mv88e639x_pcs *mpcs = xg_pcs_to_mv88e639x_pcs(pcs); 602 + u16 status; 603 + int err; 604 + 605 + state->link = false; 606 + 607 + err = mv88e639x_read(mpcs, MV88E6390_10G_STAT1, &status); 608 + if (err) { 609 + dev_err(mpcs->mdio.dev.parent, 610 + "can't read Serdes PHY %s: %pe\n", 611 + "STAT1", ERR_PTR(err)); 612 + return; 613 + } 614 + 615 + state->link = !!(status & MDIO_STAT1_LSTATUS); 616 + if (state->link) { 617 + switch (state->interface) { 618 + case PHY_INTERFACE_MODE_5GBASER: 619 + state->speed = SPEED_5000; 620 + break; 621 + 622 + case PHY_INTERFACE_MODE_10GBASER: 623 + case PHY_INTERFACE_MODE_RXAUI: 624 + case PHY_INTERFACE_MODE_XAUI: 625 + state->speed = SPEED_10000; 626 + break; 627 + 628 + default: 629 + state->link = false; 630 + return; 631 + } 632 + 633 + state->duplex = DUPLEX_FULL; 634 + } 635 +} 636 + 637 +static int mv88e639x_xg_pcs_config(struct phylink_pcs *pcs, unsigned int mode, 638 + phy_interface_t interface, 639 + const unsigned long *advertising, 640 + bool permit_pause_to_mac) 641 +{ 642 + return 0; 643 +} 644 + 645 +struct phylink_pcs *mv88e639x_pcs_select(struct mv88e6xxx_chip *chip, int port, 646 + phy_interface_t mode) 647 +{ 648 + struct mv88e639x_pcs *mpcs; 649 + 650 + mpcs = chip->ports[port].pcs_private; 651 + if (!mpcs) 652 + return NULL; 653 + 654 + switch (mode) { 655 + case PHY_INTERFACE_MODE_SGMII: 656 + case PHY_INTERFACE_MODE_1000BASEX: 657 + case PHY_INTERFACE_MODE_2500BASEX: 658 + return &mpcs->sgmii_pcs; 659 + 660 + case PHY_INTERFACE_MODE_5GBASER: 661 + if (!mpcs->supports_5g) 662 + return NULL; 663 + fallthrough; 664 + case PHY_INTERFACE_MODE_10GBASER: 665 + case PHY_INTERFACE_MODE_XAUI: 666 + case PHY_INTERFACE_MODE_RXAUI: 667 + return &mpcs->xg_pcs; 668 + 669 + default: 670 + return NULL; 671 + } 672 +} 673 + 674 +/* Marvell 88E6390 Specific support */ 675 + 676 +static irqreturn_t mv88e6390_xg_handle_irq(struct mv88e639x_pcs *mpcs) 677 +{ 678 + u16 int_status; 679 + bool link_down; 680 + int err; 681 + 682 + err = mv88e639x_read(mpcs, MV88E6390_10G_INT_STATUS, &int_status); 683 + if (err) 684 + return IRQ_NONE; 685 + 686 + if (int_status & (MV88E6390_10G_INT_LINK_DOWN | 687 + MV88E6390_10G_INT_LINK_UP)) { 688 + link_down = !!(int_status & MV88E6390_10G_INT_LINK_DOWN); 689 + 690 + mv88e639x_pcs_link_change(mpcs, link_down); 691 + 692 + return IRQ_HANDLED; 693 + } 694 + 695 + return IRQ_NONE; 696 +} 697 + 698 +static int mv88e6390_xg_control_irq(struct mv88e639x_pcs *mpcs, bool enable) 699 +{ 700 + u16 val = 0; 701 + 702 + if (enable) 703 + val = MV88E6390_10G_INT_LINK_DOWN | MV88E6390_10G_INT_LINK_UP; 704 + 705 + return mv88e639x_modify(mpcs, MV88E6390_10G_INT_ENABLE, 706 + MV88E6390_10G_INT_LINK_DOWN | 707 + MV88E6390_10G_INT_LINK_UP, val); 708 +} 709 + 710 +static int mv88e6390_xg_pcs_enable(struct phylink_pcs *pcs) 711 +{ 712 + struct mv88e639x_pcs *mpcs = xg_pcs_to_mv88e639x_pcs(pcs); 713 + int err; 714 + 715 + err = mv88e639x_xg_pcs_enable(mpcs); 716 + if (err) 717 + return err; 718 + 719 + mpcs->handle_irq = mv88e6390_xg_handle_irq; 720 + 721 + return mv88e6390_xg_control_irq(mpcs, !!mpcs->irq); 722 +} 723 + 724 +static void mv88e6390_xg_pcs_disable(struct phylink_pcs *pcs) 725 +{ 726 + struct mv88e639x_pcs *mpcs = xg_pcs_to_mv88e639x_pcs(pcs); 727 + 728 + mv88e6390_xg_control_irq(mpcs, false); 729 + mv88e639x_xg_pcs_disable(mpcs); 730 +} 731 + 732 +static const struct phylink_pcs_ops mv88e6390_xg_pcs_ops = { 733 + .pcs_enable = mv88e6390_xg_pcs_enable, 734 + .pcs_disable = mv88e6390_xg_pcs_disable, 735 + .pcs_get_state = mv88e639x_xg_pcs_get_state, 736 + .pcs_config = mv88e639x_xg_pcs_config, 737 +}; 738 + 739 +static int mv88e6390_pcs_enable_checker(struct mv88e639x_pcs *mpcs) 740 +{ 741 + return mv88e639x_modify(mpcs, MV88E6390_PG_CONTROL, 742 + MV88E6390_PG_CONTROL_ENABLE_PC, 743 + MV88E6390_PG_CONTROL_ENABLE_PC); 744 +} 745 + 746 +int mv88e6390_pcs_init(struct mv88e6xxx_chip *chip, int port) 747 +{ 748 + struct mv88e639x_pcs *mpcs; 749 + struct mii_bus *bus; 750 + struct device *dev; 751 + int lane, err; 752 + 753 + lane = mv88e6xxx_serdes_get_lane(chip, port); 754 + if (lane < 0) 755 + return 0; 756 + 757 + bus = mv88e6xxx_default_mdio_bus(chip); 758 + dev = chip->dev; 759 + 760 + mpcs = mv88e639x_pcs_alloc(dev, bus, lane, port); 761 + if (!mpcs) 762 + return -ENOMEM; 763 + 764 + mpcs->port = &chip->ports[port]; 765 + mpcs->sgmii_pcs.ops = &mv88e639x_sgmii_pcs_ops; 766 + mpcs->xg_pcs.ops = &mv88e6390_xg_pcs_ops; 767 + 768 + err = mv88e639x_pcs_setup_irq(mpcs, chip, port); 769 + if (err) 770 + goto err_free; 771 + 772 + /* 6390 and 6390x has the checker, 6393x doesn't appear to? */ 773 + /* This is to enable gathering the statistics. Maybe this 774 + * should call out to a helper? Or we could do this at init time. 775 + */ 776 + err = mv88e6390_pcs_enable_checker(mpcs); 777 + if (err) 778 + goto err_free; 779 + 780 + mpcs->port->pcs_private = mpcs; 781 + 782 + return 0; 783 + 784 +err_free: 785 + kfree(mpcs); 786 + return err; 787 +} 788 + 789 +/* Marvell 88E6393X Specific support */ 790 + 791 +static int mv88e6393x_power_lane(struct mv88e639x_pcs *mpcs, bool enable) 792 +{ 793 + u16 val = MV88E6393X_SERDES_CTRL1_TX_PDOWN | 794 + MV88E6393X_SERDES_CTRL1_RX_PDOWN; 795 + 796 + return mv88e639x_modify(mpcs, MV88E6393X_SERDES_CTRL1, val, 797 + enable ? 0 : val); 798 +} 799 + 800 +/* mv88e6393x family errata 4.6: 801 + * Cannot clear PwrDn bit on SERDES if device is configured CPU_MGD mode or 802 + * P0_mode is configured for [x]MII. 803 + * Workaround: Set SERDES register 4.F002 bit 5=0 and bit 15=1. 804 + * 805 + * It seems that after this workaround the SERDES is automatically powered up 806 + * (the bit is cleared), so power it down. 807 + */ 808 +static int mv88e6393x_erratum_4_6(struct mv88e639x_pcs *mpcs) 809 +{ 810 + int err; 811 + 812 + err = mv88e639x_modify(mpcs, MV88E6393X_SERDES_POC, 813 + MV88E6393X_SERDES_POC_PDOWN | 814 + MV88E6393X_SERDES_POC_RESET, 815 + MV88E6393X_SERDES_POC_RESET); 816 + if (err) 817 + return err; 818 + 819 + err = mv88e639x_modify(mpcs, MV88E6390_SGMII_BMCR, 820 + BMCR_PDOWN, BMCR_PDOWN); 821 + if (err) 822 + return err; 823 + 824 + err = mv88e639x_sgmii_pcs_control_pwr(mpcs, false); 825 + if (err) 826 + return err; 827 + 828 + return mv88e6393x_power_lane(mpcs, false); 829 +} 830 + 831 +/* mv88e6393x family errata 4.8: 832 + * When a SERDES port is operating in 1000BASE-X or SGMII mode link may not 833 + * come up after hardware reset or software reset of SERDES core. Workaround 834 + * is to write SERDES register 4.F074.14=1 for only those modes and 0 in all 835 + * other modes. 836 + */ 837 +static int mv88e6393x_erratum_4_8(struct mv88e639x_pcs *mpcs) 838 +{ 839 + u16 reg, poc; 840 + int err; 841 + 842 + err = mv88e639x_read(mpcs, MV88E6393X_SERDES_POC, &poc); 843 + if (err) 844 + return err; 845 + 846 + poc &= MV88E6393X_SERDES_POC_PCS_MASK; 847 + if (poc == MV88E6393X_SERDES_POC_PCS_1000BASEX || 848 + poc == MV88E6393X_SERDES_POC_PCS_SGMII_PHY || 849 + poc == MV88E6393X_SERDES_POC_PCS_SGMII_MAC) 850 + reg = MV88E6393X_ERRATA_4_8_BIT; 851 + else 852 + reg = 0; 853 + 854 + return mv88e639x_modify(mpcs, MV88E6393X_ERRATA_4_8_REG, 855 + MV88E6393X_ERRATA_4_8_BIT, reg); 856 +} 857 + 858 +/* mv88e6393x family errata 5.2: 859 + * For optimal signal integrity the following sequence should be applied to 860 + * SERDES operating in 10G mode. These registers only apply to 10G operation 861 + * and have no effect on other speeds. 862 + */ 863 +static int mv88e6393x_erratum_5_2(struct mv88e639x_pcs *mpcs) 864 +{ 865 + static const struct { 866 + u16 dev, reg, val, mask; 867 + } fixes[] = { 868 + { MDIO_MMD_VEND1, 0x8093, 0xcb5a, 0xffff }, 869 + { MDIO_MMD_VEND1, 0x8171, 0x7088, 0xffff }, 870 + { MDIO_MMD_VEND1, 0x80c9, 0x311a, 0xffff }, 871 + { MDIO_MMD_VEND1, 0x80a2, 0x8000, 0xff7f }, 872 + { MDIO_MMD_VEND1, 0x80a9, 0x0000, 0xfff0 }, 873 + { MDIO_MMD_VEND1, 0x80a3, 0x0000, 0xf8ff }, 874 + { MDIO_MMD_PHYXS, MV88E6393X_SERDES_POC, 875 + MV88E6393X_SERDES_POC_RESET, MV88E6393X_SERDES_POC_RESET }, 876 + }; 877 + int err, i; 878 + 879 + for (i = 0; i < ARRAY_SIZE(fixes); ++i) { 880 + u32 reg_c45 = mdiobus_c45_addr(fixes[i].dev, fixes[i].reg); 881 + 882 + err = mdiodev_modify(&mpcs->mdio, reg_c45, fixes[i].mask, 883 + fixes[i].val); 884 + if (err) 885 + return err; 886 + } 887 + 888 + return 0; 889 +} 890 + 891 +/* Inband AN is broken on Amethyst in 2500base-x mode when set by standard 892 + * mechanism (via cmode). 893 + * We can get around this by configuring the PCS mode to 1000base-x and then 894 + * writing value 0x58 to register 1e.8000. (This must be done while SerDes 895 + * receiver and transmitter are disabled, which is, when this function is 896 + * called.) 897 + * It seem that when we do this configuration to 2500base-x mode (by changing 898 + * PCS mode to 1000base-x and frequency to 3.125 GHz from 1.25 GHz) and then 899 + * configure to sgmii or 1000base-x, the device thinks that it already has 900 + * SerDes at 1.25 GHz and does not change the 1e.8000 register, leaving SerDes 901 + * at 3.125 GHz. 902 + * To avoid this, change PCS mode back to 2500base-x when disabling SerDes from 903 + * 2500base-x mode. 904 + */ 905 +static int mv88e6393x_fix_2500basex_an(struct mv88e639x_pcs *mpcs, bool on) 906 +{ 907 + u16 reg; 908 + int err; 909 + 910 + if (on) 911 + reg = MV88E6393X_SERDES_POC_PCS_1000BASEX | 912 + MV88E6393X_SERDES_POC_AN; 913 + else 914 + reg = MV88E6393X_SERDES_POC_PCS_2500BASEX; 915 + 916 + reg |= MV88E6393X_SERDES_POC_RESET; 917 + 918 + err = mv88e639x_modify(mpcs, MV88E6393X_SERDES_POC, 919 + MV88E6393X_SERDES_POC_PCS_MASK | 920 + MV88E6393X_SERDES_POC_AN | 921 + MV88E6393X_SERDES_POC_RESET, reg); 922 + if (err) 923 + return err; 924 + 925 + return mdiodev_write(&mpcs->mdio, 926 + mdiobus_c45_addr(MDIO_MMD_VEND1, 0x8000), 0x58); 927 +} 928 + 929 +static int mv88e6393x_sgmii_apply_2500basex_an(struct mv88e639x_pcs *mpcs, 930 + phy_interface_t interface, 931 + bool enable) 932 +{ 933 + int err; 934 + 935 + if (interface != PHY_INTERFACE_MODE_2500BASEX) 936 + return 0; 937 + 938 + err = mv88e6393x_fix_2500basex_an(mpcs, enable); 939 + if (err) 940 + dev_err(mpcs->mdio.dev.parent, 941 + "failed to %s 2500basex fix: %pe\n", 942 + enable ? "enable" : "disable", ERR_PTR(err)); 943 + 944 + return err; 945 +} 946 + 947 +static void mv88e6393x_sgmii_pcs_disable(struct phylink_pcs *pcs) 948 +{ 949 + struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs); 950 + 951 + mv88e639x_sgmii_pcs_disable(pcs); 952 + mv88e6393x_power_lane(mpcs, false); 953 + mv88e6393x_sgmii_apply_2500basex_an(mpcs, mpcs->interface, false); 954 +} 955 + 956 +static void mv88e6393x_sgmii_pcs_pre_config(struct phylink_pcs *pcs, 957 + phy_interface_t interface) 958 +{ 959 + struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs); 960 + 961 + mv88e639x_sgmii_pcs_pre_config(pcs, interface); 962 + mv88e6393x_power_lane(mpcs, false); 963 + mv88e6393x_sgmii_apply_2500basex_an(mpcs, mpcs->interface, false); 964 +} 965 + 966 +static int mv88e6393x_sgmii_pcs_post_config(struct phylink_pcs *pcs, 967 + phy_interface_t interface) 968 +{ 969 + struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs); 970 + int err; 971 + 972 + err = mv88e6393x_erratum_4_8(mpcs); 973 + if (err) 974 + return err; 975 + 976 + err = mv88e6393x_sgmii_apply_2500basex_an(mpcs, interface, true); 977 + if (err) 978 + return err; 979 + 980 + err = mv88e6393x_power_lane(mpcs, true); 981 + if (err) 982 + return err; 983 + 984 + return mv88e639x_sgmii_pcs_post_config(pcs, interface); 985 +} 986 + 987 +static const struct phylink_pcs_ops mv88e6393x_sgmii_pcs_ops = { 988 + .pcs_enable = mv88e639x_sgmii_pcs_enable, 989 + .pcs_disable = mv88e6393x_sgmii_pcs_disable, 990 + .pcs_pre_config = mv88e6393x_sgmii_pcs_pre_config, 991 + .pcs_post_config = mv88e6393x_sgmii_pcs_post_config, 992 + .pcs_get_state = mv88e639x_sgmii_pcs_get_state, 993 + .pcs_an_restart = mv88e639x_sgmii_pcs_an_restart, 994 + .pcs_config = mv88e639x_sgmii_pcs_config, 995 + .pcs_link_up = mv88e639x_sgmii_pcs_link_up, 996 +}; 997 + 998 +static irqreturn_t mv88e6393x_xg_handle_irq(struct mv88e639x_pcs *mpcs) 999 +{ 1000 + u16 int_status, stat1; 1001 + bool link_down; 1002 + int err; 1003 + 1004 + err = mv88e639x_read(mpcs, MV88E6393X_10G_INT_STATUS, &int_status); 1005 + if (err) 1006 + return IRQ_NONE; 1007 + 1008 + if (int_status & MV88E6393X_10G_INT_LINK_CHANGE) { 1009 + err = mv88e639x_read(mpcs, MV88E6390_10G_STAT1, &stat1); 1010 + if (err) 1011 + return IRQ_NONE; 1012 + 1013 + link_down = !(stat1 & MDIO_STAT1_LSTATUS); 1014 + 1015 + mv88e639x_pcs_link_change(mpcs, link_down); 1016 + 1017 + return IRQ_HANDLED; 1018 + } 1019 + 1020 + return IRQ_NONE; 1021 +} 1022 + 1023 +static int mv88e6393x_xg_control_irq(struct mv88e639x_pcs *mpcs, bool enable) 1024 +{ 1025 + u16 val = 0; 1026 + 1027 + if (enable) 1028 + val = MV88E6393X_10G_INT_LINK_CHANGE; 1029 + 1030 + return mv88e639x_modify(mpcs, MV88E6393X_10G_INT_ENABLE, 1031 + MV88E6393X_10G_INT_LINK_CHANGE, val); 1032 +} 1033 + 1034 +static int mv88e6393x_xg_pcs_enable(struct phylink_pcs *pcs) 1035 +{ 1036 + struct mv88e639x_pcs *mpcs = xg_pcs_to_mv88e639x_pcs(pcs); 1037 + 1038 + mpcs->handle_irq = mv88e6393x_xg_handle_irq; 1039 + 1040 + return mv88e6393x_xg_control_irq(mpcs, !!mpcs->irq); 1041 +} 1042 + 1043 +static void mv88e6393x_xg_pcs_disable(struct phylink_pcs *pcs) 1044 +{ 1045 + struct mv88e639x_pcs *mpcs = xg_pcs_to_mv88e639x_pcs(pcs); 1046 + 1047 + mv88e6393x_xg_control_irq(mpcs, false); 1048 + mv88e639x_xg_pcs_disable(mpcs); 1049 + mv88e6393x_power_lane(mpcs, false); 1050 +} 1051 + 1052 +/* The PCS has to be powered down while CMODE is changed */ 1053 +static void mv88e6393x_xg_pcs_pre_config(struct phylink_pcs *pcs, 1054 + phy_interface_t interface) 1055 +{ 1056 + struct mv88e639x_pcs *mpcs = xg_pcs_to_mv88e639x_pcs(pcs); 1057 + 1058 + mv88e639x_xg_pcs_disable(mpcs); 1059 + mv88e6393x_power_lane(mpcs, false); 1060 +} 1061 + 1062 +static int mv88e6393x_xg_pcs_post_config(struct phylink_pcs *pcs, 1063 + phy_interface_t interface) 1064 +{ 1065 + struct mv88e639x_pcs *mpcs = xg_pcs_to_mv88e639x_pcs(pcs); 1066 + int err; 1067 + 1068 + if (interface == PHY_INTERFACE_MODE_10GBASER) { 1069 + err = mv88e6393x_erratum_5_2(mpcs); 1070 + if (err) 1071 + return err; 1072 + } 1073 + 1074 + err = mv88e6393x_power_lane(mpcs, true); 1075 + if (err) 1076 + return err; 1077 + 1078 + return mv88e639x_xg_pcs_enable(mpcs); 1079 +} 1080 + 1081 +static const struct phylink_pcs_ops mv88e6393x_xg_pcs_ops = { 1082 + .pcs_enable = mv88e6393x_xg_pcs_enable, 1083 + .pcs_disable = mv88e6393x_xg_pcs_disable, 1084 + .pcs_pre_config = mv88e6393x_xg_pcs_pre_config, 1085 + .pcs_post_config = mv88e6393x_xg_pcs_post_config, 1086 + .pcs_get_state = mv88e639x_xg_pcs_get_state, 1087 + .pcs_config = mv88e639x_xg_pcs_config, 1088 +}; 1089 + 1090 +int mv88e6393x_pcs_init(struct mv88e6xxx_chip *chip, int port) 1091 +{ 1092 + struct mv88e639x_pcs *mpcs; 1093 + struct mii_bus *bus; 1094 + struct device *dev; 1095 + int lane, err; 1096 + 1097 + lane = mv88e6xxx_serdes_get_lane(chip, port); 1098 + if (lane < 0) 1099 + return 0; 1100 + 1101 + bus = mv88e6xxx_default_mdio_bus(chip); 1102 + dev = chip->dev; 1103 + 1104 + mpcs = mv88e639x_pcs_alloc(dev, bus, lane, port); 1105 + if (!mpcs) 1106 + return -ENOMEM; 1107 + 1108 + mpcs->port = &chip->ports[port]; 1109 + mpcs->sgmii_pcs.ops = &mv88e6393x_sgmii_pcs_ops; 1110 + mpcs->xg_pcs.ops = &mv88e6393x_xg_pcs_ops; 1111 + mpcs->supports_5g = true; 1112 + 1113 + err = mv88e6393x_erratum_4_6(mpcs); 1114 + if (err) 1115 + goto err_free; 1116 + 1117 + err = mv88e639x_pcs_setup_irq(mpcs, chip, port); 1118 + if (err) 1119 + goto err_free; 1120 + 1121 + mpcs->port->pcs_private = mpcs; 1122 + 1123 + return 0; 1124 + 1125 +err_free: 1126 + kfree(mpcs); 1127 + return err; 1128 +} 1129 diff --git a/drivers/net/dsa/mv88e6xxx/serdes.c b/drivers/net/dsa/mv88e6xxx/serdes.c 1130 index 6cb85d58e0c2..d7484732fcf1 100644 1131 --- a/drivers/net/dsa/mv88e6xxx/serdes.c 1132 +++ b/drivers/net/dsa/mv88e6xxx/serdes.c 1133 @@ -376,57 +376,6 @@ int mv88e6393x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port) 1134 return lane; 1135 } 1136 1137 -/* Set power up/down for 10GBASE-R and 10GBASE-X4/X2 */ 1138 -static int mv88e6390_serdes_power_10g(struct mv88e6xxx_chip *chip, int lane, 1139 - bool up) 1140 -{ 1141 - u16 val, new_val; 1142 - int err; 1143 - 1144 - err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, 1145 - MV88E6390_10G_CTRL1, &val); 1146 - 1147 - if (err) 1148 - return err; 1149 - 1150 - if (up) 1151 - new_val = val & ~(MDIO_CTRL1_RESET | 1152 - MDIO_PCS_CTRL1_LOOPBACK | 1153 - MDIO_CTRL1_LPOWER); 1154 - else 1155 - new_val = val | MDIO_CTRL1_LPOWER; 1156 - 1157 - if (val != new_val) 1158 - err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, 1159 - MV88E6390_10G_CTRL1, new_val); 1160 - 1161 - return err; 1162 -} 1163 - 1164 -/* Set power up/down for SGMII and 1000Base-X */ 1165 -static int mv88e6390_serdes_power_sgmii(struct mv88e6xxx_chip *chip, int lane, 1166 - bool up) 1167 -{ 1168 - u16 val, new_val; 1169 - int err; 1170 - 1171 - err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, 1172 - MV88E6390_SGMII_BMCR, &val); 1173 - if (err) 1174 - return err; 1175 - 1176 - if (up) 1177 - new_val = val & ~(BMCR_RESET | BMCR_LOOPBACK | BMCR_PDOWN); 1178 - else 1179 - new_val = val | BMCR_PDOWN; 1180 - 1181 - if (val != new_val) 1182 - err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, 1183 - MV88E6390_SGMII_BMCR, new_val); 1184 - 1185 - return err; 1186 -} 1187 - 1188 struct mv88e6390_serdes_hw_stat { 1189 char string[ETH_GSTRING_LEN]; 1190 int reg; 1191 @@ -500,444 +449,6 @@ int mv88e6390_serdes_get_stats(struct mv88e6xxx_chip *chip, int port, 1192 return ARRAY_SIZE(mv88e6390_serdes_hw_stats); 1193 } 1194 1195 -static int mv88e6390_serdes_enable_checker(struct mv88e6xxx_chip *chip, int lane) 1196 -{ 1197 - u16 reg; 1198 - int err; 1199 - 1200 - err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, 1201 - MV88E6390_PG_CONTROL, ®); 1202 - if (err) 1203 - return err; 1204 - 1205 - reg |= MV88E6390_PG_CONTROL_ENABLE_PC; 1206 - return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, 1207 - MV88E6390_PG_CONTROL, reg); 1208 -} 1209 - 1210 -int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane, 1211 - bool up) 1212 -{ 1213 - u8 cmode = chip->ports[port].cmode; 1214 - int err; 1215 - 1216 - switch (cmode) { 1217 - case MV88E6XXX_PORT_STS_CMODE_SGMII: 1218 - case MV88E6XXX_PORT_STS_CMODE_1000BASEX: 1219 - case MV88E6XXX_PORT_STS_CMODE_2500BASEX: 1220 - err = mv88e6390_serdes_power_sgmii(chip, lane, up); 1221 - break; 1222 - case MV88E6XXX_PORT_STS_CMODE_XAUI: 1223 - case MV88E6XXX_PORT_STS_CMODE_RXAUI: 1224 - err = mv88e6390_serdes_power_10g(chip, lane, up); 1225 - break; 1226 - default: 1227 - err = -EINVAL; 1228 - break; 1229 - } 1230 - 1231 - if (!err && up) 1232 - err = mv88e6390_serdes_enable_checker(chip, lane); 1233 - 1234 - return err; 1235 -} 1236 - 1237 -int mv88e6390_serdes_pcs_config(struct mv88e6xxx_chip *chip, int port, 1238 - int lane, unsigned int mode, 1239 - phy_interface_t interface, 1240 - const unsigned long *advertise) 1241 -{ 1242 - u16 val, bmcr, adv; 1243 - bool changed; 1244 - int err; 1245 - 1246 - switch (interface) { 1247 - case PHY_INTERFACE_MODE_SGMII: 1248 - adv = 0x0001; 1249 - break; 1250 - 1251 - case PHY_INTERFACE_MODE_1000BASEX: 1252 - adv = linkmode_adv_to_mii_adv_x(advertise, 1253 - ETHTOOL_LINK_MODE_1000baseX_Full_BIT); 1254 - break; 1255 - 1256 - case PHY_INTERFACE_MODE_2500BASEX: 1257 - adv = linkmode_adv_to_mii_adv_x(advertise, 1258 - ETHTOOL_LINK_MODE_2500baseX_Full_BIT); 1259 - break; 1260 - 1261 - default: 1262 - return 0; 1263 - } 1264 - 1265 - err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, 1266 - MV88E6390_SGMII_ADVERTISE, &val); 1267 - if (err) 1268 - return err; 1269 - 1270 - changed = val != adv; 1271 - if (changed) { 1272 - err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, 1273 - MV88E6390_SGMII_ADVERTISE, adv); 1274 - if (err) 1275 - return err; 1276 - } 1277 - 1278 - err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, 1279 - MV88E6390_SGMII_BMCR, &val); 1280 - if (err) 1281 - return err; 1282 - 1283 - if (phylink_autoneg_inband(mode)) 1284 - bmcr = val | BMCR_ANENABLE; 1285 - else 1286 - bmcr = val & ~BMCR_ANENABLE; 1287 - 1288 - /* setting ANENABLE triggers a restart of negotiation */ 1289 - if (bmcr == val) 1290 - return changed; 1291 - 1292 - return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, 1293 - MV88E6390_SGMII_BMCR, bmcr); 1294 -} 1295 - 1296 -static int mv88e6390_serdes_pcs_get_state_sgmii(struct mv88e6xxx_chip *chip, 1297 - int port, int lane, struct phylink_link_state *state) 1298 -{ 1299 - u16 bmsr, lpa, status; 1300 - int err; 1301 - 1302 - err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, 1303 - MV88E6390_SGMII_BMSR, &bmsr); 1304 - if (err) { 1305 - dev_err(chip->dev, "can't read Serdes PHY BMSR: %d\n", err); 1306 - return err; 1307 - } 1308 - 1309 - err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, 1310 - MV88E6390_SGMII_PHY_STATUS, &status); 1311 - if (err) { 1312 - dev_err(chip->dev, "can't read Serdes PHY status: %d\n", err); 1313 - return err; 1314 - } 1315 - 1316 - err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, 1317 - MV88E6390_SGMII_LPA, &lpa); 1318 - if (err) { 1319 - dev_err(chip->dev, "can't read Serdes PHY LPA: %d\n", err); 1320 - return err; 1321 - } 1322 - 1323 - return mv88e6xxx_pcs_decode_state(chip->dev, bmsr, lpa, status, state); 1324 -} 1325 - 1326 -static int mv88e6390_serdes_pcs_get_state_10g(struct mv88e6xxx_chip *chip, 1327 - int port, int lane, struct phylink_link_state *state) 1328 -{ 1329 - u16 status; 1330 - int err; 1331 - 1332 - err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, 1333 - MV88E6390_10G_STAT1, &status); 1334 - if (err) 1335 - return err; 1336 - 1337 - state->link = !!(status & MDIO_STAT1_LSTATUS); 1338 - if (state->link) { 1339 - state->speed = SPEED_10000; 1340 - state->duplex = DUPLEX_FULL; 1341 - } 1342 - 1343 - return 0; 1344 -} 1345 - 1346 -static int mv88e6393x_serdes_pcs_get_state_10g(struct mv88e6xxx_chip *chip, 1347 - int port, int lane, 1348 - struct phylink_link_state *state) 1349 -{ 1350 - u16 status; 1351 - int err; 1352 - 1353 - err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, 1354 - MV88E6390_10G_STAT1, &status); 1355 - if (err) 1356 - return err; 1357 - 1358 - state->link = !!(status & MDIO_STAT1_LSTATUS); 1359 - if (state->link) { 1360 - if (state->interface == PHY_INTERFACE_MODE_5GBASER) 1361 - state->speed = SPEED_5000; 1362 - else 1363 - state->speed = SPEED_10000; 1364 - state->duplex = DUPLEX_FULL; 1365 - } 1366 - 1367 - return 0; 1368 -} 1369 - 1370 -int mv88e6390_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port, 1371 - int lane, struct phylink_link_state *state) 1372 -{ 1373 - switch (state->interface) { 1374 - case PHY_INTERFACE_MODE_SGMII: 1375 - case PHY_INTERFACE_MODE_1000BASEX: 1376 - case PHY_INTERFACE_MODE_2500BASEX: 1377 - return mv88e6390_serdes_pcs_get_state_sgmii(chip, port, lane, 1378 - state); 1379 - case PHY_INTERFACE_MODE_XAUI: 1380 - case PHY_INTERFACE_MODE_RXAUI: 1381 - return mv88e6390_serdes_pcs_get_state_10g(chip, port, lane, 1382 - state); 1383 - 1384 - default: 1385 - return -EOPNOTSUPP; 1386 - } 1387 -} 1388 - 1389 -int mv88e6393x_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port, 1390 - int lane, struct phylink_link_state *state) 1391 -{ 1392 - switch (state->interface) { 1393 - case PHY_INTERFACE_MODE_SGMII: 1394 - case PHY_INTERFACE_MODE_1000BASEX: 1395 - case PHY_INTERFACE_MODE_2500BASEX: 1396 - return mv88e6390_serdes_pcs_get_state_sgmii(chip, port, lane, 1397 - state); 1398 - case PHY_INTERFACE_MODE_5GBASER: 1399 - case PHY_INTERFACE_MODE_10GBASER: 1400 - return mv88e6393x_serdes_pcs_get_state_10g(chip, port, lane, 1401 - state); 1402 - 1403 - default: 1404 - return -EOPNOTSUPP; 1405 - } 1406 -} 1407 - 1408 -int mv88e6390_serdes_pcs_an_restart(struct mv88e6xxx_chip *chip, int port, 1409 - int lane) 1410 -{ 1411 - u16 bmcr; 1412 - int err; 1413 - 1414 - err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, 1415 - MV88E6390_SGMII_BMCR, &bmcr); 1416 - if (err) 1417 - return err; 1418 - 1419 - return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, 1420 - MV88E6390_SGMII_BMCR, 1421 - bmcr | BMCR_ANRESTART); 1422 -} 1423 - 1424 -int mv88e6390_serdes_pcs_link_up(struct mv88e6xxx_chip *chip, int port, 1425 - int lane, int speed, int duplex) 1426 -{ 1427 - u16 val, bmcr; 1428 - int err; 1429 - 1430 - err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, 1431 - MV88E6390_SGMII_BMCR, &val); 1432 - if (err) 1433 - return err; 1434 - 1435 - bmcr = val & ~(BMCR_SPEED100 | BMCR_FULLDPLX | BMCR_SPEED1000); 1436 - switch (speed) { 1437 - case SPEED_2500: 1438 - case SPEED_1000: 1439 - bmcr |= BMCR_SPEED1000; 1440 - break; 1441 - case SPEED_100: 1442 - bmcr |= BMCR_SPEED100; 1443 - break; 1444 - case SPEED_10: 1445 - break; 1446 - } 1447 - 1448 - if (duplex == DUPLEX_FULL) 1449 - bmcr |= BMCR_FULLDPLX; 1450 - 1451 - if (bmcr == val) 1452 - return 0; 1453 - 1454 - return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, 1455 - MV88E6390_SGMII_BMCR, bmcr); 1456 -} 1457 - 1458 -static void mv88e6390_serdes_irq_link_sgmii(struct mv88e6xxx_chip *chip, 1459 - int port, int lane) 1460 -{ 1461 - u16 bmsr; 1462 - int err; 1463 - 1464 - /* If the link has dropped, we want to know about it. */ 1465 - err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, 1466 - MV88E6390_SGMII_BMSR, &bmsr); 1467 - if (err) { 1468 - dev_err(chip->dev, "can't read Serdes BMSR: %d\n", err); 1469 - return; 1470 - } 1471 - 1472 - dsa_port_phylink_mac_change(chip->ds, port, !!(bmsr & BMSR_LSTATUS)); 1473 -} 1474 - 1475 -static void mv88e6393x_serdes_irq_link_10g(struct mv88e6xxx_chip *chip, 1476 - int port, u8 lane) 1477 -{ 1478 - u16 status; 1479 - int err; 1480 - 1481 - /* If the link has dropped, we want to know about it. */ 1482 - err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, 1483 - MV88E6390_10G_STAT1, &status); 1484 - if (err) { 1485 - dev_err(chip->dev, "can't read Serdes STAT1: %d\n", err); 1486 - return; 1487 - } 1488 - 1489 - dsa_port_phylink_mac_change(chip->ds, port, !!(status & MDIO_STAT1_LSTATUS)); 1490 -} 1491 - 1492 -static int mv88e6390_serdes_irq_enable_sgmii(struct mv88e6xxx_chip *chip, 1493 - int lane, bool enable) 1494 -{ 1495 - u16 val = 0; 1496 - 1497 - if (enable) 1498 - val |= MV88E6390_SGMII_INT_LINK_DOWN | 1499 - MV88E6390_SGMII_INT_LINK_UP; 1500 - 1501 - return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, 1502 - MV88E6390_SGMII_INT_ENABLE, val); 1503 -} 1504 - 1505 -int mv88e6390_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, int lane, 1506 - bool enable) 1507 -{ 1508 - u8 cmode = chip->ports[port].cmode; 1509 - 1510 - switch (cmode) { 1511 - case MV88E6XXX_PORT_STS_CMODE_SGMII: 1512 - case MV88E6XXX_PORT_STS_CMODE_1000BASEX: 1513 - case MV88E6XXX_PORT_STS_CMODE_2500BASEX: 1514 - return mv88e6390_serdes_irq_enable_sgmii(chip, lane, enable); 1515 - } 1516 - 1517 - return 0; 1518 -} 1519 - 1520 -static int mv88e6390_serdes_irq_status_sgmii(struct mv88e6xxx_chip *chip, 1521 - int lane, u16 *status) 1522 -{ 1523 - int err; 1524 - 1525 - err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, 1526 - MV88E6390_SGMII_INT_STATUS, status); 1527 - 1528 - return err; 1529 -} 1530 - 1531 -static int mv88e6393x_serdes_irq_enable_10g(struct mv88e6xxx_chip *chip, 1532 - u8 lane, bool enable) 1533 -{ 1534 - u16 val = 0; 1535 - 1536 - if (enable) 1537 - val |= MV88E6393X_10G_INT_LINK_CHANGE; 1538 - 1539 - return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, 1540 - MV88E6393X_10G_INT_ENABLE, val); 1541 -} 1542 - 1543 -int mv88e6393x_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, 1544 - int lane, bool enable) 1545 -{ 1546 - u8 cmode = chip->ports[port].cmode; 1547 - 1548 - switch (cmode) { 1549 - case MV88E6XXX_PORT_STS_CMODE_SGMII: 1550 - case MV88E6XXX_PORT_STS_CMODE_1000BASEX: 1551 - case MV88E6XXX_PORT_STS_CMODE_2500BASEX: 1552 - return mv88e6390_serdes_irq_enable_sgmii(chip, lane, enable); 1553 - case MV88E6393X_PORT_STS_CMODE_5GBASER: 1554 - case MV88E6393X_PORT_STS_CMODE_10GBASER: 1555 - return mv88e6393x_serdes_irq_enable_10g(chip, lane, enable); 1556 - } 1557 - 1558 - return 0; 1559 -} 1560 - 1561 -static int mv88e6393x_serdes_irq_status_10g(struct mv88e6xxx_chip *chip, 1562 - u8 lane, u16 *status) 1563 -{ 1564 - int err; 1565 - 1566 - err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, 1567 - MV88E6393X_10G_INT_STATUS, status); 1568 - 1569 - return err; 1570 -} 1571 - 1572 -irqreturn_t mv88e6393x_serdes_irq_status(struct mv88e6xxx_chip *chip, int port, 1573 - int lane) 1574 -{ 1575 - u8 cmode = chip->ports[port].cmode; 1576 - irqreturn_t ret = IRQ_NONE; 1577 - u16 status; 1578 - int err; 1579 - 1580 - switch (cmode) { 1581 - case MV88E6XXX_PORT_STS_CMODE_SGMII: 1582 - case MV88E6XXX_PORT_STS_CMODE_1000BASEX: 1583 - case MV88E6XXX_PORT_STS_CMODE_2500BASEX: 1584 - err = mv88e6390_serdes_irq_status_sgmii(chip, lane, &status); 1585 - if (err) 1586 - return ret; 1587 - if (status & (MV88E6390_SGMII_INT_LINK_DOWN | 1588 - MV88E6390_SGMII_INT_LINK_UP)) { 1589 - ret = IRQ_HANDLED; 1590 - mv88e6390_serdes_irq_link_sgmii(chip, port, lane); 1591 - } 1592 - break; 1593 - case MV88E6393X_PORT_STS_CMODE_5GBASER: 1594 - case MV88E6393X_PORT_STS_CMODE_10GBASER: 1595 - err = mv88e6393x_serdes_irq_status_10g(chip, lane, &status); 1596 - if (err) 1597 - return err; 1598 - if (status & MV88E6393X_10G_INT_LINK_CHANGE) { 1599 - ret = IRQ_HANDLED; 1600 - mv88e6393x_serdes_irq_link_10g(chip, port, lane); 1601 - } 1602 - break; 1603 - } 1604 - 1605 - return ret; 1606 -} 1607 - 1608 -irqreturn_t mv88e6390_serdes_irq_status(struct mv88e6xxx_chip *chip, int port, 1609 - int lane) 1610 -{ 1611 - u8 cmode = chip->ports[port].cmode; 1612 - irqreturn_t ret = IRQ_NONE; 1613 - u16 status; 1614 - int err; 1615 - 1616 - switch (cmode) { 1617 - case MV88E6XXX_PORT_STS_CMODE_SGMII: 1618 - case MV88E6XXX_PORT_STS_CMODE_1000BASEX: 1619 - case MV88E6XXX_PORT_STS_CMODE_2500BASEX: 1620 - err = mv88e6390_serdes_irq_status_sgmii(chip, lane, &status); 1621 - if (err) 1622 - return ret; 1623 - if (status & (MV88E6390_SGMII_INT_LINK_DOWN | 1624 - MV88E6390_SGMII_INT_LINK_UP)) { 1625 - ret = IRQ_HANDLED; 1626 - mv88e6390_serdes_irq_link_sgmii(chip, port, lane); 1627 - } 1628 - } 1629 - 1630 - return ret; 1631 -} 1632 - 1633 unsigned int mv88e6390_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port) 1634 { 1635 return irq_find_mapping(chip->g2_irq.domain, port); 1636 @@ -1036,257 +547,3 @@ int mv88e6352_serdes_set_tx_amplitude(struct mv88e6xxx_chip *chip, int port, 1637 1638 return mv88e6352_serdes_write(chip, MV88E6352_SERDES_SPEC_CTRL2, ctrl); 1639 } 1640 - 1641 -static int mv88e6393x_serdes_power_lane(struct mv88e6xxx_chip *chip, int lane, 1642 - bool on) 1643 -{ 1644 - u16 reg; 1645 - int err; 1646 - 1647 - err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, 1648 - MV88E6393X_SERDES_CTRL1, ®); 1649 - if (err) 1650 - return err; 1651 - 1652 - if (on) 1653 - reg &= ~(MV88E6393X_SERDES_CTRL1_TX_PDOWN | 1654 - MV88E6393X_SERDES_CTRL1_RX_PDOWN); 1655 - else 1656 - reg |= MV88E6393X_SERDES_CTRL1_TX_PDOWN | 1657 - MV88E6393X_SERDES_CTRL1_RX_PDOWN; 1658 - 1659 - return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, 1660 - MV88E6393X_SERDES_CTRL1, reg); 1661 -} 1662 - 1663 -static int mv88e6393x_serdes_erratum_4_6(struct mv88e6xxx_chip *chip, int lane) 1664 -{ 1665 - u16 reg; 1666 - int err; 1667 - 1668 - /* mv88e6393x family errata 4.6: 1669 - * Cannot clear PwrDn bit on SERDES if device is configured CPU_MGD 1670 - * mode or P0_mode is configured for [x]MII. 1671 - * Workaround: Set SERDES register 4.F002 bit 5=0 and bit 15=1. 1672 - * 1673 - * It seems that after this workaround the SERDES is automatically 1674 - * powered up (the bit is cleared), so power it down. 1675 - */ 1676 - err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, 1677 - MV88E6393X_SERDES_POC, ®); 1678 - if (err) 1679 - return err; 1680 - 1681 - reg &= ~MV88E6393X_SERDES_POC_PDOWN; 1682 - reg |= MV88E6393X_SERDES_POC_RESET; 1683 - 1684 - err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, 1685 - MV88E6393X_SERDES_POC, reg); 1686 - if (err) 1687 - return err; 1688 - 1689 - err = mv88e6390_serdes_power_sgmii(chip, lane, false); 1690 - if (err) 1691 - return err; 1692 - 1693 - return mv88e6393x_serdes_power_lane(chip, lane, false); 1694 -} 1695 - 1696 -int mv88e6393x_serdes_setup_errata(struct mv88e6xxx_chip *chip) 1697 -{ 1698 - int err; 1699 - 1700 - err = mv88e6393x_serdes_erratum_4_6(chip, MV88E6393X_PORT0_LANE); 1701 - if (err) 1702 - return err; 1703 - 1704 - err = mv88e6393x_serdes_erratum_4_6(chip, MV88E6393X_PORT9_LANE); 1705 - if (err) 1706 - return err; 1707 - 1708 - return mv88e6393x_serdes_erratum_4_6(chip, MV88E6393X_PORT10_LANE); 1709 -} 1710 - 1711 -static int mv88e6393x_serdes_erratum_4_8(struct mv88e6xxx_chip *chip, int lane) 1712 -{ 1713 - u16 reg, pcs; 1714 - int err; 1715 - 1716 - /* mv88e6393x family errata 4.8: 1717 - * When a SERDES port is operating in 1000BASE-X or SGMII mode link may 1718 - * not come up after hardware reset or software reset of SERDES core. 1719 - * Workaround is to write SERDES register 4.F074.14=1 for only those 1720 - * modes and 0 in all other modes. 1721 - */ 1722 - err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, 1723 - MV88E6393X_SERDES_POC, &pcs); 1724 - if (err) 1725 - return err; 1726 - 1727 - pcs &= MV88E6393X_SERDES_POC_PCS_MASK; 1728 - 1729 - err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, 1730 - MV88E6393X_ERRATA_4_8_REG, ®); 1731 - if (err) 1732 - return err; 1733 - 1734 - if (pcs == MV88E6393X_SERDES_POC_PCS_1000BASEX || 1735 - pcs == MV88E6393X_SERDES_POC_PCS_SGMII_PHY || 1736 - pcs == MV88E6393X_SERDES_POC_PCS_SGMII_MAC) 1737 - reg |= MV88E6393X_ERRATA_4_8_BIT; 1738 - else 1739 - reg &= ~MV88E6393X_ERRATA_4_8_BIT; 1740 - 1741 - return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, 1742 - MV88E6393X_ERRATA_4_8_REG, reg); 1743 -} 1744 - 1745 -static int mv88e6393x_serdes_erratum_5_2(struct mv88e6xxx_chip *chip, int lane, 1746 - u8 cmode) 1747 -{ 1748 - static const struct { 1749 - u16 dev, reg, val, mask; 1750 - } fixes[] = { 1751 - { MDIO_MMD_VEND1, 0x8093, 0xcb5a, 0xffff }, 1752 - { MDIO_MMD_VEND1, 0x8171, 0x7088, 0xffff }, 1753 - { MDIO_MMD_VEND1, 0x80c9, 0x311a, 0xffff }, 1754 - { MDIO_MMD_VEND1, 0x80a2, 0x8000, 0xff7f }, 1755 - { MDIO_MMD_VEND1, 0x80a9, 0x0000, 0xfff0 }, 1756 - { MDIO_MMD_VEND1, 0x80a3, 0x0000, 0xf8ff }, 1757 - { MDIO_MMD_PHYXS, MV88E6393X_SERDES_POC, 1758 - MV88E6393X_SERDES_POC_RESET, MV88E6393X_SERDES_POC_RESET }, 1759 - }; 1760 - int err, i; 1761 - u16 reg; 1762 - 1763 - /* mv88e6393x family errata 5.2: 1764 - * For optimal signal integrity the following sequence should be applied 1765 - * to SERDES operating in 10G mode. These registers only apply to 10G 1766 - * operation and have no effect on other speeds. 1767 - */ 1768 - if (cmode != MV88E6393X_PORT_STS_CMODE_10GBASER) 1769 - return 0; 1770 - 1771 - for (i = 0; i < ARRAY_SIZE(fixes); ++i) { 1772 - err = mv88e6390_serdes_read(chip, lane, fixes[i].dev, 1773 - fixes[i].reg, ®); 1774 - if (err) 1775 - return err; 1776 - 1777 - reg &= ~fixes[i].mask; 1778 - reg |= fixes[i].val; 1779 - 1780 - err = mv88e6390_serdes_write(chip, lane, fixes[i].dev, 1781 - fixes[i].reg, reg); 1782 - if (err) 1783 - return err; 1784 - } 1785 - 1786 - return 0; 1787 -} 1788 - 1789 -static int mv88e6393x_serdes_fix_2500basex_an(struct mv88e6xxx_chip *chip, 1790 - int lane, u8 cmode, bool on) 1791 -{ 1792 - u16 reg; 1793 - int err; 1794 - 1795 - if (cmode != MV88E6XXX_PORT_STS_CMODE_2500BASEX) 1796 - return 0; 1797 - 1798 - /* Inband AN is broken on Amethyst in 2500base-x mode when set by 1799 - * standard mechanism (via cmode). 1800 - * We can get around this by configuring the PCS mode to 1000base-x 1801 - * and then writing value 0x58 to register 1e.8000. (This must be done 1802 - * while SerDes receiver and transmitter are disabled, which is, when 1803 - * this function is called.) 1804 - * It seem that when we do this configuration to 2500base-x mode (by 1805 - * changing PCS mode to 1000base-x and frequency to 3.125 GHz from 1806 - * 1.25 GHz) and then configure to sgmii or 1000base-x, the device 1807 - * thinks that it already has SerDes at 1.25 GHz and does not change 1808 - * the 1e.8000 register, leaving SerDes at 3.125 GHz. 1809 - * To avoid this, change PCS mode back to 2500base-x when disabling 1810 - * SerDes from 2500base-x mode. 1811 - */ 1812 - err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, 1813 - MV88E6393X_SERDES_POC, ®); 1814 - if (err) 1815 - return err; 1816 - 1817 - reg &= ~(MV88E6393X_SERDES_POC_PCS_MASK | MV88E6393X_SERDES_POC_AN); 1818 - if (on) 1819 - reg |= MV88E6393X_SERDES_POC_PCS_1000BASEX | 1820 - MV88E6393X_SERDES_POC_AN; 1821 - else 1822 - reg |= MV88E6393X_SERDES_POC_PCS_2500BASEX; 1823 - reg |= MV88E6393X_SERDES_POC_RESET; 1824 - 1825 - err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, 1826 - MV88E6393X_SERDES_POC, reg); 1827 - if (err) 1828 - return err; 1829 - 1830 - err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_VEND1, 0x8000, 0x58); 1831 - if (err) 1832 - return err; 1833 - 1834 - return 0; 1835 -} 1836 - 1837 -int mv88e6393x_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane, 1838 - bool on) 1839 -{ 1840 - u8 cmode = chip->ports[port].cmode; 1841 - int err; 1842 - 1843 - if (port != 0 && port != 9 && port != 10) 1844 - return -EOPNOTSUPP; 1845 - 1846 - if (on) { 1847 - err = mv88e6393x_serdes_erratum_4_8(chip, lane); 1848 - if (err) 1849 - return err; 1850 - 1851 - err = mv88e6393x_serdes_erratum_5_2(chip, lane, cmode); 1852 - if (err) 1853 - return err; 1854 - 1855 - err = mv88e6393x_serdes_fix_2500basex_an(chip, lane, cmode, 1856 - true); 1857 - if (err) 1858 - return err; 1859 - 1860 - err = mv88e6393x_serdes_power_lane(chip, lane, true); 1861 - if (err) 1862 - return err; 1863 - } 1864 - 1865 - switch (cmode) { 1866 - case MV88E6XXX_PORT_STS_CMODE_SGMII: 1867 - case MV88E6XXX_PORT_STS_CMODE_1000BASEX: 1868 - case MV88E6XXX_PORT_STS_CMODE_2500BASEX: 1869 - err = mv88e6390_serdes_power_sgmii(chip, lane, on); 1870 - break; 1871 - case MV88E6393X_PORT_STS_CMODE_5GBASER: 1872 - case MV88E6393X_PORT_STS_CMODE_10GBASER: 1873 - err = mv88e6390_serdes_power_10g(chip, lane, on); 1874 - break; 1875 - default: 1876 - err = -EINVAL; 1877 - break; 1878 - } 1879 - 1880 - if (err) 1881 - return err; 1882 - 1883 - if (!on) { 1884 - err = mv88e6393x_serdes_power_lane(chip, lane, false); 1885 - if (err) 1886 - return err; 1887 - 1888 - err = mv88e6393x_serdes_fix_2500basex_an(chip, lane, cmode, 1889 - false); 1890 - } 1891 - 1892 - return err; 1893 -} 1894 diff --git a/drivers/net/dsa/mv88e6xxx/serdes.h b/drivers/net/dsa/mv88e6xxx/serdes.h 1895 index 8d3e068665cf..6d8248592877 100644 1896 --- a/drivers/net/dsa/mv88e6xxx/serdes.h 1897 +++ b/drivers/net/dsa/mv88e6xxx/serdes.h 1898 @@ -46,6 +46,10 @@ struct phylink_link_state; 1899 /* 10GBASE-R and 10GBASE-X4/X2 */ 1900 #define MV88E6390_10G_CTRL1 (0x1000 + MDIO_CTRL1) 1901 #define MV88E6390_10G_STAT1 (0x1000 + MDIO_STAT1) 1902 +#define MV88E6390_10G_INT_ENABLE 0x9001 1903 +#define MV88E6390_10G_INT_LINK_DOWN BIT(3) 1904 +#define MV88E6390_10G_INT_LINK_UP BIT(2) 1905 +#define MV88E6390_10G_INT_STATUS 0x9003 1906 #define MV88E6393X_10G_INT_ENABLE 0x9000 1907 #define MV88E6393X_10G_INT_LINK_CHANGE BIT(2) 1908 #define MV88E6393X_10G_INT_STATUS 0x9001 1909 @@ -112,35 +116,10 @@ int mv88e6341_serdes_get_lane(struct mv88e6xxx_chip *chip, int port); 1910 int mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port); 1911 int mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port); 1912 int mv88e6393x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port); 1913 -int mv88e6390_serdes_pcs_config(struct mv88e6xxx_chip *chip, int port, 1914 - int lane, unsigned int mode, 1915 - phy_interface_t interface, 1916 - const unsigned long *advertise); 1917 -int mv88e6390_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port, 1918 - int lane, struct phylink_link_state *state); 1919 -int mv88e6393x_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port, 1920 - int lane, struct phylink_link_state *state); 1921 -int mv88e6390_serdes_pcs_an_restart(struct mv88e6xxx_chip *chip, int port, 1922 - int lane); 1923 -int mv88e6390_serdes_pcs_link_up(struct mv88e6xxx_chip *chip, int port, 1924 - int lane, int speed, int duplex); 1925 unsigned int mv88e6352_serdes_irq_mapping(struct mv88e6xxx_chip *chip, 1926 int port); 1927 unsigned int mv88e6390_serdes_irq_mapping(struct mv88e6xxx_chip *chip, 1928 int port); 1929 -int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane, 1930 - bool on); 1931 -int mv88e6393x_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane, 1932 - bool on); 1933 -int mv88e6393x_serdes_setup_errata(struct mv88e6xxx_chip *chip); 1934 -int mv88e6390_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, int lane, 1935 - bool enable); 1936 -int mv88e6393x_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, 1937 - int lane, bool enable); 1938 -irqreturn_t mv88e6390_serdes_irq_status(struct mv88e6xxx_chip *chip, int port, 1939 - int lane); 1940 -irqreturn_t mv88e6393x_serdes_irq_status(struct mv88e6xxx_chip *chip, int port, 1941 - int lane); 1942 int mv88e6352_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port); 1943 int mv88e6352_serdes_get_strings(struct mv88e6xxx_chip *chip, 1944 int port, uint8_t *data); 1945 @@ -230,4 +209,11 @@ void mv88e6185_pcs_teardown(struct mv88e6xxx_chip *chip, int port); 1946 int mv88e6352_pcs_init(struct mv88e6xxx_chip *chip, int port); 1947 void mv88e6352_pcs_teardown(struct mv88e6xxx_chip *chip, int port); 1948 1949 +int mv88e6390_pcs_init(struct mv88e6xxx_chip *chip, int port); 1950 +int mv88e6393x_pcs_init(struct mv88e6xxx_chip *chip, int port); 1951 +void mv88e639x_pcs_teardown(struct mv88e6xxx_chip *chip, int port); 1952 + 1953 +struct phylink_pcs *mv88e639x_pcs_select(struct mv88e6xxx_chip *chip, int port, 1954 + phy_interface_t mode); 1955 + 1956 #endif 1957 -- 1958 2.35.1 1959