xref: /dpdk/drivers/common/sfc_efx/base/efx_phy.c (revision 0d09cbc7)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  *
3  * Copyright(c) 2019-2020 Xilinx, Inc.
4  * Copyright(c) 2007-2019 Solarflare Communications Inc.
5  */
6 
7 #include "efx.h"
8 #include "efx_impl.h"
9 
10 
11 #if EFSYS_OPT_SIENA
12 static const efx_phy_ops_t	__efx_phy_siena_ops = {
13 	siena_phy_power,		/* epo_power */
14 	NULL,				/* epo_reset */
15 	siena_phy_reconfigure,		/* epo_reconfigure */
16 	siena_phy_verify,		/* epo_verify */
17 	siena_phy_oui_get,		/* epo_oui_get */
18 	NULL,				/* epo_link_state_get */
19 #if EFSYS_OPT_PHY_STATS
20 	siena_phy_stats_update,		/* epo_stats_update */
21 #endif	/* EFSYS_OPT_PHY_STATS */
22 #if EFSYS_OPT_BIST
23 	NULL,				/* epo_bist_enable_offline */
24 	siena_phy_bist_start,		/* epo_bist_start */
25 	siena_phy_bist_poll,		/* epo_bist_poll */
26 	siena_phy_bist_stop,		/* epo_bist_stop */
27 #endif	/* EFSYS_OPT_BIST */
28 };
29 #endif	/* EFSYS_OPT_SIENA */
30 
31 #if EFX_OPTS_EF10()
32 static const efx_phy_ops_t	__efx_phy_ef10_ops = {
33 	ef10_phy_power,			/* epo_power */
34 	NULL,				/* epo_reset */
35 	ef10_phy_reconfigure,		/* epo_reconfigure */
36 	ef10_phy_verify,		/* epo_verify */
37 	ef10_phy_oui_get,		/* epo_oui_get */
38 	ef10_phy_link_state_get,	/* epo_link_state_get */
39 #if EFSYS_OPT_PHY_STATS
40 	ef10_phy_stats_update,		/* epo_stats_update */
41 #endif	/* EFSYS_OPT_PHY_STATS */
42 #if EFSYS_OPT_BIST
43 	ef10_bist_enable_offline,	/* epo_bist_enable_offline */
44 	ef10_bist_start,		/* epo_bist_start */
45 	ef10_bist_poll,			/* epo_bist_poll */
46 	ef10_bist_stop,			/* epo_bist_stop */
47 #endif	/* EFSYS_OPT_BIST */
48 };
49 #endif	/* EFX_OPTS_EF10() */
50 
51 	__checkReturn	efx_rc_t
52 efx_phy_probe(
53 	__in		efx_nic_t *enp)
54 {
55 	efx_port_t *epp = &(enp->en_port);
56 	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
57 	const efx_phy_ops_t *epop;
58 	efx_rc_t rc;
59 
60 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
61 
62 	epp->ep_port = encp->enc_port;
63 	epp->ep_phy_type = encp->enc_phy_type;
64 
65 	/* Hook in operations structure */
66 	switch (enp->en_family) {
67 #if EFSYS_OPT_SIENA
68 	case EFX_FAMILY_SIENA:
69 		epop = &__efx_phy_siena_ops;
70 		break;
71 #endif	/* EFSYS_OPT_SIENA */
72 
73 #if EFSYS_OPT_HUNTINGTON
74 	case EFX_FAMILY_HUNTINGTON:
75 		epop = &__efx_phy_ef10_ops;
76 		break;
77 #endif	/* EFSYS_OPT_HUNTINGTON */
78 
79 #if EFSYS_OPT_MEDFORD
80 	case EFX_FAMILY_MEDFORD:
81 		epop = &__efx_phy_ef10_ops;
82 		break;
83 #endif	/* EFSYS_OPT_MEDFORD */
84 
85 #if EFSYS_OPT_MEDFORD2
86 	case EFX_FAMILY_MEDFORD2:
87 		epop = &__efx_phy_ef10_ops;
88 		break;
89 #endif	/* EFSYS_OPT_MEDFORD2 */
90 
91 	default:
92 		rc = ENOTSUP;
93 		goto fail1;
94 	}
95 
96 	epp->ep_epop = epop;
97 
98 	return (0);
99 
100 fail1:
101 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
102 
103 	epp->ep_port = 0;
104 	epp->ep_phy_type = 0;
105 
106 	return (rc);
107 }
108 
109 	__checkReturn	efx_rc_t
110 efx_phy_verify(
111 	__in		efx_nic_t *enp)
112 {
113 	efx_port_t *epp = &(enp->en_port);
114 	const efx_phy_ops_t *epop = epp->ep_epop;
115 
116 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
117 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
118 
119 	return (epop->epo_verify(enp));
120 }
121 
122 #if EFSYS_OPT_PHY_LED_CONTROL
123 
124 	__checkReturn	efx_rc_t
125 efx_phy_led_set(
126 	__in		efx_nic_t *enp,
127 	__in		efx_phy_led_mode_t mode)
128 {
129 	efx_nic_cfg_t *encp = (&enp->en_nic_cfg);
130 	efx_port_t *epp = &(enp->en_port);
131 	const efx_phy_ops_t *epop = epp->ep_epop;
132 	uint32_t mask;
133 	efx_rc_t rc;
134 
135 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
136 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
137 
138 	if (epp->ep_phy_led_mode == mode)
139 		goto done;
140 
141 	mask = (1 << EFX_PHY_LED_DEFAULT);
142 	mask |= encp->enc_led_mask;
143 
144 	if (!((1 << mode) & mask)) {
145 		rc = ENOTSUP;
146 		goto fail1;
147 	}
148 
149 	EFSYS_ASSERT3U(mode, <, EFX_PHY_LED_NMODES);
150 	epp->ep_phy_led_mode = mode;
151 
152 	if ((rc = epop->epo_reconfigure(enp)) != 0)
153 		goto fail2;
154 
155 done:
156 	return (0);
157 
158 fail2:
159 	EFSYS_PROBE(fail2);
160 fail1:
161 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
162 
163 	return (rc);
164 }
165 #endif	/* EFSYS_OPT_PHY_LED_CONTROL */
166 
167 			void
168 efx_phy_adv_cap_get(
169 	__in		efx_nic_t *enp,
170 	__in		uint32_t flag,
171 	__out		uint32_t *maskp)
172 {
173 	efx_port_t *epp = &(enp->en_port);
174 
175 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
176 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
177 
178 	switch (flag) {
179 	case EFX_PHY_CAP_CURRENT:
180 		*maskp = epp->ep_adv_cap_mask;
181 		break;
182 	case EFX_PHY_CAP_DEFAULT:
183 		*maskp = epp->ep_default_adv_cap_mask;
184 		break;
185 	case EFX_PHY_CAP_PERM:
186 		*maskp = epp->ep_phy_cap_mask;
187 		break;
188 	default:
189 		EFSYS_ASSERT(B_FALSE);
190 		*maskp = 0;
191 		break;
192 	}
193 }
194 
195 	__checkReturn	efx_rc_t
196 efx_phy_adv_cap_set(
197 	__in		efx_nic_t *enp,
198 	__in		uint32_t mask)
199 {
200 	efx_port_t *epp = &(enp->en_port);
201 	const efx_phy_ops_t *epop = epp->ep_epop;
202 	uint32_t old_mask;
203 	efx_rc_t rc;
204 
205 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
206 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
207 
208 	if ((mask & ~epp->ep_phy_cap_mask) != 0) {
209 		rc = ENOTSUP;
210 		goto fail1;
211 	}
212 
213 	if (epp->ep_adv_cap_mask == mask)
214 		goto done;
215 
216 	old_mask = epp->ep_adv_cap_mask;
217 	epp->ep_adv_cap_mask = mask;
218 
219 	if ((rc = epop->epo_reconfigure(enp)) != 0)
220 		goto fail2;
221 
222 done:
223 	return (0);
224 
225 fail2:
226 	EFSYS_PROBE(fail2);
227 
228 	epp->ep_adv_cap_mask = old_mask;
229 	/* Reconfigure for robustness */
230 	if (epop->epo_reconfigure(enp) != 0) {
231 		/*
232 		 * We may have an inconsistent view of our advertised speed
233 		 * capabilities.
234 		 */
235 		EFSYS_ASSERT(0);
236 	}
237 
238 fail1:
239 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
240 
241 	return (rc);
242 }
243 
244 	void
245 efx_phy_lp_cap_get(
246 	__in		efx_nic_t *enp,
247 	__out		uint32_t *maskp)
248 {
249 	efx_port_t *epp = &(enp->en_port);
250 
251 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
252 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
253 
254 	*maskp = epp->ep_lp_cap_mask;
255 }
256 
257 	__checkReturn	efx_rc_t
258 efx_phy_oui_get(
259 	__in		efx_nic_t *enp,
260 	__out		uint32_t *ouip)
261 {
262 	efx_port_t *epp = &(enp->en_port);
263 	const efx_phy_ops_t *epop = epp->ep_epop;
264 
265 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
266 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
267 
268 	return (epop->epo_oui_get(enp, ouip));
269 }
270 
271 			void
272 efx_phy_media_type_get(
273 	__in		efx_nic_t *enp,
274 	__out		efx_phy_media_type_t *typep)
275 {
276 	efx_port_t *epp = &(enp->en_port);
277 
278 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
279 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
280 
281 	if (epp->ep_module_type != EFX_PHY_MEDIA_INVALID)
282 		*typep = epp->ep_module_type;
283 	else
284 		*typep = epp->ep_fixed_port_type;
285 }
286 
287 	__checkReturn		efx_rc_t
288 efx_phy_module_get_info(
289 	__in			efx_nic_t *enp,
290 	__in			uint8_t dev_addr,
291 	__in			size_t offset,
292 	__in			size_t len,
293 	__out_bcount(len)	uint8_t *data)
294 {
295 	efx_rc_t rc;
296 
297 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
298 	EFSYS_ASSERT(data != NULL);
299 
300 	if ((offset > EFX_PHY_MEDIA_INFO_MAX_OFFSET) ||
301 	    ((offset + len) > EFX_PHY_MEDIA_INFO_MAX_OFFSET)) {
302 		rc = EINVAL;
303 		goto fail1;
304 	}
305 
306 	if ((rc = efx_mcdi_phy_module_get_info(enp, dev_addr,
307 	    offset, len, data)) != 0)
308 		goto fail2;
309 
310 	return (0);
311 
312 fail2:
313 	EFSYS_PROBE(fail2);
314 fail1:
315 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
316 
317 	return (rc);
318 }
319 
320 	__checkReturn		efx_rc_t
321 efx_phy_fec_type_get(
322 	__in		efx_nic_t *enp,
323 	__out		efx_phy_fec_type_t *typep)
324 {
325 	efx_rc_t rc;
326 	efx_phy_link_state_t epls;
327 
328 	if ((rc = efx_phy_link_state_get(enp, &epls)) != 0)
329 		goto fail1;
330 
331 	*typep = epls.epls_fec;
332 
333 	return (0);
334 
335 fail1:
336 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
337 
338 	return (rc);
339 }
340 
341 	__checkReturn		efx_rc_t
342 efx_phy_link_state_get(
343 	__in		efx_nic_t *enp,
344 	__out		efx_phy_link_state_t *eplsp)
345 {
346 	efx_port_t *epp = &(enp->en_port);
347 	const efx_phy_ops_t *epop = epp->ep_epop;
348 	efx_rc_t rc;
349 
350 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
351 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
352 
353 	if (epop->epo_link_state_get == NULL) {
354 		rc = ENOTSUP;
355 		goto fail1;
356 	}
357 
358 	if ((rc = epop->epo_link_state_get(enp, eplsp)) != 0)
359 		goto fail2;
360 
361 	return (0);
362 
363 fail2:
364 	EFSYS_PROBE(fail2);
365 fail1:
366 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
367 
368 	return (rc);
369 }
370 
371 #if EFSYS_OPT_PHY_STATS
372 
373 #if EFSYS_OPT_NAMES
374 
375 /* START MKCONFIG GENERATED PhyStatNamesBlock af9ffa24da3bc100 */
376 static const char * const __efx_phy_stat_name[] = {
377 	"oui",
378 	"pma_pmd_link_up",
379 	"pma_pmd_rx_fault",
380 	"pma_pmd_tx_fault",
381 	"pma_pmd_rev_a",
382 	"pma_pmd_rev_b",
383 	"pma_pmd_rev_c",
384 	"pma_pmd_rev_d",
385 	"pcs_link_up",
386 	"pcs_rx_fault",
387 	"pcs_tx_fault",
388 	"pcs_ber",
389 	"pcs_block_errors",
390 	"phy_xs_link_up",
391 	"phy_xs_rx_fault",
392 	"phy_xs_tx_fault",
393 	"phy_xs_align",
394 	"phy_xs_sync_a",
395 	"phy_xs_sync_b",
396 	"phy_xs_sync_c",
397 	"phy_xs_sync_d",
398 	"an_link_up",
399 	"an_master",
400 	"an_local_rx_ok",
401 	"an_remote_rx_ok",
402 	"cl22ext_link_up",
403 	"snr_a",
404 	"snr_b",
405 	"snr_c",
406 	"snr_d",
407 	"pma_pmd_signal_a",
408 	"pma_pmd_signal_b",
409 	"pma_pmd_signal_c",
410 	"pma_pmd_signal_d",
411 	"an_complete",
412 	"pma_pmd_rev_major",
413 	"pma_pmd_rev_minor",
414 	"pma_pmd_rev_micro",
415 	"pcs_fw_version_0",
416 	"pcs_fw_version_1",
417 	"pcs_fw_version_2",
418 	"pcs_fw_version_3",
419 	"pcs_fw_build_yy",
420 	"pcs_fw_build_mm",
421 	"pcs_fw_build_dd",
422 	"pcs_op_mode",
423 };
424 
425 /* END MKCONFIG GENERATED PhyStatNamesBlock */
426 
427 					const char *
428 efx_phy_stat_name(
429 	__in				efx_nic_t *enp,
430 	__in				efx_phy_stat_t type)
431 {
432 	_NOTE(ARGUNUSED(enp))
433 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
434 	EFSYS_ASSERT3U(type, <, EFX_PHY_NSTATS);
435 
436 	return (__efx_phy_stat_name[type]);
437 }
438 
439 #endif	/* EFSYS_OPT_NAMES */
440 
441 	__checkReturn			efx_rc_t
442 efx_phy_stats_update(
443 	__in				efx_nic_t *enp,
444 	__in				efsys_mem_t *esmp,
445 	__inout_ecount(EFX_PHY_NSTATS)	uint32_t *stat)
446 {
447 	efx_port_t *epp = &(enp->en_port);
448 	const efx_phy_ops_t *epop = epp->ep_epop;
449 
450 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
451 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
452 
453 	return (epop->epo_stats_update(enp, esmp, stat));
454 }
455 
456 #endif	/* EFSYS_OPT_PHY_STATS */
457 
458 
459 #if EFSYS_OPT_BIST
460 
461 	__checkReturn		efx_rc_t
462 efx_bist_enable_offline(
463 	__in			efx_nic_t *enp)
464 {
465 	efx_port_t *epp = &(enp->en_port);
466 	const efx_phy_ops_t *epop = epp->ep_epop;
467 	efx_rc_t rc;
468 
469 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
470 
471 	if (epop->epo_bist_enable_offline == NULL) {
472 		rc = ENOTSUP;
473 		goto fail1;
474 	}
475 
476 	if ((rc = epop->epo_bist_enable_offline(enp)) != 0)
477 		goto fail2;
478 
479 	return (0);
480 
481 fail2:
482 	EFSYS_PROBE(fail2);
483 fail1:
484 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
485 
486 	return (rc);
487 
488 }
489 
490 	__checkReturn		efx_rc_t
491 efx_bist_start(
492 	__in			efx_nic_t *enp,
493 	__in			efx_bist_type_t type)
494 {
495 	efx_port_t *epp = &(enp->en_port);
496 	const efx_phy_ops_t *epop = epp->ep_epop;
497 	efx_rc_t rc;
498 
499 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
500 
501 	EFSYS_ASSERT3U(type, !=, EFX_BIST_TYPE_UNKNOWN);
502 	EFSYS_ASSERT3U(type, <, EFX_BIST_TYPE_NTYPES);
503 	EFSYS_ASSERT3U(epp->ep_current_bist, ==, EFX_BIST_TYPE_UNKNOWN);
504 
505 	if (epop->epo_bist_start == NULL) {
506 		rc = ENOTSUP;
507 		goto fail1;
508 	}
509 
510 	if ((rc = epop->epo_bist_start(enp, type)) != 0)
511 		goto fail2;
512 
513 	epp->ep_current_bist = type;
514 
515 	return (0);
516 
517 fail2:
518 	EFSYS_PROBE(fail2);
519 fail1:
520 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
521 
522 	return (rc);
523 }
524 
525 	__checkReturn		efx_rc_t
526 efx_bist_poll(
527 	__in			efx_nic_t *enp,
528 	__in			efx_bist_type_t type,
529 	__out			efx_bist_result_t *resultp,
530 	__out_opt		uint32_t *value_maskp,
531 	__out_ecount_opt(count)	unsigned long *valuesp,
532 	__in			size_t count)
533 {
534 	efx_port_t *epp = &(enp->en_port);
535 	const efx_phy_ops_t *epop = epp->ep_epop;
536 	efx_rc_t rc;
537 
538 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
539 
540 	EFSYS_ASSERT3U(type, !=, EFX_BIST_TYPE_UNKNOWN);
541 	EFSYS_ASSERT3U(type, <, EFX_BIST_TYPE_NTYPES);
542 	EFSYS_ASSERT3U(epp->ep_current_bist, ==, type);
543 
544 	EFSYS_ASSERT(epop->epo_bist_poll != NULL);
545 	if (epop->epo_bist_poll == NULL) {
546 		rc = ENOTSUP;
547 		goto fail1;
548 	}
549 
550 	if ((rc = epop->epo_bist_poll(enp, type, resultp, value_maskp,
551 	    valuesp, count)) != 0)
552 		goto fail2;
553 
554 	return (0);
555 
556 fail2:
557 	EFSYS_PROBE(fail2);
558 fail1:
559 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
560 
561 	return (rc);
562 }
563 
564 			void
565 efx_bist_stop(
566 	__in		efx_nic_t *enp,
567 	__in		efx_bist_type_t type)
568 {
569 	efx_port_t *epp = &(enp->en_port);
570 	const efx_phy_ops_t *epop = epp->ep_epop;
571 
572 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
573 
574 	EFSYS_ASSERT3U(type, !=, EFX_BIST_TYPE_UNKNOWN);
575 	EFSYS_ASSERT3U(type, <, EFX_BIST_TYPE_NTYPES);
576 	EFSYS_ASSERT3U(epp->ep_current_bist, ==, type);
577 
578 	EFSYS_ASSERT(epop->epo_bist_stop != NULL);
579 
580 	if (epop->epo_bist_stop != NULL)
581 		epop->epo_bist_stop(enp, type);
582 
583 	epp->ep_current_bist = EFX_BIST_TYPE_UNKNOWN;
584 }
585 
586 #endif	/* EFSYS_OPT_BIST */
587 			void
588 efx_phy_unprobe(
589 	__in	efx_nic_t *enp)
590 {
591 	efx_port_t *epp = &(enp->en_port);
592 
593 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
594 
595 	epp->ep_epop = NULL;
596 
597 	epp->ep_adv_cap_mask = 0;
598 
599 	epp->ep_port = 0;
600 	epp->ep_phy_type = 0;
601 }
602