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