1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* Copyright(c) 1999 - 2018 Intel Corporation. */ |
3 | |
4 | #include "ixgbe_x540.h" |
5 | #include "ixgbe_type.h" |
6 | #include "ixgbe_common.h" |
7 | #include "ixgbe_phy.h" |
8 | |
9 | static s32 ixgbe_setup_kr_speed_x550em(struct ixgbe_hw *, ixgbe_link_speed); |
10 | static s32 ixgbe_setup_fc_x550em(struct ixgbe_hw *); |
11 | static void ixgbe_fc_autoneg_fiber_x550em_a(struct ixgbe_hw *); |
12 | static void ixgbe_fc_autoneg_backplane_x550em_a(struct ixgbe_hw *); |
13 | static s32 ixgbe_setup_fc_backplane_x550em_a(struct ixgbe_hw *); |
14 | |
15 | static s32 ixgbe_get_invariants_X550_x(struct ixgbe_hw *hw) |
16 | { |
17 | struct ixgbe_mac_info *mac = &hw->mac; |
18 | struct ixgbe_phy_info *phy = &hw->phy; |
19 | struct ixgbe_link_info *link = &hw->link; |
20 | |
21 | /* Start with X540 invariants, since so simular */ |
22 | ixgbe_get_invariants_X540(hw); |
23 | |
24 | if (mac->ops.get_media_type(hw) != ixgbe_media_type_copper) |
25 | phy->ops.set_phy_power = NULL; |
26 | |
27 | link->addr = IXGBE_CS4227; |
28 | |
29 | return 0; |
30 | } |
31 | |
32 | static s32 ixgbe_get_invariants_X550_x_fw(struct ixgbe_hw *hw) |
33 | { |
34 | struct ixgbe_phy_info *phy = &hw->phy; |
35 | |
36 | /* Start with X540 invariants, since so similar */ |
37 | ixgbe_get_invariants_X540(hw); |
38 | |
39 | phy->ops.set_phy_power = NULL; |
40 | |
41 | return 0; |
42 | } |
43 | |
44 | static s32 ixgbe_get_invariants_X550_a(struct ixgbe_hw *hw) |
45 | { |
46 | struct ixgbe_mac_info *mac = &hw->mac; |
47 | struct ixgbe_phy_info *phy = &hw->phy; |
48 | |
49 | /* Start with X540 invariants, since so simular */ |
50 | ixgbe_get_invariants_X540(hw); |
51 | |
52 | if (mac->ops.get_media_type(hw) != ixgbe_media_type_copper) |
53 | phy->ops.set_phy_power = NULL; |
54 | |
55 | return 0; |
56 | } |
57 | |
58 | static s32 ixgbe_get_invariants_X550_a_fw(struct ixgbe_hw *hw) |
59 | { |
60 | struct ixgbe_phy_info *phy = &hw->phy; |
61 | |
62 | /* Start with X540 invariants, since so similar */ |
63 | ixgbe_get_invariants_X540(hw); |
64 | |
65 | phy->ops.set_phy_power = NULL; |
66 | |
67 | return 0; |
68 | } |
69 | |
70 | /** ixgbe_setup_mux_ctl - Setup ESDP register for I2C mux control |
71 | * @hw: pointer to hardware structure |
72 | **/ |
73 | static void ixgbe_setup_mux_ctl(struct ixgbe_hw *hw) |
74 | { |
75 | u32 esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); |
76 | |
77 | if (hw->bus.lan_id) { |
78 | esdp &= ~(IXGBE_ESDP_SDP1_NATIVE | IXGBE_ESDP_SDP1); |
79 | esdp |= IXGBE_ESDP_SDP1_DIR; |
80 | } |
81 | esdp &= ~(IXGBE_ESDP_SDP0_NATIVE | IXGBE_ESDP_SDP0_DIR); |
82 | IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); |
83 | IXGBE_WRITE_FLUSH(hw); |
84 | } |
85 | |
86 | /** |
87 | * ixgbe_read_cs4227 - Read CS4227 register |
88 | * @hw: pointer to hardware structure |
89 | * @reg: register number to write |
90 | * @value: pointer to receive value read |
91 | * |
92 | * Returns status code |
93 | */ |
94 | static s32 ixgbe_read_cs4227(struct ixgbe_hw *hw, u16 reg, u16 *value) |
95 | { |
96 | return hw->link.ops.read_link_unlocked(hw, hw->link.addr, reg, value); |
97 | } |
98 | |
99 | /** |
100 | * ixgbe_write_cs4227 - Write CS4227 register |
101 | * @hw: pointer to hardware structure |
102 | * @reg: register number to write |
103 | * @value: value to write to register |
104 | * |
105 | * Returns status code |
106 | */ |
107 | static s32 ixgbe_write_cs4227(struct ixgbe_hw *hw, u16 reg, u16 value) |
108 | { |
109 | return hw->link.ops.write_link_unlocked(hw, hw->link.addr, reg, value); |
110 | } |
111 | |
112 | /** |
113 | * ixgbe_read_pe - Read register from port expander |
114 | * @hw: pointer to hardware structure |
115 | * @reg: register number to read |
116 | * @value: pointer to receive read value |
117 | * |
118 | * Returns status code |
119 | */ |
120 | static s32 ixgbe_read_pe(struct ixgbe_hw *hw, u8 reg, u8 *value) |
121 | { |
122 | s32 status; |
123 | |
124 | status = ixgbe_read_i2c_byte_generic_unlocked(hw, byte_offset: reg, IXGBE_PE, data: value); |
125 | if (status) |
126 | hw_err(hw, "port expander access failed with %d\n" , status); |
127 | return status; |
128 | } |
129 | |
130 | /** |
131 | * ixgbe_write_pe - Write register to port expander |
132 | * @hw: pointer to hardware structure |
133 | * @reg: register number to write |
134 | * @value: value to write |
135 | * |
136 | * Returns status code |
137 | */ |
138 | static s32 ixgbe_write_pe(struct ixgbe_hw *hw, u8 reg, u8 value) |
139 | { |
140 | s32 status; |
141 | |
142 | status = ixgbe_write_i2c_byte_generic_unlocked(hw, byte_offset: reg, IXGBE_PE, |
143 | data: value); |
144 | if (status) |
145 | hw_err(hw, "port expander access failed with %d\n" , status); |
146 | return status; |
147 | } |
148 | |
149 | /** |
150 | * ixgbe_reset_cs4227 - Reset CS4227 using port expander |
151 | * @hw: pointer to hardware structure |
152 | * |
153 | * This function assumes that the caller has acquired the proper semaphore. |
154 | * Returns error code |
155 | */ |
156 | static s32 ixgbe_reset_cs4227(struct ixgbe_hw *hw) |
157 | { |
158 | s32 status; |
159 | u32 retry; |
160 | u16 value; |
161 | u8 reg; |
162 | |
163 | /* Trigger hard reset. */ |
164 | status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, value: ®); |
165 | if (status) |
166 | return status; |
167 | reg |= IXGBE_PE_BIT1; |
168 | status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, value: reg); |
169 | if (status) |
170 | return status; |
171 | |
172 | status = ixgbe_read_pe(hw, IXGBE_PE_CONFIG, value: ®); |
173 | if (status) |
174 | return status; |
175 | reg &= ~IXGBE_PE_BIT1; |
176 | status = ixgbe_write_pe(hw, IXGBE_PE_CONFIG, value: reg); |
177 | if (status) |
178 | return status; |
179 | |
180 | status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, value: ®); |
181 | if (status) |
182 | return status; |
183 | reg &= ~IXGBE_PE_BIT1; |
184 | status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, value: reg); |
185 | if (status) |
186 | return status; |
187 | |
188 | usleep_range(IXGBE_CS4227_RESET_HOLD, IXGBE_CS4227_RESET_HOLD + 100); |
189 | |
190 | status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, value: ®); |
191 | if (status) |
192 | return status; |
193 | reg |= IXGBE_PE_BIT1; |
194 | status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, value: reg); |
195 | if (status) |
196 | return status; |
197 | |
198 | /* Wait for the reset to complete. */ |
199 | msleep(IXGBE_CS4227_RESET_DELAY); |
200 | for (retry = 0; retry < IXGBE_CS4227_RETRIES; retry++) { |
201 | status = ixgbe_read_cs4227(hw, IXGBE_CS4227_EFUSE_STATUS, |
202 | value: &value); |
203 | if (!status && value == IXGBE_CS4227_EEPROM_LOAD_OK) |
204 | break; |
205 | msleep(IXGBE_CS4227_CHECK_DELAY); |
206 | } |
207 | if (retry == IXGBE_CS4227_RETRIES) { |
208 | hw_err(hw, "CS4227 reset did not complete\n" ); |
209 | return IXGBE_ERR_PHY; |
210 | } |
211 | |
212 | status = ixgbe_read_cs4227(hw, IXGBE_CS4227_EEPROM_STATUS, value: &value); |
213 | if (status || !(value & IXGBE_CS4227_EEPROM_LOAD_OK)) { |
214 | hw_err(hw, "CS4227 EEPROM did not load successfully\n" ); |
215 | return IXGBE_ERR_PHY; |
216 | } |
217 | |
218 | return 0; |
219 | } |
220 | |
221 | /** |
222 | * ixgbe_check_cs4227 - Check CS4227 and reset as needed |
223 | * @hw: pointer to hardware structure |
224 | */ |
225 | static void ixgbe_check_cs4227(struct ixgbe_hw *hw) |
226 | { |
227 | u32 swfw_mask = hw->phy.phy_semaphore_mask; |
228 | s32 status; |
229 | u16 value; |
230 | u8 retry; |
231 | |
232 | for (retry = 0; retry < IXGBE_CS4227_RETRIES; retry++) { |
233 | status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask); |
234 | if (status) { |
235 | hw_err(hw, "semaphore failed with %d\n" , status); |
236 | msleep(IXGBE_CS4227_CHECK_DELAY); |
237 | continue; |
238 | } |
239 | |
240 | /* Get status of reset flow. */ |
241 | status = ixgbe_read_cs4227(hw, IXGBE_CS4227_SCRATCH, value: &value); |
242 | if (!status && value == IXGBE_CS4227_RESET_COMPLETE) |
243 | goto out; |
244 | |
245 | if (status || value != IXGBE_CS4227_RESET_PENDING) |
246 | break; |
247 | |
248 | /* Reset is pending. Wait and check again. */ |
249 | hw->mac.ops.release_swfw_sync(hw, swfw_mask); |
250 | msleep(IXGBE_CS4227_CHECK_DELAY); |
251 | } |
252 | /* If still pending, assume other instance failed. */ |
253 | if (retry == IXGBE_CS4227_RETRIES) { |
254 | status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask); |
255 | if (status) { |
256 | hw_err(hw, "semaphore failed with %d\n" , status); |
257 | return; |
258 | } |
259 | } |
260 | |
261 | /* Reset the CS4227. */ |
262 | status = ixgbe_reset_cs4227(hw); |
263 | if (status) { |
264 | hw_err(hw, "CS4227 reset failed: %d" , status); |
265 | goto out; |
266 | } |
267 | |
268 | /* Reset takes so long, temporarily release semaphore in case the |
269 | * other driver instance is waiting for the reset indication. |
270 | */ |
271 | ixgbe_write_cs4227(hw, IXGBE_CS4227_SCRATCH, |
272 | IXGBE_CS4227_RESET_PENDING); |
273 | hw->mac.ops.release_swfw_sync(hw, swfw_mask); |
274 | usleep_range(min: 10000, max: 12000); |
275 | status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask); |
276 | if (status) { |
277 | hw_err(hw, "semaphore failed with %d" , status); |
278 | return; |
279 | } |
280 | |
281 | /* Record completion for next time. */ |
282 | status = ixgbe_write_cs4227(hw, IXGBE_CS4227_SCRATCH, |
283 | IXGBE_CS4227_RESET_COMPLETE); |
284 | |
285 | out: |
286 | hw->mac.ops.release_swfw_sync(hw, swfw_mask); |
287 | msleep(msecs: hw->eeprom.semaphore_delay); |
288 | } |
289 | |
290 | /** ixgbe_identify_phy_x550em - Get PHY type based on device id |
291 | * @hw: pointer to hardware structure |
292 | * |
293 | * Returns error code |
294 | */ |
295 | static s32 ixgbe_identify_phy_x550em(struct ixgbe_hw *hw) |
296 | { |
297 | switch (hw->device_id) { |
298 | case IXGBE_DEV_ID_X550EM_A_SFP: |
299 | if (hw->bus.lan_id) |
300 | hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY1_SM; |
301 | else |
302 | hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY0_SM; |
303 | return ixgbe_identify_module_generic(hw); |
304 | case IXGBE_DEV_ID_X550EM_X_SFP: |
305 | /* set up for CS4227 usage */ |
306 | hw->phy.phy_semaphore_mask = IXGBE_GSSR_SHARED_I2C_SM; |
307 | ixgbe_setup_mux_ctl(hw); |
308 | ixgbe_check_cs4227(hw); |
309 | fallthrough; |
310 | case IXGBE_DEV_ID_X550EM_A_SFP_N: |
311 | return ixgbe_identify_module_generic(hw); |
312 | case IXGBE_DEV_ID_X550EM_X_KX4: |
313 | hw->phy.type = ixgbe_phy_x550em_kx4; |
314 | break; |
315 | case IXGBE_DEV_ID_X550EM_X_XFI: |
316 | hw->phy.type = ixgbe_phy_x550em_xfi; |
317 | break; |
318 | case IXGBE_DEV_ID_X550EM_X_KR: |
319 | case IXGBE_DEV_ID_X550EM_A_KR: |
320 | case IXGBE_DEV_ID_X550EM_A_KR_L: |
321 | hw->phy.type = ixgbe_phy_x550em_kr; |
322 | break; |
323 | case IXGBE_DEV_ID_X550EM_A_10G_T: |
324 | if (hw->bus.lan_id) |
325 | hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY1_SM; |
326 | else |
327 | hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY0_SM; |
328 | fallthrough; |
329 | case IXGBE_DEV_ID_X550EM_X_10G_T: |
330 | return ixgbe_identify_phy_generic(hw); |
331 | case IXGBE_DEV_ID_X550EM_X_1G_T: |
332 | hw->phy.type = ixgbe_phy_ext_1g_t; |
333 | break; |
334 | case IXGBE_DEV_ID_X550EM_A_1G_T: |
335 | case IXGBE_DEV_ID_X550EM_A_1G_T_L: |
336 | hw->phy.type = ixgbe_phy_fw; |
337 | hw->phy.ops.read_reg = NULL; |
338 | hw->phy.ops.write_reg = NULL; |
339 | if (hw->bus.lan_id) |
340 | hw->phy.phy_semaphore_mask |= IXGBE_GSSR_PHY1_SM; |
341 | else |
342 | hw->phy.phy_semaphore_mask |= IXGBE_GSSR_PHY0_SM; |
343 | break; |
344 | default: |
345 | break; |
346 | } |
347 | return 0; |
348 | } |
349 | |
350 | static s32 ixgbe_read_phy_reg_x550em(struct ixgbe_hw *hw, u32 reg_addr, |
351 | u32 device_type, u16 *phy_data) |
352 | { |
353 | return IXGBE_NOT_IMPLEMENTED; |
354 | } |
355 | |
356 | static s32 ixgbe_write_phy_reg_x550em(struct ixgbe_hw *hw, u32 reg_addr, |
357 | u32 device_type, u16 phy_data) |
358 | { |
359 | return IXGBE_NOT_IMPLEMENTED; |
360 | } |
361 | |
362 | /** |
363 | * ixgbe_read_i2c_combined_generic - Perform I2C read combined operation |
364 | * @hw: pointer to the hardware structure |
365 | * @addr: I2C bus address to read from |
366 | * @reg: I2C device register to read from |
367 | * @val: pointer to location to receive read value |
368 | * |
369 | * Returns an error code on error. |
370 | **/ |
371 | static s32 ixgbe_read_i2c_combined_generic(struct ixgbe_hw *hw, u8 addr, |
372 | u16 reg, u16 *val) |
373 | { |
374 | return ixgbe_read_i2c_combined_generic_int(hw, addr, reg, val, lock: true); |
375 | } |
376 | |
377 | /** |
378 | * ixgbe_read_i2c_combined_generic_unlocked - Do I2C read combined operation |
379 | * @hw: pointer to the hardware structure |
380 | * @addr: I2C bus address to read from |
381 | * @reg: I2C device register to read from |
382 | * @val: pointer to location to receive read value |
383 | * |
384 | * Returns an error code on error. |
385 | **/ |
386 | static s32 |
387 | ixgbe_read_i2c_combined_generic_unlocked(struct ixgbe_hw *hw, u8 addr, |
388 | u16 reg, u16 *val) |
389 | { |
390 | return ixgbe_read_i2c_combined_generic_int(hw, addr, reg, val, lock: false); |
391 | } |
392 | |
393 | /** |
394 | * ixgbe_write_i2c_combined_generic - Perform I2C write combined operation |
395 | * @hw: pointer to the hardware structure |
396 | * @addr: I2C bus address to write to |
397 | * @reg: I2C device register to write to |
398 | * @val: value to write |
399 | * |
400 | * Returns an error code on error. |
401 | **/ |
402 | static s32 ixgbe_write_i2c_combined_generic(struct ixgbe_hw *hw, |
403 | u8 addr, u16 reg, u16 val) |
404 | { |
405 | return ixgbe_write_i2c_combined_generic_int(hw, addr, reg, val, lock: true); |
406 | } |
407 | |
408 | /** |
409 | * ixgbe_write_i2c_combined_generic_unlocked - Do I2C write combined operation |
410 | * @hw: pointer to the hardware structure |
411 | * @addr: I2C bus address to write to |
412 | * @reg: I2C device register to write to |
413 | * @val: value to write |
414 | * |
415 | * Returns an error code on error. |
416 | **/ |
417 | static s32 |
418 | ixgbe_write_i2c_combined_generic_unlocked(struct ixgbe_hw *hw, |
419 | u8 addr, u16 reg, u16 val) |
420 | { |
421 | return ixgbe_write_i2c_combined_generic_int(hw, addr, reg, val, lock: false); |
422 | } |
423 | |
424 | /** |
425 | * ixgbe_fw_phy_activity - Perform an activity on a PHY |
426 | * @hw: pointer to hardware structure |
427 | * @activity: activity to perform |
428 | * @data: Pointer to 4 32-bit words of data |
429 | */ |
430 | s32 ixgbe_fw_phy_activity(struct ixgbe_hw *hw, u16 activity, |
431 | u32 (*data)[FW_PHY_ACT_DATA_COUNT]) |
432 | { |
433 | union { |
434 | struct ixgbe_hic_phy_activity_req cmd; |
435 | struct ixgbe_hic_phy_activity_resp rsp; |
436 | } hic; |
437 | u16 retries = FW_PHY_ACT_RETRIES; |
438 | s32 rc; |
439 | u32 i; |
440 | |
441 | do { |
442 | memset(&hic, 0, sizeof(hic)); |
443 | hic.cmd.hdr.cmd = FW_PHY_ACT_REQ_CMD; |
444 | hic.cmd.hdr.buf_len = FW_PHY_ACT_REQ_LEN; |
445 | hic.cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; |
446 | hic.cmd.port_number = hw->bus.lan_id; |
447 | hic.cmd.activity_id = cpu_to_le16(activity); |
448 | for (i = 0; i < ARRAY_SIZE(hic.cmd.data); ++i) |
449 | hic.cmd.data[i] = cpu_to_be32((*data)[i]); |
450 | |
451 | rc = ixgbe_host_interface_command(hw, &hic.cmd, length: sizeof(hic.cmd), |
452 | IXGBE_HI_COMMAND_TIMEOUT, |
453 | return_data: true); |
454 | if (rc) |
455 | return rc; |
456 | if (hic.rsp.hdr.cmd_or_resp.ret_status == |
457 | FW_CEM_RESP_STATUS_SUCCESS) { |
458 | for (i = 0; i < FW_PHY_ACT_DATA_COUNT; ++i) |
459 | (*data)[i] = be32_to_cpu(hic.rsp.data[i]); |
460 | return 0; |
461 | } |
462 | usleep_range(min: 20, max: 30); |
463 | --retries; |
464 | } while (retries > 0); |
465 | |
466 | return IXGBE_ERR_HOST_INTERFACE_COMMAND; |
467 | } |
468 | |
469 | static const struct { |
470 | u16 fw_speed; |
471 | ixgbe_link_speed phy_speed; |
472 | } ixgbe_fw_map[] = { |
473 | { FW_PHY_ACT_LINK_SPEED_10, IXGBE_LINK_SPEED_10_FULL }, |
474 | { FW_PHY_ACT_LINK_SPEED_100, IXGBE_LINK_SPEED_100_FULL }, |
475 | { FW_PHY_ACT_LINK_SPEED_1G, IXGBE_LINK_SPEED_1GB_FULL }, |
476 | { FW_PHY_ACT_LINK_SPEED_2_5G, IXGBE_LINK_SPEED_2_5GB_FULL }, |
477 | { FW_PHY_ACT_LINK_SPEED_5G, IXGBE_LINK_SPEED_5GB_FULL }, |
478 | { FW_PHY_ACT_LINK_SPEED_10G, IXGBE_LINK_SPEED_10GB_FULL }, |
479 | }; |
480 | |
481 | /** |
482 | * ixgbe_get_phy_id_fw - Get the phy ID via firmware command |
483 | * @hw: pointer to hardware structure |
484 | * |
485 | * Returns error code |
486 | */ |
487 | static s32 ixgbe_get_phy_id_fw(struct ixgbe_hw *hw) |
488 | { |
489 | u32 info[FW_PHY_ACT_DATA_COUNT] = { 0 }; |
490 | u16 phy_speeds; |
491 | u16 phy_id_lo; |
492 | s32 rc; |
493 | u16 i; |
494 | |
495 | if (hw->phy.id) |
496 | return 0; |
497 | |
498 | rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_GET_PHY_INFO, data: &info); |
499 | if (rc) |
500 | return rc; |
501 | |
502 | hw->phy.speeds_supported = 0; |
503 | phy_speeds = info[0] & FW_PHY_INFO_SPEED_MASK; |
504 | for (i = 0; i < ARRAY_SIZE(ixgbe_fw_map); ++i) { |
505 | if (phy_speeds & ixgbe_fw_map[i].fw_speed) |
506 | hw->phy.speeds_supported |= ixgbe_fw_map[i].phy_speed; |
507 | } |
508 | |
509 | hw->phy.id = info[0] & FW_PHY_INFO_ID_HI_MASK; |
510 | phy_id_lo = info[1] & FW_PHY_INFO_ID_LO_MASK; |
511 | hw->phy.id |= phy_id_lo & IXGBE_PHY_REVISION_MASK; |
512 | hw->phy.revision = phy_id_lo & ~IXGBE_PHY_REVISION_MASK; |
513 | if (!hw->phy.id || hw->phy.id == IXGBE_PHY_REVISION_MASK) |
514 | return IXGBE_ERR_PHY_ADDR_INVALID; |
515 | |
516 | hw->phy.autoneg_advertised = hw->phy.speeds_supported; |
517 | hw->phy.eee_speeds_supported = IXGBE_LINK_SPEED_100_FULL | |
518 | IXGBE_LINK_SPEED_1GB_FULL; |
519 | hw->phy.eee_speeds_advertised = hw->phy.eee_speeds_supported; |
520 | return 0; |
521 | } |
522 | |
523 | /** |
524 | * ixgbe_identify_phy_fw - Get PHY type based on firmware command |
525 | * @hw: pointer to hardware structure |
526 | * |
527 | * Returns error code |
528 | */ |
529 | static s32 ixgbe_identify_phy_fw(struct ixgbe_hw *hw) |
530 | { |
531 | if (hw->bus.lan_id) |
532 | hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY1_SM; |
533 | else |
534 | hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY0_SM; |
535 | |
536 | hw->phy.type = ixgbe_phy_fw; |
537 | hw->phy.ops.read_reg = NULL; |
538 | hw->phy.ops.write_reg = NULL; |
539 | return ixgbe_get_phy_id_fw(hw); |
540 | } |
541 | |
542 | /** |
543 | * ixgbe_shutdown_fw_phy - Shutdown a firmware-controlled PHY |
544 | * @hw: pointer to hardware structure |
545 | * |
546 | * Returns error code |
547 | */ |
548 | static s32 ixgbe_shutdown_fw_phy(struct ixgbe_hw *hw) |
549 | { |
550 | u32 setup[FW_PHY_ACT_DATA_COUNT] = { 0 }; |
551 | |
552 | setup[0] = FW_PHY_ACT_FORCE_LINK_DOWN_OFF; |
553 | return ixgbe_fw_phy_activity(hw, FW_PHY_ACT_FORCE_LINK_DOWN, data: &setup); |
554 | } |
555 | |
556 | /** |
557 | * ixgbe_setup_fw_link - Setup firmware-controlled PHYs |
558 | * @hw: pointer to hardware structure |
559 | */ |
560 | static s32 ixgbe_setup_fw_link(struct ixgbe_hw *hw) |
561 | { |
562 | u32 setup[FW_PHY_ACT_DATA_COUNT] = { 0 }; |
563 | s32 rc; |
564 | u16 i; |
565 | |
566 | if (hw->phy.reset_disable || ixgbe_check_reset_blocked(hw)) |
567 | return 0; |
568 | |
569 | if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) { |
570 | hw_err(hw, "rx_pause not valid in strict IEEE mode\n" ); |
571 | return IXGBE_ERR_INVALID_LINK_SETTINGS; |
572 | } |
573 | |
574 | switch (hw->fc.requested_mode) { |
575 | case ixgbe_fc_full: |
576 | setup[0] |= FW_PHY_ACT_SETUP_LINK_PAUSE_RXTX << |
577 | FW_PHY_ACT_SETUP_LINK_PAUSE_SHIFT; |
578 | break; |
579 | case ixgbe_fc_rx_pause: |
580 | setup[0] |= FW_PHY_ACT_SETUP_LINK_PAUSE_RX << |
581 | FW_PHY_ACT_SETUP_LINK_PAUSE_SHIFT; |
582 | break; |
583 | case ixgbe_fc_tx_pause: |
584 | setup[0] |= FW_PHY_ACT_SETUP_LINK_PAUSE_TX << |
585 | FW_PHY_ACT_SETUP_LINK_PAUSE_SHIFT; |
586 | break; |
587 | default: |
588 | break; |
589 | } |
590 | |
591 | for (i = 0; i < ARRAY_SIZE(ixgbe_fw_map); ++i) { |
592 | if (hw->phy.autoneg_advertised & ixgbe_fw_map[i].phy_speed) |
593 | setup[0] |= ixgbe_fw_map[i].fw_speed; |
594 | } |
595 | setup[0] |= FW_PHY_ACT_SETUP_LINK_HP | FW_PHY_ACT_SETUP_LINK_AN; |
596 | |
597 | if (hw->phy.eee_speeds_advertised) |
598 | setup[0] |= FW_PHY_ACT_SETUP_LINK_EEE; |
599 | |
600 | rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_SETUP_LINK, data: &setup); |
601 | if (rc) |
602 | return rc; |
603 | if (setup[0] == FW_PHY_ACT_SETUP_LINK_RSP_DOWN) |
604 | return IXGBE_ERR_OVERTEMP; |
605 | return 0; |
606 | } |
607 | |
608 | /** |
609 | * ixgbe_fc_autoneg_fw - Set up flow control for FW-controlled PHYs |
610 | * @hw: pointer to hardware structure |
611 | * |
612 | * Called at init time to set up flow control. |
613 | */ |
614 | static s32 ixgbe_fc_autoneg_fw(struct ixgbe_hw *hw) |
615 | { |
616 | if (hw->fc.requested_mode == ixgbe_fc_default) |
617 | hw->fc.requested_mode = ixgbe_fc_full; |
618 | |
619 | return ixgbe_setup_fw_link(hw); |
620 | } |
621 | |
622 | /** ixgbe_init_eeprom_params_X550 - Initialize EEPROM params |
623 | * @hw: pointer to hardware structure |
624 | * |
625 | * Initializes the EEPROM parameters ixgbe_eeprom_info within the |
626 | * ixgbe_hw struct in order to set up EEPROM access. |
627 | **/ |
628 | static s32 ixgbe_init_eeprom_params_X550(struct ixgbe_hw *hw) |
629 | { |
630 | struct ixgbe_eeprom_info *eeprom = &hw->eeprom; |
631 | u32 eec; |
632 | u16 eeprom_size; |
633 | |
634 | if (eeprom->type == ixgbe_eeprom_uninitialized) { |
635 | eeprom->semaphore_delay = 10; |
636 | eeprom->type = ixgbe_flash; |
637 | |
638 | eec = IXGBE_READ_REG(hw, IXGBE_EEC(hw)); |
639 | eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >> |
640 | IXGBE_EEC_SIZE_SHIFT); |
641 | eeprom->word_size = BIT(eeprom_size + |
642 | IXGBE_EEPROM_WORD_SIZE_SHIFT); |
643 | |
644 | hw_dbg(hw, "Eeprom params: type = %d, size = %d\n" , |
645 | eeprom->type, eeprom->word_size); |
646 | } |
647 | |
648 | return 0; |
649 | } |
650 | |
651 | /** |
652 | * ixgbe_iosf_wait - Wait for IOSF command completion |
653 | * @hw: pointer to hardware structure |
654 | * @ctrl: pointer to location to receive final IOSF control value |
655 | * |
656 | * Return: failing status on timeout |
657 | * |
658 | * Note: ctrl can be NULL if the IOSF control register value is not needed |
659 | */ |
660 | static s32 ixgbe_iosf_wait(struct ixgbe_hw *hw, u32 *ctrl) |
661 | { |
662 | u32 i, command; |
663 | |
664 | /* Check every 10 usec to see if the address cycle completed. |
665 | * The SB IOSF BUSY bit will clear when the operation is |
666 | * complete. |
667 | */ |
668 | for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) { |
669 | command = IXGBE_READ_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL); |
670 | if (!(command & IXGBE_SB_IOSF_CTRL_BUSY)) |
671 | break; |
672 | udelay(10); |
673 | } |
674 | if (ctrl) |
675 | *ctrl = command; |
676 | if (i == IXGBE_MDIO_COMMAND_TIMEOUT) { |
677 | hw_dbg(hw, "IOSF wait timed out\n" ); |
678 | return IXGBE_ERR_PHY; |
679 | } |
680 | |
681 | return 0; |
682 | } |
683 | |
684 | /** ixgbe_read_iosf_sb_reg_x550 - Writes a value to specified register of the |
685 | * IOSF device |
686 | * @hw: pointer to hardware structure |
687 | * @reg_addr: 32 bit PHY register to write |
688 | * @device_type: 3 bit device type |
689 | * @phy_data: Pointer to read data from the register |
690 | **/ |
691 | static s32 ixgbe_read_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr, |
692 | u32 device_type, u32 *data) |
693 | { |
694 | u32 gssr = IXGBE_GSSR_PHY1_SM | IXGBE_GSSR_PHY0_SM; |
695 | u32 command, error; |
696 | s32 ret; |
697 | |
698 | ret = hw->mac.ops.acquire_swfw_sync(hw, gssr); |
699 | if (ret) |
700 | return ret; |
701 | |
702 | ret = ixgbe_iosf_wait(hw, NULL); |
703 | if (ret) |
704 | goto out; |
705 | |
706 | command = ((reg_addr << IXGBE_SB_IOSF_CTRL_ADDR_SHIFT) | |
707 | (device_type << IXGBE_SB_IOSF_CTRL_TARGET_SELECT_SHIFT)); |
708 | |
709 | /* Write IOSF control register */ |
710 | IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL, command); |
711 | |
712 | ret = ixgbe_iosf_wait(hw, ctrl: &command); |
713 | |
714 | if ((command & IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK) != 0) { |
715 | error = (command & IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK) >> |
716 | IXGBE_SB_IOSF_CTRL_CMPL_ERR_SHIFT; |
717 | hw_dbg(hw, "Failed to read, error %x\n" , error); |
718 | return IXGBE_ERR_PHY; |
719 | } |
720 | |
721 | if (!ret) |
722 | *data = IXGBE_READ_REG(hw, IXGBE_SB_IOSF_INDIRECT_DATA); |
723 | |
724 | out: |
725 | hw->mac.ops.release_swfw_sync(hw, gssr); |
726 | return ret; |
727 | } |
728 | |
729 | /** |
730 | * ixgbe_get_phy_token - Get the token for shared PHY access |
731 | * @hw: Pointer to hardware structure |
732 | */ |
733 | static s32 ixgbe_get_phy_token(struct ixgbe_hw *hw) |
734 | { |
735 | struct ixgbe_hic_phy_token_req token_cmd; |
736 | s32 status; |
737 | |
738 | token_cmd.hdr.cmd = FW_PHY_TOKEN_REQ_CMD; |
739 | token_cmd.hdr.buf_len = FW_PHY_TOKEN_REQ_LEN; |
740 | token_cmd.hdr.cmd_or_resp.cmd_resv = 0; |
741 | token_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; |
742 | token_cmd.port_number = hw->bus.lan_id; |
743 | token_cmd.command_type = FW_PHY_TOKEN_REQ; |
744 | token_cmd.pad = 0; |
745 | status = ixgbe_host_interface_command(hw, &token_cmd, length: sizeof(token_cmd), |
746 | IXGBE_HI_COMMAND_TIMEOUT, |
747 | return_data: true); |
748 | if (status) |
749 | return status; |
750 | if (token_cmd.hdr.cmd_or_resp.ret_status == FW_PHY_TOKEN_OK) |
751 | return 0; |
752 | if (token_cmd.hdr.cmd_or_resp.ret_status != FW_PHY_TOKEN_RETRY) |
753 | return IXGBE_ERR_FW_RESP_INVALID; |
754 | |
755 | return IXGBE_ERR_TOKEN_RETRY; |
756 | } |
757 | |
758 | /** |
759 | * ixgbe_put_phy_token - Put the token for shared PHY access |
760 | * @hw: Pointer to hardware structure |
761 | */ |
762 | static s32 ixgbe_put_phy_token(struct ixgbe_hw *hw) |
763 | { |
764 | struct ixgbe_hic_phy_token_req token_cmd; |
765 | s32 status; |
766 | |
767 | token_cmd.hdr.cmd = FW_PHY_TOKEN_REQ_CMD; |
768 | token_cmd.hdr.buf_len = FW_PHY_TOKEN_REQ_LEN; |
769 | token_cmd.hdr.cmd_or_resp.cmd_resv = 0; |
770 | token_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; |
771 | token_cmd.port_number = hw->bus.lan_id; |
772 | token_cmd.command_type = FW_PHY_TOKEN_REL; |
773 | token_cmd.pad = 0; |
774 | status = ixgbe_host_interface_command(hw, &token_cmd, length: sizeof(token_cmd), |
775 | IXGBE_HI_COMMAND_TIMEOUT, |
776 | return_data: true); |
777 | if (status) |
778 | return status; |
779 | if (token_cmd.hdr.cmd_or_resp.ret_status == FW_PHY_TOKEN_OK) |
780 | return 0; |
781 | return IXGBE_ERR_FW_RESP_INVALID; |
782 | } |
783 | |
784 | /** |
785 | * ixgbe_write_iosf_sb_reg_x550a - Write to IOSF PHY register |
786 | * @hw: pointer to hardware structure |
787 | * @reg_addr: 32 bit PHY register to write |
788 | * @device_type: 3 bit device type |
789 | * @data: Data to write to the register |
790 | **/ |
791 | static s32 ixgbe_write_iosf_sb_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr, |
792 | __always_unused u32 device_type, |
793 | u32 data) |
794 | { |
795 | struct ixgbe_hic_internal_phy_req write_cmd; |
796 | |
797 | memset(&write_cmd, 0, sizeof(write_cmd)); |
798 | write_cmd.hdr.cmd = FW_INT_PHY_REQ_CMD; |
799 | write_cmd.hdr.buf_len = FW_INT_PHY_REQ_LEN; |
800 | write_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; |
801 | write_cmd.port_number = hw->bus.lan_id; |
802 | write_cmd.command_type = FW_INT_PHY_REQ_WRITE; |
803 | write_cmd.address = cpu_to_be16(reg_addr); |
804 | write_cmd.write_data = cpu_to_be32(data); |
805 | |
806 | return ixgbe_host_interface_command(hw, &write_cmd, length: sizeof(write_cmd), |
807 | IXGBE_HI_COMMAND_TIMEOUT, return_data: false); |
808 | } |
809 | |
810 | /** |
811 | * ixgbe_read_iosf_sb_reg_x550a - Read from IOSF PHY register |
812 | * @hw: pointer to hardware structure |
813 | * @reg_addr: 32 bit PHY register to write |
814 | * @device_type: 3 bit device type |
815 | * @data: Pointer to read data from the register |
816 | **/ |
817 | static s32 ixgbe_read_iosf_sb_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr, |
818 | __always_unused u32 device_type, |
819 | u32 *data) |
820 | { |
821 | union { |
822 | struct ixgbe_hic_internal_phy_req cmd; |
823 | struct ixgbe_hic_internal_phy_resp rsp; |
824 | } hic; |
825 | s32 status; |
826 | |
827 | memset(&hic, 0, sizeof(hic)); |
828 | hic.cmd.hdr.cmd = FW_INT_PHY_REQ_CMD; |
829 | hic.cmd.hdr.buf_len = FW_INT_PHY_REQ_LEN; |
830 | hic.cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; |
831 | hic.cmd.port_number = hw->bus.lan_id; |
832 | hic.cmd.command_type = FW_INT_PHY_REQ_READ; |
833 | hic.cmd.address = cpu_to_be16(reg_addr); |
834 | |
835 | status = ixgbe_host_interface_command(hw, &hic.cmd, length: sizeof(hic.cmd), |
836 | IXGBE_HI_COMMAND_TIMEOUT, return_data: true); |
837 | |
838 | /* Extract the register value from the response. */ |
839 | *data = be32_to_cpu(hic.rsp.read_data); |
840 | |
841 | return status; |
842 | } |
843 | |
844 | /** ixgbe_read_ee_hostif_buffer_X550- Read EEPROM word(s) using hostif |
845 | * @hw: pointer to hardware structure |
846 | * @offset: offset of word in the EEPROM to read |
847 | * @words: number of words |
848 | * @data: word(s) read from the EEPROM |
849 | * |
850 | * Reads a 16 bit word(s) from the EEPROM using the hostif. |
851 | **/ |
852 | static s32 ixgbe_read_ee_hostif_buffer_X550(struct ixgbe_hw *hw, |
853 | u16 offset, u16 words, u16 *data) |
854 | { |
855 | const u32 mask = IXGBE_GSSR_SW_MNG_SM | IXGBE_GSSR_EEP_SM; |
856 | struct ixgbe_hic_read_shadow_ram buffer; |
857 | u32 current_word = 0; |
858 | u16 words_to_read; |
859 | s32 status; |
860 | u32 i; |
861 | |
862 | /* Take semaphore for the entire operation. */ |
863 | status = hw->mac.ops.acquire_swfw_sync(hw, mask); |
864 | if (status) { |
865 | hw_dbg(hw, "EEPROM read buffer - semaphore failed\n" ); |
866 | return status; |
867 | } |
868 | |
869 | while (words) { |
870 | if (words > FW_MAX_READ_BUFFER_SIZE / 2) |
871 | words_to_read = FW_MAX_READ_BUFFER_SIZE / 2; |
872 | else |
873 | words_to_read = words; |
874 | |
875 | buffer.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD; |
876 | buffer.hdr.req.buf_lenh = 0; |
877 | buffer.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN; |
878 | buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM; |
879 | |
880 | /* convert offset from words to bytes */ |
881 | buffer.address = (__force u32)cpu_to_be32((offset + |
882 | current_word) * 2); |
883 | buffer.length = (__force u16)cpu_to_be16(words_to_read * 2); |
884 | buffer.pad2 = 0; |
885 | buffer.pad3 = 0; |
886 | |
887 | status = ixgbe_hic_unlocked(hw, buffer: (u32 *)&buffer, len: sizeof(buffer), |
888 | IXGBE_HI_COMMAND_TIMEOUT); |
889 | if (status) { |
890 | hw_dbg(hw, "Host interface command failed\n" ); |
891 | goto out; |
892 | } |
893 | |
894 | for (i = 0; i < words_to_read; i++) { |
895 | u32 reg = IXGBE_FLEX_MNG + (FW_NVM_DATA_OFFSET << 2) + |
896 | 2 * i; |
897 | u32 value = IXGBE_READ_REG(hw, reg); |
898 | |
899 | data[current_word] = (u16)(value & 0xffff); |
900 | current_word++; |
901 | i++; |
902 | if (i < words_to_read) { |
903 | value >>= 16; |
904 | data[current_word] = (u16)(value & 0xffff); |
905 | current_word++; |
906 | } |
907 | } |
908 | words -= words_to_read; |
909 | } |
910 | |
911 | out: |
912 | hw->mac.ops.release_swfw_sync(hw, mask); |
913 | return status; |
914 | } |
915 | |
916 | /** ixgbe_checksum_ptr_x550 - Checksum one pointer region |
917 | * @hw: pointer to hardware structure |
918 | * @ptr: pointer offset in eeprom |
919 | * @size: size of section pointed by ptr, if 0 first word will be used as size |
920 | * @csum: address of checksum to update |
921 | * |
922 | * Returns error status for any failure |
923 | **/ |
924 | static s32 ixgbe_checksum_ptr_x550(struct ixgbe_hw *hw, u16 ptr, |
925 | u16 size, u16 *csum, u16 *buffer, |
926 | u32 buffer_size) |
927 | { |
928 | u16 buf[256]; |
929 | s32 status; |
930 | u16 length, bufsz, i, start; |
931 | u16 *local_buffer; |
932 | |
933 | bufsz = ARRAY_SIZE(buf); |
934 | |
935 | /* Read a chunk at the pointer location */ |
936 | if (!buffer) { |
937 | status = ixgbe_read_ee_hostif_buffer_X550(hw, offset: ptr, words: bufsz, data: buf); |
938 | if (status) { |
939 | hw_dbg(hw, "Failed to read EEPROM image\n" ); |
940 | return status; |
941 | } |
942 | local_buffer = buf; |
943 | } else { |
944 | if (buffer_size < ptr) |
945 | return IXGBE_ERR_PARAM; |
946 | local_buffer = &buffer[ptr]; |
947 | } |
948 | |
949 | if (size) { |
950 | start = 0; |
951 | length = size; |
952 | } else { |
953 | start = 1; |
954 | length = local_buffer[0]; |
955 | |
956 | /* Skip pointer section if length is invalid. */ |
957 | if (length == 0xFFFF || length == 0 || |
958 | (ptr + length) >= hw->eeprom.word_size) |
959 | return 0; |
960 | } |
961 | |
962 | if (buffer && ((u32)start + (u32)length > buffer_size)) |
963 | return IXGBE_ERR_PARAM; |
964 | |
965 | for (i = start; length; i++, length--) { |
966 | if (i == bufsz && !buffer) { |
967 | ptr += bufsz; |
968 | i = 0; |
969 | if (length < bufsz) |
970 | bufsz = length; |
971 | |
972 | /* Read a chunk at the pointer location */ |
973 | status = ixgbe_read_ee_hostif_buffer_X550(hw, offset: ptr, |
974 | words: bufsz, data: buf); |
975 | if (status) { |
976 | hw_dbg(hw, "Failed to read EEPROM image\n" ); |
977 | return status; |
978 | } |
979 | } |
980 | *csum += local_buffer[i]; |
981 | } |
982 | return 0; |
983 | } |
984 | |
985 | /** ixgbe_calc_checksum_X550 - Calculates and returns the checksum |
986 | * @hw: pointer to hardware structure |
987 | * @buffer: pointer to buffer containing calculated checksum |
988 | * @buffer_size: size of buffer |
989 | * |
990 | * Returns a negative error code on error, or the 16-bit checksum |
991 | **/ |
992 | static s32 ixgbe_calc_checksum_X550(struct ixgbe_hw *hw, u16 *buffer, |
993 | u32 buffer_size) |
994 | { |
995 | u16 eeprom_ptrs[IXGBE_EEPROM_LAST_WORD + 1]; |
996 | u16 *local_buffer; |
997 | s32 status; |
998 | u16 checksum = 0; |
999 | u16 pointer, i, size; |
1000 | |
1001 | hw->eeprom.ops.init_params(hw); |
1002 | |
1003 | if (!buffer) { |
1004 | /* Read pointer area */ |
1005 | status = ixgbe_read_ee_hostif_buffer_X550(hw, offset: 0, |
1006 | IXGBE_EEPROM_LAST_WORD + 1, |
1007 | data: eeprom_ptrs); |
1008 | if (status) { |
1009 | hw_dbg(hw, "Failed to read EEPROM image\n" ); |
1010 | return status; |
1011 | } |
1012 | local_buffer = eeprom_ptrs; |
1013 | } else { |
1014 | if (buffer_size < IXGBE_EEPROM_LAST_WORD) |
1015 | return IXGBE_ERR_PARAM; |
1016 | local_buffer = buffer; |
1017 | } |
1018 | |
1019 | /* For X550 hardware include 0x0-0x41 in the checksum, skip the |
1020 | * checksum word itself |
1021 | */ |
1022 | for (i = 0; i <= IXGBE_EEPROM_LAST_WORD; i++) |
1023 | if (i != IXGBE_EEPROM_CHECKSUM) |
1024 | checksum += local_buffer[i]; |
1025 | |
1026 | /* Include all data from pointers 0x3, 0x6-0xE. This excludes the |
1027 | * FW, PHY module, and PCIe Expansion/Option ROM pointers. |
1028 | */ |
1029 | for (i = IXGBE_PCIE_ANALOG_PTR_X550; i < IXGBE_FW_PTR; i++) { |
1030 | if (i == IXGBE_PHY_PTR || i == IXGBE_OPTION_ROM_PTR) |
1031 | continue; |
1032 | |
1033 | pointer = local_buffer[i]; |
1034 | |
1035 | /* Skip pointer section if the pointer is invalid. */ |
1036 | if (pointer == 0xFFFF || pointer == 0 || |
1037 | pointer >= hw->eeprom.word_size) |
1038 | continue; |
1039 | |
1040 | switch (i) { |
1041 | case IXGBE_PCIE_GENERAL_PTR: |
1042 | size = IXGBE_IXGBE_PCIE_GENERAL_SIZE; |
1043 | break; |
1044 | case IXGBE_PCIE_CONFIG0_PTR: |
1045 | case IXGBE_PCIE_CONFIG1_PTR: |
1046 | size = IXGBE_PCIE_CONFIG_SIZE; |
1047 | break; |
1048 | default: |
1049 | size = 0; |
1050 | break; |
1051 | } |
1052 | |
1053 | status = ixgbe_checksum_ptr_x550(hw, ptr: pointer, size, csum: &checksum, |
1054 | buffer, buffer_size); |
1055 | if (status) |
1056 | return status; |
1057 | } |
1058 | |
1059 | checksum = (u16)IXGBE_EEPROM_SUM - checksum; |
1060 | |
1061 | return (s32)checksum; |
1062 | } |
1063 | |
1064 | /** ixgbe_calc_eeprom_checksum_X550 - Calculates and returns the checksum |
1065 | * @hw: pointer to hardware structure |
1066 | * |
1067 | * Returns a negative error code on error, or the 16-bit checksum |
1068 | **/ |
1069 | static s32 ixgbe_calc_eeprom_checksum_X550(struct ixgbe_hw *hw) |
1070 | { |
1071 | return ixgbe_calc_checksum_X550(hw, NULL, buffer_size: 0); |
1072 | } |
1073 | |
1074 | /** ixgbe_read_ee_hostif_X550 - Read EEPROM word using a host interface command |
1075 | * @hw: pointer to hardware structure |
1076 | * @offset: offset of word in the EEPROM to read |
1077 | * @data: word read from the EEPROM |
1078 | * |
1079 | * Reads a 16 bit word from the EEPROM using the hostif. |
1080 | **/ |
1081 | static s32 ixgbe_read_ee_hostif_X550(struct ixgbe_hw *hw, u16 offset, u16 *data) |
1082 | { |
1083 | const u32 mask = IXGBE_GSSR_SW_MNG_SM | IXGBE_GSSR_EEP_SM; |
1084 | struct ixgbe_hic_read_shadow_ram buffer; |
1085 | s32 status; |
1086 | |
1087 | buffer.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD; |
1088 | buffer.hdr.req.buf_lenh = 0; |
1089 | buffer.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN; |
1090 | buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM; |
1091 | |
1092 | /* convert offset from words to bytes */ |
1093 | buffer.address = (__force u32)cpu_to_be32(offset * 2); |
1094 | /* one word */ |
1095 | buffer.length = (__force u16)cpu_to_be16(sizeof(u16)); |
1096 | |
1097 | status = hw->mac.ops.acquire_swfw_sync(hw, mask); |
1098 | if (status) |
1099 | return status; |
1100 | |
1101 | status = ixgbe_hic_unlocked(hw, buffer: (u32 *)&buffer, len: sizeof(buffer), |
1102 | IXGBE_HI_COMMAND_TIMEOUT); |
1103 | if (!status) { |
1104 | *data = (u16)IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, |
1105 | FW_NVM_DATA_OFFSET); |
1106 | } |
1107 | |
1108 | hw->mac.ops.release_swfw_sync(hw, mask); |
1109 | return status; |
1110 | } |
1111 | |
1112 | /** ixgbe_validate_eeprom_checksum_X550 - Validate EEPROM checksum |
1113 | * @hw: pointer to hardware structure |
1114 | * @checksum_val: calculated checksum |
1115 | * |
1116 | * Performs checksum calculation and validates the EEPROM checksum. If the |
1117 | * caller does not need checksum_val, the value can be NULL. |
1118 | **/ |
1119 | static s32 ixgbe_validate_eeprom_checksum_X550(struct ixgbe_hw *hw, |
1120 | u16 *checksum_val) |
1121 | { |
1122 | s32 status; |
1123 | u16 checksum; |
1124 | u16 read_checksum = 0; |
1125 | |
1126 | /* Read the first word from the EEPROM. If this times out or fails, do |
1127 | * not continue or we could be in for a very long wait while every |
1128 | * EEPROM read fails |
1129 | */ |
1130 | status = hw->eeprom.ops.read(hw, 0, &checksum); |
1131 | if (status) { |
1132 | hw_dbg(hw, "EEPROM read failed\n" ); |
1133 | return status; |
1134 | } |
1135 | |
1136 | status = hw->eeprom.ops.calc_checksum(hw); |
1137 | if (status < 0) |
1138 | return status; |
1139 | |
1140 | checksum = (u16)(status & 0xffff); |
1141 | |
1142 | status = ixgbe_read_ee_hostif_X550(hw, IXGBE_EEPROM_CHECKSUM, |
1143 | data: &read_checksum); |
1144 | if (status) |
1145 | return status; |
1146 | |
1147 | /* Verify read checksum from EEPROM is the same as |
1148 | * calculated checksum |
1149 | */ |
1150 | if (read_checksum != checksum) { |
1151 | status = IXGBE_ERR_EEPROM_CHECKSUM; |
1152 | hw_dbg(hw, "Invalid EEPROM checksum" ); |
1153 | } |
1154 | |
1155 | /* If the user cares, return the calculated checksum */ |
1156 | if (checksum_val) |
1157 | *checksum_val = checksum; |
1158 | |
1159 | return status; |
1160 | } |
1161 | |
1162 | /** ixgbe_write_ee_hostif_X550 - Write EEPROM word using hostif |
1163 | * @hw: pointer to hardware structure |
1164 | * @offset: offset of word in the EEPROM to write |
1165 | * @data: word write to the EEPROM |
1166 | * |
1167 | * Write a 16 bit word to the EEPROM using the hostif. |
1168 | **/ |
1169 | static s32 ixgbe_write_ee_hostif_data_X550(struct ixgbe_hw *hw, u16 offset, |
1170 | u16 data) |
1171 | { |
1172 | s32 status; |
1173 | struct ixgbe_hic_write_shadow_ram buffer; |
1174 | |
1175 | buffer.hdr.req.cmd = FW_WRITE_SHADOW_RAM_CMD; |
1176 | buffer.hdr.req.buf_lenh = 0; |
1177 | buffer.hdr.req.buf_lenl = FW_WRITE_SHADOW_RAM_LEN; |
1178 | buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM; |
1179 | |
1180 | /* one word */ |
1181 | buffer.length = cpu_to_be16(sizeof(u16)); |
1182 | buffer.data = data; |
1183 | buffer.address = cpu_to_be32(offset * 2); |
1184 | |
1185 | status = ixgbe_host_interface_command(hw, &buffer, length: sizeof(buffer), |
1186 | IXGBE_HI_COMMAND_TIMEOUT, return_data: false); |
1187 | return status; |
1188 | } |
1189 | |
1190 | /** ixgbe_write_ee_hostif_X550 - Write EEPROM word using hostif |
1191 | * @hw: pointer to hardware structure |
1192 | * @offset: offset of word in the EEPROM to write |
1193 | * @data: word write to the EEPROM |
1194 | * |
1195 | * Write a 16 bit word to the EEPROM using the hostif. |
1196 | **/ |
1197 | static s32 ixgbe_write_ee_hostif_X550(struct ixgbe_hw *hw, u16 offset, u16 data) |
1198 | { |
1199 | s32 status = 0; |
1200 | |
1201 | if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == 0) { |
1202 | status = ixgbe_write_ee_hostif_data_X550(hw, offset, data); |
1203 | hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); |
1204 | } else { |
1205 | hw_dbg(hw, "write ee hostif failed to get semaphore" ); |
1206 | status = IXGBE_ERR_SWFW_SYNC; |
1207 | } |
1208 | |
1209 | return status; |
1210 | } |
1211 | |
1212 | /** ixgbe_update_flash_X550 - Instruct HW to copy EEPROM to Flash device |
1213 | * @hw: pointer to hardware structure |
1214 | * |
1215 | * Issue a shadow RAM dump to FW to copy EEPROM from shadow RAM to the flash. |
1216 | **/ |
1217 | static s32 ixgbe_update_flash_X550(struct ixgbe_hw *hw) |
1218 | { |
1219 | s32 status = 0; |
1220 | union ixgbe_hic_hdr2 buffer; |
1221 | |
1222 | buffer.req.cmd = FW_SHADOW_RAM_DUMP_CMD; |
1223 | buffer.req.buf_lenh = 0; |
1224 | buffer.req.buf_lenl = FW_SHADOW_RAM_DUMP_LEN; |
1225 | buffer.req.checksum = FW_DEFAULT_CHECKSUM; |
1226 | |
1227 | status = ixgbe_host_interface_command(hw, &buffer, length: sizeof(buffer), |
1228 | IXGBE_HI_COMMAND_TIMEOUT, return_data: false); |
1229 | return status; |
1230 | } |
1231 | |
1232 | /** |
1233 | * ixgbe_get_bus_info_X550em - Set PCI bus info |
1234 | * @hw: pointer to hardware structure |
1235 | * |
1236 | * Sets bus link width and speed to unknown because X550em is |
1237 | * not a PCI device. |
1238 | **/ |
1239 | static s32 ixgbe_get_bus_info_X550em(struct ixgbe_hw *hw) |
1240 | { |
1241 | hw->bus.type = ixgbe_bus_type_internal; |
1242 | hw->bus.width = ixgbe_bus_width_unknown; |
1243 | hw->bus.speed = ixgbe_bus_speed_unknown; |
1244 | |
1245 | hw->mac.ops.set_lan_id(hw); |
1246 | |
1247 | return 0; |
1248 | } |
1249 | |
1250 | /** |
1251 | * ixgbe_fw_recovery_mode_X550 - Check FW NVM recovery mode |
1252 | * @hw: pointer t hardware structure |
1253 | * |
1254 | * Returns true if in FW NVM recovery mode. |
1255 | */ |
1256 | static bool ixgbe_fw_recovery_mode_X550(struct ixgbe_hw *hw) |
1257 | { |
1258 | u32 fwsm; |
1259 | |
1260 | fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM(hw)); |
1261 | return !!(fwsm & IXGBE_FWSM_FW_NVM_RECOVERY_MODE); |
1262 | } |
1263 | |
1264 | /** ixgbe_disable_rx_x550 - Disable RX unit |
1265 | * |
1266 | * Enables the Rx DMA unit for x550 |
1267 | **/ |
1268 | static void ixgbe_disable_rx_x550(struct ixgbe_hw *hw) |
1269 | { |
1270 | u32 rxctrl, pfdtxgswc; |
1271 | s32 status; |
1272 | struct ixgbe_hic_disable_rxen fw_cmd; |
1273 | |
1274 | rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); |
1275 | if (rxctrl & IXGBE_RXCTRL_RXEN) { |
1276 | pfdtxgswc = IXGBE_READ_REG(hw, IXGBE_PFDTXGSWC); |
1277 | if (pfdtxgswc & IXGBE_PFDTXGSWC_VT_LBEN) { |
1278 | pfdtxgswc &= ~IXGBE_PFDTXGSWC_VT_LBEN; |
1279 | IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, pfdtxgswc); |
1280 | hw->mac.set_lben = true; |
1281 | } else { |
1282 | hw->mac.set_lben = false; |
1283 | } |
1284 | |
1285 | fw_cmd.hdr.cmd = FW_DISABLE_RXEN_CMD; |
1286 | fw_cmd.hdr.buf_len = FW_DISABLE_RXEN_LEN; |
1287 | fw_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; |
1288 | fw_cmd.port_number = hw->bus.lan_id; |
1289 | |
1290 | status = ixgbe_host_interface_command(hw, &fw_cmd, |
1291 | length: sizeof(struct ixgbe_hic_disable_rxen), |
1292 | IXGBE_HI_COMMAND_TIMEOUT, return_data: true); |
1293 | |
1294 | /* If we fail - disable RX using register write */ |
1295 | if (status) { |
1296 | rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); |
1297 | if (rxctrl & IXGBE_RXCTRL_RXEN) { |
1298 | rxctrl &= ~IXGBE_RXCTRL_RXEN; |
1299 | IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl); |
1300 | } |
1301 | } |
1302 | } |
1303 | } |
1304 | |
1305 | /** ixgbe_update_eeprom_checksum_X550 - Updates the EEPROM checksum and flash |
1306 | * @hw: pointer to hardware structure |
1307 | * |
1308 | * After writing EEPROM to shadow RAM using EEWR register, software calculates |
1309 | * checksum and updates the EEPROM and instructs the hardware to update |
1310 | * the flash. |
1311 | **/ |
1312 | static s32 ixgbe_update_eeprom_checksum_X550(struct ixgbe_hw *hw) |
1313 | { |
1314 | s32 status; |
1315 | u16 checksum = 0; |
1316 | |
1317 | /* Read the first word from the EEPROM. If this times out or fails, do |
1318 | * not continue or we could be in for a very long wait while every |
1319 | * EEPROM read fails |
1320 | */ |
1321 | status = ixgbe_read_ee_hostif_X550(hw, offset: 0, data: &checksum); |
1322 | if (status) { |
1323 | hw_dbg(hw, "EEPROM read failed\n" ); |
1324 | return status; |
1325 | } |
1326 | |
1327 | status = ixgbe_calc_eeprom_checksum_X550(hw); |
1328 | if (status < 0) |
1329 | return status; |
1330 | |
1331 | checksum = (u16)(status & 0xffff); |
1332 | |
1333 | status = ixgbe_write_ee_hostif_X550(hw, IXGBE_EEPROM_CHECKSUM, |
1334 | data: checksum); |
1335 | if (status) |
1336 | return status; |
1337 | |
1338 | status = ixgbe_update_flash_X550(hw); |
1339 | |
1340 | return status; |
1341 | } |
1342 | |
1343 | /** ixgbe_write_ee_hostif_buffer_X550 - Write EEPROM word(s) using hostif |
1344 | * @hw: pointer to hardware structure |
1345 | * @offset: offset of word in the EEPROM to write |
1346 | * @words: number of words |
1347 | * @data: word(s) write to the EEPROM |
1348 | * |
1349 | * |
1350 | * Write a 16 bit word(s) to the EEPROM using the hostif. |
1351 | **/ |
1352 | static s32 ixgbe_write_ee_hostif_buffer_X550(struct ixgbe_hw *hw, |
1353 | u16 offset, u16 words, |
1354 | u16 *data) |
1355 | { |
1356 | s32 status = 0; |
1357 | u32 i = 0; |
1358 | |
1359 | /* Take semaphore for the entire operation. */ |
1360 | status = hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM); |
1361 | if (status) { |
1362 | hw_dbg(hw, "EEPROM write buffer - semaphore failed\n" ); |
1363 | return status; |
1364 | } |
1365 | |
1366 | for (i = 0; i < words; i++) { |
1367 | status = ixgbe_write_ee_hostif_data_X550(hw, offset: offset + i, |
1368 | data: data[i]); |
1369 | if (status) { |
1370 | hw_dbg(hw, "Eeprom buffered write failed\n" ); |
1371 | break; |
1372 | } |
1373 | } |
1374 | |
1375 | hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); |
1376 | |
1377 | return status; |
1378 | } |
1379 | |
1380 | /** ixgbe_write_iosf_sb_reg_x550 - Writes a value to specified register of the |
1381 | * IOSF device |
1382 | * |
1383 | * @hw: pointer to hardware structure |
1384 | * @reg_addr: 32 bit PHY register to write |
1385 | * @device_type: 3 bit device type |
1386 | * @data: Data to write to the register |
1387 | **/ |
1388 | static s32 ixgbe_write_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr, |
1389 | u32 device_type, u32 data) |
1390 | { |
1391 | u32 gssr = IXGBE_GSSR_PHY1_SM | IXGBE_GSSR_PHY0_SM; |
1392 | u32 command, error; |
1393 | s32 ret; |
1394 | |
1395 | ret = hw->mac.ops.acquire_swfw_sync(hw, gssr); |
1396 | if (ret) |
1397 | return ret; |
1398 | |
1399 | ret = ixgbe_iosf_wait(hw, NULL); |
1400 | if (ret) |
1401 | goto out; |
1402 | |
1403 | command = ((reg_addr << IXGBE_SB_IOSF_CTRL_ADDR_SHIFT) | |
1404 | (device_type << IXGBE_SB_IOSF_CTRL_TARGET_SELECT_SHIFT)); |
1405 | |
1406 | /* Write IOSF control register */ |
1407 | IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL, command); |
1408 | |
1409 | /* Write IOSF data register */ |
1410 | IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_DATA, data); |
1411 | |
1412 | ret = ixgbe_iosf_wait(hw, ctrl: &command); |
1413 | |
1414 | if ((command & IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK) != 0) { |
1415 | error = (command & IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK) >> |
1416 | IXGBE_SB_IOSF_CTRL_CMPL_ERR_SHIFT; |
1417 | hw_dbg(hw, "Failed to write, error %x\n" , error); |
1418 | return IXGBE_ERR_PHY; |
1419 | } |
1420 | |
1421 | out: |
1422 | hw->mac.ops.release_swfw_sync(hw, gssr); |
1423 | return ret; |
1424 | } |
1425 | |
1426 | /** |
1427 | * ixgbe_setup_ixfi_x550em_x - MAC specific iXFI configuration |
1428 | * @hw: pointer to hardware structure |
1429 | * |
1430 | * iXfI configuration needed for ixgbe_mac_X550EM_x devices. |
1431 | **/ |
1432 | static s32 ixgbe_setup_ixfi_x550em_x(struct ixgbe_hw *hw) |
1433 | { |
1434 | s32 status; |
1435 | u32 reg_val; |
1436 | |
1437 | /* Disable training protocol FSM. */ |
1438 | status = ixgbe_read_iosf_sb_reg_x550(hw, |
1439 | IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id), |
1440 | IXGBE_SB_IOSF_TARGET_KR_PHY, data: ®_val); |
1441 | if (status) |
1442 | return status; |
1443 | |
1444 | reg_val |= IXGBE_KRM_RX_TRN_LINKUP_CTRL_CONV_WO_PROTOCOL; |
1445 | status = ixgbe_write_iosf_sb_reg_x550(hw, |
1446 | IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id), |
1447 | IXGBE_SB_IOSF_TARGET_KR_PHY, data: reg_val); |
1448 | if (status) |
1449 | return status; |
1450 | |
1451 | /* Disable Flex from training TXFFE. */ |
1452 | status = ixgbe_read_iosf_sb_reg_x550(hw, |
1453 | IXGBE_KRM_DSP_TXFFE_STATE_4(hw->bus.lan_id), |
1454 | IXGBE_SB_IOSF_TARGET_KR_PHY, data: ®_val); |
1455 | if (status) |
1456 | return status; |
1457 | |
1458 | reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_C0_EN; |
1459 | reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN; |
1460 | reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CO_ADAPT_EN; |
1461 | status = ixgbe_write_iosf_sb_reg_x550(hw, |
1462 | IXGBE_KRM_DSP_TXFFE_STATE_4(hw->bus.lan_id), |
1463 | IXGBE_SB_IOSF_TARGET_KR_PHY, data: reg_val); |
1464 | if (status) |
1465 | return status; |
1466 | |
1467 | status = ixgbe_read_iosf_sb_reg_x550(hw, |
1468 | IXGBE_KRM_DSP_TXFFE_STATE_5(hw->bus.lan_id), |
1469 | IXGBE_SB_IOSF_TARGET_KR_PHY, data: ®_val); |
1470 | if (status) |
1471 | return status; |
1472 | |
1473 | reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_C0_EN; |
1474 | reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN; |
1475 | reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CO_ADAPT_EN; |
1476 | status = ixgbe_write_iosf_sb_reg_x550(hw, |
1477 | IXGBE_KRM_DSP_TXFFE_STATE_5(hw->bus.lan_id), |
1478 | IXGBE_SB_IOSF_TARGET_KR_PHY, data: reg_val); |
1479 | if (status) |
1480 | return status; |
1481 | |
1482 | /* Enable override for coefficients. */ |
1483 | status = ixgbe_read_iosf_sb_reg_x550(hw, |
1484 | IXGBE_KRM_TX_COEFF_CTRL_1(hw->bus.lan_id), |
1485 | IXGBE_SB_IOSF_TARGET_KR_PHY, data: ®_val); |
1486 | if (status) |
1487 | return status; |
1488 | |
1489 | reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_OVRRD_EN; |
1490 | reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CZERO_EN; |
1491 | reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CPLUS1_OVRRD_EN; |
1492 | reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CMINUS1_OVRRD_EN; |
1493 | status = ixgbe_write_iosf_sb_reg_x550(hw, |
1494 | IXGBE_KRM_TX_COEFF_CTRL_1(hw->bus.lan_id), |
1495 | IXGBE_SB_IOSF_TARGET_KR_PHY, data: reg_val); |
1496 | return status; |
1497 | } |
1498 | |
1499 | /** |
1500 | * ixgbe_restart_an_internal_phy_x550em - restart autonegotiation for the |
1501 | * internal PHY |
1502 | * @hw: pointer to hardware structure |
1503 | **/ |
1504 | static s32 ixgbe_restart_an_internal_phy_x550em(struct ixgbe_hw *hw) |
1505 | { |
1506 | s32 status; |
1507 | u32 link_ctrl; |
1508 | |
1509 | /* Restart auto-negotiation. */ |
1510 | status = hw->mac.ops.read_iosf_sb_reg(hw, |
1511 | IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), |
1512 | IXGBE_SB_IOSF_TARGET_KR_PHY, &link_ctrl); |
1513 | |
1514 | if (status) { |
1515 | hw_dbg(hw, "Auto-negotiation did not complete\n" ); |
1516 | return status; |
1517 | } |
1518 | |
1519 | link_ctrl |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART; |
1520 | status = hw->mac.ops.write_iosf_sb_reg(hw, |
1521 | IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), |
1522 | IXGBE_SB_IOSF_TARGET_KR_PHY, link_ctrl); |
1523 | |
1524 | if (hw->mac.type == ixgbe_mac_x550em_a) { |
1525 | u32 flx_mask_st20; |
1526 | |
1527 | /* Indicate to FW that AN restart has been asserted */ |
1528 | status = hw->mac.ops.read_iosf_sb_reg(hw, |
1529 | IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), |
1530 | IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_mask_st20); |
1531 | |
1532 | if (status) { |
1533 | hw_dbg(hw, "Auto-negotiation did not complete\n" ); |
1534 | return status; |
1535 | } |
1536 | |
1537 | flx_mask_st20 |= IXGBE_KRM_PMD_FLX_MASK_ST20_FW_AN_RESTART; |
1538 | status = hw->mac.ops.write_iosf_sb_reg(hw, |
1539 | IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), |
1540 | IXGBE_SB_IOSF_TARGET_KR_PHY, flx_mask_st20); |
1541 | } |
1542 | |
1543 | return status; |
1544 | } |
1545 | |
1546 | /** ixgbe_setup_ixfi_x550em - Configure the KR PHY for iXFI mode. |
1547 | * @hw: pointer to hardware structure |
1548 | * @speed: the link speed to force |
1549 | * |
1550 | * Configures the integrated KR PHY to use iXFI mode. Used to connect an |
1551 | * internal and external PHY at a specific speed, without autonegotiation. |
1552 | **/ |
1553 | static s32 ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed) |
1554 | { |
1555 | struct ixgbe_mac_info *mac = &hw->mac; |
1556 | s32 status; |
1557 | u32 reg_val; |
1558 | |
1559 | /* iXFI is only supported with X552 */ |
1560 | if (mac->type != ixgbe_mac_X550EM_x) |
1561 | return IXGBE_ERR_LINK_SETUP; |
1562 | |
1563 | /* Disable AN and force speed to 10G Serial. */ |
1564 | status = ixgbe_read_iosf_sb_reg_x550(hw, |
1565 | IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), |
1566 | IXGBE_SB_IOSF_TARGET_KR_PHY, data: ®_val); |
1567 | if (status) |
1568 | return status; |
1569 | |
1570 | reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; |
1571 | reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK; |
1572 | |
1573 | /* Select forced link speed for internal PHY. */ |
1574 | switch (*speed) { |
1575 | case IXGBE_LINK_SPEED_10GB_FULL: |
1576 | reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_10G; |
1577 | break; |
1578 | case IXGBE_LINK_SPEED_1GB_FULL: |
1579 | reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G; |
1580 | break; |
1581 | default: |
1582 | /* Other link speeds are not supported by internal KR PHY. */ |
1583 | return IXGBE_ERR_LINK_SETUP; |
1584 | } |
1585 | |
1586 | status = ixgbe_write_iosf_sb_reg_x550(hw, |
1587 | IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), |
1588 | IXGBE_SB_IOSF_TARGET_KR_PHY, data: reg_val); |
1589 | if (status) |
1590 | return status; |
1591 | |
1592 | /* Additional configuration needed for x550em_x */ |
1593 | if (hw->mac.type == ixgbe_mac_X550EM_x) { |
1594 | status = ixgbe_setup_ixfi_x550em_x(hw); |
1595 | if (status) |
1596 | return status; |
1597 | } |
1598 | |
1599 | /* Toggle port SW reset by AN reset. */ |
1600 | status = ixgbe_restart_an_internal_phy_x550em(hw); |
1601 | |
1602 | return status; |
1603 | } |
1604 | |
1605 | /** |
1606 | * ixgbe_supported_sfp_modules_X550em - Check if SFP module type is supported |
1607 | * @hw: pointer to hardware structure |
1608 | * @linear: true if SFP module is linear |
1609 | */ |
1610 | static s32 ixgbe_supported_sfp_modules_X550em(struct ixgbe_hw *hw, bool *linear) |
1611 | { |
1612 | switch (hw->phy.sfp_type) { |
1613 | case ixgbe_sfp_type_not_present: |
1614 | return IXGBE_ERR_SFP_NOT_PRESENT; |
1615 | case ixgbe_sfp_type_da_cu_core0: |
1616 | case ixgbe_sfp_type_da_cu_core1: |
1617 | *linear = true; |
1618 | break; |
1619 | case ixgbe_sfp_type_srlr_core0: |
1620 | case ixgbe_sfp_type_srlr_core1: |
1621 | case ixgbe_sfp_type_da_act_lmt_core0: |
1622 | case ixgbe_sfp_type_da_act_lmt_core1: |
1623 | case ixgbe_sfp_type_1g_sx_core0: |
1624 | case ixgbe_sfp_type_1g_sx_core1: |
1625 | case ixgbe_sfp_type_1g_lx_core0: |
1626 | case ixgbe_sfp_type_1g_lx_core1: |
1627 | *linear = false; |
1628 | break; |
1629 | case ixgbe_sfp_type_unknown: |
1630 | case ixgbe_sfp_type_1g_cu_core0: |
1631 | case ixgbe_sfp_type_1g_cu_core1: |
1632 | default: |
1633 | return IXGBE_ERR_SFP_NOT_SUPPORTED; |
1634 | } |
1635 | |
1636 | return 0; |
1637 | } |
1638 | |
1639 | /** |
1640 | * ixgbe_setup_mac_link_sfp_x550em - Configure the KR PHY for SFP. |
1641 | * @hw: pointer to hardware structure |
1642 | * @speed: the link speed to force |
1643 | * @autoneg_wait_to_complete: unused |
1644 | * |
1645 | * Configures the extern PHY and the integrated KR PHY for SFP support. |
1646 | */ |
1647 | static s32 |
1648 | ixgbe_setup_mac_link_sfp_x550em(struct ixgbe_hw *hw, |
1649 | ixgbe_link_speed speed, |
1650 | __always_unused bool autoneg_wait_to_complete) |
1651 | { |
1652 | s32 status; |
1653 | u16 reg_slice, reg_val; |
1654 | bool setup_linear = false; |
1655 | |
1656 | /* Check if SFP module is supported and linear */ |
1657 | status = ixgbe_supported_sfp_modules_X550em(hw, linear: &setup_linear); |
1658 | |
1659 | /* If no SFP module present, then return success. Return success since |
1660 | * there is no reason to configure CS4227 and SFP not present error is |
1661 | * not accepted in the setup MAC link flow. |
1662 | */ |
1663 | if (status == IXGBE_ERR_SFP_NOT_PRESENT) |
1664 | return 0; |
1665 | |
1666 | if (status) |
1667 | return status; |
1668 | |
1669 | /* Configure internal PHY for KR/KX. */ |
1670 | ixgbe_setup_kr_speed_x550em(hw, speed); |
1671 | |
1672 | /* Configure CS4227 LINE side to proper mode. */ |
1673 | reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB + (hw->bus.lan_id << 12); |
1674 | if (setup_linear) |
1675 | reg_val = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1; |
1676 | else |
1677 | reg_val = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1; |
1678 | |
1679 | status = hw->link.ops.write_link(hw, hw->link.addr, reg_slice, |
1680 | reg_val); |
1681 | |
1682 | return status; |
1683 | } |
1684 | |
1685 | /** |
1686 | * ixgbe_setup_sfi_x550a - Configure the internal PHY for native SFI mode |
1687 | * @hw: pointer to hardware structure |
1688 | * @speed: the link speed to force |
1689 | * |
1690 | * Configures the integrated PHY for native SFI mode. Used to connect the |
1691 | * internal PHY directly to an SFP cage, without autonegotiation. |
1692 | **/ |
1693 | static s32 ixgbe_setup_sfi_x550a(struct ixgbe_hw *hw, ixgbe_link_speed *speed) |
1694 | { |
1695 | struct ixgbe_mac_info *mac = &hw->mac; |
1696 | s32 status; |
1697 | u32 reg_val; |
1698 | |
1699 | /* Disable all AN and force speed to 10G Serial. */ |
1700 | status = mac->ops.read_iosf_sb_reg(hw, |
1701 | IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), |
1702 | IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); |
1703 | if (status) |
1704 | return status; |
1705 | |
1706 | reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN; |
1707 | reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN; |
1708 | reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN; |
1709 | reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK; |
1710 | |
1711 | /* Select forced link speed for internal PHY. */ |
1712 | switch (*speed) { |
1713 | case IXGBE_LINK_SPEED_10GB_FULL: |
1714 | reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_10G; |
1715 | break; |
1716 | case IXGBE_LINK_SPEED_1GB_FULL: |
1717 | reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_1G; |
1718 | break; |
1719 | default: |
1720 | /* Other link speeds are not supported by internal PHY. */ |
1721 | return IXGBE_ERR_LINK_SETUP; |
1722 | } |
1723 | |
1724 | (void)mac->ops.write_iosf_sb_reg(hw, |
1725 | IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), |
1726 | IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); |
1727 | |
1728 | /* change mode enforcement rules to hybrid */ |
1729 | (void)mac->ops.read_iosf_sb_reg(hw, |
1730 | IXGBE_KRM_FLX_TMRS_CTRL_ST31(hw->bus.lan_id), |
1731 | IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); |
1732 | reg_val |= 0x0400; |
1733 | |
1734 | (void)mac->ops.write_iosf_sb_reg(hw, |
1735 | IXGBE_KRM_FLX_TMRS_CTRL_ST31(hw->bus.lan_id), |
1736 | IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); |
1737 | |
1738 | /* manually control the config */ |
1739 | (void)mac->ops.read_iosf_sb_reg(hw, |
1740 | IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), |
1741 | IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); |
1742 | reg_val |= 0x20002240; |
1743 | |
1744 | (void)mac->ops.write_iosf_sb_reg(hw, |
1745 | IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), |
1746 | IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); |
1747 | |
1748 | /* move the AN base page values */ |
1749 | (void)mac->ops.read_iosf_sb_reg(hw, |
1750 | IXGBE_KRM_PCS_KX_AN(hw->bus.lan_id), |
1751 | IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); |
1752 | reg_val |= 0x1; |
1753 | |
1754 | (void)mac->ops.write_iosf_sb_reg(hw, |
1755 | IXGBE_KRM_PCS_KX_AN(hw->bus.lan_id), |
1756 | IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); |
1757 | |
1758 | /* set the AN37 over CB mode */ |
1759 | (void)mac->ops.read_iosf_sb_reg(hw, |
1760 | IXGBE_KRM_AN_CNTL_4(hw->bus.lan_id), |
1761 | IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); |
1762 | reg_val |= 0x20000000; |
1763 | |
1764 | (void)mac->ops.write_iosf_sb_reg(hw, |
1765 | IXGBE_KRM_AN_CNTL_4(hw->bus.lan_id), |
1766 | IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); |
1767 | |
1768 | /* restart AN manually */ |
1769 | (void)mac->ops.read_iosf_sb_reg(hw, |
1770 | IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), |
1771 | IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); |
1772 | reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART; |
1773 | |
1774 | (void)mac->ops.write_iosf_sb_reg(hw, |
1775 | IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), |
1776 | IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); |
1777 | |
1778 | /* Toggle port SW reset by AN reset. */ |
1779 | status = ixgbe_restart_an_internal_phy_x550em(hw); |
1780 | |
1781 | return status; |
1782 | } |
1783 | |
1784 | /** |
1785 | * ixgbe_setup_mac_link_sfp_n - Setup internal PHY for native SFP |
1786 | * @hw: pointer to hardware structure |
1787 | * @speed: link speed |
1788 | * @autoneg_wait_to_complete: unused |
1789 | * |
1790 | * Configure the integrated PHY for native SFP support. |
1791 | */ |
1792 | static s32 |
1793 | ixgbe_setup_mac_link_sfp_n(struct ixgbe_hw *hw, ixgbe_link_speed speed, |
1794 | __always_unused bool autoneg_wait_to_complete) |
1795 | { |
1796 | bool setup_linear = false; |
1797 | u32 reg_phy_int; |
1798 | s32 ret_val; |
1799 | |
1800 | /* Check if SFP module is supported and linear */ |
1801 | ret_val = ixgbe_supported_sfp_modules_X550em(hw, linear: &setup_linear); |
1802 | |
1803 | /* If no SFP module present, then return success. Return success since |
1804 | * SFP not present error is not excepted in the setup MAC link flow. |
1805 | */ |
1806 | if (ret_val == IXGBE_ERR_SFP_NOT_PRESENT) |
1807 | return 0; |
1808 | |
1809 | if (ret_val) |
1810 | return ret_val; |
1811 | |
1812 | /* Configure internal PHY for native SFI based on module type */ |
1813 | ret_val = hw->mac.ops.read_iosf_sb_reg(hw, |
1814 | IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), |
1815 | IXGBE_SB_IOSF_TARGET_KR_PHY, ®_phy_int); |
1816 | if (ret_val) |
1817 | return ret_val; |
1818 | |
1819 | reg_phy_int &= IXGBE_KRM_PMD_FLX_MASK_ST20_SFI_10G_DA; |
1820 | if (!setup_linear) |
1821 | reg_phy_int |= IXGBE_KRM_PMD_FLX_MASK_ST20_SFI_10G_SR; |
1822 | |
1823 | ret_val = hw->mac.ops.write_iosf_sb_reg(hw, |
1824 | IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), |
1825 | IXGBE_SB_IOSF_TARGET_KR_PHY, reg_phy_int); |
1826 | if (ret_val) |
1827 | return ret_val; |
1828 | |
1829 | /* Setup SFI internal link. */ |
1830 | return ixgbe_setup_sfi_x550a(hw, speed: &speed); |
1831 | } |
1832 | |
1833 | /** |
1834 | * ixgbe_setup_mac_link_sfp_x550a - Setup internal PHY for SFP |
1835 | * @hw: pointer to hardware structure |
1836 | * @speed: link speed |
1837 | * @autoneg_wait_to_complete: unused |
1838 | * |
1839 | * Configure the integrated PHY for SFP support. |
1840 | */ |
1841 | static s32 |
1842 | ixgbe_setup_mac_link_sfp_x550a(struct ixgbe_hw *hw, ixgbe_link_speed speed, |
1843 | __always_unused bool autoneg_wait_to_complete) |
1844 | { |
1845 | u32 reg_slice, slice_offset; |
1846 | bool setup_linear = false; |
1847 | u16 reg_phy_ext; |
1848 | s32 ret_val; |
1849 | |
1850 | /* Check if SFP module is supported and linear */ |
1851 | ret_val = ixgbe_supported_sfp_modules_X550em(hw, linear: &setup_linear); |
1852 | |
1853 | /* If no SFP module present, then return success. Return success since |
1854 | * SFP not present error is not excepted in the setup MAC link flow. |
1855 | */ |
1856 | if (ret_val == IXGBE_ERR_SFP_NOT_PRESENT) |
1857 | return 0; |
1858 | |
1859 | if (ret_val) |
1860 | return ret_val; |
1861 | |
1862 | /* Configure internal PHY for KR/KX. */ |
1863 | ixgbe_setup_kr_speed_x550em(hw, speed); |
1864 | |
1865 | if (hw->phy.mdio.prtad == MDIO_PRTAD_NONE) |
1866 | return IXGBE_ERR_PHY_ADDR_INVALID; |
1867 | |
1868 | /* Get external PHY SKU id */ |
1869 | ret_val = hw->phy.ops.read_reg(hw, IXGBE_CS4227_EFUSE_PDF_SKU, |
1870 | IXGBE_MDIO_ZERO_DEV_TYPE, ®_phy_ext); |
1871 | if (ret_val) |
1872 | return ret_val; |
1873 | |
1874 | /* When configuring quad port CS4223, the MAC instance is part |
1875 | * of the slice offset. |
1876 | */ |
1877 | if (reg_phy_ext == IXGBE_CS4223_SKU_ID) |
1878 | slice_offset = (hw->bus.lan_id + |
1879 | (hw->bus.instance_id << 1)) << 12; |
1880 | else |
1881 | slice_offset = hw->bus.lan_id << 12; |
1882 | |
1883 | /* Configure CS4227/CS4223 LINE side to proper mode. */ |
1884 | reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB + slice_offset; |
1885 | |
1886 | ret_val = hw->phy.ops.read_reg(hw, reg_slice, |
1887 | IXGBE_MDIO_ZERO_DEV_TYPE, ®_phy_ext); |
1888 | if (ret_val) |
1889 | return ret_val; |
1890 | |
1891 | reg_phy_ext &= ~((IXGBE_CS4227_EDC_MODE_CX1 << 1) | |
1892 | (IXGBE_CS4227_EDC_MODE_SR << 1)); |
1893 | |
1894 | if (setup_linear) |
1895 | reg_phy_ext |= (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 1; |
1896 | else |
1897 | reg_phy_ext |= (IXGBE_CS4227_EDC_MODE_SR << 1) | 1; |
1898 | |
1899 | ret_val = hw->phy.ops.write_reg(hw, reg_slice, |
1900 | IXGBE_MDIO_ZERO_DEV_TYPE, reg_phy_ext); |
1901 | if (ret_val) |
1902 | return ret_val; |
1903 | |
1904 | /* Flush previous write with a read */ |
1905 | return hw->phy.ops.read_reg(hw, reg_slice, |
1906 | IXGBE_MDIO_ZERO_DEV_TYPE, ®_phy_ext); |
1907 | } |
1908 | |
1909 | /** |
1910 | * ixgbe_setup_mac_link_t_X550em - Sets the auto advertised link speed |
1911 | * @hw: pointer to hardware structure |
1912 | * @speed: new link speed |
1913 | * @autoneg_wait: true when waiting for completion is needed |
1914 | * |
1915 | * Setup internal/external PHY link speed based on link speed, then set |
1916 | * external PHY auto advertised link speed. |
1917 | * |
1918 | * Returns error status for any failure |
1919 | **/ |
1920 | static s32 ixgbe_setup_mac_link_t_X550em(struct ixgbe_hw *hw, |
1921 | ixgbe_link_speed speed, |
1922 | bool autoneg_wait) |
1923 | { |
1924 | s32 status; |
1925 | ixgbe_link_speed force_speed; |
1926 | |
1927 | /* Setup internal/external PHY link speed to iXFI (10G), unless |
1928 | * only 1G is auto advertised then setup KX link. |
1929 | */ |
1930 | if (speed & IXGBE_LINK_SPEED_10GB_FULL) |
1931 | force_speed = IXGBE_LINK_SPEED_10GB_FULL; |
1932 | else |
1933 | force_speed = IXGBE_LINK_SPEED_1GB_FULL; |
1934 | |
1935 | /* If X552 and internal link mode is XFI, then setup XFI internal link. |
1936 | */ |
1937 | if (hw->mac.type == ixgbe_mac_X550EM_x && |
1938 | !(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE)) { |
1939 | status = ixgbe_setup_ixfi_x550em(hw, speed: &force_speed); |
1940 | |
1941 | if (status) |
1942 | return status; |
1943 | } |
1944 | |
1945 | return hw->phy.ops.setup_link_speed(hw, speed, autoneg_wait); |
1946 | } |
1947 | |
1948 | /** ixgbe_check_link_t_X550em - Determine link and speed status |
1949 | * @hw: pointer to hardware structure |
1950 | * @speed: pointer to link speed |
1951 | * @link_up: true when link is up |
1952 | * @link_up_wait_to_complete: bool used to wait for link up or not |
1953 | * |
1954 | * Check that both the MAC and X557 external PHY have link. |
1955 | **/ |
1956 | static s32 ixgbe_check_link_t_X550em(struct ixgbe_hw *hw, |
1957 | ixgbe_link_speed *speed, |
1958 | bool *link_up, |
1959 | bool link_up_wait_to_complete) |
1960 | { |
1961 | u32 status; |
1962 | u16 i, autoneg_status; |
1963 | |
1964 | if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_copper) |
1965 | return IXGBE_ERR_CONFIG; |
1966 | |
1967 | status = ixgbe_check_mac_link_generic(hw, speed, link_up, |
1968 | link_up_wait_to_complete); |
1969 | |
1970 | /* If check link fails or MAC link is not up, then return */ |
1971 | if (status || !(*link_up)) |
1972 | return status; |
1973 | |
1974 | /* MAC link is up, so check external PHY link. |
1975 | * Link status is latching low, and can only be used to detect link |
1976 | * drop, and not the current status of the link without performing |
1977 | * back-to-back reads. |
1978 | */ |
1979 | for (i = 0; i < 2; i++) { |
1980 | status = hw->phy.ops.read_reg(hw, MDIO_STAT1, MDIO_MMD_AN, |
1981 | &autoneg_status); |
1982 | |
1983 | if (status) |
1984 | return status; |
1985 | } |
1986 | |
1987 | /* If external PHY link is not up, then indicate link not up */ |
1988 | if (!(autoneg_status & IXGBE_MDIO_AUTO_NEG_LINK_STATUS)) |
1989 | *link_up = false; |
1990 | |
1991 | return 0; |
1992 | } |
1993 | |
1994 | /** |
1995 | * ixgbe_setup_sgmii - Set up link for sgmii |
1996 | * @hw: pointer to hardware structure |
1997 | * @speed: unused |
1998 | * @autoneg_wait_to_complete: unused |
1999 | */ |
2000 | static s32 |
2001 | ixgbe_setup_sgmii(struct ixgbe_hw *hw, __always_unused ixgbe_link_speed speed, |
2002 | __always_unused bool autoneg_wait_to_complete) |
2003 | { |
2004 | struct ixgbe_mac_info *mac = &hw->mac; |
2005 | u32 lval, sval, flx_val; |
2006 | s32 rc; |
2007 | |
2008 | rc = mac->ops.read_iosf_sb_reg(hw, |
2009 | IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), |
2010 | IXGBE_SB_IOSF_TARGET_KR_PHY, &lval); |
2011 | if (rc) |
2012 | return rc; |
2013 | |
2014 | lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; |
2015 | lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK; |
2016 | lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_SGMII_EN; |
2017 | lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CLAUSE_37_EN; |
2018 | lval |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G; |
2019 | rc = mac->ops.write_iosf_sb_reg(hw, |
2020 | IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), |
2021 | IXGBE_SB_IOSF_TARGET_KR_PHY, lval); |
2022 | if (rc) |
2023 | return rc; |
2024 | |
2025 | rc = mac->ops.read_iosf_sb_reg(hw, |
2026 | IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id), |
2027 | IXGBE_SB_IOSF_TARGET_KR_PHY, &sval); |
2028 | if (rc) |
2029 | return rc; |
2030 | |
2031 | sval |= IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_10_D; |
2032 | sval |= IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_100_D; |
2033 | rc = mac->ops.write_iosf_sb_reg(hw, |
2034 | IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id), |
2035 | IXGBE_SB_IOSF_TARGET_KR_PHY, sval); |
2036 | if (rc) |
2037 | return rc; |
2038 | |
2039 | rc = mac->ops.read_iosf_sb_reg(hw, |
2040 | IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), |
2041 | IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_val); |
2042 | if (rc) |
2043 | return rc; |
2044 | |
2045 | rc = mac->ops.read_iosf_sb_reg(hw, |
2046 | IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), |
2047 | IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_val); |
2048 | if (rc) |
2049 | return rc; |
2050 | |
2051 | flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK; |
2052 | flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_1G; |
2053 | flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN; |
2054 | flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN; |
2055 | flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN; |
2056 | |
2057 | rc = mac->ops.write_iosf_sb_reg(hw, |
2058 | IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), |
2059 | IXGBE_SB_IOSF_TARGET_KR_PHY, flx_val); |
2060 | if (rc) |
2061 | return rc; |
2062 | |
2063 | rc = ixgbe_restart_an_internal_phy_x550em(hw); |
2064 | return rc; |
2065 | } |
2066 | |
2067 | /** |
2068 | * ixgbe_setup_sgmii_fw - Set up link for sgmii with firmware-controlled PHYs |
2069 | * @hw: pointer to hardware structure |
2070 | * @speed: the link speed to force |
2071 | * @autoneg_wait: true when waiting for completion is needed |
2072 | */ |
2073 | static s32 ixgbe_setup_sgmii_fw(struct ixgbe_hw *hw, ixgbe_link_speed speed, |
2074 | bool autoneg_wait) |
2075 | { |
2076 | struct ixgbe_mac_info *mac = &hw->mac; |
2077 | u32 lval, sval, flx_val; |
2078 | s32 rc; |
2079 | |
2080 | rc = mac->ops.read_iosf_sb_reg(hw, |
2081 | IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), |
2082 | IXGBE_SB_IOSF_TARGET_KR_PHY, &lval); |
2083 | if (rc) |
2084 | return rc; |
2085 | |
2086 | lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; |
2087 | lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK; |
2088 | lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_SGMII_EN; |
2089 | lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CLAUSE_37_EN; |
2090 | lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G; |
2091 | rc = mac->ops.write_iosf_sb_reg(hw, |
2092 | IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), |
2093 | IXGBE_SB_IOSF_TARGET_KR_PHY, lval); |
2094 | if (rc) |
2095 | return rc; |
2096 | |
2097 | rc = mac->ops.read_iosf_sb_reg(hw, |
2098 | IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id), |
2099 | IXGBE_SB_IOSF_TARGET_KR_PHY, &sval); |
2100 | if (rc) |
2101 | return rc; |
2102 | |
2103 | sval &= ~IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_10_D; |
2104 | sval &= ~IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_100_D; |
2105 | rc = mac->ops.write_iosf_sb_reg(hw, |
2106 | IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id), |
2107 | IXGBE_SB_IOSF_TARGET_KR_PHY, sval); |
2108 | if (rc) |
2109 | return rc; |
2110 | |
2111 | rc = mac->ops.write_iosf_sb_reg(hw, |
2112 | IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), |
2113 | IXGBE_SB_IOSF_TARGET_KR_PHY, lval); |
2114 | if (rc) |
2115 | return rc; |
2116 | |
2117 | rc = mac->ops.read_iosf_sb_reg(hw, |
2118 | IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), |
2119 | IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_val); |
2120 | if (rc) |
2121 | return rc; |
2122 | |
2123 | flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK; |
2124 | flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_AN; |
2125 | flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN; |
2126 | flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN; |
2127 | flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN; |
2128 | |
2129 | rc = mac->ops.write_iosf_sb_reg(hw, |
2130 | IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), |
2131 | IXGBE_SB_IOSF_TARGET_KR_PHY, flx_val); |
2132 | if (rc) |
2133 | return rc; |
2134 | |
2135 | ixgbe_restart_an_internal_phy_x550em(hw); |
2136 | |
2137 | return hw->phy.ops.setup_link_speed(hw, speed, autoneg_wait); |
2138 | } |
2139 | |
2140 | /** |
2141 | * ixgbe_fc_autoneg_sgmii_x550em_a - Enable flow control IEEE clause 37 |
2142 | * @hw: pointer to hardware structure |
2143 | * |
2144 | * Enable flow control according to IEEE clause 37. |
2145 | */ |
2146 | static void ixgbe_fc_autoneg_sgmii_x550em_a(struct ixgbe_hw *hw) |
2147 | { |
2148 | s32 status = IXGBE_ERR_FC_NOT_NEGOTIATED; |
2149 | u32 info[FW_PHY_ACT_DATA_COUNT] = { 0 }; |
2150 | ixgbe_link_speed speed; |
2151 | bool link_up; |
2152 | |
2153 | /* AN should have completed when the cable was plugged in. |
2154 | * Look for reasons to bail out. Bail out if: |
2155 | * - FC autoneg is disabled, or if |
2156 | * - link is not up. |
2157 | */ |
2158 | if (hw->fc.disable_fc_autoneg) |
2159 | goto out; |
2160 | |
2161 | hw->mac.ops.check_link(hw, &speed, &link_up, false); |
2162 | if (!link_up) |
2163 | goto out; |
2164 | |
2165 | /* Check if auto-negotiation has completed */ |
2166 | status = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_GET_LINK_INFO, data: &info); |
2167 | if (status || !(info[0] & FW_PHY_ACT_GET_LINK_INFO_AN_COMPLETE)) { |
2168 | status = IXGBE_ERR_FC_NOT_NEGOTIATED; |
2169 | goto out; |
2170 | } |
2171 | |
2172 | /* Negotiate the flow control */ |
2173 | status = ixgbe_negotiate_fc(hw, adv_reg: info[0], lp_reg: info[0], |
2174 | FW_PHY_ACT_GET_LINK_INFO_FC_RX, |
2175 | FW_PHY_ACT_GET_LINK_INFO_FC_TX, |
2176 | FW_PHY_ACT_GET_LINK_INFO_LP_FC_RX, |
2177 | FW_PHY_ACT_GET_LINK_INFO_LP_FC_TX); |
2178 | |
2179 | out: |
2180 | if (!status) { |
2181 | hw->fc.fc_was_autonegged = true; |
2182 | } else { |
2183 | hw->fc.fc_was_autonegged = false; |
2184 | hw->fc.current_mode = hw->fc.requested_mode; |
2185 | } |
2186 | } |
2187 | |
2188 | /** ixgbe_init_mac_link_ops_X550em_a - Init mac link function pointers |
2189 | * @hw: pointer to hardware structure |
2190 | **/ |
2191 | static void ixgbe_init_mac_link_ops_X550em_a(struct ixgbe_hw *hw) |
2192 | { |
2193 | struct ixgbe_mac_info *mac = &hw->mac; |
2194 | |
2195 | switch (mac->ops.get_media_type(hw)) { |
2196 | case ixgbe_media_type_fiber: |
2197 | mac->ops.setup_fc = NULL; |
2198 | mac->ops.fc_autoneg = ixgbe_fc_autoneg_fiber_x550em_a; |
2199 | break; |
2200 | case ixgbe_media_type_copper: |
2201 | if (hw->device_id != IXGBE_DEV_ID_X550EM_A_1G_T && |
2202 | hw->device_id != IXGBE_DEV_ID_X550EM_A_1G_T_L) { |
2203 | mac->ops.setup_link = ixgbe_setup_mac_link_t_X550em; |
2204 | break; |
2205 | } |
2206 | mac->ops.fc_autoneg = ixgbe_fc_autoneg_sgmii_x550em_a; |
2207 | mac->ops.setup_fc = ixgbe_fc_autoneg_fw; |
2208 | mac->ops.setup_link = ixgbe_setup_sgmii_fw; |
2209 | mac->ops.check_link = ixgbe_check_mac_link_generic; |
2210 | break; |
2211 | case ixgbe_media_type_backplane: |
2212 | mac->ops.fc_autoneg = ixgbe_fc_autoneg_backplane_x550em_a; |
2213 | mac->ops.setup_fc = ixgbe_setup_fc_backplane_x550em_a; |
2214 | break; |
2215 | default: |
2216 | break; |
2217 | } |
2218 | } |
2219 | |
2220 | /** ixgbe_init_mac_link_ops_X550em - init mac link function pointers |
2221 | * @hw: pointer to hardware structure |
2222 | **/ |
2223 | static void ixgbe_init_mac_link_ops_X550em(struct ixgbe_hw *hw) |
2224 | { |
2225 | struct ixgbe_mac_info *mac = &hw->mac; |
2226 | |
2227 | mac->ops.setup_fc = ixgbe_setup_fc_x550em; |
2228 | |
2229 | switch (mac->ops.get_media_type(hw)) { |
2230 | case ixgbe_media_type_fiber: |
2231 | /* CS4227 does not support autoneg, so disable the laser control |
2232 | * functions for SFP+ fiber |
2233 | */ |
2234 | mac->ops.disable_tx_laser = NULL; |
2235 | mac->ops.enable_tx_laser = NULL; |
2236 | mac->ops.flap_tx_laser = NULL; |
2237 | mac->ops.setup_link = ixgbe_setup_mac_link_multispeed_fiber; |
2238 | switch (hw->device_id) { |
2239 | case IXGBE_DEV_ID_X550EM_A_SFP_N: |
2240 | mac->ops.setup_mac_link = ixgbe_setup_mac_link_sfp_n; |
2241 | break; |
2242 | case IXGBE_DEV_ID_X550EM_A_SFP: |
2243 | mac->ops.setup_mac_link = |
2244 | ixgbe_setup_mac_link_sfp_x550a; |
2245 | break; |
2246 | default: |
2247 | mac->ops.setup_mac_link = |
2248 | ixgbe_setup_mac_link_sfp_x550em; |
2249 | break; |
2250 | } |
2251 | mac->ops.set_rate_select_speed = |
2252 | ixgbe_set_soft_rate_select_speed; |
2253 | break; |
2254 | case ixgbe_media_type_copper: |
2255 | if (hw->device_id == IXGBE_DEV_ID_X550EM_X_1G_T) |
2256 | break; |
2257 | mac->ops.setup_link = ixgbe_setup_mac_link_t_X550em; |
2258 | mac->ops.setup_fc = ixgbe_setup_fc_generic; |
2259 | mac->ops.check_link = ixgbe_check_link_t_X550em; |
2260 | break; |
2261 | case ixgbe_media_type_backplane: |
2262 | if (hw->device_id == IXGBE_DEV_ID_X550EM_A_SGMII || |
2263 | hw->device_id == IXGBE_DEV_ID_X550EM_A_SGMII_L) |
2264 | mac->ops.setup_link = ixgbe_setup_sgmii; |
2265 | break; |
2266 | default: |
2267 | break; |
2268 | } |
2269 | |
2270 | /* Additional modification for X550em_a devices */ |
2271 | if (hw->mac.type == ixgbe_mac_x550em_a) |
2272 | ixgbe_init_mac_link_ops_X550em_a(hw); |
2273 | } |
2274 | |
2275 | /** ixgbe_setup_sfp_modules_X550em - Setup SFP module |
2276 | * @hw: pointer to hardware structure |
2277 | */ |
2278 | static s32 ixgbe_setup_sfp_modules_X550em(struct ixgbe_hw *hw) |
2279 | { |
2280 | s32 status; |
2281 | bool linear; |
2282 | |
2283 | /* Check if SFP module is supported */ |
2284 | status = ixgbe_supported_sfp_modules_X550em(hw, linear: &linear); |
2285 | if (status) |
2286 | return status; |
2287 | |
2288 | ixgbe_init_mac_link_ops_X550em(hw); |
2289 | hw->phy.ops.reset = NULL; |
2290 | |
2291 | return 0; |
2292 | } |
2293 | |
2294 | /** ixgbe_get_link_capabilities_x550em - Determines link capabilities |
2295 | * @hw: pointer to hardware structure |
2296 | * @speed: pointer to link speed |
2297 | * @autoneg: true when autoneg or autotry is enabled |
2298 | **/ |
2299 | static s32 ixgbe_get_link_capabilities_X550em(struct ixgbe_hw *hw, |
2300 | ixgbe_link_speed *speed, |
2301 | bool *autoneg) |
2302 | { |
2303 | if (hw->phy.type == ixgbe_phy_fw) { |
2304 | *autoneg = true; |
2305 | *speed = hw->phy.speeds_supported; |
2306 | return 0; |
2307 | } |
2308 | |
2309 | /* SFP */ |
2310 | if (hw->phy.media_type == ixgbe_media_type_fiber) { |
2311 | /* CS4227 SFP must not enable auto-negotiation */ |
2312 | *autoneg = false; |
2313 | |
2314 | if (hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 || |
2315 | hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1 || |
2316 | hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core0 || |
2317 | hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core1) { |
2318 | *speed = IXGBE_LINK_SPEED_1GB_FULL; |
2319 | return 0; |
2320 | } |
2321 | |
2322 | /* Link capabilities are based on SFP */ |
2323 | if (hw->phy.multispeed_fiber) |
2324 | *speed = IXGBE_LINK_SPEED_10GB_FULL | |
2325 | IXGBE_LINK_SPEED_1GB_FULL; |
2326 | else |
2327 | *speed = IXGBE_LINK_SPEED_10GB_FULL; |
2328 | } else { |
2329 | switch (hw->phy.type) { |
2330 | case ixgbe_phy_x550em_kx4: |
2331 | *speed = IXGBE_LINK_SPEED_1GB_FULL | |
2332 | IXGBE_LINK_SPEED_2_5GB_FULL | |
2333 | IXGBE_LINK_SPEED_10GB_FULL; |
2334 | break; |
2335 | case ixgbe_phy_x550em_xfi: |
2336 | *speed = IXGBE_LINK_SPEED_1GB_FULL | |
2337 | IXGBE_LINK_SPEED_10GB_FULL; |
2338 | break; |
2339 | case ixgbe_phy_ext_1g_t: |
2340 | case ixgbe_phy_sgmii: |
2341 | *speed = IXGBE_LINK_SPEED_1GB_FULL; |
2342 | break; |
2343 | case ixgbe_phy_x550em_kr: |
2344 | if (hw->mac.type == ixgbe_mac_x550em_a) { |
2345 | /* check different backplane modes */ |
2346 | if (hw->phy.nw_mng_if_sel & |
2347 | IXGBE_NW_MNG_IF_SEL_PHY_SPEED_2_5G) { |
2348 | *speed = IXGBE_LINK_SPEED_2_5GB_FULL; |
2349 | break; |
2350 | } else if (hw->device_id == |
2351 | IXGBE_DEV_ID_X550EM_A_KR_L) { |
2352 | *speed = IXGBE_LINK_SPEED_1GB_FULL; |
2353 | break; |
2354 | } |
2355 | } |
2356 | fallthrough; |
2357 | default: |
2358 | *speed = IXGBE_LINK_SPEED_10GB_FULL | |
2359 | IXGBE_LINK_SPEED_1GB_FULL; |
2360 | break; |
2361 | } |
2362 | *autoneg = true; |
2363 | } |
2364 | return 0; |
2365 | } |
2366 | |
2367 | /** |
2368 | * ixgbe_get_lasi_ext_t_x550em - Determime external Base T PHY interrupt cause |
2369 | * @hw: pointer to hardware structure |
2370 | * @lsc: pointer to boolean flag which indicates whether external Base T |
2371 | * PHY interrupt is lsc |
2372 | * |
2373 | * Determime if external Base T PHY interrupt cause is high temperature |
2374 | * failure alarm or link status change. |
2375 | * |
2376 | * Return IXGBE_ERR_OVERTEMP if interrupt is high temperature |
2377 | * failure alarm, else return PHY access status. |
2378 | **/ |
2379 | static s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc) |
2380 | { |
2381 | u32 status; |
2382 | u16 reg; |
2383 | |
2384 | *lsc = false; |
2385 | |
2386 | /* Vendor alarm triggered */ |
2387 | status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_CHIP_STD_INT_FLAG, |
2388 | MDIO_MMD_VEND1, |
2389 | ®); |
2390 | |
2391 | if (status || !(reg & IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN)) |
2392 | return status; |
2393 | |
2394 | /* Vendor Auto-Neg alarm triggered or Global alarm 1 triggered */ |
2395 | status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_FLAG, |
2396 | MDIO_MMD_VEND1, |
2397 | ®); |
2398 | |
2399 | if (status || !(reg & (IXGBE_MDIO_GLOBAL_AN_VEN_ALM_INT_EN | |
2400 | IXGBE_MDIO_GLOBAL_ALARM_1_INT))) |
2401 | return status; |
2402 | |
2403 | /* Global alarm triggered */ |
2404 | status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_ALARM_1, |
2405 | MDIO_MMD_VEND1, |
2406 | ®); |
2407 | |
2408 | if (status) |
2409 | return status; |
2410 | |
2411 | /* If high temperature failure, then return over temp error and exit */ |
2412 | if (reg & IXGBE_MDIO_GLOBAL_ALM_1_HI_TMP_FAIL) { |
2413 | /* power down the PHY in case the PHY FW didn't already */ |
2414 | ixgbe_set_copper_phy_power(hw, on: false); |
2415 | return IXGBE_ERR_OVERTEMP; |
2416 | } |
2417 | if (reg & IXGBE_MDIO_GLOBAL_ALM_1_DEV_FAULT) { |
2418 | /* device fault alarm triggered */ |
2419 | status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_FAULT_MSG, |
2420 | MDIO_MMD_VEND1, |
2421 | ®); |
2422 | if (status) |
2423 | return status; |
2424 | |
2425 | /* if device fault was due to high temp alarm handle and exit */ |
2426 | if (reg == IXGBE_MDIO_GLOBAL_FAULT_MSG_HI_TMP) { |
2427 | /* power down the PHY in case the PHY FW didn't */ |
2428 | ixgbe_set_copper_phy_power(hw, on: false); |
2429 | return IXGBE_ERR_OVERTEMP; |
2430 | } |
2431 | } |
2432 | |
2433 | /* Vendor alarm 2 triggered */ |
2434 | status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_CHIP_STD_INT_FLAG, |
2435 | MDIO_MMD_AN, ®); |
2436 | |
2437 | if (status || !(reg & IXGBE_MDIO_GLOBAL_STD_ALM2_INT)) |
2438 | return status; |
2439 | |
2440 | /* link connect/disconnect event occurred */ |
2441 | status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM2, |
2442 | MDIO_MMD_AN, ®); |
2443 | |
2444 | if (status) |
2445 | return status; |
2446 | |
2447 | /* Indicate LSC */ |
2448 | if (reg & IXGBE_MDIO_AUTO_NEG_VEN_LSC) |
2449 | *lsc = true; |
2450 | |
2451 | return 0; |
2452 | } |
2453 | |
2454 | /** |
2455 | * ixgbe_enable_lasi_ext_t_x550em - Enable external Base T PHY interrupts |
2456 | * @hw: pointer to hardware structure |
2457 | * |
2458 | * Enable link status change and temperature failure alarm for the external |
2459 | * Base T PHY |
2460 | * |
2461 | * Returns PHY access status |
2462 | **/ |
2463 | static s32 ixgbe_enable_lasi_ext_t_x550em(struct ixgbe_hw *hw) |
2464 | { |
2465 | u32 status; |
2466 | u16 reg; |
2467 | bool lsc; |
2468 | |
2469 | /* Clear interrupt flags */ |
2470 | status = ixgbe_get_lasi_ext_t_x550em(hw, lsc: &lsc); |
2471 | |
2472 | /* Enable link status change alarm */ |
2473 | |
2474 | /* Enable the LASI interrupts on X552 devices to receive notifications |
2475 | * of the link configurations of the external PHY and correspondingly |
2476 | * support the configuration of the internal iXFI link, since iXFI does |
2477 | * not support auto-negotiation. This is not required for X553 devices |
2478 | * having KR support, which performs auto-negotiations and which is used |
2479 | * as the internal link to the external PHY. Hence adding a check here |
2480 | * to avoid enabling LASI interrupts for X553 devices. |
2481 | */ |
2482 | if (hw->mac.type != ixgbe_mac_x550em_a) { |
2483 | status = hw->phy.ops.read_reg(hw, |
2484 | IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK, |
2485 | MDIO_MMD_AN, ®); |
2486 | if (status) |
2487 | return status; |
2488 | |
2489 | reg |= IXGBE_MDIO_PMA_TX_VEN_LASI_INT_EN; |
2490 | |
2491 | status = hw->phy.ops.write_reg(hw, |
2492 | IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK, |
2493 | MDIO_MMD_AN, reg); |
2494 | if (status) |
2495 | return status; |
2496 | } |
2497 | |
2498 | /* Enable high temperature failure and global fault alarms */ |
2499 | status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_MASK, |
2500 | MDIO_MMD_VEND1, |
2501 | ®); |
2502 | if (status) |
2503 | return status; |
2504 | |
2505 | reg |= (IXGBE_MDIO_GLOBAL_INT_HI_TEMP_EN | |
2506 | IXGBE_MDIO_GLOBAL_INT_DEV_FAULT_EN); |
2507 | |
2508 | status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_MASK, |
2509 | MDIO_MMD_VEND1, |
2510 | reg); |
2511 | if (status) |
2512 | return status; |
2513 | |
2514 | /* Enable vendor Auto-Neg alarm and Global Interrupt Mask 1 alarm */ |
2515 | status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK, |
2516 | MDIO_MMD_VEND1, |
2517 | ®); |
2518 | if (status) |
2519 | return status; |
2520 | |
2521 | reg |= (IXGBE_MDIO_GLOBAL_AN_VEN_ALM_INT_EN | |
2522 | IXGBE_MDIO_GLOBAL_ALARM_1_INT); |
2523 | |
2524 | status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK, |
2525 | MDIO_MMD_VEND1, |
2526 | reg); |
2527 | if (status) |
2528 | return status; |
2529 | |
2530 | /* Enable chip-wide vendor alarm */ |
2531 | status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_STD_MASK, |
2532 | MDIO_MMD_VEND1, |
2533 | ®); |
2534 | if (status) |
2535 | return status; |
2536 | |
2537 | reg |= IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN; |
2538 | |
2539 | status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_STD_MASK, |
2540 | MDIO_MMD_VEND1, |
2541 | reg); |
2542 | |
2543 | return status; |
2544 | } |
2545 | |
2546 | /** |
2547 | * ixgbe_handle_lasi_ext_t_x550em - Handle external Base T PHY interrupt |
2548 | * @hw: pointer to hardware structure |
2549 | * |
2550 | * Handle external Base T PHY interrupt. If high temperature |
2551 | * failure alarm then return error, else if link status change |
2552 | * then setup internal/external PHY link |
2553 | * |
2554 | * Return IXGBE_ERR_OVERTEMP if interrupt is high temperature |
2555 | * failure alarm, else return PHY access status. |
2556 | **/ |
2557 | static s32 ixgbe_handle_lasi_ext_t_x550em(struct ixgbe_hw *hw) |
2558 | { |
2559 | struct ixgbe_phy_info *phy = &hw->phy; |
2560 | bool lsc; |
2561 | u32 status; |
2562 | |
2563 | status = ixgbe_get_lasi_ext_t_x550em(hw, lsc: &lsc); |
2564 | if (status) |
2565 | return status; |
2566 | |
2567 | if (lsc && phy->ops.setup_internal_link) |
2568 | return phy->ops.setup_internal_link(hw); |
2569 | |
2570 | return 0; |
2571 | } |
2572 | |
2573 | /** |
2574 | * ixgbe_setup_kr_speed_x550em - Configure the KR PHY for link speed. |
2575 | * @hw: pointer to hardware structure |
2576 | * @speed: link speed |
2577 | * |
2578 | * Configures the integrated KR PHY. |
2579 | **/ |
2580 | static s32 ixgbe_setup_kr_speed_x550em(struct ixgbe_hw *hw, |
2581 | ixgbe_link_speed speed) |
2582 | { |
2583 | s32 status; |
2584 | u32 reg_val; |
2585 | |
2586 | status = hw->mac.ops.read_iosf_sb_reg(hw, |
2587 | IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), |
2588 | IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); |
2589 | if (status) |
2590 | return status; |
2591 | |
2592 | reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; |
2593 | reg_val &= ~(IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR | |
2594 | IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX); |
2595 | |
2596 | /* Advertise 10G support. */ |
2597 | if (speed & IXGBE_LINK_SPEED_10GB_FULL) |
2598 | reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR; |
2599 | |
2600 | /* Advertise 1G support. */ |
2601 | if (speed & IXGBE_LINK_SPEED_1GB_FULL) |
2602 | reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX; |
2603 | |
2604 | status = hw->mac.ops.write_iosf_sb_reg(hw, |
2605 | IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), |
2606 | IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); |
2607 | |
2608 | if (hw->mac.type == ixgbe_mac_x550em_a) { |
2609 | /* Set lane mode to KR auto negotiation */ |
2610 | status = hw->mac.ops.read_iosf_sb_reg(hw, |
2611 | IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), |
2612 | IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); |
2613 | |
2614 | if (status) |
2615 | return status; |
2616 | |
2617 | reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK; |
2618 | reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_AN; |
2619 | reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN; |
2620 | reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN; |
2621 | reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN; |
2622 | |
2623 | status = hw->mac.ops.write_iosf_sb_reg(hw, |
2624 | IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), |
2625 | IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); |
2626 | } |
2627 | |
2628 | return ixgbe_restart_an_internal_phy_x550em(hw); |
2629 | } |
2630 | |
2631 | /** |
2632 | * ixgbe_setup_kr_x550em - Configure the KR PHY |
2633 | * @hw: pointer to hardware structure |
2634 | **/ |
2635 | static s32 ixgbe_setup_kr_x550em(struct ixgbe_hw *hw) |
2636 | { |
2637 | /* leave link alone for 2.5G */ |
2638 | if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_2_5GB_FULL) |
2639 | return 0; |
2640 | |
2641 | if (ixgbe_check_reset_blocked(hw)) |
2642 | return 0; |
2643 | |
2644 | return ixgbe_setup_kr_speed_x550em(hw, speed: hw->phy.autoneg_advertised); |
2645 | } |
2646 | |
2647 | /** ixgbe_ext_phy_t_x550em_get_link - Get ext phy link status |
2648 | * @hw: address of hardware structure |
2649 | * @link_up: address of boolean to indicate link status |
2650 | * |
2651 | * Returns error code if unable to get link status. |
2652 | **/ |
2653 | static s32 ixgbe_ext_phy_t_x550em_get_link(struct ixgbe_hw *hw, bool *link_up) |
2654 | { |
2655 | u32 ret; |
2656 | u16 autoneg_status; |
2657 | |
2658 | *link_up = false; |
2659 | |
2660 | /* read this twice back to back to indicate current status */ |
2661 | ret = hw->phy.ops.read_reg(hw, MDIO_STAT1, MDIO_MMD_AN, |
2662 | &autoneg_status); |
2663 | if (ret) |
2664 | return ret; |
2665 | |
2666 | ret = hw->phy.ops.read_reg(hw, MDIO_STAT1, MDIO_MMD_AN, |
2667 | &autoneg_status); |
2668 | if (ret) |
2669 | return ret; |
2670 | |
2671 | *link_up = !!(autoneg_status & IXGBE_MDIO_AUTO_NEG_LINK_STATUS); |
2672 | |
2673 | return 0; |
2674 | } |
2675 | |
2676 | /** ixgbe_setup_internal_phy_t_x550em - Configure KR PHY to X557 link |
2677 | * @hw: point to hardware structure |
2678 | * |
2679 | * Configures the link between the integrated KR PHY and the external X557 PHY |
2680 | * The driver will call this function when it gets a link status change |
2681 | * interrupt from the X557 PHY. This function configures the link speed |
2682 | * between the PHYs to match the link speed of the BASE-T link. |
2683 | * |
2684 | * A return of a non-zero value indicates an error, and the base driver should |
2685 | * not report link up. |
2686 | **/ |
2687 | static s32 ixgbe_setup_internal_phy_t_x550em(struct ixgbe_hw *hw) |
2688 | { |
2689 | ixgbe_link_speed force_speed; |
2690 | bool link_up; |
2691 | u32 status; |
2692 | u16 speed; |
2693 | |
2694 | if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_copper) |
2695 | return IXGBE_ERR_CONFIG; |
2696 | |
2697 | if (!(hw->mac.type == ixgbe_mac_X550EM_x && |
2698 | !(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE))) { |
2699 | speed = IXGBE_LINK_SPEED_10GB_FULL | |
2700 | IXGBE_LINK_SPEED_1GB_FULL; |
2701 | return ixgbe_setup_kr_speed_x550em(hw, speed); |
2702 | } |
2703 | |
2704 | /* If link is not up, then there is no setup necessary so return */ |
2705 | status = ixgbe_ext_phy_t_x550em_get_link(hw, link_up: &link_up); |
2706 | if (status) |
2707 | return status; |
2708 | |
2709 | if (!link_up) |
2710 | return 0; |
2711 | |
2712 | status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_STAT, |
2713 | MDIO_MMD_AN, |
2714 | &speed); |
2715 | if (status) |
2716 | return status; |
2717 | |
2718 | /* If link is not still up, then no setup is necessary so return */ |
2719 | status = ixgbe_ext_phy_t_x550em_get_link(hw, link_up: &link_up); |
2720 | if (status) |
2721 | return status; |
2722 | |
2723 | if (!link_up) |
2724 | return 0; |
2725 | |
2726 | /* clear everything but the speed and duplex bits */ |
2727 | speed &= IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_MASK; |
2728 | |
2729 | switch (speed) { |
2730 | case IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB_FULL: |
2731 | force_speed = IXGBE_LINK_SPEED_10GB_FULL; |
2732 | break; |
2733 | case IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_1GB_FULL: |
2734 | force_speed = IXGBE_LINK_SPEED_1GB_FULL; |
2735 | break; |
2736 | default: |
2737 | /* Internal PHY does not support anything else */ |
2738 | return IXGBE_ERR_INVALID_LINK_SETTINGS; |
2739 | } |
2740 | |
2741 | return ixgbe_setup_ixfi_x550em(hw, speed: &force_speed); |
2742 | } |
2743 | |
2744 | /** ixgbe_reset_phy_t_X550em - Performs X557 PHY reset and enables LASI |
2745 | * @hw: pointer to hardware structure |
2746 | **/ |
2747 | static s32 ixgbe_reset_phy_t_X550em(struct ixgbe_hw *hw) |
2748 | { |
2749 | s32 status; |
2750 | |
2751 | status = ixgbe_reset_phy_generic(hw); |
2752 | |
2753 | if (status) |
2754 | return status; |
2755 | |
2756 | /* Configure Link Status Alarm and Temperature Threshold interrupts */ |
2757 | return ixgbe_enable_lasi_ext_t_x550em(hw); |
2758 | } |
2759 | |
2760 | /** |
2761 | * ixgbe_led_on_t_x550em - Turns on the software controllable LEDs. |
2762 | * @hw: pointer to hardware structure |
2763 | * @led_idx: led number to turn on |
2764 | **/ |
2765 | static s32 ixgbe_led_on_t_x550em(struct ixgbe_hw *hw, u32 led_idx) |
2766 | { |
2767 | u16 phy_data; |
2768 | |
2769 | if (led_idx >= IXGBE_X557_MAX_LED_INDEX) |
2770 | return IXGBE_ERR_PARAM; |
2771 | |
2772 | /* To turn on the LED, set mode to ON. */ |
2773 | hw->phy.ops.read_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx, |
2774 | MDIO_MMD_VEND1, &phy_data); |
2775 | phy_data |= IXGBE_X557_LED_MANUAL_SET_MASK; |
2776 | hw->phy.ops.write_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx, |
2777 | MDIO_MMD_VEND1, phy_data); |
2778 | |
2779 | return 0; |
2780 | } |
2781 | |
2782 | /** |
2783 | * ixgbe_led_off_t_x550em - Turns off the software controllable LEDs. |
2784 | * @hw: pointer to hardware structure |
2785 | * @led_idx: led number to turn off |
2786 | **/ |
2787 | static s32 ixgbe_led_off_t_x550em(struct ixgbe_hw *hw, u32 led_idx) |
2788 | { |
2789 | u16 phy_data; |
2790 | |
2791 | if (led_idx >= IXGBE_X557_MAX_LED_INDEX) |
2792 | return IXGBE_ERR_PARAM; |
2793 | |
2794 | /* To turn on the LED, set mode to ON. */ |
2795 | hw->phy.ops.read_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx, |
2796 | MDIO_MMD_VEND1, &phy_data); |
2797 | phy_data &= ~IXGBE_X557_LED_MANUAL_SET_MASK; |
2798 | hw->phy.ops.write_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx, |
2799 | MDIO_MMD_VEND1, phy_data); |
2800 | |
2801 | return 0; |
2802 | } |
2803 | |
2804 | /** |
2805 | * ixgbe_set_fw_drv_ver_x550 - Sends driver version to firmware |
2806 | * @hw: pointer to the HW structure |
2807 | * @maj: driver version major number |
2808 | * @min: driver version minor number |
2809 | * @build: driver version build number |
2810 | * @sub: driver version sub build number |
2811 | * @len: length of driver_ver string |
2812 | * @driver_ver: driver string |
2813 | * |
2814 | * Sends driver version number to firmware through the manageability |
2815 | * block. On success return 0 |
2816 | * else returns IXGBE_ERR_SWFW_SYNC when encountering an error acquiring |
2817 | * semaphore or IXGBE_ERR_HOST_INTERFACE_COMMAND when command fails. |
2818 | **/ |
2819 | static s32 ixgbe_set_fw_drv_ver_x550(struct ixgbe_hw *hw, u8 maj, u8 min, |
2820 | u8 build, u8 sub, u16 len, |
2821 | const char *driver_ver) |
2822 | { |
2823 | struct ixgbe_hic_drv_info2 fw_cmd; |
2824 | s32 ret_val; |
2825 | int i; |
2826 | |
2827 | if (!len || !driver_ver || (len > sizeof(fw_cmd.driver_string))) |
2828 | return IXGBE_ERR_INVALID_ARGUMENT; |
2829 | |
2830 | fw_cmd.hdr.cmd = FW_CEM_CMD_DRIVER_INFO; |
2831 | fw_cmd.hdr.buf_len = FW_CEM_CMD_DRIVER_INFO_LEN + len; |
2832 | fw_cmd.hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED; |
2833 | fw_cmd.port_num = (u8)hw->bus.func; |
2834 | fw_cmd.ver_maj = maj; |
2835 | fw_cmd.ver_min = min; |
2836 | fw_cmd.ver_build = build; |
2837 | fw_cmd.ver_sub = sub; |
2838 | fw_cmd.hdr.checksum = 0; |
2839 | memcpy(fw_cmd.driver_string, driver_ver, len); |
2840 | fw_cmd.hdr.checksum = ixgbe_calculate_checksum(buffer: (u8 *)&fw_cmd, |
2841 | length: (FW_CEM_HDR_LEN + fw_cmd.hdr.buf_len)); |
2842 | |
2843 | for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) { |
2844 | ret_val = ixgbe_host_interface_command(hw, (u32 *)&fw_cmd, |
2845 | length: sizeof(fw_cmd), |
2846 | IXGBE_HI_COMMAND_TIMEOUT, |
2847 | return_data: true); |
2848 | if (ret_val) |
2849 | continue; |
2850 | |
2851 | if (fw_cmd.hdr.cmd_or_resp.ret_status != |
2852 | FW_CEM_RESP_STATUS_SUCCESS) |
2853 | return IXGBE_ERR_HOST_INTERFACE_COMMAND; |
2854 | return 0; |
2855 | } |
2856 | |
2857 | return ret_val; |
2858 | } |
2859 | |
2860 | /** ixgbe_get_lcd_x550em - Determine lowest common denominator |
2861 | * @hw: pointer to hardware structure |
2862 | * @lcd_speed: pointer to lowest common link speed |
2863 | * |
2864 | * Determine lowest common link speed with link partner. |
2865 | **/ |
2866 | static s32 ixgbe_get_lcd_t_x550em(struct ixgbe_hw *hw, |
2867 | ixgbe_link_speed *lcd_speed) |
2868 | { |
2869 | u16 an_lp_status; |
2870 | s32 status; |
2871 | u16 word = hw->eeprom.ctrl_word_3; |
2872 | |
2873 | *lcd_speed = IXGBE_LINK_SPEED_UNKNOWN; |
2874 | |
2875 | status = hw->phy.ops.read_reg(hw, IXGBE_AUTO_NEG_LP_STATUS, |
2876 | MDIO_MMD_AN, |
2877 | &an_lp_status); |
2878 | if (status) |
2879 | return status; |
2880 | |
2881 | /* If link partner advertised 1G, return 1G */ |
2882 | if (an_lp_status & IXGBE_AUTO_NEG_LP_1000BASE_CAP) { |
2883 | *lcd_speed = IXGBE_LINK_SPEED_1GB_FULL; |
2884 | return status; |
2885 | } |
2886 | |
2887 | /* If 10G disabled for LPLU via NVM D10GMP, then return no valid LCD */ |
2888 | if ((hw->bus.lan_id && (word & NVM_INIT_CTRL_3_D10GMP_PORT1)) || |
2889 | (word & NVM_INIT_CTRL_3_D10GMP_PORT0)) |
2890 | return status; |
2891 | |
2892 | /* Link partner not capable of lower speeds, return 10G */ |
2893 | *lcd_speed = IXGBE_LINK_SPEED_10GB_FULL; |
2894 | return status; |
2895 | } |
2896 | |
2897 | /** |
2898 | * ixgbe_setup_fc_x550em - Set up flow control |
2899 | * @hw: pointer to hardware structure |
2900 | */ |
2901 | static s32 ixgbe_setup_fc_x550em(struct ixgbe_hw *hw) |
2902 | { |
2903 | bool pause, asm_dir; |
2904 | u32 reg_val; |
2905 | s32 rc = 0; |
2906 | |
2907 | /* Validate the requested mode */ |
2908 | if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) { |
2909 | hw_err(hw, "ixgbe_fc_rx_pause not valid in strict IEEE mode\n" ); |
2910 | return IXGBE_ERR_INVALID_LINK_SETTINGS; |
2911 | } |
2912 | |
2913 | /* 10gig parts do not have a word in the EEPROM to determine the |
2914 | * default flow control setting, so we explicitly set it to full. |
2915 | */ |
2916 | if (hw->fc.requested_mode == ixgbe_fc_default) |
2917 | hw->fc.requested_mode = ixgbe_fc_full; |
2918 | |
2919 | /* Determine PAUSE and ASM_DIR bits. */ |
2920 | switch (hw->fc.requested_mode) { |
2921 | case ixgbe_fc_none: |
2922 | pause = false; |
2923 | asm_dir = false; |
2924 | break; |
2925 | case ixgbe_fc_tx_pause: |
2926 | pause = false; |
2927 | asm_dir = true; |
2928 | break; |
2929 | case ixgbe_fc_rx_pause: |
2930 | /* Rx Flow control is enabled and Tx Flow control is |
2931 | * disabled by software override. Since there really |
2932 | * isn't a way to advertise that we are capable of RX |
2933 | * Pause ONLY, we will advertise that we support both |
2934 | * symmetric and asymmetric Rx PAUSE, as such we fall |
2935 | * through to the fc_full statement. Later, we will |
2936 | * disable the adapter's ability to send PAUSE frames. |
2937 | */ |
2938 | fallthrough; |
2939 | case ixgbe_fc_full: |
2940 | pause = true; |
2941 | asm_dir = true; |
2942 | break; |
2943 | default: |
2944 | hw_err(hw, "Flow control param set incorrectly\n" ); |
2945 | return IXGBE_ERR_CONFIG; |
2946 | } |
2947 | |
2948 | switch (hw->device_id) { |
2949 | case IXGBE_DEV_ID_X550EM_X_KR: |
2950 | case IXGBE_DEV_ID_X550EM_A_KR: |
2951 | case IXGBE_DEV_ID_X550EM_A_KR_L: |
2952 | rc = hw->mac.ops.read_iosf_sb_reg(hw, |
2953 | IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id), |
2954 | IXGBE_SB_IOSF_TARGET_KR_PHY, |
2955 | ®_val); |
2956 | if (rc) |
2957 | return rc; |
2958 | |
2959 | reg_val &= ~(IXGBE_KRM_AN_CNTL_1_SYM_PAUSE | |
2960 | IXGBE_KRM_AN_CNTL_1_ASM_PAUSE); |
2961 | if (pause) |
2962 | reg_val |= IXGBE_KRM_AN_CNTL_1_SYM_PAUSE; |
2963 | if (asm_dir) |
2964 | reg_val |= IXGBE_KRM_AN_CNTL_1_ASM_PAUSE; |
2965 | rc = hw->mac.ops.write_iosf_sb_reg(hw, |
2966 | IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id), |
2967 | IXGBE_SB_IOSF_TARGET_KR_PHY, |
2968 | reg_val); |
2969 | |
2970 | /* This device does not fully support AN. */ |
2971 | hw->fc.disable_fc_autoneg = true; |
2972 | break; |
2973 | case IXGBE_DEV_ID_X550EM_X_XFI: |
2974 | hw->fc.disable_fc_autoneg = true; |
2975 | break; |
2976 | default: |
2977 | break; |
2978 | } |
2979 | return rc; |
2980 | } |
2981 | |
2982 | /** |
2983 | * ixgbe_fc_autoneg_backplane_x550em_a - Enable flow control IEEE clause 37 |
2984 | * @hw: pointer to hardware structure |
2985 | **/ |
2986 | static void ixgbe_fc_autoneg_backplane_x550em_a(struct ixgbe_hw *hw) |
2987 | { |
2988 | u32 link_s1, lp_an_page_low, an_cntl_1; |
2989 | s32 status = IXGBE_ERR_FC_NOT_NEGOTIATED; |
2990 | ixgbe_link_speed speed; |
2991 | bool link_up; |
2992 | |
2993 | /* AN should have completed when the cable was plugged in. |
2994 | * Look for reasons to bail out. Bail out if: |
2995 | * - FC autoneg is disabled, or if |
2996 | * - link is not up. |
2997 | */ |
2998 | if (hw->fc.disable_fc_autoneg) { |
2999 | hw_err(hw, "Flow control autoneg is disabled" ); |
3000 | goto out; |
3001 | } |
3002 | |
3003 | hw->mac.ops.check_link(hw, &speed, &link_up, false); |
3004 | if (!link_up) { |
3005 | hw_err(hw, "The link is down" ); |
3006 | goto out; |
3007 | } |
3008 | |
3009 | /* Check at auto-negotiation has completed */ |
3010 | status = hw->mac.ops.read_iosf_sb_reg(hw, |
3011 | IXGBE_KRM_LINK_S1(hw->bus.lan_id), |
3012 | IXGBE_SB_IOSF_TARGET_KR_PHY, &link_s1); |
3013 | |
3014 | if (status || (link_s1 & IXGBE_KRM_LINK_S1_MAC_AN_COMPLETE) == 0) { |
3015 | hw_dbg(hw, "Auto-Negotiation did not complete\n" ); |
3016 | status = IXGBE_ERR_FC_NOT_NEGOTIATED; |
3017 | goto out; |
3018 | } |
3019 | |
3020 | /* Read the 10g AN autoc and LP ability registers and resolve |
3021 | * local flow control settings accordingly |
3022 | */ |
3023 | status = hw->mac.ops.read_iosf_sb_reg(hw, |
3024 | IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id), |
3025 | IXGBE_SB_IOSF_TARGET_KR_PHY, &an_cntl_1); |
3026 | |
3027 | if (status) { |
3028 | hw_dbg(hw, "Auto-Negotiation did not complete\n" ); |
3029 | goto out; |
3030 | } |
3031 | |
3032 | status = hw->mac.ops.read_iosf_sb_reg(hw, |
3033 | IXGBE_KRM_LP_BASE_PAGE_HIGH(hw->bus.lan_id), |
3034 | IXGBE_SB_IOSF_TARGET_KR_PHY, &lp_an_page_low); |
3035 | |
3036 | if (status) { |
3037 | hw_dbg(hw, "Auto-Negotiation did not complete\n" ); |
3038 | goto out; |
3039 | } |
3040 | |
3041 | status = ixgbe_negotiate_fc(hw, adv_reg: an_cntl_1, lp_reg: lp_an_page_low, |
3042 | IXGBE_KRM_AN_CNTL_1_SYM_PAUSE, |
3043 | IXGBE_KRM_AN_CNTL_1_ASM_PAUSE, |
3044 | IXGBE_KRM_LP_BASE_PAGE_HIGH_SYM_PAUSE, |
3045 | IXGBE_KRM_LP_BASE_PAGE_HIGH_ASM_PAUSE); |
3046 | |
3047 | out: |
3048 | if (!status) { |
3049 | hw->fc.fc_was_autonegged = true; |
3050 | } else { |
3051 | hw->fc.fc_was_autonegged = false; |
3052 | hw->fc.current_mode = hw->fc.requested_mode; |
3053 | } |
3054 | } |
3055 | |
3056 | /** |
3057 | * ixgbe_fc_autoneg_fiber_x550em_a - passthrough FC settings |
3058 | * @hw: pointer to hardware structure |
3059 | **/ |
3060 | static void ixgbe_fc_autoneg_fiber_x550em_a(struct ixgbe_hw *hw) |
3061 | { |
3062 | hw->fc.fc_was_autonegged = false; |
3063 | hw->fc.current_mode = hw->fc.requested_mode; |
3064 | } |
3065 | |
3066 | /** ixgbe_enter_lplu_x550em - Transition to low power states |
3067 | * @hw: pointer to hardware structure |
3068 | * |
3069 | * Configures Low Power Link Up on transition to low power states |
3070 | * (from D0 to non-D0). Link is required to enter LPLU so avoid resetting |
3071 | * the X557 PHY immediately prior to entering LPLU. |
3072 | **/ |
3073 | static s32 ixgbe_enter_lplu_t_x550em(struct ixgbe_hw *hw) |
3074 | { |
3075 | u16 an_10g_cntl_reg, autoneg_reg, speed; |
3076 | s32 status; |
3077 | ixgbe_link_speed lcd_speed; |
3078 | u32 save_autoneg; |
3079 | bool link_up; |
3080 | |
3081 | /* If blocked by MNG FW, then don't restart AN */ |
3082 | if (ixgbe_check_reset_blocked(hw)) |
3083 | return 0; |
3084 | |
3085 | status = ixgbe_ext_phy_t_x550em_get_link(hw, link_up: &link_up); |
3086 | if (status) |
3087 | return status; |
3088 | |
3089 | status = hw->eeprom.ops.read(hw, NVM_INIT_CTRL_3, |
3090 | &hw->eeprom.ctrl_word_3); |
3091 | if (status) |
3092 | return status; |
3093 | |
3094 | /* If link is down, LPLU disabled in NVM, WoL disabled, or |
3095 | * manageability disabled, then force link down by entering |
3096 | * low power mode. |
3097 | */ |
3098 | if (!link_up || !(hw->eeprom.ctrl_word_3 & NVM_INIT_CTRL_3_LPLU) || |
3099 | !(hw->wol_enabled || ixgbe_mng_present(hw))) |
3100 | return ixgbe_set_copper_phy_power(hw, on: false); |
3101 | |
3102 | /* Determine LCD */ |
3103 | status = ixgbe_get_lcd_t_x550em(hw, lcd_speed: &lcd_speed); |
3104 | if (status) |
3105 | return status; |
3106 | |
3107 | /* If no valid LCD link speed, then force link down and exit. */ |
3108 | if (lcd_speed == IXGBE_LINK_SPEED_UNKNOWN) |
3109 | return ixgbe_set_copper_phy_power(hw, on: false); |
3110 | |
3111 | status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_STAT, |
3112 | MDIO_MMD_AN, |
3113 | &speed); |
3114 | if (status) |
3115 | return status; |
3116 | |
3117 | /* If no link now, speed is invalid so take link down */ |
3118 | status = ixgbe_ext_phy_t_x550em_get_link(hw, link_up: &link_up); |
3119 | if (status) |
3120 | return ixgbe_set_copper_phy_power(hw, on: false); |
3121 | |
3122 | /* clear everything but the speed bits */ |
3123 | speed &= IXGBE_MDIO_AUTO_NEG_VEN_STAT_SPEED_MASK; |
3124 | |
3125 | /* If current speed is already LCD, then exit. */ |
3126 | if (((speed == IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_1GB) && |
3127 | (lcd_speed == IXGBE_LINK_SPEED_1GB_FULL)) || |
3128 | ((speed == IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB) && |
3129 | (lcd_speed == IXGBE_LINK_SPEED_10GB_FULL))) |
3130 | return status; |
3131 | |
3132 | /* Clear AN completed indication */ |
3133 | status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM, |
3134 | MDIO_MMD_AN, |
3135 | &autoneg_reg); |
3136 | if (status) |
3137 | return status; |
3138 | |
3139 | status = hw->phy.ops.read_reg(hw, MDIO_AN_10GBT_CTRL, |
3140 | MDIO_MMD_AN, |
3141 | &an_10g_cntl_reg); |
3142 | if (status) |
3143 | return status; |
3144 | |
3145 | status = hw->phy.ops.read_reg(hw, |
3146 | IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG, |
3147 | MDIO_MMD_AN, |
3148 | &autoneg_reg); |
3149 | if (status) |
3150 | return status; |
3151 | |
3152 | save_autoneg = hw->phy.autoneg_advertised; |
3153 | |
3154 | /* Setup link at least common link speed */ |
3155 | status = hw->mac.ops.setup_link(hw, lcd_speed, false); |
3156 | |
3157 | /* restore autoneg from before setting lplu speed */ |
3158 | hw->phy.autoneg_advertised = save_autoneg; |
3159 | |
3160 | return status; |
3161 | } |
3162 | |
3163 | /** |
3164 | * ixgbe_reset_phy_fw - Reset firmware-controlled PHYs |
3165 | * @hw: pointer to hardware structure |
3166 | */ |
3167 | static s32 ixgbe_reset_phy_fw(struct ixgbe_hw *hw) |
3168 | { |
3169 | u32 store[FW_PHY_ACT_DATA_COUNT] = { 0 }; |
3170 | s32 rc; |
3171 | |
3172 | if (hw->phy.reset_disable || ixgbe_check_reset_blocked(hw)) |
3173 | return 0; |
3174 | |
3175 | rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_PHY_SW_RESET, data: &store); |
3176 | if (rc) |
3177 | return rc; |
3178 | memset(store, 0, sizeof(store)); |
3179 | |
3180 | rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_INIT_PHY, data: &store); |
3181 | if (rc) |
3182 | return rc; |
3183 | |
3184 | return ixgbe_setup_fw_link(hw); |
3185 | } |
3186 | |
3187 | /** |
3188 | * ixgbe_check_overtemp_fw - Check firmware-controlled PHYs for overtemp |
3189 | * @hw: pointer to hardware structure |
3190 | */ |
3191 | static s32 ixgbe_check_overtemp_fw(struct ixgbe_hw *hw) |
3192 | { |
3193 | u32 store[FW_PHY_ACT_DATA_COUNT] = { 0 }; |
3194 | s32 rc; |
3195 | |
3196 | rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_GET_LINK_INFO, data: &store); |
3197 | if (rc) |
3198 | return rc; |
3199 | |
3200 | if (store[0] & FW_PHY_ACT_GET_LINK_INFO_TEMP) { |
3201 | ixgbe_shutdown_fw_phy(hw); |
3202 | return IXGBE_ERR_OVERTEMP; |
3203 | } |
3204 | return 0; |
3205 | } |
3206 | |
3207 | /** |
3208 | * ixgbe_read_mng_if_sel_x550em - Read NW_MNG_IF_SEL register |
3209 | * @hw: pointer to hardware structure |
3210 | * |
3211 | * Read NW_MNG_IF_SEL register and save field values. |
3212 | */ |
3213 | static void ixgbe_read_mng_if_sel_x550em(struct ixgbe_hw *hw) |
3214 | { |
3215 | /* Save NW management interface connected on board. This is used |
3216 | * to determine internal PHY mode. |
3217 | */ |
3218 | hw->phy.nw_mng_if_sel = IXGBE_READ_REG(hw, IXGBE_NW_MNG_IF_SEL); |
3219 | |
3220 | /* If X552 (X550EM_a) and MDIO is connected to external PHY, then set |
3221 | * PHY address. This register field was has only been used for X552. |
3222 | */ |
3223 | if (hw->mac.type == ixgbe_mac_x550em_a && |
3224 | hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_MDIO_ACT) { |
3225 | hw->phy.mdio.prtad = (hw->phy.nw_mng_if_sel & |
3226 | IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD) >> |
3227 | IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD_SHIFT; |
3228 | } |
3229 | } |
3230 | |
3231 | /** ixgbe_init_phy_ops_X550em - PHY/SFP specific init |
3232 | * @hw: pointer to hardware structure |
3233 | * |
3234 | * Initialize any function pointers that were not able to be |
3235 | * set during init_shared_code because the PHY/SFP type was |
3236 | * not known. Perform the SFP init if necessary. |
3237 | **/ |
3238 | static s32 ixgbe_init_phy_ops_X550em(struct ixgbe_hw *hw) |
3239 | { |
3240 | struct ixgbe_phy_info *phy = &hw->phy; |
3241 | s32 ret_val; |
3242 | |
3243 | hw->mac.ops.set_lan_id(hw); |
3244 | |
3245 | ixgbe_read_mng_if_sel_x550em(hw); |
3246 | |
3247 | if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber) { |
3248 | phy->phy_semaphore_mask = IXGBE_GSSR_SHARED_I2C_SM; |
3249 | ixgbe_setup_mux_ctl(hw); |
3250 | } |
3251 | |
3252 | /* Identify the PHY or SFP module */ |
3253 | ret_val = phy->ops.identify(hw); |
3254 | if (ret_val == IXGBE_ERR_SFP_NOT_SUPPORTED || |
3255 | ret_val == IXGBE_ERR_PHY_ADDR_INVALID) |
3256 | return ret_val; |
3257 | |
3258 | /* Setup function pointers based on detected hardware */ |
3259 | ixgbe_init_mac_link_ops_X550em(hw); |
3260 | if (phy->sfp_type != ixgbe_sfp_type_unknown) |
3261 | phy->ops.reset = NULL; |
3262 | |
3263 | /* Set functions pointers based on phy type */ |
3264 | switch (hw->phy.type) { |
3265 | case ixgbe_phy_x550em_kx4: |
3266 | phy->ops.setup_link = NULL; |
3267 | phy->ops.read_reg = ixgbe_read_phy_reg_x550em; |
3268 | phy->ops.write_reg = ixgbe_write_phy_reg_x550em; |
3269 | break; |
3270 | case ixgbe_phy_x550em_kr: |
3271 | phy->ops.setup_link = ixgbe_setup_kr_x550em; |
3272 | phy->ops.read_reg = ixgbe_read_phy_reg_x550em; |
3273 | phy->ops.write_reg = ixgbe_write_phy_reg_x550em; |
3274 | break; |
3275 | case ixgbe_phy_x550em_xfi: |
3276 | /* link is managed by HW */ |
3277 | phy->ops.setup_link = NULL; |
3278 | phy->ops.read_reg = ixgbe_read_phy_reg_x550em; |
3279 | phy->ops.write_reg = ixgbe_write_phy_reg_x550em; |
3280 | break; |
3281 | case ixgbe_phy_x550em_ext_t: |
3282 | /* Save NW management interface connected on board. This is used |
3283 | * to determine internal PHY mode |
3284 | */ |
3285 | phy->nw_mng_if_sel = IXGBE_READ_REG(hw, IXGBE_NW_MNG_IF_SEL); |
3286 | |
3287 | /* If internal link mode is XFI, then setup iXFI internal link, |
3288 | * else setup KR now. |
3289 | */ |
3290 | phy->ops.setup_internal_link = |
3291 | ixgbe_setup_internal_phy_t_x550em; |
3292 | |
3293 | /* setup SW LPLU only for first revision */ |
3294 | if (hw->mac.type == ixgbe_mac_X550EM_x && |
3295 | !(IXGBE_READ_REG(hw, IXGBE_FUSES0_GROUP(0)) & |
3296 | IXGBE_FUSES0_REV_MASK)) |
3297 | phy->ops.enter_lplu = ixgbe_enter_lplu_t_x550em; |
3298 | |
3299 | phy->ops.handle_lasi = ixgbe_handle_lasi_ext_t_x550em; |
3300 | phy->ops.reset = ixgbe_reset_phy_t_X550em; |
3301 | break; |
3302 | case ixgbe_phy_sgmii: |
3303 | phy->ops.setup_link = NULL; |
3304 | break; |
3305 | case ixgbe_phy_fw: |
3306 | phy->ops.setup_link = ixgbe_setup_fw_link; |
3307 | phy->ops.reset = ixgbe_reset_phy_fw; |
3308 | break; |
3309 | case ixgbe_phy_ext_1g_t: |
3310 | phy->ops.setup_link = NULL; |
3311 | phy->ops.read_reg = NULL; |
3312 | phy->ops.write_reg = NULL; |
3313 | phy->ops.reset = NULL; |
3314 | break; |
3315 | default: |
3316 | break; |
3317 | } |
3318 | |
3319 | return ret_val; |
3320 | } |
3321 | |
3322 | /** ixgbe_get_media_type_X550em - Get media type |
3323 | * @hw: pointer to hardware structure |
3324 | * |
3325 | * Returns the media type (fiber, copper, backplane) |
3326 | * |
3327 | */ |
3328 | static enum ixgbe_media_type ixgbe_get_media_type_X550em(struct ixgbe_hw *hw) |
3329 | { |
3330 | enum ixgbe_media_type media_type; |
3331 | |
3332 | /* Detect if there is a copper PHY attached. */ |
3333 | switch (hw->device_id) { |
3334 | case IXGBE_DEV_ID_X550EM_A_SGMII: |
3335 | case IXGBE_DEV_ID_X550EM_A_SGMII_L: |
3336 | hw->phy.type = ixgbe_phy_sgmii; |
3337 | fallthrough; |
3338 | case IXGBE_DEV_ID_X550EM_X_KR: |
3339 | case IXGBE_DEV_ID_X550EM_X_KX4: |
3340 | case IXGBE_DEV_ID_X550EM_X_XFI: |
3341 | case IXGBE_DEV_ID_X550EM_A_KR: |
3342 | case IXGBE_DEV_ID_X550EM_A_KR_L: |
3343 | media_type = ixgbe_media_type_backplane; |
3344 | break; |
3345 | case IXGBE_DEV_ID_X550EM_X_SFP: |
3346 | case IXGBE_DEV_ID_X550EM_A_SFP: |
3347 | case IXGBE_DEV_ID_X550EM_A_SFP_N: |
3348 | media_type = ixgbe_media_type_fiber; |
3349 | break; |
3350 | case IXGBE_DEV_ID_X550EM_X_1G_T: |
3351 | case IXGBE_DEV_ID_X550EM_X_10G_T: |
3352 | case IXGBE_DEV_ID_X550EM_A_10G_T: |
3353 | case IXGBE_DEV_ID_X550EM_A_1G_T: |
3354 | case IXGBE_DEV_ID_X550EM_A_1G_T_L: |
3355 | media_type = ixgbe_media_type_copper; |
3356 | break; |
3357 | default: |
3358 | media_type = ixgbe_media_type_unknown; |
3359 | break; |
3360 | } |
3361 | return media_type; |
3362 | } |
3363 | |
3364 | /** ixgbe_init_ext_t_x550em - Start (unstall) the external Base T PHY. |
3365 | ** @hw: pointer to hardware structure |
3366 | **/ |
3367 | static s32 ixgbe_init_ext_t_x550em(struct ixgbe_hw *hw) |
3368 | { |
3369 | s32 status; |
3370 | u16 reg; |
3371 | |
3372 | status = hw->phy.ops.read_reg(hw, |
3373 | IXGBE_MDIO_TX_VENDOR_ALARMS_3, |
3374 | MDIO_MMD_PMAPMD, |
3375 | ®); |
3376 | if (status) |
3377 | return status; |
3378 | |
3379 | /* If PHY FW reset completed bit is set then this is the first |
3380 | * SW instance after a power on so the PHY FW must be un-stalled. |
3381 | */ |
3382 | if (reg & IXGBE_MDIO_TX_VENDOR_ALARMS_3_RST_MASK) { |
3383 | status = hw->phy.ops.read_reg(hw, |
3384 | IXGBE_MDIO_GLOBAL_RES_PR_10, |
3385 | MDIO_MMD_VEND1, |
3386 | ®); |
3387 | if (status) |
3388 | return status; |
3389 | |
3390 | reg &= ~IXGBE_MDIO_POWER_UP_STALL; |
3391 | |
3392 | status = hw->phy.ops.write_reg(hw, |
3393 | IXGBE_MDIO_GLOBAL_RES_PR_10, |
3394 | MDIO_MMD_VEND1, |
3395 | reg); |
3396 | if (status) |
3397 | return status; |
3398 | } |
3399 | |
3400 | return status; |
3401 | } |
3402 | |
3403 | /** |
3404 | * ixgbe_set_mdio_speed - Set MDIO clock speed |
3405 | * @hw: pointer to hardware structure |
3406 | */ |
3407 | static void ixgbe_set_mdio_speed(struct ixgbe_hw *hw) |
3408 | { |
3409 | u32 hlreg0; |
3410 | |
3411 | switch (hw->device_id) { |
3412 | case IXGBE_DEV_ID_X550EM_X_10G_T: |
3413 | case IXGBE_DEV_ID_X550EM_A_SGMII: |
3414 | case IXGBE_DEV_ID_X550EM_A_SGMII_L: |
3415 | case IXGBE_DEV_ID_X550EM_A_10G_T: |
3416 | case IXGBE_DEV_ID_X550EM_A_SFP: |
3417 | /* Config MDIO clock speed before the first MDIO PHY access */ |
3418 | hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0); |
3419 | hlreg0 &= ~IXGBE_HLREG0_MDCSPD; |
3420 | IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0); |
3421 | break; |
3422 | case IXGBE_DEV_ID_X550EM_A_1G_T: |
3423 | case IXGBE_DEV_ID_X550EM_A_1G_T_L: |
3424 | /* Select fast MDIO clock speed for these devices */ |
3425 | hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0); |
3426 | hlreg0 |= IXGBE_HLREG0_MDCSPD; |
3427 | IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0); |
3428 | break; |
3429 | default: |
3430 | break; |
3431 | } |
3432 | } |
3433 | |
3434 | /** ixgbe_reset_hw_X550em - Perform hardware reset |
3435 | ** @hw: pointer to hardware structure |
3436 | ** |
3437 | ** Resets the hardware by resetting the transmit and receive units, masks |
3438 | ** and clears all interrupts, perform a PHY reset, and perform a link (MAC) |
3439 | ** reset. |
3440 | **/ |
3441 | static s32 ixgbe_reset_hw_X550em(struct ixgbe_hw *hw) |
3442 | { |
3443 | ixgbe_link_speed link_speed; |
3444 | s32 status; |
3445 | u32 ctrl = 0; |
3446 | u32 i; |
3447 | bool link_up = false; |
3448 | u32 swfw_mask = hw->phy.phy_semaphore_mask; |
3449 | |
3450 | /* Call adapter stop to disable Tx/Rx and clear interrupts */ |
3451 | status = hw->mac.ops.stop_adapter(hw); |
3452 | if (status) |
3453 | return status; |
3454 | |
3455 | /* flush pending Tx transactions */ |
3456 | ixgbe_clear_tx_pending(hw); |
3457 | |
3458 | /* set MDIO speed before talking to the PHY in case it's the 1st time */ |
3459 | ixgbe_set_mdio_speed(hw); |
3460 | |
3461 | /* PHY ops must be identified and initialized prior to reset */ |
3462 | status = hw->phy.ops.init(hw); |
3463 | if (status == IXGBE_ERR_SFP_NOT_SUPPORTED || |
3464 | status == IXGBE_ERR_PHY_ADDR_INVALID) |
3465 | return status; |
3466 | |
3467 | /* start the external PHY */ |
3468 | if (hw->phy.type == ixgbe_phy_x550em_ext_t) { |
3469 | status = ixgbe_init_ext_t_x550em(hw); |
3470 | if (status) |
3471 | return status; |
3472 | } |
3473 | |
3474 | /* Setup SFP module if there is one present. */ |
3475 | if (hw->phy.sfp_setup_needed) { |
3476 | status = hw->mac.ops.setup_sfp(hw); |
3477 | hw->phy.sfp_setup_needed = false; |
3478 | } |
3479 | |
3480 | if (status == IXGBE_ERR_SFP_NOT_SUPPORTED) |
3481 | return status; |
3482 | |
3483 | /* Reset PHY */ |
3484 | if (!hw->phy.reset_disable && hw->phy.ops.reset) |
3485 | hw->phy.ops.reset(hw); |
3486 | |
3487 | mac_reset_top: |
3488 | /* Issue global reset to the MAC. Needs to be SW reset if link is up. |
3489 | * If link reset is used when link is up, it might reset the PHY when |
3490 | * mng is using it. If link is down or the flag to force full link |
3491 | * reset is set, then perform link reset. |
3492 | */ |
3493 | ctrl = IXGBE_CTRL_LNK_RST; |
3494 | |
3495 | if (!hw->force_full_reset) { |
3496 | hw->mac.ops.check_link(hw, &link_speed, &link_up, false); |
3497 | if (link_up) |
3498 | ctrl = IXGBE_CTRL_RST; |
3499 | } |
3500 | |
3501 | status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask); |
3502 | if (status) { |
3503 | hw_dbg(hw, "semaphore failed with %d" , status); |
3504 | return IXGBE_ERR_SWFW_SYNC; |
3505 | } |
3506 | |
3507 | ctrl |= IXGBE_READ_REG(hw, IXGBE_CTRL); |
3508 | IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl); |
3509 | IXGBE_WRITE_FLUSH(hw); |
3510 | hw->mac.ops.release_swfw_sync(hw, swfw_mask); |
3511 | usleep_range(min: 1000, max: 1200); |
3512 | |
3513 | /* Poll for reset bit to self-clear meaning reset is complete */ |
3514 | for (i = 0; i < 10; i++) { |
3515 | ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL); |
3516 | if (!(ctrl & IXGBE_CTRL_RST_MASK)) |
3517 | break; |
3518 | udelay(1); |
3519 | } |
3520 | |
3521 | if (ctrl & IXGBE_CTRL_RST_MASK) { |
3522 | status = IXGBE_ERR_RESET_FAILED; |
3523 | hw_dbg(hw, "Reset polling failed to complete.\n" ); |
3524 | } |
3525 | |
3526 | msleep(msecs: 50); |
3527 | |
3528 | /* Double resets are required for recovery from certain error |
3529 | * clear the multicast table. Also reset num_rar_entries to 128, |
3530 | * since we modify this value when programming the SAN MAC address. |
3531 | */ |
3532 | if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) { |
3533 | hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED; |
3534 | goto mac_reset_top; |
3535 | } |
3536 | |
3537 | /* Store the permanent mac address */ |
3538 | hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr); |
3539 | |
3540 | /* Store MAC address from RAR0, clear receive address registers, and |
3541 | * clear the multicast table. Also reset num_rar_entries to 128, |
3542 | * since we modify this value when programming the SAN MAC address. |
3543 | */ |
3544 | hw->mac.num_rar_entries = 128; |
3545 | hw->mac.ops.init_rx_addrs(hw); |
3546 | |
3547 | ixgbe_set_mdio_speed(hw); |
3548 | |
3549 | if (hw->device_id == IXGBE_DEV_ID_X550EM_X_SFP) |
3550 | ixgbe_setup_mux_ctl(hw); |
3551 | |
3552 | return status; |
3553 | } |
3554 | |
3555 | /** ixgbe_set_ethertype_anti_spoofing_X550 - Enable/Disable Ethertype |
3556 | * anti-spoofing |
3557 | * @hw: pointer to hardware structure |
3558 | * @enable: enable or disable switch for Ethertype anti-spoofing |
3559 | * @vf: Virtual Function pool - VF Pool to set for Ethertype anti-spoofing |
3560 | **/ |
3561 | static void ixgbe_set_ethertype_anti_spoofing_X550(struct ixgbe_hw *hw, |
3562 | bool enable, int vf) |
3563 | { |
3564 | int vf_target_reg = vf >> 3; |
3565 | int vf_target_shift = vf % 8 + IXGBE_SPOOF_ETHERTYPEAS_SHIFT; |
3566 | u32 pfvfspoof; |
3567 | |
3568 | pfvfspoof = IXGBE_READ_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg)); |
3569 | if (enable) |
3570 | pfvfspoof |= BIT(vf_target_shift); |
3571 | else |
3572 | pfvfspoof &= ~BIT(vf_target_shift); |
3573 | |
3574 | IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg), pfvfspoof); |
3575 | } |
3576 | |
3577 | /** ixgbe_set_source_address_pruning_X550 - Enable/Disbale src address pruning |
3578 | * @hw: pointer to hardware structure |
3579 | * @enable: enable or disable source address pruning |
3580 | * @pool: Rx pool to set source address pruning for |
3581 | **/ |
3582 | static void ixgbe_set_source_address_pruning_X550(struct ixgbe_hw *hw, |
3583 | bool enable, |
3584 | unsigned int pool) |
3585 | { |
3586 | u64 pfflp; |
3587 | |
3588 | /* max rx pool is 63 */ |
3589 | if (pool > 63) |
3590 | return; |
3591 | |
3592 | pfflp = (u64)IXGBE_READ_REG(hw, IXGBE_PFFLPL); |
3593 | pfflp |= (u64)IXGBE_READ_REG(hw, IXGBE_PFFLPH) << 32; |
3594 | |
3595 | if (enable) |
3596 | pfflp |= (1ULL << pool); |
3597 | else |
3598 | pfflp &= ~(1ULL << pool); |
3599 | |
3600 | IXGBE_WRITE_REG(hw, IXGBE_PFFLPL, (u32)pfflp); |
3601 | IXGBE_WRITE_REG(hw, IXGBE_PFFLPH, (u32)(pfflp >> 32)); |
3602 | } |
3603 | |
3604 | /** |
3605 | * ixgbe_setup_fc_backplane_x550em_a - Set up flow control |
3606 | * @hw: pointer to hardware structure |
3607 | * |
3608 | * Called at init time to set up flow control. |
3609 | **/ |
3610 | static s32 ixgbe_setup_fc_backplane_x550em_a(struct ixgbe_hw *hw) |
3611 | { |
3612 | s32 status = 0; |
3613 | u32 an_cntl = 0; |
3614 | |
3615 | /* Validate the requested mode */ |
3616 | if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) { |
3617 | hw_err(hw, "ixgbe_fc_rx_pause not valid in strict IEEE mode\n" ); |
3618 | return IXGBE_ERR_INVALID_LINK_SETTINGS; |
3619 | } |
3620 | |
3621 | if (hw->fc.requested_mode == ixgbe_fc_default) |
3622 | hw->fc.requested_mode = ixgbe_fc_full; |
3623 | |
3624 | /* Set up the 1G and 10G flow control advertisement registers so the |
3625 | * HW will be able to do FC autoneg once the cable is plugged in. If |
3626 | * we link at 10G, the 1G advertisement is harmless and vice versa. |
3627 | */ |
3628 | status = hw->mac.ops.read_iosf_sb_reg(hw, |
3629 | IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id), |
3630 | IXGBE_SB_IOSF_TARGET_KR_PHY, &an_cntl); |
3631 | |
3632 | if (status) { |
3633 | hw_dbg(hw, "Auto-Negotiation did not complete\n" ); |
3634 | return status; |
3635 | } |
3636 | |
3637 | /* The possible values of fc.requested_mode are: |
3638 | * 0: Flow control is completely disabled |
3639 | * 1: Rx flow control is enabled (we can receive pause frames, |
3640 | * but not send pause frames). |
3641 | * 2: Tx flow control is enabled (we can send pause frames but |
3642 | * we do not support receiving pause frames). |
3643 | * 3: Both Rx and Tx flow control (symmetric) are enabled. |
3644 | * other: Invalid. |
3645 | */ |
3646 | switch (hw->fc.requested_mode) { |
3647 | case ixgbe_fc_none: |
3648 | /* Flow control completely disabled by software override. */ |
3649 | an_cntl &= ~(IXGBE_KRM_AN_CNTL_1_SYM_PAUSE | |
3650 | IXGBE_KRM_AN_CNTL_1_ASM_PAUSE); |
3651 | break; |
3652 | case ixgbe_fc_tx_pause: |
3653 | /* Tx Flow control is enabled, and Rx Flow control is |
3654 | * disabled by software override. |
3655 | */ |
3656 | an_cntl |= IXGBE_KRM_AN_CNTL_1_ASM_PAUSE; |
3657 | an_cntl &= ~IXGBE_KRM_AN_CNTL_1_SYM_PAUSE; |
3658 | break; |
3659 | case ixgbe_fc_rx_pause: |
3660 | /* Rx Flow control is enabled and Tx Flow control is |
3661 | * disabled by software override. Since there really |
3662 | * isn't a way to advertise that we are capable of RX |
3663 | * Pause ONLY, we will advertise that we support both |
3664 | * symmetric and asymmetric Rx PAUSE, as such we fall |
3665 | * through to the fc_full statement. Later, we will |
3666 | * disable the adapter's ability to send PAUSE frames. |
3667 | */ |
3668 | case ixgbe_fc_full: |
3669 | /* Flow control (both Rx and Tx) is enabled by SW override. */ |
3670 | an_cntl |= IXGBE_KRM_AN_CNTL_1_SYM_PAUSE | |
3671 | IXGBE_KRM_AN_CNTL_1_ASM_PAUSE; |
3672 | break; |
3673 | default: |
3674 | hw_err(hw, "Flow control param set incorrectly\n" ); |
3675 | return IXGBE_ERR_CONFIG; |
3676 | } |
3677 | |
3678 | status = hw->mac.ops.write_iosf_sb_reg(hw, |
3679 | IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id), |
3680 | IXGBE_SB_IOSF_TARGET_KR_PHY, an_cntl); |
3681 | |
3682 | /* Restart auto-negotiation. */ |
3683 | status = ixgbe_restart_an_internal_phy_x550em(hw); |
3684 | |
3685 | return status; |
3686 | } |
3687 | |
3688 | /** |
3689 | * ixgbe_set_mux - Set mux for port 1 access with CS4227 |
3690 | * @hw: pointer to hardware structure |
3691 | * @state: set mux if 1, clear if 0 |
3692 | */ |
3693 | static void ixgbe_set_mux(struct ixgbe_hw *hw, u8 state) |
3694 | { |
3695 | u32 esdp; |
3696 | |
3697 | if (!hw->bus.lan_id) |
3698 | return; |
3699 | esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); |
3700 | if (state) |
3701 | esdp |= IXGBE_ESDP_SDP1; |
3702 | else |
3703 | esdp &= ~IXGBE_ESDP_SDP1; |
3704 | IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); |
3705 | IXGBE_WRITE_FLUSH(hw); |
3706 | } |
3707 | |
3708 | /** |
3709 | * ixgbe_acquire_swfw_sync_X550em - Acquire SWFW semaphore |
3710 | * @hw: pointer to hardware structure |
3711 | * @mask: Mask to specify which semaphore to acquire |
3712 | * |
3713 | * Acquires the SWFW semaphore and sets the I2C MUX |
3714 | */ |
3715 | static s32 ixgbe_acquire_swfw_sync_X550em(struct ixgbe_hw *hw, u32 mask) |
3716 | { |
3717 | s32 status; |
3718 | |
3719 | status = ixgbe_acquire_swfw_sync_X540(hw, mask); |
3720 | if (status) |
3721 | return status; |
3722 | |
3723 | if (mask & IXGBE_GSSR_I2C_MASK) |
3724 | ixgbe_set_mux(hw, state: 1); |
3725 | |
3726 | return 0; |
3727 | } |
3728 | |
3729 | /** |
3730 | * ixgbe_release_swfw_sync_X550em - Release SWFW semaphore |
3731 | * @hw: pointer to hardware structure |
3732 | * @mask: Mask to specify which semaphore to release |
3733 | * |
3734 | * Releases the SWFW semaphore and sets the I2C MUX |
3735 | */ |
3736 | static void ixgbe_release_swfw_sync_X550em(struct ixgbe_hw *hw, u32 mask) |
3737 | { |
3738 | if (mask & IXGBE_GSSR_I2C_MASK) |
3739 | ixgbe_set_mux(hw, state: 0); |
3740 | |
3741 | ixgbe_release_swfw_sync_X540(hw, mask); |
3742 | } |
3743 | |
3744 | /** |
3745 | * ixgbe_acquire_swfw_sync_x550em_a - Acquire SWFW semaphore |
3746 | * @hw: pointer to hardware structure |
3747 | * @mask: Mask to specify which semaphore to acquire |
3748 | * |
3749 | * Acquires the SWFW semaphore and get the shared PHY token as needed |
3750 | */ |
3751 | static s32 ixgbe_acquire_swfw_sync_x550em_a(struct ixgbe_hw *hw, u32 mask) |
3752 | { |
3753 | u32 hmask = mask & ~IXGBE_GSSR_TOKEN_SM; |
3754 | int retries = FW_PHY_TOKEN_RETRIES; |
3755 | s32 status; |
3756 | |
3757 | while (--retries) { |
3758 | status = 0; |
3759 | if (hmask) |
3760 | status = ixgbe_acquire_swfw_sync_X540(hw, mask: hmask); |
3761 | if (status) |
3762 | return status; |
3763 | if (!(mask & IXGBE_GSSR_TOKEN_SM)) |
3764 | return 0; |
3765 | |
3766 | status = ixgbe_get_phy_token(hw); |
3767 | if (!status) |
3768 | return 0; |
3769 | if (hmask) |
3770 | ixgbe_release_swfw_sync_X540(hw, mask: hmask); |
3771 | if (status != IXGBE_ERR_TOKEN_RETRY) |
3772 | return status; |
3773 | msleep(FW_PHY_TOKEN_DELAY); |
3774 | } |
3775 | |
3776 | return status; |
3777 | } |
3778 | |
3779 | /** |
3780 | * ixgbe_release_swfw_sync_x550em_a - Release SWFW semaphore |
3781 | * @hw: pointer to hardware structure |
3782 | * @mask: Mask to specify which semaphore to release |
3783 | * |
3784 | * Release the SWFW semaphore and puts the shared PHY token as needed |
3785 | */ |
3786 | static void ixgbe_release_swfw_sync_x550em_a(struct ixgbe_hw *hw, u32 mask) |
3787 | { |
3788 | u32 hmask = mask & ~IXGBE_GSSR_TOKEN_SM; |
3789 | |
3790 | if (mask & IXGBE_GSSR_TOKEN_SM) |
3791 | ixgbe_put_phy_token(hw); |
3792 | |
3793 | if (hmask) |
3794 | ixgbe_release_swfw_sync_X540(hw, mask: hmask); |
3795 | } |
3796 | |
3797 | /** |
3798 | * ixgbe_read_phy_reg_x550a - Reads specified PHY register |
3799 | * @hw: pointer to hardware structure |
3800 | * @reg_addr: 32 bit address of PHY register to read |
3801 | * @device_type: 5 bit device type |
3802 | * @phy_data: Pointer to read data from PHY register |
3803 | * |
3804 | * Reads a value from a specified PHY register using the SWFW lock and PHY |
3805 | * Token. The PHY Token is needed since the MDIO is shared between to MAC |
3806 | * instances. |
3807 | */ |
3808 | static s32 ixgbe_read_phy_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr, |
3809 | u32 device_type, u16 *phy_data) |
3810 | { |
3811 | u32 mask = hw->phy.phy_semaphore_mask | IXGBE_GSSR_TOKEN_SM; |
3812 | s32 status; |
3813 | |
3814 | if (hw->mac.ops.acquire_swfw_sync(hw, mask)) |
3815 | return IXGBE_ERR_SWFW_SYNC; |
3816 | |
3817 | status = hw->phy.ops.read_reg_mdi(hw, reg_addr, device_type, phy_data); |
3818 | |
3819 | hw->mac.ops.release_swfw_sync(hw, mask); |
3820 | |
3821 | return status; |
3822 | } |
3823 | |
3824 | /** |
3825 | * ixgbe_write_phy_reg_x550a - Writes specified PHY register |
3826 | * @hw: pointer to hardware structure |
3827 | * @reg_addr: 32 bit PHY register to write |
3828 | * @device_type: 5 bit device type |
3829 | * @phy_data: Data to write to the PHY register |
3830 | * |
3831 | * Writes a value to specified PHY register using the SWFW lock and PHY Token. |
3832 | * The PHY Token is needed since the MDIO is shared between to MAC instances. |
3833 | */ |
3834 | static s32 ixgbe_write_phy_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr, |
3835 | u32 device_type, u16 phy_data) |
3836 | { |
3837 | u32 mask = hw->phy.phy_semaphore_mask | IXGBE_GSSR_TOKEN_SM; |
3838 | s32 status; |
3839 | |
3840 | if (hw->mac.ops.acquire_swfw_sync(hw, mask)) |
3841 | return IXGBE_ERR_SWFW_SYNC; |
3842 | |
3843 | status = ixgbe_write_phy_reg_mdi(hw, reg_addr, device_type, phy_data); |
3844 | hw->mac.ops.release_swfw_sync(hw, mask); |
3845 | |
3846 | return status; |
3847 | } |
3848 | |
3849 | #define X550_COMMON_MAC \ |
3850 | .init_hw = &ixgbe_init_hw_generic, \ |
3851 | .start_hw = &ixgbe_start_hw_X540, \ |
3852 | .clear_hw_cntrs = &ixgbe_clear_hw_cntrs_generic, \ |
3853 | .enable_rx_dma = &ixgbe_enable_rx_dma_generic, \ |
3854 | .get_mac_addr = &ixgbe_get_mac_addr_generic, \ |
3855 | .get_device_caps = &ixgbe_get_device_caps_generic, \ |
3856 | .stop_adapter = &ixgbe_stop_adapter_generic, \ |
3857 | .set_lan_id = &ixgbe_set_lan_id_multi_port_pcie, \ |
3858 | .read_analog_reg8 = NULL, \ |
3859 | .write_analog_reg8 = NULL, \ |
3860 | .set_rxpba = &ixgbe_set_rxpba_generic, \ |
3861 | .check_link = &ixgbe_check_mac_link_generic, \ |
3862 | .blink_led_start = &ixgbe_blink_led_start_X540, \ |
3863 | .blink_led_stop = &ixgbe_blink_led_stop_X540, \ |
3864 | .set_rar = &ixgbe_set_rar_generic, \ |
3865 | .clear_rar = &ixgbe_clear_rar_generic, \ |
3866 | .set_vmdq = &ixgbe_set_vmdq_generic, \ |
3867 | .set_vmdq_san_mac = &ixgbe_set_vmdq_san_mac_generic, \ |
3868 | .clear_vmdq = &ixgbe_clear_vmdq_generic, \ |
3869 | .init_rx_addrs = &ixgbe_init_rx_addrs_generic, \ |
3870 | .update_mc_addr_list = &ixgbe_update_mc_addr_list_generic, \ |
3871 | .enable_mc = &ixgbe_enable_mc_generic, \ |
3872 | .disable_mc = &ixgbe_disable_mc_generic, \ |
3873 | .clear_vfta = &ixgbe_clear_vfta_generic, \ |
3874 | .set_vfta = &ixgbe_set_vfta_generic, \ |
3875 | .fc_enable = &ixgbe_fc_enable_generic, \ |
3876 | .set_fw_drv_ver = &ixgbe_set_fw_drv_ver_x550, \ |
3877 | .init_uta_tables = &ixgbe_init_uta_tables_generic, \ |
3878 | .set_mac_anti_spoofing = &ixgbe_set_mac_anti_spoofing, \ |
3879 | .set_vlan_anti_spoofing = &ixgbe_set_vlan_anti_spoofing, \ |
3880 | .set_source_address_pruning = \ |
3881 | &ixgbe_set_source_address_pruning_X550, \ |
3882 | .set_ethertype_anti_spoofing = \ |
3883 | &ixgbe_set_ethertype_anti_spoofing_X550, \ |
3884 | .disable_rx_buff = &ixgbe_disable_rx_buff_generic, \ |
3885 | .enable_rx_buff = &ixgbe_enable_rx_buff_generic, \ |
3886 | .get_thermal_sensor_data = NULL, \ |
3887 | .init_thermal_sensor_thresh = NULL, \ |
3888 | .fw_recovery_mode = &ixgbe_fw_recovery_mode_X550, \ |
3889 | .enable_rx = &ixgbe_enable_rx_generic, \ |
3890 | .disable_rx = &ixgbe_disable_rx_x550, \ |
3891 | |
3892 | static const struct ixgbe_mac_operations mac_ops_X550 = { |
3893 | X550_COMMON_MAC |
3894 | .led_on = ixgbe_led_on_generic, |
3895 | .led_off = ixgbe_led_off_generic, |
3896 | .init_led_link_act = ixgbe_init_led_link_act_generic, |
3897 | .reset_hw = &ixgbe_reset_hw_X540, |
3898 | .get_media_type = &ixgbe_get_media_type_X540, |
3899 | .get_san_mac_addr = &ixgbe_get_san_mac_addr_generic, |
3900 | .get_wwn_prefix = &ixgbe_get_wwn_prefix_generic, |
3901 | .setup_link = &ixgbe_setup_mac_link_X540, |
3902 | .get_link_capabilities = &ixgbe_get_copper_link_capabilities_generic, |
3903 | .get_bus_info = &ixgbe_get_bus_info_generic, |
3904 | .setup_sfp = NULL, |
3905 | .acquire_swfw_sync = &ixgbe_acquire_swfw_sync_X540, |
3906 | .release_swfw_sync = &ixgbe_release_swfw_sync_X540, |
3907 | .init_swfw_sync = &ixgbe_init_swfw_sync_X540, |
3908 | .prot_autoc_read = prot_autoc_read_generic, |
3909 | .prot_autoc_write = prot_autoc_write_generic, |
3910 | .setup_fc = ixgbe_setup_fc_generic, |
3911 | .fc_autoneg = ixgbe_fc_autoneg, |
3912 | }; |
3913 | |
3914 | static const struct ixgbe_mac_operations mac_ops_X550EM_x = { |
3915 | X550_COMMON_MAC |
3916 | .led_on = ixgbe_led_on_t_x550em, |
3917 | .led_off = ixgbe_led_off_t_x550em, |
3918 | .init_led_link_act = ixgbe_init_led_link_act_generic, |
3919 | .reset_hw = &ixgbe_reset_hw_X550em, |
3920 | .get_media_type = &ixgbe_get_media_type_X550em, |
3921 | .get_san_mac_addr = NULL, |
3922 | .get_wwn_prefix = NULL, |
3923 | .setup_link = &ixgbe_setup_mac_link_X540, |
3924 | .get_link_capabilities = &ixgbe_get_link_capabilities_X550em, |
3925 | .get_bus_info = &ixgbe_get_bus_info_X550em, |
3926 | .setup_sfp = ixgbe_setup_sfp_modules_X550em, |
3927 | .acquire_swfw_sync = &ixgbe_acquire_swfw_sync_X550em, |
3928 | .release_swfw_sync = &ixgbe_release_swfw_sync_X550em, |
3929 | .init_swfw_sync = &ixgbe_init_swfw_sync_X540, |
3930 | .setup_fc = NULL, /* defined later */ |
3931 | .fc_autoneg = ixgbe_fc_autoneg, |
3932 | .read_iosf_sb_reg = ixgbe_read_iosf_sb_reg_x550, |
3933 | .write_iosf_sb_reg = ixgbe_write_iosf_sb_reg_x550, |
3934 | }; |
3935 | |
3936 | static const struct ixgbe_mac_operations mac_ops_X550EM_x_fw = { |
3937 | X550_COMMON_MAC |
3938 | .led_on = NULL, |
3939 | .led_off = NULL, |
3940 | .init_led_link_act = NULL, |
3941 | .reset_hw = &ixgbe_reset_hw_X550em, |
3942 | .get_media_type = &ixgbe_get_media_type_X550em, |
3943 | .get_san_mac_addr = NULL, |
3944 | .get_wwn_prefix = NULL, |
3945 | .setup_link = &ixgbe_setup_mac_link_X540, |
3946 | .get_link_capabilities = &ixgbe_get_link_capabilities_X550em, |
3947 | .get_bus_info = &ixgbe_get_bus_info_X550em, |
3948 | .setup_sfp = ixgbe_setup_sfp_modules_X550em, |
3949 | .acquire_swfw_sync = &ixgbe_acquire_swfw_sync_X550em, |
3950 | .release_swfw_sync = &ixgbe_release_swfw_sync_X550em, |
3951 | .init_swfw_sync = &ixgbe_init_swfw_sync_X540, |
3952 | .setup_fc = NULL, |
3953 | .fc_autoneg = ixgbe_fc_autoneg, |
3954 | .read_iosf_sb_reg = ixgbe_read_iosf_sb_reg_x550, |
3955 | .write_iosf_sb_reg = ixgbe_write_iosf_sb_reg_x550, |
3956 | }; |
3957 | |
3958 | static const struct ixgbe_mac_operations mac_ops_x550em_a = { |
3959 | X550_COMMON_MAC |
3960 | .led_on = ixgbe_led_on_t_x550em, |
3961 | .led_off = ixgbe_led_off_t_x550em, |
3962 | .init_led_link_act = ixgbe_init_led_link_act_generic, |
3963 | .reset_hw = ixgbe_reset_hw_X550em, |
3964 | .get_media_type = ixgbe_get_media_type_X550em, |
3965 | .get_san_mac_addr = NULL, |
3966 | .get_wwn_prefix = NULL, |
3967 | .setup_link = &ixgbe_setup_mac_link_X540, |
3968 | .get_link_capabilities = ixgbe_get_link_capabilities_X550em, |
3969 | .get_bus_info = ixgbe_get_bus_info_X550em, |
3970 | .setup_sfp = ixgbe_setup_sfp_modules_X550em, |
3971 | .acquire_swfw_sync = ixgbe_acquire_swfw_sync_x550em_a, |
3972 | .release_swfw_sync = ixgbe_release_swfw_sync_x550em_a, |
3973 | .setup_fc = ixgbe_setup_fc_x550em, |
3974 | .fc_autoneg = ixgbe_fc_autoneg, |
3975 | .read_iosf_sb_reg = ixgbe_read_iosf_sb_reg_x550a, |
3976 | .write_iosf_sb_reg = ixgbe_write_iosf_sb_reg_x550a, |
3977 | }; |
3978 | |
3979 | static const struct ixgbe_mac_operations mac_ops_x550em_a_fw = { |
3980 | X550_COMMON_MAC |
3981 | .led_on = ixgbe_led_on_generic, |
3982 | .led_off = ixgbe_led_off_generic, |
3983 | .init_led_link_act = ixgbe_init_led_link_act_generic, |
3984 | .reset_hw = ixgbe_reset_hw_X550em, |
3985 | .get_media_type = ixgbe_get_media_type_X550em, |
3986 | .get_san_mac_addr = NULL, |
3987 | .get_wwn_prefix = NULL, |
3988 | .setup_link = NULL, /* defined later */ |
3989 | .get_link_capabilities = ixgbe_get_link_capabilities_X550em, |
3990 | .get_bus_info = ixgbe_get_bus_info_X550em, |
3991 | .setup_sfp = ixgbe_setup_sfp_modules_X550em, |
3992 | .acquire_swfw_sync = ixgbe_acquire_swfw_sync_x550em_a, |
3993 | .release_swfw_sync = ixgbe_release_swfw_sync_x550em_a, |
3994 | .setup_fc = ixgbe_setup_fc_x550em, |
3995 | .fc_autoneg = ixgbe_fc_autoneg, |
3996 | .read_iosf_sb_reg = ixgbe_read_iosf_sb_reg_x550a, |
3997 | .write_iosf_sb_reg = ixgbe_write_iosf_sb_reg_x550a, |
3998 | }; |
3999 | |
4000 | #define X550_COMMON_EEP \ |
4001 | .read = &ixgbe_read_ee_hostif_X550, \ |
4002 | .read_buffer = &ixgbe_read_ee_hostif_buffer_X550, \ |
4003 | .write = &ixgbe_write_ee_hostif_X550, \ |
4004 | .write_buffer = &ixgbe_write_ee_hostif_buffer_X550, \ |
4005 | .validate_checksum = &ixgbe_validate_eeprom_checksum_X550, \ |
4006 | .update_checksum = &ixgbe_update_eeprom_checksum_X550, \ |
4007 | .calc_checksum = &ixgbe_calc_eeprom_checksum_X550, \ |
4008 | |
4009 | static const struct ixgbe_eeprom_operations eeprom_ops_X550 = { |
4010 | X550_COMMON_EEP |
4011 | .init_params = &ixgbe_init_eeprom_params_X550, |
4012 | }; |
4013 | |
4014 | static const struct ixgbe_eeprom_operations eeprom_ops_X550EM_x = { |
4015 | X550_COMMON_EEP |
4016 | .init_params = &ixgbe_init_eeprom_params_X540, |
4017 | }; |
4018 | |
4019 | #define X550_COMMON_PHY \ |
4020 | .identify_sfp = &ixgbe_identify_module_generic, \ |
4021 | .reset = NULL, \ |
4022 | .setup_link_speed = &ixgbe_setup_phy_link_speed_generic, \ |
4023 | .read_i2c_byte = &ixgbe_read_i2c_byte_generic, \ |
4024 | .write_i2c_byte = &ixgbe_write_i2c_byte_generic, \ |
4025 | .read_i2c_sff8472 = &ixgbe_read_i2c_sff8472_generic, \ |
4026 | .read_i2c_eeprom = &ixgbe_read_i2c_eeprom_generic, \ |
4027 | .write_i2c_eeprom = &ixgbe_write_i2c_eeprom_generic, \ |
4028 | .setup_link = &ixgbe_setup_phy_link_generic, \ |
4029 | .set_phy_power = NULL, |
4030 | |
4031 | static const struct ixgbe_phy_operations phy_ops_X550 = { |
4032 | X550_COMMON_PHY |
4033 | .check_overtemp = &ixgbe_tn_check_overtemp, |
4034 | .init = NULL, |
4035 | .identify = &ixgbe_identify_phy_generic, |
4036 | .read_reg = &ixgbe_read_phy_reg_generic, |
4037 | .write_reg = &ixgbe_write_phy_reg_generic, |
4038 | }; |
4039 | |
4040 | static const struct ixgbe_phy_operations phy_ops_X550EM_x = { |
4041 | X550_COMMON_PHY |
4042 | .check_overtemp = &ixgbe_tn_check_overtemp, |
4043 | .init = &ixgbe_init_phy_ops_X550em, |
4044 | .identify = &ixgbe_identify_phy_x550em, |
4045 | .read_reg = &ixgbe_read_phy_reg_generic, |
4046 | .write_reg = &ixgbe_write_phy_reg_generic, |
4047 | }; |
4048 | |
4049 | static const struct ixgbe_phy_operations phy_ops_x550em_x_fw = { |
4050 | X550_COMMON_PHY |
4051 | .check_overtemp = NULL, |
4052 | .init = ixgbe_init_phy_ops_X550em, |
4053 | .identify = ixgbe_identify_phy_x550em, |
4054 | .read_reg = NULL, |
4055 | .write_reg = NULL, |
4056 | .read_reg_mdi = NULL, |
4057 | .write_reg_mdi = NULL, |
4058 | }; |
4059 | |
4060 | static const struct ixgbe_phy_operations phy_ops_x550em_a = { |
4061 | X550_COMMON_PHY |
4062 | .check_overtemp = &ixgbe_tn_check_overtemp, |
4063 | .init = &ixgbe_init_phy_ops_X550em, |
4064 | .identify = &ixgbe_identify_phy_x550em, |
4065 | .read_reg = &ixgbe_read_phy_reg_x550a, |
4066 | .write_reg = &ixgbe_write_phy_reg_x550a, |
4067 | .read_reg_mdi = &ixgbe_read_phy_reg_mdi, |
4068 | .write_reg_mdi = &ixgbe_write_phy_reg_mdi, |
4069 | }; |
4070 | |
4071 | static const struct ixgbe_phy_operations phy_ops_x550em_a_fw = { |
4072 | X550_COMMON_PHY |
4073 | .check_overtemp = ixgbe_check_overtemp_fw, |
4074 | .init = ixgbe_init_phy_ops_X550em, |
4075 | .identify = ixgbe_identify_phy_fw, |
4076 | .read_reg = NULL, |
4077 | .write_reg = NULL, |
4078 | .read_reg_mdi = NULL, |
4079 | .write_reg_mdi = NULL, |
4080 | }; |
4081 | |
4082 | static const struct ixgbe_link_operations link_ops_x550em_x = { |
4083 | .read_link = &ixgbe_read_i2c_combined_generic, |
4084 | .read_link_unlocked = &ixgbe_read_i2c_combined_generic_unlocked, |
4085 | .write_link = &ixgbe_write_i2c_combined_generic, |
4086 | .write_link_unlocked = &ixgbe_write_i2c_combined_generic_unlocked, |
4087 | }; |
4088 | |
4089 | static const u32 ixgbe_mvals_X550[IXGBE_MVALS_IDX_LIMIT] = { |
4090 | IXGBE_MVALS_INIT(X550) |
4091 | }; |
4092 | |
4093 | static const u32 ixgbe_mvals_X550EM_x[IXGBE_MVALS_IDX_LIMIT] = { |
4094 | IXGBE_MVALS_INIT(X550EM_x) |
4095 | }; |
4096 | |
4097 | static const u32 ixgbe_mvals_x550em_a[IXGBE_MVALS_IDX_LIMIT] = { |
4098 | IXGBE_MVALS_INIT(X550EM_a) |
4099 | }; |
4100 | |
4101 | const struct ixgbe_info ixgbe_X550_info = { |
4102 | .mac = ixgbe_mac_X550, |
4103 | .get_invariants = &ixgbe_get_invariants_X540, |
4104 | .mac_ops = &mac_ops_X550, |
4105 | .eeprom_ops = &eeprom_ops_X550, |
4106 | .phy_ops = &phy_ops_X550, |
4107 | .mbx_ops = &mbx_ops_generic, |
4108 | .mvals = ixgbe_mvals_X550, |
4109 | }; |
4110 | |
4111 | const struct ixgbe_info ixgbe_X550EM_x_info = { |
4112 | .mac = ixgbe_mac_X550EM_x, |
4113 | .get_invariants = &ixgbe_get_invariants_X550_x, |
4114 | .mac_ops = &mac_ops_X550EM_x, |
4115 | .eeprom_ops = &eeprom_ops_X550EM_x, |
4116 | .phy_ops = &phy_ops_X550EM_x, |
4117 | .mbx_ops = &mbx_ops_generic, |
4118 | .mvals = ixgbe_mvals_X550EM_x, |
4119 | .link_ops = &link_ops_x550em_x, |
4120 | }; |
4121 | |
4122 | const struct ixgbe_info ixgbe_x550em_x_fw_info = { |
4123 | .mac = ixgbe_mac_X550EM_x, |
4124 | .get_invariants = ixgbe_get_invariants_X550_x_fw, |
4125 | .mac_ops = &mac_ops_X550EM_x_fw, |
4126 | .eeprom_ops = &eeprom_ops_X550EM_x, |
4127 | .phy_ops = &phy_ops_x550em_x_fw, |
4128 | .mbx_ops = &mbx_ops_generic, |
4129 | .mvals = ixgbe_mvals_X550EM_x, |
4130 | }; |
4131 | |
4132 | const struct ixgbe_info ixgbe_x550em_a_info = { |
4133 | .mac = ixgbe_mac_x550em_a, |
4134 | .get_invariants = &ixgbe_get_invariants_X550_a, |
4135 | .mac_ops = &mac_ops_x550em_a, |
4136 | .eeprom_ops = &eeprom_ops_X550EM_x, |
4137 | .phy_ops = &phy_ops_x550em_a, |
4138 | .mbx_ops = &mbx_ops_generic, |
4139 | .mvals = ixgbe_mvals_x550em_a, |
4140 | }; |
4141 | |
4142 | const struct ixgbe_info ixgbe_x550em_a_fw_info = { |
4143 | .mac = ixgbe_mac_x550em_a, |
4144 | .get_invariants = ixgbe_get_invariants_X550_a_fw, |
4145 | .mac_ops = &mac_ops_x550em_a_fw, |
4146 | .eeprom_ops = &eeprom_ops_X550EM_x, |
4147 | .phy_ops = &phy_ops_x550em_a_fw, |
4148 | .mbx_ops = &mbx_ops_generic, |
4149 | .mvals = ixgbe_mvals_x550em_a, |
4150 | }; |
4151 | |