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