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