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