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 "falcon_nvram.h"
32 #include "sft9001.h"
33 #include "sft9001_impl.h"
34 #include "xphy.h"
35 #include "falcon_impl.h"
36
37 #if EFSYS_OPT_PHY_SFT9001
38
39 static __checkReturn int
40 sft9001_short_reach_set(
41 __in efx_nic_t *enp,
42 __in boolean_t on)
43 {
44 efx_port_t *epp = &(enp->en_port);
45 efx_word_t word;
46 int rc;
47
48 if ((rc = falcon_mdio_read(enp, epp->ep_port,
49 PMA_PMD_MMD, PMA_PMD_PWR_BACKOFF_REG, &word)) != 0)
50 goto fail1;
51
52 EFX_SET_WORD_FIELD(word, SHORT_REACH, (on) ? 1 : 0);
53
54 if ((rc = falcon_mdio_write(enp, epp->ep_port,
55 PMA_PMD_MMD, PMA_PMD_PWR_BACKOFF_REG, &word)) != 0)
56 goto fail2;
57
58 return (0);
59
60 fail2:
61 EFSYS_PROBE(fail2);
62 fail1:
63 EFSYS_PROBE1(fail1, int, rc);
64
65 return (rc);
66 }
67
68 static __checkReturn int
69 sft9001_short_reach_get(
70 __in efx_nic_t *enp,
71 __out boolean_t *onp)
72 {
73 efx_port_t *epp = &(enp->en_port);
74 efx_word_t word;
75 int rc;
76
77 if ((rc = falcon_mdio_read(enp, epp->ep_port,
78 PMA_PMD_MMD, PMA_PMD_PWR_BACKOFF_REG, &word)) != 0)
79 goto fail1;
80
81 *onp = (EFX_WORD_FIELD(word, SHORT_REACH) != 0);
82
83 return (0);
84
85 fail1:
86 EFSYS_PROBE1(fail1, int, rc);
87
88 return (rc);
89 }
90
91 static __checkReturn int
92 sft9001_robust_set(
93 __in efx_nic_t *enp,
94 __in boolean_t on)
95 {
96 efx_port_t *epp = &(enp->en_port);
97 efx_word_t word;
98 int rc;
99
100 if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD,
101 PMA_PMD_XCONTROL_REG, &word)) != 0)
102 goto fail1;
103
104 EFX_SET_WORD_FIELD(word, ROBUST, (on) ? 1 : 0);
105
106 if ((rc = falcon_mdio_write(enp, epp->ep_port, PMA_PMD_MMD,
107 PMA_PMD_XCONTROL_REG, &word)) != 0)
108 goto fail2;
109
110 return (0);
111
112 fail2:
113 EFSYS_PROBE(fail2);
114 fail1:
115 EFSYS_PROBE1(fail1, int, rc);
116
117 return (rc);
118 }
119
120 static __checkReturn int
121 sft9001_robust_get(
122 __in efx_nic_t *enp,
123 __out boolean_t *onp)
124 {
125 efx_port_t *epp = &(enp->en_port);
126 efx_word_t word;
127 int rc;
128
129 if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD,
130 PMA_PMD_XCONTROL_REG, &word)) != 0)
131 goto fail1;
132
133 *onp = (EFX_WORD_FIELD(word, ROBUST) != 0);
134
135 return (0);
136
137 fail1:
138 EFSYS_PROBE1(fail1, int, rc);
139
140 return (rc);
141 }
142
143 static __checkReturn int
144 sft9001_an_set(
145 __in efx_nic_t *enp,
146 __in boolean_t on)
147 {
148 efx_port_t *epp = &(enp->en_port);
149 efx_word_t word;
150 int rc;
151
152 if ((rc = falcon_mdio_read(enp, epp->ep_port, AN_MMD,
153 AN_CONTROL1_REG, &word)) != 0)
154 goto fail1;
155
156 if (on) {
157 EFX_SET_WORD_FIELD(word, AN_ENABLE, 1);
158 EFX_SET_WORD_FIELD(word, AN_RESTART, 1);
159 } else {
160 EFX_SET_WORD_FIELD(word, AN_ENABLE, 0);
161 }
162
163 if ((rc = falcon_mdio_write(enp, epp->ep_port, AN_MMD,
164 AN_CONTROL1_REG, &word)) != 0)
165 goto fail2;
166
167 return (0);
168
169 fail2:
170 EFSYS_PROBE(fail2);
171 fail1:
172 EFSYS_PROBE1(fail1, int, rc);
173
174 return (rc);
175 }
176
177 static __checkReturn int
178 sft9001_gmii_cfg(
179 __in efx_nic_t *enp)
180 {
181 efx_port_t *epp = &(enp->en_port);
182 efx_word_t word;
183 int rc;
184
185 if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD,
186 PMA_PMD_XCONTROL_REG, &word)) != 0)
187 goto fail1;
188
189 EFX_SET_WORD_FIELD(word, GMII_EN, 1);
190
191 if ((rc = falcon_mdio_write(enp, epp->ep_port, PMA_PMD_MMD,
192 PMA_PMD_XCONTROL_REG, &word)) != 0)
193 goto fail2;
194
195 return (0);
196
197 fail2:
198 EFSYS_PROBE(fail2);
199 fail1:
200 EFSYS_PROBE1(fail1, int, rc);
201
202 return (rc);
203 }
204
205 static __checkReturn int
206 sft9001_clock_cfg(
207 __in efx_nic_t *enp)
208 {
209 efx_port_t *epp = &(enp->en_port);
210 efx_word_t word;
211 int rc;
212
213 if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD,
214 PMA_PMD_XCONTROL_REG, &word)) != 0)
215 goto fail1;
216
217 /* Select 312MHz clock on CLK312_OUT_{P,N} */
218 EFX_SET_WORD_FIELD(word, CLK312_OUT_SEL, SEL_312MHZ_DECODE);
219 EFX_SET_WORD_FIELD(word, CLK312_OUT_EN, 1);
220
221 /* Select 125MHz clock on TEST_CLKOUT_{P,N} */
222 EFX_SET_WORD_FIELD(word, TEST_CLKOUT_SEL, SEL_125MHZ_DECODE);
223 EFX_SET_WORD_FIELD(word, TEST_CLKOUT_EN, 1);
224
225 if ((rc = falcon_mdio_write(enp, epp->ep_port, PMA_PMD_MMD,
226 PMA_PMD_XCONTROL_REG, &word)) != 0)
227 goto fail2;
228
229 return (0);
230
231 fail2:
232 EFSYS_PROBE(fail2);
233 fail1:
234 EFSYS_PROBE1(fail1, int, rc);
235
236 return (rc);
237 }
238
239 static __checkReturn int
240 sft9001_adv_cap_cfg(
241 __in efx_nic_t *enp)
242 {
243 efx_port_t *epp = &(enp->en_port);
244 efx_word_t word;
245 int rc;
246
247 /* Check base page */
248 if ((rc = falcon_mdio_read(enp, epp->ep_port, AN_MMD,
249 AN_ADV_BP_CAP_REG, &word)) != 0)
250 goto fail1;
251
252 EFSYS_ASSERT(!(epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_10HDX)));
253 if (EFX_WORD_FIELD(word, AN_ADV_TA_10BASE_T) != 0)
254 EFX_SET_WORD_FIELD(word, AN_ADV_TA_10BASE_T, 0);
255
256 EFSYS_ASSERT(!(epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_10FDX)));
257 if (EFX_WORD_FIELD(word, AN_ADV_TA_10BASE_T_FDX) != 0)
258 EFX_SET_WORD_FIELD(word, AN_ADV_TA_10BASE_T_FDX, 0);
259
260 if (EFX_WORD_FIELD(word, AN_ADV_TA_100BASE_TX) == 0 &&
261 epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_100HDX))
262 EFX_SET_WORD_FIELD(word, AN_ADV_TA_100BASE_TX, 1);
263 else if (EFX_WORD_FIELD(word, AN_ADV_TA_100BASE_TX) != 0 &&
264 !(epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_100HDX)))
265 EFX_SET_WORD_FIELD(word, AN_ADV_TA_100BASE_TX, 0);
266
267 if (EFX_WORD_FIELD(word, AN_ADV_TA_100BASE_TX_FDX) == 0 &&
268 epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_100FDX))
269 EFX_SET_WORD_FIELD(word, AN_ADV_TA_100BASE_TX_FDX, 1);
270 else if (EFX_WORD_FIELD(word, AN_ADV_TA_100BASE_TX_FDX) != 0 &&
271 !(epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_100FDX)))
272 EFX_SET_WORD_FIELD(word, AN_ADV_TA_100BASE_TX_FDX, 0);
273
274 if (EFX_WORD_FIELD(word, AN_ADV_TA_PAUSE) == 0 &&
275 epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_PAUSE))
276 EFX_SET_WORD_FIELD(word, AN_ADV_TA_PAUSE, 1);
277 else if (EFX_WORD_FIELD(word, AN_ADV_TA_PAUSE) != 0 &&
278 !(epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_PAUSE)))
279 EFX_SET_WORD_FIELD(word, AN_ADV_TA_PAUSE, 0);
280
281 if (EFX_WORD_FIELD(word, AN_ADV_TA_ASM_DIR) == 0 &&
282 epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_ASYM))
283 EFX_SET_WORD_FIELD(word, AN_ADV_TA_ASM_DIR, 1);
284 else if (EFX_WORD_FIELD(word, AN_ADV_TA_ASM_DIR) != 0 &&
285 !(epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_ASYM)))
286 EFX_SET_WORD_FIELD(word, AN_ADV_TA_ASM_DIR, 0);
287
288 if ((rc = falcon_mdio_write(enp, epp->ep_port, AN_MMD,
289 AN_ADV_BP_CAP_REG, &word)) != 0)
290 goto fail2;
291
292 /* Check 1G operation */
293 if ((rc = falcon_mdio_read(enp, epp->ep_port, CL22EXT_MMD,
294 CL22EXT_MS_CONTROL_REG, &word)) != 0)
295 goto fail3;
296
297 EFSYS_ASSERT(!(epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_1000HDX)));
298 if (EFX_WORD_FIELD(word, CL22EXT_1000BASE_T_ADV) != 0)
299 EFX_SET_WORD_FIELD(word, CL22EXT_1000BASE_T_ADV, 0);
300
301 if (EFX_WORD_FIELD(word, CL22EXT_1000BASE_T_FDX_ADV) == 0 &&
302 epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_1000FDX))
303 EFX_SET_WORD_FIELD(word, CL22EXT_1000BASE_T_FDX_ADV, 1);
304 else if (EFX_WORD_FIELD(word, CL22EXT_1000BASE_T_FDX_ADV) != 0 &&
305 !(epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_1000FDX)))
306 EFX_SET_WORD_FIELD(word, CL22EXT_1000BASE_T_FDX_ADV, 0);
307
308 if ((rc = falcon_mdio_write(enp, epp->ep_port, CL22EXT_MMD,
309 CL22EXT_MS_CONTROL_REG, &word)) != 0)
310 goto fail4;
311
312 /* Check 10G operation */
313 if ((rc = falcon_mdio_read(enp, epp->ep_port, AN_MMD,
314 AN_10G_BASE_T_CONTROL_REG, &word)) != 0)
315 goto fail5;
316
317 if (EFX_WORD_FIELD(word, AN_10G_BASE_T_ADV) == 0 &&
318 epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_10000FDX))
319 EFX_SET_WORD_FIELD(word, AN_10G_BASE_T_ADV, 1);
320 else if (EFX_WORD_FIELD(word, AN_10G_BASE_T_ADV) != 0 &&
321 !(epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_10000FDX)))
322 EFX_SET_WORD_FIELD(word, AN_10G_BASE_T_ADV, 0);
323
324 if ((rc = falcon_mdio_write(enp, epp->ep_port, AN_MMD,
325 AN_10G_BASE_T_CONTROL_REG, &word)) != 0)
326 goto fail6;
327
328 return (0);
329
330 fail6:
331 EFSYS_PROBE(fail6);
332 fail5:
333 EFSYS_PROBE(fail5);
334 fail4:
335 EFSYS_PROBE(fail4);
336 fail3:
337 EFSYS_PROBE(fail3);
338 fail2:
339 EFSYS_PROBE(fail2);
340 fail1:
341 EFSYS_PROBE1(fail1, int, rc);
342
343 return (rc);
344 }
345
346 #if EFSYS_OPT_LOOPBACK
347 static __checkReturn int
348 sft9001_loopback_cfg(
349 __in efx_nic_t *enp)
350 {
351 efx_port_t *epp = &(enp->en_port);
352 efx_word_t word;
353 int rc;
354
355 switch (epp->ep_loopback_type) {
356 case EFX_LOOPBACK_PHY_XS:
357 if ((rc = falcon_mdio_read(enp, epp->ep_port,
358 PHY_XS_MMD, PHY_XS_TEST1_REG, &word)) != 0)
359 goto fail1;
360
361 EFX_SET_WORD_FIELD(word, PHY_XS_NE_LOOPBACK, 1);
362
363 if ((rc = falcon_mdio_write(enp, epp->ep_port,
364 PHY_XS_MMD, PHY_XS_TEST1_REG, &word)) != 0)
365 goto fail2;
366
367 break;
368
369 case EFX_LOOPBACK_PCS:
370 if ((rc = xphy_mmd_loopback_set(enp, epp->ep_port, PCS_MMD,
371 B_TRUE)) != 0)
372 goto fail1;
373
374 break;
375
376 case EFX_LOOPBACK_PMA_PMD:
377 if ((rc = xphy_mmd_loopback_set(enp, epp->ep_port, PMA_PMD_MMD,
378 B_TRUE)) != 0)
379 goto fail1;
380
381 break;
382
383 case EFX_LOOPBACK_GPHY:
384 if ((rc = falcon_mdio_read(enp, epp->ep_port,
385 CL22EXT_MMD, CL22EXT_CONTROL_REG, &word)) != 0)
386 goto fail1;
387
388 EFX_SET_WORD_FIELD(word, CL22EXT_NE_LOOPBACK, 1);
389
390 if ((rc = falcon_mdio_write(enp, epp->ep_port,
391 CL22EXT_MMD, CL22EXT_CONTROL_REG, &word)) != 0)
392 goto fail2;
393
394 break;
395
396 default:
397 break;
398 }
399
400 return (0);
401
402 fail2:
403 EFSYS_PROBE(fail2);
404 fail1:
405 EFSYS_PROBE1(fail1, int, rc);
406
407 return (rc);
408 }
409 #endif /* EFSYS_OPT_LOOPBACK */
410
411 static __checkReturn int
412 sft9001_led_cfg(
413 __in efx_nic_t *enp)
414 {
415 efx_port_t *epp = &(enp->en_port);
416 efx_word_t word;
417 int rc;
418
419 #if EFSYS_OPT_PHY_LED_CONTROL
420
421 switch (epp->ep_phy_led_mode) {
422 case EFX_PHY_LED_DEFAULT:
423 EFX_POPULATE_WORD_8(word,
424 LED_TMODE, LED_NORMAL_DECODE,
425 LED_SPARE, LED_NORMAL_DECODE,
426 LED_MS, LED_NORMAL_DECODE,
427 LED_RX, LED_NORMAL_DECODE,
428 LED_TX, LED_NORMAL_DECODE,
429 LED_SPEED0, LED_NORMAL_DECODE,
430 LED_SPEED1, LED_NORMAL_DECODE,
431 LED_LINK, LED_NORMAL_DECODE);
432 break;
433
434 case EFX_PHY_LED_OFF:
435 EFX_POPULATE_WORD_8(word,
436 LED_TMODE, LED_OFF_DECODE,
437 LED_SPARE, LED_OFF_DECODE,
438 LED_MS, LED_OFF_DECODE,
439 LED_RX, LED_OFF_DECODE,
440 LED_TX, LED_OFF_DECODE,
441 LED_SPEED0, LED_OFF_DECODE,
442 LED_SPEED1, LED_OFF_DECODE,
443 LED_LINK, LED_OFF_DECODE);
444 break;
445
446 case EFX_PHY_LED_ON:
447 EFX_POPULATE_WORD_8(word,
448 LED_TMODE, LED_ON_DECODE,
449 LED_SPARE, LED_ON_DECODE,
450 LED_MS, LED_ON_DECODE,
451 LED_RX, LED_ON_DECODE,
452 LED_TX, LED_ON_DECODE,
453 LED_SPEED0, LED_ON_DECODE,
454 LED_SPEED1, LED_ON_DECODE,
455 LED_LINK, LED_ON_DECODE);
456 break;
457
458 case EFX_PHY_LED_FLASH:
459 EFX_POPULATE_WORD_8(word,
460 LED_TMODE, LED_FLASH_DECODE,
461 LED_SPARE, LED_FLASH_DECODE,
462 LED_MS, LED_FLASH_DECODE,
463 LED_RX, LED_FLASH_DECODE,
464 LED_TX, LED_FLASH_DECODE,
465 LED_SPEED0, LED_FLASH_DECODE,
466 LED_SPEED1, LED_FLASH_DECODE,
467 LED_LINK, LED_FLASH_DECODE);
468 break;
469
470 default:
471 EFSYS_ASSERT(B_FALSE);
472 break;
473 }
474
475 #else /* EFSYS_OPT_PHY_LED_CONTROL */
476
477 EFX_POPULATE_WORD_8(word,
478 LED_TMODE, LED_NORMAL_DECODE,
479 LED_SPARE, LED_NORMAL_DECODE,
480 LED_MS, LED_NORMAL_DECODE,
481 LED_RX, LED_NORMAL_DECODE,
482 LED_TX, LED_NORMAL_DECODE,
483 LED_SPEED0, LED_NORMAL_DECODE,
484 LED_SPEED1, LED_NORMAL_DECODE,
485 LED_LINK, LED_NORMAL_DECODE);
486
487 #endif /* EFSYS_OPT_PHY_LED_CONTROL */
488
489 if ((rc = falcon_mdio_write(enp, epp->ep_port, PMA_PMD_MMD,
490 PMA_PMD_LED_OVERRIDE_REG, &word)) != 0)
491 goto fail1;
492
493 return (0);
494
495 fail1:
496 EFSYS_PROBE1(fail1, int, rc);
497
498 return (rc);
499 }
500
501 __checkReturn int
502 sft9001_reset(
503 __in efx_nic_t *enp)
504 {
505 int state;
506
507 /* Lock I2C bus because sft9001 is sensitive to GPIO3 */
508 EFSYS_LOCK(enp->en_eslp, state);
509 EFSYS_ASSERT(!enp->en_u.falcon.enu_i2c_locked);
510 enp->en_u.falcon.enu_i2c_locked = B_TRUE;
511 EFSYS_UNLOCK(enp->en_eslp, state);
512
513 /* Pull the external reset line */
514 falcon_nic_phy_reset(enp);
515
516 /* Unlock I2C */
517 EFSYS_LOCK(enp->en_eslp, state);
518 enp->en_u.falcon.enu_i2c_locked = B_FALSE;
519 EFSYS_UNLOCK(enp->en_eslp, state);
520
521 return (0);
522 }
523
524 __checkReturn int
525 sft9001_reconfigure(
526 __in efx_nic_t *enp)
527 {
528 efx_port_t *epp = &(enp->en_port);
529 unsigned int count;
530 int rc;
531
532 /* Wait for the firmware boot to complete */
533 count = 0;
534 do {
535 efx_word_t word;
536
537 EFSYS_PROBE1(wait, unsigned int, count);
538
539 /* Spin for 1 ms */
540 EFSYS_SPIN(1000);
541
542 if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD,
543 PCS_BOOT_STATUS_REG, &word)) != 0)
544 goto fail1;
545
546 if (EFX_WORD_FIELD(word, FATAL_ERR) != 0)
547 break; /* no point in continuing */
548
549 if (EFX_WORD_FIELD(word, BOOT_STATUS) != 0 &&
550 EFX_WORD_FIELD(word, CODE_DOWNLOAD) != 0 &&
551 EFX_WORD_FIELD(word, CKSUM_OK) != 0 &&
552 EFX_WORD_FIELD(word, CODE_STARTED) != 0 &&
553 EFX_WORD_FIELD(word, BOOT_PROGRESS) == APP_JMP_DECODE)
554 goto configure;
555
556 } while (++count < 1000);
557
558 rc = ENOTACTIVE;
559 goto fail2;
560
561 configure:
562 if ((rc = xphy_pkg_wait(enp, epp->ep_port, SFT9001_MMD_MASK)) != 0)
563 goto fail3;
564
565 /* Make sure auto-negotiation is off whilst we configure the PHY */
566 if ((rc = sft9001_an_set(enp, B_FALSE)) != 0)
567 goto fail4;
568
569 if ((rc = sft9001_gmii_cfg(enp)) != 0)
570 goto fail5;
571
572 if ((rc = sft9001_clock_cfg(enp)) != 0)
573 goto fail6;
574
575 if ((rc = sft9001_adv_cap_cfg(enp)) != 0)
576 goto fail7;
577
578 #if EFSYS_OPT_LOOPBACK
579 if ((rc = sft9001_loopback_cfg(enp)) != 0)
580 goto fail8;
581 #endif /* EFSYS_OPT_LOOPBACK */
582
583 if ((rc = sft9001_led_cfg(enp)) != 0)
584 goto fail9;
585
586 if ((rc = sft9001_robust_set(enp, B_TRUE)) != 0)
587 goto fail10;
588
589 #if EFSYS_OPT_LOOPBACK
590 if (epp->ep_loopback_type == EFX_LOOPBACK_OFF) {
591 if ((rc = sft9001_an_set(enp, B_TRUE)) != 0)
592 goto fail11;
593 }
594 #else /* EFSYS_OPT_LOOPBACK */
595 if ((rc = sft9001_an_set(enp, B_TRUE)) != 0)
596 goto fail11;
597 #endif /* EFSYS_OPT_LOOPBACK */
598
599 return (0);
600
601 fail11:
602 EFSYS_PROBE(fail11);
603 fail10:
604 EFSYS_PROBE(fail10);
605 fail9:
606 EFSYS_PROBE(fail9);
607
608 #if EFSYS_OPT_LOOPBACK
609 fail8:
610 EFSYS_PROBE(fail8);
611 #endif /* EFSYS_OPT_LOOPBACK */
612
613 fail7:
614 EFSYS_PROBE(fail7);
615 fail6:
616 EFSYS_PROBE(fail6);
617 fail5:
618 EFSYS_PROBE(fail5);
619 fail4:
620 EFSYS_PROBE(fail4);
621 fail3:
622 EFSYS_PROBE(fail3);
623 fail2:
624 EFSYS_PROBE(fail2);
625 fail1:
626 EFSYS_PROBE1(fail1, int, rc);
627
628 return (rc);
629 }
630
631 __checkReturn int
632 sft9001_verify(
633 __in efx_nic_t *enp)
634 {
635 efx_port_t *epp = &(enp->en_port);
636 int rc;
637
638 if ((rc = xphy_pkg_verify(enp, epp->ep_port, SFT9001_MMD_MASK)) != 0)
639 goto fail1;
640
641 return (0);
642
643 fail1:
644 EFSYS_PROBE1(fail1, int, rc);
645
646 return (rc);
647 }
648
649 __checkReturn int
650 sft9001_uplink_check(
651 __in efx_nic_t *enp,
652 __out boolean_t *upp)
653 {
654 efx_port_t *epp = &(enp->en_port);
655 efx_word_t word;
656 int rc;
657
658 if (epp->ep_mac_type != EFX_MAC_FALCON_XMAC) {
659 rc = ENOTSUP;
660 goto fail1;
661 }
662
663 if ((rc = falcon_mdio_read(enp, epp->ep_port, PHY_XS_MMD,
664 PHY_XS_LANE_STATUS_REG, &word)) != 0)
665 goto fail2;
666
667 *upp = ((EFX_WORD_FIELD(word, PHY_XS_ALIGNED) != 0) &&
668 (EFX_WORD_FIELD(word, PHY_XS_LANE0_SYNC) != 0) &&
669 (EFX_WORD_FIELD(word, PHY_XS_LANE1_SYNC) != 0) &&
670 (EFX_WORD_FIELD(word, PHY_XS_LANE2_SYNC) != 0) &&
671 (EFX_WORD_FIELD(word, PHY_XS_LANE3_SYNC) != 0));
672
673 return (0);
674
675 fail2:
676 EFSYS_PROBE(fail2);
677 fail1:
678 EFSYS_PROBE1(fail1, int, rc);
679
680 return (rc);
681 }
682
683 static __checkReturn int
684 sft9001_lp_cap_get(
685 __in efx_nic_t *enp,
686 __out unsigned int *maskp)
687 {
688 efx_port_t *epp = &(enp->en_port);
689 efx_word_t word;
690 int rc;
691
692 *maskp = 0;
693
694 if ((rc = falcon_mdio_read(enp, epp->ep_port, AN_MMD,
695 AN_LP_BP_CAP_REG, &word)) != 0)
696 goto fail1;
697
698 if (EFX_WORD_FIELD(word, AN_LP_TA_10BASE_T) != 0)
699 *maskp |= (1 << EFX_PHY_CAP_10HDX);
700
701 if (EFX_WORD_FIELD(word, AN_LP_TA_10BASE_T_FDX) != 0)
702 *maskp |= (1 << EFX_PHY_CAP_10FDX);
703
704 if (EFX_WORD_FIELD(word, AN_LP_TA_100BASE_TX) != 0)
705 *maskp |= (1 << EFX_PHY_CAP_100HDX);
706
707 if (EFX_WORD_FIELD(word, AN_LP_TA_100BASE_TX_FDX) != 0)
708 *maskp |= (1 << EFX_PHY_CAP_100FDX);
709
710 if (EFX_WORD_FIELD(word, AN_LP_TA_PAUSE) != 0)
711 *maskp |= (1 << EFX_PHY_CAP_PAUSE);
712
713 if (EFX_WORD_FIELD(word, AN_LP_TA_ASM_DIR) != 0)
714 *maskp |= (1 << EFX_PHY_CAP_ASYM);
715
716 if ((rc = falcon_mdio_read(enp, epp->ep_port, CL22EXT_MMD,
717 CL22EXT_MS_STATUS_REG, &word)) != 0)
718 goto fail2;
719
720 if (EFX_WORD_FIELD(word, CL22EXT_1000BASE_T_LP) != 0)
721 *maskp |= (1 << EFX_PHY_CAP_1000HDX);
722
723 if (EFX_WORD_FIELD(word, CL22EXT_1000BASE_T_FDX_LP) != 0)
724 *maskp |= (1 << EFX_PHY_CAP_1000FDX);
725
726 if ((rc = falcon_mdio_read(enp, epp->ep_port, AN_MMD,
727 AN_10G_BASE_T_STATUS_REG, &word)) != 0)
728 goto fail3;
729
730 if (EFX_WORD_FIELD(word, AN_10G_BASE_T_LP) != 0)
731 *maskp |= (1 << EFX_PHY_CAP_10000FDX);
732
733 return (0);
734
735 fail3:
736 EFSYS_PROBE(fail3);
737 fail2:
738 EFSYS_PROBE(fail2);
739 fail1:
740 EFSYS_PROBE1(fail1, int, rc);
741
742 return (rc);
743 }
744
745 __checkReturn int
746 sft9001_downlink_check(
747 __in efx_nic_t *enp,
748 __out efx_link_mode_t *modep,
749 __out unsigned int *fcntlp,
750 __out uint32_t *lp_cap_maskp)
751 {
752 efx_port_t *epp = &(enp->en_port);
753 unsigned int fcntl = epp->ep_fcntl;
754 unsigned int lp_cap_mask = epp->ep_lp_cap_mask;
755 boolean_t up;
756 uint32_t common;
757 int rc;
758
759 #if EFSYS_OPT_LOOPBACK
760 switch (epp->ep_loopback_type) {
761 case EFX_LOOPBACK_PHY_XS:
762 rc = xphy_mmd_fault(enp, epp->ep_port, &up);
763 if (rc != 0)
764 goto fail1;
765
766 *modep = (up) ? EFX_LINK_10000FDX : EFX_LINK_DOWN;
767 goto done;
768
769 case EFX_LOOPBACK_PCS:
770 case EFX_LOOPBACK_PMA_PMD:
771 rc = xphy_mmd_check(enp, epp->ep_port, PHY_XS_MMD, &up);
772 if (rc != 0)
773 goto fail1;
774
775 *modep = (up) ? EFX_LINK_10000FDX : EFX_LINK_DOWN;
776 goto done;
777
778 case EFX_LOOPBACK_GPHY:
779 *modep = EFX_LINK_1000FDX;
780 goto done;
781
782 default:
783 break;
784 }
785 #endif /* EFSYS_OPT_LOOPBACK */
786
787 if ((rc = xphy_mmd_check(enp, epp->ep_port, AN_MMD, &up)) != 0)
788 goto fail1;
789
790 if (!up) {
791 *modep = EFX_LINK_DOWN;
792 goto done;
793 }
794
795 /* Check the link partner capabilities */
796 if ((rc = sft9001_lp_cap_get(enp, &lp_cap_mask)) != 0)
797 goto fail2;
798
799 /* Resolve the common capabilities */
800 common = epp->ep_adv_cap_mask & lp_cap_mask;
801
802 /* The 'best' common link mode should be the one in operation */
803 if (common & (1 << EFX_PHY_CAP_10000FDX)) {
804 *modep = EFX_LINK_10000FDX;
805 } else if (common & (1 << EFX_PHY_CAP_1000FDX)) {
806 *modep = EFX_LINK_1000FDX;
807 } else if (common & (1 << EFX_PHY_CAP_100FDX)) {
808 *modep = EFX_LINK_100FDX;
809 } else if (common & (1 << EFX_PHY_CAP_100HDX)) {
810 *modep = EFX_LINK_100HDX;
811 } else {
812 *modep = EFX_LINK_UNKNOWN;
813 }
814
815 /* Determine negotiated or forced flow control mode */
816 fcntl = 0;
817 if (epp->ep_fcntl_autoneg) {
818 if (common & (1 << EFX_PHY_CAP_PAUSE))
819 fcntl = EFX_FCNTL_GENERATE | EFX_FCNTL_RESPOND;
820 else if (common & (1 << EFX_PHY_CAP_ASYM)) {
821 if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_PAUSE))
822 fcntl = EFX_FCNTL_RESPOND;
823 else if (lp_cap_mask & (1 << EFX_PHY_CAP_PAUSE))
824 fcntl = EFX_FCNTL_GENERATE;
825 }
826 } else {
827 if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_PAUSE))
828 fcntl = EFX_FCNTL_GENERATE | EFX_FCNTL_RESPOND;
829 if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_ASYM))
830 fcntl ^= EFX_FCNTL_GENERATE;
831 }
832
833 done:
834 *fcntlp = fcntl;
835 *lp_cap_maskp = lp_cap_mask;
836
837 return (0);
838
839 fail2:
840 EFSYS_PROBE(fail2);
841 fail1:
842 EFSYS_PROBE1(fail1, int, rc);
843
844 return (rc);
845 }
846
847 __checkReturn int
848 sft9001_oui_get(
849 __in efx_nic_t *enp,
850 __out uint32_t *ouip)
851 {
852 efx_port_t *epp = &(enp->en_port);
853 int rc;
854
855 if ((rc = xphy_mmd_oui_get(enp, epp->ep_port, PMA_PMD_MMD, ouip)) != 0)
856 goto fail1;
857
858 return (0);
859
860 fail1:
861 EFSYS_PROBE1(fail1, int, rc);
862
863 return (rc);
864 }
865
866 #define SFT9001_STAT_SET(_stat, _mode, _id, _val) \
867 do { \
868 (_mode) |= (1 << (_id)); \
869 (_stat)[_id] = (uint32_t)(_val); \
870 _NOTE(CONSTANTCONDITION) \
871 } while (B_FALSE)
872
873 static __checkReturn int
874 sft9001_rev_get(
875 __in efx_nic_t *enp,
876 __out uint8_t *ap,
877 __out uint8_t *bp,
878 __out uint8_t *cp,
879 __out uint8_t *dp)
880 {
881 efx_port_t *epp = &(enp->en_port);
882 efx_word_t word;
883 int rc;
884
885 if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD,
886 PMA_PMD_FW_REV0_REG, &word)) != 0)
887 goto fail1;
888
889 *ap = (uint8_t)EFX_WORD_FIELD(word, EFX_BYTE_1);
890 *bp = (uint8_t)EFX_WORD_FIELD(word, EFX_BYTE_0);
891
892 if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD,
893 PMA_PMD_FW_REV1_REG, &word)) != 0)
894 goto fail2;
895
896 *cp = (uint8_t)EFX_WORD_FIELD(word, EFX_BYTE_1);
897 *dp = (uint8_t)EFX_WORD_FIELD(word, EFX_BYTE_0);
898
899 return (0);
900
901 fail2:
902 EFSYS_PROBE(fail2);
903 fail1:
904 EFSYS_PROBE1(fail1, int, rc);
905
906 return (rc);
907 }
908
909 #if EFSYS_OPT_PHY_STATS
910
911 static __checkReturn int
912 sft9001_pma_pmd_stats_update(
913 __in efx_nic_t *enp,
914 __inout uint64_t *maskp,
915 __inout_ecount(EFX_PHY_NSTATS) uint32_t *stat)
916 {
917 efx_port_t *epp = &(enp->en_port);
918 efx_word_t word;
919 uint8_t a;
920 uint8_t b;
921 uint8_t c;
922 uint8_t d;
923 int rc;
924
925 if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD,
926 PMA_PMD_STATUS1_REG, &word)) != 0)
927 goto fail1;
928
929 SFT9001_STAT_SET(stat, *maskp, EFX_PHY_STAT_PMA_PMD_LINK_UP,
930 (EFX_WORD_FIELD(word, PMA_PMD_LINK_UP) != 0) ? 1 : 0);
931
932 if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD,
933 PMA_PMD_STATUS2_REG, &word)) != 0)
934 goto fail2;
935
936 SFT9001_STAT_SET(stat, *maskp, EFX_PHY_STAT_PMA_PMD_RX_FAULT,
937 (EFX_WORD_FIELD(word, PMA_PMD_RX_FAULT) != 0) ? 1 : 0);
938 SFT9001_STAT_SET(stat, *maskp, EFX_PHY_STAT_PMA_PMD_TX_FAULT,
939 (EFX_WORD_FIELD(word, PMA_PMD_TX_FAULT) != 0) ? 1 : 0);
940
941 if ((rc = sft9001_rev_get(enp, &a, &b, &c, &d)) != 0)
942 goto fail3;
943
944 SFT9001_STAT_SET(stat, *maskp, EFX_PHY_STAT_PMA_PMD_REV_A, a);
945 SFT9001_STAT_SET(stat, *maskp, EFX_PHY_STAT_PMA_PMD_REV_B, b);
946 SFT9001_STAT_SET(stat, *maskp, EFX_PHY_STAT_PMA_PMD_REV_C, c);
947 SFT9001_STAT_SET(stat, *maskp, EFX_PHY_STAT_PMA_PMD_REV_D, d);
948
949 if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD,
950 PMA_PMD_CHANNELA_SNR_REG, &word)) != 0)
951 goto fail4;
952
953 SFT9001_STAT_SET(stat, *maskp, EFX_PHY_STAT_SNR_A,
954 EFX_WORD_FIELD(word, PMA_PMD_SNR));
955
956 if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD,
957 PMA_PMD_CHANNELB_SNR_REG, &word)) != 0)
958 goto fail5;
959
960 SFT9001_STAT_SET(stat, *maskp, EFX_PHY_STAT_SNR_B,
961 EFX_WORD_FIELD(word, PMA_PMD_SNR));
962
963 if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD,
964 PMA_PMD_CHANNELC_SNR_REG, &word)) != 0)
965 goto fail6;
966
967 SFT9001_STAT_SET(stat, *maskp, EFX_PHY_STAT_SNR_C,
968 EFX_WORD_FIELD(word, PMA_PMD_SNR));
969
970 if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD,
971 PMA_PMD_CHANNELD_SNR_REG, &word)) != 0)
972 goto fail7;
973
974 SFT9001_STAT_SET(stat, *maskp, EFX_PHY_STAT_SNR_D,
975 EFX_WORD_FIELD(word, PMA_PMD_SNR));
976
977 return (0);
978
979 fail7:
980 EFSYS_PROBE(fail7);
981 fail6:
982 EFSYS_PROBE(fail6);
983 fail5:
984 EFSYS_PROBE(fail5);
985 fail4:
986 EFSYS_PROBE(fail4);
987 fail3:
988 EFSYS_PROBE(fail3);
989 fail2:
990 EFSYS_PROBE(fail2);
991 fail1:
992 EFSYS_PROBE1(fail1, int, rc);
993
994 return (rc);
995 }
996
997 static __checkReturn int
998 sft9001_pcs_stats_update(
999 __in efx_nic_t *enp,
1000 __inout uint64_t *maskp,
1001 __inout_ecount(EFX_PHY_NSTATS) uint32_t *stat)
1002 {
1003 efx_port_t *epp = &(enp->en_port);
1004 efx_word_t word;
1005 int rc;
1006
1007 if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD,
1008 PCS_STATUS1_REG, &word)) != 0)
1009 goto fail1;
1010
1011 SFT9001_STAT_SET(stat, *maskp, EFX_PHY_STAT_PCS_LINK_UP,
1012 (EFX_WORD_FIELD(word, PCS_LINK_UP) != 0) ? 1 : 0);
1013
1014 if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD,
1015 PCS_STATUS2_REG, &word)) != 0)
1016 goto fail2;
1017
1018 SFT9001_STAT_SET(stat, *maskp, EFX_PHY_STAT_PCS_RX_FAULT,
1019 (EFX_WORD_FIELD(word, PCS_RX_FAULT) != 0) ? 1 : 0);
1020 SFT9001_STAT_SET(stat, *maskp, EFX_PHY_STAT_PCS_TX_FAULT,
1021 (EFX_WORD_FIELD(word, PCS_TX_FAULT) != 0) ? 1 : 0);
1022
1023 if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD,
1024 PCS_10GBASE_T_STATUS2_REG, &word)) != 0)
1025 goto fail3;
1026
1027 SFT9001_STAT_SET(stat, *maskp, EFX_PHY_STAT_PCS_BER,
1028 EFX_WORD_FIELD(word, PCS_BER));
1029 SFT9001_STAT_SET(stat, *maskp, EFX_PHY_STAT_PCS_BLOCK_ERRORS,
1030 EFX_WORD_FIELD(word, PCS_ERR));
1031
1032 return (0);
1033
1034 fail3:
1035 EFSYS_PROBE(fail3);
1036 fail2:
1037 EFSYS_PROBE(fail2);
1038 fail1:
1039 EFSYS_PROBE1(fail1, int, rc);
1040
1041 return (rc);
1042 }
1043
1044 static __checkReturn int
1045 sft9001_phy_xs_stats_update(
1046 __in efx_nic_t *enp,
1047 __inout uint64_t *maskp,
1048 __inout_ecount(EFX_PHY_NSTATS) uint32_t *stat)
1049 {
1050 efx_port_t *epp = &(enp->en_port);
1051 efx_word_t word;
1052 int rc;
1053
1054 if ((rc = falcon_mdio_read(enp, epp->ep_port, PHY_XS_MMD,
1055 PHY_XS_STATUS1_REG, &word)) != 0)
1056 goto fail1;
1057
1058 SFT9001_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_LINK_UP,
1059 (EFX_WORD_FIELD(word, PHY_XS_LINK_UP) != 0) ? 1 : 0);
1060
1061 if ((rc = falcon_mdio_read(enp, epp->ep_port, PHY_XS_MMD,
1062 PHY_XS_STATUS2_REG, &word)) != 0)
1063 goto fail2;
1064
1065 SFT9001_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_RX_FAULT,
1066 (EFX_WORD_FIELD(word, PHY_XS_RX_FAULT) != 0) ? 1 : 0);
1067 SFT9001_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_TX_FAULT,
1068 (EFX_WORD_FIELD(word, PHY_XS_TX_FAULT) != 0) ? 1 : 0);
1069
1070 if ((rc = falcon_mdio_read(enp, epp->ep_port, PHY_XS_MMD,
1071 PHY_XS_LANE_STATUS_REG, &word)) != 0)
1072 goto fail3;
1073
1074 SFT9001_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_ALIGN,
1075 (EFX_WORD_FIELD(word, PHY_XS_ALIGNED) != 0) ? 1 : 0);
1076 SFT9001_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_SYNC_A,
1077 (EFX_WORD_FIELD(word, PHY_XS_LANE0_SYNC) != 0) ? 1 : 0);
1078 SFT9001_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_SYNC_B,
1079 (EFX_WORD_FIELD(word, PHY_XS_LANE1_SYNC) != 0) ? 1 : 0);
1080 SFT9001_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_SYNC_C,
1081 (EFX_WORD_FIELD(word, PHY_XS_LANE2_SYNC) != 0) ? 1 : 0);
1082 SFT9001_STAT_SET(stat, *maskp, EFX_PHY_STAT_PHY_XS_SYNC_D,
1083 (EFX_WORD_FIELD(word, PHY_XS_LANE3_SYNC) != 0) ? 1 : 0);
1084
1085 return (0);
1086
1087 fail3:
1088 EFSYS_PROBE(fail3);
1089 fail2:
1090 EFSYS_PROBE(fail2);
1091 fail1:
1092 EFSYS_PROBE1(fail1, int, rc);
1093
1094 return (rc);
1095 }
1096
1097 static __checkReturn int
1098 sft9001_an_stats_update(
1099 __in efx_nic_t *enp,
1100 __inout uint64_t *maskp,
1101 __inout_ecount(EFX_PHY_NSTATS) uint32_t *stat)
1102 {
1103 efx_port_t *epp = &(enp->en_port);
1104 efx_word_t word;
1105 int rc;
1106
1107 if ((rc = falcon_mdio_read(enp, epp->ep_port, AN_MMD,
1108 AN_STATUS1_REG, &word)) != 0)
1109 goto fail1;
1110
1111 SFT9001_STAT_SET(stat, *maskp, EFX_PHY_STAT_AN_LINK_UP,
1112 (EFX_WORD_FIELD(word, AN_LINK_UP) != 0) ? 1 : 0);
1113
1114 if ((rc = falcon_mdio_read(enp, epp->ep_port, AN_MMD,
1115 AN_10G_BASE_T_STATUS_REG, &word)) != 0)
1116 goto fail2;
1117
1118 SFT9001_STAT_SET(stat, *maskp, EFX_PHY_STAT_AN_MASTER,
1119 (EFX_WORD_FIELD(word, AN_MASTER) != 0) ? 1 : 0);
1120 SFT9001_STAT_SET(stat, *maskp, EFX_PHY_STAT_AN_LOCAL_RX_OK,
1121 (EFX_WORD_FIELD(word, AN_LOCAL_RX_OK) != 0) ? 1 : 0);
1122 SFT9001_STAT_SET(stat, *maskp, EFX_PHY_STAT_AN_REMOTE_RX_OK,
1123 (EFX_WORD_FIELD(word, AN_REMOTE_RX_OK) != 0) ? 1 : 0);
1124
1125 return (0);
1126
1127 fail2:
1128 EFSYS_PROBE(fail2);
1129 fail1:
1130 EFSYS_PROBE1(fail1, int, rc);
1131
1132 return (rc);
1133 }
1134
1135 static __checkReturn int
1136 sft9001_cl22ext_stats_update(
1137 __in efx_nic_t *enp,
1138 __inout uint64_t *maskp,
1139 __inout_ecount(EFX_PHY_NSTATS) uint32_t *stat)
1140 {
1141 efx_port_t *epp = &(enp->en_port);
1142 efx_word_t word;
1143 int rc;
1144
1145 if ((rc = falcon_mdio_read(enp, epp->ep_port, CL22EXT_MMD,
1146 CL22EXT_STATUS_REG, &word)) != 0)
1147 goto fail1;
1148
1149 SFT9001_STAT_SET(stat, *maskp, EFX_PHY_STAT_CL22EXT_LINK_UP,
1150 (EFX_WORD_FIELD(word, CL22EXT_LINK_UP) != 0) ? 1 : 0);
1151
1152 return (0);
1153
1154 fail1:
1155 EFSYS_PROBE1(fail1, int, rc);
1156
1157 return (rc);
1158 }
1159
1160
1161 __checkReturn int
1162 sft9001_stats_update(
1163 __in efx_nic_t *enp,
1164 __in efsys_mem_t *esmp,
1165 __out_ecount(EFX_PHY_NSTATS) uint32_t *stat)
1166 {
1167 efx_port_t *epp = &(enp->en_port);
1168 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
1169 uint64_t mask = 0;
1170 uint32_t oui;
1171 int rc;
1172
1173 _NOTE(ARGUNUSED(esmp))
1174
1175 if ((rc = xphy_mmd_oui_get(enp, epp->ep_port, PMA_PMD_MMD, &oui)) != 0)
1176 goto fail1;
1177
1178 SFT9001_STAT_SET(stat, mask, EFX_PHY_STAT_OUI, oui);
1179
1180 if ((rc = sft9001_pma_pmd_stats_update(enp, &mask, stat)) != 0)
1181 goto fail2;
1182
1183 if ((rc = sft9001_pcs_stats_update(enp, &mask, stat)) != 0)
1184 goto fail3;
1185
1186 if ((rc = sft9001_phy_xs_stats_update(enp, &mask, stat)) != 0)
1187 goto fail4;
1188
1189 if ((rc = sft9001_an_stats_update(enp, &mask, stat)) != 0)
1190 goto fail5;
1191
1192 if ((rc = sft9001_cl22ext_stats_update(enp, &mask, stat)) != 0)
1193 goto fail6;
1194
1195 /* Ensure all the supported statistics are up to date */
1196 EFSYS_ASSERT(mask == encp->enc_phy_stat_mask);
1197
1198 return (0);
1199
1200 fail6:
1201 EFSYS_PROBE(fail6);
1202 fail5:
1203 EFSYS_PROBE(fail5);
1204 fail4:
1205 EFSYS_PROBE(fail4);
1206 fail3:
1207 EFSYS_PROBE(fail3);
1208 fail2:
1209 EFSYS_PROBE(fail2);
1210 fail1:
1211 EFSYS_PROBE1(fail1, int, rc);
1212
1213 return (rc);
1214 }
1215 #endif /* EFSYS_OPT_PHY_STATS */
1216
1217 #if EFSYS_OPT_PHY_PROPS
1218
1219 #if EFSYS_OPT_NAMES
1220 /* START MKCONFIG GENERATED Sft9001PhyPropNamesBlock 575ed5e718aa4657 */
1221 static const char __cs * __cs __sft9001_prop_name[] = {
1222 "short_reach",
1223 "robust",
1224 };
1225
1226 /* END MKCONFIG GENERATED Sft9001PhyPropNamesBlock */
1227
1228 const char __cs *
1229 sft9001_prop_name(
1230 __in efx_nic_t *enp,
1231 __in unsigned int id)
1232 {
1233 _NOTE(ARGUNUSED(enp))
1234
1235 EFSYS_ASSERT3U(id, <, SFT9001_NPROPS);
1236
1237 return (__sft9001_prop_name[id]);
1238 }
1239 #endif /* EFSYS_OPT_NAMES */
1240
1241 __checkReturn int
1242 sft9001_prop_get(
1243 __in efx_nic_t *enp,
1244 __in unsigned int id,
1245 __in uint32_t flags,
1246 __out uint32_t *valp)
1247 {
1248 uint32_t val;
1249 int rc;
1250
1251 switch (id) {
1252 case SFT9001_SHORT_REACH: {
1253 boolean_t on;
1254
1255 if (flags * EFX_PHY_PROP_DEFAULT) {
1256 val = 0;
1257 break;
1258 }
1259
1260 if ((rc = sft9001_short_reach_get(enp, &on)) != 0)
1261 goto fail1;
1262
1263 val = (on) ? 1 : 0;
1264 break;
1265 }
1266 case SFT9001_ROBUST: {
1267 boolean_t on;
1268
1269 if (flags * EFX_PHY_PROP_DEFAULT) {
1270 val = 0;
1271 break;
1272 }
1273
1274 if ((rc = sft9001_robust_get(enp, &on)) != 0)
1275 goto fail1;
1276
1277 val = (on) ? 1 : 0;
1278 break;
1279 }
1280 default:
1281 EFSYS_ASSERT(B_FALSE);
1282
1283 val = 0;
1284 break;
1285 }
1286
1287 *valp = val;
1288 return (0);
1289
1290 fail1:
1291 EFSYS_PROBE1(fail1, int, rc);
1292
1293 return (rc);
1294 }
1295
1296 __checkReturn int
1297 sft9001_prop_set(
1298 __in efx_nic_t *enp,
1299 __in unsigned int id,
1300 __in uint32_t val)
1301 {
1302 efx_port_t *epp = &(enp->en_port);
1303 int rc;
1304
1305 switch (id) {
1306 case SFT9001_SHORT_REACH:
1307 if ((rc = sft9001_an_set(enp, B_FALSE)) != 0)
1308 goto fail1;
1309
1310 if ((rc = sft9001_short_reach_set(enp, (val != 0))) != 0)
1311 goto fail2;
1312
1313 #if EFSYS_OPT_LOOPBACK
1314 if (epp->ep_loopback_type == EFX_LOOPBACK_OFF) {
1315 if ((rc = sft9001_an_set(enp, B_TRUE)) != 0)
1316 goto fail3;
1317 }
1318 #else /* EFSYS_OPT_LOOPBACK */
1319 if ((rc = sft9001_an_set(enp, B_TRUE)) != 0)
1320 goto fail3;
1321 #endif /* EFSYS_OPT_LOOPBACK */
1322
1323 break;
1324
1325 case SFT9001_ROBUST:
1326 if ((rc = sft9001_an_set(enp, B_FALSE)) != 0)
1327 goto fail1;
1328
1329 if ((rc = sft9001_robust_set(enp, (val != 0))) != 0)
1330 goto fail2;
1331
1332 #if EFSYS_OPT_LOOPBACK
1333 if (epp->ep_loopback_type == EFX_LOOPBACK_OFF) {
1334 if ((rc = sft9001_an_set(enp, B_TRUE)) != 0)
1335 goto fail3;
1336 }
1337 #else /* EFSYS_OPT_LOOPBACK */
1338 if ((rc = sft9001_an_set(enp, B_TRUE)) != 0)
1339 goto fail3;
1340 #endif /* EFSYS_OPT_LOOPBACK */
1341
1342 break;
1343
1344 default:
1345 EFSYS_ASSERT(B_FALSE);
1346 break;
1347 }
1348
1349 return (0);
1350
1351 fail3:
1352 EFSYS_PROBE(fail3);
1353 fail2:
1354 EFSYS_PROBE(fail2);
1355 fail1:
1356 EFSYS_PROBE1(fail1, int, rc);
1357
1358 return (rc);
1359 }
1360 #endif /* EFSYS_OPT_PHY_PROPS */
1361
1362 #if EFSYS_OPT_NVRAM_SFT9001
1363
1364 static __checkReturn int
1365 sft9001_ssr(
1366 __in efx_nic_t *enp,
1367 __in boolean_t loader)
1368 {
1369 efx_port_t *epp = &(enp->en_port);
1370 efx_oword_t oword;
1371 efx_word_t word;
1372 int state;
1373 int rc;
1374
1375 EFSYS_LOCK(enp->en_eslp, state);
1376
1377 /* Lock I2C bus and pull GPIO(3) low */
1378 EFSYS_ASSERT(!enp->en_u.falcon.enu_i2c_locked);
1379 enp->en_u.falcon.enu_i2c_locked = B_TRUE;
1380
1381 EFX_BAR_READO(enp, FR_AB_GPIO_CTL_REG, &oword);
1382 EFX_SET_OWORD_FIELD(oword, FRF_AB_GPIO3_OEN, loader ? 1 : 0);
1383 EFX_SET_OWORD_FIELD(oword, FRF_AB_GPIO3_OUT, 0);
1384 EFX_BAR_WRITEO(enp, FR_AB_GPIO_CTL_REG, &oword);
1385
1386 EFSYS_UNLOCK(enp->en_eslp, state);
1387
1388 /* Special software reset */
1389 if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD,
1390 PMA_PMD_XCONTROL_REG, &word)) != 0)
1391 goto fail1;
1392 EFX_SET_WORD_FIELD(word, SSR, 1);
1393 if ((rc = falcon_mdio_write(enp, epp->ep_port, PMA_PMD_MMD,
1394 PMA_PMD_XCONTROL_REG, &word)) != 0)
1395 goto fail2;
1396
1397 /* Sleep for 500ms */
1398 EFSYS_SLEEP(500000);
1399
1400 goto out;
1401
1402 fail2:
1403 EFSYS_PROBE(fail2);
1404 fail1:
1405 EFSYS_PROBE1(fail1, int, rc);
1406
1407 out:
1408 /* Unlock the I2C bus and restore GPIO(3) */
1409 EFSYS_LOCK(enp->en_eslp, state);
1410 enp->en_u.falcon.enu_i2c_locked = B_FALSE;
1411
1412 EFX_BAR_READO(enp, FR_AB_GPIO_CTL_REG, &oword);
1413 EFX_SET_OWORD_FIELD(oword, FRF_AB_GPIO3_OEN, 0);
1414 EFX_BAR_WRITEO(enp, FR_AB_GPIO_CTL_REG, &oword);
1415
1416 EFSYS_UNLOCK(enp->en_eslp, state);
1417
1418 return (rc);
1419 }
1420
1421 static __checkReturn int
1422 sft9001_loader_wait(
1423 __in efx_nic_t *enp)
1424 {
1425 efx_port_t *epp = &(enp->en_port);
1426 efx_word_t word;
1427 unsigned int count;
1428 unsigned int response;
1429 int rc;
1430
1431 /* Wait up to 20s for the command to complete */
1432 for (count = 0; count < 200; count++) {
1433 EFSYS_SLEEP(100000); /* 100ms */
1434
1435 if ((rc = falcon_mdio_read(enp, epp->ep_port, LOADER_MMD,
1436 LOADER_CMD_RESPONSE_REG, &word)) != 0)
1437 goto fail1;
1438
1439 response = EFX_WORD_FIELD(word, EFX_WORD_0);
1440 if (response == LOADER_RESPONSE_OK)
1441 return (0);
1442 if (response != LOADER_RESPONSE_BUSY) {
1443 rc = EIO;
1444 goto fail2;
1445 }
1446 }
1447
1448 rc = ETIMEDOUT;
1449
1450 EFSYS_PROBE(fail3);
1451 fail2:
1452 EFSYS_PROBE(fail2);
1453 fail1:
1454 EFSYS_PROBE1(fail1, int, rc);
1455
1456 return (rc);
1457 }
1458
1459 static __checkReturn int
1460 sft9001_program_loader(
1461 __in efx_nic_t *enp,
1462 __in unsigned int offset,
1463 __in size_t words)
1464 {
1465 efx_port_t *epp = &(enp->en_port);
1466 efx_word_t word;
1467 int rc;
1468
1469 /* Setup address of block transfer */
1470 EFX_POPULATE_WORD_1(word, EFX_WORD_0, offset);
1471 if ((rc = falcon_mdio_write(enp, epp->ep_port, LOADER_MMD,
1472 LOADER_FLASH_ADDR_LOW_REG, &word)) != 0)
1473 goto fail1;
1474
1475 EFX_POPULATE_WORD_1(word, EFX_WORD_0, (offset >> 16));
1476 if ((rc = falcon_mdio_write(enp, epp->ep_port, LOADER_MMD,
1477 LOADER_FLASH_ADDR_HI_REG, &word)) != 0)
1478 goto fail2;
1479
1480 EFX_POPULATE_WORD_1(word, EFX_WORD_0, words);
1481 if ((rc = falcon_mdio_write(enp, epp->ep_port, LOADER_MMD,
1482 LOADER_ACTUAL_BUFF_SZ_REG, &word)) != 0)
1483 goto fail3;
1484
1485 return (0);
1486
1487 fail3:
1488 EFSYS_PROBE(fail3);
1489 fail2:
1490 EFSYS_PROBE(fail2);
1491 fail1:
1492 EFSYS_PROBE1(fail1, int, rc);
1493
1494 return (rc);
1495 }
1496
1497 __checkReturn int
1498 sft9001_nvram_size(
1499 __in efx_nic_t *enp,
1500 __out size_t *sizep)
1501 {
1502 _NOTE(ARGUNUSED(enp))
1503 EFSYS_ASSERT(sizep);
1504
1505 *sizep = FIRMWARE_MAX_SIZE;
1506
1507 return (0);
1508 }
1509
1510 __checkReturn int
1511 sft9001_nvram_get_version(
1512 __in efx_nic_t *enp,
1513 __out uint32_t *subtypep,
1514 __out_ecount(4) uint16_t version[4])
1515 {
1516 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
1517 uint8_t a, b, c, d;
1518 int rc;
1519
1520 if ((rc = sft9001_rev_get(enp, &a, &b, &c, &d)) != 0)
1521 goto fail1;
1522
1523 version[0] = a;
1524 version[1] = b;
1525 version[2] = c;
1526 version[3] = d;
1527
1528 switch (encp->enc_phy_type) {
1529 case EFX_PHY_SFT9001A:
1530 *subtypep = PHY_TYPE_SFT9001A_DECODE;
1531 break;
1532 case EFX_PHY_SFT9001B:
1533 *subtypep = PHY_TYPE_SFT9001B_DECODE;
1534 break;
1535 default:
1536 EFSYS_ASSERT(0);
1537 *subtypep = 0;
1538 }
1539
1540 return (0);
1541
1542 fail1:
1543 EFSYS_PROBE1(fail1, int, rc);
1544
1545 return (0);
1546 }
1547
1548 __checkReturn int
1549 sft9001_nvram_rw_start(
1550 __in efx_nic_t *enp,
1551 __out size_t *block_sizep)
1552 {
1553 efx_port_t *epp = &(enp->en_port);
1554 sft9001_firmware_header_t header;
1555 unsigned int pos;
1556 efx_word_t word;
1557 int rc;
1558
1559 /* Reboot without starting the firmware */
1560 if ((rc = sft9001_ssr(enp, B_TRUE)) != 0)
1561 goto fail1;
1562
1563 /* Check that the C166 is idle, and in download mode */
1564 if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD,
1565 PCS_BOOT_STATUS_REG, &word)) != 0)
1566 goto fail2;
1567 if (EFX_WORD_FIELD(word, BOOT_STATUS) == 0 ||
1568 EFX_WORD_FIELD(word, BOOT_PROGRESS) != MDIO_WAIT_DECODE) {
1569 rc = ETIMEDOUT;
1570 goto fail3;
1571 }
1572
1573 /* Download loader code */
1574 EFX_ZERO_WORD(word);
1575 if ((rc = falcon_mdio_write(enp, epp->ep_port, PCS_MMD,
1576 PCS_LM_RAM_LS_ADDR_REG, &word)) != 0)
1577 goto fail4;
1578 if ((rc = falcon_mdio_write(enp, epp->ep_port, PCS_MMD,
1579 PCS_LM_RAM_MS_ADDR_REG, &word)) != 0)
1580 goto fail5;
1581 for (pos = 0; pos < sft9001_loader_size / sizeof (uint16_t); pos++) {
1582 /* Firmware is little endian */
1583 word.ew_u8[0] = sft9001_loader[pos];
1584 word.ew_u8[1] = sft9001_loader[pos+1];
1585 if ((rc = falcon_mdio_write(enp, epp->ep_port, PCS_MMD,
1586 PCS_LM_RAM_DATA_REG, &word)) != 0)
1587 goto fail6;
1588 }
1589
1590 /* Sleep for 500ms */
1591 EFSYS_SLEEP(500000);
1592
1593 /* Start downloaded code */
1594 if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD,
1595 PCS_BOOT_STATUS_REG, &word)) != 0)
1596 goto fail7;
1597 EFX_SET_WORD_FIELD(word, CODE_DOWNLOAD, 1);
1598 if ((rc = falcon_mdio_write(enp, epp->ep_port, PCS_MMD,
1599 PCS_BOOT_STATUS_REG, &word)) != 0)
1600 goto fail8;
1601
1602 /* Sleep 1s */
1603 EFSYS_SLEEP(1000000);
1604
1605 /* And check it started */
1606 if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD,
1607 PCS_BOOT_STATUS_REG, &word)) != 0)
1608 goto fail9;
1609
1610 if (EFX_WORD_FIELD(word, CODE_STARTED) == 0) {
1611 rc = ETIMEDOUT;
1612 goto fail10;
1613 }
1614
1615 /* Verify program block size is appropriate */
1616 if ((rc = falcon_mdio_read(enp, epp->ep_port, LOADER_MMD,
1617 LOADER_MAX_BUFF_SZ_REG, &word)) != 0)
1618 goto fail11;
1619 if (EFX_WORD_FIELD(word, EFX_WORD_0) < FIRMWARE_BLOCK_SIZE) {
1620 rc = EIO;
1621 goto fail12;
1622 }
1623 if (block_sizep != NULL)
1624 *block_sizep = FIRMWARE_BLOCK_SIZE;
1625
1626 /* Read firmware header */
1627 if ((rc = sft9001_nvram_read_chunk(enp, 0, (void *)&header,
1628 sizeof (header))) != 0)
1629 goto fail13;
1630
1631 /* Verify firmware isn't too large */
1632 if (EFX_DWORD_FIELD(header.code_length, EFX_DWORD_0) +
1633 sizeof (sft9001_firmware_header_t) > FIRMWARE_MAX_SIZE) {
1634 rc = EIO;
1635 goto fail14;
1636 }
1637
1638 return (0);
1639
1640 fail14:
1641 EFSYS_PROBE(fail14);
1642 fail13:
1643 EFSYS_PROBE(fail13);
1644 fail12:
1645 EFSYS_PROBE(fail12);
1646 fail11:
1647 EFSYS_PROBE(fail11);
1648 fail10:
1649 EFSYS_PROBE(fail10);
1650 fail9:
1651 EFSYS_PROBE(fail9);
1652 fail8:
1653 EFSYS_PROBE(fail8);
1654 fail7:
1655 EFSYS_PROBE(fail7);
1656 fail6:
1657 EFSYS_PROBE(fail6);
1658 fail5:
1659 EFSYS_PROBE(fail5);
1660 fail4:
1661 EFSYS_PROBE(fail4);
1662 fail3:
1663 EFSYS_PROBE(fail3);
1664 fail2:
1665 EFSYS_PROBE(fail2);
1666 fail1:
1667 EFSYS_PROBE1(fail1, int, rc);
1668
1669 /* Reboot the PHY into the main firmware */
1670 (void) sft9001_ssr(enp, B_FALSE);
1671
1672 /* Sleep for 500ms */
1673 EFSYS_SLEEP(500000);
1674
1675 return (rc);
1676 }
1677
1678 __checkReturn int
1679 sft9001_nvram_read_chunk(
1680 __in efx_nic_t *enp,
1681 __in unsigned int offset,
1682 __out_bcount(size) caddr_t data,
1683 __in size_t size)
1684 {
1685 efx_port_t *epp = &(enp->en_port);
1686 efx_word_t word;
1687 unsigned int pos;
1688 size_t chunk;
1689 size_t words;
1690 int rc;
1691
1692 while (size > 0) {
1693 chunk = MIN(size, FIRMWARE_BLOCK_SIZE);
1694
1695 /* Read in 2byte words */
1696 EFSYS_ASSERT(!(chunk & 0x1));
1697 words = chunk >> 1;
1698
1699 /* Program address/length */
1700 if ((rc = sft9001_program_loader(enp, offset, words)) != 0)
1701 goto fail1;
1702
1703 /* Select read mode, and wait for buffer to fill */
1704 EFX_POPULATE_WORD_1(word, EFX_WORD_0, LOADER_CMD_READ_FLASH);
1705 if ((rc = falcon_mdio_write(enp, epp->ep_port, LOADER_MMD,
1706 LOADER_CMD_RESPONSE_REG, &word)) != 0)
1707 goto fail2;
1708
1709 if ((rc = sft9001_loader_wait(enp)) != 0)
1710 goto fail3;
1711
1712 if ((rc = falcon_mdio_read(enp, epp->ep_port, LOADER_MMD,
1713 LOADER_WORDS_READ_REG, &word)) != 0)
1714 goto fail4;
1715
1716 if (words != (size_t)EFX_WORD_FIELD(word, EFX_WORD_0))
1717 goto fail5;
1718
1719 for (pos = 0; pos < words; ++pos) {
1720 if ((rc = falcon_mdio_read(enp, epp->ep_port,
1721 LOADER_MMD, LOADER_DATA_REG, &word)) != 0)
1722 goto fail6;
1723
1724 /* Firmware is little endian */
1725 data[pos] = word.ew_u8[0];
1726 data[pos+1] = word.ew_u8[1];
1727 }
1728
1729 size -= chunk;
1730 offset += chunk;
1731 data += chunk;
1732 }
1733
1734 return (0);
1735
1736 fail6:
1737 EFSYS_PROBE(fail6);
1738 fail5:
1739 EFSYS_PROBE(fail5);
1740 fail4:
1741 EFSYS_PROBE(fail4);
1742 fail3:
1743 EFSYS_PROBE(fail3);
1744 fail2:
1745 EFSYS_PROBE(fail2);
1746 fail1:
1747 EFSYS_PROBE1(fail1, int, rc);
1748
1749 return (rc);
1750 }
1751
1752 __checkReturn int
1753 sft9001_nvram_erase(
1754 __in efx_nic_t *enp)
1755 {
1756 efx_port_t *epp = &(enp->en_port);
1757 efx_word_t word;
1758 int rc;
1759
1760 EFX_POPULATE_WORD_1(word, EFX_BYTE_0, LOADER_CMD_ERASE_FLASH);
1761 if ((rc = falcon_mdio_write(enp, epp->ep_port,
1762 LOADER_MMD, LOADER_CMD_RESPONSE_REG, &word)) != 0)
1763 goto fail1;
1764
1765 if ((rc = sft9001_loader_wait(enp)) != 0)
1766 goto fail2;
1767
1768 return (0);
1769
1770 fail2:
1771 EFSYS_PROBE(fail2);
1772 fail1:
1773 EFSYS_PROBE1(fail1, int, rc);
1774
1775 return (rc);
1776 }
1777
1778 __checkReturn int
1779 sft9001_nvram_write_chunk(
1780 __in efx_nic_t *enp,
1781 __in unsigned int offset,
1782 __in_bcount(size) caddr_t data,
1783 __in size_t size)
1784 {
1785 efx_port_t *epp = &(enp->en_port);
1786 efx_word_t word;
1787 unsigned int pos;
1788 size_t chunk;
1789 size_t words;
1790 int rc;
1791
1792 while (size > 0) {
1793 chunk = MIN(size, FIRMWARE_BLOCK_SIZE);
1794
1795 /* Write in 2byte words */
1796 EFSYS_ASSERT(!(chunk & 0x1));
1797 words = chunk >> 1;
1798
1799 /* Program address/length */
1800 if ((rc = sft9001_program_loader(enp, offset, words)) != 0)
1801 goto fail1;
1802
1803 /* Select write mode */
1804 EFX_POPULATE_WORD_1(word, EFX_WORD_0, LOADER_CMD_FILL_BUFFER);
1805 if ((rc = falcon_mdio_write(enp, epp->ep_port, LOADER_MMD,
1806 LOADER_CMD_RESPONSE_REG, &word)) != 0)
1807 goto fail2;
1808
1809 for (pos = 0; pos < words; ++pos) {
1810 /* Firmware is little-endian */
1811 word.ew_u8[0] = data[pos];
1812 word.ew_u8[1] = data[pos+1];
1813
1814 if ((rc = falcon_mdio_write(enp, epp->ep_port,
1815 LOADER_MMD, LOADER_DATA_REG, &word)) != 0)
1816 goto fail3;
1817 }
1818
1819 EFX_POPULATE_WORD_1(word, EFX_WORD_0,
1820 LOADER_CMD_PROGRAM_FLASH);
1821 if ((rc = falcon_mdio_write(enp, epp->ep_port,
1822 LOADER_MMD, LOADER_CMD_RESPONSE_REG, &word)) != 0)
1823 goto fail4;
1824
1825 if ((rc = sft9001_loader_wait(enp)) != 0)
1826 goto fail5;
1827
1828 if ((rc = falcon_mdio_read(enp, epp->ep_port, LOADER_MMD,
1829 LOADER_WORDS_WRITTEN_REG, &word)) != 0)
1830 goto fail6;
1831
1832 if (words != EFX_WORD_FIELD(word, EFX_WORD_0))
1833 goto fail7;
1834
1835 size -= chunk;
1836 offset += chunk;
1837 data += chunk;
1838 }
1839
1840 return (0);
1841
1842 fail7:
1843 EFSYS_PROBE(fail7);
1844 fail6:
1845 EFSYS_PROBE(fail6);
1846 fail5:
1847 EFSYS_PROBE(fail5);
1848 fail4:
1849 EFSYS_PROBE(fail4);
1850 fail3:
1851 EFSYS_PROBE(fail3);
1852 fail2:
1853 EFSYS_PROBE(fail2);
1854 fail1:
1855 EFSYS_PROBE1(fail1, int, rc);
1856
1857 return (rc);
1858 }
1859
1860 void
1861 sft9001_nvram_rw_finish(
1862 __in efx_nic_t *enp)
1863 {
1864 efx_port_t *epp = &(enp->en_port);
1865 efx_word_t word;
1866 int rc;
1867
1868 /* Reboot the PHY into the main firmware */
1869 if ((rc = sft9001_ssr(enp, B_FALSE)) != 0)
1870 goto fail1;
1871
1872 /* Sleep for 500ms */
1873 EFSYS_SLEEP(500000);
1874
1875 /* Verify that PHY rebooted */
1876 if ((rc = falcon_mdio_read(enp, epp->ep_port, PCS_MMD,
1877 PCS_BOOT_STATUS_REG, &word)) != 0)
1878 goto fail2;
1879 if (EFX_WORD_FIELD(word, EFX_WORD_0) != 0x7E)
1880 goto fail3;
1881
1882 return;
1883
1884 fail3:
1885 EFSYS_PROBE(fail3);
1886 fail2:
1887 EFSYS_PROBE(fail2);
1888 fail1:
1889 EFSYS_PROBE1(fail1, int, rc);
1890 }
1891
1892 #endif /* EFSYS_OPT_NVRAM_SFT9001 */
1893
1894 #if EFSYS_OPT_PHY_BIST
1895
1896 __checkReturn int
1897 sft9001_bist_start(
1898 __in efx_nic_t *enp,
1899 __in efx_phy_bist_type_t type)
1900 {
1901 efx_port_t *epp = &(enp->en_port);
1902 boolean_t break_link = (type == EFX_PHY_BIST_TYPE_CABLE_LONG);
1903 efx_word_t word;
1904 int rc;
1905
1906 if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD,
1907 PMA_PMD_DIAG_CONTROL_REG, &word)) != 0)
1908 goto fail1;
1909
1910 if (EFX_WORD_FIELD(word, DIAG_RUNNING) != 0) {
1911 rc = EBUSY;
1912 goto fail2;
1913 }
1914
1915 EFX_POPULATE_WORD_3(word,
1916 RUN_DIAG_IMMED, 1,
1917 LENGTH_UNIT, LENGTH_M_DECODE,
1918 BREAK_LINK, break_link ? 1 : 0);
1919 if ((rc = falcon_mdio_write(enp, epp->ep_port, PMA_PMD_MMD,
1920 PMA_PMD_DIAG_CONTROL_REG, &word)) != 0)
1921 goto fail3;
1922
1923 return (0);
1924
1925 fail3:
1926 EFSYS_PROBE(fail3);
1927 fail2:
1928 EFSYS_PROBE(fail2);
1929 fail1:
1930 EFSYS_PROBE1(fail1, int, rc);
1931
1932 return (rc);
1933 }
1934
1935 static efx_phy_cable_status_t
1936 sft9001_bist_status(
1937 __in uint16_t code)
1938 {
1939 switch (code) {
1940 case PAIR_BUSY_DECODE:
1941 return (EFX_PHY_CABLE_STATUS_BUSY);
1942 case INTER_PAIR_SHORT_DECODE:
1943 return (EFX_PHY_CABLE_STATUS_INTERPAIRSHORT);
1944 case INTRA_PAIR_SHORT_DECODE:
1945 return (EFX_PHY_CABLE_STATUS_INTRAPAIRSHORT);
1946 case PAIR_OPEN_DECODE:
1947 return (EFX_PHY_CABLE_STATUS_OPEN);
1948 case PAIR_OK_DECODE:
1949 return (EFX_PHY_CABLE_STATUS_OK);
1950 default:
1951 return (EFX_PHY_CABLE_STATUS_INVALID);
1952 }
1953 }
1954
1955 __checkReturn int
1956 sft9001_bist_poll(
1957 __in efx_nic_t *enp,
1958 __in efx_phy_bist_type_t type,
1959 __out efx_phy_bist_result_t *resultp,
1960 __out_opt uint32_t *value_maskp,
1961 __out_ecount_opt(count) unsigned long *valuesp,
1962 __in size_t count)
1963 {
1964 efx_port_t *epp = &(enp->en_port);
1965 uint32_t value_mask = 0;
1966 efx_word_t word;
1967 int rc;
1968
1969 _NOTE(ARGUNUSED(type))
1970
1971 *resultp = EFX_PHY_BIST_RESULT_UNKNOWN;
1972
1973 if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD,
1974 PMA_PMD_DIAG_CONTROL_REG, &word)) != 0)
1975 goto fail1;
1976
1977 if (EFX_WORD_FIELD(word, DIAG_RUNNING)) {
1978 *resultp = EFX_PHY_BIST_RESULT_RUNNING;
1979 return (0);
1980 }
1981
1982 if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD,
1983 PMA_PMD_DIAG_RESULT_REG, &word)) != 0)
1984 goto fail2;
1985
1986 *resultp = EFX_PHY_BIST_RESULT_PASSED;
1987
1988 if (count > EFX_PHY_BIST_CABLE_STATUS_A) {
1989 valuesp[EFX_PHY_BIST_CABLE_STATUS_A] =
1990 sft9001_bist_status(EFX_WORD_FIELD(word, PAIR_A_CODE));
1991 value_mask |= (1 << EFX_PHY_BIST_CABLE_STATUS_A);
1992 }
1993 if (count > EFX_PHY_BIST_CABLE_STATUS_B) {
1994 valuesp[EFX_PHY_BIST_CABLE_STATUS_B] =
1995 sft9001_bist_status(EFX_WORD_FIELD(word, PAIR_B_CODE));
1996 value_mask |= (1 << EFX_PHY_BIST_CABLE_STATUS_B);
1997 }
1998 if (count > EFX_PHY_BIST_CABLE_STATUS_C) {
1999 valuesp[EFX_PHY_BIST_CABLE_STATUS_C] =
2000 sft9001_bist_status(EFX_WORD_FIELD(word, PAIR_C_CODE));
2001 value_mask |= (1 << EFX_PHY_BIST_CABLE_STATUS_C);
2002 }
2003 if (count > EFX_PHY_BIST_CABLE_STATUS_D) {
2004 valuesp[EFX_PHY_BIST_CABLE_STATUS_D] =
2005 sft9001_bist_status(EFX_WORD_FIELD(word, PAIR_D_CODE));
2006 value_mask |= (1 << EFX_PHY_BIST_CABLE_STATUS_D);
2007 }
2008
2009 if (count > EFX_PHY_BIST_CABLE_LENGTH_A) {
2010 if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD,
2011 PMA_PMD_DIAG_A_LENGTH_REG, &word)) != 0)
2012 goto fail3;
2013 valuesp[EFX_PHY_BIST_CABLE_LENGTH_A] =
2014 EFX_WORD_FIELD(word, EFX_WORD_0);
2015 value_mask |= (1 << EFX_PHY_BIST_CABLE_LENGTH_A);
2016 }
2017 if (count > EFX_PHY_BIST_CABLE_LENGTH_B) {
2018 if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD,
2019 PMA_PMD_DIAG_B_LENGTH_REG, &word)) != 0)
2020 goto fail4;
2021 valuesp[EFX_PHY_BIST_CABLE_LENGTH_B] =
2022 EFX_WORD_FIELD(word, EFX_WORD_0);
2023 value_mask |= (1 << EFX_PHY_BIST_CABLE_LENGTH_B);
2024 }
2025 if (count > EFX_PHY_BIST_CABLE_LENGTH_C) {
2026 if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD,
2027 PMA_PMD_DIAG_C_LENGTH_REG, &word)) != 0)
2028 goto fail5;
2029 valuesp[EFX_PHY_BIST_CABLE_LENGTH_C] =
2030 EFX_WORD_FIELD(word, EFX_WORD_0);
2031 value_mask |= (1 << EFX_PHY_BIST_CABLE_LENGTH_C);
2032 }
2033 if (count > EFX_PHY_BIST_CABLE_LENGTH_D) {
2034 if ((rc = falcon_mdio_read(enp, epp->ep_port, PMA_PMD_MMD,
2035 PMA_PMD_DIAG_D_LENGTH_REG, &word)) != 0)
2036 goto fail6;
2037 valuesp[EFX_PHY_BIST_CABLE_LENGTH_D] =
2038 EFX_WORD_FIELD(word, EFX_WORD_0);
2039 value_mask |= (1 << EFX_PHY_BIST_CABLE_LENGTH_D);
2040 }
2041
2042 if (value_maskp != NULL)
2043 *value_maskp = value_mask;
2044
2045 return (0);
2046
2047 fail6:
2048 EFSYS_PROBE(fail6);
2049 fail5:
2050 EFSYS_PROBE(fail5);
2051 fail4:
2052 EFSYS_PROBE(fail4);
2053 fail3:
2054 EFSYS_PROBE(fail3);
2055 fail2:
2056 EFSYS_PROBE(fail2);
2057 fail1:
2058 EFSYS_PROBE1(fail1, int, rc);
2059
2060 return (rc);
2061 }
2062
2063 void
2064 sft9001_bist_stop(
2065 __in efx_nic_t *enp,
2066 __in efx_phy_bist_type_t type)
2067 {
2068 boolean_t break_link = (type == EFX_PHY_BIST_TYPE_CABLE_LONG);
2069
2070 if (break_link) {
2071 /* Pull external reset and reconfigure the PHY */
2072 falcon_nic_phy_reset(enp);
2073
2074 EFSYS_ASSERT3U(enp->en_reset_flags, &, EFX_RESET_PHY);
2075 enp->en_reset_flags &= ~EFX_RESET_PHY;
2076
2077 (void) sft9001_reconfigure(enp);
2078 }
2079 }
2080
2081 #endif /* EFSYS_OPT_PHY_BIST */
2082
2083 #endif /* EFSYS_OPT_PHY_SFT9001 */