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