1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Marvell 88E6352 family SERDES PCS support 4 * 5 * Copyright (c) 2008 Marvell Semiconductor 6 * 7 * Copyright (c) 2017 Andrew Lunn <andrew@lunn.ch> 8 */ 9 #include <linux/interrupt.h> 10 #include <linux/irqdomain.h> 11 #include <linux/mii.h> 12 13 #include "chip.h" 14 #include "global2.h" 15 #include "phy.h" 16 #include "port.h" 17 #include "serdes.h" 18 19 struct mv88e639x_pcs { 20 struct mdio_device mdio; 21 struct phylink_pcs sgmii_pcs; 22 struct phylink_pcs xg_pcs; 23 bool erratum_3_14; 24 bool supports_5g; 25 phy_interface_t interface; 26 unsigned int irq; 27 char name[64]; 28 irqreturn_t (*handle_irq)(struct mv88e639x_pcs *mpcs); 29 }; 30 31 static int mv88e639x_read(struct mv88e639x_pcs *mpcs, u16 regnum, u16 *val) 32 { 33 int err; 34 35 err = mdiodev_c45_read(&mpcs->mdio, MDIO_MMD_PHYXS, regnum); 36 if (err < 0) 37 return err; 38 39 *val = err; 40 41 return 0; 42 } 43 44 static int mv88e639x_write(struct mv88e639x_pcs *mpcs, u16 regnum, u16 val) 45 { 46 return mdiodev_c45_write(&mpcs->mdio, MDIO_MMD_PHYXS, regnum, val); 47 } 48 49 static int mv88e639x_modify(struct mv88e639x_pcs *mpcs, u16 regnum, u16 mask, 50 u16 val) 51 { 52 return mdiodev_c45_modify(&mpcs->mdio, MDIO_MMD_PHYXS, regnum, mask, 53 val); 54 } 55 56 static int mv88e639x_modify_changed(struct mv88e639x_pcs *mpcs, u16 regnum, 57 u16 mask, u16 set) 58 { 59 return mdiodev_c45_modify_changed(&mpcs->mdio, MDIO_MMD_PHYXS, regnum, 60 mask, set); 61 } 62 63 static struct mv88e639x_pcs * 64 mv88e639x_pcs_alloc(struct device *dev, struct mii_bus *bus, unsigned int addr, 65 int port) 66 { 67 struct mv88e639x_pcs *mpcs; 68 69 mpcs = kzalloc(sizeof(*mpcs), GFP_KERNEL); 70 if (!mpcs) 71 return NULL; 72 73 mpcs->mdio.dev.parent = dev; 74 mpcs->mdio.bus = bus; 75 mpcs->mdio.addr = addr; 76 77 snprintf(mpcs->name, sizeof(mpcs->name), 78 "mv88e6xxx-%s-serdes-%d", dev_name(dev), port); 79 80 return mpcs; 81 } 82 83 static irqreturn_t mv88e639x_pcs_handle_irq(int irq, void *dev_id) 84 { 85 struct mv88e639x_pcs *mpcs = dev_id; 86 irqreturn_t (*handler)(struct mv88e639x_pcs *); 87 88 handler = READ_ONCE(mpcs->handle_irq); 89 if (!handler) 90 return IRQ_NONE; 91 92 return handler(mpcs); 93 } 94 95 static int mv88e639x_pcs_setup_irq(struct mv88e639x_pcs *mpcs, 96 struct mv88e6xxx_chip *chip, int port) 97 { 98 unsigned int irq; 99 100 irq = mv88e6xxx_serdes_irq_mapping(chip, port); 101 if (!irq) { 102 /* Use polling mode */ 103 mpcs->sgmii_pcs.poll = true; 104 mpcs->xg_pcs.poll = true; 105 return 0; 106 } 107 108 mpcs->irq = irq; 109 110 return request_threaded_irq(irq, NULL, mv88e639x_pcs_handle_irq, 111 IRQF_ONESHOT, mpcs->name, mpcs); 112 } 113 114 static void mv88e639x_pcs_teardown(struct mv88e6xxx_chip *chip, int port) 115 { 116 struct mv88e639x_pcs *mpcs = chip->ports[port].pcs_private; 117 118 if (!mpcs) 119 return; 120 121 if (mpcs->irq) 122 free_irq(mpcs->irq, mpcs); 123 124 kfree(mpcs); 125 126 chip->ports[port].pcs_private = NULL; 127 } 128 129 static struct mv88e639x_pcs *sgmii_pcs_to_mv88e639x_pcs(struct phylink_pcs *pcs) 130 { 131 return container_of(pcs, struct mv88e639x_pcs, sgmii_pcs); 132 } 133 134 static irqreturn_t mv88e639x_sgmii_handle_irq(struct mv88e639x_pcs *mpcs) 135 { 136 u16 int_status; 137 int err; 138 139 err = mv88e639x_read(mpcs, MV88E6390_SGMII_INT_STATUS, &int_status); 140 if (err) 141 return IRQ_NONE; 142 143 if (int_status & (MV88E6390_SGMII_INT_LINK_DOWN | 144 MV88E6390_SGMII_INT_LINK_UP)) { 145 phylink_pcs_change(&mpcs->sgmii_pcs, 146 int_status & MV88E6390_SGMII_INT_LINK_UP); 147 148 return IRQ_HANDLED; 149 } 150 151 return IRQ_NONE; 152 } 153 154 static int mv88e639x_sgmii_pcs_control_irq(struct mv88e639x_pcs *mpcs, 155 bool enable) 156 { 157 u16 val = 0; 158 159 if (enable) 160 val |= MV88E6390_SGMII_INT_LINK_DOWN | 161 MV88E6390_SGMII_INT_LINK_UP; 162 163 return mv88e639x_modify(mpcs, MV88E6390_SGMII_INT_ENABLE, 164 MV88E6390_SGMII_INT_LINK_DOWN | 165 MV88E6390_SGMII_INT_LINK_UP, val); 166 } 167 168 static int mv88e639x_sgmii_pcs_control_pwr(struct mv88e639x_pcs *mpcs, 169 bool enable) 170 { 171 u16 mask, val; 172 173 if (enable) { 174 mask = BMCR_RESET | BMCR_LOOPBACK | BMCR_PDOWN; 175 val = 0; 176 } else { 177 mask = val = BMCR_PDOWN; 178 } 179 180 return mv88e639x_modify(mpcs, MV88E6390_SGMII_BMCR, mask, val); 181 } 182 183 static int mv88e639x_sgmii_pcs_enable(struct phylink_pcs *pcs) 184 { 185 struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs); 186 187 /* power enable done in post_config */ 188 mpcs->handle_irq = mv88e639x_sgmii_handle_irq; 189 190 return mv88e639x_sgmii_pcs_control_irq(mpcs, !!mpcs->irq); 191 } 192 193 static void mv88e639x_sgmii_pcs_disable(struct phylink_pcs *pcs) 194 { 195 struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs); 196 197 mv88e639x_sgmii_pcs_control_irq(mpcs, false); 198 mv88e639x_sgmii_pcs_control_pwr(mpcs, false); 199 } 200 201 static void mv88e639x_sgmii_pcs_pre_config(struct phylink_pcs *pcs, 202 phy_interface_t interface) 203 { 204 struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs); 205 206 mv88e639x_sgmii_pcs_control_pwr(mpcs, false); 207 } 208 209 static int mv88e6390_erratum_3_14(struct mv88e639x_pcs *mpcs) 210 { 211 static const int lanes[] = { MV88E6390_PORT9_LANE0, MV88E6390_PORT9_LANE1, 212 MV88E6390_PORT9_LANE2, MV88E6390_PORT9_LANE3, 213 MV88E6390_PORT10_LANE0, MV88E6390_PORT10_LANE1, 214 MV88E6390_PORT10_LANE2, MV88E6390_PORT10_LANE3 }; 215 int err, i; 216 217 /* 88e6190x and 88e6390x errata 3.14: 218 * After chip reset, SERDES reconfiguration or SERDES core 219 * Software Reset, the SERDES lanes may not be properly aligned 220 * resulting in CRC errors 221 */ 222 223 for (i = 0; i < ARRAY_SIZE(lanes); i++) { 224 err = mdiobus_c45_write(mpcs->mdio.bus, lanes[i], 225 MDIO_MMD_PHYXS, 226 0xf054, 0x400C); 227 if (err) 228 return err; 229 230 err = mdiobus_c45_write(mpcs->mdio.bus, lanes[i], 231 MDIO_MMD_PHYXS, 232 0xf054, 0x4000); 233 if (err) 234 return err; 235 } 236 237 return 0; 238 } 239 240 static int mv88e639x_sgmii_pcs_post_config(struct phylink_pcs *pcs, 241 phy_interface_t interface) 242 { 243 struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs); 244 int err; 245 246 mv88e639x_sgmii_pcs_control_pwr(mpcs, true); 247 248 if (mpcs->erratum_3_14) { 249 err = mv88e6390_erratum_3_14(mpcs); 250 if (err) 251 dev_err(mpcs->mdio.dev.parent, 252 "failed to apply erratum 3.14: %pe\n", 253 ERR_PTR(err)); 254 } 255 256 return 0; 257 } 258 259 static void mv88e639x_sgmii_pcs_get_state(struct phylink_pcs *pcs, 260 struct phylink_link_state *state) 261 { 262 struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs); 263 u16 bmsr, lpa, status; 264 int err; 265 266 err = mv88e639x_read(mpcs, MV88E6390_SGMII_BMSR, &bmsr); 267 if (err) { 268 dev_err(mpcs->mdio.dev.parent, 269 "can't read Serdes PHY %s: %pe\n", 270 "BMSR", ERR_PTR(err)); 271 state->link = false; 272 return; 273 } 274 275 err = mv88e639x_read(mpcs, MV88E6390_SGMII_LPA, &lpa); 276 if (err) { 277 dev_err(mpcs->mdio.dev.parent, 278 "can't read Serdes PHY %s: %pe\n", 279 "LPA", ERR_PTR(err)); 280 state->link = false; 281 return; 282 } 283 284 err = mv88e639x_read(mpcs, MV88E6390_SGMII_PHY_STATUS, &status); 285 if (err) { 286 dev_err(mpcs->mdio.dev.parent, 287 "can't read Serdes PHY %s: %pe\n", 288 "status", ERR_PTR(err)); 289 state->link = false; 290 return; 291 } 292 293 mv88e6xxx_pcs_decode_state(mpcs->mdio.dev.parent, bmsr, lpa, status, 294 state); 295 } 296 297 static int mv88e639x_sgmii_pcs_config(struct phylink_pcs *pcs, 298 unsigned int neg_mode, 299 phy_interface_t interface, 300 const unsigned long *advertising, 301 bool permit_pause_to_mac) 302 { 303 struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs); 304 u16 val, bmcr; 305 bool changed; 306 int adv, err; 307 308 adv = phylink_mii_c22_pcs_encode_advertisement(interface, advertising); 309 if (adv < 0) 310 return 0; 311 312 mpcs->interface = interface; 313 314 err = mv88e639x_modify_changed(mpcs, MV88E6390_SGMII_ADVERTISE, 315 0xffff, adv); 316 if (err < 0) 317 return err; 318 319 changed = err > 0; 320 321 err = mv88e639x_read(mpcs, MV88E6390_SGMII_BMCR, &val); 322 if (err) 323 return err; 324 325 if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) 326 bmcr = val | BMCR_ANENABLE; 327 else 328 bmcr = val & ~BMCR_ANENABLE; 329 330 /* setting ANENABLE triggers a restart of negotiation */ 331 if (bmcr == val) 332 return changed; 333 334 return mv88e639x_write(mpcs, MV88E6390_SGMII_BMCR, bmcr); 335 } 336 337 static void mv88e639x_sgmii_pcs_an_restart(struct phylink_pcs *pcs) 338 { 339 struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs); 340 341 mv88e639x_modify(mpcs, MV88E6390_SGMII_BMCR, 342 BMCR_ANRESTART, BMCR_ANRESTART); 343 } 344 345 static void mv88e639x_sgmii_pcs_link_up(struct phylink_pcs *pcs, 346 unsigned int mode, 347 phy_interface_t interface, 348 int speed, int duplex) 349 { 350 struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs); 351 u16 bmcr; 352 int err; 353 354 if (phylink_autoneg_inband(mode)) 355 return; 356 357 bmcr = mii_bmcr_encode_fixed(speed, duplex); 358 359 err = mv88e639x_modify(mpcs, MV88E6390_SGMII_BMCR, 360 BMCR_SPEED1000 | BMCR_SPEED100 | BMCR_FULLDPLX, 361 bmcr); 362 if (err) 363 dev_err(mpcs->mdio.dev.parent, 364 "can't access Serdes PHY %s: %pe\n", 365 "BMCR", ERR_PTR(err)); 366 } 367 368 static const struct phylink_pcs_ops mv88e639x_sgmii_pcs_ops = { 369 .pcs_enable = mv88e639x_sgmii_pcs_enable, 370 .pcs_disable = mv88e639x_sgmii_pcs_disable, 371 .pcs_pre_config = mv88e639x_sgmii_pcs_pre_config, 372 .pcs_post_config = mv88e639x_sgmii_pcs_post_config, 373 .pcs_get_state = mv88e639x_sgmii_pcs_get_state, 374 .pcs_an_restart = mv88e639x_sgmii_pcs_an_restart, 375 .pcs_config = mv88e639x_sgmii_pcs_config, 376 .pcs_link_up = mv88e639x_sgmii_pcs_link_up, 377 }; 378 379 static struct mv88e639x_pcs *xg_pcs_to_mv88e639x_pcs(struct phylink_pcs *pcs) 380 { 381 return container_of(pcs, struct mv88e639x_pcs, xg_pcs); 382 } 383 384 static int mv88e639x_xg_pcs_enable(struct mv88e639x_pcs *mpcs) 385 { 386 return mv88e639x_modify(mpcs, MV88E6390_10G_CTRL1, 387 MDIO_CTRL1_RESET | MDIO_PCS_CTRL1_LOOPBACK | 388 MDIO_CTRL1_LPOWER, 0); 389 } 390 391 static void mv88e639x_xg_pcs_disable(struct mv88e639x_pcs *mpcs) 392 { 393 mv88e639x_modify(mpcs, MV88E6390_10G_CTRL1, MDIO_CTRL1_LPOWER, 394 MDIO_CTRL1_LPOWER); 395 } 396 397 static void mv88e639x_xg_pcs_get_state(struct phylink_pcs *pcs, 398 struct phylink_link_state *state) 399 { 400 struct mv88e639x_pcs *mpcs = xg_pcs_to_mv88e639x_pcs(pcs); 401 u16 status; 402 int err; 403 404 state->link = false; 405 406 err = mv88e639x_read(mpcs, MV88E6390_10G_STAT1, &status); 407 if (err) { 408 dev_err(mpcs->mdio.dev.parent, 409 "can't read Serdes PHY %s: %pe\n", 410 "STAT1", ERR_PTR(err)); 411 return; 412 } 413 414 state->link = !!(status & MDIO_STAT1_LSTATUS); 415 if (state->link) { 416 switch (state->interface) { 417 case PHY_INTERFACE_MODE_5GBASER: 418 state->speed = SPEED_5000; 419 break; 420 421 case PHY_INTERFACE_MODE_10GBASER: 422 case PHY_INTERFACE_MODE_RXAUI: 423 case PHY_INTERFACE_MODE_XAUI: 424 state->speed = SPEED_10000; 425 break; 426 427 default: 428 state->link = false; 429 return; 430 } 431 432 state->duplex = DUPLEX_FULL; 433 } 434 } 435 436 static int mv88e639x_xg_pcs_config(struct phylink_pcs *pcs, 437 unsigned int neg_mode, 438 phy_interface_t interface, 439 const unsigned long *advertising, 440 bool permit_pause_to_mac) 441 { 442 return 0; 443 } 444 445 static struct phylink_pcs * 446 mv88e639x_pcs_select(struct mv88e6xxx_chip *chip, int port, 447 phy_interface_t mode) 448 { 449 struct mv88e639x_pcs *mpcs; 450 451 mpcs = chip->ports[port].pcs_private; 452 if (!mpcs) 453 return NULL; 454 455 switch (mode) { 456 case PHY_INTERFACE_MODE_SGMII: 457 case PHY_INTERFACE_MODE_1000BASEX: 458 case PHY_INTERFACE_MODE_2500BASEX: 459 return &mpcs->sgmii_pcs; 460 461 case PHY_INTERFACE_MODE_5GBASER: 462 if (!mpcs->supports_5g) 463 return NULL; 464 fallthrough; 465 case PHY_INTERFACE_MODE_10GBASER: 466 case PHY_INTERFACE_MODE_XAUI: 467 case PHY_INTERFACE_MODE_RXAUI: 468 case PHY_INTERFACE_MODE_USXGMII: 469 return &mpcs->xg_pcs; 470 471 default: 472 return NULL; 473 } 474 } 475 476 /* Marvell 88E6390 Specific support */ 477 478 static irqreturn_t mv88e6390_xg_handle_irq(struct mv88e639x_pcs *mpcs) 479 { 480 u16 int_status; 481 int err; 482 483 err = mv88e639x_read(mpcs, MV88E6390_10G_INT_STATUS, &int_status); 484 if (err) 485 return IRQ_NONE; 486 487 if (int_status & (MV88E6390_10G_INT_LINK_DOWN | 488 MV88E6390_10G_INT_LINK_UP)) { 489 phylink_pcs_change(&mpcs->xg_pcs, 490 int_status & MV88E6390_10G_INT_LINK_UP); 491 492 return IRQ_HANDLED; 493 } 494 495 return IRQ_NONE; 496 } 497 498 static int mv88e6390_xg_control_irq(struct mv88e639x_pcs *mpcs, bool enable) 499 { 500 u16 val = 0; 501 502 if (enable) 503 val = MV88E6390_10G_INT_LINK_DOWN | MV88E6390_10G_INT_LINK_UP; 504 505 return mv88e639x_modify(mpcs, MV88E6390_10G_INT_ENABLE, 506 MV88E6390_10G_INT_LINK_DOWN | 507 MV88E6390_10G_INT_LINK_UP, val); 508 } 509 510 static int mv88e6390_xg_pcs_enable(struct phylink_pcs *pcs) 511 { 512 struct mv88e639x_pcs *mpcs = xg_pcs_to_mv88e639x_pcs(pcs); 513 int err; 514 515 err = mv88e639x_xg_pcs_enable(mpcs); 516 if (err) 517 return err; 518 519 mpcs->handle_irq = mv88e6390_xg_handle_irq; 520 521 return mv88e6390_xg_control_irq(mpcs, !!mpcs->irq); 522 } 523 524 static void mv88e6390_xg_pcs_disable(struct phylink_pcs *pcs) 525 { 526 struct mv88e639x_pcs *mpcs = xg_pcs_to_mv88e639x_pcs(pcs); 527 528 mv88e6390_xg_control_irq(mpcs, false); 529 mv88e639x_xg_pcs_disable(mpcs); 530 } 531 532 static const struct phylink_pcs_ops mv88e6390_xg_pcs_ops = { 533 .pcs_enable = mv88e6390_xg_pcs_enable, 534 .pcs_disable = mv88e6390_xg_pcs_disable, 535 .pcs_get_state = mv88e639x_xg_pcs_get_state, 536 .pcs_config = mv88e639x_xg_pcs_config, 537 }; 538 539 static int mv88e6390_pcs_enable_checker(struct mv88e639x_pcs *mpcs) 540 { 541 return mv88e639x_modify(mpcs, MV88E6390_PG_CONTROL, 542 MV88E6390_PG_CONTROL_ENABLE_PC, 543 MV88E6390_PG_CONTROL_ENABLE_PC); 544 } 545 546 static int mv88e6390_pcs_init(struct mv88e6xxx_chip *chip, int port) 547 { 548 struct mv88e639x_pcs *mpcs; 549 struct mii_bus *bus; 550 struct device *dev; 551 int lane, err; 552 553 lane = mv88e6xxx_serdes_get_lane(chip, port); 554 if (lane < 0) 555 return 0; 556 557 bus = mv88e6xxx_default_mdio_bus(chip); 558 dev = chip->dev; 559 560 mpcs = mv88e639x_pcs_alloc(dev, bus, lane, port); 561 if (!mpcs) 562 return -ENOMEM; 563 564 mpcs->sgmii_pcs.ops = &mv88e639x_sgmii_pcs_ops; 565 mpcs->sgmii_pcs.neg_mode = true; 566 mpcs->xg_pcs.ops = &mv88e6390_xg_pcs_ops; 567 mpcs->xg_pcs.neg_mode = true; 568 569 if (chip->info->prod_num == MV88E6XXX_PORT_SWITCH_ID_PROD_6190X || 570 chip->info->prod_num == MV88E6XXX_PORT_SWITCH_ID_PROD_6390X) 571 mpcs->erratum_3_14 = true; 572 573 err = mv88e639x_pcs_setup_irq(mpcs, chip, port); 574 if (err) 575 goto err_free; 576 577 /* 6390 and 6390x has the checker, 6393x doesn't appear to? */ 578 /* This is to enable gathering the statistics. Maybe this 579 * should call out to a helper? Or we could do this at init time. 580 */ 581 err = mv88e6390_pcs_enable_checker(mpcs); 582 if (err) 583 goto err_free; 584 585 chip->ports[port].pcs_private = mpcs; 586 587 return 0; 588 589 err_free: 590 kfree(mpcs); 591 return err; 592 } 593 594 const struct mv88e6xxx_pcs_ops mv88e6390_pcs_ops = { 595 .pcs_init = mv88e6390_pcs_init, 596 .pcs_teardown = mv88e639x_pcs_teardown, 597 .pcs_select = mv88e639x_pcs_select, 598 }; 599 600 /* Marvell 88E6393X Specific support */ 601 602 static int mv88e6393x_power_lane(struct mv88e639x_pcs *mpcs, bool enable) 603 { 604 u16 val = MV88E6393X_SERDES_CTRL1_TX_PDOWN | 605 MV88E6393X_SERDES_CTRL1_RX_PDOWN; 606 607 return mv88e639x_modify(mpcs, MV88E6393X_SERDES_CTRL1, val, 608 enable ? 0 : val); 609 } 610 611 /* mv88e6393x family errata 4.6: 612 * Cannot clear PwrDn bit on SERDES if device is configured CPU_MGD mode or 613 * P0_mode is configured for [x]MII. 614 * Workaround: Set SERDES register 4.F002 bit 5=0 and bit 15=1. 615 * 616 * It seems that after this workaround the SERDES is automatically powered up 617 * (the bit is cleared), so power it down. 618 */ 619 static int mv88e6393x_erratum_4_6(struct mv88e639x_pcs *mpcs) 620 { 621 int err; 622 623 err = mv88e639x_modify(mpcs, MV88E6393X_SERDES_POC, 624 MV88E6393X_SERDES_POC_PDOWN | 625 MV88E6393X_SERDES_POC_RESET, 626 MV88E6393X_SERDES_POC_RESET); 627 if (err) 628 return err; 629 630 err = mv88e639x_modify(mpcs, MV88E6390_SGMII_BMCR, 631 BMCR_PDOWN, BMCR_PDOWN); 632 if (err) 633 return err; 634 635 err = mv88e639x_sgmii_pcs_control_pwr(mpcs, false); 636 if (err) 637 return err; 638 639 return mv88e6393x_power_lane(mpcs, false); 640 } 641 642 /* mv88e6393x family errata 4.8: 643 * When a SERDES port is operating in 1000BASE-X or SGMII mode link may not 644 * come up after hardware reset or software reset of SERDES core. Workaround 645 * is to write SERDES register 4.F074.14=1 for only those modes and 0 in all 646 * other modes. 647 */ 648 static int mv88e6393x_erratum_4_8(struct mv88e639x_pcs *mpcs) 649 { 650 u16 reg, poc; 651 int err; 652 653 err = mv88e639x_read(mpcs, MV88E6393X_SERDES_POC, &poc); 654 if (err) 655 return err; 656 657 poc &= MV88E6393X_SERDES_POC_PCS_MASK; 658 if (poc == MV88E6393X_SERDES_POC_PCS_1000BASEX || 659 poc == MV88E6393X_SERDES_POC_PCS_SGMII_PHY || 660 poc == MV88E6393X_SERDES_POC_PCS_SGMII_MAC) 661 reg = MV88E6393X_ERRATA_4_8_BIT; 662 else 663 reg = 0; 664 665 return mv88e639x_modify(mpcs, MV88E6393X_ERRATA_4_8_REG, 666 MV88E6393X_ERRATA_4_8_BIT, reg); 667 } 668 669 /* mv88e6393x family errata 5.2: 670 * For optimal signal integrity the following sequence should be applied to 671 * SERDES operating in 10G mode. These registers only apply to 10G operation 672 * and have no effect on other speeds. 673 */ 674 static int mv88e6393x_erratum_5_2(struct mv88e639x_pcs *mpcs) 675 { 676 static const struct { 677 u16 dev, reg, val, mask; 678 } fixes[] = { 679 { MDIO_MMD_VEND1, 0x8093, 0xcb5a, 0xffff }, 680 { MDIO_MMD_VEND1, 0x8171, 0x7088, 0xffff }, 681 { MDIO_MMD_VEND1, 0x80c9, 0x311a, 0xffff }, 682 { MDIO_MMD_VEND1, 0x80a2, 0x8000, 0xff7f }, 683 { MDIO_MMD_VEND1, 0x80a9, 0x0000, 0xfff0 }, 684 { MDIO_MMD_VEND1, 0x80a3, 0x0000, 0xf8ff }, 685 { MDIO_MMD_PHYXS, MV88E6393X_SERDES_POC, 686 MV88E6393X_SERDES_POC_RESET, MV88E6393X_SERDES_POC_RESET }, 687 }; 688 int err, i; 689 690 for (i = 0; i < ARRAY_SIZE(fixes); ++i) { 691 err = mdiodev_c45_modify(&mpcs->mdio, fixes[i].dev, 692 fixes[i].reg, fixes[i].mask, 693 fixes[i].val); 694 if (err) 695 return err; 696 } 697 698 return 0; 699 } 700 701 /* Inband AN is broken on Amethyst in 2500base-x mode when set by standard 702 * mechanism (via cmode). 703 * We can get around this by configuring the PCS mode to 1000base-x and then 704 * writing value 0x58 to register 1e.8000. (This must be done while SerDes 705 * receiver and transmitter are disabled, which is, when this function is 706 * called.) 707 * It seem that when we do this configuration to 2500base-x mode (by changing 708 * PCS mode to 1000base-x and frequency to 3.125 GHz from 1.25 GHz) and then 709 * configure to sgmii or 1000base-x, the device thinks that it already has 710 * SerDes at 1.25 GHz and does not change the 1e.8000 register, leaving SerDes 711 * at 3.125 GHz. 712 * To avoid this, change PCS mode back to 2500base-x when disabling SerDes from 713 * 2500base-x mode. 714 */ 715 static int mv88e6393x_fix_2500basex_an(struct mv88e639x_pcs *mpcs, bool on) 716 { 717 u16 reg; 718 int err; 719 720 if (on) 721 reg = MV88E6393X_SERDES_POC_PCS_1000BASEX | 722 MV88E6393X_SERDES_POC_AN; 723 else 724 reg = MV88E6393X_SERDES_POC_PCS_2500BASEX; 725 726 reg |= MV88E6393X_SERDES_POC_RESET; 727 728 err = mv88e639x_modify(mpcs, MV88E6393X_SERDES_POC, 729 MV88E6393X_SERDES_POC_PCS_MASK | 730 MV88E6393X_SERDES_POC_AN | 731 MV88E6393X_SERDES_POC_RESET, reg); 732 if (err) 733 return err; 734 735 return mdiodev_c45_write(&mpcs->mdio, MDIO_MMD_VEND1, 0x8000, 0x58); 736 } 737 738 static int mv88e6393x_sgmii_apply_2500basex_an(struct mv88e639x_pcs *mpcs, 739 phy_interface_t interface, 740 bool enable) 741 { 742 int err; 743 744 if (interface != PHY_INTERFACE_MODE_2500BASEX) 745 return 0; 746 747 err = mv88e6393x_fix_2500basex_an(mpcs, enable); 748 if (err) 749 dev_err(mpcs->mdio.dev.parent, 750 "failed to %s 2500basex fix: %pe\n", 751 enable ? "enable" : "disable", ERR_PTR(err)); 752 753 return err; 754 } 755 756 static void mv88e6393x_sgmii_pcs_disable(struct phylink_pcs *pcs) 757 { 758 struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs); 759 760 mv88e639x_sgmii_pcs_disable(pcs); 761 mv88e6393x_power_lane(mpcs, false); 762 mv88e6393x_sgmii_apply_2500basex_an(mpcs, mpcs->interface, false); 763 } 764 765 static void mv88e6393x_sgmii_pcs_pre_config(struct phylink_pcs *pcs, 766 phy_interface_t interface) 767 { 768 struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs); 769 770 mv88e639x_sgmii_pcs_pre_config(pcs, interface); 771 mv88e6393x_power_lane(mpcs, false); 772 mv88e6393x_sgmii_apply_2500basex_an(mpcs, mpcs->interface, false); 773 } 774 775 static int mv88e6393x_sgmii_pcs_post_config(struct phylink_pcs *pcs, 776 phy_interface_t interface) 777 { 778 struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs); 779 int err; 780 781 err = mv88e6393x_erratum_4_8(mpcs); 782 if (err) 783 return err; 784 785 err = mv88e6393x_sgmii_apply_2500basex_an(mpcs, interface, true); 786 if (err) 787 return err; 788 789 err = mv88e6393x_power_lane(mpcs, true); 790 if (err) 791 return err; 792 793 return mv88e639x_sgmii_pcs_post_config(pcs, interface); 794 } 795 796 static const struct phylink_pcs_ops mv88e6393x_sgmii_pcs_ops = { 797 .pcs_enable = mv88e639x_sgmii_pcs_enable, 798 .pcs_disable = mv88e6393x_sgmii_pcs_disable, 799 .pcs_pre_config = mv88e6393x_sgmii_pcs_pre_config, 800 .pcs_post_config = mv88e6393x_sgmii_pcs_post_config, 801 .pcs_get_state = mv88e639x_sgmii_pcs_get_state, 802 .pcs_an_restart = mv88e639x_sgmii_pcs_an_restart, 803 .pcs_config = mv88e639x_sgmii_pcs_config, 804 .pcs_link_up = mv88e639x_sgmii_pcs_link_up, 805 }; 806 807 static irqreturn_t mv88e6393x_xg_handle_irq(struct mv88e639x_pcs *mpcs) 808 { 809 u16 int_status, stat1; 810 bool link_down; 811 int err; 812 813 err = mv88e639x_read(mpcs, MV88E6393X_10G_INT_STATUS, &int_status); 814 if (err) 815 return IRQ_NONE; 816 817 if (int_status & MV88E6393X_10G_INT_LINK_CHANGE) { 818 err = mv88e639x_read(mpcs, MV88E6390_10G_STAT1, &stat1); 819 if (err) 820 return IRQ_NONE; 821 822 link_down = !(stat1 & MDIO_STAT1_LSTATUS); 823 824 phylink_pcs_change(&mpcs->xg_pcs, !link_down); 825 826 return IRQ_HANDLED; 827 } 828 829 return IRQ_NONE; 830 } 831 832 static int mv88e6393x_xg_control_irq(struct mv88e639x_pcs *mpcs, bool enable) 833 { 834 u16 val = 0; 835 836 if (enable) 837 val = MV88E6393X_10G_INT_LINK_CHANGE; 838 839 return mv88e639x_modify(mpcs, MV88E6393X_10G_INT_ENABLE, 840 MV88E6393X_10G_INT_LINK_CHANGE, val); 841 } 842 843 static int mv88e6393x_xg_pcs_enable(struct phylink_pcs *pcs) 844 { 845 struct mv88e639x_pcs *mpcs = xg_pcs_to_mv88e639x_pcs(pcs); 846 847 mpcs->handle_irq = mv88e6393x_xg_handle_irq; 848 849 return mv88e6393x_xg_control_irq(mpcs, !!mpcs->irq); 850 } 851 852 static void mv88e6393x_xg_pcs_disable(struct phylink_pcs *pcs) 853 { 854 struct mv88e639x_pcs *mpcs = xg_pcs_to_mv88e639x_pcs(pcs); 855 856 mv88e6393x_xg_control_irq(mpcs, false); 857 mv88e639x_xg_pcs_disable(mpcs); 858 mv88e6393x_power_lane(mpcs, false); 859 } 860 861 /* The PCS has to be powered down while CMODE is changed */ 862 static void mv88e6393x_xg_pcs_pre_config(struct phylink_pcs *pcs, 863 phy_interface_t interface) 864 { 865 struct mv88e639x_pcs *mpcs = xg_pcs_to_mv88e639x_pcs(pcs); 866 867 mv88e639x_xg_pcs_disable(mpcs); 868 mv88e6393x_power_lane(mpcs, false); 869 } 870 871 static int mv88e6393x_xg_pcs_post_config(struct phylink_pcs *pcs, 872 phy_interface_t interface) 873 { 874 struct mv88e639x_pcs *mpcs = xg_pcs_to_mv88e639x_pcs(pcs); 875 int err; 876 877 if (interface == PHY_INTERFACE_MODE_10GBASER || 878 interface == PHY_INTERFACE_MODE_USXGMII) { 879 err = mv88e6393x_erratum_5_2(mpcs); 880 if (err) 881 return err; 882 } 883 884 err = mv88e6393x_power_lane(mpcs, true); 885 if (err) 886 return err; 887 888 return mv88e639x_xg_pcs_enable(mpcs); 889 } 890 891 static void mv88e6393x_xg_pcs_get_state(struct phylink_pcs *pcs, 892 struct phylink_link_state *state) 893 { 894 struct mv88e639x_pcs *mpcs = xg_pcs_to_mv88e639x_pcs(pcs); 895 u16 status, lp_status; 896 int err; 897 898 if (state->interface != PHY_INTERFACE_MODE_USXGMII) 899 return mv88e639x_xg_pcs_get_state(pcs, state); 900 901 state->link = false; 902 903 err = mv88e639x_read(mpcs, MV88E6390_USXGMII_PHY_STATUS, &status); 904 err = err ? : mv88e639x_read(mpcs, MV88E6390_USXGMII_LP_STATUS, &lp_status); 905 if (err) { 906 dev_err(mpcs->mdio.dev.parent, 907 "can't read USXGMII status: %pe\n", ERR_PTR(err)); 908 return; 909 } 910 911 state->link = !!(status & MDIO_USXGMII_LINK); 912 state->an_complete = state->link; 913 phylink_decode_usxgmii_word(state, lp_status); 914 } 915 916 static const struct phylink_pcs_ops mv88e6393x_xg_pcs_ops = { 917 .pcs_enable = mv88e6393x_xg_pcs_enable, 918 .pcs_disable = mv88e6393x_xg_pcs_disable, 919 .pcs_pre_config = mv88e6393x_xg_pcs_pre_config, 920 .pcs_post_config = mv88e6393x_xg_pcs_post_config, 921 .pcs_get_state = mv88e6393x_xg_pcs_get_state, 922 .pcs_config = mv88e639x_xg_pcs_config, 923 }; 924 925 static int mv88e6393x_pcs_init(struct mv88e6xxx_chip *chip, int port) 926 { 927 struct mv88e639x_pcs *mpcs; 928 struct mii_bus *bus; 929 struct device *dev; 930 int lane, err; 931 932 lane = mv88e6xxx_serdes_get_lane(chip, port); 933 if (lane < 0) 934 return 0; 935 936 bus = mv88e6xxx_default_mdio_bus(chip); 937 dev = chip->dev; 938 939 mpcs = mv88e639x_pcs_alloc(dev, bus, lane, port); 940 if (!mpcs) 941 return -ENOMEM; 942 943 mpcs->sgmii_pcs.ops = &mv88e6393x_sgmii_pcs_ops; 944 mpcs->sgmii_pcs.neg_mode = true; 945 mpcs->xg_pcs.ops = &mv88e6393x_xg_pcs_ops; 946 mpcs->xg_pcs.neg_mode = true; 947 mpcs->supports_5g = true; 948 949 err = mv88e6393x_erratum_4_6(mpcs); 950 if (err) 951 goto err_free; 952 953 err = mv88e639x_pcs_setup_irq(mpcs, chip, port); 954 if (err) 955 goto err_free; 956 957 chip->ports[port].pcs_private = mpcs; 958 959 return 0; 960 961 err_free: 962 kfree(mpcs); 963 return err; 964 } 965 966 const struct mv88e6xxx_pcs_ops mv88e6393x_pcs_ops = { 967 .pcs_init = mv88e6393x_pcs_init, 968 .pcs_teardown = mv88e639x_pcs_teardown, 969 .pcs_select = mv88e639x_pcs_select, 970 }; 971