1 /* 2 * Copyright 2008-2013 Solarflare Communications Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND 14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * SUCH DAMAGE. 24 */ 25 26 #include "efsys.h" 27 #include "efx.h" 28 #include "efx_types.h" 29 #include "efx_regs.h" 30 #include "efx_impl.h" 31 #include "xphy.h" 32 #include "qt2025c.h" 33 #include "qt2025c_impl.h" 34 #include "falcon_impl.h" 35 36 #if EFSYS_OPT_PHY_QT2025C 37 38 static __checkReturn int 39 qt2025c_led_cfg( 40 __in efx_nic_t *enp) 41 { 42 efx_port_t *epp = &(enp->en_port); 43 efx_word_t led1; 44 efx_word_t led2; 45 int rc; 46 47 #if EFSYS_OPT_PHY_LED_CONTROL 48 49 switch (epp->ep_phy_led_mode) { 50 case EFX_PHY_LED_DEFAULT: 51 EFX_POPULATE_WORD_2(led1, PMA_PMD_LED_CFG, LED_CFG_LA_DECODE, 52 PMA_PMD_LED_PATH, LED_PATH_RX_DECODE); 53 EFX_POPULATE_WORD_2(led2, PMA_PMD_LED_CFG, LED_CFG_LS_DECODE, 54 PMA_PMD_LED_PATH, LED_PATH_RX_DECODE); 55 break; 56 57 case EFX_PHY_LED_OFF: 58 EFX_POPULATE_WORD_1(led1, PMA_PMD_LED_CFG, LED_CFG_OFF_DECODE); 59 EFX_POPULATE_WORD_1(led2, PMA_PMD_LED_CFG, LED_CFG_OFF_DECODE); 60 break; 61 62 case EFX_PHY_LED_ON: 63 EFX_POPULATE_WORD_1(led1, PMA_PMD_LED_CFG, LED_CFG_ON_DECODE); 64 EFX_POPULATE_WORD_1(led2, PMA_PMD_LED_CFG, LED_CFG_ON_DECODE); 65 break; 66 67 default: 68 EFSYS_ASSERT(B_FALSE); 69 break; 70 } 71 72 #else /* EFSYS_OPT_PHY_LED_CONTROL */ 73 74 EFX_POPULATE_WORD_2(led1, PMA_PMD_LED_CFG, LED_CFG_LA_DECODE, 75 PMA_PMD_LED_PATH, LED_PATH_RX_DECODE); 76 EFX_POPULATE_WORD_2(led2, PMA_PMD_LED_CFG, LED_CFG_LS_DECODE, 77 PMA_PMD_LED_PATH, LED_PATH_RX_DECODE); 78 79 #endif /* EFSYS_OPT_PHY_LED_CONTROL */ 80 81 if ((rc = falcon_mdio_write(enp, epp->ep_port, PMA_PMD_MMD, 82 PMA_PMD_LED1_REG, &led1)) != 0) 83 goto fail1; 84 85 if ((rc = falcon_mdio_write(enp, epp->ep_port, PMA_PMD_MMD, 86 PMA_PMD_LED2_REG, &led2)) != 0) 87 goto fail2; 88 89 return (0); 90 91 fail2: 92 EFSYS_PROBE(fail2); 93 fail1: 94 EFSYS_PROBE1(fail1, int, rc); 95 96 return (rc); 97 } 98 99 #if EFSYS_OPT_LOOPBACK 100 static __checkReturn int 101 qt2025c_loopback_cfg( 102 __in efx_nic_t *enp) 103 { 104 efx_port_t *epp = &(enp->en_port); 105 efx_word_t word; 106 int rc; 107 108 /* Set static mode appropriately */ 109 if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD, 110 PMA_FTX_CTRL2_REG, &word)) != 0) 111 goto fail1; 112 113 EFX_SET_WORD_FIELD(word, FTX_STATIC, 114 (epp->ep_loopback_type == EFX_LOOPBACK_PCS || 115 epp->ep_loopback_type == EFX_LOOPBACK_PMA_PMD) ? 1 : 0); 116 117 /* Set static mode appropriately */ 118 if ((rc = falcon_mdio_write(enp, epp->ep_port, PMA_PMD_MMD, 119 PMA_FTX_CTRL2_REG, &word)) != 0) 120 goto fail2; 121 122 switch (epp->ep_loopback_type) { 123 case EFX_LOOPBACK_PHY_XS: { 124 efx_word_t xsword; 125 126 if ((rc = falcon_mdio_read(enp, epp->ep_port, PHY_XS_MMD, 127 XGXS_VENDOR_SPECIFIC_1_REG, &xsword)) != 0) 128 goto fail3; 129 130 EFX_SET_WORD_FIELD(xsword, XGXS_SYSLPBK, 1); 131 132 if ((rc = falcon_mdio_write(enp, epp->ep_port, PHY_XS_MMD, 133 XGXS_VENDOR_SPECIFIC_1_REG, &xsword)) != 0) 134 goto fail4; 135 136 break; 137 } 138 case EFX_LOOPBACK_PCS: 139 if ((rc = xphy_mmd_loopback_set(enp, epp->ep_port, PCS_MMD, 140 B_TRUE)) != 0) 141 goto fail3; 142 143 break; 144 145 case EFX_LOOPBACK_PMA_PMD: 146 if ((rc = xphy_mmd_loopback_set(enp, epp->ep_port, PMA_PMD_MMD, 147 B_TRUE)) != 0) 148 goto fail3; 149 150 break; 151 152 default: 153 break; 154 } 155 156 return (0); 157 158 fail4: 159 EFSYS_PROBE(fail4); 160 fail3: 161 EFSYS_PROBE(fail3); 162 fail2: 163 EFSYS_PROBE(fail2); 164 fail1: 165 EFSYS_PROBE1(fail1, int, rc); 166 167 return (rc); 168 } 169 #endif /* EFSYS_OPT_LOOPBACK */ 170 171 static __checkReturn int 172 qt2025c_version_get( 173 __in efx_nic_t *enp, 174 __out_ecount(4) uint8_t version[]) 175 { 176 efx_port_t *epp = &(enp->en_port); 177 efx_word_t word; 178 int rc; 179 180 if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD, 181 FW_VERSION1_REG, &word)) != 0) 182 goto fail1; 183 184 version[0] = (uint8_t)EFX_WORD_FIELD(word, EFX_BYTE_0) >> 4; 185 version[1] = (uint8_t)EFX_WORD_FIELD(word, EFX_BYTE_0) & 0x0f; 186 187 if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD, 188 FW_VERSION2_REG, &word)) != 0) 189 goto fail2; 190 191 version[2] = (uint8_t)EFX_WORD_FIELD(word, EFX_BYTE_0); 192 193 if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD, 194 FW_VERSION3_REG, &word)) != 0) 195 goto fail3; 196 197 version[3] = (uint8_t)EFX_WORD_FIELD(word, EFX_BYTE_0); 198 199 return (0); 200 201 fail3: 202 EFSYS_PROBE(fail3); 203 fail2: 204 EFSYS_PROBE(fail2); 205 fail1: 206 EFSYS_PROBE1(fail1, int, rc); 207 208 return (rc); 209 } 210 211 /* 212 * Convinience function so that the large number of MDIO writes 213 * in qt2025c_select_phy_mode are condensed, and easier to compare 214 * directly with the data sheet. 215 */ 216 static __checkReturn int 217 qt2025c_mdio_write( 218 __in efx_nic_t *enp, 219 __in uint8_t mmd, 220 __in uint16_t addr, 221 __in uint16_t value) 222 { 223 efx_port_t *epp = &(enp->en_port); 224 efx_word_t word; 225 int rc; 226 227 EFX_POPULATE_WORD_1(word, EFX_WORD_0, value); 228 rc = falcon_mdio_write(enp, epp->ep_port, mmd, addr, &word); 229 230 return (rc); 231 } 232 233 static __checkReturn int 234 qt2025c_restart_firmware( 235 __in efx_nic_t *enp) 236 { 237 int rc; 238 239 /* Restart microcontroller execution of firmware from RAM */ 240 if ((rc = qt2025c_mdio_write(enp, 3, 0xe854, 0x00c0)) != 0) 241 goto fail1; 242 243 if ((rc = qt2025c_mdio_write(enp, 3, 0xe854, 0x0040)) != 0) 244 goto fail2; 245 246 EFSYS_SLEEP(50000); /* 50ms */ 247 248 return (0); 249 fail2: 250 EFSYS_PROBE(fail2); 251 fail1: 252 EFSYS_PROBE1(fail1, int, rc); 253 254 return (rc); 255 } 256 257 static __checkReturn int 258 qt2025c_wait_heartbeat( 259 __in efx_nic_t *enp) 260 { 261 efx_port_t *epp = &(enp->en_port); 262 efx_word_t word; 263 unsigned int count; 264 uint8_t heartb; 265 int rc; 266 267 /* Read the initial heartbeat */ 268 if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD, 269 FW_HEARTBEAT_REG, &word)) != 0) 270 goto fail1; 271 272 heartb = EFX_WORD_FIELD(word, FW_HEARTB); 273 274 /* Wait for the heartbeat to start updating */ 275 count = 0; 276 do { 277 EFSYS_PROBE1(wait, unsigned int, count); 278 279 EFSYS_SLEEP(100000); /* 100ms */ 280 281 if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD, 282 FW_HEARTBEAT_REG, &word)) != 0) 283 goto fail2; 284 285 if (EFX_WORD_FIELD(word, FW_HEARTB) != heartb) 286 return (0); 287 288 } while (++count < 50); /* For up to 5s */ 289 290 rc = ENOTACTIVE; 291 EFSYS_PROBE(fail3); 292 fail2: 293 EFSYS_PROBE(fail2); 294 fail1: 295 EFSYS_PROBE1(fail1, int, rc); 296 297 return (rc); 298 } 299 300 static __checkReturn int 301 qt2025c_wait_firmware( 302 __in efx_nic_t *enp) 303 { 304 efx_port_t *epp = &(enp->en_port); 305 efx_word_t word; 306 unsigned int count; 307 uint16_t status; 308 int rc; 309 310 count = 0; 311 do { 312 EFSYS_PROBE1(wait, unsigned int, count); 313 314 EFSYS_SLEEP(100000); /* 100ms */ 315 316 if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD, 317 UC8051_STATUS_REG, &word)) != 0) 318 goto fail1; 319 320 status = EFX_WORD_FIELD(word, UC_STATUS); 321 if (status >= UC_STATUS_FW_SAVE_DECODE) 322 return (0); 323 324 } while (++count < 25); /* For up to 2.5s */ 325 326 rc = ENOTACTIVE; 327 EFSYS_PROBE(fail2); 328 fail1: 329 EFSYS_PROBE1(fail1, int, rc); 330 331 return (rc); 332 } 333 334 static __checkReturn int 335 qt2025c_wait_reset( 336 __in efx_nic_t *enp) 337 { 338 boolean_t retry = B_TRUE; 339 int rc; 340 341 /* 342 * Bug17689: occasionally heartbeat starts but firmware status 343 * code never progresses beyond 0x00. Try again, once, after 344 * restarting execution of the firmware image. 345 */ 346 again: 347 if ((rc = qt2025c_wait_heartbeat(enp)) != 0) 348 goto fail1; 349 350 rc = qt2025c_wait_firmware(enp); 351 if (rc == ENOTACTIVE && retry) { 352 if ((rc = qt2025c_restart_firmware(enp)) != 0) 353 goto fail2; 354 355 retry = B_FALSE; 356 goto again; 357 } 358 if (rc != 0) 359 goto fail3; 360 361 return (0); 362 363 fail3: 364 EFSYS_PROBE(fail3); 365 fail2: 366 EFSYS_PROBE(fail2); 367 fail1: 368 EFSYS_PROBE1(fail1, int, rc); 369 370 return (rc); 371 } 372 373 __checkReturn int 374 qt2025c_reset( 375 __in efx_nic_t *enp) 376 { 377 efx_port_t *epp = &(enp->en_port); 378 uint8_t version[4]; 379 int rc; 380 381 /* Pull the external reset line */ 382 falcon_nic_phy_reset(enp); 383 384 /* Wait for the reset to complete */ 385 if ((rc = qt2025c_wait_reset(enp)) != 0) 386 goto fail1; 387 388 /* Read the firmware version again post-reset */ 389 if ((rc = qt2025c_version_get(enp, version)) != 0) 390 goto fail2; 391 epp->ep_fwver = \ 392 ((uint32_t)version[0] << 24 | (uint32_t)version[1] << 16 | \ 393 (uint32_t)version[2] << 8 | (uint32_t)version[3]); 394 395 return (0); 396 397 fail2: 398 EFSYS_PROBE(fail2); 399 fail1: 400 EFSYS_PROBE1(fail1, int, rc); 401 402 return (rc); 403 } 404 405 static __checkReturn int 406 qt2025c_select_phy_mode( 407 __in efx_nic_t *enp) 408 { 409 efx_port_t *epp = &(enp->en_port); 410 efx_word_t word; 411 uint16_t phy_op_mode; 412 int i; 413 int rc; 414 415 /* 416 * Only 2.0.1.0+ PHY firmware supports the more optimal SFP+ 417 * Self-Configure mode. Don't attempt any switching if we encounter 418 * older firmware. 419 * 420 * NOTE: This code uses explicit integers for MMD's and register 421 * addresses so that it is trivially comparable to the firmware 422 * release notes. 423 */ 424 if (epp->ep_fwver < 0x02000100) 425 return (0); 426 427 /* 428 * In general we will get optimal behaviour in "SFP+ Self-Configure" 429 * mode; however, that powers down most of the PHY when no module is 430 * present, so we must use a different mode (any fixed mode will do) 431 * to be sure that loopbacks will work. 432 */ 433 phy_op_mode = 0x0038; 434 #if EFSYS_OPT_LOOPBACK 435 if (epp->ep_loopback_type != EFX_LOOPBACK_OFF) 436 phy_op_mode = 0x0020; 437 #endif /* EFSYS_OPT_LOOPBACK */ 438 439 /* Only change mode if really necessary */ 440 if ((rc = falcon_mdio_read(enp, epp->ep_port, 1, 0xc319, &word)) != 0) 441 goto fail1; 442 if ((EFX_WORD_FIELD(word, EFX_WORD_0) & 0x0038) == phy_op_mode) 443 return (0); 444 445 /* Do a full reset and wait for it to complete */ 446 if ((rc = qt2025c_mdio_write(enp, 1, 0x0000, 0x8000)) != 0) 447 goto fail2; 448 EFSYS_SLEEP(50000); /* 50ms */ 449 450 if ((rc = qt2025c_wait_reset(enp)) != 0) 451 goto fail3; 452 453 /* 454 * This sequence replicates the register writes configured in the boot 455 * EEPROM (including the differences between board revisions), except 456 * that the operating mode is changed, and the PHY is prevented from 457 * unnecessarily reloading the main firmware image again. 458 */ 459 if ((rc = qt2025c_mdio_write(enp, 1, 0xc300, 0)) != 0) 460 goto fail4; 461 462 /* 463 * (Note: this portion of the boot EEPROM sequence, which bit-bashes 9 464 * STOPs onto the firmware/module I2C bus to reset it, varies across 465 * board revisions, as the bus is connected to different GPIO/LED 466 * outputs on the PHY.) 467 */ 468 if (enp->en_u.falcon.enu_board_rev < 2) { 469 if ((rc = qt2025c_mdio_write(enp, 1, 0xc303, 0x4498)) != 0) 470 goto fail5; 471 for (i = 0; i < 9; i++) { 472 rc = qt2025c_mdio_write(enp, 1, 0xc303, 0x4488); 473 if (rc != 0) 474 goto fail5; 475 rc = qt2025c_mdio_write(enp, 1, 0xc303, 0x4480); 476 if (rc != 0) 477 goto fail5; 478 rc = qt2025c_mdio_write(enp, 1, 0xc303, 0x4490); 479 if (rc != 0) 480 goto fail5; 481 rc = qt2025c_mdio_write(enp, 1, 0xc303, 0x4498); 482 if (rc != 0) 483 goto fail5; 484 } 485 } else { 486 if ((rc = qt2025c_mdio_write(enp, 1, 0xc303, 0x0920)) != 0) 487 goto fail5; 488 if ((rc = qt2025c_mdio_write(enp, 1, 0xd008, 0x0004)) != 0) 489 goto fail5; 490 for (i = 0; i < 9; i++) { 491 rc = qt2025c_mdio_write(enp, 1, 0xc303, 0x0900); 492 if (rc != 0) 493 goto fail5; 494 rc = qt2025c_mdio_write(enp, 1, 0xd008, 0x0005); 495 if (rc != 0) 496 goto fail5; 497 rc = qt2025c_mdio_write(enp, 1, 0xc303, 0x0920); 498 if (rc != 0) 499 goto fail5; 500 rc = qt2025c_mdio_write(enp, 1, 0xd008, 0x0004); 501 if (rc != 0) 502 goto fail5; 503 } 504 if ((rc = qt2025c_mdio_write(enp, 1, 0xc303, 0x4900)) != 0) 505 goto fail5; 506 } 507 508 if ((rc = qt2025c_mdio_write(enp, 1, 0xc303, 0x4900)) != 0) 509 goto fail6; 510 if ((rc = qt2025c_mdio_write(enp, 1, 0xc302, 0x0004)) != 0) 511 goto fail6; 512 if ((rc = qt2025c_mdio_write(enp, 1, 0xc316, 0x0013)) != 0) 513 goto fail6; 514 if ((rc = qt2025c_mdio_write(enp, 1, 0xc318, 0x0054)) != 0) 515 goto fail6; 516 if ((rc = qt2025c_mdio_write(enp, 1, 0xc319, phy_op_mode)) != 0) 517 goto fail6; 518 if ((rc = qt2025c_mdio_write(enp, 1, 0xc31a, 0x0098)) != 0) 519 goto fail6; 520 if ((rc = qt2025c_mdio_write(enp, 3, 0x0026, 0x0e00)) != 0) 521 goto fail6; 522 if ((rc = qt2025c_mdio_write(enp, 3, 0x0027, 0x0013)) != 0) 523 goto fail6; 524 if ((rc = qt2025c_mdio_write(enp, 3, 0x0028, 0xa528)) != 0) 525 goto fail6; 526 if ((rc = qt2025c_mdio_write(enp, 1, 0xd006, 0x000a)) != 0) 527 goto fail6; 528 if ((rc = qt2025c_mdio_write(enp, 1, 0xd007, 0x0009)) != 0) 529 goto fail6; 530 if ((rc = qt2025c_mdio_write(enp, 1, 0xd008, 0x0004)) != 0) 531 goto fail6; 532 /* 533 * This additional write prevents the PHY boot ROM doing another 534 * pointless reload of the firmware image (the microcontroller's 535 * code memory is not affected by the microcontroller reset). 536 */ 537 if ((rc = qt2025c_mdio_write(enp, 1, 0xc317, 0x00ff)) != 0) 538 goto fail7; 539 if ((rc = qt2025c_mdio_write(enp, 1, 0xc300, 0x0002)) != 0) 540 goto fail7; 541 EFSYS_SLEEP(20000); /* 20ms */ 542 543 /* Restart microcontroller execution from RAM */ 544 if ((rc = qt2025c_restart_firmware(enp)) != 0) 545 goto fail8; 546 547 /* Wait for the microcontroller to be ready again */ 548 if ((rc = qt2025c_wait_reset(enp)) != 0) 549 goto fail9; 550 551 return (0); 552 553 fail9: 554 EFSYS_PROBE(fail9); 555 fail8: 556 EFSYS_PROBE(fail8); 557 fail7: 558 EFSYS_PROBE(fail7); 559 fail6: 560 EFSYS_PROBE(fail6); 561 fail5: 562 EFSYS_PROBE(fail5); 563 fail4: 564 EFSYS_PROBE(fail4); 565 fail3: 566 EFSYS_PROBE(fail3); 567 fail2: 568 EFSYS_PROBE(fail2); 569 fail1: 570 EFSYS_PROBE1(fail1, int, rc); 571 572 return (rc); 573 } 574 575 __checkReturn int 576 qt2025c_reconfigure( 577 __in efx_nic_t *enp) 578 { 579 efx_port_t *epp = &(enp->en_port); 580 int rc; 581 582 if ((rc = qt2025c_select_phy_mode(enp)) != 0) 583 goto fail1; 584 585 if ((rc = xphy_pkg_wait(enp, epp->ep_port, QT2025C_MMD_MASK)) != 0) 586 goto fail2; 587 588 if ((rc = qt2025c_led_cfg(enp)) != 0) 589 goto fail3; 590 591 EFSYS_ASSERT3U(epp->ep_adv_cap_mask, ==, QT2025C_ADV_CAP_MASK); 592 593 #if EFSYS_OPT_LOOPBACK 594 if ((rc = qt2025c_loopback_cfg(enp)) != 0) 595 goto fail4; 596 #endif /* EFSYS_OPT_LOOPBACK */ 597 598 return (0); 599 600 #if EFSYS_OPT_LOOPBACK 601 fail4: 602 EFSYS_PROBE(fail4); 603 #endif /* EFSYS_OPT_LOOPBACK */ 604 fail3: 605 EFSYS_PROBE(fail3); 606 fail2: 607 EFSYS_PROBE(fail2); 608 fail1: 609 EFSYS_PROBE1(fail1, int, rc); 610 611 return (rc); 612 } 613 614 __checkReturn int 615 qt2025c_verify( 616 __in efx_nic_t *enp) 617 { 618 efx_port_t *epp = &(enp->en_port); 619 int rc; 620 621 if ((rc = xphy_pkg_verify(enp, epp->ep_port, QT2025C_MMD_MASK)) != 0) 622 goto fail1; 623 624 return (0); 625 626 fail1: 627 EFSYS_PROBE1(fail1, int, rc); 628 629 return (rc); 630 } 631 632 __checkReturn int 633 qt2025c_uplink_check( 634 __in efx_nic_t *enp, 635 __out boolean_t *upp) 636 { 637 efx_port_t *epp = &(enp->en_port); 638 efx_word_t word; 639 int rc; 640 641 if (epp->ep_mac_type != EFX_MAC_FALCON_XMAC) { 642 rc = ENOTSUP; 643 goto fail1; 644 } 645 646 if ((rc = falcon_mdio_read(enp, epp->ep_port, PHY_XS_MMD, 647 PHY_XS_LANE_STATUS_REG, &word)) != 0) 648 goto fail2; 649 650 *upp = ((EFX_WORD_FIELD(word, PHY_XS_ALIGNED) != 0) && 651 (EFX_WORD_FIELD(word, PHY_XS_LANE0_SYNC) != 0) && 652 (EFX_WORD_FIELD(word, PHY_XS_LANE1_SYNC) != 0) && 653 (EFX_WORD_FIELD(word, PHY_XS_LANE2_SYNC) != 0) && 654 (EFX_WORD_FIELD(word, PHY_XS_LANE3_SYNC) != 0)); 655 656 return (0); 657 658 fail2: 659 EFSYS_PROBE(fail2); 660 fail1: 661 EFSYS_PROBE1(fail1, int, rc); 662 663 return (rc); 664 } 665 666 /* Recover from bug17190 by moving into and out of PMA loopback */ 667 static __checkReturn int 668 qt2025c_bug17190_workaround( 669 __in efx_nic_t *enp) 670 { 671 efx_port_t *epp = &(enp->en_port); 672 efx_word_t word; 673 int rc; 674 675 if ((rc = falcon_mdio_read(enp, epp->ep_port, 676 PMA_PMD_MMD, MMD_CONTROL1_REG, &word)) != 0) 677 goto fail1; 678 EFX_SET_WORD_FIELD(word, MMD_PMA_LOOPBACK, 1); 679 if ((rc = falcon_mdio_write(enp, epp->ep_port, 680 PMA_PMD_MMD, MMD_CONTROL1_REG, &word)) != 0) 681 goto fail2; 682 683 EFSYS_SLEEP(100000); /* 100ms */ 684 685 EFX_SET_WORD_FIELD(word, MMD_PMA_LOOPBACK, 0); 686 if ((rc = falcon_mdio_write(enp, epp->ep_port, 687 PMA_PMD_MMD, MMD_CONTROL1_REG, &word)) != 0) 688 goto fail3; 689 690 return (0); 691 692 fail3: 693 EFSYS_PROBE(fail3); 694 fail2: 695 EFSYS_PROBE(fail2); 696 fail1: 697 EFSYS_PROBE1(fail1, int, rc); 698 699 return (rc); 700 } 701 702 __checkReturn int 703 qt2025c_downlink_check( 704 __in efx_nic_t *enp, 705 __out efx_link_mode_t *modep, 706 __out unsigned int *fcntlp, 707 __out uint32_t *lp_cap_maskp) 708 { 709 efx_port_t *epp = &(enp->en_port); 710 uint8_t mmd; 711 uint8_t mmds; 712 boolean_t broken; 713 boolean_t ok; 714 boolean_t up; 715 int rc; 716 717 mmds = (1 << PMA_PMD_MMD) | (1 << PCS_MMD) | (1 << PHY_XS_MMD); 718 #if EFSYS_OPT_LOOPBACK 719 switch (epp->ep_loopback_type) { 720 case EFX_LOOPBACK_PHY_XS: 721 mmds = 0; 722 break; 723 case EFX_LOOPBACK_PCS: 724 mmds = (1 << PHY_XS_MMD); 725 break; 726 case EFX_LOOPBACK_PMA_PMD: 727 mmds = (1 << PHY_XS_MMD) | (1 << PCS_MMD); 728 break; 729 default: 730 break; 731 } 732 #endif /* EFSYS_OPT_LOOPBACK */ 733 734 /* 735 * bug17190 is a persistent failure of PCS block lock when PMA 736 * and PHYXS are up. Only check for this when not in phy loopback. 737 */ 738 broken = !!(mmds & (1 << PMA_PMD_MMD)); 739 740 if (!mmds) { 741 /* Use the fault state instead */ 742 if ((rc = xphy_mmd_fault(enp, epp->ep_port, &up)) != 0) 743 goto fail1; 744 745 } else { 746 up = B_TRUE; 747 for (mmd = 0; mmd < MAXMMD; mmd++) { 748 if (~mmds & (1 << mmd)) 749 continue; 750 751 rc = xphy_mmd_check(enp, epp->ep_port, mmd, &ok); 752 if (rc != 0) 753 goto fail2; 754 up &= ok; 755 broken &= (ok == (mmd != PCS_MMD)); 756 } 757 } 758 759 /* Recover from bug17190 if we've been stuck there for 3 polls. */ 760 if (!broken) 761 epp->ep_qt2025c.bug17190_count = 0; 762 else if (++(epp->ep_qt2025c.bug17190_count) >= 3) { 763 epp->ep_qt2025c.bug17190_count = 0; 764 EFSYS_PROBE(bug17190_recovery); 765 766 if ((rc = qt2025c_bug17190_workaround(enp)) != 0) 767 goto fail3; 768 } 769 770 *modep = (up) ? EFX_LINK_10000FDX : EFX_LINK_DOWN; 771 *fcntlp = epp->ep_fcntl; 772 *lp_cap_maskp = epp->ep_lp_cap_mask; 773 774 return (0); 775 776 fail3: 777 EFSYS_PROBE(fail3); 778 fail2: 779 EFSYS_PROBE(fail2); 780 fail1: 781 EFSYS_PROBE1(fail1, int, rc); 782 783 return (rc); 784 } 785 786 __checkReturn int 787 qt2025c_oui_get( 788 __in efx_nic_t *enp, 789 __out uint32_t *ouip) 790 { 791 efx_port_t *epp = &(enp->en_port); 792 int rc; 793 794 if ((rc = xphy_mmd_oui_get(enp, epp->ep_port, PMA_PMD_MMD, ouip)) != 0) 795 goto fail1; 796 797 return (0); 798 799 fail1: 800 EFSYS_PROBE1(fail1, int, rc); 801 802 return (rc); 803 } 804 805 #if EFSYS_OPT_PHY_STATS 806 807 #define QT2025C_STAT_SET(_stat, _mask, _id, _val) \ 808 do { \ 809 (_mask) |= (1ULL << (_id)); \ 810 (_stat)[_id] = (uint32_t)(_val); \ 811 _NOTE(CONSTANTCONDITION) \ 812 } while (B_FALSE) 813 814 static __checkReturn int 815 qt2025c_build_get( 816 __in efx_nic_t *enp, 817 __out uint8_t *yp, 818 __out uint8_t *mp, 819 __out uint8_t *dp) 820 { 821 efx_port_t *epp = &(enp->en_port); 822 efx_word_t word; 823 int rc; 824 825 if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD, 826 FW_BUILD1_REG, &word)) != 0) 827 goto fail1; 828 829 *yp = (uint8_t)EFX_WORD_FIELD(word, EFX_BYTE_0); 830 831 if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD, 832 FW_BUILD2_REG, &word)) != 0) 833 goto fail2; 834 835 *mp = (uint8_t)EFX_WORD_FIELD(word, EFX_BYTE_0); 836 837 if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD, 838 FW_BUILD3_REG, &word)) != 0) 839 goto fail3; 840 841 *dp = (uint8_t)EFX_WORD_FIELD(word, EFX_BYTE_0); 842 843 return (0); 844 845 fail3: 846 EFSYS_PROBE(fail3); 847 fail2: 848 EFSYS_PROBE(fail2); 849 fail1: 850 EFSYS_PROBE1(fail1, int, rc); 851 852 return (rc); 853 } 854 855 static __checkReturn int 856 qt2025c_pma_pmd_stats_update( 857 __in efx_nic_t *enp, 858 __inout uint64_t *maskp, 859 __inout_ecount(EFX_PHY_NSTATS) uint32_t *stat) 860 { 861 efx_port_t *epp = &(enp->en_port); 862 efx_word_t word; 863 int rc; 864 865 if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD, 866 PMA_PMD_STATUS1_REG, &word)) != 0) 867 goto fail1; 868 869 QT2025C_STAT_SET(stat, *maskp, EFX_PHY_STAT_PMA_PMD_LINK_UP, 870 (EFX_WORD_FIELD(word, PMA_PMD_LINK_UP) != 0) ? 1 : 0); 871 872 if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD, 873 PMA_PMD_STATUS2_REG, &word)) != 0) 874 goto fail2; 875 876 QT2025C_STAT_SET(stat, *maskp, EFX_PHY_STAT_PMA_PMD_RX_FAULT, 877 (EFX_WORD_FIELD(word, PMA_PMD_RX_FAULT) != 0) ? 1 : 0); 878 QT2025C_STAT_SET(stat, *maskp, EFX_PHY_STAT_PMA_PMD_TX_FAULT, 879 (EFX_WORD_FIELD(word, PMA_PMD_TX_FAULT) != 0) ? 1 : 0); 880 881 return (0); 882 883 fail2: 884 EFSYS_PROBE(fail2); 885 fail1: 886 EFSYS_PROBE1(fail1, int, rc); 887 888 return (rc); 889 } 890 891 static __checkReturn int 892 qt2025c_pcs_stats_update( 893 __in efx_nic_t *enp, 894 __inout uint64_t *maskp, 895 __inout_ecount(EFX_PHY_NSTATS) uint32_t *stat) 896 { 897 efx_port_t *epp = &(enp->en_port); 898 efx_word_t word; 899 uint8_t version[4]; 900 uint8_t yy; 901 uint8_t mm; 902 uint8_t dd; 903 int rc; 904 905 if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD, 906 PCS_STATUS1_REG, &word)) != 0) 907 goto fail1; 908 909 QT2025C_STAT_SET(stat, *maskp, EFX_PHY_STAT_PCS_LINK_UP, 910 (EFX_WORD_FIELD(word, PCS_LINK_UP) != 0) ? 1 : 0); 911 912 if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD, 913 PCS_STATUS2_REG, &word)) != 0) 914 goto fail2; 915 916 QT2025C_STAT_SET(stat, *maskp, EFX_PHY_STAT_PCS_RX_FAULT, 917 (EFX_WORD_FIELD(word, PCS_RX_FAULT) != 0) ? 1 : 0); 918 QT2025C_STAT_SET(stat, *maskp, EFX_PHY_STAT_PCS_TX_FAULT, 919 (EFX_WORD_FIELD(word, PCS_TX_FAULT) != 0) ? 1 : 0); 920 921 if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD, 922 PCS_10GBASE_R_STATUS2_REG, &word)) != 0) 923 goto fail3; 924 925 QT2025C_STAT_SET(stat, *maskp, EFX_PHY_STAT_PCS_BER, 926 EFX_WORD_FIELD(word, PCS_BER)); 927 QT2025C_STAT_SET(stat, *maskp, EFX_PHY_STAT_PCS_BLOCK_ERRORS, 928 EFX_WORD_FIELD(word, PCS_ERR)); 929 930 if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD, 931 OP_MODE_REG, &word)) != 0) 932 goto fail4; 933 934 QT2025C_STAT_SET(stat, *maskp, EFX_PHY_STAT_PCS_OP_MODE, 935 EFX_WORD_FIELD(word, OP_MODE_CURRENT)); 936 937 if ((rc = qt2025c_version_get(enp, version)) != 0) 938 goto fail5; 939 940 QT2025C_STAT_SET(stat, *maskp, EFX_PHY_STAT_PCS_FW_VERSION_0, 941 version[0]); 942 QT2025C_STAT_SET(stat, *maskp, EFX_PHY_STAT_PCS_FW_VERSION_1, 943 version[1]); 944 QT2025C_STAT_SET(stat, *maskp, EFX_PHY_STAT_PCS_FW_VERSION_2, 945 version[2]); 946 QT2025C_STAT_SET(stat, *maskp, EFX_PHY_STAT_PCS_FW_VERSION_3, 947 version[3]); 948 949 if ((rc = qt2025c_build_get(enp, &yy, &mm, &dd)) != 0) 950 goto fail6; 951 952 QT2025C_STAT_SET(stat, *maskp, EFX_PHY_STAT_PCS_FW_BUILD_YY, yy); 953 QT2025C_STAT_SET(stat, *maskp, EFX_PHY_STAT_PCS_FW_BUILD_MM, mm); 954 QT2025C_STAT_SET(stat, *maskp, EFX_PHY_STAT_PCS_FW_BUILD_DD, dd); 955 956 return (0); 957 958 fail6: 959 EFSYS_PROBE(fail6); 960 fail5: 961 EFSYS_PROBE(fail5); 962 fail4: 963 EFSYS_PROBE(fail4); 964 fail3: 965 EFSYS_PROBE(fail3); 966 fail2: 967 EFSYS_PROBE(fail2); 968 fail1: 969 EFSYS_PROBE1(fail1, int, rc); 970 971 return (rc); 972 } 973 974 static __checkReturn int 975 qt2025c_phy_xs_stats_update( 976 __in efx_nic_t *enp, 977 __inout uint64_t *maskp, 978 __inout_ecount(EFX_PHY_NSTATS) uint32_t *stat) 979 { 980 efx_port_t *epp = &(enp->en_port); 981 efx_word_t word; 982 int rc; 983 984 if ((rc = falcon_mdio_read(enp, epp->ep_port, PHY_XS_MMD, 985 PHY_XS_STATUS1_REG, &word)) != 0) 986 goto fail1; 987 988 QT2025C_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_LINK_UP, 989 (EFX_WORD_FIELD(word, PHY_XS_LINK_UP) != 0) ? 1 : 0); 990 991 if ((rc = falcon_mdio_read(enp, epp->ep_port, PHY_XS_MMD, 992 PHY_XS_STATUS2_REG, &word)) != 0) 993 goto fail2; 994 995 QT2025C_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_RX_FAULT, 996 (EFX_WORD_FIELD(word, PHY_XS_RX_FAULT) != 0) ? 1 : 0); 997 QT2025C_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_TX_FAULT, 998 (EFX_WORD_FIELD(word, PHY_XS_TX_FAULT) != 0) ? 1 : 0); 999 1000 if ((rc = falcon_mdio_read(enp, epp->ep_port, PHY_XS_MMD, 1001 PHY_XS_LANE_STATUS_REG, &word)) != 0) 1002 goto fail3; 1003 1004 QT2025C_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_ALIGN, 1005 (EFX_WORD_FIELD(word, PHY_XS_ALIGNED) != 0) ? 1 : 0); 1006 QT2025C_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_SYNC_A, 1007 (EFX_WORD_FIELD(word, PHY_XS_LANE0_SYNC) != 0) ? 1 : 0); 1008 QT2025C_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_SYNC_B, 1009 (EFX_WORD_FIELD(word, PHY_XS_LANE1_SYNC) != 0) ? 1 : 0); 1010 QT2025C_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_SYNC_C, 1011 (EFX_WORD_FIELD(word, PHY_XS_LANE2_SYNC) != 0) ? 1 : 0); 1012 QT2025C_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_SYNC_D, 1013 (EFX_WORD_FIELD(word, PHY_XS_LANE3_SYNC) != 0) ? 1 : 0); 1014 1015 return (0); 1016 1017 fail3: 1018 EFSYS_PROBE(fail3); 1019 fail2: 1020 EFSYS_PROBE(fail2); 1021 fail1: 1022 EFSYS_PROBE1(fail1, int, rc); 1023 1024 return (rc); 1025 } 1026 1027 __checkReturn int 1028 qt2025c_stats_update( 1029 __in efx_nic_t *enp, 1030 __in efsys_mem_t *esmp, 1031 __out_ecount(EFX_PHY_NSTATS) uint32_t *stat) 1032 { 1033 efx_port_t *epp = &(enp->en_port); 1034 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 1035 uint64_t mask = 0; 1036 uint32_t oui; 1037 int rc; 1038 1039 _NOTE(ARGUNUSED(esmp)) 1040 1041 if ((rc = xphy_mmd_oui_get(enp, epp->ep_port, PMA_PMD_MMD, &oui)) != 0) 1042 goto fail1; 1043 1044 QT2025C_STAT_SET(stat, mask, EFX_PHY_STAT_OUI, oui); 1045 1046 if ((rc = qt2025c_pma_pmd_stats_update(enp, &mask, stat)) != 0) 1047 goto fail2; 1048 1049 if ((rc = qt2025c_pcs_stats_update(enp, &mask, stat)) != 0) 1050 goto fail3; 1051 1052 if ((rc = qt2025c_phy_xs_stats_update(enp, &mask, stat)) != 0) 1053 goto fail4; 1054 1055 /* Ensure all the supported statistics are up to date */ 1056 EFSYS_ASSERT(mask == encp->enc_phy_stat_mask); 1057 1058 return (0); 1059 1060 fail4: 1061 EFSYS_PROBE(fail4); 1062 fail3: 1063 EFSYS_PROBE(fail3); 1064 fail2: 1065 EFSYS_PROBE(fail2); 1066 fail1: 1067 EFSYS_PROBE1(fail1, int, rc); 1068 1069 return (rc); 1070 } 1071 #endif /* EFSYS_OPT_PHY_STATS */ 1072 1073 #if EFSYS_OPT_PHY_PROPS 1074 1075 #if EFSYS_OPT_NAMES 1076 const char __cs * 1077 qt2025c_prop_name( 1078 __in efx_nic_t *enp, 1079 __in unsigned int id) 1080 { 1081 _NOTE(ARGUNUSED(enp, id)) 1082 1083 EFSYS_ASSERT(B_FALSE); 1084 1085 return (NULL); 1086 } 1087 #endif /* EFSYS_OPT_NAMES */ 1088 1089 __checkReturn int 1090 qt2025c_prop_get( 1091 __in efx_nic_t *enp, 1092 __in unsigned int id, 1093 __in uint32_t flags, 1094 __out uint32_t *valp) 1095 { 1096 _NOTE(ARGUNUSED(enp, id, flags, valp)) 1097 1098 EFSYS_ASSERT(B_FALSE); 1099 1100 return (ENOTSUP); 1101 } 1102 1103 __checkReturn int 1104 qt2025c_prop_set( 1105 __in efx_nic_t *enp, 1106 __in unsigned int id, 1107 __in uint32_t val) 1108 { 1109 _NOTE(ARGUNUSED(enp, id, val)) 1110 1111 EFSYS_ASSERT(B_FALSE); 1112 1113 return (ENOTSUP); 1114 } 1115 #endif /* EFSYS_OPT_PHY_PROPS */ 1116 1117 #endif /* EFSYS_OPT_PHY_QT2025C */