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 : :
16 : 0 : void txgbe_init_ops_aml(struct txgbe_hw *hw)
17 : : {
18 : : struct txgbe_mac_info *mac = &hw->mac;
19 : : struct txgbe_phy_info *phy = &hw->phy;
20 : : struct txgbe_mbx_info *mbx = &hw->mbx;
21 : :
22 : 0 : txgbe_init_ops_generic(hw);
23 : :
24 : : /* PHY */
25 : 0 : phy->get_media_type = txgbe_get_media_type_aml;
26 : :
27 : : /* LINK */
28 : 0 : mac->init_mac_link_ops = txgbe_init_mac_link_ops_aml;
29 : 0 : mac->get_link_capabilities = txgbe_get_link_capabilities_aml;
30 : 0 : mac->check_link = txgbe_check_mac_link_aml;
31 : :
32 : : /* FW interaction */
33 : 0 : mbx->host_interface_command = txgbe_host_interface_command_aml;
34 : 0 : }
35 : :
36 : 0 : s32 txgbe_check_mac_link_aml(struct txgbe_hw *hw, u32 *speed,
37 : : bool *link_up, bool link_up_wait_to_complete)
38 : : {
39 : : u32 links_reg, links_orig;
40 : : u32 i;
41 : :
42 : : /* clear the old state */
43 : : links_orig = rd32(hw, TXGBE_PORTSTAT);
44 : :
45 : : links_reg = rd32(hw, TXGBE_PORTSTAT);
46 : :
47 [ # # ]: 0 : if (links_orig != links_reg) {
48 : 0 : DEBUGOUT("LINKS changed from %08X to %08X",
49 : : links_orig, links_reg);
50 : : }
51 : :
52 [ # # ]: 0 : if (link_up_wait_to_complete) {
53 [ # # ]: 0 : for (i = 0; i < hw->mac.max_link_up_time; i++) {
54 [ # # ]: 0 : if (!(links_reg & TXGBE_PORTSTAT_UP)) {
55 : 0 : *link_up = false;
56 : : } else {
57 : 0 : *link_up = true;
58 : 0 : break;
59 : : }
60 : : msec_delay(100);
61 : : links_reg = rd32(hw, TXGBE_PORTSTAT);
62 : : }
63 : : } else {
64 [ # # ]: 0 : if (links_reg & TXGBE_PORTSTAT_UP)
65 : 0 : *link_up = true;
66 : : else
67 : 0 : *link_up = false;
68 : : }
69 : :
70 [ # # ]: 0 : if (link_up) {
71 [ # # # ]: 0 : switch (links_reg & TXGBE_CFG_PORT_ST_AML_LINK_MASK) {
72 : 0 : case TXGBE_CFG_PORT_ST_AML_LINK_25G:
73 : 0 : *speed = TXGBE_LINK_SPEED_25GB_FULL;
74 : 0 : break;
75 : 0 : case TXGBE_CFG_PORT_ST_AML_LINK_10G:
76 : 0 : *speed = TXGBE_LINK_SPEED_10GB_FULL;
77 : 0 : break;
78 : 0 : default:
79 : 0 : *speed = TXGBE_LINK_SPEED_UNKNOWN;
80 : : }
81 : : } else {
82 : 0 : *speed = TXGBE_LINK_SPEED_UNKNOWN;
83 : : }
84 : :
85 : 0 : return 0;
86 : : }
87 : :
88 : 0 : s32 txgbe_get_link_capabilities_aml(struct txgbe_hw *hw,
89 : : u32 *speed,
90 : : bool *autoneg)
91 : : {
92 [ # # ]: 0 : if (hw->phy.multispeed_fiber) {
93 : 0 : *speed = TXGBE_LINK_SPEED_10GB_FULL |
94 : : TXGBE_LINK_SPEED_25GB_FULL;
95 : 0 : *autoneg = true;
96 : 0 : } else if (hw->phy.sfp_type == txgbe_sfp_type_25g_sr_core0 ||
97 : : hw->phy.sfp_type == txgbe_sfp_type_25g_sr_core1 ||
98 [ # # ]: 0 : hw->phy.sfp_type == txgbe_sfp_type_25g_lr_core0 ||
99 : : hw->phy.sfp_type == txgbe_sfp_type_25g_lr_core1) {
100 : 0 : *speed = TXGBE_LINK_SPEED_25GB_FULL;
101 : 0 : *autoneg = false;
102 [ # # ]: 0 : } else if (hw->phy.sfp_type == txgbe_sfp_type_25g_aoc_core0 ||
103 : : hw->phy.sfp_type == txgbe_sfp_type_25g_aoc_core1) {
104 : 0 : *speed = TXGBE_LINK_SPEED_25GB_FULL;
105 : 0 : *autoneg = false;
106 : : } else {
107 : : /* SFP */
108 [ # # ]: 0 : if (hw->phy.sfp_type == txgbe_sfp_type_not_present)
109 : 0 : *speed = TXGBE_LINK_SPEED_25GB_FULL;
110 : : else
111 : 0 : *speed = TXGBE_LINK_SPEED_10GB_FULL;
112 : 0 : *autoneg = true;
113 : : }
114 : :
115 : 0 : return 0;
116 : : }
117 : :
118 : 0 : u32 txgbe_get_media_type_aml(struct txgbe_hw *hw)
119 : : {
120 : 0 : u8 device_type = hw->subsystem_device_id & 0xF0;
121 : : enum txgbe_media_type media_type;
122 : :
123 [ # # # ]: 0 : switch (device_type) {
124 : : case TXGBE_DEV_ID_KR_KX_KX4:
125 : : media_type = txgbe_media_type_backplane;
126 : : break;
127 : 0 : case TXGBE_DEV_ID_SFP:
128 : : media_type = txgbe_media_type_fiber;
129 : 0 : break;
130 : 0 : default:
131 : : media_type = txgbe_media_type_unknown;
132 : 0 : break;
133 : : }
134 : :
135 : 0 : return media_type;
136 : : }
137 : :
138 : : static int
139 : 0 : txgbe_phy_fec_get(struct txgbe_hw *hw)
140 : : {
141 : : int value = 0;
142 : :
143 : 0 : rte_spinlock_lock(&hw->phy_lock);
144 : 0 : value = rd32_epcs(hw, SR_PMA_RS_FEC_CTRL);
145 : : rte_spinlock_unlock(&hw->phy_lock);
146 [ # # ]: 0 : if (value & 0x4)
147 : : return TXGBE_PHY_FEC_RS;
148 : :
149 : : rte_spinlock_lock(&hw->phy_lock);
150 : 0 : value = rd32_epcs(hw, SR_PMA_KR_FEC_CTRL);
151 : : rte_spinlock_unlock(&hw->phy_lock);
152 [ # # ]: 0 : if (value & 0x1)
153 : 0 : return TXGBE_PHY_FEC_BASER;
154 : :
155 : : return TXGBE_PHY_FEC_OFF;
156 : : }
157 : :
158 : 0 : void txgbe_wait_for_link_up_aml(struct txgbe_hw *hw, u32 speed)
159 : : {
160 : 0 : u32 link_speed = TXGBE_LINK_SPEED_UNKNOWN;
161 : 0 : bool link_up = false;
162 : : int cnt = 0;
163 : : int i;
164 : :
165 [ # # ]: 0 : if (speed == TXGBE_LINK_SPEED_25GB_FULL)
166 : : cnt = 4;
167 : : else
168 : : cnt = 1;
169 : :
170 [ # # ]: 0 : for (i = 0; i < (4 * cnt); i++) {
171 : 0 : hw->mac.check_link(hw, &link_speed, &link_up, false);
172 [ # # ]: 0 : if (link_up)
173 : : break;
174 : : msleep(250);
175 : : }
176 : 0 : }
177 : :
178 : 0 : s32 txgbe_setup_mac_link_aml(struct txgbe_hw *hw,
179 : : u32 speed,
180 : : bool autoneg_wait_to_complete)
181 : : {
182 : 0 : bool autoneg = false;
183 : : s32 status = 0;
184 : 0 : u32 link_speed = TXGBE_LINK_SPEED_UNKNOWN;
185 : 0 : bool link_up = false;
186 : 0 : u32 link_capabilities = TXGBE_LINK_SPEED_UNKNOWN;
187 : : u32 value = 0;
188 : :
189 [ # # ]: 0 : if (hw->phy.sfp_type == txgbe_sfp_type_not_present) {
190 : 0 : DEBUGOUT("SFP not detected, skip setup mac link");
191 : 0 : return 0;
192 : : }
193 : :
194 : : /* Check to see if speed passed in is supported. */
195 : 0 : status = hw->mac.get_link_capabilities(hw,
196 : : &link_capabilities, &autoneg);
197 [ # # ]: 0 : if (status)
198 : : return status;
199 : :
200 : 0 : speed &= link_capabilities;
201 [ # # ]: 0 : if (speed == TXGBE_LINK_SPEED_UNKNOWN)
202 : : return TXGBE_ERR_LINK_SETUP;
203 : :
204 : : value = rd32(hw, TXGBE_GPIOEXT);
205 [ # # ]: 0 : if (value & (TXGBE_SFP1_MOD_ABS_LS | TXGBE_SFP1_RX_LOS_LS))
206 : : return status;
207 : :
208 : 0 : status = hw->mac.check_link(hw, &link_speed, &link_up,
209 : : autoneg_wait_to_complete);
210 : :
211 [ # # # # ]: 0 : if (link_up && speed == TXGBE_LINK_SPEED_25GB_FULL)
212 : 0 : hw->cur_fec_link = txgbe_phy_fec_get(hw);
213 : :
214 [ # # # # : 0 : if (link_speed == speed && link_up &&
# # ]
215 : 0 : !(speed == TXGBE_LINK_SPEED_25GB_FULL &&
216 [ # # ]: 0 : !(hw->fec_mode & hw->cur_fec_link)))
217 : : return status;
218 : :
219 [ # # ]: 0 : if (speed & TXGBE_LINK_SPEED_25GB_FULL)
220 : : speed = 0x10;
221 [ # # ]: 0 : else if (speed & TXGBE_LINK_SPEED_10GB_FULL)
222 : : speed = 0x08;
223 : :
224 : 0 : status = hw->phy.set_link_hostif(hw, (u8)speed, autoneg, true);
225 : :
226 : 0 : txgbe_wait_for_link_up_aml(hw, speed);
227 : :
228 : 0 : return status;
229 : : }
230 : :
231 : : /**
232 : : * txgbe_setup_mac_link_multispeed_fiber_aml - Set MAC link speed
233 : : * @hw: pointer to hardware structure
234 : : * @speed: new link speed
235 : : * @autoneg_wait_to_complete: true when waiting for completion is needed
236 : : *
237 : : * Set the link speed in the MAC and/or PHY register and restarts link.
238 : : **/
239 : 0 : static s32 txgbe_setup_mac_link_multispeed_fiber_aml(struct txgbe_hw *hw,
240 : : u32 speed,
241 : : bool autoneg_wait_to_complete)
242 : : {
243 : 0 : u32 link_speed = TXGBE_LINK_SPEED_UNKNOWN;
244 : : u32 highest_link_speed = TXGBE_LINK_SPEED_UNKNOWN;
245 : : s32 status = 0;
246 : : u32 speedcnt = 0;
247 : 0 : bool autoneg, link_up = false;
248 : :
249 : : /* Mask off requested but non-supported speeds */
250 : 0 : status = hw->mac.get_link_capabilities(hw, &link_speed, &autoneg);
251 [ # # ]: 0 : if (status != 0)
252 : : return status;
253 : :
254 : 0 : speed &= link_speed;
255 : :
256 : : /* Try each speed one by one, highest priority first. We do this in
257 : : * software because 25Gb fiber doesn't support speed autonegotiation.
258 : : */
259 [ # # ]: 0 : if (speed & TXGBE_LINK_SPEED_25GB_FULL) {
260 : : speedcnt++;
261 : : highest_link_speed = TXGBE_LINK_SPEED_25GB_FULL;
262 : :
263 : : /* If we already have link at this speed, just jump out */
264 : 0 : txgbe_e56_check_phy_link(hw, &link_speed, &link_up);
265 : :
266 [ # # # # ]: 0 : if (link_speed == TXGBE_LINK_SPEED_25GB_FULL && link_up)
267 : 0 : goto out;
268 : :
269 : : /* Allow module to change analog characteristics (10G -> 25G) */
270 : : msec_delay(40);
271 : :
272 : 0 : status = hw->mac.setup_mac_link(hw,
273 : : TXGBE_LINK_SPEED_25GB_FULL,
274 : : autoneg_wait_to_complete);
275 [ # # ]: 0 : if (status != 0)
276 : : return status;
277 : :
278 : : /* Aml wait link in setup, no need to repeatedly wait */
279 : : /* If we have link, just jump out */
280 : 0 : txgbe_e56_check_phy_link(hw, &link_speed, &link_up);
281 : :
282 [ # # ]: 0 : if (link_up)
283 : 0 : goto out;
284 : : }
285 : :
286 [ # # ]: 0 : if (speed & TXGBE_LINK_SPEED_10GB_FULL) {
287 : 0 : speedcnt++;
288 [ # # ]: 0 : if (highest_link_speed == TXGBE_LINK_SPEED_UNKNOWN)
289 : : highest_link_speed = TXGBE_LINK_SPEED_10GB_FULL;
290 : :
291 : : /* If we already have link at this speed, just jump out */
292 : 0 : txgbe_e56_check_phy_link(hw, &link_speed, &link_up);
293 : :
294 [ # # # # ]: 0 : if (link_speed == TXGBE_LINK_SPEED_10GB_FULL && link_up)
295 : 0 : goto out;
296 : :
297 : : /* Allow module to change analog characteristics (25G->10G) */
298 : : msec_delay(40);
299 : :
300 : 0 : status = hw->mac.setup_mac_link(hw, TXGBE_LINK_SPEED_10GB_FULL,
301 : : autoneg_wait_to_complete);
302 [ # # ]: 0 : if (status != 0)
303 : : return status;
304 : :
305 : : /* Aml wait link in setup, no need to repeatedly wait */
306 : : /* If we have link, just jump out */
307 : 0 : txgbe_e56_check_phy_link(hw, &link_speed, &link_up);
308 : :
309 [ # # ]: 0 : if (link_up)
310 : 0 : goto out;
311 : : }
312 : :
313 : : /* We didn't get link. Configure back to the highest speed we tried,
314 : : * (if there was more than one). We call ourselves back with just the
315 : : * single highest speed that the user requested.
316 : : */
317 [ # # ]: 0 : if (speedcnt > 1)
318 : 0 : status = txgbe_setup_mac_link_multispeed_fiber_aml(hw,
319 : : highest_link_speed,
320 : : autoneg_wait_to_complete);
321 : :
322 : 0 : out:
323 : : /* Set autoneg_advertised value based on input link speed */
324 : 0 : hw->phy.autoneg_advertised = 0;
325 : :
326 [ # # ]: 0 : if (speed & TXGBE_LINK_SPEED_25GB_FULL)
327 : 0 : hw->phy.autoneg_advertised |= TXGBE_LINK_SPEED_25GB_FULL;
328 : :
329 [ # # ]: 0 : if (speed & TXGBE_LINK_SPEED_10GB_FULL)
330 : 0 : hw->phy.autoneg_advertised |= TXGBE_LINK_SPEED_10GB_FULL;
331 : :
332 : : return status;
333 : : }
334 : :
335 : 0 : void txgbe_init_mac_link_ops_aml(struct txgbe_hw *hw)
336 : : {
337 : : struct txgbe_mac_info *mac = &hw->mac;
338 : :
339 [ # # ]: 0 : if (hw->phy.media_type == txgbe_media_type_fiber ||
340 : : hw->phy.media_type == txgbe_media_type_fiber_qsfp) {
341 : 0 : mac->disable_tx_laser =
342 : : txgbe_disable_tx_laser_multispeed_fiber;
343 : 0 : mac->enable_tx_laser =
344 : : txgbe_enable_tx_laser_multispeed_fiber;
345 : 0 : mac->flap_tx_laser =
346 : : txgbe_flap_tx_laser_multispeed_fiber;
347 : :
348 [ # # ]: 0 : if (hw->phy.multispeed_fiber) {
349 : : /* Set up dual speed SFP+ support */
350 : 0 : mac->setup_link = txgbe_setup_mac_link_multispeed_fiber_aml;
351 : 0 : mac->setup_mac_link = txgbe_setup_mac_link_aml;
352 : 0 : mac->set_rate_select_speed = txgbe_set_hard_rate_select_speed;
353 : : } else {
354 : 0 : mac->setup_link = txgbe_setup_mac_link_aml;
355 : 0 : mac->set_rate_select_speed = txgbe_set_hard_rate_select_speed;
356 : : }
357 : : }
358 : 0 : }
|