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 */