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 unsigned int neg_mode, 261 struct phylink_link_state *state) 262 { 263 struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs); 264 u16 bmsr, lpa, status; 265 int err; 266 267 err = mv88e639x_read(mpcs, MV88E6390_SGMII_BMSR, &bmsr); 268 if (err) { 269 dev_err(mpcs->mdio.dev.parent, 270 "can't read Serdes PHY %s: %pe\n", 271 "BMSR", ERR_PTR(err)); 272 state->link = false; 273 return; 274 } 275 276 err = mv88e639x_read(mpcs, MV88E6390_SGMII_LPA, &lpa); 277 if (err) { 278 dev_err(mpcs->mdio.dev.parent, 279 "can't read Serdes PHY %s: %pe\n", 280 "LPA", ERR_PTR(err)); 281 state->link = false; 282 return; 283 } 284 285 err = mv88e639x_read(mpcs, MV88E6390_SGMII_PHY_STATUS, &status); 286 if (err) { 287 dev_err(mpcs->mdio.dev.parent, 288 "can't read Serdes PHY %s: %pe\n", 289 "status", ERR_PTR(err)); 290 state->link = false; 291 return; 292 } 293 294 mv88e6xxx_pcs_decode_state(mpcs->mdio.dev.parent, bmsr, lpa, status, 295 state); 296 } 297 298 static int mv88e639x_sgmii_pcs_config(struct phylink_pcs *pcs, 299 unsigned int neg_mode, 300 phy_interface_t interface, 301 const unsigned long *advertising, 302 bool permit_pause_to_mac) 303 { 304 struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs); 305 u16 val, bmcr; 306 bool changed; 307 int adv, err; 308 309 adv = phylink_mii_c22_pcs_encode_advertisement(interface, advertising); 310 if (adv < 0) 311 return 0; 312 313 mpcs->interface = interface; 314 315 err = mv88e639x_modify_changed(mpcs, MV88E6390_SGMII_ADVERTISE, 316 0xffff, adv); 317 if (err < 0) 318 return err; 319 320 changed = err > 0; 321 322 err = mv88e639x_read(mpcs, MV88E6390_SGMII_BMCR, &val); 323 if (err) 324 return err; 325 326 if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) 327 bmcr = val | BMCR_ANENABLE; 328 else 329 bmcr = val & ~BMCR_ANENABLE; 330 331 /* setting ANENABLE triggers a restart of negotiation */ 332 if (bmcr == val) 333 return changed; 334 335 return mv88e639x_write(mpcs, MV88E6390_SGMII_BMCR, bmcr); 336 } 337 338 static void mv88e639x_sgmii_pcs_an_restart(struct phylink_pcs *pcs) 339 { 340 struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs); 341 342 mv88e639x_modify(mpcs, MV88E6390_SGMII_BMCR, 343 BMCR_ANRESTART, BMCR_ANRESTART); 344 } 345 346 static void mv88e639x_sgmii_pcs_link_up(struct phylink_pcs *pcs, 347 unsigned int mode, 348 phy_interface_t interface, 349 int speed, int duplex) 350 { 351 struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs); 352 u16 bmcr; 353 int err; 354 355 if (phylink_autoneg_inband(mode)) 356 return; 357 358 bmcr = mii_bmcr_encode_fixed(speed, duplex); 359 360 err = mv88e639x_modify(mpcs, MV88E6390_SGMII_BMCR, 361 BMCR_SPEED1000 | BMCR_SPEED100 | BMCR_FULLDPLX, 362 bmcr); 363 if (err) 364 dev_err(mpcs->mdio.dev.parent, 365 "can't access Serdes PHY %s: %pe\n", 366 "BMCR", ERR_PTR(err)); 367 } 368 369 static const struct phylink_pcs_ops mv88e639x_sgmii_pcs_ops = { 370 .pcs_enable = mv88e639x_sgmii_pcs_enable, 371 .pcs_disable = mv88e639x_sgmii_pcs_disable, 372 .pcs_pre_config = mv88e639x_sgmii_pcs_pre_config, 373 .pcs_post_config = mv88e639x_sgmii_pcs_post_config, 374 .pcs_get_state = mv88e639x_sgmii_pcs_get_state, 375 .pcs_an_restart = mv88e639x_sgmii_pcs_an_restart, 376 .pcs_config = mv88e639x_sgmii_pcs_config, 377 .pcs_link_up = mv88e639x_sgmii_pcs_link_up, 378 }; 379 380 static struct mv88e639x_pcs *xg_pcs_to_mv88e639x_pcs(struct phylink_pcs *pcs) 381 { 382 return container_of(pcs, struct mv88e639x_pcs, xg_pcs); 383 } 384 385 static int mv88e639x_xg_pcs_enable(struct mv88e639x_pcs *mpcs) 386 { 387 return mv88e639x_modify(mpcs, MV88E6390_10G_CTRL1, 388 MDIO_CTRL1_RESET | MDIO_PCS_CTRL1_LOOPBACK | 389 MDIO_CTRL1_LPOWER, 0); 390 } 391 392 static void mv88e639x_xg_pcs_disable(struct mv88e639x_pcs *mpcs) 393 { 394 mv88e639x_modify(mpcs, MV88E6390_10G_CTRL1, MDIO_CTRL1_LPOWER, 395 MDIO_CTRL1_LPOWER); 396 } 397 398 static void mv88e639x_xg_pcs_get_state(struct phylink_pcs *pcs, 399 unsigned int neg_mode, 400 struct phylink_link_state *state) 401 { 402 struct mv88e639x_pcs *mpcs = xg_pcs_to_mv88e639x_pcs(pcs); 403 u16 status; 404 int err; 405 406 state->link = false; 407 408 err = mv88e639x_read(mpcs, MV88E6390_10G_STAT1, &status); 409 if (err) { 410 dev_err(mpcs->mdio.dev.parent, 411 "can't read Serdes PHY %s: %pe\n", 412 "STAT1", ERR_PTR(err)); 413 return; 414 } 415 416 state->link = !!(status & MDIO_STAT1_LSTATUS); 417 if (state->link) { 418 switch (state->interface) { 419 case PHY_INTERFACE_MODE_5GBASER: 420 state->speed = SPEED_5000; 421 break; 422 423 case PHY_INTERFACE_MODE_10GBASER: 424 case PHY_INTERFACE_MODE_RXAUI: 425 case PHY_INTERFACE_MODE_XAUI: 426 state->speed = SPEED_10000; 427 break; 428 429 default: 430 state->link = false; 431 return; 432 } 433 434 state->duplex = DUPLEX_FULL; 435 } 436 } 437 438 static int mv88e639x_xg_pcs_config(struct phylink_pcs *pcs, 439 unsigned int neg_mode, 440 phy_interface_t interface, 441 const unsigned long *advertising, 442 bool permit_pause_to_mac) 443 { 444 return 0; 445 } 446 447 static struct phylink_pcs * 448 mv88e639x_pcs_select(struct mv88e6xxx_chip *chip, int port, 449 phy_interface_t mode) 450 { 451 struct mv88e639x_pcs *mpcs; 452 453 mpcs = chip->ports[port].pcs_private; 454 if (!mpcs) 455 return NULL; 456 457 switch (mode) { 458 case PHY_INTERFACE_MODE_SGMII: 459 case PHY_INTERFACE_MODE_1000BASEX: 460 case PHY_INTERFACE_MODE_2500BASEX: 461 return &mpcs->sgmii_pcs; 462 463 case PHY_INTERFACE_MODE_5GBASER: 464 if (!mpcs->supports_5g) 465 return NULL; 466 fallthrough; 467 case PHY_INTERFACE_MODE_10GBASER: 468 case PHY_INTERFACE_MODE_XAUI: 469 case PHY_INTERFACE_MODE_RXAUI: 470 case PHY_INTERFACE_MODE_USXGMII: 471 return &mpcs->xg_pcs; 472 473 default: 474 return NULL; 475 } 476 } 477 478 /* Marvell 88E6390 Specific support */ 479 480 static irqreturn_t mv88e6390_xg_handle_irq(struct mv88e639x_pcs *mpcs) 481 { 482 u16 int_status; 483 int err; 484 485 err = mv88e639x_read(mpcs, MV88E6390_10G_INT_STATUS, &int_status); 486 if (err) 487 return IRQ_NONE; 488 489 if (int_status & (MV88E6390_10G_INT_LINK_DOWN | 490 MV88E6390_10G_INT_LINK_UP)) { 491 phylink_pcs_change(&mpcs->xg_pcs, 492 int_status & MV88E6390_10G_INT_LINK_UP); 493 494 return IRQ_HANDLED; 495 } 496 497 return IRQ_NONE; 498 } 499 500 static int mv88e6390_xg_control_irq(struct mv88e639x_pcs *mpcs, bool enable) 501 { 502 u16 val = 0; 503 504 if (enable) 505 val = MV88E6390_10G_INT_LINK_DOWN | MV88E6390_10G_INT_LINK_UP; 506 507 return mv88e639x_modify(mpcs, MV88E6390_10G_INT_ENABLE, 508 MV88E6390_10G_INT_LINK_DOWN | 509 MV88E6390_10G_INT_LINK_UP, val); 510 } 511 512 static int mv88e6390_xg_pcs_enable(struct phylink_pcs *pcs) 513 { 514 struct mv88e639x_pcs *mpcs = xg_pcs_to_mv88e639x_pcs(pcs); 515 int err; 516 517 err = mv88e639x_xg_pcs_enable(mpcs); 518 if (err) 519 return err; 520 521 mpcs->handle_irq = mv88e6390_xg_handle_irq; 522 523 return mv88e6390_xg_control_irq(mpcs, !!mpcs->irq); 524 } 525 526 static void mv88e6390_xg_pcs_disable(struct phylink_pcs *pcs) 527 { 528 struct mv88e639x_pcs *mpcs = xg_pcs_to_mv88e639x_pcs(pcs); 529 530 mv88e6390_xg_control_irq(mpcs, false); 531 mv88e639x_xg_pcs_disable(mpcs); 532 } 533 534 static const struct phylink_pcs_ops mv88e6390_xg_pcs_ops = { 535 .pcs_enable = mv88e6390_xg_pcs_enable, 536 .pcs_disable = mv88e6390_xg_pcs_disable, 537 .pcs_get_state = mv88e639x_xg_pcs_get_state, 538 .pcs_config = mv88e639x_xg_pcs_config, 539 }; 540 541 static int mv88e6390_pcs_enable_checker(struct mv88e639x_pcs *mpcs) 542 { 543 return mv88e639x_modify(mpcs, MV88E6390_PG_CONTROL, 544 MV88E6390_PG_CONTROL_ENABLE_PC, 545 MV88E6390_PG_CONTROL_ENABLE_PC); 546 } 547 548 static int mv88e6390_pcs_init(struct mv88e6xxx_chip *chip, int port) 549 { 550 struct mv88e639x_pcs *mpcs; 551 struct mii_bus *bus; 552 struct device *dev; 553 int lane, err; 554 555 lane = mv88e6xxx_serdes_get_lane(chip, port); 556 if (lane < 0) 557 return 0; 558 559 bus = mv88e6xxx_default_mdio_bus(chip); 560 dev = chip->dev; 561 562 mpcs = mv88e639x_pcs_alloc(dev, bus, lane, port); 563 if (!mpcs) 564 return -ENOMEM; 565 566 mpcs->sgmii_pcs.ops = &mv88e639x_sgmii_pcs_ops; 567 mpcs->sgmii_pcs.neg_mode = true; 568 mpcs->xg_pcs.ops = &mv88e6390_xg_pcs_ops; 569 mpcs->xg_pcs.neg_mode = true; 570 571 if (chip->info->prod_num == MV88E6XXX_PORT_SWITCH_ID_PROD_6190X || 572 chip->info->prod_num == MV88E6XXX_PORT_SWITCH_ID_PROD_6390X) 573 mpcs->erratum_3_14 = true; 574 575 err = mv88e639x_pcs_setup_irq(mpcs, chip, port); 576 if (err) 577 goto err_free; 578 579 /* 6390 and 6390x has the checker, 6393x doesn't appear to? */ 580 /* This is to enable gathering the statistics. Maybe this 581 * should call out to a helper? Or we could do this at init time. 582 */ 583 err = mv88e6390_pcs_enable_checker(mpcs); 584 if (err) 585 goto err_free; 586 587 chip->ports[port].pcs_private = mpcs; 588 589 return 0; 590 591 err_free: 592 kfree(mpcs); 593 return err; 594 } 595 596 const struct mv88e6xxx_pcs_ops mv88e6390_pcs_ops = { 597 .pcs_init = mv88e6390_pcs_init, 598 .pcs_teardown = mv88e639x_pcs_teardown, 599 .pcs_select = mv88e639x_pcs_select, 600 }; 601 602 /* Marvell 88E6393X Specific support */ 603 604 static int mv88e6393x_power_lane(struct mv88e639x_pcs *mpcs, bool enable) 605 { 606 u16 val = MV88E6393X_SERDES_CTRL1_TX_PDOWN | 607 MV88E6393X_SERDES_CTRL1_RX_PDOWN; 608 609 return mv88e639x_modify(mpcs, MV88E6393X_SERDES_CTRL1, val, 610 enable ? 0 : val); 611 } 612 613 /* mv88e6393x family errata 4.6: 614 * Cannot clear PwrDn bit on SERDES if device is configured CPU_MGD mode or 615 * P0_mode is configured for [x]MII. 616 * Workaround: Set SERDES register 4.F002 bit 5=0 and bit 15=1. 617 * 618 * It seems that after this workaround the SERDES is automatically powered up 619 * (the bit is cleared), so power it down. 620 */ 621 static int mv88e6393x_erratum_4_6(struct mv88e639x_pcs *mpcs) 622 { 623 int err; 624 625 err = mv88e639x_modify(mpcs, MV88E6393X_SERDES_POC, 626 MV88E6393X_SERDES_POC_PDOWN | 627 MV88E6393X_SERDES_POC_RESET, 628 MV88E6393X_SERDES_POC_RESET); 629 if (err) 630 return err; 631 632 err = mv88e639x_modify(mpcs, MV88E6390_SGMII_BMCR, 633 BMCR_PDOWN, BMCR_PDOWN); 634 if (err) 635 return err; 636 637 err = mv88e639x_sgmii_pcs_control_pwr(mpcs, false); 638 if (err) 639 return err; 640 641 return mv88e6393x_power_lane(mpcs, false); 642 } 643 644 /* mv88e6393x family errata 4.8: 645 * When a SERDES port is operating in 1000BASE-X or SGMII mode link may not 646 * come up after hardware reset or software reset of SERDES core. Workaround 647 * is to write SERDES register 4.F074.14=1 for only those modes and 0 in all 648 * other modes. 649 */ 650 static int mv88e6393x_erratum_4_8(struct mv88e639x_pcs *mpcs) 651 { 652 u16 reg, poc; 653 int err; 654 655 err = mv88e639x_read(mpcs, MV88E6393X_SERDES_POC, &poc); 656 if (err) 657 return err; 658 659 poc &= MV88E6393X_SERDES_POC_PCS_MASK; 660 if (poc == MV88E6393X_SERDES_POC_PCS_1000BASEX || 661 poc == MV88E6393X_SERDES_POC_PCS_SGMII_PHY || 662 poc == MV88E6393X_SERDES_POC_PCS_SGMII_MAC) 663 reg = MV88E6393X_ERRATA_4_8_BIT; 664 else 665 reg = 0; 666 667 return mv88e639x_modify(mpcs, MV88E6393X_ERRATA_4_8_REG, 668 MV88E6393X_ERRATA_4_8_BIT, reg); 669 } 670 671 /* mv88e6393x family errata 5.2: 672 * For optimal signal integrity the following sequence should be applied to 673 * SERDES operating in 10G mode. These registers only apply to 10G operation 674 * and have no effect on other speeds. 675 */ 676 static int mv88e6393x_erratum_5_2(struct mv88e639x_pcs *mpcs) 677 { 678 static const struct { 679 u16 dev, reg, val, mask; 680 } fixes[] = { 681 { MDIO_MMD_VEND1, 0x8093, 0xcb5a, 0xffff }, 682 { MDIO_MMD_VEND1, 0x8171, 0x7088, 0xffff }, 683 { MDIO_MMD_VEND1, 0x80c9, 0x311a, 0xffff }, 684 { MDIO_MMD_VEND1, 0x80a2, 0x8000, 0xff7f }, 685 { MDIO_MMD_VEND1, 0x80a9, 0x0000, 0xfff0 }, 686 { MDIO_MMD_VEND1, 0x80a3, 0x0000, 0xf8ff }, 687 { MDIO_MMD_PHYXS, MV88E6393X_SERDES_POC, 688 MV88E6393X_SERDES_POC_RESET, MV88E6393X_SERDES_POC_RESET }, 689 }; 690 int err, i; 691 692 for (i = 0; i < ARRAY_SIZE(fixes); ++i) { 693 err = mdiodev_c45_modify(&mpcs->mdio, fixes[i].dev, 694 fixes[i].reg, fixes[i].mask, 695 fixes[i].val); 696 if (err) 697 return err; 698 } 699 700 return 0; 701 } 702 703 /* Inband AN is broken on Amethyst in 2500base-x mode when set by standard 704 * mechanism (via cmode). 705 * We can get around this by configuring the PCS mode to 1000base-x and then 706 * writing value 0x58 to register 1e.8000. (This must be done while SerDes 707 * receiver and transmitter are disabled, which is, when this function is 708 * called.) 709 * It seem that when we do this configuration to 2500base-x mode (by changing 710 * PCS mode to 1000base-x and frequency to 3.125 GHz from 1.25 GHz) and then 711 * configure to sgmii or 1000base-x, the device thinks that it already has 712 * SerDes at 1.25 GHz and does not change the 1e.8000 register, leaving SerDes 713 * at 3.125 GHz. 714 * To avoid this, change PCS mode back to 2500base-x when disabling SerDes from 715 * 2500base-x mode. 716 */ 717 static int mv88e6393x_fix_2500basex_an(struct mv88e639x_pcs *mpcs, bool on) 718 { 719 u16 reg; 720 int err; 721 722 if (on) 723 reg = MV88E6393X_SERDES_POC_PCS_1000BASEX | 724 MV88E6393X_SERDES_POC_AN; 725 else 726 reg = MV88E6393X_SERDES_POC_PCS_2500BASEX; 727 728 reg |= MV88E6393X_SERDES_POC_RESET; 729 730 err = mv88e639x_modify(mpcs, MV88E6393X_SERDES_POC, 731 MV88E6393X_SERDES_POC_PCS_MASK | 732 MV88E6393X_SERDES_POC_AN | 733 MV88E6393X_SERDES_POC_RESET, reg); 734 if (err) 735 return err; 736 737 return mdiodev_c45_write(&mpcs->mdio, MDIO_MMD_VEND1, 0x8000, 0x58); 738 } 739 740 static int mv88e6393x_sgmii_apply_2500basex_an(struct mv88e639x_pcs *mpcs, 741 phy_interface_t interface, 742 bool enable) 743 { 744 int err; 745 746 if (interface != PHY_INTERFACE_MODE_2500BASEX) 747 return 0; 748 749 err = mv88e6393x_fix_2500basex_an(mpcs, enable); 750 if (err) 751 dev_err(mpcs->mdio.dev.parent, 752 "failed to %s 2500basex fix: %pe\n", 753 enable ? "enable" : "disable", ERR_PTR(err)); 754 755 return err; 756 } 757 758 static void mv88e6393x_sgmii_pcs_disable(struct phylink_pcs *pcs) 759 { 760 struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs); 761 762 mv88e639x_sgmii_pcs_disable(pcs); 763 mv88e6393x_power_lane(mpcs, false); 764 mv88e6393x_sgmii_apply_2500basex_an(mpcs, mpcs->interface, false); 765 } 766 767 static void mv88e6393x_sgmii_pcs_pre_config(struct phylink_pcs *pcs, 768 phy_interface_t interface) 769 { 770 struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs); 771 772 mv88e639x_sgmii_pcs_pre_config(pcs, interface); 773 mv88e6393x_power_lane(mpcs, false); 774 mv88e6393x_sgmii_apply_2500basex_an(mpcs, mpcs->interface, false); 775 } 776 777 static int mv88e6393x_sgmii_pcs_post_config(struct phylink_pcs *pcs, 778 phy_interface_t interface) 779 { 780 struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs); 781 int err; 782 783 err = mv88e6393x_erratum_4_8(mpcs); 784 if (err) 785 return err; 786 787 err = mv88e6393x_sgmii_apply_2500basex_an(mpcs, interface, true); 788 if (err) 789 return err; 790 791 err = mv88e6393x_power_lane(mpcs, true); 792 if (err) 793 return err; 794 795 return mv88e639x_sgmii_pcs_post_config(pcs, interface); 796 } 797 798 static const struct phylink_pcs_ops mv88e6393x_sgmii_pcs_ops = { 799 .pcs_enable = mv88e639x_sgmii_pcs_enable, 800 .pcs_disable = mv88e6393x_sgmii_pcs_disable, 801 .pcs_pre_config = mv88e6393x_sgmii_pcs_pre_config, 802 .pcs_post_config = mv88e6393x_sgmii_pcs_post_config, 803 .pcs_get_state = mv88e639x_sgmii_pcs_get_state, 804 .pcs_an_restart = mv88e639x_sgmii_pcs_an_restart, 805 .pcs_config = mv88e639x_sgmii_pcs_config, 806 .pcs_link_up = mv88e639x_sgmii_pcs_link_up, 807 }; 808 809 static irqreturn_t mv88e6393x_xg_handle_irq(struct mv88e639x_pcs *mpcs) 810 { 811 u16 int_status, stat1; 812 bool link_down; 813 int err; 814 815 err = mv88e639x_read(mpcs, MV88E6393X_10G_INT_STATUS, &int_status); 816 if (err) 817 return IRQ_NONE; 818 819 if (int_status & MV88E6393X_10G_INT_LINK_CHANGE) { 820 err = mv88e639x_read(mpcs, MV88E6390_10G_STAT1, &stat1); 821 if (err) 822 return IRQ_NONE; 823 824 link_down = !(stat1 & MDIO_STAT1_LSTATUS); 825 826 phylink_pcs_change(&mpcs->xg_pcs, !link_down); 827 828 return IRQ_HANDLED; 829 } 830 831 return IRQ_NONE; 832 } 833 834 static int mv88e6393x_xg_control_irq(struct mv88e639x_pcs *mpcs, bool enable) 835 { 836 u16 val = 0; 837 838 if (enable) 839 val = MV88E6393X_10G_INT_LINK_CHANGE; 840 841 return mv88e639x_modify(mpcs, MV88E6393X_10G_INT_ENABLE, 842 MV88E6393X_10G_INT_LINK_CHANGE, val); 843 } 844 845 static int mv88e6393x_xg_pcs_enable(struct phylink_pcs *pcs) 846 { 847 struct mv88e639x_pcs *mpcs = xg_pcs_to_mv88e639x_pcs(pcs); 848 849 mpcs->handle_irq = mv88e6393x_xg_handle_irq; 850 851 return mv88e6393x_xg_control_irq(mpcs, !!mpcs->irq); 852 } 853 854 static void mv88e6393x_xg_pcs_disable(struct phylink_pcs *pcs) 855 { 856 struct mv88e639x_pcs *mpcs = xg_pcs_to_mv88e639x_pcs(pcs); 857 858 mv88e6393x_xg_control_irq(mpcs, false); 859 mv88e639x_xg_pcs_disable(mpcs); 860 mv88e6393x_power_lane(mpcs, false); 861 } 862 863 /* The PCS has to be powered down while CMODE is changed */ 864 static void mv88e6393x_xg_pcs_pre_config(struct phylink_pcs *pcs, 865 phy_interface_t interface) 866 { 867 struct mv88e639x_pcs *mpcs = xg_pcs_to_mv88e639x_pcs(pcs); 868 869 mv88e639x_xg_pcs_disable(mpcs); 870 mv88e6393x_power_lane(mpcs, false); 871 } 872 873 static int mv88e6393x_xg_pcs_post_config(struct phylink_pcs *pcs, 874 phy_interface_t interface) 875 { 876 struct mv88e639x_pcs *mpcs = xg_pcs_to_mv88e639x_pcs(pcs); 877 int err; 878 879 if (interface == PHY_INTERFACE_MODE_10GBASER || 880 interface == PHY_INTERFACE_MODE_USXGMII) { 881 err = mv88e6393x_erratum_5_2(mpcs); 882 if (err) 883 return err; 884 } 885 886 err = mv88e6393x_power_lane(mpcs, true); 887 if (err) 888 return err; 889 890 return mv88e639x_xg_pcs_enable(mpcs); 891 } 892 893 static void mv88e6393x_xg_pcs_get_state(struct phylink_pcs *pcs, 894 unsigned int neg_mode, 895 struct phylink_link_state *state) 896 { 897 struct mv88e639x_pcs *mpcs = xg_pcs_to_mv88e639x_pcs(pcs); 898 u16 status, lp_status; 899 int err; 900 901 if (state->interface != PHY_INTERFACE_MODE_USXGMII) 902 return mv88e639x_xg_pcs_get_state(pcs, neg_mode, state); 903 904 state->link = false; 905 906 err = mv88e639x_read(mpcs, MV88E6390_USXGMII_PHY_STATUS, &status); 907 err = err ? : mv88e639x_read(mpcs, MV88E6390_USXGMII_LP_STATUS, &lp_status); 908 if (err) { 909 dev_err(mpcs->mdio.dev.parent, 910 "can't read USXGMII status: %pe\n", ERR_PTR(err)); 911 return; 912 } 913 914 state->link = !!(status & MDIO_USXGMII_LINK); 915 state->an_complete = state->link; 916 phylink_decode_usxgmii_word(state, lp_status); 917 } 918 919 static const struct phylink_pcs_ops mv88e6393x_xg_pcs_ops = { 920 .pcs_enable = mv88e6393x_xg_pcs_enable, 921 .pcs_disable = mv88e6393x_xg_pcs_disable, 922 .pcs_pre_config = mv88e6393x_xg_pcs_pre_config, 923 .pcs_post_config = mv88e6393x_xg_pcs_post_config, 924 .pcs_get_state = mv88e6393x_xg_pcs_get_state, 925 .pcs_config = mv88e639x_xg_pcs_config, 926 }; 927 928 static int mv88e6393x_pcs_init(struct mv88e6xxx_chip *chip, int port) 929 { 930 struct mv88e639x_pcs *mpcs; 931 struct mii_bus *bus; 932 struct device *dev; 933 int lane, err; 934 935 lane = mv88e6xxx_serdes_get_lane(chip, port); 936 if (lane < 0) 937 return 0; 938 939 bus = mv88e6xxx_default_mdio_bus(chip); 940 dev = chip->dev; 941 942 mpcs = mv88e639x_pcs_alloc(dev, bus, lane, port); 943 if (!mpcs) 944 return -ENOMEM; 945 946 mpcs->sgmii_pcs.ops = &mv88e6393x_sgmii_pcs_ops; 947 mpcs->sgmii_pcs.neg_mode = true; 948 mpcs->xg_pcs.ops = &mv88e6393x_xg_pcs_ops; 949 mpcs->xg_pcs.neg_mode = true; 950 mpcs->supports_5g = true; 951 952 err = mv88e6393x_erratum_4_6(mpcs); 953 if (err) 954 goto err_free; 955 956 err = mv88e639x_pcs_setup_irq(mpcs, chip, port); 957 if (err) 958 goto err_free; 959 960 chip->ports[port].pcs_private = mpcs; 961 962 return 0; 963 964 err_free: 965 kfree(mpcs); 966 return err; 967 } 968 969 const struct mv88e6xxx_pcs_ops mv88e6393x_pcs_ops = { 970 .pcs_init = mv88e6393x_pcs_init, 971 .pcs_teardown = mv88e639x_pcs_teardown, 972 .pcs_select = mv88e639x_pcs_select, 973 }; 974