Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2015-2025 Beijing WangXun Technology Co., Ltd.
3 : : * Copyright(c) 2010-2017 Intel Corporation
4 : : */
5 : :
6 : : #include "txgbe_type.h"
7 : : #include "txgbe_mbx.h"
8 : : #include "txgbe_phy.h"
9 : : #include "txgbe_dcb.h"
10 : : #include "txgbe_vf.h"
11 : : #include "txgbe_eeprom.h"
12 : : #include "txgbe_mng.h"
13 : : #include "txgbe_hw.h"
14 : : #include "txgbe_aml.h"
15 : : #include "txgbe_e56.h"
16 : : #include "txgbe_e56_bp.h"
17 : :
18 : 0 : void txgbe_init_ops_aml(struct txgbe_hw *hw)
19 : : {
20 : : struct txgbe_mac_info *mac = &hw->mac;
21 : : struct txgbe_phy_info *phy = &hw->phy;
22 : : struct txgbe_mbx_info *mbx = &hw->mbx;
23 : :
24 : 0 : txgbe_init_ops_generic(hw);
25 : :
26 : : /* PHY */
27 : 0 : phy->get_media_type = txgbe_get_media_type_aml;
28 : 0 : phy->setup_link_core = txgbe_setup_phy_link_aml;
29 : :
30 : : /* LINK */
31 : 0 : mac->init_mac_link_ops = txgbe_init_mac_link_ops_aml;
32 : 0 : mac->get_link_capabilities = txgbe_get_link_capabilities_aml;
33 : 0 : mac->check_link = txgbe_check_mac_link_aml;
34 : :
35 : : /* FW interaction */
36 : 0 : mbx->host_interface_command = txgbe_host_interface_command_aml;
37 : 0 : }
38 : :
39 : 0 : s32 txgbe_check_mac_link_aml(struct txgbe_hw *hw, u32 *speed,
40 : : bool *link_up, bool link_up_wait_to_complete)
41 : : {
42 : : u32 links_reg, links_orig;
43 : : u32 i;
44 : :
45 : : /* clear the old state */
46 : : links_orig = rd32(hw, TXGBE_PORTSTAT);
47 : :
48 : : links_reg = rd32(hw, TXGBE_PORTSTAT);
49 : :
50 [ # # ]: 0 : if (links_orig != links_reg) {
51 : 0 : DEBUGOUT("LINKS changed from %08X to %08X",
52 : : links_orig, links_reg);
53 : : }
54 : :
55 [ # # ]: 0 : if (link_up_wait_to_complete) {
56 [ # # ]: 0 : for (i = 0; i < hw->mac.max_link_up_time; i++) {
57 [ # # ]: 0 : if (!(links_reg & TXGBE_PORTSTAT_UP)) {
58 : 0 : *link_up = false;
59 : : } else {
60 : 0 : *link_up = true;
61 : 0 : break;
62 : : }
63 : : msec_delay(100);
64 : : links_reg = rd32(hw, TXGBE_PORTSTAT);
65 : : }
66 : : } else {
67 [ # # ]: 0 : if (links_reg & TXGBE_PORTSTAT_UP)
68 : 0 : *link_up = true;
69 : : else
70 : 0 : *link_up = false;
71 : : }
72 : :
73 [ # # ]: 0 : if (*link_up) {
74 [ # # # ]: 0 : switch (links_reg & TXGBE_CFG_PORT_ST_AML_LINK_MASK) {
75 : 0 : case TXGBE_CFG_PORT_ST_AML_LINK_25G:
76 : 0 : *speed = TXGBE_LINK_SPEED_25GB_FULL;
77 : 0 : break;
78 : 0 : case TXGBE_CFG_PORT_ST_AML_LINK_10G:
79 : 0 : *speed = TXGBE_LINK_SPEED_10GB_FULL;
80 : 0 : break;
81 : 0 : default:
82 : 0 : *speed = TXGBE_LINK_SPEED_UNKNOWN;
83 : : }
84 : : } else {
85 : 0 : *speed = TXGBE_LINK_SPEED_UNKNOWN;
86 : : }
87 : :
88 [ # # ]: 0 : if (txgbe_xpcs_an_enabled(hw)) {
89 [ # # ]: 0 : if (!hw->an_done) {
90 : 0 : *link_up = false;
91 : 0 : *speed = TXGBE_LINK_SPEED_UNKNOWN;
92 : : }
93 : : }
94 : :
95 : 0 : return 0;
96 : : }
97 : :
98 : 0 : s32 txgbe_get_link_capabilities_aml(struct txgbe_hw *hw,
99 : : u32 *speed,
100 : : bool *autoneg)
101 : : {
102 [ # # ]: 0 : if (hw->phy.multispeed_fiber) {
103 : 0 : *speed = TXGBE_LINK_SPEED_10GB_FULL |
104 : : TXGBE_LINK_SPEED_25GB_FULL;
105 : 0 : *autoneg = true;
106 [ # # ]: 0 : } else if (hw->phy.sfp_type == txgbe_sfp_type_da_cu_core0 ||
107 : : hw->phy.sfp_type == txgbe_sfp_type_da_cu_core1) {
108 [ # # ]: 0 : if (hw->phy.fiber_suppport_speed ==
109 : : TXGBE_LINK_SPEED_10GB_FULL) {
110 : 0 : hw->devarg.auto_neg = false;
111 : 0 : *autoneg = false;
112 : : } else {
113 : 0 : *autoneg = true;
114 : : }
115 : 0 : *speed = hw->phy.fiber_suppport_speed;
116 : 0 : } else if (hw->phy.sfp_type == txgbe_sfp_type_25g_sr_core0 ||
117 : : hw->phy.sfp_type == txgbe_sfp_type_25g_sr_core1 ||
118 : : hw->phy.sfp_type == txgbe_sfp_type_25g_lr_core0 ||
119 : : hw->phy.sfp_type == txgbe_sfp_type_25g_lr_core1 ||
120 [ # # ]: 0 : hw->phy.sfp_type == txgbe_sfp_type_25g_aoc_core0 ||
121 : : hw->phy.sfp_type == txgbe_sfp_type_25g_aoc_core1) {
122 : 0 : *speed = TXGBE_LINK_SPEED_25GB_FULL;
123 : 0 : *autoneg = false;
124 [ # # ]: 0 : } else if (hw->phy.media_type == txgbe_media_type_backplane) {
125 : : /* Backplane */
126 : 0 : *speed = TXGBE_LINK_SPEED_10GB_FULL |
127 : : TXGBE_LINK_SPEED_25GB_FULL;
128 : : /* Backplane supports autonegotiation */
129 : 0 : *autoneg = hw->devarg.auto_neg;
130 [ # # ]: 0 : } else if (hw->phy.media_type == txgbe_media_type_fiber) {
131 : : /* Fiber */
132 : 0 : *speed = TXGBE_LINK_SPEED_10GB_FULL |
133 : : TXGBE_LINK_SPEED_25GB_FULL;
134 : 0 : *autoneg = false;
135 : : } else {
136 : : /* Unknown */
137 : 0 : *speed = TXGBE_LINK_SPEED_UNKNOWN;
138 : 0 : *autoneg = false;
139 : 0 : PMD_DRV_LOG(DEBUG, "GET link capabilities failed");
140 : 0 : return TXGBE_ERR_LINK_SETUP;
141 : : }
142 : :
143 : : return 0;
144 : : }
145 : :
146 : 0 : u32 txgbe_get_media_type_aml(struct txgbe_hw *hw)
147 : : {
148 : 0 : u8 device_type = hw->subsystem_device_id & 0xF0;
149 : : enum txgbe_media_type media_type;
150 : :
151 [ # # # ]: 0 : switch (device_type) {
152 : : case TXGBE_DEV_ID_KR_KX_KX4:
153 : : media_type = txgbe_media_type_backplane;
154 : : break;
155 : 0 : case TXGBE_DEV_ID_SFP:
156 : : media_type = txgbe_media_type_fiber;
157 : 0 : break;
158 : 0 : default:
159 : : media_type = txgbe_media_type_unknown;
160 : 0 : break;
161 : : }
162 : :
163 : 0 : return media_type;
164 : : }
165 : :
166 : : static int
167 : 0 : txgbe_phy_fec_get(struct txgbe_hw *hw)
168 : : {
169 : : int value = 0;
170 : :
171 : 0 : rte_spinlock_lock(&hw->phy_lock);
172 : 0 : value = rd32_epcs(hw, SR_PMA_RS_FEC_CTRL);
173 : : rte_spinlock_unlock(&hw->phy_lock);
174 [ # # ]: 0 : if (value & 0x4)
175 : : return TXGBE_PHY_FEC_RS;
176 : :
177 : : rte_spinlock_lock(&hw->phy_lock);
178 : 0 : value = rd32_epcs(hw, SR_PMA_KR_FEC_CTRL);
179 : : rte_spinlock_unlock(&hw->phy_lock);
180 [ # # ]: 0 : if (value & 0x1)
181 : 0 : return TXGBE_PHY_FEC_BASER;
182 : :
183 : : return TXGBE_PHY_FEC_OFF;
184 : : }
185 : :
186 : 0 : void txgbe_wait_for_link_up_aml(struct txgbe_hw *hw, u32 speed)
187 : : {
188 : 0 : u32 link_speed = TXGBE_LINK_SPEED_UNKNOWN;
189 : 0 : bool link_up = false;
190 : : int cnt = 0;
191 : : int i;
192 : :
193 [ # # ]: 0 : if (speed == TXGBE_LINK_SPEED_25GB_FULL)
194 : : cnt = 4;
195 : : else
196 : : cnt = 1;
197 : :
198 [ # # ]: 0 : for (i = 0; i < (4 * cnt); i++) {
199 : 0 : hw->mac.check_link(hw, &link_speed, &link_up, false);
200 [ # # ]: 0 : if (link_up)
201 : : break;
202 : : msleep(250);
203 : : }
204 : 0 : }
205 : :
206 : 0 : s32 txgbe_setup_phy_link_aml(struct txgbe_hw *hw,
207 : : u32 speed,
208 : : bool autoneg_wait_to_complete,
209 : : bool *need_reset)
210 : : {
211 : 0 : bool autoneg = false;
212 : : s32 status = 0;
213 : : s32 ret_status = 0;
214 : 0 : u32 link_speed = TXGBE_LINK_SPEED_UNKNOWN;
215 : 0 : bool link_up = false;
216 : : int i;
217 : 0 : u32 link_capabilities = TXGBE_LINK_SPEED_UNKNOWN;
218 : : u32 value;
219 : :
220 : 0 : *need_reset = false;
221 : :
222 [ # # # # ]: 0 : if (hw->phy.sfp_type == txgbe_sfp_type_not_present && !txgbe_is_backplane(hw)) {
223 : 0 : DEBUGOUT("SFP not detected, skip setup mac link");
224 : 0 : return 0;
225 : : }
226 : :
227 : : /* Check to see if speed passed in is supported. */
228 : 0 : status = hw->mac.get_link_capabilities(hw,
229 : : &link_capabilities, &autoneg);
230 [ # # ]: 0 : if (status)
231 : : return status;
232 : :
233 : : /* setup the highest link when no autoneg */
234 [ # # ]: 0 : if (!autoneg) {
235 [ # # ]: 0 : if (speed & TXGBE_LINK_SPEED_25GB_FULL)
236 : : speed = TXGBE_LINK_SPEED_25GB_FULL;
237 [ # # ]: 0 : else if (speed & TXGBE_LINK_SPEED_10GB_FULL)
238 : : speed = TXGBE_LINK_SPEED_10GB_FULL;
239 : : }
240 : :
241 : 0 : speed &= link_capabilities;
242 [ # # ]: 0 : if (speed == TXGBE_LINK_SPEED_UNKNOWN)
243 : : return TXGBE_ERR_LINK_SETUP;
244 : :
245 [ # # ]: 0 : if (txgbe_xpcs_an_enabled(hw)) {
246 : 0 : txgbe_e56_check_phy_link(hw, &link_speed, &link_up);
247 [ # # # # : 0 : if (link_up && hw->an_done && !autoneg_wait_to_complete)
# # ]
248 : : return status;
249 : 0 : rte_spinlock_lock(&hw->phy_lock);
250 : 0 : txgbe_e56_set_phy_link_mode(hw, speed, autoneg_wait_to_complete);
251 : : rte_spinlock_unlock(&hw->phy_lock);
252 : 0 : return 0;
253 : : }
254 : :
255 [ # # # # ]: 0 : if (txgbe_is_backplane(hw) || txgbe_is_dac_cable(hw) ||
256 [ # # ]: 0 : hw->phy.ffe_set) {
257 : 0 : rte_spinlock_lock(&hw->phy_lock);
258 : 0 : txgbe_e56_tx_ffe_cfg(hw, speed);
259 : : rte_spinlock_unlock(&hw->phy_lock);
260 : : }
261 : :
262 [ # # ]: 0 : if (txgbe_gpio_ext_check(hw, TXGBE_SFP1_MOD_ABS_LS |
263 : : TXGBE_SFP1_RX_LOS_LS)) {
264 : 0 : DEBUGOUT("RX LOS");
265 : 0 : return status;
266 : : }
267 : :
268 [ # # ]: 0 : for (i = 0; i < 4; i++) {
269 : 0 : txgbe_e56_check_phy_link(hw, &link_speed, &link_up);
270 [ # # ]: 0 : if (link_up) {
271 : 0 : DEBUGOUT("check phy link_up");
272 : 0 : break;
273 : : }
274 : : msleep(250);
275 : : }
276 : :
277 [ # # ]: 0 : if (speed == TXGBE_LINK_SPEED_25GB_FULL)
278 : 0 : hw->cur_fec_link = txgbe_phy_fec_get(hw);
279 : :
280 [ # # # # : 0 : if (link_speed == speed && link_up &&
# # ]
281 : 0 : !(speed == TXGBE_LINK_SPEED_25GB_FULL &&
282 [ # # ]: 0 : !(hw->fec_mode & hw->cur_fec_link)))
283 : 0 : goto out;
284 : :
285 [ # # # # ]: 0 : if (speed == TXGBE_LINK_SPEED_25GB_FULL &&
286 : : link_speed == TXGBE_LINK_SPEED_25GB_FULL) {
287 : 0 : txgbe_e56_fec_polling(hw, &link_up);
288 : :
289 [ # # ]: 0 : if (link_up)
290 : 0 : goto out;
291 : : }
292 : :
293 : 0 : rte_spinlock_lock(&hw->phy_lock);
294 : 0 : ret_status = txgbe_set_link_to_amlite(hw, speed);
295 : : rte_spinlock_unlock(&hw->phy_lock);
296 : :
297 [ # # ]: 0 : if (ret_status == TXGBE_ERR_PHY_INIT_NOT_DONE)
298 : 0 : goto out;
299 : :
300 [ # # ]: 0 : if (ret_status == TXGBE_ERR_TIMEOUT) {
301 : 0 : hw->link_valid = false;
302 : 0 : link_up = false;
303 : 0 : goto out;
304 : : } else {
305 : 0 : hw->link_valid = true;
306 : : }
307 : :
308 [ # # ]: 0 : if (speed == TXGBE_LINK_SPEED_25GB_FULL) {
309 : 0 : txgbe_e56_fec_polling(hw, &link_up);
310 : : } else {
311 [ # # ]: 0 : for (i = 0; i < 4; i++) {
312 : 0 : txgbe_e56_check_phy_link(hw, &link_speed, &link_up);
313 [ # # ]: 0 : if (link_up)
314 : 0 : goto out;
315 : : msleep(250);
316 : : }
317 : : }
318 : :
319 : 0 : out:
320 [ # # ]: 0 : if (link_up) {
321 : : value = rd32(hw, TXGBE_PORTSTAT);
322 [ # # ]: 0 : if (!(value & TXGBE_PORTSTAT_UP)) {
323 : 0 : DEBUGOUT("MAC link 0x14404: 0x%x", value);
324 : 0 : *need_reset = true;
325 : : value = rd32(hw, 0x110b0);
326 : 0 : DEBUGOUT("MAC intr status 0x110b0: 0x%x", value);
327 : : }
328 : : } else {
329 : 0 : *need_reset = true;
330 : 0 : DEBUGOUT("Link reconfiguration required. Reset scheduled in 2000ms.");
331 : : }
332 : :
333 : : return status;
334 : : }
335 : :
336 : : /**
337 : : * txgbe_setup_mac_link_multispeed_fiber_aml - Set MAC link speed
338 : : * @hw: pointer to hardware structure
339 : : * @speed: new link speed
340 : : * @autoneg_wait_to_complete: true when waiting for completion is needed
341 : : *
342 : : * Set the link speed in the MAC and/or PHY register and restarts link.
343 : : **/
344 : 0 : static s32 txgbe_setup_mac_link_multispeed_fiber_aml(struct txgbe_hw *hw,
345 : : u32 speed,
346 : : bool autoneg_wait_to_complete)
347 : : {
348 : 0 : u32 link_speed = TXGBE_LINK_SPEED_UNKNOWN;
349 : : u32 highest_link_speed = TXGBE_LINK_SPEED_UNKNOWN;
350 : 0 : bool autoneg, need_reset, link_up = false;
351 : : s32 status = 0;
352 : : u32 speedcnt = 0;
353 : :
354 : : /* Mask off requested but non-supported speeds */
355 : 0 : status = hw->mac.get_link_capabilities(hw, &link_speed, &autoneg);
356 [ # # ]: 0 : if (status != 0)
357 : : return status;
358 : :
359 : 0 : speed &= link_speed;
360 : :
361 : : /* Try each speed one by one, highest priority first. We do this in
362 : : * software because 25Gb fiber doesn't support speed autonegotiation.
363 : : */
364 [ # # ]: 0 : if (speed & TXGBE_LINK_SPEED_25GB_FULL) {
365 : : speedcnt++;
366 : : highest_link_speed = TXGBE_LINK_SPEED_25GB_FULL;
367 : :
368 : : /* If we already have link at this speed, just jump out */
369 : 0 : txgbe_e56_check_phy_link(hw, &link_speed, &link_up);
370 : :
371 : 0 : hw->cur_fec_link = txgbe_phy_fec_get(hw);
372 : :
373 [ # # # # ]: 0 : if (link_speed == TXGBE_LINK_SPEED_25GB_FULL && link_up &&
374 [ # # ]: 0 : hw->fec_mode & hw->cur_fec_link)
375 : 0 : goto out;
376 : :
377 : : /* Allow module to change analog characteristics (10G -> 25G) */
378 : : msec_delay(40);
379 : :
380 : 0 : status = hw->phy.setup_link_core(hw,
381 : : TXGBE_LINK_SPEED_25GB_FULL,
382 : : autoneg_wait_to_complete,
383 : : &need_reset);
384 [ # # ]: 0 : if (status != 0)
385 : : return status;
386 : :
387 : : /* Aml wait link in setup, no need to repeatedly wait */
388 : : /* If we have link, just jump out */
389 : 0 : txgbe_e56_check_phy_link(hw, &link_speed, &link_up);
390 : :
391 [ # # ]: 0 : if (link_up)
392 : 0 : goto out;
393 : : }
394 : :
395 [ # # ]: 0 : if (speed & TXGBE_LINK_SPEED_10GB_FULL) {
396 : 0 : speedcnt++;
397 [ # # ]: 0 : if (highest_link_speed == TXGBE_LINK_SPEED_UNKNOWN)
398 : : highest_link_speed = TXGBE_LINK_SPEED_10GB_FULL;
399 : :
400 : : /* If we already have link at this speed, just jump out */
401 : 0 : txgbe_e56_check_phy_link(hw, &link_speed, &link_up);
402 : :
403 [ # # # # ]: 0 : if (link_speed == TXGBE_LINK_SPEED_10GB_FULL && link_up)
404 : 0 : goto out;
405 : :
406 : : /* Allow module to change analog characteristics (25G->10G) */
407 : : msec_delay(40);
408 : :
409 : 0 : status = hw->phy.setup_link_core(hw,
410 : : TXGBE_LINK_SPEED_10GB_FULL,
411 : : autoneg_wait_to_complete,
412 : : &need_reset);
413 [ # # ]: 0 : if (status != 0)
414 : : return status;
415 : :
416 : : /* Aml wait link in setup, no need to repeatedly wait */
417 : : /* If we have link, just jump out */
418 : 0 : txgbe_e56_check_phy_link(hw, &link_speed, &link_up);
419 : :
420 [ # # ]: 0 : if (link_up)
421 : 0 : goto out;
422 : : }
423 : :
424 : : /* We didn't get link. Configure back to the highest speed we tried,
425 : : * (if there was more than one). We call ourselves back with just the
426 : : * single highest speed that the user requested.
427 : : */
428 [ # # ]: 0 : if (speedcnt > 1)
429 : 0 : status = txgbe_setup_mac_link_multispeed_fiber_aml(hw,
430 : : highest_link_speed,
431 : : autoneg_wait_to_complete);
432 : :
433 : 0 : out:
434 : : /* Set autoneg_advertised value based on input link speed */
435 : 0 : hw->phy.autoneg_advertised = 0;
436 : :
437 [ # # ]: 0 : if (speed & TXGBE_LINK_SPEED_25GB_FULL)
438 : 0 : hw->phy.autoneg_advertised |= TXGBE_LINK_SPEED_25GB_FULL;
439 : :
440 [ # # ]: 0 : if (speed & TXGBE_LINK_SPEED_10GB_FULL)
441 : 0 : hw->phy.autoneg_advertised |= TXGBE_LINK_SPEED_10GB_FULL;
442 : :
443 : : return status;
444 : : }
445 : :
446 : 0 : void txgbe_init_mac_link_ops_aml(struct txgbe_hw *hw)
447 : : {
448 : : struct txgbe_mac_info *mac = &hw->mac;
449 : :
450 [ # # ]: 0 : if (hw->phy.media_type == txgbe_media_type_fiber ||
451 : : hw->phy.media_type == txgbe_media_type_fiber_qsfp) {
452 : 0 : mac->disable_tx_laser =
453 : : txgbe_disable_tx_laser_multispeed_fiber;
454 : 0 : mac->enable_tx_laser =
455 : : txgbe_enable_tx_laser_multispeed_fiber;
456 : 0 : mac->flap_tx_laser =
457 : : txgbe_flap_tx_laser_multispeed_fiber;
458 : :
459 [ # # ]: 0 : if (hw->phy.multispeed_fiber) {
460 : : /* Set up dual speed SFP+ support */
461 : 0 : mac->setup_link = txgbe_setup_mac_link_multispeed_fiber_aml;
462 : 0 : mac->set_rate_select_speed = txgbe_set_hard_rate_select_speed;
463 : : } else {
464 : 0 : mac->set_rate_select_speed = txgbe_set_hard_rate_select_speed;
465 : : }
466 : : }
467 : 0 : }
|