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