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->xg_pcs.ops = &mv88e6390_xg_pcs_ops; 569 570 if (chip->info->prod_num == MV88E6XXX_PORT_SWITCH_ID_PROD_6190X || 571 chip->info->prod_num == MV88E6XXX_PORT_SWITCH_ID_PROD_6390X) 572 mpcs->erratum_3_14 = true; 573 574 err = mv88e639x_pcs_setup_irq(mpcs, chip, port); 575 if (err) 576 goto err_free; 577 578 /* 6390 and 6390x has the checker, 6393x doesn't appear to? */ 579 /* This is to enable gathering the statistics. Maybe this 580 * should call out to a helper? Or we could do this at init time. 581 */ 582 err = mv88e6390_pcs_enable_checker(mpcs); 583 if (err) 584 goto err_free; 585 586 chip->ports[port].pcs_private = mpcs; 587 588 return 0; 589 590 err_free: 591 kfree(mpcs); 592 return err; 593 } 594 595 const struct mv88e6xxx_pcs_ops mv88e6390_pcs_ops = { 596 .pcs_init = mv88e6390_pcs_init, 597 .pcs_teardown = mv88e639x_pcs_teardown, 598 .pcs_select = mv88e639x_pcs_select, 599 }; 600 601 /* Marvell 88E6393X Specific support */ 602 603 static int mv88e6393x_power_lane(struct mv88e639x_pcs *mpcs, bool enable) 604 { 605 u16 val = MV88E6393X_SERDES_CTRL1_TX_PDOWN | 606 MV88E6393X_SERDES_CTRL1_RX_PDOWN; 607 608 return mv88e639x_modify(mpcs, MV88E6393X_SERDES_CTRL1, val, 609 enable ? 0 : val); 610 } 611 612 /* mv88e6393x family errata 4.6: 613 * Cannot clear PwrDn bit on SERDES if device is configured CPU_MGD mode or 614 * P0_mode is configured for [x]MII. 615 * Workaround: Set SERDES register 4.F002 bit 5=0 and bit 15=1. 616 * 617 * It seems that after this workaround the SERDES is automatically powered up 618 * (the bit is cleared), so power it down. 619 */ 620 static int mv88e6393x_erratum_4_6(struct mv88e639x_pcs *mpcs) 621 { 622 int err; 623 624 err = mv88e639x_modify(mpcs, MV88E6393X_SERDES_POC, 625 MV88E6393X_SERDES_POC_PDOWN | 626 MV88E6393X_SERDES_POC_RESET, 627 MV88E6393X_SERDES_POC_RESET); 628 if (err) 629 return err; 630 631 err = mv88e639x_modify(mpcs, MV88E6390_SGMII_BMCR, 632 BMCR_PDOWN, BMCR_PDOWN); 633 if (err) 634 return err; 635 636 err = mv88e639x_sgmii_pcs_control_pwr(mpcs, false); 637 if (err) 638 return err; 639 640 return mv88e6393x_power_lane(mpcs, false); 641 } 642 643 /* mv88e6393x family errata 4.8: 644 * When a SERDES port is operating in 1000BASE-X or SGMII mode link may not 645 * come up after hardware reset or software reset of SERDES core. Workaround 646 * is to write SERDES register 4.F074.14=1 for only those modes and 0 in all 647 * other modes. 648 */ 649 static int mv88e6393x_erratum_4_8(struct mv88e639x_pcs *mpcs) 650 { 651 u16 reg, poc; 652 int err; 653 654 err = mv88e639x_read(mpcs, MV88E6393X_SERDES_POC, &poc); 655 if (err) 656 return err; 657 658 poc &= MV88E6393X_SERDES_POC_PCS_MASK; 659 if (poc == MV88E6393X_SERDES_POC_PCS_1000BASEX || 660 poc == MV88E6393X_SERDES_POC_PCS_SGMII_PHY || 661 poc == MV88E6393X_SERDES_POC_PCS_SGMII_MAC) 662 reg = MV88E6393X_ERRATA_4_8_BIT; 663 else 664 reg = 0; 665 666 return mv88e639x_modify(mpcs, MV88E6393X_ERRATA_4_8_REG, 667 MV88E6393X_ERRATA_4_8_BIT, reg); 668 } 669 670 /* mv88e6393x family errata 5.2: 671 * For optimal signal integrity the following sequence should be applied to 672 * SERDES operating in 10G mode. These registers only apply to 10G operation 673 * and have no effect on other speeds. 674 */ 675 static int mv88e6393x_erratum_5_2(struct mv88e639x_pcs *mpcs) 676 { 677 static const struct { 678 u16 dev, reg, val, mask; 679 } fixes[] = { 680 { MDIO_MMD_VEND1, 0x8093, 0xcb5a, 0xffff }, 681 { MDIO_MMD_VEND1, 0x8171, 0x7088, 0xffff }, 682 { MDIO_MMD_VEND1, 0x80c9, 0x311a, 0xffff }, 683 { MDIO_MMD_VEND1, 0x80a2, 0x8000, 0xff7f }, 684 { MDIO_MMD_VEND1, 0x80a9, 0x0000, 0xfff0 }, 685 { MDIO_MMD_VEND1, 0x80a3, 0x0000, 0xf8ff }, 686 { MDIO_MMD_PHYXS, MV88E6393X_SERDES_POC, 687 MV88E6393X_SERDES_POC_RESET, MV88E6393X_SERDES_POC_RESET }, 688 }; 689 int err, i; 690 691 for (i = 0; i < ARRAY_SIZE(fixes); ++i) { 692 err = mdiodev_c45_modify(&mpcs->mdio, fixes[i].dev, 693 fixes[i].reg, fixes[i].mask, 694 fixes[i].val); 695 if (err) 696 return err; 697 } 698 699 return 0; 700 } 701 702 /* Inband AN is broken on Amethyst in 2500base-x mode when set by standard 703 * mechanism (via cmode). 704 * We can get around this by configuring the PCS mode to 1000base-x and then 705 * writing value 0x58 to register 1e.8000. (This must be done while SerDes 706 * receiver and transmitter are disabled, which is, when this function is 707 * called.) 708 * It seem that when we do this configuration to 2500base-x mode (by changing 709 * PCS mode to 1000base-x and frequency to 3.125 GHz from 1.25 GHz) and then 710 * configure to sgmii or 1000base-x, the device thinks that it already has 711 * SerDes at 1.25 GHz and does not change the 1e.8000 register, leaving SerDes 712 * at 3.125 GHz. 713 * To avoid this, change PCS mode back to 2500base-x when disabling SerDes from 714 * 2500base-x mode. 715 */ 716 static int mv88e6393x_fix_2500basex_an(struct mv88e639x_pcs *mpcs, bool on) 717 { 718 u16 reg; 719 int err; 720 721 if (on) 722 reg = MV88E6393X_SERDES_POC_PCS_1000BASEX | 723 MV88E6393X_SERDES_POC_AN; 724 else 725 reg = MV88E6393X_SERDES_POC_PCS_2500BASEX; 726 727 reg |= MV88E6393X_SERDES_POC_RESET; 728 729 err = mv88e639x_modify(mpcs, MV88E6393X_SERDES_POC, 730 MV88E6393X_SERDES_POC_PCS_MASK | 731 MV88E6393X_SERDES_POC_AN | 732 MV88E6393X_SERDES_POC_RESET, reg); 733 if (err) 734 return err; 735 736 return mdiodev_c45_write(&mpcs->mdio, MDIO_MMD_VEND1, 0x8000, 0x58); 737 } 738 739 static int mv88e6393x_sgmii_apply_2500basex_an(struct mv88e639x_pcs *mpcs, 740 phy_interface_t interface, 741 bool enable) 742 { 743 int err; 744 745 if (interface != PHY_INTERFACE_MODE_2500BASEX) 746 return 0; 747 748 err = mv88e6393x_fix_2500basex_an(mpcs, enable); 749 if (err) 750 dev_err(mpcs->mdio.dev.parent, 751 "failed to %s 2500basex fix: %pe\n", 752 str_enable_disable(enable), ERR_PTR(err)); 753 754 return err; 755 } 756 757 static void mv88e6393x_sgmii_pcs_disable(struct phylink_pcs *pcs) 758 { 759 struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs); 760 761 mv88e639x_sgmii_pcs_disable(pcs); 762 mv88e6393x_power_lane(mpcs, false); 763 mv88e6393x_sgmii_apply_2500basex_an(mpcs, mpcs->interface, false); 764 } 765 766 static void mv88e6393x_sgmii_pcs_pre_config(struct phylink_pcs *pcs, 767 phy_interface_t interface) 768 { 769 struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs); 770 771 mv88e639x_sgmii_pcs_pre_config(pcs, interface); 772 mv88e6393x_power_lane(mpcs, false); 773 mv88e6393x_sgmii_apply_2500basex_an(mpcs, mpcs->interface, false); 774 } 775 776 static int mv88e6393x_sgmii_pcs_post_config(struct phylink_pcs *pcs, 777 phy_interface_t interface) 778 { 779 struct mv88e639x_pcs *mpcs = sgmii_pcs_to_mv88e639x_pcs(pcs); 780 int err; 781 782 err = mv88e6393x_erratum_4_8(mpcs); 783 if (err) 784 return err; 785 786 err = mv88e6393x_sgmii_apply_2500basex_an(mpcs, interface, true); 787 if (err) 788 return err; 789 790 err = mv88e6393x_power_lane(mpcs, true); 791 if (err) 792 return err; 793 794 return mv88e639x_sgmii_pcs_post_config(pcs, interface); 795 } 796 797 static const struct phylink_pcs_ops mv88e6393x_sgmii_pcs_ops = { 798 .pcs_enable = mv88e639x_sgmii_pcs_enable, 799 .pcs_disable = mv88e6393x_sgmii_pcs_disable, 800 .pcs_pre_config = mv88e6393x_sgmii_pcs_pre_config, 801 .pcs_post_config = mv88e6393x_sgmii_pcs_post_config, 802 .pcs_get_state = mv88e639x_sgmii_pcs_get_state, 803 .pcs_an_restart = mv88e639x_sgmii_pcs_an_restart, 804 .pcs_config = mv88e639x_sgmii_pcs_config, 805 .pcs_link_up = mv88e639x_sgmii_pcs_link_up, 806 }; 807 808 static irqreturn_t mv88e6393x_xg_handle_irq(struct mv88e639x_pcs *mpcs) 809 { 810 u16 int_status, stat1; 811 bool link_down; 812 int err; 813 814 err = mv88e639x_read(mpcs, MV88E6393X_10G_INT_STATUS, &int_status); 815 if (err) 816 return IRQ_NONE; 817 818 if (int_status & MV88E6393X_10G_INT_LINK_CHANGE) { 819 err = mv88e639x_read(mpcs, MV88E6390_10G_STAT1, &stat1); 820 if (err) 821 return IRQ_NONE; 822 823 link_down = !(stat1 & MDIO_STAT1_LSTATUS); 824 825 phylink_pcs_change(&mpcs->xg_pcs, !link_down); 826 827 return IRQ_HANDLED; 828 } 829 830 return IRQ_NONE; 831 } 832 833 static int mv88e6393x_xg_control_irq(struct mv88e639x_pcs *mpcs, bool enable) 834 { 835 u16 val = 0; 836 837 if (enable) 838 val = MV88E6393X_10G_INT_LINK_CHANGE; 839 840 return mv88e639x_modify(mpcs, MV88E6393X_10G_INT_ENABLE, 841 MV88E6393X_10G_INT_LINK_CHANGE, val); 842 } 843 844 static int mv88e6393x_xg_pcs_enable(struct phylink_pcs *pcs) 845 { 846 struct mv88e639x_pcs *mpcs = xg_pcs_to_mv88e639x_pcs(pcs); 847 848 mpcs->handle_irq = mv88e6393x_xg_handle_irq; 849 850 return mv88e6393x_xg_control_irq(mpcs, !!mpcs->irq); 851 } 852 853 static void mv88e6393x_xg_pcs_disable(struct phylink_pcs *pcs) 854 { 855 struct mv88e639x_pcs *mpcs = xg_pcs_to_mv88e639x_pcs(pcs); 856 857 mv88e6393x_xg_control_irq(mpcs, false); 858 mv88e639x_xg_pcs_disable(mpcs); 859 mv88e6393x_power_lane(mpcs, false); 860 } 861 862 /* The PCS has to be powered down while CMODE is changed */ 863 static void mv88e6393x_xg_pcs_pre_config(struct phylink_pcs *pcs, 864 phy_interface_t interface) 865 { 866 struct mv88e639x_pcs *mpcs = xg_pcs_to_mv88e639x_pcs(pcs); 867 868 mv88e639x_xg_pcs_disable(mpcs); 869 mv88e6393x_power_lane(mpcs, false); 870 } 871 872 static int mv88e6393x_xg_pcs_post_config(struct phylink_pcs *pcs, 873 phy_interface_t interface) 874 { 875 struct mv88e639x_pcs *mpcs = xg_pcs_to_mv88e639x_pcs(pcs); 876 int err; 877 878 if (interface == PHY_INTERFACE_MODE_10GBASER || 879 interface == PHY_INTERFACE_MODE_USXGMII) { 880 err = mv88e6393x_erratum_5_2(mpcs); 881 if (err) 882 return err; 883 } 884 885 err = mv88e6393x_power_lane(mpcs, true); 886 if (err) 887 return err; 888 889 return mv88e639x_xg_pcs_enable(mpcs); 890 } 891 892 static void mv88e6393x_xg_pcs_get_state(struct phylink_pcs *pcs, 893 unsigned int neg_mode, 894 struct phylink_link_state *state) 895 { 896 struct mv88e639x_pcs *mpcs = xg_pcs_to_mv88e639x_pcs(pcs); 897 u16 status, lp_status; 898 int err; 899 900 if (state->interface != PHY_INTERFACE_MODE_USXGMII) 901 return mv88e639x_xg_pcs_get_state(pcs, neg_mode, state); 902 903 state->link = false; 904 905 err = mv88e639x_read(mpcs, MV88E6390_USXGMII_PHY_STATUS, &status); 906 err = err ? : mv88e639x_read(mpcs, MV88E6390_USXGMII_LP_STATUS, &lp_status); 907 if (err) { 908 dev_err(mpcs->mdio.dev.parent, 909 "can't read USXGMII status: %pe\n", ERR_PTR(err)); 910 return; 911 } 912 913 state->link = !!(status & MDIO_USXGMII_LINK); 914 state->an_complete = state->link; 915 phylink_decode_usxgmii_word(state, lp_status); 916 } 917 918 static const struct phylink_pcs_ops mv88e6393x_xg_pcs_ops = { 919 .pcs_enable = mv88e6393x_xg_pcs_enable, 920 .pcs_disable = mv88e6393x_xg_pcs_disable, 921 .pcs_pre_config = mv88e6393x_xg_pcs_pre_config, 922 .pcs_post_config = mv88e6393x_xg_pcs_post_config, 923 .pcs_get_state = mv88e6393x_xg_pcs_get_state, 924 .pcs_config = mv88e639x_xg_pcs_config, 925 }; 926 927 static int mv88e6393x_pcs_init(struct mv88e6xxx_chip *chip, int port) 928 { 929 struct mv88e639x_pcs *mpcs; 930 struct mii_bus *bus; 931 struct device *dev; 932 int lane, err; 933 934 lane = mv88e6xxx_serdes_get_lane(chip, port); 935 if (lane < 0) 936 return 0; 937 938 bus = mv88e6xxx_default_mdio_bus(chip); 939 dev = chip->dev; 940 941 mpcs = mv88e639x_pcs_alloc(dev, bus, lane, port); 942 if (!mpcs) 943 return -ENOMEM; 944 945 mpcs->sgmii_pcs.ops = &mv88e6393x_sgmii_pcs_ops; 946 mpcs->xg_pcs.ops = &mv88e6393x_xg_pcs_ops; 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