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