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 15 #define SYNOPSYS_XPCS_USXGMII_ID 0x7996ced0 16 #define SYNOPSYS_XPCS_10GKR_ID 0x7996ced0 17 #define SYNOPSYS_XPCS_XLGMII_ID 0x7996ced0 18 #define SYNOPSYS_XPCS_MASK 0xffffffff 19 20 /* Vendor regs access */ 21 #define DW_VENDOR BIT(15) 22 23 /* VR_XS_PCS */ 24 #define DW_USXGMII_RST BIT(10) 25 #define DW_USXGMII_EN BIT(9) 26 #define DW_VR_XS_PCS_DIG_STS 0x0010 27 #define DW_RXFIFO_ERR GENMASK(6, 5) 28 29 /* SR_MII */ 30 #define DW_USXGMII_FULL BIT(8) 31 #define DW_USXGMII_SS_MASK (BIT(13) | BIT(6) | BIT(5)) 32 #define DW_USXGMII_10000 (BIT(13) | BIT(6)) 33 #define DW_USXGMII_5000 (BIT(13) | BIT(5)) 34 #define DW_USXGMII_2500 (BIT(5)) 35 #define DW_USXGMII_1000 (BIT(6)) 36 #define DW_USXGMII_100 (BIT(13)) 37 #define DW_USXGMII_10 (0) 38 39 /* SR_AN */ 40 #define DW_SR_AN_ADV1 0x10 41 #define DW_SR_AN_ADV2 0x11 42 #define DW_SR_AN_ADV3 0x12 43 #define DW_SR_AN_LP_ABL1 0x13 44 #define DW_SR_AN_LP_ABL2 0x14 45 #define DW_SR_AN_LP_ABL3 0x15 46 47 /* Clause 73 Defines */ 48 /* AN_LP_ABL1 */ 49 #define DW_C73_PAUSE BIT(10) 50 #define DW_C73_ASYM_PAUSE BIT(11) 51 #define DW_C73_AN_ADV_SF 0x1 52 /* AN_LP_ABL2 */ 53 #define DW_C73_1000KX BIT(5) 54 #define DW_C73_10000KX4 BIT(6) 55 #define DW_C73_10000KR BIT(7) 56 /* AN_LP_ABL3 */ 57 #define DW_C73_2500KX BIT(0) 58 #define DW_C73_5000KR BIT(1) 59 60 static const int xpcs_usxgmii_features[] = { 61 ETHTOOL_LINK_MODE_Pause_BIT, 62 ETHTOOL_LINK_MODE_Asym_Pause_BIT, 63 ETHTOOL_LINK_MODE_Autoneg_BIT, 64 ETHTOOL_LINK_MODE_1000baseKX_Full_BIT, 65 ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT, 66 ETHTOOL_LINK_MODE_10000baseKR_Full_BIT, 67 ETHTOOL_LINK_MODE_2500baseX_Full_BIT, 68 __ETHTOOL_LINK_MODE_MASK_NBITS, 69 }; 70 71 static const int xpcs_10gkr_features[] = { 72 ETHTOOL_LINK_MODE_Pause_BIT, 73 ETHTOOL_LINK_MODE_Asym_Pause_BIT, 74 ETHTOOL_LINK_MODE_10000baseKR_Full_BIT, 75 __ETHTOOL_LINK_MODE_MASK_NBITS, 76 }; 77 78 static const int xpcs_xlgmii_features[] = { 79 ETHTOOL_LINK_MODE_Pause_BIT, 80 ETHTOOL_LINK_MODE_Asym_Pause_BIT, 81 ETHTOOL_LINK_MODE_25000baseCR_Full_BIT, 82 ETHTOOL_LINK_MODE_25000baseKR_Full_BIT, 83 ETHTOOL_LINK_MODE_25000baseSR_Full_BIT, 84 ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT, 85 ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT, 86 ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT, 87 ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT, 88 ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT, 89 ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT, 90 ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT, 91 ETHTOOL_LINK_MODE_50000baseKR_Full_BIT, 92 ETHTOOL_LINK_MODE_50000baseSR_Full_BIT, 93 ETHTOOL_LINK_MODE_50000baseCR_Full_BIT, 94 ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT, 95 ETHTOOL_LINK_MODE_50000baseDR_Full_BIT, 96 ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT, 97 ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT, 98 ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT, 99 ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT, 100 ETHTOOL_LINK_MODE_100000baseKR2_Full_BIT, 101 ETHTOOL_LINK_MODE_100000baseSR2_Full_BIT, 102 ETHTOOL_LINK_MODE_100000baseCR2_Full_BIT, 103 ETHTOOL_LINK_MODE_100000baseLR2_ER2_FR2_Full_BIT, 104 ETHTOOL_LINK_MODE_100000baseDR2_Full_BIT, 105 __ETHTOOL_LINK_MODE_MASK_NBITS, 106 }; 107 108 static const phy_interface_t xpcs_usxgmii_interfaces[] = { 109 PHY_INTERFACE_MODE_USXGMII, 110 PHY_INTERFACE_MODE_MAX, 111 }; 112 113 static const phy_interface_t xpcs_10gkr_interfaces[] = { 114 PHY_INTERFACE_MODE_10GKR, 115 PHY_INTERFACE_MODE_MAX, 116 }; 117 118 static const phy_interface_t xpcs_xlgmii_interfaces[] = { 119 PHY_INTERFACE_MODE_XLGMII, 120 PHY_INTERFACE_MODE_MAX, 121 }; 122 123 static struct xpcs_id { 124 u32 id; 125 u32 mask; 126 const int *supported; 127 const phy_interface_t *interface; 128 } xpcs_id_list[] = { 129 { 130 .id = SYNOPSYS_XPCS_USXGMII_ID, 131 .mask = SYNOPSYS_XPCS_MASK, 132 .supported = xpcs_usxgmii_features, 133 .interface = xpcs_usxgmii_interfaces, 134 }, { 135 .id = SYNOPSYS_XPCS_10GKR_ID, 136 .mask = SYNOPSYS_XPCS_MASK, 137 .supported = xpcs_10gkr_features, 138 .interface = xpcs_10gkr_interfaces, 139 }, { 140 .id = SYNOPSYS_XPCS_XLGMII_ID, 141 .mask = SYNOPSYS_XPCS_MASK, 142 .supported = xpcs_xlgmii_features, 143 .interface = xpcs_xlgmii_interfaces, 144 }, 145 }; 146 147 static int xpcs_read(struct mdio_xpcs_args *xpcs, int dev, u32 reg) 148 { 149 u32 reg_addr = MII_ADDR_C45 | dev << 16 | reg; 150 151 return mdiobus_read(xpcs->bus, xpcs->addr, reg_addr); 152 } 153 154 static int xpcs_write(struct mdio_xpcs_args *xpcs, int dev, u32 reg, u16 val) 155 { 156 u32 reg_addr = MII_ADDR_C45 | dev << 16 | reg; 157 158 return mdiobus_write(xpcs->bus, xpcs->addr, reg_addr, val); 159 } 160 161 static int xpcs_read_vendor(struct mdio_xpcs_args *xpcs, int dev, u32 reg) 162 { 163 return xpcs_read(xpcs, dev, DW_VENDOR | reg); 164 } 165 166 static int xpcs_write_vendor(struct mdio_xpcs_args *xpcs, int dev, int reg, 167 u16 val) 168 { 169 return xpcs_write(xpcs, dev, DW_VENDOR | reg, val); 170 } 171 172 static int xpcs_read_vpcs(struct mdio_xpcs_args *xpcs, int reg) 173 { 174 return xpcs_read_vendor(xpcs, MDIO_MMD_PCS, reg); 175 } 176 177 static int xpcs_write_vpcs(struct mdio_xpcs_args *xpcs, int reg, u16 val) 178 { 179 return xpcs_write_vendor(xpcs, MDIO_MMD_PCS, reg, val); 180 } 181 182 static int xpcs_poll_reset(struct mdio_xpcs_args *xpcs, int dev) 183 { 184 /* Poll until the reset bit clears (50ms per retry == 0.6 sec) */ 185 unsigned int retries = 12; 186 int ret; 187 188 do { 189 msleep(50); 190 ret = xpcs_read(xpcs, dev, MDIO_CTRL1); 191 if (ret < 0) 192 return ret; 193 } while (ret & MDIO_CTRL1_RESET && --retries); 194 195 return (ret & MDIO_CTRL1_RESET) ? -ETIMEDOUT : 0; 196 } 197 198 static int xpcs_soft_reset(struct mdio_xpcs_args *xpcs, int dev) 199 { 200 int ret; 201 202 ret = xpcs_write(xpcs, dev, MDIO_CTRL1, MDIO_CTRL1_RESET); 203 if (ret < 0) 204 return ret; 205 206 return xpcs_poll_reset(xpcs, dev); 207 } 208 209 #define xpcs_warn(__xpcs, __state, __args...) \ 210 ({ \ 211 if ((__state)->link) \ 212 dev_warn(&(__xpcs)->bus->dev, ##__args); \ 213 }) 214 215 static int xpcs_read_fault(struct mdio_xpcs_args *xpcs, 216 struct phylink_link_state *state) 217 { 218 int ret; 219 220 ret = xpcs_read(xpcs, MDIO_MMD_PCS, MDIO_STAT1); 221 if (ret < 0) 222 return ret; 223 224 if (ret & MDIO_STAT1_FAULT) { 225 xpcs_warn(xpcs, state, "Link fault condition detected!\n"); 226 return -EFAULT; 227 } 228 229 ret = xpcs_read(xpcs, MDIO_MMD_PCS, MDIO_STAT2); 230 if (ret < 0) 231 return ret; 232 233 if (ret & MDIO_STAT2_RXFAULT) 234 xpcs_warn(xpcs, state, "Receiver fault detected!\n"); 235 if (ret & MDIO_STAT2_TXFAULT) 236 xpcs_warn(xpcs, state, "Transmitter fault detected!\n"); 237 238 ret = xpcs_read_vendor(xpcs, MDIO_MMD_PCS, DW_VR_XS_PCS_DIG_STS); 239 if (ret < 0) 240 return ret; 241 242 if (ret & DW_RXFIFO_ERR) { 243 xpcs_warn(xpcs, state, "FIFO fault condition detected!\n"); 244 return -EFAULT; 245 } 246 247 ret = xpcs_read(xpcs, MDIO_MMD_PCS, MDIO_PCS_10GBRT_STAT1); 248 if (ret < 0) 249 return ret; 250 251 if (!(ret & MDIO_PCS_10GBRT_STAT1_BLKLK)) 252 xpcs_warn(xpcs, state, "Link is not locked!\n"); 253 254 ret = xpcs_read(xpcs, MDIO_MMD_PCS, MDIO_PCS_10GBRT_STAT2); 255 if (ret < 0) 256 return ret; 257 258 if (ret & MDIO_PCS_10GBRT_STAT2_ERR) { 259 xpcs_warn(xpcs, state, "Link has errors!\n"); 260 return -EFAULT; 261 } 262 263 return 0; 264 } 265 266 static int xpcs_read_link(struct mdio_xpcs_args *xpcs, bool an) 267 { 268 bool link = true; 269 int ret; 270 271 ret = xpcs_read(xpcs, MDIO_MMD_PCS, MDIO_STAT1); 272 if (ret < 0) 273 return ret; 274 275 if (!(ret & MDIO_STAT1_LSTATUS)) 276 link = false; 277 278 if (an) { 279 ret = xpcs_read(xpcs, MDIO_MMD_AN, MDIO_STAT1); 280 if (ret < 0) 281 return ret; 282 283 if (!(ret & MDIO_STAT1_LSTATUS)) 284 link = false; 285 } 286 287 return link; 288 } 289 290 static int xpcs_get_max_usxgmii_speed(const unsigned long *supported) 291 { 292 int max = SPEED_UNKNOWN; 293 294 if (phylink_test(supported, 1000baseKX_Full)) 295 max = SPEED_1000; 296 if (phylink_test(supported, 2500baseX_Full)) 297 max = SPEED_2500; 298 if (phylink_test(supported, 10000baseKX4_Full)) 299 max = SPEED_10000; 300 if (phylink_test(supported, 10000baseKR_Full)) 301 max = SPEED_10000; 302 303 return max; 304 } 305 306 static int xpcs_config_usxgmii(struct mdio_xpcs_args *xpcs, int speed) 307 { 308 int ret, speed_sel; 309 310 switch (speed) { 311 case SPEED_10: 312 speed_sel = DW_USXGMII_10; 313 break; 314 case SPEED_100: 315 speed_sel = DW_USXGMII_100; 316 break; 317 case SPEED_1000: 318 speed_sel = DW_USXGMII_1000; 319 break; 320 case SPEED_2500: 321 speed_sel = DW_USXGMII_2500; 322 break; 323 case SPEED_5000: 324 speed_sel = DW_USXGMII_5000; 325 break; 326 case SPEED_10000: 327 speed_sel = DW_USXGMII_10000; 328 break; 329 default: 330 /* Nothing to do here */ 331 return -EINVAL; 332 } 333 334 ret = xpcs_read_vpcs(xpcs, MDIO_CTRL1); 335 if (ret < 0) 336 return ret; 337 338 ret = xpcs_write_vpcs(xpcs, MDIO_CTRL1, ret | DW_USXGMII_EN); 339 if (ret < 0) 340 return ret; 341 342 ret = xpcs_read(xpcs, MDIO_MMD_VEND2, MDIO_CTRL1); 343 if (ret < 0) 344 return ret; 345 346 ret &= ~DW_USXGMII_SS_MASK; 347 ret |= speed_sel | DW_USXGMII_FULL; 348 349 ret = xpcs_write(xpcs, MDIO_MMD_VEND2, MDIO_CTRL1, ret); 350 if (ret < 0) 351 return ret; 352 353 ret = xpcs_read_vpcs(xpcs, MDIO_CTRL1); 354 if (ret < 0) 355 return ret; 356 357 return xpcs_write_vpcs(xpcs, MDIO_CTRL1, ret | DW_USXGMII_RST); 358 } 359 360 static int xpcs_config_aneg_c73(struct mdio_xpcs_args *xpcs) 361 { 362 int ret, adv; 363 364 /* By default, in USXGMII mode XPCS operates at 10G baud and 365 * replicates data to achieve lower speeds. Hereby, in this 366 * default configuration we need to advertise all supported 367 * modes and not only the ones we want to use. 368 */ 369 370 /* SR_AN_ADV3 */ 371 adv = 0; 372 if (phylink_test(xpcs->supported, 2500baseX_Full)) 373 adv |= DW_C73_2500KX; 374 375 /* TODO: 5000baseKR */ 376 377 ret = xpcs_write(xpcs, MDIO_MMD_AN, DW_SR_AN_ADV3, adv); 378 if (ret < 0) 379 return ret; 380 381 /* SR_AN_ADV2 */ 382 adv = 0; 383 if (phylink_test(xpcs->supported, 1000baseKX_Full)) 384 adv |= DW_C73_1000KX; 385 if (phylink_test(xpcs->supported, 10000baseKX4_Full)) 386 adv |= DW_C73_10000KX4; 387 if (phylink_test(xpcs->supported, 10000baseKR_Full)) 388 adv |= DW_C73_10000KR; 389 390 ret = xpcs_write(xpcs, MDIO_MMD_AN, DW_SR_AN_ADV2, adv); 391 if (ret < 0) 392 return ret; 393 394 /* SR_AN_ADV1 */ 395 adv = DW_C73_AN_ADV_SF; 396 if (phylink_test(xpcs->supported, Pause)) 397 adv |= DW_C73_PAUSE; 398 if (phylink_test(xpcs->supported, Asym_Pause)) 399 adv |= DW_C73_ASYM_PAUSE; 400 401 return xpcs_write(xpcs, MDIO_MMD_AN, DW_SR_AN_ADV1, adv); 402 } 403 404 static int xpcs_config_aneg(struct mdio_xpcs_args *xpcs) 405 { 406 int ret; 407 408 ret = xpcs_config_aneg_c73(xpcs); 409 if (ret < 0) 410 return ret; 411 412 ret = xpcs_read(xpcs, MDIO_MMD_AN, MDIO_CTRL1); 413 if (ret < 0) 414 return ret; 415 416 ret |= MDIO_AN_CTRL1_ENABLE | MDIO_AN_CTRL1_RESTART; 417 418 return xpcs_write(xpcs, MDIO_MMD_AN, MDIO_CTRL1, ret); 419 } 420 421 static int xpcs_aneg_done(struct mdio_xpcs_args *xpcs, 422 struct phylink_link_state *state) 423 { 424 int ret; 425 426 ret = xpcs_read(xpcs, MDIO_MMD_AN, MDIO_STAT1); 427 if (ret < 0) 428 return ret; 429 430 if (ret & MDIO_AN_STAT1_COMPLETE) { 431 ret = xpcs_read(xpcs, MDIO_MMD_AN, DW_SR_AN_LP_ABL1); 432 if (ret < 0) 433 return ret; 434 435 /* Check if Aneg outcome is valid */ 436 if (!(ret & DW_C73_AN_ADV_SF)) { 437 xpcs_config_aneg(xpcs); 438 return 0; 439 } 440 441 return 1; 442 } 443 444 return 0; 445 } 446 447 static int xpcs_read_lpa(struct mdio_xpcs_args *xpcs, 448 struct phylink_link_state *state) 449 { 450 int ret; 451 452 ret = xpcs_read(xpcs, MDIO_MMD_AN, MDIO_STAT1); 453 if (ret < 0) 454 return ret; 455 456 if (!(ret & MDIO_AN_STAT1_LPABLE)) { 457 phylink_clear(state->lp_advertising, Autoneg); 458 return 0; 459 } 460 461 phylink_set(state->lp_advertising, Autoneg); 462 463 /* Clause 73 outcome */ 464 ret = xpcs_read(xpcs, MDIO_MMD_AN, DW_SR_AN_LP_ABL3); 465 if (ret < 0) 466 return ret; 467 468 if (ret & DW_C73_2500KX) 469 phylink_set(state->lp_advertising, 2500baseX_Full); 470 471 ret = xpcs_read(xpcs, MDIO_MMD_AN, DW_SR_AN_LP_ABL2); 472 if (ret < 0) 473 return ret; 474 475 if (ret & DW_C73_1000KX) 476 phylink_set(state->lp_advertising, 1000baseKX_Full); 477 if (ret & DW_C73_10000KX4) 478 phylink_set(state->lp_advertising, 10000baseKX4_Full); 479 if (ret & DW_C73_10000KR) 480 phylink_set(state->lp_advertising, 10000baseKR_Full); 481 482 ret = xpcs_read(xpcs, MDIO_MMD_AN, DW_SR_AN_LP_ABL1); 483 if (ret < 0) 484 return ret; 485 486 if (ret & DW_C73_PAUSE) 487 phylink_set(state->lp_advertising, Pause); 488 if (ret & DW_C73_ASYM_PAUSE) 489 phylink_set(state->lp_advertising, Asym_Pause); 490 491 linkmode_and(state->lp_advertising, state->lp_advertising, 492 state->advertising); 493 return 0; 494 } 495 496 static void xpcs_resolve_lpa(struct mdio_xpcs_args *xpcs, 497 struct phylink_link_state *state) 498 { 499 int max_speed = xpcs_get_max_usxgmii_speed(state->lp_advertising); 500 501 state->pause = MLO_PAUSE_TX | MLO_PAUSE_RX; 502 state->speed = max_speed; 503 state->duplex = DUPLEX_FULL; 504 } 505 506 static int xpcs_get_max_xlgmii_speed(struct mdio_xpcs_args *xpcs, 507 struct phylink_link_state *state) 508 { 509 unsigned long *adv = state->advertising; 510 int speed = SPEED_UNKNOWN; 511 int bit; 512 513 for_each_set_bit(bit, adv, __ETHTOOL_LINK_MODE_MASK_NBITS) { 514 int new_speed = SPEED_UNKNOWN; 515 516 switch (bit) { 517 case ETHTOOL_LINK_MODE_25000baseCR_Full_BIT: 518 case ETHTOOL_LINK_MODE_25000baseKR_Full_BIT: 519 case ETHTOOL_LINK_MODE_25000baseSR_Full_BIT: 520 new_speed = SPEED_25000; 521 break; 522 case ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT: 523 case ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT: 524 case ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT: 525 case ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT: 526 new_speed = SPEED_40000; 527 break; 528 case ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT: 529 case ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT: 530 case ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT: 531 case ETHTOOL_LINK_MODE_50000baseKR_Full_BIT: 532 case ETHTOOL_LINK_MODE_50000baseSR_Full_BIT: 533 case ETHTOOL_LINK_MODE_50000baseCR_Full_BIT: 534 case ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT: 535 case ETHTOOL_LINK_MODE_50000baseDR_Full_BIT: 536 new_speed = SPEED_50000; 537 break; 538 case ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT: 539 case ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT: 540 case ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT: 541 case ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT: 542 case ETHTOOL_LINK_MODE_100000baseKR2_Full_BIT: 543 case ETHTOOL_LINK_MODE_100000baseSR2_Full_BIT: 544 case ETHTOOL_LINK_MODE_100000baseCR2_Full_BIT: 545 case ETHTOOL_LINK_MODE_100000baseLR2_ER2_FR2_Full_BIT: 546 case ETHTOOL_LINK_MODE_100000baseDR2_Full_BIT: 547 new_speed = SPEED_100000; 548 break; 549 default: 550 continue; 551 } 552 553 if (new_speed > speed) 554 speed = new_speed; 555 } 556 557 return speed; 558 } 559 560 static void xpcs_resolve_pma(struct mdio_xpcs_args *xpcs, 561 struct phylink_link_state *state) 562 { 563 state->pause = MLO_PAUSE_TX | MLO_PAUSE_RX; 564 state->duplex = DUPLEX_FULL; 565 566 switch (state->interface) { 567 case PHY_INTERFACE_MODE_10GKR: 568 state->speed = SPEED_10000; 569 break; 570 case PHY_INTERFACE_MODE_XLGMII: 571 state->speed = xpcs_get_max_xlgmii_speed(xpcs, state); 572 break; 573 default: 574 state->speed = SPEED_UNKNOWN; 575 break; 576 } 577 } 578 579 static int xpcs_validate(struct mdio_xpcs_args *xpcs, 580 unsigned long *supported, 581 struct phylink_link_state *state) 582 { 583 linkmode_and(supported, supported, xpcs->supported); 584 linkmode_and(state->advertising, state->advertising, xpcs->supported); 585 return 0; 586 } 587 588 static int xpcs_config(struct mdio_xpcs_args *xpcs, 589 const struct phylink_link_state *state) 590 { 591 int ret; 592 593 if (state->an_enabled) { 594 ret = xpcs_config_aneg(xpcs); 595 if (ret) 596 return ret; 597 } 598 599 return 0; 600 } 601 602 static int xpcs_get_state(struct mdio_xpcs_args *xpcs, 603 struct phylink_link_state *state) 604 { 605 int ret; 606 607 /* Link needs to be read first ... */ 608 state->link = xpcs_read_link(xpcs, state->an_enabled) > 0 ? 1 : 0; 609 610 /* ... and then we check the faults. */ 611 ret = xpcs_read_fault(xpcs, state); 612 if (ret) { 613 ret = xpcs_soft_reset(xpcs, MDIO_MMD_PCS); 614 if (ret) 615 return ret; 616 617 state->link = 0; 618 619 return xpcs_config(xpcs, state); 620 } 621 622 if (state->an_enabled && xpcs_aneg_done(xpcs, state)) { 623 state->an_complete = true; 624 xpcs_read_lpa(xpcs, state); 625 xpcs_resolve_lpa(xpcs, state); 626 } else if (state->an_enabled) { 627 state->link = 0; 628 } else if (state->link) { 629 xpcs_resolve_pma(xpcs, state); 630 } 631 632 return 0; 633 } 634 635 static int xpcs_link_up(struct mdio_xpcs_args *xpcs, int speed, 636 phy_interface_t interface) 637 { 638 if (interface == PHY_INTERFACE_MODE_USXGMII) 639 return xpcs_config_usxgmii(xpcs, speed); 640 641 return 0; 642 } 643 644 static u32 xpcs_get_id(struct mdio_xpcs_args *xpcs) 645 { 646 int ret; 647 u32 id; 648 649 ret = xpcs_read(xpcs, MDIO_MMD_PCS, MII_PHYSID1); 650 if (ret < 0) 651 return 0xffffffff; 652 653 id = ret << 16; 654 655 ret = xpcs_read(xpcs, MDIO_MMD_PCS, MII_PHYSID2); 656 if (ret < 0) 657 return 0xffffffff; 658 659 return id | ret; 660 } 661 662 static bool xpcs_check_features(struct mdio_xpcs_args *xpcs, 663 struct xpcs_id *match, 664 phy_interface_t interface) 665 { 666 int i; 667 668 for (i = 0; match->interface[i] != PHY_INTERFACE_MODE_MAX; i++) { 669 if (match->interface[i] == interface) 670 break; 671 } 672 673 if (match->interface[i] == PHY_INTERFACE_MODE_MAX) 674 return false; 675 676 for (i = 0; match->supported[i] != __ETHTOOL_LINK_MODE_MASK_NBITS; i++) 677 set_bit(match->supported[i], xpcs->supported); 678 679 return true; 680 } 681 682 static int xpcs_probe(struct mdio_xpcs_args *xpcs, phy_interface_t interface) 683 { 684 u32 xpcs_id = xpcs_get_id(xpcs); 685 struct xpcs_id *match = NULL; 686 int i; 687 688 for (i = 0; i < ARRAY_SIZE(xpcs_id_list); i++) { 689 struct xpcs_id *entry = &xpcs_id_list[i]; 690 691 if ((xpcs_id & entry->mask) == entry->id) { 692 match = entry; 693 694 if (xpcs_check_features(xpcs, match, interface)) 695 return xpcs_soft_reset(xpcs, MDIO_MMD_PCS); 696 } 697 } 698 699 return -ENODEV; 700 } 701 702 static struct mdio_xpcs_ops xpcs_ops = { 703 .validate = xpcs_validate, 704 .config = xpcs_config, 705 .get_state = xpcs_get_state, 706 .link_up = xpcs_link_up, 707 .probe = xpcs_probe, 708 }; 709 710 struct mdio_xpcs_ops *mdio_xpcs_get_ops(void) 711 { 712 return &xpcs_ops; 713 } 714 EXPORT_SYMBOL_GPL(mdio_xpcs_get_ops); 715 716 MODULE_LICENSE("GPL v2"); 717