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