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