1 /* 2 * Copyright 2007-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 "txc43128.h" 32 #include "txc43128_impl.h" 33 #include "xphy.h" 34 35 #if EFSYS_OPT_PHY_TXC43128 36 37 static __checkReturn int 38 txc43128_bist_run( 39 __in efx_nic_t *enp) 40 { 41 efx_port_t *epp = &(enp->en_port); 42 efx_word_t word; 43 unsigned int count; 44 int rc; 45 46 /* Set the BIST type */ 47 EFX_POPULATE_WORD_1(word, BTYPE, TSDET_DECODE); 48 if ((rc = falcon_mdio_write(enp, epp->ep_port, PCS_MMD, BCTL, 49 &word)) != 0) 50 goto fail1; 51 52 /* Enable BIST */ 53 EFX_SET_WORD_FIELD(word, BSTEN, 1); 54 if ((rc = falcon_mdio_write(enp, epp->ep_port, PCS_MMD, BCTL, 55 &word)) != 0) 56 goto fail2; 57 58 /* Start BIST */ 59 EFX_SET_WORD_FIELD(word, BSTRT, 1); 60 if ((rc = falcon_mdio_write(enp, epp->ep_port, PCS_MMD, BCTL, 61 &word)) != 0) 62 goto fail3; 63 64 EFX_SET_WORD_FIELD(word, BSTRT, 0); 65 66 /* Spin for 100 us */ 67 EFSYS_SPIN(100); 68 69 /* Stop BIST */ 70 EFX_SET_WORD_FIELD(word, BSTOP, 1); 71 if ((rc = falcon_mdio_write(enp, epp->ep_port, PCS_MMD, BCTL, 72 &word)) != 0) 73 goto fail4; 74 75 /* Wait until BIST has stopped */ 76 count = 0; 77 do { 78 EFSYS_PROBE1(wait, unsigned int, count); 79 80 /* Spin for 10 us */ 81 EFSYS_SPIN(10); 82 83 /* Check whether the reset bit has cleared */ 84 if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD, 85 BCTL, &word)) != 0) 86 goto fail5; 87 88 if (EFX_WORD_FIELD(word, BSTOP) == 0) 89 goto done; 90 91 } while (++count < 20); 92 93 rc = ETIMEDOUT; 94 goto fail6; 95 96 done: 97 /* Disable BIST */ 98 EFX_ZERO_WORD(word); 99 if ((rc = falcon_mdio_write(enp, epp->ep_port, PCS_MMD, BCTL, 100 &word)) != 0) 101 goto fail7; 102 103 return (0); 104 105 fail7: 106 EFSYS_PROBE(fail7); 107 fail6: 108 EFSYS_PROBE(fail6); 109 fail5: 110 EFSYS_PROBE(fail5); 111 fail4: 112 EFSYS_PROBE(fail4); 113 fail3: 114 EFSYS_PROBE(fail3); 115 fail2: 116 EFSYS_PROBE(fail2); 117 fail1: 118 EFSYS_PROBE1(fail1, int, rc); 119 120 return (rc); 121 } 122 123 static __checkReturn int 124 txc43128_bist_check( 125 __in efx_nic_t *enp) 126 { 127 efx_port_t *epp = &(enp->en_port); 128 efx_word_t word; 129 int rc; 130 131 /* Check lane 0 frame count */ 132 if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD, BRX0FRMCNT, 133 &word)) != 0) 134 goto fail1; 135 136 if (EFX_WORD_FIELD(word, EFX_WORD_0) == 0) 137 goto fail2; 138 139 /* Check lane 0 error count */ 140 if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD, BRX0ERRCNT, 141 &word)) != 0) 142 goto fail3; 143 144 if (EFX_WORD_FIELD(word, EFX_WORD_0) != 0) 145 goto fail4; 146 147 /* Check lane 1 frame count */ 148 if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD, BRX1FRMCNT, 149 &word)) != 0) 150 goto fail5; 151 152 if (EFX_WORD_FIELD(word, EFX_WORD_0) == 0) 153 goto fail6; 154 155 /* Check lane 1 error count */ 156 if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD, BRX1ERRCNT, 157 &word)) != 0) 158 goto fail7; 159 160 if (EFX_WORD_FIELD(word, EFX_WORD_0) != 0) 161 goto fail8; 162 163 /* Check lane 2 frame count */ 164 if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD, BRX2FRMCNT, 165 &word)) != 0) 166 goto fail9; 167 168 if (EFX_WORD_FIELD(word, EFX_WORD_0) == 0) 169 goto fail10; 170 171 /* Check lane 2 error count */ 172 if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD, BRX2ERRCNT, 173 &word)) != 0) 174 goto fail11; 175 176 if (EFX_WORD_FIELD(word, EFX_WORD_0) != 0) 177 goto fail12; 178 179 /* Check lane 3 frame count */ 180 if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD, BRX3FRMCNT, 181 &word)) != 0) 182 goto fail13; 183 184 if (EFX_WORD_FIELD(word, EFX_WORD_0) == 0) 185 goto fail14; 186 187 /* Check lane 3 error count */ 188 if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD, BRX3ERRCNT, 189 &word)) != 0) 190 goto fail15; 191 192 if (EFX_WORD_FIELD(word, EFX_WORD_0) != 0) 193 goto fail16; 194 195 return (0); 196 197 fail16: 198 EFSYS_PROBE(fail16); 199 fail15: 200 EFSYS_PROBE(fail15); 201 fail14: 202 EFSYS_PROBE(fail14); 203 fail13: 204 EFSYS_PROBE(fail13); 205 fail12: 206 EFSYS_PROBE(fail12); 207 fail11: 208 EFSYS_PROBE(fail11); 209 fail10: 210 EFSYS_PROBE(fail10); 211 fail9: 212 EFSYS_PROBE(fail9); 213 fail8: 214 EFSYS_PROBE(fail8); 215 fail7: 216 EFSYS_PROBE(fail7); 217 fail6: 218 EFSYS_PROBE(fail6); 219 fail5: 220 EFSYS_PROBE(fail5); 221 fail4: 222 EFSYS_PROBE(fail4); 223 fail3: 224 EFSYS_PROBE(fail3); 225 fail2: 226 EFSYS_PROBE(fail2); 227 fail1: 228 EFSYS_PROBE1(fail1, int, rc); 229 230 return (rc); 231 } 232 233 static __checkReturn int 234 txc43128_bist( 235 __in efx_nic_t *enp) 236 { 237 efx_port_t *epp = &(enp->en_port); 238 efx_word_t word; 239 int rc; 240 241 /* Set PMA into loopback */ 242 if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD, MNDBLCFG, 243 &word)) != 0) 244 goto fail1; 245 246 EFX_SET_WORD_FIELD(word, LNALPBK, 1); 247 248 if ((rc = falcon_mdio_write(enp, epp->ep_port, PCS_MMD, MNDBLCFG, 249 &word)) != 0) 250 goto fail2; 251 252 /* Run BIST */ 253 if ((rc = txc43128_bist_run(enp)) != 0) 254 goto fail3; 255 256 /* Check BIST */ 257 if ((rc = txc43128_bist_check(enp)) != 0) 258 goto fail4; 259 260 /* Turn off loopback */ 261 EFX_SET_WORD_FIELD(word, LNALPBK, 0); 262 263 if ((rc = falcon_mdio_write(enp, epp->ep_port, PCS_MMD, MNDBLCFG, 264 &word)) != 0) 265 goto fail5; 266 267 return (0); 268 269 fail5: 270 EFSYS_PROBE(fail5); 271 fail4: 272 EFSYS_PROBE(fail4); 273 fail3: 274 EFSYS_PROBE(fail3); 275 fail2: 276 EFSYS_PROBE(fail2); 277 fail1: 278 EFSYS_PROBE1(fail1, int, rc); 279 280 return (rc); 281 } 282 283 static __checkReturn int 284 txc43128_led_cfg( 285 __in efx_nic_t *enp) 286 { 287 efx_port_t *epp = &(enp->en_port); 288 efx_word_t word; 289 int rc; 290 291 /* PIO11 allows us to control the red LED */ 292 293 EFX_POPULATE_WORD_1(word, PIO11FNC, PIOFNC_GPIO_DECODE); 294 295 if ((rc = falcon_mdio_write(enp, epp->ep_port, PHY_XS_MMD, 296 PIOCFG, &word)) != 0) 297 goto fail1; 298 299 EFX_POPULATE_WORD_1(word, PIO11DIR, PIODIR_OUT_DECODE); 300 301 if ((rc = falcon_mdio_write(enp, epp->ep_port, PHY_XS_MMD, 302 PIODIR, &word)) != 0) 303 goto fail2; 304 305 306 #if EFSYS_OPT_PHY_LED_CONTROL 307 308 switch (epp->ep_phy_led_mode) { 309 case EFX_PHY_LED_DEFAULT: 310 case EFX_PHY_LED_OFF: 311 EFX_POPULATE_WORD_1(word, PIO11OUT, 0); 312 break; 313 314 case EFX_PHY_LED_ON: 315 EFX_POPULATE_WORD_1(word, PIO11OUT, 1); 316 break; 317 318 default: 319 EFSYS_ASSERT(B_FALSE); 320 break; 321 } 322 323 #else /* EFSYS_OPT_PHY_LED_CONTROL */ 324 325 EFX_POPULATE_WORD_1(word, PIO11OUT, 0); 326 327 #endif /* EFSYS_OPT_PHY_LED_CONTROL */ 328 329 if ((rc = falcon_mdio_write(enp, epp->ep_port, PHY_XS_MMD, 330 PIODO, &word)) != 0) 331 goto fail3; 332 333 return (0); 334 335 fail3: 336 EFSYS_PROBE(fail3); 337 fail2: 338 EFSYS_PROBE(fail2); 339 fail1: 340 EFSYS_PROBE1(fail1, int, rc); 341 342 return (rc); 343 } 344 345 static __checkReturn int 346 txc43128_preemphasis_cfg( 347 __in efx_nic_t *enp) 348 { 349 efx_port_t *epp = &(enp->en_port); 350 efx_word_t word; 351 int rc; 352 353 /* XAUI settings */ 354 EFX_POPULATE_WORD_2(word, TXPRE02, 0, TXPRE13, 0); 355 356 if ((rc = falcon_mdio_write(enp, epp->ep_port, PHY_XS_MMD, 357 ATXPRE0, &word)) != 0) 358 goto fail1; 359 360 if ((rc = falcon_mdio_write(enp, epp->ep_port, PHY_XS_MMD, 361 ATXPRE1, &word)) != 0) 362 goto fail2; 363 364 /* Line settings */ 365 EFX_POPULATE_WORD_2(word, TXPRE02, 2, TXPRE13, 2); 366 367 if ((rc = falcon_mdio_write(enp, epp->ep_port, PMA_PMD_MMD, 368 ATXPRE0, &word)) != 0) 369 goto fail3; 370 371 if ((rc = falcon_mdio_write(enp, epp->ep_port, PMA_PMD_MMD, 372 ATXPRE1, &word)) != 0) 373 goto fail4; 374 375 return (0); 376 377 fail4: 378 EFSYS_PROBE(fail4); 379 fail3: 380 EFSYS_PROBE(fail3); 381 fail2: 382 EFSYS_PROBE(fail2); 383 fail1: 384 EFSYS_PROBE1(fail1, int, rc); 385 386 return (rc); 387 } 388 389 static __checkReturn int 390 txc43128_amplitude_cfg( 391 __in efx_nic_t *enp) 392 { 393 efx_port_t *epp = &(enp->en_port); 394 efx_word_t word; 395 int rc; 396 397 /* XAUI settings */ 398 EFX_POPULATE_WORD_2(word, TXAMP02, 25, TXAMP13, 25); 399 400 if ((rc = falcon_mdio_write(enp, epp->ep_port, PHY_XS_MMD, 401 ATXAMP0, &word)) != 0) 402 goto fail1; 403 404 if ((rc = falcon_mdio_write(enp, epp->ep_port, PHY_XS_MMD, 405 ATXAMP1, &word)) != 0) 406 goto fail2; 407 408 /* Line settings */ 409 EFX_POPULATE_WORD_2(word, TXAMP02, 12, TXAMP13, 12); 410 411 if ((rc = falcon_mdio_write(enp, epp->ep_port, PMA_PMD_MMD, 412 ATXAMP0, &word)) != 0) 413 goto fail3; 414 415 if ((rc = falcon_mdio_write(enp, epp->ep_port, PMA_PMD_MMD, 416 ATXAMP1, &word)) != 0) 417 goto fail4; 418 419 return (0); 420 421 fail4: 422 EFSYS_PROBE(fail4); 423 fail3: 424 EFSYS_PROBE(fail3); 425 fail2: 426 EFSYS_PROBE(fail2); 427 fail1: 428 EFSYS_PROBE1(fail1, int, rc); 429 430 return (rc); 431 } 432 433 #if EFSYS_OPT_LOOPBACK 434 static __checkReturn int 435 txc43128_loopback_cfg( 436 __in efx_nic_t *enp) 437 { 438 efx_port_t *epp = &(enp->en_port); 439 efx_word_t word; 440 int rc; 441 442 switch (epp->ep_loopback_type) { 443 case EFX_LOOPBACK_PHY_XS: 444 if ((rc = falcon_mdio_read(enp, epp->ep_port, PHY_XS_MMD, 445 MNDBLCFG, &word)) != 0) 446 goto fail1; 447 448 EFX_SET_WORD_FIELD(word, PXS8BLPBK, 1); 449 450 if ((rc = falcon_mdio_write(enp, epp->ep_port, PHY_XS_MMD, 451 MNDBLCFG, &word)) != 0) 452 goto fail2; 453 454 break; 455 456 case EFX_LOOPBACK_PCS: 457 if ((rc = xphy_mmd_loopback_set(enp, epp->ep_port, PCS_MMD, 458 B_TRUE)) != 0) 459 goto fail1; 460 461 break; 462 463 case EFX_LOOPBACK_PMA_PMD: 464 if ((rc = xphy_mmd_loopback_set(enp, epp->ep_port, PMA_PMD_MMD, 465 B_TRUE)) != 0) 466 goto fail1; 467 468 break; 469 470 default: 471 break; 472 } 473 474 return (0); 475 476 fail2: 477 EFSYS_PROBE(fail2); 478 fail1: 479 EFSYS_PROBE1(fail1, int, rc); 480 481 return (rc); 482 } 483 #endif /* EFSYS_PHY_LOOPBACK */ 484 485 static __checkReturn int 486 txc43128_logic_reset( 487 __in efx_nic_t *enp) 488 { 489 efx_port_t *epp = &(enp->en_port); 490 efx_word_t word; 491 unsigned int count; 492 int rc; 493 494 EFSYS_PROBE(logic_reset); 495 496 /* Set the reset bit in the global command register */ 497 if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD, GLCMD, 498 &word)) != 0) 499 goto fail1; 500 501 EFX_SET_WORD_FIELD(word, LMTSWRST, 1); 502 503 if ((rc = falcon_mdio_write(enp, epp->ep_port, PCS_MMD, GLCMD, 504 &word)) != 0) 505 goto fail2; 506 507 count = 0; 508 do { 509 EFSYS_PROBE1(wait, unsigned int, count); 510 511 /* Spin for 10 us */ 512 EFSYS_SPIN(10); 513 514 /* Check whether the reset bit has cleared */ 515 if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD, 516 GLCMD, &word)) != 0) 517 goto fail3; 518 519 if (EFX_WORD_FIELD(word, LMTSWRST) == 0) 520 goto done; 521 522 } while (++count < 1000); 523 524 rc = ETIMEDOUT; 525 goto fail4; 526 527 done: 528 return (0); 529 530 fail4: 531 EFSYS_PROBE(fail4); 532 fail3: 533 EFSYS_PROBE(fail3); 534 fail2: 535 EFSYS_PROBE(fail2); 536 fail1: 537 EFSYS_PROBE1(fail1, int, rc); 538 539 return (rc); 540 } 541 542 __checkReturn int 543 txc43128_reset( 544 __in efx_nic_t *enp) 545 { 546 efx_port_t *epp = &(enp->en_port); 547 efx_word_t word; 548 unsigned int count; 549 int rc; 550 551 /* Set the reset bit in the main control register */ 552 if ((rc = falcon_mdio_read(enp, epp->ep_port, PHY_XS_MMD, MNCTL, 553 &word)) != 0) 554 goto fail1; 555 556 EFX_SET_WORD_FIELD(word, MRST, 1); 557 558 if ((rc = falcon_mdio_write(enp, epp->ep_port, PHY_XS_MMD, MNCTL, 559 &word)) != 0) 560 goto fail2; 561 562 count = 0; 563 do { 564 EFSYS_PROBE1(wait, unsigned int, count); 565 566 /* Spin for 10 us */ 567 EFSYS_SPIN(10); 568 569 /* Check whether the reset bit has cleared */ 570 if ((rc = falcon_mdio_read(enp, epp->ep_port, PHY_XS_MMD, 571 MNCTL, &word)) != 0) 572 goto fail3; 573 574 if (EFX_WORD_FIELD(word, MRST) == 0) 575 goto done; 576 577 } while (++count < 1000); 578 579 rc = ETIMEDOUT; 580 goto fail4; 581 582 done: 583 /* 584 * Despite the global reset having completed, we will still be unable 585 * to get sensible values out of the 802.3ae registers for some 586 * unknown time. 250 ms seems to cover it but this is empirically 587 * determined. 588 */ 589 EFSYS_SLEEP(250000); 590 591 enp->en_reset_flags |= EFX_RESET_PHY; 592 593 return (0); 594 595 fail4: 596 EFSYS_PROBE(fail4); 597 fail3: 598 EFSYS_PROBE(fail3); 599 fail2: 600 EFSYS_PROBE(fail2); 601 fail1: 602 EFSYS_PROBE1(fail1, int, rc); 603 604 return (rc); 605 } 606 607 __checkReturn int 608 txc43128_reconfigure( 609 __in efx_nic_t *enp) 610 { 611 efx_port_t *epp = &(enp->en_port); 612 int rc; 613 614 if ((rc = xphy_pkg_wait(enp, epp->ep_port, TXC43128_MMD_MASK)) != 0) 615 goto fail1; 616 617 if ((rc = txc43128_bist(enp)) != 0) 618 goto fail2; 619 620 if ((rc = txc43128_led_cfg(enp)) != 0) 621 goto fail3; 622 623 if ((rc = txc43128_preemphasis_cfg(enp)) != 0) 624 goto fail4; 625 626 if ((rc = txc43128_amplitude_cfg(enp)) != 0) 627 goto fail5; 628 629 EFSYS_ASSERT3U(epp->ep_adv_cap_mask, ==, TXC43128_ADV_CAP_MASK); 630 631 #if EFSYS_OPT_LOOPBACK 632 if ((rc = txc43128_loopback_cfg(enp)) != 0) 633 goto fail6; 634 #endif /* EFSYS_OPT_LOOPBACK */ 635 636 if ((rc = txc43128_logic_reset(enp)) != 0) 637 goto fail7; 638 639 return (0); 640 641 fail7: 642 EFSYS_PROBE(fail7); 643 644 #if EFSYS_OPT_LOOPBACK 645 fail6: 646 EFSYS_PROBE(fail6); 647 #endif /* EFSYS_OPT_LOOPBACK */ 648 649 fail5: 650 EFSYS_PROBE(fail5); 651 fail4: 652 EFSYS_PROBE(fail4); 653 fail3: 654 EFSYS_PROBE(fail3); 655 fail2: 656 EFSYS_PROBE(fail2); 657 fail1: 658 EFSYS_PROBE1(fail1, int, rc); 659 660 return (rc); 661 } 662 663 __checkReturn int 664 txc43128_verify( 665 __in efx_nic_t *enp) 666 { 667 efx_port_t *epp = &(enp->en_port); 668 int rc; 669 670 if ((rc = xphy_pkg_verify(enp, epp->ep_port, TXC43128_MMD_MASK)) != 0) 671 goto fail1; 672 673 return (0); 674 675 fail1: 676 EFSYS_PROBE1(fail1, int, rc); 677 678 return (rc); 679 } 680 681 __checkReturn int 682 txc43128_uplink_check( 683 __in efx_nic_t *enp, 684 __out boolean_t *upp) 685 { 686 efx_port_t *epp = &(enp->en_port); 687 efx_word_t word; 688 int rc; 689 690 if (epp->ep_mac_type != EFX_MAC_FALCON_XMAC) { 691 rc = ENOTSUP; 692 goto fail1; 693 } 694 695 if ((rc = falcon_mdio_read(enp, epp->ep_port, PHY_XS_MMD, 696 PHY_XS_LANE_STATUS_REG, &word)) != 0) 697 goto fail2; 698 699 *upp = ((EFX_WORD_FIELD(word, PHY_XS_ALIGNED) != 0) && 700 ((EFX_WORD_FIELD(word, PHY_XS_LANE0_SYNC) != 0) || 701 (EFX_WORD_FIELD(word, PHY_XS_LANE1_SYNC) != 0) || 702 (EFX_WORD_FIELD(word, PHY_XS_LANE2_SYNC) != 0) || 703 (EFX_WORD_FIELD(word, PHY_XS_LANE3_SYNC) != 0))); 704 705 return (0); 706 707 fail2: 708 EFSYS_PROBE(fail2); 709 fail1: 710 EFSYS_PROBE1(fail1, int, rc); 711 712 return (rc); 713 } 714 715 __checkReturn int 716 txc43128_downlink_check( 717 __in efx_nic_t *enp, 718 __out efx_link_mode_t *modep, 719 __out unsigned int *fcntlp, 720 __out uint32_t *lp_cap_maskp) 721 { 722 efx_port_t *epp = &(enp->en_port); 723 boolean_t up; 724 int rc; 725 726 #if EFSYS_OPT_LOOPBACK 727 switch (epp->ep_loopback_type) { 728 case EFX_LOOPBACK_PHY_XS: 729 rc = xphy_mmd_fault(enp, epp->ep_port, &up); 730 if (rc != 0) 731 goto fail1; 732 733 *modep = (up) ? EFX_LINK_10000FDX : EFX_LINK_DOWN; 734 goto done; 735 736 case EFX_LOOPBACK_PCS: 737 rc = xphy_mmd_check(enp, epp->ep_port, PHY_XS_MMD, &up); 738 if (rc != 0) 739 goto fail1; 740 741 *modep = (up) ? EFX_LINK_10000FDX : EFX_LINK_DOWN; 742 goto done; 743 744 default: 745 break; 746 } 747 #endif /* EFSYS_OPT_LOOPBACK */ 748 749 if ((rc = xphy_mmd_check(enp, epp->ep_port, PCS_MMD, &up)) != 0) 750 goto fail1; 751 752 /* bug10934: Reset the controller if the PCS block is stuck down */ 753 if (up) 754 epp->ep_txc43128.bug10934_count = 0; 755 else if (++(epp->ep_txc43128.bug10934_count) > 10) { 756 (void) txc43128_logic_reset(enp); 757 epp->ep_txc43128.bug10934_count = 0; 758 } 759 760 *modep = (up) ? EFX_LINK_10000FDX : EFX_LINK_DOWN; 761 762 #if EFSYS_OPT_LOOPBACK 763 done: 764 #endif 765 *fcntlp = epp->ep_fcntl; 766 *lp_cap_maskp = epp->ep_lp_cap_mask; 767 768 return (0); 769 770 fail1: 771 EFSYS_PROBE1(fail1, int, rc); 772 773 return (rc); 774 } 775 776 __checkReturn int 777 txc43128_oui_get( 778 __in efx_nic_t *enp, 779 __out uint32_t *ouip) 780 { 781 efx_port_t *epp = &(enp->en_port); 782 int rc; 783 784 if ((rc = xphy_mmd_oui_get(enp, epp->ep_port, PMA_PMD_MMD, 785 ouip)) != 0) 786 goto fail1; 787 788 return (0); 789 790 fail1: 791 EFSYS_PROBE1(fail1, int, rc); 792 793 return (rc); 794 } 795 796 #if EFSYS_OPT_PHY_STATS 797 798 #define TXC43128_STAT_SET(_stat, _mask, _id, _val) \ 799 do { \ 800 (_mask) |= (1ULL << (_id)); \ 801 (_stat)[_id] = (uint32_t)(_val); \ 802 _NOTE(CONSTANTCONDITION) \ 803 } while (B_FALSE) 804 805 static __checkReturn int 806 txc43128_pma_pmd_stats_update( 807 __in efx_nic_t *enp, 808 __inout uint64_t *maskp, 809 __inout_ecount(EFX_PHY_NSTATS) uint32_t *stat) 810 { 811 efx_port_t *epp = &(enp->en_port); 812 efx_word_t word; 813 int rc; 814 815 if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD, 816 PMA_PMD_STATUS1_REG, &word)) != 0) 817 goto fail1; 818 819 TXC43128_STAT_SET(stat, *maskp, EFX_PHY_STAT_PMA_PMD_LINK_UP, 820 (EFX_WORD_FIELD(word, PMA_PMD_LINK_UP) != 0) ? 1 : 0); 821 822 if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD, 823 PMA_PMD_STATUS2_REG, &word)) != 0) 824 goto fail2; 825 826 TXC43128_STAT_SET(stat, *maskp, EFX_PHY_STAT_PMA_PMD_RX_FAULT, 827 (EFX_WORD_FIELD(word, PMA_PMD_RX_FAULT) != 0) ? 1 : 0); 828 TXC43128_STAT_SET(stat, *maskp, EFX_PHY_STAT_PMA_PMD_TX_FAULT, 829 (EFX_WORD_FIELD(word, PMA_PMD_TX_FAULT) != 0) ? 1 : 0); 830 831 if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD, SIGDET, 832 &word)) != 0) 833 goto fail3; 834 835 TXC43128_STAT_SET(stat, *maskp, EFX_PHY_STAT_PMA_PMD_SIGNAL_A, 836 (EFX_WORD_FIELD(word, RX0SIGDET) != 0)); 837 TXC43128_STAT_SET(stat, *maskp, EFX_PHY_STAT_PMA_PMD_SIGNAL_B, 838 (EFX_WORD_FIELD(word, RX1SIGDET) != 0)); 839 TXC43128_STAT_SET(stat, *maskp, EFX_PHY_STAT_PMA_PMD_SIGNAL_C, 840 (EFX_WORD_FIELD(word, RX2SIGDET) != 0)); 841 TXC43128_STAT_SET(stat, *maskp, EFX_PHY_STAT_PMA_PMD_SIGNAL_D, 842 (EFX_WORD_FIELD(word, RX3SIGDET) != 0)); 843 844 return (0); 845 846 fail3: 847 EFSYS_PROBE(fail3); 848 fail2: 849 EFSYS_PROBE(fail2); 850 fail1: 851 EFSYS_PROBE1(fail1, int, rc); 852 853 return (rc); 854 } 855 856 static __checkReturn int 857 txc43128_pcs_stats_update( 858 __in efx_nic_t *enp, 859 __inout uint64_t *maskp, 860 __inout_ecount(EFX_PHY_NSTATS) uint32_t *stat) 861 { 862 efx_port_t *epp = &(enp->en_port); 863 efx_word_t word; 864 int rc; 865 866 if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD, 867 PCS_STATUS1_REG, &word)) != 0) 868 goto fail1; 869 870 TXC43128_STAT_SET(stat, *maskp, EFX_PHY_STAT_PCS_LINK_UP, 871 (EFX_WORD_FIELD(word, PCS_LINK_UP) != 0) ? 1 : 0); 872 873 if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD, 874 PCS_STATUS2_REG, &word)) != 0) 875 goto fail2; 876 877 TXC43128_STAT_SET(stat, *maskp, EFX_PHY_STAT_PCS_RX_FAULT, 878 (EFX_WORD_FIELD(word, PCS_RX_FAULT) != 0) ? 1 : 0); 879 TXC43128_STAT_SET(stat, *maskp, EFX_PHY_STAT_PCS_TX_FAULT, 880 (EFX_WORD_FIELD(word, PCS_TX_FAULT) != 0) ? 1 : 0); 881 882 return (0); 883 884 fail2: 885 EFSYS_PROBE(fail2); 886 fail1: 887 EFSYS_PROBE1(fail1, int, rc); 888 889 return (rc); 890 } 891 892 static __checkReturn int 893 txc43128_phy_xs_stats_update( 894 __in efx_nic_t *enp, 895 __inout uint64_t *maskp, 896 __inout_ecount(EFX_PHY_NSTATS) uint32_t *stat) 897 { 898 efx_port_t *epp = &(enp->en_port); 899 efx_word_t word; 900 int rc; 901 902 if ((rc = falcon_mdio_read(enp, epp->ep_port, PHY_XS_MMD, 903 PHY_XS_STATUS1_REG, &word)) != 0) 904 goto fail1; 905 906 TXC43128_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_LINK_UP, 907 (EFX_WORD_FIELD(word, PHY_XS_LINK_UP) != 0) ? 1 : 0); 908 909 if ((rc = falcon_mdio_read(enp, epp->ep_port, PHY_XS_MMD, 910 PHY_XS_STATUS2_REG, &word)) != 0) 911 goto fail2; 912 913 TXC43128_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_RX_FAULT, 914 (EFX_WORD_FIELD(word, PHY_XS_RX_FAULT) != 0) ? 1 : 0); 915 TXC43128_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_TX_FAULT, 916 (EFX_WORD_FIELD(word, PHY_XS_TX_FAULT) != 0) ? 1 : 0); 917 918 if ((rc = falcon_mdio_read(enp, epp->ep_port, PHY_XS_MMD, 919 PHY_XS_LANE_STATUS_REG, &word)) != 0) 920 goto fail3; 921 922 TXC43128_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_ALIGN, 923 (EFX_WORD_FIELD(word, PHY_XS_ALIGNED) != 0) ? 1 : 0); 924 TXC43128_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_SYNC_A, 925 (EFX_WORD_FIELD(word, PHY_XS_LANE0_SYNC) != 0) ? 1 : 0); 926 TXC43128_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_SYNC_B, 927 (EFX_WORD_FIELD(word, PHY_XS_LANE1_SYNC) != 0) ? 1 : 0); 928 TXC43128_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_SYNC_C, 929 (EFX_WORD_FIELD(word, PHY_XS_LANE2_SYNC) != 0) ? 1 : 0); 930 TXC43128_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_SYNC_D, 931 (EFX_WORD_FIELD(word, PHY_XS_LANE3_SYNC) != 0) ? 1 : 0); 932 933 return (0); 934 935 fail3: 936 EFSYS_PROBE(fail3); 937 fail2: 938 EFSYS_PROBE(fail2); 939 fail1: 940 EFSYS_PROBE1(fail1, int, rc); 941 942 return (rc); 943 } 944 945 __checkReturn int 946 txc43128_stats_update( 947 __in efx_nic_t *enp, 948 __in efsys_mem_t *esmp, 949 __out_ecount(EFX_PHY_NSTATS) uint32_t *stat) 950 { 951 efx_port_t *epp = &(enp->en_port); 952 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 953 uint64_t mask = 0; 954 uint32_t oui; 955 int rc; 956 957 _NOTE(ARGUNUSED(esmp)) 958 959 if ((rc = xphy_mmd_oui_get(enp, epp->ep_port, PMA_PMD_MMD, &oui)) != 0) 960 goto fail1; 961 962 TXC43128_STAT_SET(stat, mask, EFX_PHY_STAT_OUI, oui); 963 964 if ((rc = txc43128_pma_pmd_stats_update(enp, &mask, stat)) != 0) 965 goto fail2; 966 967 if ((rc = txc43128_pcs_stats_update(enp, &mask, stat)) != 0) 968 goto fail3; 969 970 if ((rc = txc43128_phy_xs_stats_update(enp, &mask, stat)) != 0) 971 goto fail4; 972 973 /* Ensure all the supported statistics are up to date */ 974 EFSYS_ASSERT(mask == encp->enc_phy_stat_mask); 975 976 return (0); 977 978 fail4: 979 EFSYS_PROBE(fail4); 980 fail3: 981 EFSYS_PROBE(fail3); 982 fail2: 983 EFSYS_PROBE(fail2); 984 fail1: 985 EFSYS_PROBE1(fail1, int, rc); 986 987 return (rc); 988 } 989 #endif /* EFSYS_OPT_PHY_STATS */ 990 991 #if EFSYS_OPT_PHY_PROPS 992 993 #if EFSYS_OPT_NAMES 994 const char __cs * 995 txc43128_prop_name( 996 __in efx_nic_t *enp, 997 __in unsigned int id) 998 { 999 _NOTE(ARGUNUSED(enp, id)) 1000 1001 EFSYS_ASSERT(B_FALSE); 1002 1003 return (NULL); 1004 } 1005 #endif /* EFSYS_OPT_NAMES */ 1006 1007 __checkReturn int 1008 txc43128_prop_get( 1009 __in efx_nic_t *enp, 1010 __in unsigned int id, 1011 __in uint32_t flags, 1012 __out uint32_t *valp) 1013 { 1014 _NOTE(ARGUNUSED(enp, id, flags, valp)) 1015 1016 EFSYS_ASSERT(B_FALSE); 1017 1018 return (ENOTSUP); 1019 } 1020 1021 __checkReturn int 1022 txc43128_prop_set( 1023 __in efx_nic_t *enp, 1024 __in unsigned int id, 1025 __in uint32_t val) 1026 { 1027 _NOTE(ARGUNUSED(enp, id, val)) 1028 1029 EFSYS_ASSERT(B_FALSE); 1030 1031 return (ENOTSUP); 1032 } 1033 #endif /* EFSYS_OPT_PHY_PROPS */ 1034 1035 #endif /* EFSYS_OPT_PHY_TXC43128 */