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