pcs-xpcs.c (28696B)
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright (c) 2020 Synopsys, Inc. and/or its affiliates. 4 * Synopsys DesignWare XPCS helpers 5 * 6 * Author: Jose Abreu <Jose.Abreu@synopsys.com> 7 */ 8 9#include <linux/delay.h> 10#include <linux/pcs/pcs-xpcs.h> 11#include <linux/mdio.h> 12#include <linux/phylink.h> 13#include <linux/workqueue.h> 14#include "pcs-xpcs.h" 15 16#define phylink_pcs_to_xpcs(pl_pcs) \ 17 container_of((pl_pcs), struct dw_xpcs, pcs) 18 19static const int xpcs_usxgmii_features[] = { 20 ETHTOOL_LINK_MODE_Pause_BIT, 21 ETHTOOL_LINK_MODE_Asym_Pause_BIT, 22 ETHTOOL_LINK_MODE_Autoneg_BIT, 23 ETHTOOL_LINK_MODE_1000baseKX_Full_BIT, 24 ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT, 25 ETHTOOL_LINK_MODE_10000baseKR_Full_BIT, 26 ETHTOOL_LINK_MODE_2500baseX_Full_BIT, 27 __ETHTOOL_LINK_MODE_MASK_NBITS, 28}; 29 30static const int xpcs_10gkr_features[] = { 31 ETHTOOL_LINK_MODE_Pause_BIT, 32 ETHTOOL_LINK_MODE_Asym_Pause_BIT, 33 ETHTOOL_LINK_MODE_10000baseKR_Full_BIT, 34 __ETHTOOL_LINK_MODE_MASK_NBITS, 35}; 36 37static const int xpcs_xlgmii_features[] = { 38 ETHTOOL_LINK_MODE_Pause_BIT, 39 ETHTOOL_LINK_MODE_Asym_Pause_BIT, 40 ETHTOOL_LINK_MODE_25000baseCR_Full_BIT, 41 ETHTOOL_LINK_MODE_25000baseKR_Full_BIT, 42 ETHTOOL_LINK_MODE_25000baseSR_Full_BIT, 43 ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT, 44 ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT, 45 ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT, 46 ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT, 47 ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT, 48 ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT, 49 ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT, 50 ETHTOOL_LINK_MODE_50000baseKR_Full_BIT, 51 ETHTOOL_LINK_MODE_50000baseSR_Full_BIT, 52 ETHTOOL_LINK_MODE_50000baseCR_Full_BIT, 53 ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT, 54 ETHTOOL_LINK_MODE_50000baseDR_Full_BIT, 55 ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT, 56 ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT, 57 ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT, 58 ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT, 59 ETHTOOL_LINK_MODE_100000baseKR2_Full_BIT, 60 ETHTOOL_LINK_MODE_100000baseSR2_Full_BIT, 61 ETHTOOL_LINK_MODE_100000baseCR2_Full_BIT, 62 ETHTOOL_LINK_MODE_100000baseLR2_ER2_FR2_Full_BIT, 63 ETHTOOL_LINK_MODE_100000baseDR2_Full_BIT, 64 __ETHTOOL_LINK_MODE_MASK_NBITS, 65}; 66 67static const int xpcs_sgmii_features[] = { 68 ETHTOOL_LINK_MODE_Pause_BIT, 69 ETHTOOL_LINK_MODE_Asym_Pause_BIT, 70 ETHTOOL_LINK_MODE_Autoneg_BIT, 71 ETHTOOL_LINK_MODE_10baseT_Half_BIT, 72 ETHTOOL_LINK_MODE_10baseT_Full_BIT, 73 ETHTOOL_LINK_MODE_100baseT_Half_BIT, 74 ETHTOOL_LINK_MODE_100baseT_Full_BIT, 75 ETHTOOL_LINK_MODE_1000baseT_Half_BIT, 76 ETHTOOL_LINK_MODE_1000baseT_Full_BIT, 77 __ETHTOOL_LINK_MODE_MASK_NBITS, 78}; 79 80static const int xpcs_2500basex_features[] = { 81 ETHTOOL_LINK_MODE_Pause_BIT, 82 ETHTOOL_LINK_MODE_Asym_Pause_BIT, 83 ETHTOOL_LINK_MODE_Autoneg_BIT, 84 ETHTOOL_LINK_MODE_2500baseX_Full_BIT, 85 ETHTOOL_LINK_MODE_2500baseT_Full_BIT, 86 __ETHTOOL_LINK_MODE_MASK_NBITS, 87}; 88 89static const phy_interface_t xpcs_usxgmii_interfaces[] = { 90 PHY_INTERFACE_MODE_USXGMII, 91}; 92 93static const phy_interface_t xpcs_10gkr_interfaces[] = { 94 PHY_INTERFACE_MODE_10GKR, 95}; 96 97static const phy_interface_t xpcs_xlgmii_interfaces[] = { 98 PHY_INTERFACE_MODE_XLGMII, 99}; 100 101static const phy_interface_t xpcs_sgmii_interfaces[] = { 102 PHY_INTERFACE_MODE_SGMII, 103}; 104 105static const phy_interface_t xpcs_2500basex_interfaces[] = { 106 PHY_INTERFACE_MODE_2500BASEX, 107 PHY_INTERFACE_MODE_MAX, 108}; 109 110enum { 111 DW_XPCS_USXGMII, 112 DW_XPCS_10GKR, 113 DW_XPCS_XLGMII, 114 DW_XPCS_SGMII, 115 DW_XPCS_2500BASEX, 116 DW_XPCS_INTERFACE_MAX, 117}; 118 119struct xpcs_compat { 120 const int *supported; 121 const phy_interface_t *interface; 122 int num_interfaces; 123 int an_mode; 124 int (*pma_config)(struct dw_xpcs *xpcs); 125}; 126 127struct xpcs_id { 128 u32 id; 129 u32 mask; 130 const struct xpcs_compat *compat; 131}; 132 133static const struct xpcs_compat *xpcs_find_compat(const struct xpcs_id *id, 134 phy_interface_t interface) 135{ 136 int i, j; 137 138 for (i = 0; i < DW_XPCS_INTERFACE_MAX; i++) { 139 const struct xpcs_compat *compat = &id->compat[i]; 140 141 for (j = 0; j < compat->num_interfaces; j++) 142 if (compat->interface[j] == interface) 143 return compat; 144 } 145 146 return NULL; 147} 148 149int xpcs_get_an_mode(struct dw_xpcs *xpcs, phy_interface_t interface) 150{ 151 const struct xpcs_compat *compat; 152 153 compat = xpcs_find_compat(xpcs->id, interface); 154 if (!compat) 155 return -ENODEV; 156 157 return compat->an_mode; 158} 159EXPORT_SYMBOL_GPL(xpcs_get_an_mode); 160 161static bool __xpcs_linkmode_supported(const struct xpcs_compat *compat, 162 enum ethtool_link_mode_bit_indices linkmode) 163{ 164 int i; 165 166 for (i = 0; compat->supported[i] != __ETHTOOL_LINK_MODE_MASK_NBITS; i++) 167 if (compat->supported[i] == linkmode) 168 return true; 169 170 return false; 171} 172 173#define xpcs_linkmode_supported(compat, mode) \ 174 __xpcs_linkmode_supported(compat, ETHTOOL_LINK_MODE_ ## mode ## _BIT) 175 176int xpcs_read(struct dw_xpcs *xpcs, int dev, u32 reg) 177{ 178 struct mii_bus *bus = xpcs->mdiodev->bus; 179 int addr = xpcs->mdiodev->addr; 180 181 return mdiobus_c45_read(bus, addr, dev, reg); 182} 183 184int xpcs_write(struct dw_xpcs *xpcs, int dev, u32 reg, u16 val) 185{ 186 struct mii_bus *bus = xpcs->mdiodev->bus; 187 int addr = xpcs->mdiodev->addr; 188 189 return mdiobus_c45_write(bus, addr, dev, reg, val); 190} 191 192static int xpcs_read_vendor(struct dw_xpcs *xpcs, int dev, u32 reg) 193{ 194 return xpcs_read(xpcs, dev, DW_VENDOR | reg); 195} 196 197static int xpcs_write_vendor(struct dw_xpcs *xpcs, int dev, int reg, 198 u16 val) 199{ 200 return xpcs_write(xpcs, dev, DW_VENDOR | reg, val); 201} 202 203static int xpcs_read_vpcs(struct dw_xpcs *xpcs, int reg) 204{ 205 return xpcs_read_vendor(xpcs, MDIO_MMD_PCS, reg); 206} 207 208static int xpcs_write_vpcs(struct dw_xpcs *xpcs, int reg, u16 val) 209{ 210 return xpcs_write_vendor(xpcs, MDIO_MMD_PCS, reg, val); 211} 212 213static int xpcs_poll_reset(struct dw_xpcs *xpcs, int dev) 214{ 215 /* Poll until the reset bit clears (50ms per retry == 0.6 sec) */ 216 unsigned int retries = 12; 217 int ret; 218 219 do { 220 msleep(50); 221 ret = xpcs_read(xpcs, dev, MDIO_CTRL1); 222 if (ret < 0) 223 return ret; 224 } while (ret & MDIO_CTRL1_RESET && --retries); 225 226 return (ret & MDIO_CTRL1_RESET) ? -ETIMEDOUT : 0; 227} 228 229static int xpcs_soft_reset(struct dw_xpcs *xpcs, 230 const struct xpcs_compat *compat) 231{ 232 int ret, dev; 233 234 switch (compat->an_mode) { 235 case DW_AN_C73: 236 dev = MDIO_MMD_PCS; 237 break; 238 case DW_AN_C37_SGMII: 239 case DW_2500BASEX: 240 dev = MDIO_MMD_VEND2; 241 break; 242 default: 243 return -1; 244 } 245 246 ret = xpcs_write(xpcs, dev, MDIO_CTRL1, MDIO_CTRL1_RESET); 247 if (ret < 0) 248 return ret; 249 250 return xpcs_poll_reset(xpcs, dev); 251} 252 253#define xpcs_warn(__xpcs, __state, __args...) \ 254({ \ 255 if ((__state)->link) \ 256 dev_warn(&(__xpcs)->mdiodev->dev, ##__args); \ 257}) 258 259static int xpcs_read_fault_c73(struct dw_xpcs *xpcs, 260 struct phylink_link_state *state) 261{ 262 int ret; 263 264 ret = xpcs_read(xpcs, MDIO_MMD_PCS, MDIO_STAT1); 265 if (ret < 0) 266 return ret; 267 268 if (ret & MDIO_STAT1_FAULT) { 269 xpcs_warn(xpcs, state, "Link fault condition detected!\n"); 270 return -EFAULT; 271 } 272 273 ret = xpcs_read(xpcs, MDIO_MMD_PCS, MDIO_STAT2); 274 if (ret < 0) 275 return ret; 276 277 if (ret & MDIO_STAT2_RXFAULT) 278 xpcs_warn(xpcs, state, "Receiver fault detected!\n"); 279 if (ret & MDIO_STAT2_TXFAULT) 280 xpcs_warn(xpcs, state, "Transmitter fault detected!\n"); 281 282 ret = xpcs_read_vendor(xpcs, MDIO_MMD_PCS, DW_VR_XS_PCS_DIG_STS); 283 if (ret < 0) 284 return ret; 285 286 if (ret & DW_RXFIFO_ERR) { 287 xpcs_warn(xpcs, state, "FIFO fault condition detected!\n"); 288 return -EFAULT; 289 } 290 291 ret = xpcs_read(xpcs, MDIO_MMD_PCS, MDIO_PCS_10GBRT_STAT1); 292 if (ret < 0) 293 return ret; 294 295 if (!(ret & MDIO_PCS_10GBRT_STAT1_BLKLK)) 296 xpcs_warn(xpcs, state, "Link is not locked!\n"); 297 298 ret = xpcs_read(xpcs, MDIO_MMD_PCS, MDIO_PCS_10GBRT_STAT2); 299 if (ret < 0) 300 return ret; 301 302 if (ret & MDIO_PCS_10GBRT_STAT2_ERR) { 303 xpcs_warn(xpcs, state, "Link has errors!\n"); 304 return -EFAULT; 305 } 306 307 return 0; 308} 309 310static int xpcs_read_link_c73(struct dw_xpcs *xpcs, bool an) 311{ 312 bool link = true; 313 int ret; 314 315 ret = xpcs_read(xpcs, MDIO_MMD_PCS, MDIO_STAT1); 316 if (ret < 0) 317 return ret; 318 319 if (!(ret & MDIO_STAT1_LSTATUS)) 320 link = false; 321 322 if (an) { 323 ret = xpcs_read(xpcs, MDIO_MMD_AN, MDIO_STAT1); 324 if (ret < 0) 325 return ret; 326 327 if (!(ret & MDIO_STAT1_LSTATUS)) 328 link = false; 329 } 330 331 return link; 332} 333 334static int xpcs_get_max_usxgmii_speed(const unsigned long *supported) 335{ 336 int max = SPEED_UNKNOWN; 337 338 if (phylink_test(supported, 1000baseKX_Full)) 339 max = SPEED_1000; 340 if (phylink_test(supported, 2500baseX_Full)) 341 max = SPEED_2500; 342 if (phylink_test(supported, 10000baseKX4_Full)) 343 max = SPEED_10000; 344 if (phylink_test(supported, 10000baseKR_Full)) 345 max = SPEED_10000; 346 347 return max; 348} 349 350static void xpcs_config_usxgmii(struct dw_xpcs *xpcs, int speed) 351{ 352 int ret, speed_sel; 353 354 switch (speed) { 355 case SPEED_10: 356 speed_sel = DW_USXGMII_10; 357 break; 358 case SPEED_100: 359 speed_sel = DW_USXGMII_100; 360 break; 361 case SPEED_1000: 362 speed_sel = DW_USXGMII_1000; 363 break; 364 case SPEED_2500: 365 speed_sel = DW_USXGMII_2500; 366 break; 367 case SPEED_5000: 368 speed_sel = DW_USXGMII_5000; 369 break; 370 case SPEED_10000: 371 speed_sel = DW_USXGMII_10000; 372 break; 373 default: 374 /* Nothing to do here */ 375 return; 376 } 377 378 ret = xpcs_read_vpcs(xpcs, MDIO_CTRL1); 379 if (ret < 0) 380 goto out; 381 382 ret = xpcs_write_vpcs(xpcs, MDIO_CTRL1, ret | DW_USXGMII_EN); 383 if (ret < 0) 384 goto out; 385 386 ret = xpcs_read(xpcs, MDIO_MMD_VEND2, MDIO_CTRL1); 387 if (ret < 0) 388 goto out; 389 390 ret &= ~DW_USXGMII_SS_MASK; 391 ret |= speed_sel | DW_USXGMII_FULL; 392 393 ret = xpcs_write(xpcs, MDIO_MMD_VEND2, MDIO_CTRL1, ret); 394 if (ret < 0) 395 goto out; 396 397 ret = xpcs_read_vpcs(xpcs, MDIO_CTRL1); 398 if (ret < 0) 399 goto out; 400 401 ret = xpcs_write_vpcs(xpcs, MDIO_CTRL1, ret | DW_USXGMII_RST); 402 if (ret < 0) 403 goto out; 404 405 return; 406 407out: 408 pr_err("%s: XPCS access returned %pe\n", __func__, ERR_PTR(ret)); 409} 410 411static int _xpcs_config_aneg_c73(struct dw_xpcs *xpcs, 412 const struct xpcs_compat *compat) 413{ 414 int ret, adv; 415 416 /* By default, in USXGMII mode XPCS operates at 10G baud and 417 * replicates data to achieve lower speeds. Hereby, in this 418 * default configuration we need to advertise all supported 419 * modes and not only the ones we want to use. 420 */ 421 422 /* SR_AN_ADV3 */ 423 adv = 0; 424 if (xpcs_linkmode_supported(compat, 2500baseX_Full)) 425 adv |= DW_C73_2500KX; 426 427 /* TODO: 5000baseKR */ 428 429 ret = xpcs_write(xpcs, MDIO_MMD_AN, DW_SR_AN_ADV3, adv); 430 if (ret < 0) 431 return ret; 432 433 /* SR_AN_ADV2 */ 434 adv = 0; 435 if (xpcs_linkmode_supported(compat, 1000baseKX_Full)) 436 adv |= DW_C73_1000KX; 437 if (xpcs_linkmode_supported(compat, 10000baseKX4_Full)) 438 adv |= DW_C73_10000KX4; 439 if (xpcs_linkmode_supported(compat, 10000baseKR_Full)) 440 adv |= DW_C73_10000KR; 441 442 ret = xpcs_write(xpcs, MDIO_MMD_AN, DW_SR_AN_ADV2, adv); 443 if (ret < 0) 444 return ret; 445 446 /* SR_AN_ADV1 */ 447 adv = DW_C73_AN_ADV_SF; 448 if (xpcs_linkmode_supported(compat, Pause)) 449 adv |= DW_C73_PAUSE; 450 if (xpcs_linkmode_supported(compat, Asym_Pause)) 451 adv |= DW_C73_ASYM_PAUSE; 452 453 return xpcs_write(xpcs, MDIO_MMD_AN, DW_SR_AN_ADV1, adv); 454} 455 456static int xpcs_config_aneg_c73(struct dw_xpcs *xpcs, 457 const struct xpcs_compat *compat) 458{ 459 int ret; 460 461 ret = _xpcs_config_aneg_c73(xpcs, compat); 462 if (ret < 0) 463 return ret; 464 465 ret = xpcs_read(xpcs, MDIO_MMD_AN, MDIO_CTRL1); 466 if (ret < 0) 467 return ret; 468 469 ret |= MDIO_AN_CTRL1_ENABLE | MDIO_AN_CTRL1_RESTART; 470 471 return xpcs_write(xpcs, MDIO_MMD_AN, MDIO_CTRL1, ret); 472} 473 474static int xpcs_aneg_done_c73(struct dw_xpcs *xpcs, 475 struct phylink_link_state *state, 476 const struct xpcs_compat *compat) 477{ 478 int ret; 479 480 ret = xpcs_read(xpcs, MDIO_MMD_AN, MDIO_STAT1); 481 if (ret < 0) 482 return ret; 483 484 if (ret & MDIO_AN_STAT1_COMPLETE) { 485 ret = xpcs_read(xpcs, MDIO_MMD_AN, DW_SR_AN_LP_ABL1); 486 if (ret < 0) 487 return ret; 488 489 /* Check if Aneg outcome is valid */ 490 if (!(ret & DW_C73_AN_ADV_SF)) { 491 xpcs_config_aneg_c73(xpcs, compat); 492 return 0; 493 } 494 495 return 1; 496 } 497 498 return 0; 499} 500 501static int xpcs_read_lpa_c73(struct dw_xpcs *xpcs, 502 struct phylink_link_state *state) 503{ 504 int ret; 505 506 ret = xpcs_read(xpcs, MDIO_MMD_AN, MDIO_STAT1); 507 if (ret < 0) 508 return ret; 509 510 if (!(ret & MDIO_AN_STAT1_LPABLE)) { 511 phylink_clear(state->lp_advertising, Autoneg); 512 return 0; 513 } 514 515 phylink_set(state->lp_advertising, Autoneg); 516 517 /* Clause 73 outcome */ 518 ret = xpcs_read(xpcs, MDIO_MMD_AN, DW_SR_AN_LP_ABL3); 519 if (ret < 0) 520 return ret; 521 522 if (ret & DW_C73_2500KX) 523 phylink_set(state->lp_advertising, 2500baseX_Full); 524 525 ret = xpcs_read(xpcs, MDIO_MMD_AN, DW_SR_AN_LP_ABL2); 526 if (ret < 0) 527 return ret; 528 529 if (ret & DW_C73_1000KX) 530 phylink_set(state->lp_advertising, 1000baseKX_Full); 531 if (ret & DW_C73_10000KX4) 532 phylink_set(state->lp_advertising, 10000baseKX4_Full); 533 if (ret & DW_C73_10000KR) 534 phylink_set(state->lp_advertising, 10000baseKR_Full); 535 536 ret = xpcs_read(xpcs, MDIO_MMD_AN, DW_SR_AN_LP_ABL1); 537 if (ret < 0) 538 return ret; 539 540 if (ret & DW_C73_PAUSE) 541 phylink_set(state->lp_advertising, Pause); 542 if (ret & DW_C73_ASYM_PAUSE) 543 phylink_set(state->lp_advertising, Asym_Pause); 544 545 linkmode_and(state->lp_advertising, state->lp_advertising, 546 state->advertising); 547 return 0; 548} 549 550static void xpcs_resolve_lpa_c73(struct dw_xpcs *xpcs, 551 struct phylink_link_state *state) 552{ 553 int max_speed = xpcs_get_max_usxgmii_speed(state->lp_advertising); 554 555 state->pause = MLO_PAUSE_TX | MLO_PAUSE_RX; 556 state->speed = max_speed; 557 state->duplex = DUPLEX_FULL; 558} 559 560static int xpcs_get_max_xlgmii_speed(struct dw_xpcs *xpcs, 561 struct phylink_link_state *state) 562{ 563 unsigned long *adv = state->advertising; 564 int speed = SPEED_UNKNOWN; 565 int bit; 566 567 for_each_set_bit(bit, adv, __ETHTOOL_LINK_MODE_MASK_NBITS) { 568 int new_speed = SPEED_UNKNOWN; 569 570 switch (bit) { 571 case ETHTOOL_LINK_MODE_25000baseCR_Full_BIT: 572 case ETHTOOL_LINK_MODE_25000baseKR_Full_BIT: 573 case ETHTOOL_LINK_MODE_25000baseSR_Full_BIT: 574 new_speed = SPEED_25000; 575 break; 576 case ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT: 577 case ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT: 578 case ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT: 579 case ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT: 580 new_speed = SPEED_40000; 581 break; 582 case ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT: 583 case ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT: 584 case ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT: 585 case ETHTOOL_LINK_MODE_50000baseKR_Full_BIT: 586 case ETHTOOL_LINK_MODE_50000baseSR_Full_BIT: 587 case ETHTOOL_LINK_MODE_50000baseCR_Full_BIT: 588 case ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT: 589 case ETHTOOL_LINK_MODE_50000baseDR_Full_BIT: 590 new_speed = SPEED_50000; 591 break; 592 case ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT: 593 case ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT: 594 case ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT: 595 case ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT: 596 case ETHTOOL_LINK_MODE_100000baseKR2_Full_BIT: 597 case ETHTOOL_LINK_MODE_100000baseSR2_Full_BIT: 598 case ETHTOOL_LINK_MODE_100000baseCR2_Full_BIT: 599 case ETHTOOL_LINK_MODE_100000baseLR2_ER2_FR2_Full_BIT: 600 case ETHTOOL_LINK_MODE_100000baseDR2_Full_BIT: 601 new_speed = SPEED_100000; 602 break; 603 default: 604 continue; 605 } 606 607 if (new_speed > speed) 608 speed = new_speed; 609 } 610 611 return speed; 612} 613 614static void xpcs_resolve_pma(struct dw_xpcs *xpcs, 615 struct phylink_link_state *state) 616{ 617 state->pause = MLO_PAUSE_TX | MLO_PAUSE_RX; 618 state->duplex = DUPLEX_FULL; 619 620 switch (state->interface) { 621 case PHY_INTERFACE_MODE_10GKR: 622 state->speed = SPEED_10000; 623 break; 624 case PHY_INTERFACE_MODE_XLGMII: 625 state->speed = xpcs_get_max_xlgmii_speed(xpcs, state); 626 break; 627 default: 628 state->speed = SPEED_UNKNOWN; 629 break; 630 } 631} 632 633static int xpcs_validate(struct phylink_pcs *pcs, unsigned long *supported, 634 const struct phylink_link_state *state) 635{ 636 __ETHTOOL_DECLARE_LINK_MODE_MASK(xpcs_supported) = { 0, }; 637 const struct xpcs_compat *compat; 638 struct dw_xpcs *xpcs; 639 int i; 640 641 xpcs = phylink_pcs_to_xpcs(pcs); 642 compat = xpcs_find_compat(xpcs->id, state->interface); 643 644 /* Populate the supported link modes for this PHY interface type. 645 * FIXME: what about the port modes and autoneg bit? This masks 646 * all those away. 647 */ 648 if (compat) 649 for (i = 0; compat->supported[i] != __ETHTOOL_LINK_MODE_MASK_NBITS; i++) 650 set_bit(compat->supported[i], xpcs_supported); 651 652 linkmode_and(supported, supported, xpcs_supported); 653 654 return 0; 655} 656 657void xpcs_get_interfaces(struct dw_xpcs *xpcs, unsigned long *interfaces) 658{ 659 int i, j; 660 661 for (i = 0; i < DW_XPCS_INTERFACE_MAX; i++) { 662 const struct xpcs_compat *compat = &xpcs->id->compat[i]; 663 664 for (j = 0; j < compat->num_interfaces; j++) 665 if (compat->interface[j] < PHY_INTERFACE_MODE_MAX) 666 __set_bit(compat->interface[j], interfaces); 667 } 668} 669EXPORT_SYMBOL_GPL(xpcs_get_interfaces); 670 671int xpcs_config_eee(struct dw_xpcs *xpcs, int mult_fact_100ns, int enable) 672{ 673 int ret; 674 675 ret = xpcs_read(xpcs, MDIO_MMD_VEND2, DW_VR_MII_EEE_MCTRL0); 676 if (ret < 0) 677 return ret; 678 679 if (enable) { 680 /* Enable EEE */ 681 ret = DW_VR_MII_EEE_LTX_EN | DW_VR_MII_EEE_LRX_EN | 682 DW_VR_MII_EEE_TX_QUIET_EN | DW_VR_MII_EEE_RX_QUIET_EN | 683 DW_VR_MII_EEE_TX_EN_CTRL | DW_VR_MII_EEE_RX_EN_CTRL | 684 mult_fact_100ns << DW_VR_MII_EEE_MULT_FACT_100NS_SHIFT; 685 } else { 686 ret &= ~(DW_VR_MII_EEE_LTX_EN | DW_VR_MII_EEE_LRX_EN | 687 DW_VR_MII_EEE_TX_QUIET_EN | DW_VR_MII_EEE_RX_QUIET_EN | 688 DW_VR_MII_EEE_TX_EN_CTRL | DW_VR_MII_EEE_RX_EN_CTRL | 689 DW_VR_MII_EEE_MULT_FACT_100NS); 690 } 691 692 ret = xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_EEE_MCTRL0, ret); 693 if (ret < 0) 694 return ret; 695 696 ret = xpcs_read(xpcs, MDIO_MMD_VEND2, DW_VR_MII_EEE_MCTRL1); 697 if (ret < 0) 698 return ret; 699 700 if (enable) 701 ret |= DW_VR_MII_EEE_TRN_LPI; 702 else 703 ret &= ~DW_VR_MII_EEE_TRN_LPI; 704 705 return xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_EEE_MCTRL1, ret); 706} 707EXPORT_SYMBOL_GPL(xpcs_config_eee); 708 709static int xpcs_config_aneg_c37_sgmii(struct dw_xpcs *xpcs, unsigned int mode) 710{ 711 int ret, mdio_ctrl; 712 713 /* For AN for C37 SGMII mode, the settings are :- 714 * 1) VR_MII_MMD_CTRL Bit(12) [AN_ENABLE] = 0b (Disable SGMII AN in case 715 it is already enabled) 716 * 2) VR_MII_AN_CTRL Bit(2:1)[PCS_MODE] = 10b (SGMII AN) 717 * 3) VR_MII_AN_CTRL Bit(3) [TX_CONFIG] = 0b (MAC side SGMII) 718 * DW xPCS used with DW EQoS MAC is always MAC side SGMII. 719 * 4) VR_MII_DIG_CTRL1 Bit(9) [MAC_AUTO_SW] = 1b (Automatic 720 * speed/duplex mode change by HW after SGMII AN complete) 721 * 5) VR_MII_MMD_CTRL Bit(12) [AN_ENABLE] = 1b (Enable SGMII AN) 722 * 723 * Note: Since it is MAC side SGMII, there is no need to set 724 * SR_MII_AN_ADV. MAC side SGMII receives AN Tx Config from 725 * PHY about the link state change after C28 AN is completed 726 * between PHY and Link Partner. There is also no need to 727 * trigger AN restart for MAC-side SGMII. 728 */ 729 mdio_ctrl = xpcs_read(xpcs, MDIO_MMD_VEND2, DW_VR_MII_MMD_CTRL); 730 if (mdio_ctrl < 0) 731 return mdio_ctrl; 732 733 if (mdio_ctrl & AN_CL37_EN) { 734 ret = xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_MMD_CTRL, 735 mdio_ctrl & ~AN_CL37_EN); 736 if (ret < 0) 737 return ret; 738 } 739 740 ret = xpcs_read(xpcs, MDIO_MMD_VEND2, DW_VR_MII_AN_CTRL); 741 if (ret < 0) 742 return ret; 743 744 ret &= ~(DW_VR_MII_PCS_MODE_MASK | DW_VR_MII_TX_CONFIG_MASK); 745 ret |= (DW_VR_MII_PCS_MODE_C37_SGMII << 746 DW_VR_MII_AN_CTRL_PCS_MODE_SHIFT & 747 DW_VR_MII_PCS_MODE_MASK); 748 ret |= (DW_VR_MII_TX_CONFIG_MAC_SIDE_SGMII << 749 DW_VR_MII_AN_CTRL_TX_CONFIG_SHIFT & 750 DW_VR_MII_TX_CONFIG_MASK); 751 ret = xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_AN_CTRL, ret); 752 if (ret < 0) 753 return ret; 754 755 ret = xpcs_read(xpcs, MDIO_MMD_VEND2, DW_VR_MII_DIG_CTRL1); 756 if (ret < 0) 757 return ret; 758 759 if (phylink_autoneg_inband(mode)) 760 ret |= DW_VR_MII_DIG_CTRL1_MAC_AUTO_SW; 761 else 762 ret &= ~DW_VR_MII_DIG_CTRL1_MAC_AUTO_SW; 763 764 ret = xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_DIG_CTRL1, ret); 765 if (ret < 0) 766 return ret; 767 768 if (phylink_autoneg_inband(mode)) 769 ret = xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_MMD_CTRL, 770 mdio_ctrl | AN_CL37_EN); 771 772 return ret; 773} 774 775static int xpcs_config_2500basex(struct dw_xpcs *xpcs) 776{ 777 int ret; 778 779 ret = xpcs_read(xpcs, MDIO_MMD_VEND2, DW_VR_MII_DIG_CTRL1); 780 if (ret < 0) 781 return ret; 782 ret |= DW_VR_MII_DIG_CTRL1_2G5_EN; 783 ret &= ~DW_VR_MII_DIG_CTRL1_MAC_AUTO_SW; 784 ret = xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_DIG_CTRL1, ret); 785 if (ret < 0) 786 return ret; 787 788 ret = xpcs_read(xpcs, MDIO_MMD_VEND2, DW_VR_MII_MMD_CTRL); 789 if (ret < 0) 790 return ret; 791 ret &= ~AN_CL37_EN; 792 ret |= SGMII_SPEED_SS6; 793 ret &= ~SGMII_SPEED_SS13; 794 return xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_MMD_CTRL, ret); 795} 796 797int xpcs_do_config(struct dw_xpcs *xpcs, phy_interface_t interface, 798 unsigned int mode) 799{ 800 const struct xpcs_compat *compat; 801 int ret; 802 803 compat = xpcs_find_compat(xpcs->id, interface); 804 if (!compat) 805 return -ENODEV; 806 807 switch (compat->an_mode) { 808 case DW_AN_C73: 809 if (phylink_autoneg_inband(mode)) { 810 ret = xpcs_config_aneg_c73(xpcs, compat); 811 if (ret) 812 return ret; 813 } 814 break; 815 case DW_AN_C37_SGMII: 816 ret = xpcs_config_aneg_c37_sgmii(xpcs, mode); 817 if (ret) 818 return ret; 819 break; 820 case DW_2500BASEX: 821 ret = xpcs_config_2500basex(xpcs); 822 if (ret) 823 return ret; 824 break; 825 default: 826 return -1; 827 } 828 829 if (compat->pma_config) { 830 ret = compat->pma_config(xpcs); 831 if (ret) 832 return ret; 833 } 834 835 return 0; 836} 837EXPORT_SYMBOL_GPL(xpcs_do_config); 838 839static int xpcs_config(struct phylink_pcs *pcs, unsigned int mode, 840 phy_interface_t interface, 841 const unsigned long *advertising, 842 bool permit_pause_to_mac) 843{ 844 struct dw_xpcs *xpcs = phylink_pcs_to_xpcs(pcs); 845 846 return xpcs_do_config(xpcs, interface, mode); 847} 848 849static int xpcs_get_state_c73(struct dw_xpcs *xpcs, 850 struct phylink_link_state *state, 851 const struct xpcs_compat *compat) 852{ 853 int ret; 854 855 /* Link needs to be read first ... */ 856 state->link = xpcs_read_link_c73(xpcs, state->an_enabled) > 0 ? 1 : 0; 857 858 /* ... and then we check the faults. */ 859 ret = xpcs_read_fault_c73(xpcs, state); 860 if (ret) { 861 ret = xpcs_soft_reset(xpcs, compat); 862 if (ret) 863 return ret; 864 865 state->link = 0; 866 867 return xpcs_do_config(xpcs, state->interface, MLO_AN_INBAND); 868 } 869 870 if (state->an_enabled && xpcs_aneg_done_c73(xpcs, state, compat)) { 871 state->an_complete = true; 872 xpcs_read_lpa_c73(xpcs, state); 873 xpcs_resolve_lpa_c73(xpcs, state); 874 } else if (state->an_enabled) { 875 state->link = 0; 876 } else if (state->link) { 877 xpcs_resolve_pma(xpcs, state); 878 } 879 880 return 0; 881} 882 883static int xpcs_get_state_c37_sgmii(struct dw_xpcs *xpcs, 884 struct phylink_link_state *state) 885{ 886 int ret; 887 888 /* Reset link_state */ 889 state->link = false; 890 state->speed = SPEED_UNKNOWN; 891 state->duplex = DUPLEX_UNKNOWN; 892 state->pause = 0; 893 894 /* For C37 SGMII mode, we check DW_VR_MII_AN_INTR_STS for link 895 * status, speed and duplex. 896 */ 897 ret = xpcs_read(xpcs, MDIO_MMD_VEND2, DW_VR_MII_AN_INTR_STS); 898 if (ret < 0) 899 return false; 900 901 if (ret & DW_VR_MII_C37_ANSGM_SP_LNKSTS) { 902 int speed_value; 903 904 state->link = true; 905 906 speed_value = (ret & DW_VR_MII_AN_STS_C37_ANSGM_SP) >> 907 DW_VR_MII_AN_STS_C37_ANSGM_SP_SHIFT; 908 if (speed_value == DW_VR_MII_C37_ANSGM_SP_1000) 909 state->speed = SPEED_1000; 910 else if (speed_value == DW_VR_MII_C37_ANSGM_SP_100) 911 state->speed = SPEED_100; 912 else 913 state->speed = SPEED_10; 914 915 if (ret & DW_VR_MII_AN_STS_C37_ANSGM_FD) 916 state->duplex = DUPLEX_FULL; 917 else 918 state->duplex = DUPLEX_HALF; 919 } 920 921 return 0; 922} 923 924static void xpcs_get_state(struct phylink_pcs *pcs, 925 struct phylink_link_state *state) 926{ 927 struct dw_xpcs *xpcs = phylink_pcs_to_xpcs(pcs); 928 const struct xpcs_compat *compat; 929 int ret; 930 931 compat = xpcs_find_compat(xpcs->id, state->interface); 932 if (!compat) 933 return; 934 935 switch (compat->an_mode) { 936 case DW_AN_C73: 937 ret = xpcs_get_state_c73(xpcs, state, compat); 938 if (ret) { 939 pr_err("xpcs_get_state_c73 returned %pe\n", 940 ERR_PTR(ret)); 941 return; 942 } 943 break; 944 case DW_AN_C37_SGMII: 945 ret = xpcs_get_state_c37_sgmii(xpcs, state); 946 if (ret) { 947 pr_err("xpcs_get_state_c37_sgmii returned %pe\n", 948 ERR_PTR(ret)); 949 } 950 break; 951 default: 952 return; 953 } 954} 955 956static void xpcs_link_up_sgmii(struct dw_xpcs *xpcs, unsigned int mode, 957 int speed, int duplex) 958{ 959 int val, ret; 960 961 if (phylink_autoneg_inband(mode)) 962 return; 963 964 switch (speed) { 965 case SPEED_1000: 966 val = BMCR_SPEED1000; 967 break; 968 case SPEED_100: 969 val = BMCR_SPEED100; 970 break; 971 case SPEED_10: 972 val = BMCR_SPEED10; 973 break; 974 default: 975 return; 976 } 977 978 if (duplex == DUPLEX_FULL) 979 val |= BMCR_FULLDPLX; 980 981 ret = xpcs_write(xpcs, MDIO_MMD_VEND2, MDIO_CTRL1, val); 982 if (ret) 983 pr_err("%s: xpcs_write returned %pe\n", __func__, ERR_PTR(ret)); 984} 985 986void xpcs_link_up(struct phylink_pcs *pcs, unsigned int mode, 987 phy_interface_t interface, int speed, int duplex) 988{ 989 struct dw_xpcs *xpcs = phylink_pcs_to_xpcs(pcs); 990 991 if (interface == PHY_INTERFACE_MODE_USXGMII) 992 return xpcs_config_usxgmii(xpcs, speed); 993 if (interface == PHY_INTERFACE_MODE_SGMII) 994 return xpcs_link_up_sgmii(xpcs, mode, speed, duplex); 995} 996EXPORT_SYMBOL_GPL(xpcs_link_up); 997 998static u32 xpcs_get_id(struct dw_xpcs *xpcs) 999{ 1000 int ret; 1001 u32 id; 1002 1003 /* First, search C73 PCS using PCS MMD */ 1004 ret = xpcs_read(xpcs, MDIO_MMD_PCS, MII_PHYSID1); 1005 if (ret < 0) 1006 return 0xffffffff; 1007 1008 id = ret << 16; 1009 1010 ret = xpcs_read(xpcs, MDIO_MMD_PCS, MII_PHYSID2); 1011 if (ret < 0) 1012 return 0xffffffff; 1013 1014 /* If Device IDs are not all zeros or all ones, 1015 * we found C73 AN-type device 1016 */ 1017 if ((id | ret) && (id | ret) != 0xffffffff) 1018 return id | ret; 1019 1020 /* Next, search C37 PCS using Vendor-Specific MII MMD */ 1021 ret = xpcs_read(xpcs, MDIO_MMD_VEND2, MII_PHYSID1); 1022 if (ret < 0) 1023 return 0xffffffff; 1024 1025 id = ret << 16; 1026 1027 ret = xpcs_read(xpcs, MDIO_MMD_VEND2, MII_PHYSID2); 1028 if (ret < 0) 1029 return 0xffffffff; 1030 1031 /* If Device IDs are not all zeros, we found C37 AN-type device */ 1032 if (id | ret) 1033 return id | ret; 1034 1035 return 0xffffffff; 1036} 1037 1038static const struct xpcs_compat synopsys_xpcs_compat[DW_XPCS_INTERFACE_MAX] = { 1039 [DW_XPCS_USXGMII] = { 1040 .supported = xpcs_usxgmii_features, 1041 .interface = xpcs_usxgmii_interfaces, 1042 .num_interfaces = ARRAY_SIZE(xpcs_usxgmii_interfaces), 1043 .an_mode = DW_AN_C73, 1044 }, 1045 [DW_XPCS_10GKR] = { 1046 .supported = xpcs_10gkr_features, 1047 .interface = xpcs_10gkr_interfaces, 1048 .num_interfaces = ARRAY_SIZE(xpcs_10gkr_interfaces), 1049 .an_mode = DW_AN_C73, 1050 }, 1051 [DW_XPCS_XLGMII] = { 1052 .supported = xpcs_xlgmii_features, 1053 .interface = xpcs_xlgmii_interfaces, 1054 .num_interfaces = ARRAY_SIZE(xpcs_xlgmii_interfaces), 1055 .an_mode = DW_AN_C73, 1056 }, 1057 [DW_XPCS_SGMII] = { 1058 .supported = xpcs_sgmii_features, 1059 .interface = xpcs_sgmii_interfaces, 1060 .num_interfaces = ARRAY_SIZE(xpcs_sgmii_interfaces), 1061 .an_mode = DW_AN_C37_SGMII, 1062 }, 1063 [DW_XPCS_2500BASEX] = { 1064 .supported = xpcs_2500basex_features, 1065 .interface = xpcs_2500basex_interfaces, 1066 .num_interfaces = ARRAY_SIZE(xpcs_2500basex_features), 1067 .an_mode = DW_2500BASEX, 1068 }, 1069}; 1070 1071static const struct xpcs_compat nxp_sja1105_xpcs_compat[DW_XPCS_INTERFACE_MAX] = { 1072 [DW_XPCS_SGMII] = { 1073 .supported = xpcs_sgmii_features, 1074 .interface = xpcs_sgmii_interfaces, 1075 .num_interfaces = ARRAY_SIZE(xpcs_sgmii_interfaces), 1076 .an_mode = DW_AN_C37_SGMII, 1077 .pma_config = nxp_sja1105_sgmii_pma_config, 1078 }, 1079}; 1080 1081static const struct xpcs_compat nxp_sja1110_xpcs_compat[DW_XPCS_INTERFACE_MAX] = { 1082 [DW_XPCS_SGMII] = { 1083 .supported = xpcs_sgmii_features, 1084 .interface = xpcs_sgmii_interfaces, 1085 .num_interfaces = ARRAY_SIZE(xpcs_sgmii_interfaces), 1086 .an_mode = DW_AN_C37_SGMII, 1087 .pma_config = nxp_sja1110_sgmii_pma_config, 1088 }, 1089 [DW_XPCS_2500BASEX] = { 1090 .supported = xpcs_2500basex_features, 1091 .interface = xpcs_2500basex_interfaces, 1092 .num_interfaces = ARRAY_SIZE(xpcs_2500basex_interfaces), 1093 .an_mode = DW_2500BASEX, 1094 .pma_config = nxp_sja1110_2500basex_pma_config, 1095 }, 1096}; 1097 1098static const struct xpcs_id xpcs_id_list[] = { 1099 { 1100 .id = SYNOPSYS_XPCS_ID, 1101 .mask = SYNOPSYS_XPCS_MASK, 1102 .compat = synopsys_xpcs_compat, 1103 }, { 1104 .id = NXP_SJA1105_XPCS_ID, 1105 .mask = SYNOPSYS_XPCS_MASK, 1106 .compat = nxp_sja1105_xpcs_compat, 1107 }, { 1108 .id = NXP_SJA1110_XPCS_ID, 1109 .mask = SYNOPSYS_XPCS_MASK, 1110 .compat = nxp_sja1110_xpcs_compat, 1111 }, 1112}; 1113 1114static const struct phylink_pcs_ops xpcs_phylink_ops = { 1115 .pcs_validate = xpcs_validate, 1116 .pcs_config = xpcs_config, 1117 .pcs_get_state = xpcs_get_state, 1118 .pcs_link_up = xpcs_link_up, 1119}; 1120 1121struct dw_xpcs *xpcs_create(struct mdio_device *mdiodev, 1122 phy_interface_t interface) 1123{ 1124 struct dw_xpcs *xpcs; 1125 u32 xpcs_id; 1126 int i, ret; 1127 1128 xpcs = kzalloc(sizeof(*xpcs), GFP_KERNEL); 1129 if (!xpcs) 1130 return ERR_PTR(-ENOMEM); 1131 1132 xpcs->mdiodev = mdiodev; 1133 1134 xpcs_id = xpcs_get_id(xpcs); 1135 1136 for (i = 0; i < ARRAY_SIZE(xpcs_id_list); i++) { 1137 const struct xpcs_id *entry = &xpcs_id_list[i]; 1138 const struct xpcs_compat *compat; 1139 1140 if ((xpcs_id & entry->mask) != entry->id) 1141 continue; 1142 1143 xpcs->id = entry; 1144 1145 compat = xpcs_find_compat(entry, interface); 1146 if (!compat) { 1147 ret = -ENODEV; 1148 goto out; 1149 } 1150 1151 xpcs->pcs.ops = &xpcs_phylink_ops; 1152 xpcs->pcs.poll = true; 1153 1154 ret = xpcs_soft_reset(xpcs, compat); 1155 if (ret) 1156 goto out; 1157 1158 return xpcs; 1159 } 1160 1161 ret = -ENODEV; 1162 1163out: 1164 kfree(xpcs); 1165 1166 return ERR_PTR(ret); 1167} 1168EXPORT_SYMBOL_GPL(xpcs_create); 1169 1170void xpcs_destroy(struct dw_xpcs *xpcs) 1171{ 1172 kfree(xpcs); 1173} 1174EXPORT_SYMBOL_GPL(xpcs_destroy); 1175 1176MODULE_LICENSE("GPL v2");