]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /******************************************************************************* |
2 | ||
3 | Copyright (c) 2001-2015, Intel Corporation | |
4 | All rights reserved. | |
5 | ||
6 | Redistribution and use in source and binary forms, with or without | |
7 | modification, are permitted provided that the following conditions are met: | |
8 | ||
9 | 1. Redistributions of source code must retain the above copyright notice, | |
10 | this list of conditions and the following disclaimer. | |
11 | ||
12 | 2. Redistributions in binary form must reproduce the above copyright | |
13 | notice, this list of conditions and the following disclaimer in the | |
14 | documentation and/or other materials provided with the distribution. | |
15 | ||
16 | 3. Neither the name of the Intel Corporation nor the names of its | |
17 | contributors may be used to endorse or promote products derived from | |
18 | this software without specific prior written permission. | |
19 | ||
20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |
21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
23 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | |
24 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
25 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
26 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
27 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
28 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
29 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
30 | POSSIBILITY OF SUCH DAMAGE. | |
31 | ||
32 | ***************************************************************************/ | |
33 | ||
34 | #include "ixgbe_x550.h" | |
35 | #include "ixgbe_x540.h" | |
36 | #include "ixgbe_type.h" | |
37 | #include "ixgbe_api.h" | |
38 | #include "ixgbe_common.h" | |
39 | #include "ixgbe_phy.h" | |
40 | ||
41 | STATIC s32 ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed); | |
42 | STATIC s32 ixgbe_acquire_swfw_sync_X550a(struct ixgbe_hw *, u32 mask); | |
43 | STATIC void ixgbe_release_swfw_sync_X550a(struct ixgbe_hw *, u32 mask); | |
44 | STATIC s32 ixgbe_read_mng_if_sel_x550em(struct ixgbe_hw *hw); | |
45 | ||
46 | /** | |
47 | * ixgbe_init_ops_X550 - Inits func ptrs and MAC type | |
48 | * @hw: pointer to hardware structure | |
49 | * | |
50 | * Initialize the function pointers and assign the MAC type for X550. | |
51 | * Does not touch the hardware. | |
52 | **/ | |
53 | s32 ixgbe_init_ops_X550(struct ixgbe_hw *hw) | |
54 | { | |
55 | struct ixgbe_mac_info *mac = &hw->mac; | |
56 | struct ixgbe_eeprom_info *eeprom = &hw->eeprom; | |
57 | s32 ret_val; | |
58 | ||
59 | DEBUGFUNC("ixgbe_init_ops_X550"); | |
60 | ||
61 | ret_val = ixgbe_init_ops_X540(hw); | |
62 | mac->ops.dmac_config = ixgbe_dmac_config_X550; | |
63 | mac->ops.dmac_config_tcs = ixgbe_dmac_config_tcs_X550; | |
64 | mac->ops.dmac_update_tcs = ixgbe_dmac_update_tcs_X550; | |
65 | mac->ops.setup_eee = ixgbe_setup_eee_X550; | |
66 | mac->ops.set_source_address_pruning = | |
67 | ixgbe_set_source_address_pruning_X550; | |
68 | mac->ops.set_ethertype_anti_spoofing = | |
69 | ixgbe_set_ethertype_anti_spoofing_X550; | |
70 | ||
71 | mac->ops.get_rtrup2tc = ixgbe_dcb_get_rtrup2tc_generic; | |
72 | eeprom->ops.init_params = ixgbe_init_eeprom_params_X550; | |
73 | eeprom->ops.calc_checksum = ixgbe_calc_eeprom_checksum_X550; | |
74 | eeprom->ops.read = ixgbe_read_ee_hostif_X550; | |
75 | eeprom->ops.read_buffer = ixgbe_read_ee_hostif_buffer_X550; | |
76 | eeprom->ops.write = ixgbe_write_ee_hostif_X550; | |
77 | eeprom->ops.write_buffer = ixgbe_write_ee_hostif_buffer_X550; | |
78 | eeprom->ops.update_checksum = ixgbe_update_eeprom_checksum_X550; | |
79 | eeprom->ops.validate_checksum = ixgbe_validate_eeprom_checksum_X550; | |
80 | ||
81 | mac->ops.disable_mdd = ixgbe_disable_mdd_X550; | |
82 | mac->ops.enable_mdd = ixgbe_enable_mdd_X550; | |
83 | mac->ops.mdd_event = ixgbe_mdd_event_X550; | |
84 | mac->ops.restore_mdd_vf = ixgbe_restore_mdd_vf_X550; | |
85 | mac->ops.disable_rx = ixgbe_disable_rx_x550; | |
86 | switch (hw->device_id) { | |
87 | case IXGBE_DEV_ID_X550EM_X_10G_T: | |
88 | case IXGBE_DEV_ID_X550EM_A_10G_T: | |
89 | hw->mac.ops.led_on = ixgbe_led_on_t_X550em; | |
90 | hw->mac.ops.led_off = ixgbe_led_off_t_X550em; | |
91 | break; | |
92 | default: | |
93 | break; | |
94 | } | |
95 | return ret_val; | |
96 | } | |
97 | ||
98 | /** | |
99 | * ixgbe_read_cs4227 - Read CS4227 register | |
100 | * @hw: pointer to hardware structure | |
101 | * @reg: register number to write | |
102 | * @value: pointer to receive value read | |
103 | * | |
104 | * Returns status code | |
105 | **/ | |
106 | STATIC s32 ixgbe_read_cs4227(struct ixgbe_hw *hw, u16 reg, u16 *value) | |
107 | { | |
108 | return hw->link.ops.read_link_unlocked(hw, hw->link.addr, reg, value); | |
109 | } | |
110 | ||
111 | /** | |
112 | * ixgbe_write_cs4227 - Write CS4227 register | |
113 | * @hw: pointer to hardware structure | |
114 | * @reg: register number to write | |
115 | * @value: value to write to register | |
116 | * | |
117 | * Returns status code | |
118 | **/ | |
119 | STATIC s32 ixgbe_write_cs4227(struct ixgbe_hw *hw, u16 reg, u16 value) | |
120 | { | |
121 | return hw->link.ops.write_link_unlocked(hw, hw->link.addr, reg, value); | |
122 | } | |
123 | ||
124 | /** | |
125 | * ixgbe_read_pe - Read register from port expander | |
126 | * @hw: pointer to hardware structure | |
127 | * @reg: register number to read | |
128 | * @value: pointer to receive read value | |
129 | * | |
130 | * Returns status code | |
131 | **/ | |
132 | STATIC s32 ixgbe_read_pe(struct ixgbe_hw *hw, u8 reg, u8 *value) | |
133 | { | |
134 | s32 status; | |
135 | ||
136 | status = ixgbe_read_i2c_byte_unlocked(hw, reg, IXGBE_PE, value); | |
137 | if (status != IXGBE_SUCCESS) | |
138 | ERROR_REPORT2(IXGBE_ERROR_CAUTION, | |
139 | "port expander access failed with %d\n", status); | |
140 | return status; | |
141 | } | |
142 | ||
143 | /** | |
144 | * ixgbe_write_pe - Write register to port expander | |
145 | * @hw: pointer to hardware structure | |
146 | * @reg: register number to write | |
147 | * @value: value to write | |
148 | * | |
149 | * Returns status code | |
150 | **/ | |
151 | STATIC s32 ixgbe_write_pe(struct ixgbe_hw *hw, u8 reg, u8 value) | |
152 | { | |
153 | s32 status; | |
154 | ||
155 | status = ixgbe_write_i2c_byte_unlocked(hw, reg, IXGBE_PE, value); | |
156 | if (status != IXGBE_SUCCESS) | |
157 | ERROR_REPORT2(IXGBE_ERROR_CAUTION, | |
158 | "port expander access failed with %d\n", status); | |
159 | return status; | |
160 | } | |
161 | ||
162 | /** | |
163 | * ixgbe_reset_cs4227 - Reset CS4227 using port expander | |
164 | * @hw: pointer to hardware structure | |
165 | * | |
166 | * This function assumes that the caller has acquired the proper semaphore. | |
167 | * Returns error code | |
168 | **/ | |
169 | STATIC s32 ixgbe_reset_cs4227(struct ixgbe_hw *hw) | |
170 | { | |
171 | s32 status; | |
172 | u32 retry; | |
173 | u16 value; | |
174 | u8 reg; | |
175 | ||
176 | /* Trigger hard reset. */ | |
177 | status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, ®); | |
178 | if (status != IXGBE_SUCCESS) | |
179 | return status; | |
180 | reg |= IXGBE_PE_BIT1; | |
181 | status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg); | |
182 | if (status != IXGBE_SUCCESS) | |
183 | return status; | |
184 | ||
185 | status = ixgbe_read_pe(hw, IXGBE_PE_CONFIG, ®); | |
186 | if (status != IXGBE_SUCCESS) | |
187 | return status; | |
188 | reg &= ~IXGBE_PE_BIT1; | |
189 | status = ixgbe_write_pe(hw, IXGBE_PE_CONFIG, reg); | |
190 | if (status != IXGBE_SUCCESS) | |
191 | return status; | |
192 | ||
193 | status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, ®); | |
194 | if (status != IXGBE_SUCCESS) | |
195 | return status; | |
196 | reg &= ~IXGBE_PE_BIT1; | |
197 | status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg); | |
198 | if (status != IXGBE_SUCCESS) | |
199 | return status; | |
200 | ||
201 | usec_delay(IXGBE_CS4227_RESET_HOLD); | |
202 | ||
203 | status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, ®); | |
204 | if (status != IXGBE_SUCCESS) | |
205 | return status; | |
206 | reg |= IXGBE_PE_BIT1; | |
207 | status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg); | |
208 | if (status != IXGBE_SUCCESS) | |
209 | return status; | |
210 | ||
211 | /* Wait for the reset to complete. */ | |
212 | msec_delay(IXGBE_CS4227_RESET_DELAY); | |
213 | for (retry = 0; retry < IXGBE_CS4227_RETRIES; retry++) { | |
214 | status = ixgbe_read_cs4227(hw, IXGBE_CS4227_EFUSE_STATUS, | |
215 | &value); | |
216 | if (status == IXGBE_SUCCESS && | |
217 | value == IXGBE_CS4227_EEPROM_LOAD_OK) | |
218 | break; | |
219 | msec_delay(IXGBE_CS4227_CHECK_DELAY); | |
220 | } | |
221 | if (retry == IXGBE_CS4227_RETRIES) { | |
222 | ERROR_REPORT1(IXGBE_ERROR_INVALID_STATE, | |
223 | "CS4227 reset did not complete."); | |
224 | return IXGBE_ERR_PHY; | |
225 | } | |
226 | ||
227 | status = ixgbe_read_cs4227(hw, IXGBE_CS4227_EEPROM_STATUS, &value); | |
228 | if (status != IXGBE_SUCCESS || | |
229 | !(value & IXGBE_CS4227_EEPROM_LOAD_OK)) { | |
230 | ERROR_REPORT1(IXGBE_ERROR_INVALID_STATE, | |
231 | "CS4227 EEPROM did not load successfully."); | |
232 | return IXGBE_ERR_PHY; | |
233 | } | |
234 | ||
235 | return IXGBE_SUCCESS; | |
236 | } | |
237 | ||
238 | /** | |
239 | * ixgbe_check_cs4227 - Check CS4227 and reset as needed | |
240 | * @hw: pointer to hardware structure | |
241 | **/ | |
242 | STATIC void ixgbe_check_cs4227(struct ixgbe_hw *hw) | |
243 | { | |
244 | s32 status = IXGBE_SUCCESS; | |
245 | u32 swfw_mask = hw->phy.phy_semaphore_mask; | |
246 | u16 value = 0; | |
247 | u8 retry; | |
248 | ||
249 | for (retry = 0; retry < IXGBE_CS4227_RETRIES; retry++) { | |
250 | status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask); | |
251 | if (status != IXGBE_SUCCESS) { | |
252 | ERROR_REPORT2(IXGBE_ERROR_CAUTION, | |
253 | "semaphore failed with %d", status); | |
254 | msec_delay(IXGBE_CS4227_CHECK_DELAY); | |
255 | continue; | |
256 | } | |
257 | ||
258 | /* Get status of reset flow. */ | |
259 | status = ixgbe_read_cs4227(hw, IXGBE_CS4227_SCRATCH, &value); | |
260 | ||
261 | if (status == IXGBE_SUCCESS && | |
262 | value == IXGBE_CS4227_RESET_COMPLETE) | |
263 | goto out; | |
264 | ||
265 | if (status != IXGBE_SUCCESS || | |
266 | value != IXGBE_CS4227_RESET_PENDING) | |
267 | break; | |
268 | ||
269 | /* Reset is pending. Wait and check again. */ | |
270 | hw->mac.ops.release_swfw_sync(hw, swfw_mask); | |
271 | msec_delay(IXGBE_CS4227_CHECK_DELAY); | |
272 | } | |
273 | ||
274 | /* If still pending, assume other instance failed. */ | |
275 | if (retry == IXGBE_CS4227_RETRIES) { | |
276 | status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask); | |
277 | if (status != IXGBE_SUCCESS) { | |
278 | ERROR_REPORT2(IXGBE_ERROR_CAUTION, | |
279 | "semaphore failed with %d", status); | |
280 | return; | |
281 | } | |
282 | } | |
283 | ||
284 | /* Reset the CS4227. */ | |
285 | status = ixgbe_reset_cs4227(hw); | |
286 | if (status != IXGBE_SUCCESS) { | |
287 | ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE, | |
288 | "CS4227 reset failed: %d", status); | |
289 | goto out; | |
290 | } | |
291 | ||
292 | /* Reset takes so long, temporarily release semaphore in case the | |
293 | * other driver instance is waiting for the reset indication. | |
294 | */ | |
295 | ixgbe_write_cs4227(hw, IXGBE_CS4227_SCRATCH, | |
296 | IXGBE_CS4227_RESET_PENDING); | |
297 | hw->mac.ops.release_swfw_sync(hw, swfw_mask); | |
298 | msec_delay(10); | |
299 | status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask); | |
300 | if (status != IXGBE_SUCCESS) { | |
301 | ERROR_REPORT2(IXGBE_ERROR_CAUTION, | |
302 | "semaphore failed with %d", status); | |
303 | return; | |
304 | } | |
305 | ||
306 | /* Record completion for next time. */ | |
307 | status = ixgbe_write_cs4227(hw, IXGBE_CS4227_SCRATCH, | |
308 | IXGBE_CS4227_RESET_COMPLETE); | |
309 | ||
310 | out: | |
311 | hw->mac.ops.release_swfw_sync(hw, swfw_mask); | |
312 | msec_delay(hw->eeprom.semaphore_delay); | |
313 | } | |
314 | ||
315 | /** | |
316 | * ixgbe_setup_mux_ctl - Setup ESDP register for I2C mux control | |
317 | * @hw: pointer to hardware structure | |
318 | **/ | |
319 | STATIC void ixgbe_setup_mux_ctl(struct ixgbe_hw *hw) | |
320 | { | |
321 | u32 esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); | |
322 | ||
323 | if (hw->bus.lan_id) { | |
324 | esdp &= ~(IXGBE_ESDP_SDP1_NATIVE | IXGBE_ESDP_SDP1); | |
325 | esdp |= IXGBE_ESDP_SDP1_DIR; | |
326 | } | |
327 | esdp &= ~(IXGBE_ESDP_SDP0_NATIVE | IXGBE_ESDP_SDP0_DIR); | |
328 | IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); | |
329 | IXGBE_WRITE_FLUSH(hw); | |
330 | } | |
331 | ||
332 | /** | |
333 | * ixgbe_read_phy_reg_mdi_22 - Read from a clause 22 PHY register without lock | |
334 | * @hw: pointer to hardware structure | |
335 | * @reg_addr: 32 bit address of PHY register to read | |
336 | * @dev_type: always unused | |
337 | * @phy_data: Pointer to read data from PHY register | |
338 | */ | |
339 | STATIC s32 ixgbe_read_phy_reg_mdi_22(struct ixgbe_hw *hw, u32 reg_addr, | |
340 | u32 dev_type, u16 *phy_data) | |
341 | { | |
342 | u32 i, data, command; | |
343 | UNREFERENCED_1PARAMETER(dev_type); | |
344 | ||
345 | /* Setup and write the read command */ | |
346 | command = (reg_addr << IXGBE_MSCA_DEV_TYPE_SHIFT) | | |
347 | (hw->phy.addr << IXGBE_MSCA_PHY_ADDR_SHIFT) | | |
348 | IXGBE_MSCA_OLD_PROTOCOL | IXGBE_MSCA_READ_AUTOINC | | |
349 | IXGBE_MSCA_MDI_COMMAND; | |
350 | ||
351 | IXGBE_WRITE_REG(hw, IXGBE_MSCA, command); | |
352 | ||
353 | /* Check every 10 usec to see if the access completed. | |
354 | * The MDI Command bit will clear when the operation is | |
355 | * complete | |
356 | */ | |
357 | for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) { | |
358 | usec_delay(10); | |
359 | ||
360 | command = IXGBE_READ_REG(hw, IXGBE_MSCA); | |
361 | if (!(command & IXGBE_MSCA_MDI_COMMAND)) | |
362 | break; | |
363 | } | |
364 | ||
365 | if (command & IXGBE_MSCA_MDI_COMMAND) { | |
366 | ERROR_REPORT1(IXGBE_ERROR_POLLING, | |
367 | "PHY read command did not complete.\n"); | |
368 | return IXGBE_ERR_PHY; | |
369 | } | |
370 | ||
371 | /* Read operation is complete. Get the data from MSRWD */ | |
372 | data = IXGBE_READ_REG(hw, IXGBE_MSRWD); | |
373 | data >>= IXGBE_MSRWD_READ_DATA_SHIFT; | |
374 | *phy_data = (u16)data; | |
375 | ||
376 | return IXGBE_SUCCESS; | |
377 | } | |
378 | ||
379 | /** | |
380 | * ixgbe_write_phy_reg_mdi_22 - Write to a clause 22 PHY register without lock | |
381 | * @hw: pointer to hardware structure | |
382 | * @reg_addr: 32 bit PHY register to write | |
383 | * @dev_type: always unused | |
384 | * @phy_data: Data to write to the PHY register | |
385 | */ | |
386 | STATIC s32 ixgbe_write_phy_reg_mdi_22(struct ixgbe_hw *hw, u32 reg_addr, | |
387 | u32 dev_type, u16 phy_data) | |
388 | { | |
389 | u32 i, command; | |
390 | UNREFERENCED_1PARAMETER(dev_type); | |
391 | ||
392 | /* Put the data in the MDI single read and write data register*/ | |
393 | IXGBE_WRITE_REG(hw, IXGBE_MSRWD, (u32)phy_data); | |
394 | ||
395 | /* Setup and write the write command */ | |
396 | command = (reg_addr << IXGBE_MSCA_DEV_TYPE_SHIFT) | | |
397 | (hw->phy.addr << IXGBE_MSCA_PHY_ADDR_SHIFT) | | |
398 | IXGBE_MSCA_OLD_PROTOCOL | IXGBE_MSCA_WRITE | | |
399 | IXGBE_MSCA_MDI_COMMAND; | |
400 | ||
401 | IXGBE_WRITE_REG(hw, IXGBE_MSCA, command); | |
402 | ||
403 | /* Check every 10 usec to see if the access completed. | |
404 | * The MDI Command bit will clear when the operation is | |
405 | * complete | |
406 | */ | |
407 | for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) { | |
408 | usec_delay(10); | |
409 | ||
410 | command = IXGBE_READ_REG(hw, IXGBE_MSCA); | |
411 | if (!(command & IXGBE_MSCA_MDI_COMMAND)) | |
412 | break; | |
413 | } | |
414 | ||
415 | if (command & IXGBE_MSCA_MDI_COMMAND) { | |
416 | ERROR_REPORT1(IXGBE_ERROR_POLLING, | |
417 | "PHY write cmd didn't complete\n"); | |
418 | return IXGBE_ERR_PHY; | |
419 | } | |
420 | ||
421 | return IXGBE_SUCCESS; | |
422 | } | |
423 | ||
424 | /** | |
425 | * ixgbe_identify_phy_x550em - Get PHY type based on device id | |
426 | * @hw: pointer to hardware structure | |
427 | * | |
428 | * Returns error code | |
429 | */ | |
430 | STATIC s32 ixgbe_identify_phy_x550em(struct ixgbe_hw *hw) | |
431 | { | |
432 | hw->mac.ops.set_lan_id(hw); | |
433 | ||
434 | ixgbe_read_mng_if_sel_x550em(hw); | |
435 | ||
436 | switch (hw->device_id) { | |
437 | case IXGBE_DEV_ID_X550EM_A_SFP: | |
438 | return ixgbe_identify_module_generic(hw); | |
439 | case IXGBE_DEV_ID_X550EM_X_SFP: | |
440 | /* set up for CS4227 usage */ | |
441 | ixgbe_setup_mux_ctl(hw); | |
442 | ixgbe_check_cs4227(hw); | |
443 | /* Fallthrough */ | |
444 | ||
445 | case IXGBE_DEV_ID_X550EM_A_SFP_N: | |
446 | return ixgbe_identify_module_generic(hw); | |
447 | break; | |
448 | case IXGBE_DEV_ID_X550EM_X_KX4: | |
449 | hw->phy.type = ixgbe_phy_x550em_kx4; | |
450 | break; | |
451 | case IXGBE_DEV_ID_X550EM_X_KR: | |
452 | case IXGBE_DEV_ID_X550EM_A_KR: | |
453 | case IXGBE_DEV_ID_X550EM_A_KR_L: | |
454 | hw->phy.type = ixgbe_phy_x550em_kr; | |
455 | break; | |
456 | case IXGBE_DEV_ID_X550EM_A_10G_T: | |
457 | case IXGBE_DEV_ID_X550EM_A_1G_T: | |
458 | case IXGBE_DEV_ID_X550EM_A_1G_T_L: | |
459 | case IXGBE_DEV_ID_X550EM_X_1G_T: | |
460 | case IXGBE_DEV_ID_X550EM_X_10G_T: | |
461 | return ixgbe_identify_phy_generic(hw); | |
462 | default: | |
463 | break; | |
464 | } | |
465 | return IXGBE_SUCCESS; | |
466 | } | |
467 | ||
468 | STATIC s32 ixgbe_read_phy_reg_x550em(struct ixgbe_hw *hw, u32 reg_addr, | |
469 | u32 device_type, u16 *phy_data) | |
470 | { | |
471 | UNREFERENCED_4PARAMETER(*hw, reg_addr, device_type, *phy_data); | |
472 | return IXGBE_NOT_IMPLEMENTED; | |
473 | } | |
474 | ||
475 | STATIC s32 ixgbe_write_phy_reg_x550em(struct ixgbe_hw *hw, u32 reg_addr, | |
476 | u32 device_type, u16 phy_data) | |
477 | { | |
478 | UNREFERENCED_4PARAMETER(*hw, reg_addr, device_type, phy_data); | |
479 | return IXGBE_NOT_IMPLEMENTED; | |
480 | } | |
481 | ||
482 | /** | |
483 | * ixgbe_read_i2c_combined_generic - Perform I2C read combined operation | |
484 | * @hw: pointer to the hardware structure | |
485 | * @addr: I2C bus address to read from | |
486 | * @reg: I2C device register to read from | |
487 | * @val: pointer to location to receive read value | |
488 | * | |
489 | * Returns an error code on error. | |
490 | **/ | |
491 | STATIC s32 ixgbe_read_i2c_combined_generic(struct ixgbe_hw *hw, u8 addr, | |
492 | u16 reg, u16 *val) | |
493 | { | |
494 | return ixgbe_read_i2c_combined_generic_int(hw, addr, reg, val, true); | |
495 | } | |
496 | ||
497 | /** | |
498 | * ixgbe_read_i2c_combined_generic_unlocked - Do I2C read combined operation | |
499 | * @hw: pointer to the hardware structure | |
500 | * @addr: I2C bus address to read from | |
501 | * @reg: I2C device register to read from | |
502 | * @val: pointer to location to receive read value | |
503 | * | |
504 | * Returns an error code on error. | |
505 | **/ | |
506 | STATIC s32 | |
507 | ixgbe_read_i2c_combined_generic_unlocked(struct ixgbe_hw *hw, u8 addr, | |
508 | u16 reg, u16 *val) | |
509 | { | |
510 | return ixgbe_read_i2c_combined_generic_int(hw, addr, reg, val, false); | |
511 | } | |
512 | ||
513 | /** | |
514 | * ixgbe_write_i2c_combined_generic - Perform I2C write combined operation | |
515 | * @hw: pointer to the hardware structure | |
516 | * @addr: I2C bus address to write to | |
517 | * @reg: I2C device register to write to | |
518 | * @val: value to write | |
519 | * | |
520 | * Returns an error code on error. | |
521 | **/ | |
522 | STATIC s32 ixgbe_write_i2c_combined_generic(struct ixgbe_hw *hw, | |
523 | u8 addr, u16 reg, u16 val) | |
524 | { | |
525 | return ixgbe_write_i2c_combined_generic_int(hw, addr, reg, val, true); | |
526 | } | |
527 | ||
528 | /** | |
529 | * ixgbe_write_i2c_combined_generic_unlocked - Do I2C write combined operation | |
530 | * @hw: pointer to the hardware structure | |
531 | * @addr: I2C bus address to write to | |
532 | * @reg: I2C device register to write to | |
533 | * @val: value to write | |
534 | * | |
535 | * Returns an error code on error. | |
536 | **/ | |
537 | STATIC s32 | |
538 | ixgbe_write_i2c_combined_generic_unlocked(struct ixgbe_hw *hw, | |
539 | u8 addr, u16 reg, u16 val) | |
540 | { | |
541 | return ixgbe_write_i2c_combined_generic_int(hw, addr, reg, val, false); | |
542 | } | |
543 | ||
544 | /** | |
545 | * ixgbe_init_ops_X550EM - Inits func ptrs and MAC type | |
546 | * @hw: pointer to hardware structure | |
547 | * | |
548 | * Initialize the function pointers and for MAC type X550EM. | |
549 | * Does not touch the hardware. | |
550 | **/ | |
551 | s32 ixgbe_init_ops_X550EM(struct ixgbe_hw *hw) | |
552 | { | |
553 | struct ixgbe_mac_info *mac = &hw->mac; | |
554 | struct ixgbe_eeprom_info *eeprom = &hw->eeprom; | |
555 | struct ixgbe_phy_info *phy = &hw->phy; | |
556 | s32 ret_val; | |
557 | ||
558 | DEBUGFUNC("ixgbe_init_ops_X550EM"); | |
559 | ||
560 | /* Similar to X550 so start there. */ | |
561 | ret_val = ixgbe_init_ops_X550(hw); | |
562 | ||
563 | /* Since this function eventually calls | |
564 | * ixgbe_init_ops_540 by design, we are setting | |
565 | * the pointers to NULL explicitly here to overwrite | |
566 | * the values being set in the x540 function. | |
567 | */ | |
568 | /* Thermal sensor not supported in x550EM */ | |
569 | mac->ops.get_thermal_sensor_data = NULL; | |
570 | mac->ops.init_thermal_sensor_thresh = NULL; | |
571 | mac->thermal_sensor_enabled = false; | |
572 | ||
573 | /* FCOE not supported in x550EM */ | |
574 | mac->ops.get_san_mac_addr = NULL; | |
575 | mac->ops.set_san_mac_addr = NULL; | |
576 | mac->ops.get_wwn_prefix = NULL; | |
577 | mac->ops.get_fcoe_boot_status = NULL; | |
578 | ||
579 | /* IPsec not supported in x550EM */ | |
580 | mac->ops.disable_sec_rx_path = NULL; | |
581 | mac->ops.enable_sec_rx_path = NULL; | |
582 | ||
583 | /* AUTOC register is not present in x550EM. */ | |
584 | mac->ops.prot_autoc_read = NULL; | |
585 | mac->ops.prot_autoc_write = NULL; | |
586 | ||
587 | /* X550EM bus type is internal*/ | |
588 | hw->bus.type = ixgbe_bus_type_internal; | |
589 | mac->ops.get_bus_info = ixgbe_get_bus_info_X550em; | |
590 | ||
591 | ||
592 | mac->ops.get_media_type = ixgbe_get_media_type_X550em; | |
593 | mac->ops.setup_sfp = ixgbe_setup_sfp_modules_X550em; | |
594 | mac->ops.get_link_capabilities = ixgbe_get_link_capabilities_X550em; | |
595 | mac->ops.reset_hw = ixgbe_reset_hw_X550em; | |
596 | mac->ops.get_supported_physical_layer = | |
597 | ixgbe_get_supported_physical_layer_X550em; | |
598 | ||
599 | if (mac->ops.get_media_type(hw) == ixgbe_media_type_copper) | |
600 | mac->ops.setup_fc = ixgbe_setup_fc_generic; | |
601 | else | |
602 | mac->ops.setup_fc = ixgbe_setup_fc_X550em; | |
603 | ||
604 | switch (hw->device_id) { | |
605 | case IXGBE_DEV_ID_X550EM_X_KR: | |
606 | case IXGBE_DEV_ID_X550EM_A_KR: | |
607 | case IXGBE_DEV_ID_X550EM_A_KR_L: | |
608 | break; | |
609 | default: | |
610 | mac->ops.setup_eee = NULL; | |
611 | } | |
612 | ||
613 | /* PHY */ | |
614 | phy->ops.init = ixgbe_init_phy_ops_X550em; | |
615 | phy->ops.identify = ixgbe_identify_phy_x550em; | |
616 | if (mac->ops.get_media_type(hw) != ixgbe_media_type_copper) | |
617 | phy->ops.set_phy_power = NULL; | |
618 | ||
619 | ||
620 | /* EEPROM */ | |
621 | eeprom->ops.init_params = ixgbe_init_eeprom_params_X540; | |
622 | eeprom->ops.read = ixgbe_read_ee_hostif_X550; | |
623 | eeprom->ops.read_buffer = ixgbe_read_ee_hostif_buffer_X550; | |
624 | eeprom->ops.write = ixgbe_write_ee_hostif_X550; | |
625 | eeprom->ops.write_buffer = ixgbe_write_ee_hostif_buffer_X550; | |
626 | eeprom->ops.update_checksum = ixgbe_update_eeprom_checksum_X550; | |
627 | eeprom->ops.validate_checksum = ixgbe_validate_eeprom_checksum_X550; | |
628 | eeprom->ops.calc_checksum = ixgbe_calc_eeprom_checksum_X550; | |
629 | ||
630 | return ret_val; | |
631 | } | |
632 | ||
633 | /** | |
634 | * ixgbe_init_ops_X550EM_a - Inits func ptrs and MAC type | |
635 | * @hw: pointer to hardware structure | |
636 | * | |
637 | * Initialize the function pointers and for MAC type X550EM_a. | |
638 | * Does not touch the hardware. | |
639 | **/ | |
640 | s32 ixgbe_init_ops_X550EM_a(struct ixgbe_hw *hw) | |
641 | { | |
642 | struct ixgbe_mac_info *mac = &hw->mac; | |
643 | s32 ret_val; | |
644 | ||
645 | DEBUGFUNC("ixgbe_init_ops_X550EM_a"); | |
646 | ||
647 | /* Start with generic X550EM init */ | |
648 | ret_val = ixgbe_init_ops_X550EM(hw); | |
649 | ||
650 | if (hw->device_id == IXGBE_DEV_ID_X550EM_A_SGMII || | |
651 | hw->device_id == IXGBE_DEV_ID_X550EM_A_SGMII_L) { | |
652 | mac->ops.read_iosf_sb_reg = ixgbe_read_iosf_sb_reg_x550; | |
653 | mac->ops.write_iosf_sb_reg = ixgbe_write_iosf_sb_reg_x550; | |
654 | } else { | |
655 | mac->ops.read_iosf_sb_reg = ixgbe_read_iosf_sb_reg_x550a; | |
656 | mac->ops.write_iosf_sb_reg = ixgbe_write_iosf_sb_reg_x550a; | |
657 | } | |
658 | mac->ops.acquire_swfw_sync = ixgbe_acquire_swfw_sync_X550a; | |
659 | mac->ops.release_swfw_sync = ixgbe_release_swfw_sync_X550a; | |
660 | ||
661 | switch (mac->ops.get_media_type(hw)) { | |
662 | case ixgbe_media_type_fiber: | |
663 | mac->ops.setup_fc = NULL; | |
664 | mac->ops.fc_autoneg = ixgbe_fc_autoneg_fiber_x550em_a; | |
665 | break; | |
666 | case ixgbe_media_type_backplane: | |
667 | mac->ops.fc_autoneg = ixgbe_fc_autoneg_backplane_x550em_a; | |
668 | mac->ops.setup_fc = ixgbe_setup_fc_backplane_x550em_a; | |
669 | break; | |
670 | default: | |
671 | break; | |
672 | } | |
673 | ||
674 | if ((hw->device_id == IXGBE_DEV_ID_X550EM_A_1G_T) || | |
675 | (hw->device_id == IXGBE_DEV_ID_X550EM_A_1G_T_L)) { | |
676 | mac->ops.fc_autoneg = ixgbe_fc_autoneg_sgmii_x550em_a; | |
677 | mac->ops.setup_fc = ixgbe_setup_fc_sgmii_x550em_a; | |
678 | } | |
679 | ||
680 | return ret_val; | |
681 | } | |
682 | ||
683 | /** | |
684 | * ixgbe_init_ops_X550EM_x - Inits func ptrs and MAC type | |
685 | * @hw: pointer to hardware structure | |
686 | * | |
687 | * Initialize the function pointers and for MAC type X550EM_x. | |
688 | * Does not touch the hardware. | |
689 | **/ | |
690 | s32 ixgbe_init_ops_X550EM_x(struct ixgbe_hw *hw) | |
691 | { | |
692 | struct ixgbe_mac_info *mac = &hw->mac; | |
693 | struct ixgbe_link_info *link = &hw->link; | |
694 | s32 ret_val; | |
695 | ||
696 | DEBUGFUNC("ixgbe_init_ops_X550EM_x"); | |
697 | ||
698 | /* Start with generic X550EM init */ | |
699 | ret_val = ixgbe_init_ops_X550EM(hw); | |
700 | ||
701 | mac->ops.read_iosf_sb_reg = ixgbe_read_iosf_sb_reg_x550; | |
702 | mac->ops.write_iosf_sb_reg = ixgbe_write_iosf_sb_reg_x550; | |
703 | mac->ops.acquire_swfw_sync = ixgbe_acquire_swfw_sync_X550em; | |
704 | mac->ops.release_swfw_sync = ixgbe_release_swfw_sync_X550em; | |
705 | link->ops.read_link = ixgbe_read_i2c_combined_generic; | |
706 | link->ops.read_link_unlocked = ixgbe_read_i2c_combined_generic_unlocked; | |
707 | link->ops.write_link = ixgbe_write_i2c_combined_generic; | |
708 | link->ops.write_link_unlocked = | |
709 | ixgbe_write_i2c_combined_generic_unlocked; | |
710 | link->addr = IXGBE_CS4227; | |
711 | ||
712 | return ret_val; | |
713 | } | |
714 | ||
715 | /** | |
716 | * ixgbe_dmac_config_X550 | |
717 | * @hw: pointer to hardware structure | |
718 | * | |
719 | * Configure DMA coalescing. If enabling dmac, dmac is activated. | |
720 | * When disabling dmac, dmac enable dmac bit is cleared. | |
721 | **/ | |
722 | s32 ixgbe_dmac_config_X550(struct ixgbe_hw *hw) | |
723 | { | |
724 | u32 reg, high_pri_tc; | |
725 | ||
726 | DEBUGFUNC("ixgbe_dmac_config_X550"); | |
727 | ||
728 | /* Disable DMA coalescing before configuring */ | |
729 | reg = IXGBE_READ_REG(hw, IXGBE_DMACR); | |
730 | reg &= ~IXGBE_DMACR_DMAC_EN; | |
731 | IXGBE_WRITE_REG(hw, IXGBE_DMACR, reg); | |
732 | ||
733 | /* Disable DMA Coalescing if the watchdog timer is 0 */ | |
734 | if (!hw->mac.dmac_config.watchdog_timer) | |
735 | goto out; | |
736 | ||
737 | ixgbe_dmac_config_tcs_X550(hw); | |
738 | ||
739 | /* Configure DMA Coalescing Control Register */ | |
740 | reg = IXGBE_READ_REG(hw, IXGBE_DMACR); | |
741 | ||
742 | /* Set the watchdog timer in units of 40.96 usec */ | |
743 | reg &= ~IXGBE_DMACR_DMACWT_MASK; | |
744 | reg |= (hw->mac.dmac_config.watchdog_timer * 100) / 4096; | |
745 | ||
746 | reg &= ~IXGBE_DMACR_HIGH_PRI_TC_MASK; | |
747 | /* If fcoe is enabled, set high priority traffic class */ | |
748 | if (hw->mac.dmac_config.fcoe_en) { | |
749 | high_pri_tc = 1 << hw->mac.dmac_config.fcoe_tc; | |
750 | reg |= ((high_pri_tc << IXGBE_DMACR_HIGH_PRI_TC_SHIFT) & | |
751 | IXGBE_DMACR_HIGH_PRI_TC_MASK); | |
752 | } | |
753 | reg |= IXGBE_DMACR_EN_MNG_IND; | |
754 | ||
755 | /* Enable DMA coalescing after configuration */ | |
756 | reg |= IXGBE_DMACR_DMAC_EN; | |
757 | IXGBE_WRITE_REG(hw, IXGBE_DMACR, reg); | |
758 | ||
759 | out: | |
760 | return IXGBE_SUCCESS; | |
761 | } | |
762 | ||
763 | /** | |
764 | * ixgbe_dmac_config_tcs_X550 | |
765 | * @hw: pointer to hardware structure | |
766 | * | |
767 | * Configure DMA coalescing threshold per TC. The dmac enable bit must | |
768 | * be cleared before configuring. | |
769 | **/ | |
770 | s32 ixgbe_dmac_config_tcs_X550(struct ixgbe_hw *hw) | |
771 | { | |
772 | u32 tc, reg, pb_headroom, rx_pb_size, maxframe_size_kb; | |
773 | ||
774 | DEBUGFUNC("ixgbe_dmac_config_tcs_X550"); | |
775 | ||
776 | /* Configure DMA coalescing enabled */ | |
777 | switch (hw->mac.dmac_config.link_speed) { | |
778 | case IXGBE_LINK_SPEED_10_FULL: | |
779 | case IXGBE_LINK_SPEED_100_FULL: | |
780 | pb_headroom = IXGBE_DMACRXT_100M; | |
781 | break; | |
782 | case IXGBE_LINK_SPEED_1GB_FULL: | |
783 | pb_headroom = IXGBE_DMACRXT_1G; | |
784 | break; | |
785 | default: | |
786 | pb_headroom = IXGBE_DMACRXT_10G; | |
787 | break; | |
788 | } | |
789 | ||
790 | maxframe_size_kb = ((IXGBE_READ_REG(hw, IXGBE_MAXFRS) >> | |
791 | IXGBE_MHADD_MFS_SHIFT) / 1024); | |
792 | ||
793 | /* Set the per Rx packet buffer receive threshold */ | |
794 | for (tc = 0; tc < IXGBE_DCB_MAX_TRAFFIC_CLASS; tc++) { | |
795 | reg = IXGBE_READ_REG(hw, IXGBE_DMCTH(tc)); | |
796 | reg &= ~IXGBE_DMCTH_DMACRXT_MASK; | |
797 | ||
798 | if (tc < hw->mac.dmac_config.num_tcs) { | |
799 | /* Get Rx PB size */ | |
800 | rx_pb_size = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(tc)); | |
801 | rx_pb_size = (rx_pb_size & IXGBE_RXPBSIZE_MASK) >> | |
802 | IXGBE_RXPBSIZE_SHIFT; | |
803 | ||
804 | /* Calculate receive buffer threshold in kilobytes */ | |
805 | if (rx_pb_size > pb_headroom) | |
806 | rx_pb_size = rx_pb_size - pb_headroom; | |
807 | else | |
808 | rx_pb_size = 0; | |
809 | ||
810 | /* Minimum of MFS shall be set for DMCTH */ | |
811 | reg |= (rx_pb_size > maxframe_size_kb) ? | |
812 | rx_pb_size : maxframe_size_kb; | |
813 | } | |
814 | IXGBE_WRITE_REG(hw, IXGBE_DMCTH(tc), reg); | |
815 | } | |
816 | return IXGBE_SUCCESS; | |
817 | } | |
818 | ||
819 | /** | |
820 | * ixgbe_dmac_update_tcs_X550 | |
821 | * @hw: pointer to hardware structure | |
822 | * | |
823 | * Disables dmac, updates per TC settings, and then enables dmac. | |
824 | **/ | |
825 | s32 ixgbe_dmac_update_tcs_X550(struct ixgbe_hw *hw) | |
826 | { | |
827 | u32 reg; | |
828 | ||
829 | DEBUGFUNC("ixgbe_dmac_update_tcs_X550"); | |
830 | ||
831 | /* Disable DMA coalescing before configuring */ | |
832 | reg = IXGBE_READ_REG(hw, IXGBE_DMACR); | |
833 | reg &= ~IXGBE_DMACR_DMAC_EN; | |
834 | IXGBE_WRITE_REG(hw, IXGBE_DMACR, reg); | |
835 | ||
836 | ixgbe_dmac_config_tcs_X550(hw); | |
837 | ||
838 | /* Enable DMA coalescing after configuration */ | |
839 | reg = IXGBE_READ_REG(hw, IXGBE_DMACR); | |
840 | reg |= IXGBE_DMACR_DMAC_EN; | |
841 | IXGBE_WRITE_REG(hw, IXGBE_DMACR, reg); | |
842 | ||
843 | return IXGBE_SUCCESS; | |
844 | } | |
845 | ||
846 | /** | |
847 | * ixgbe_init_eeprom_params_X550 - Initialize EEPROM params | |
848 | * @hw: pointer to hardware structure | |
849 | * | |
850 | * Initializes the EEPROM parameters ixgbe_eeprom_info within the | |
851 | * ixgbe_hw struct in order to set up EEPROM access. | |
852 | **/ | |
853 | s32 ixgbe_init_eeprom_params_X550(struct ixgbe_hw *hw) | |
854 | { | |
855 | struct ixgbe_eeprom_info *eeprom = &hw->eeprom; | |
856 | u32 eec; | |
857 | u16 eeprom_size; | |
858 | ||
859 | DEBUGFUNC("ixgbe_init_eeprom_params_X550"); | |
860 | ||
861 | if (eeprom->type == ixgbe_eeprom_uninitialized) { | |
862 | eeprom->semaphore_delay = 10; | |
863 | eeprom->type = ixgbe_flash; | |
864 | ||
865 | eec = IXGBE_READ_REG(hw, IXGBE_EEC); | |
866 | eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >> | |
867 | IXGBE_EEC_SIZE_SHIFT); | |
868 | eeprom->word_size = 1 << (eeprom_size + | |
869 | IXGBE_EEPROM_WORD_SIZE_SHIFT); | |
870 | ||
871 | DEBUGOUT2("Eeprom params: type = %d, size = %d\n", | |
872 | eeprom->type, eeprom->word_size); | |
873 | } | |
874 | ||
875 | return IXGBE_SUCCESS; | |
876 | } | |
877 | ||
878 | /** | |
879 | * ixgbe_enable_eee_x550 - Enable EEE support | |
880 | * @hw: pointer to hardware structure | |
881 | */ | |
882 | STATIC s32 ixgbe_enable_eee_x550(struct ixgbe_hw *hw) | |
883 | { | |
884 | u16 autoneg_eee_reg; | |
885 | u32 link_reg; | |
886 | s32 status; | |
887 | ||
888 | if (hw->mac.type == ixgbe_mac_X550) { | |
889 | /* Advertise EEE capability */ | |
890 | hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_EEE_ADVT, | |
891 | IXGBE_MDIO_AUTO_NEG_DEV_TYPE, | |
892 | &autoneg_eee_reg); | |
893 | ||
894 | autoneg_eee_reg |= (IXGBE_AUTO_NEG_10GBASE_EEE_ADVT | | |
895 | IXGBE_AUTO_NEG_1000BASE_EEE_ADVT | | |
896 | IXGBE_AUTO_NEG_100BASE_EEE_ADVT); | |
897 | ||
898 | hw->phy.ops.write_reg(hw, IXGBE_MDIO_AUTO_NEG_EEE_ADVT, | |
899 | IXGBE_MDIO_AUTO_NEG_DEV_TYPE, | |
900 | autoneg_eee_reg); | |
901 | return IXGBE_SUCCESS; | |
902 | } | |
903 | ||
904 | switch (hw->device_id) { | |
905 | case IXGBE_DEV_ID_X550EM_X_KR: | |
906 | case IXGBE_DEV_ID_X550EM_A_KR: | |
907 | case IXGBE_DEV_ID_X550EM_A_KR_L: | |
908 | status = hw->mac.ops.read_iosf_sb_reg(hw, | |
909 | IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), | |
910 | IXGBE_SB_IOSF_TARGET_KR_PHY, &link_reg); | |
911 | if (status != IXGBE_SUCCESS) | |
912 | return status; | |
913 | ||
914 | link_reg |= IXGBE_KRM_LINK_CTRL_1_TETH_EEE_CAP_KR | | |
915 | IXGBE_KRM_LINK_CTRL_1_TETH_EEE_CAP_KX; | |
916 | ||
917 | /* Don't advertise FEC capability when EEE enabled. */ | |
918 | link_reg &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_FEC; | |
919 | ||
920 | status = hw->mac.ops.write_iosf_sb_reg(hw, | |
921 | IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), | |
922 | IXGBE_SB_IOSF_TARGET_KR_PHY, link_reg); | |
923 | if (status != IXGBE_SUCCESS) | |
924 | return status; | |
925 | break; | |
926 | default: | |
927 | break; | |
928 | } | |
929 | ||
930 | return IXGBE_SUCCESS; | |
931 | } | |
932 | ||
933 | /** | |
934 | * ixgbe_disable_eee_x550 - Disable EEE support | |
935 | * @hw: pointer to hardware structure | |
936 | */ | |
937 | STATIC s32 ixgbe_disable_eee_x550(struct ixgbe_hw *hw) | |
938 | { | |
939 | u16 autoneg_eee_reg; | |
940 | u32 link_reg; | |
941 | s32 status; | |
942 | ||
943 | if (hw->mac.type == ixgbe_mac_X550) { | |
944 | /* Disable advertised EEE capability */ | |
945 | hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_EEE_ADVT, | |
946 | IXGBE_MDIO_AUTO_NEG_DEV_TYPE, | |
947 | &autoneg_eee_reg); | |
948 | ||
949 | autoneg_eee_reg &= ~(IXGBE_AUTO_NEG_10GBASE_EEE_ADVT | | |
950 | IXGBE_AUTO_NEG_1000BASE_EEE_ADVT | | |
951 | IXGBE_AUTO_NEG_100BASE_EEE_ADVT); | |
952 | ||
953 | hw->phy.ops.write_reg(hw, IXGBE_MDIO_AUTO_NEG_EEE_ADVT, | |
954 | IXGBE_MDIO_AUTO_NEG_DEV_TYPE, | |
955 | autoneg_eee_reg); | |
956 | return IXGBE_SUCCESS; | |
957 | } | |
958 | ||
959 | switch (hw->device_id) { | |
960 | case IXGBE_DEV_ID_X550EM_X_KR: | |
961 | case IXGBE_DEV_ID_X550EM_A_KR: | |
962 | case IXGBE_DEV_ID_X550EM_A_KR_L: | |
963 | status = hw->mac.ops.read_iosf_sb_reg(hw, | |
964 | IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), | |
965 | IXGBE_SB_IOSF_TARGET_KR_PHY, &link_reg); | |
966 | if (status != IXGBE_SUCCESS) | |
967 | return status; | |
968 | ||
969 | link_reg &= ~(IXGBE_KRM_LINK_CTRL_1_TETH_EEE_CAP_KR | | |
970 | IXGBE_KRM_LINK_CTRL_1_TETH_EEE_CAP_KX); | |
971 | ||
972 | /* Advertise FEC capability when EEE is disabled. */ | |
973 | link_reg |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_FEC; | |
974 | ||
975 | status = hw->mac.ops.write_iosf_sb_reg(hw, | |
976 | IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), | |
977 | IXGBE_SB_IOSF_TARGET_KR_PHY, link_reg); | |
978 | if (status != IXGBE_SUCCESS) | |
979 | return status; | |
980 | break; | |
981 | default: | |
982 | break; | |
983 | } | |
984 | ||
985 | return IXGBE_SUCCESS; | |
986 | } | |
987 | ||
988 | /** | |
989 | * ixgbe_setup_eee_X550 - Enable/disable EEE support | |
990 | * @hw: pointer to the HW structure | |
991 | * @enable_eee: boolean flag to enable EEE | |
992 | * | |
993 | * Enable/disable EEE based on enable_eee flag. | |
994 | * Auto-negotiation must be started after BASE-T EEE bits in PHY register 7.3C | |
995 | * are modified. | |
996 | * | |
997 | **/ | |
998 | s32 ixgbe_setup_eee_X550(struct ixgbe_hw *hw, bool enable_eee) | |
999 | { | |
1000 | s32 status; | |
1001 | u32 eeer; | |
1002 | ||
1003 | DEBUGFUNC("ixgbe_setup_eee_X550"); | |
1004 | ||
1005 | eeer = IXGBE_READ_REG(hw, IXGBE_EEER); | |
1006 | /* Enable or disable EEE per flag */ | |
1007 | if (enable_eee) { | |
1008 | eeer |= (IXGBE_EEER_TX_LPI_EN | IXGBE_EEER_RX_LPI_EN); | |
1009 | ||
1010 | /* Not supported on first revision of X550EM_x. */ | |
1011 | if ((hw->mac.type == ixgbe_mac_X550EM_x) && | |
1012 | !(IXGBE_FUSES0_REV_MASK & | |
1013 | IXGBE_READ_REG(hw, IXGBE_FUSES0_GROUP(0)))) | |
1014 | return IXGBE_SUCCESS; | |
1015 | ||
1016 | status = ixgbe_enable_eee_x550(hw); | |
1017 | if (status) | |
1018 | return status; | |
1019 | } else { | |
1020 | eeer &= ~(IXGBE_EEER_TX_LPI_EN | IXGBE_EEER_RX_LPI_EN); | |
1021 | ||
1022 | status = ixgbe_disable_eee_x550(hw); | |
1023 | if (status) | |
1024 | return status; | |
1025 | } | |
1026 | IXGBE_WRITE_REG(hw, IXGBE_EEER, eeer); | |
1027 | ||
1028 | return IXGBE_SUCCESS; | |
1029 | } | |
1030 | ||
1031 | /** | |
1032 | * ixgbe_set_source_address_pruning_X550 - Enable/Disbale source address pruning | |
1033 | * @hw: pointer to hardware structure | |
1034 | * @enable: enable or disable source address pruning | |
1035 | * @pool: Rx pool to set source address pruning for | |
1036 | **/ | |
1037 | void ixgbe_set_source_address_pruning_X550(struct ixgbe_hw *hw, bool enable, | |
1038 | unsigned int pool) | |
1039 | { | |
1040 | u64 pfflp; | |
1041 | ||
1042 | /* max rx pool is 63 */ | |
1043 | if (pool > 63) | |
1044 | return; | |
1045 | ||
1046 | pfflp = (u64)IXGBE_READ_REG(hw, IXGBE_PFFLPL); | |
1047 | pfflp |= (u64)IXGBE_READ_REG(hw, IXGBE_PFFLPH) << 32; | |
1048 | ||
1049 | if (enable) | |
1050 | pfflp |= (1ULL << pool); | |
1051 | else | |
1052 | pfflp &= ~(1ULL << pool); | |
1053 | ||
1054 | IXGBE_WRITE_REG(hw, IXGBE_PFFLPL, (u32)pfflp); | |
1055 | IXGBE_WRITE_REG(hw, IXGBE_PFFLPH, (u32)(pfflp >> 32)); | |
1056 | } | |
1057 | ||
1058 | /** | |
1059 | * ixgbe_set_ethertype_anti_spoofing_X550 - Enable/Disable Ethertype anti-spoofing | |
1060 | * @hw: pointer to hardware structure | |
1061 | * @enable: enable or disable switch for Ethertype anti-spoofing | |
1062 | * @vf: Virtual Function pool - VF Pool to set for Ethertype anti-spoofing | |
1063 | * | |
1064 | **/ | |
1065 | void ixgbe_set_ethertype_anti_spoofing_X550(struct ixgbe_hw *hw, | |
1066 | bool enable, int vf) | |
1067 | { | |
1068 | int vf_target_reg = vf >> 3; | |
1069 | int vf_target_shift = vf % 8 + IXGBE_SPOOF_ETHERTYPEAS_SHIFT; | |
1070 | u32 pfvfspoof; | |
1071 | ||
1072 | DEBUGFUNC("ixgbe_set_ethertype_anti_spoofing_X550"); | |
1073 | ||
1074 | pfvfspoof = IXGBE_READ_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg)); | |
1075 | if (enable) | |
1076 | pfvfspoof |= (1 << vf_target_shift); | |
1077 | else | |
1078 | pfvfspoof &= ~(1 << vf_target_shift); | |
1079 | ||
1080 | IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg), pfvfspoof); | |
1081 | } | |
1082 | ||
1083 | /** | |
1084 | * ixgbe_iosf_wait - Wait for IOSF command completion | |
1085 | * @hw: pointer to hardware structure | |
1086 | * @ctrl: pointer to location to receive final IOSF control value | |
1087 | * | |
1088 | * Returns failing status on timeout | |
1089 | * | |
1090 | * Note: ctrl can be NULL if the IOSF control register value is not needed | |
1091 | **/ | |
1092 | STATIC s32 ixgbe_iosf_wait(struct ixgbe_hw *hw, u32 *ctrl) | |
1093 | { | |
1094 | u32 i, command = 0; | |
1095 | ||
1096 | /* Check every 10 usec to see if the address cycle completed. | |
1097 | * The SB IOSF BUSY bit will clear when the operation is | |
1098 | * complete | |
1099 | */ | |
1100 | for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) { | |
1101 | command = IXGBE_READ_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL); | |
1102 | if ((command & IXGBE_SB_IOSF_CTRL_BUSY) == 0) | |
1103 | break; | |
1104 | usec_delay(10); | |
1105 | } | |
1106 | if (ctrl) | |
1107 | *ctrl = command; | |
1108 | if (i == IXGBE_MDIO_COMMAND_TIMEOUT) { | |
1109 | ERROR_REPORT1(IXGBE_ERROR_POLLING, "Wait timed out\n"); | |
1110 | return IXGBE_ERR_PHY; | |
1111 | } | |
1112 | ||
1113 | return IXGBE_SUCCESS; | |
1114 | } | |
1115 | ||
1116 | /** | |
1117 | * ixgbe_write_iosf_sb_reg_x550 - Writes a value to specified register | |
1118 | * of the IOSF device | |
1119 | * @hw: pointer to hardware structure | |
1120 | * @reg_addr: 32 bit PHY register to write | |
1121 | * @device_type: 3 bit device type | |
1122 | * @data: Data to write to the register | |
1123 | **/ | |
1124 | s32 ixgbe_write_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr, | |
1125 | u32 device_type, u32 data) | |
1126 | { | |
1127 | u32 gssr = IXGBE_GSSR_PHY1_SM | IXGBE_GSSR_PHY0_SM; | |
1128 | u32 command, error; | |
1129 | s32 ret; | |
1130 | ||
1131 | ret = ixgbe_acquire_swfw_semaphore(hw, gssr); | |
1132 | if (ret != IXGBE_SUCCESS) | |
1133 | return ret; | |
1134 | ||
1135 | ret = ixgbe_iosf_wait(hw, NULL); | |
1136 | if (ret != IXGBE_SUCCESS) | |
1137 | goto out; | |
1138 | ||
1139 | command = ((reg_addr << IXGBE_SB_IOSF_CTRL_ADDR_SHIFT) | | |
1140 | (device_type << IXGBE_SB_IOSF_CTRL_TARGET_SELECT_SHIFT)); | |
1141 | ||
1142 | /* Write IOSF control register */ | |
1143 | IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL, command); | |
1144 | ||
1145 | /* Write IOSF data register */ | |
1146 | IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_DATA, data); | |
1147 | ||
1148 | ret = ixgbe_iosf_wait(hw, &command); | |
1149 | ||
1150 | if ((command & IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK) != 0) { | |
1151 | error = (command & IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK) >> | |
1152 | IXGBE_SB_IOSF_CTRL_CMPL_ERR_SHIFT; | |
1153 | ERROR_REPORT2(IXGBE_ERROR_POLLING, | |
1154 | "Failed to write, error %x\n", error); | |
1155 | ret = IXGBE_ERR_PHY; | |
1156 | } | |
1157 | ||
1158 | out: | |
1159 | ixgbe_release_swfw_semaphore(hw, gssr); | |
1160 | return ret; | |
1161 | } | |
1162 | ||
1163 | /** | |
1164 | * ixgbe_read_iosf_sb_reg_x550 - Reads specified register of the IOSF device | |
1165 | * @hw: pointer to hardware structure | |
1166 | * @reg_addr: 32 bit PHY register to write | |
1167 | * @device_type: 3 bit device type | |
1168 | * @data: Pointer to read data from the register | |
1169 | **/ | |
1170 | s32 ixgbe_read_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr, | |
1171 | u32 device_type, u32 *data) | |
1172 | { | |
1173 | u32 gssr = IXGBE_GSSR_PHY1_SM | IXGBE_GSSR_PHY0_SM; | |
1174 | u32 command, error; | |
1175 | s32 ret; | |
1176 | ||
1177 | ret = ixgbe_acquire_swfw_semaphore(hw, gssr); | |
1178 | if (ret != IXGBE_SUCCESS) | |
1179 | return ret; | |
1180 | ||
1181 | ret = ixgbe_iosf_wait(hw, NULL); | |
1182 | if (ret != IXGBE_SUCCESS) | |
1183 | goto out; | |
1184 | ||
1185 | command = ((reg_addr << IXGBE_SB_IOSF_CTRL_ADDR_SHIFT) | | |
1186 | (device_type << IXGBE_SB_IOSF_CTRL_TARGET_SELECT_SHIFT)); | |
1187 | ||
1188 | /* Write IOSF control register */ | |
1189 | IXGBE_WRITE_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL, command); | |
1190 | ||
1191 | ret = ixgbe_iosf_wait(hw, &command); | |
1192 | ||
1193 | if ((command & IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK) != 0) { | |
1194 | error = (command & IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK) >> | |
1195 | IXGBE_SB_IOSF_CTRL_CMPL_ERR_SHIFT; | |
1196 | ERROR_REPORT2(IXGBE_ERROR_POLLING, | |
1197 | "Failed to read, error %x\n", error); | |
1198 | ret = IXGBE_ERR_PHY; | |
1199 | } | |
1200 | ||
1201 | if (ret == IXGBE_SUCCESS) | |
1202 | *data = IXGBE_READ_REG(hw, IXGBE_SB_IOSF_INDIRECT_DATA); | |
1203 | ||
1204 | out: | |
1205 | ixgbe_release_swfw_semaphore(hw, gssr); | |
1206 | return ret; | |
1207 | } | |
1208 | ||
1209 | /** | |
1210 | * ixgbe_get_phy_token - Get the token for shared phy access | |
1211 | * @hw: Pointer to hardware structure | |
1212 | */ | |
1213 | ||
1214 | s32 ixgbe_get_phy_token(struct ixgbe_hw *hw) | |
1215 | { | |
1216 | struct ixgbe_hic_phy_token_req token_cmd; | |
1217 | s32 status; | |
1218 | ||
1219 | token_cmd.hdr.cmd = FW_PHY_TOKEN_REQ_CMD; | |
1220 | token_cmd.hdr.buf_len = FW_PHY_TOKEN_REQ_LEN; | |
1221 | token_cmd.hdr.cmd_or_resp.cmd_resv = 0; | |
1222 | token_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; | |
1223 | token_cmd.port_number = hw->bus.lan_id; | |
1224 | token_cmd.command_type = FW_PHY_TOKEN_REQ; | |
1225 | token_cmd.pad = 0; | |
1226 | status = ixgbe_host_interface_command(hw, (u32 *)&token_cmd, | |
1227 | sizeof(token_cmd), | |
1228 | IXGBE_HI_COMMAND_TIMEOUT, | |
1229 | true); | |
1230 | if (status) | |
1231 | return status; | |
1232 | if (token_cmd.hdr.cmd_or_resp.ret_status == FW_PHY_TOKEN_OK) | |
1233 | return IXGBE_SUCCESS; | |
1234 | if (token_cmd.hdr.cmd_or_resp.ret_status != FW_PHY_TOKEN_RETRY) | |
1235 | return IXGBE_ERR_FW_RESP_INVALID; | |
1236 | ||
1237 | return IXGBE_ERR_TOKEN_RETRY; | |
1238 | } | |
1239 | ||
1240 | /** | |
1241 | * ixgbe_put_phy_token - Put the token for shared phy access | |
1242 | * @hw: Pointer to hardware structure | |
1243 | */ | |
1244 | ||
1245 | s32 ixgbe_put_phy_token(struct ixgbe_hw *hw) | |
1246 | { | |
1247 | struct ixgbe_hic_phy_token_req token_cmd; | |
1248 | s32 status; | |
1249 | ||
1250 | token_cmd.hdr.cmd = FW_PHY_TOKEN_REQ_CMD; | |
1251 | token_cmd.hdr.buf_len = FW_PHY_TOKEN_REQ_LEN; | |
1252 | token_cmd.hdr.cmd_or_resp.cmd_resv = 0; | |
1253 | token_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; | |
1254 | token_cmd.port_number = hw->bus.lan_id; | |
1255 | token_cmd.command_type = FW_PHY_TOKEN_REL; | |
1256 | token_cmd.pad = 0; | |
1257 | status = ixgbe_host_interface_command(hw, (u32 *)&token_cmd, | |
1258 | sizeof(token_cmd), | |
1259 | IXGBE_HI_COMMAND_TIMEOUT, | |
1260 | true); | |
1261 | if (status) | |
1262 | return status; | |
1263 | if (token_cmd.hdr.cmd_or_resp.ret_status == FW_PHY_TOKEN_OK) | |
1264 | return IXGBE_SUCCESS; | |
1265 | ||
1266 | DEBUGOUT("Put PHY Token host interface command failed"); | |
1267 | return IXGBE_ERR_FW_RESP_INVALID; | |
1268 | } | |
1269 | ||
1270 | /** | |
1271 | * ixgbe_write_iosf_sb_reg_x550a - Writes a value to specified register | |
1272 | * of the IOSF device | |
1273 | * @hw: pointer to hardware structure | |
1274 | * @reg_addr: 32 bit PHY register to write | |
1275 | * @device_type: 3 bit device type | |
1276 | * @data: Data to write to the register | |
1277 | **/ | |
1278 | s32 ixgbe_write_iosf_sb_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr, | |
1279 | u32 device_type, u32 data) | |
1280 | { | |
1281 | struct ixgbe_hic_internal_phy_req write_cmd; | |
1282 | s32 status; | |
1283 | UNREFERENCED_1PARAMETER(device_type); | |
1284 | ||
1285 | memset(&write_cmd, 0, sizeof(write_cmd)); | |
1286 | write_cmd.hdr.cmd = FW_INT_PHY_REQ_CMD; | |
1287 | write_cmd.hdr.buf_len = FW_INT_PHY_REQ_LEN; | |
1288 | write_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; | |
1289 | write_cmd.port_number = hw->bus.lan_id; | |
1290 | write_cmd.command_type = FW_INT_PHY_REQ_WRITE; | |
1291 | write_cmd.address = IXGBE_CPU_TO_BE16(reg_addr); | |
1292 | write_cmd.write_data = IXGBE_CPU_TO_BE32(data); | |
1293 | ||
1294 | status = ixgbe_host_interface_command(hw, (u32 *)&write_cmd, | |
1295 | sizeof(write_cmd), | |
1296 | IXGBE_HI_COMMAND_TIMEOUT, false); | |
1297 | ||
1298 | return status; | |
1299 | } | |
1300 | ||
1301 | /** | |
1302 | * ixgbe_read_iosf_sb_reg_x550a - Reads specified register of the IOSF device | |
1303 | * @hw: pointer to hardware structure | |
1304 | * @reg_addr: 32 bit PHY register to write | |
1305 | * @device_type: 3 bit device type | |
1306 | * @data: Pointer to read data from the register | |
1307 | **/ | |
1308 | s32 ixgbe_read_iosf_sb_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr, | |
1309 | u32 device_type, u32 *data) | |
1310 | { | |
1311 | union { | |
1312 | struct ixgbe_hic_internal_phy_req cmd; | |
1313 | struct ixgbe_hic_internal_phy_resp rsp; | |
1314 | } hic; | |
1315 | s32 status; | |
1316 | UNREFERENCED_1PARAMETER(device_type); | |
1317 | ||
1318 | memset(&hic, 0, sizeof(hic)); | |
1319 | hic.cmd.hdr.cmd = FW_INT_PHY_REQ_CMD; | |
1320 | hic.cmd.hdr.buf_len = FW_INT_PHY_REQ_LEN; | |
1321 | hic.cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; | |
1322 | hic.cmd.port_number = hw->bus.lan_id; | |
1323 | hic.cmd.command_type = FW_INT_PHY_REQ_READ; | |
1324 | hic.cmd.address = IXGBE_CPU_TO_BE16(reg_addr); | |
1325 | ||
1326 | status = ixgbe_host_interface_command(hw, (u32 *)&hic.cmd, | |
1327 | sizeof(hic.cmd), | |
1328 | IXGBE_HI_COMMAND_TIMEOUT, true); | |
1329 | ||
1330 | /* Extract the register value from the response. */ | |
1331 | *data = IXGBE_BE32_TO_CPU(hic.rsp.read_data); | |
1332 | ||
1333 | return status; | |
1334 | } | |
1335 | ||
1336 | /** | |
1337 | * ixgbe_disable_mdd_X550 | |
1338 | * @hw: pointer to hardware structure | |
1339 | * | |
1340 | * Disable malicious driver detection | |
1341 | **/ | |
1342 | void ixgbe_disable_mdd_X550(struct ixgbe_hw *hw) | |
1343 | { | |
1344 | u32 reg; | |
1345 | ||
1346 | DEBUGFUNC("ixgbe_disable_mdd_X550"); | |
1347 | ||
1348 | /* Disable MDD for TX DMA and interrupt */ | |
1349 | reg = IXGBE_READ_REG(hw, IXGBE_DMATXCTL); | |
1350 | reg &= ~(IXGBE_DMATXCTL_MDP_EN | IXGBE_DMATXCTL_MBINTEN); | |
1351 | IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL, reg); | |
1352 | ||
1353 | /* Disable MDD for RX and interrupt */ | |
1354 | reg = IXGBE_READ_REG(hw, IXGBE_RDRXCTL); | |
1355 | reg &= ~(IXGBE_RDRXCTL_MDP_EN | IXGBE_RDRXCTL_MBINTEN); | |
1356 | IXGBE_WRITE_REG(hw, IXGBE_RDRXCTL, reg); | |
1357 | } | |
1358 | ||
1359 | /** | |
1360 | * ixgbe_enable_mdd_X550 | |
1361 | * @hw: pointer to hardware structure | |
1362 | * | |
1363 | * Enable malicious driver detection | |
1364 | **/ | |
1365 | void ixgbe_enable_mdd_X550(struct ixgbe_hw *hw) | |
1366 | { | |
1367 | u32 reg; | |
1368 | ||
1369 | DEBUGFUNC("ixgbe_enable_mdd_X550"); | |
1370 | ||
1371 | /* Enable MDD for TX DMA and interrupt */ | |
1372 | reg = IXGBE_READ_REG(hw, IXGBE_DMATXCTL); | |
1373 | reg |= (IXGBE_DMATXCTL_MDP_EN | IXGBE_DMATXCTL_MBINTEN); | |
1374 | IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL, reg); | |
1375 | ||
1376 | /* Enable MDD for RX and interrupt */ | |
1377 | reg = IXGBE_READ_REG(hw, IXGBE_RDRXCTL); | |
1378 | reg |= (IXGBE_RDRXCTL_MDP_EN | IXGBE_RDRXCTL_MBINTEN); | |
1379 | IXGBE_WRITE_REG(hw, IXGBE_RDRXCTL, reg); | |
1380 | } | |
1381 | ||
1382 | /** | |
1383 | * ixgbe_restore_mdd_vf_X550 | |
1384 | * @hw: pointer to hardware structure | |
1385 | * @vf: vf index | |
1386 | * | |
1387 | * Restore VF that was disabled during malicious driver detection event | |
1388 | **/ | |
1389 | void ixgbe_restore_mdd_vf_X550(struct ixgbe_hw *hw, u32 vf) | |
1390 | { | |
1391 | u32 idx, reg, num_qs, start_q, bitmask; | |
1392 | ||
1393 | DEBUGFUNC("ixgbe_restore_mdd_vf_X550"); | |
1394 | ||
1395 | /* Map VF to queues */ | |
1396 | reg = IXGBE_READ_REG(hw, IXGBE_MRQC); | |
1397 | switch (reg & IXGBE_MRQC_MRQE_MASK) { | |
1398 | case IXGBE_MRQC_VMDQRT8TCEN: | |
1399 | num_qs = 8; /* 16 VFs / pools */ | |
1400 | bitmask = 0x000000FF; | |
1401 | break; | |
1402 | case IXGBE_MRQC_VMDQRSS32EN: | |
1403 | case IXGBE_MRQC_VMDQRT4TCEN: | |
1404 | num_qs = 4; /* 32 VFs / pools */ | |
1405 | bitmask = 0x0000000F; | |
1406 | break; | |
1407 | default: /* 64 VFs / pools */ | |
1408 | num_qs = 2; | |
1409 | bitmask = 0x00000003; | |
1410 | break; | |
1411 | } | |
1412 | start_q = vf * num_qs; | |
1413 | ||
1414 | /* Release vf's queues by clearing WQBR_TX and WQBR_RX (RW1C) */ | |
1415 | idx = start_q / 32; | |
1416 | reg = 0; | |
1417 | reg |= (bitmask << (start_q % 32)); | |
1418 | IXGBE_WRITE_REG(hw, IXGBE_WQBR_TX(idx), reg); | |
1419 | IXGBE_WRITE_REG(hw, IXGBE_WQBR_RX(idx), reg); | |
1420 | } | |
1421 | ||
1422 | /** | |
1423 | * ixgbe_mdd_event_X550 | |
1424 | * @hw: pointer to hardware structure | |
1425 | * @vf_bitmap: vf bitmap of malicious vfs | |
1426 | * | |
1427 | * Handle malicious driver detection event. | |
1428 | **/ | |
1429 | void ixgbe_mdd_event_X550(struct ixgbe_hw *hw, u32 *vf_bitmap) | |
1430 | { | |
1431 | u32 wqbr; | |
1432 | u32 i, j, reg, q, shift, vf, idx; | |
1433 | ||
1434 | DEBUGFUNC("ixgbe_mdd_event_X550"); | |
1435 | ||
1436 | /* figure out pool size for mapping to vf's */ | |
1437 | reg = IXGBE_READ_REG(hw, IXGBE_MRQC); | |
1438 | switch (reg & IXGBE_MRQC_MRQE_MASK) { | |
1439 | case IXGBE_MRQC_VMDQRT8TCEN: | |
1440 | shift = 3; /* 16 VFs / pools */ | |
1441 | break; | |
1442 | case IXGBE_MRQC_VMDQRSS32EN: | |
1443 | case IXGBE_MRQC_VMDQRT4TCEN: | |
1444 | shift = 2; /* 32 VFs / pools */ | |
1445 | break; | |
1446 | default: | |
1447 | shift = 1; /* 64 VFs / pools */ | |
1448 | break; | |
1449 | } | |
1450 | ||
1451 | /* Read WQBR_TX and WQBR_RX and check for malicious queues */ | |
1452 | for (i = 0; i < 4; i++) { | |
1453 | wqbr = IXGBE_READ_REG(hw, IXGBE_WQBR_TX(i)); | |
1454 | wqbr |= IXGBE_READ_REG(hw, IXGBE_WQBR_RX(i)); | |
1455 | ||
1456 | if (!wqbr) | |
1457 | continue; | |
1458 | ||
1459 | /* Get malicious queue */ | |
1460 | for (j = 0; j < 32 && wqbr; j++) { | |
1461 | ||
1462 | if (!(wqbr & (1 << j))) | |
1463 | continue; | |
1464 | ||
1465 | /* Get queue from bitmask */ | |
1466 | q = j + (i * 32); | |
1467 | ||
1468 | /* Map queue to vf */ | |
1469 | vf = (q >> shift); | |
1470 | ||
1471 | /* Set vf bit in vf_bitmap */ | |
1472 | idx = vf / 32; | |
1473 | vf_bitmap[idx] |= (1 << (vf % 32)); | |
1474 | wqbr &= ~(1 << j); | |
1475 | } | |
1476 | } | |
1477 | } | |
1478 | ||
1479 | /** | |
1480 | * ixgbe_get_media_type_X550em - Get media type | |
1481 | * @hw: pointer to hardware structure | |
1482 | * | |
1483 | * Returns the media type (fiber, copper, backplane) | |
1484 | */ | |
1485 | enum ixgbe_media_type ixgbe_get_media_type_X550em(struct ixgbe_hw *hw) | |
1486 | { | |
1487 | enum ixgbe_media_type media_type; | |
1488 | ||
1489 | DEBUGFUNC("ixgbe_get_media_type_X550em"); | |
1490 | ||
1491 | /* Detect if there is a copper PHY attached. */ | |
1492 | switch (hw->device_id) { | |
1493 | case IXGBE_DEV_ID_X550EM_X_KR: | |
1494 | case IXGBE_DEV_ID_X550EM_X_KX4: | |
1495 | case IXGBE_DEV_ID_X550EM_A_KR: | |
1496 | case IXGBE_DEV_ID_X550EM_A_KR_L: | |
1497 | media_type = ixgbe_media_type_backplane; | |
1498 | break; | |
1499 | case IXGBE_DEV_ID_X550EM_X_SFP: | |
1500 | case IXGBE_DEV_ID_X550EM_A_SFP: | |
1501 | case IXGBE_DEV_ID_X550EM_A_SFP_N: | |
1502 | case IXGBE_DEV_ID_X550EM_A_QSFP: | |
1503 | case IXGBE_DEV_ID_X550EM_A_QSFP_N: | |
1504 | media_type = ixgbe_media_type_fiber; | |
1505 | break; | |
1506 | case IXGBE_DEV_ID_X550EM_X_1G_T: | |
1507 | case IXGBE_DEV_ID_X550EM_X_10G_T: | |
1508 | case IXGBE_DEV_ID_X550EM_A_10G_T: | |
1509 | media_type = ixgbe_media_type_copper; | |
1510 | break; | |
1511 | case IXGBE_DEV_ID_X550EM_A_SGMII: | |
1512 | case IXGBE_DEV_ID_X550EM_A_SGMII_L: | |
1513 | media_type = ixgbe_media_type_backplane; | |
1514 | hw->phy.type = ixgbe_phy_sgmii; | |
1515 | break; | |
1516 | case IXGBE_DEV_ID_X550EM_A_1G_T: | |
1517 | case IXGBE_DEV_ID_X550EM_A_1G_T_L: | |
1518 | media_type = ixgbe_media_type_copper; | |
1519 | break; | |
1520 | default: | |
1521 | media_type = ixgbe_media_type_unknown; | |
1522 | break; | |
1523 | } | |
1524 | return media_type; | |
1525 | } | |
1526 | ||
1527 | /** | |
1528 | * ixgbe_supported_sfp_modules_X550em - Check if SFP module type is supported | |
1529 | * @hw: pointer to hardware structure | |
1530 | * @linear: true if SFP module is linear | |
1531 | */ | |
1532 | STATIC s32 ixgbe_supported_sfp_modules_X550em(struct ixgbe_hw *hw, bool *linear) | |
1533 | { | |
1534 | DEBUGFUNC("ixgbe_supported_sfp_modules_X550em"); | |
1535 | ||
1536 | switch (hw->phy.sfp_type) { | |
1537 | case ixgbe_sfp_type_not_present: | |
1538 | return IXGBE_ERR_SFP_NOT_PRESENT; | |
1539 | case ixgbe_sfp_type_da_cu_core0: | |
1540 | case ixgbe_sfp_type_da_cu_core1: | |
1541 | *linear = true; | |
1542 | break; | |
1543 | case ixgbe_sfp_type_srlr_core0: | |
1544 | case ixgbe_sfp_type_srlr_core1: | |
1545 | case ixgbe_sfp_type_da_act_lmt_core0: | |
1546 | case ixgbe_sfp_type_da_act_lmt_core1: | |
1547 | case ixgbe_sfp_type_1g_sx_core0: | |
1548 | case ixgbe_sfp_type_1g_sx_core1: | |
1549 | case ixgbe_sfp_type_1g_lx_core0: | |
1550 | case ixgbe_sfp_type_1g_lx_core1: | |
1551 | *linear = false; | |
1552 | break; | |
1553 | case ixgbe_sfp_type_unknown: | |
1554 | case ixgbe_sfp_type_1g_cu_core0: | |
1555 | case ixgbe_sfp_type_1g_cu_core1: | |
1556 | default: | |
1557 | return IXGBE_ERR_SFP_NOT_SUPPORTED; | |
1558 | } | |
1559 | ||
1560 | return IXGBE_SUCCESS; | |
1561 | } | |
1562 | ||
1563 | /** | |
1564 | * ixgbe_identify_sfp_module_X550em - Identifies SFP modules | |
1565 | * @hw: pointer to hardware structure | |
1566 | * | |
1567 | * Searches for and identifies the SFP module and assigns appropriate PHY type. | |
1568 | **/ | |
1569 | s32 ixgbe_identify_sfp_module_X550em(struct ixgbe_hw *hw) | |
1570 | { | |
1571 | s32 status; | |
1572 | bool linear; | |
1573 | ||
1574 | DEBUGFUNC("ixgbe_identify_sfp_module_X550em"); | |
1575 | ||
1576 | status = ixgbe_identify_module_generic(hw); | |
1577 | ||
1578 | if (status != IXGBE_SUCCESS) | |
1579 | return status; | |
1580 | ||
1581 | /* Check if SFP module is supported */ | |
1582 | status = ixgbe_supported_sfp_modules_X550em(hw, &linear); | |
1583 | ||
1584 | return status; | |
1585 | } | |
1586 | ||
1587 | /** | |
1588 | * ixgbe_setup_sfp_modules_X550em - Setup MAC link ops | |
1589 | * @hw: pointer to hardware structure | |
1590 | */ | |
1591 | s32 ixgbe_setup_sfp_modules_X550em(struct ixgbe_hw *hw) | |
1592 | { | |
1593 | s32 status; | |
1594 | bool linear; | |
1595 | ||
1596 | DEBUGFUNC("ixgbe_setup_sfp_modules_X550em"); | |
1597 | ||
1598 | /* Check if SFP module is supported */ | |
1599 | status = ixgbe_supported_sfp_modules_X550em(hw, &linear); | |
1600 | ||
1601 | if (status != IXGBE_SUCCESS) | |
1602 | return status; | |
1603 | ||
1604 | ixgbe_init_mac_link_ops_X550em(hw); | |
1605 | hw->phy.ops.reset = NULL; | |
1606 | ||
1607 | return IXGBE_SUCCESS; | |
1608 | } | |
1609 | ||
1610 | /** | |
1611 | * ixgbe_restart_an_internal_phy_x550em - restart autonegotiation for the | |
1612 | * internal PHY | |
1613 | * @hw: pointer to hardware structure | |
1614 | **/ | |
1615 | STATIC s32 ixgbe_restart_an_internal_phy_x550em(struct ixgbe_hw *hw) | |
1616 | { | |
1617 | s32 status; | |
1618 | u32 link_ctrl; | |
1619 | ||
1620 | /* Restart auto-negotiation. */ | |
1621 | status = hw->mac.ops.read_iosf_sb_reg(hw, | |
1622 | IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), | |
1623 | IXGBE_SB_IOSF_TARGET_KR_PHY, &link_ctrl); | |
1624 | ||
1625 | if (status) { | |
1626 | DEBUGOUT("Auto-negotiation did not complete\n"); | |
1627 | return status; | |
1628 | } | |
1629 | ||
1630 | link_ctrl |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART; | |
1631 | status = hw->mac.ops.write_iosf_sb_reg(hw, | |
1632 | IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), | |
1633 | IXGBE_SB_IOSF_TARGET_KR_PHY, link_ctrl); | |
1634 | ||
1635 | if (hw->mac.type == ixgbe_mac_X550EM_a) { | |
1636 | u32 flx_mask_st20; | |
1637 | ||
1638 | /* Indicate to FW that AN restart has been asserted */ | |
1639 | status = hw->mac.ops.read_iosf_sb_reg(hw, | |
1640 | IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), | |
1641 | IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_mask_st20); | |
1642 | ||
1643 | if (status) { | |
1644 | DEBUGOUT("Auto-negotiation did not complete\n"); | |
1645 | return status; | |
1646 | } | |
1647 | ||
1648 | flx_mask_st20 |= IXGBE_KRM_PMD_FLX_MASK_ST20_FW_AN_RESTART; | |
1649 | status = hw->mac.ops.write_iosf_sb_reg(hw, | |
1650 | IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), | |
1651 | IXGBE_SB_IOSF_TARGET_KR_PHY, flx_mask_st20); | |
1652 | } | |
1653 | ||
1654 | return status; | |
1655 | } | |
1656 | ||
1657 | /** | |
1658 | * ixgbe_setup_sgmii - Set up link for sgmii | |
1659 | * @hw: pointer to hardware structure | |
1660 | */ | |
1661 | STATIC s32 ixgbe_setup_sgmii(struct ixgbe_hw *hw, ixgbe_link_speed speed, | |
1662 | bool autoneg_wait) | |
1663 | { | |
1664 | struct ixgbe_mac_info *mac = &hw->mac; | |
1665 | u32 lval, sval, flx_val; | |
1666 | s32 rc; | |
1667 | ||
1668 | rc = mac->ops.read_iosf_sb_reg(hw, | |
1669 | IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), | |
1670 | IXGBE_SB_IOSF_TARGET_KR_PHY, &lval); | |
1671 | if (rc) | |
1672 | return rc; | |
1673 | ||
1674 | lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; | |
1675 | lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK; | |
1676 | lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_SGMII_EN; | |
1677 | lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CLAUSE_37_EN; | |
1678 | lval |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G; | |
1679 | rc = mac->ops.write_iosf_sb_reg(hw, | |
1680 | IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), | |
1681 | IXGBE_SB_IOSF_TARGET_KR_PHY, lval); | |
1682 | if (rc) | |
1683 | return rc; | |
1684 | ||
1685 | rc = mac->ops.read_iosf_sb_reg(hw, | |
1686 | IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id), | |
1687 | IXGBE_SB_IOSF_TARGET_KR_PHY, &sval); | |
1688 | if (rc) | |
1689 | return rc; | |
1690 | ||
1691 | sval |= IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_10_D; | |
1692 | sval |= IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_100_D; | |
1693 | rc = mac->ops.write_iosf_sb_reg(hw, | |
1694 | IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id), | |
1695 | IXGBE_SB_IOSF_TARGET_KR_PHY, sval); | |
1696 | if (rc) | |
1697 | return rc; | |
1698 | ||
1699 | rc = mac->ops.read_iosf_sb_reg(hw, | |
1700 | IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), | |
1701 | IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_val); | |
1702 | if (rc) | |
1703 | return rc; | |
1704 | ||
1705 | flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK; | |
1706 | flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_1G; | |
1707 | flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN; | |
1708 | flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN; | |
1709 | flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN; | |
1710 | ||
1711 | rc = mac->ops.write_iosf_sb_reg(hw, | |
1712 | IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), | |
1713 | IXGBE_SB_IOSF_TARGET_KR_PHY, flx_val); | |
1714 | if (rc) | |
1715 | return rc; | |
1716 | ||
1717 | rc = ixgbe_restart_an_internal_phy_x550em(hw); | |
1718 | if (rc) | |
1719 | return rc; | |
1720 | ||
1721 | return hw->phy.ops.setup_link_speed(hw, speed, autoneg_wait); | |
1722 | } | |
1723 | ||
1724 | /** | |
1725 | * ixgbe_setup_sgmii_m88 - Set up link for sgmii with Marvell PHYs | |
1726 | * @hw: pointer to hardware structure | |
1727 | */ | |
1728 | STATIC s32 ixgbe_setup_sgmii_m88(struct ixgbe_hw *hw, ixgbe_link_speed speed, | |
1729 | bool autoneg_wait) | |
1730 | { | |
1731 | struct ixgbe_mac_info *mac = &hw->mac; | |
1732 | u32 lval, sval, flx_val; | |
1733 | s32 rc; | |
1734 | ||
1735 | rc = mac->ops.read_iosf_sb_reg(hw, | |
1736 | IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), | |
1737 | IXGBE_SB_IOSF_TARGET_KR_PHY, &lval); | |
1738 | if (rc) | |
1739 | return rc; | |
1740 | ||
1741 | lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; | |
1742 | lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK; | |
1743 | lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_SGMII_EN; | |
1744 | lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CLAUSE_37_EN; | |
1745 | lval &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G; | |
1746 | rc = mac->ops.write_iosf_sb_reg(hw, | |
1747 | IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), | |
1748 | IXGBE_SB_IOSF_TARGET_KR_PHY, lval); | |
1749 | if (rc) | |
1750 | return rc; | |
1751 | ||
1752 | rc = mac->ops.read_iosf_sb_reg(hw, | |
1753 | IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id), | |
1754 | IXGBE_SB_IOSF_TARGET_KR_PHY, &sval); | |
1755 | if (rc) | |
1756 | return rc; | |
1757 | ||
1758 | sval &= ~IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_10_D; | |
1759 | sval &= ~IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_100_D; | |
1760 | rc = mac->ops.write_iosf_sb_reg(hw, | |
1761 | IXGBE_KRM_SGMII_CTRL(hw->bus.lan_id), | |
1762 | IXGBE_SB_IOSF_TARGET_KR_PHY, sval); | |
1763 | if (rc) | |
1764 | return rc; | |
1765 | ||
1766 | rc = mac->ops.write_iosf_sb_reg(hw, | |
1767 | IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), | |
1768 | IXGBE_SB_IOSF_TARGET_KR_PHY, lval); | |
1769 | if (rc) | |
1770 | return rc; | |
1771 | ||
1772 | rc = mac->ops.read_iosf_sb_reg(hw, | |
1773 | IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), | |
1774 | IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_val); | |
1775 | if (rc) | |
1776 | return rc; | |
1777 | ||
1778 | flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK; | |
1779 | flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_1G; | |
1780 | flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN; | |
1781 | flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN; | |
1782 | flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN; | |
1783 | ||
1784 | rc = mac->ops.write_iosf_sb_reg(hw, | |
1785 | IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), | |
1786 | IXGBE_SB_IOSF_TARGET_KR_PHY, flx_val); | |
1787 | if (rc) | |
1788 | return rc; | |
1789 | ||
1790 | rc = ixgbe_restart_an_internal_phy_x550em(hw); | |
1791 | ||
1792 | return hw->phy.ops.setup_link_speed(hw, speed, autoneg_wait); | |
1793 | } | |
1794 | ||
1795 | /** | |
1796 | * ixgbe_init_mac_link_ops_X550em - init mac link function pointers | |
1797 | * @hw: pointer to hardware structure | |
1798 | */ | |
1799 | void ixgbe_init_mac_link_ops_X550em(struct ixgbe_hw *hw) | |
1800 | { | |
1801 | struct ixgbe_mac_info *mac = &hw->mac; | |
1802 | ||
1803 | DEBUGFUNC("ixgbe_init_mac_link_ops_X550em"); | |
1804 | ||
1805 | switch (hw->mac.ops.get_media_type(hw)) { | |
1806 | case ixgbe_media_type_fiber: | |
1807 | /* CS4227 does not support autoneg, so disable the laser control | |
1808 | * functions for SFP+ fiber | |
1809 | */ | |
1810 | mac->ops.disable_tx_laser = NULL; | |
1811 | mac->ops.enable_tx_laser = NULL; | |
1812 | mac->ops.flap_tx_laser = NULL; | |
1813 | mac->ops.setup_link = ixgbe_setup_mac_link_multispeed_fiber; | |
1814 | mac->ops.set_rate_select_speed = | |
1815 | ixgbe_set_soft_rate_select_speed; | |
1816 | ||
1817 | if ((hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP_N) || | |
1818 | (hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP)) | |
1819 | mac->ops.setup_mac_link = | |
1820 | ixgbe_setup_mac_link_sfp_x550a; | |
1821 | else | |
1822 | mac->ops.setup_mac_link = | |
1823 | ixgbe_setup_mac_link_sfp_x550em; | |
1824 | break; | |
1825 | case ixgbe_media_type_copper: | |
1826 | if (hw->mac.type == ixgbe_mac_X550EM_a) { | |
1827 | if (hw->device_id == IXGBE_DEV_ID_X550EM_A_1G_T || | |
1828 | hw->device_id == IXGBE_DEV_ID_X550EM_A_1G_T_L) { | |
1829 | mac->ops.setup_link = ixgbe_setup_sgmii_m88; | |
1830 | } else { | |
1831 | mac->ops.setup_link = | |
1832 | ixgbe_setup_mac_link_t_X550em; | |
1833 | } | |
1834 | } else { | |
1835 | mac->ops.setup_link = ixgbe_setup_mac_link_t_X550em; | |
1836 | mac->ops.check_link = ixgbe_check_link_t_X550em; | |
1837 | } | |
1838 | break; | |
1839 | case ixgbe_media_type_backplane: | |
1840 | if (hw->device_id == IXGBE_DEV_ID_X550EM_A_SGMII || | |
1841 | hw->device_id == IXGBE_DEV_ID_X550EM_A_SGMII_L) | |
1842 | mac->ops.setup_link = ixgbe_setup_sgmii; | |
1843 | break; | |
1844 | default: | |
1845 | break; | |
1846 | } | |
1847 | } | |
1848 | ||
1849 | /** | |
1850 | * ixgbe_get_link_capabilities_x550em - Determines link capabilities | |
1851 | * @hw: pointer to hardware structure | |
1852 | * @speed: pointer to link speed | |
1853 | * @autoneg: true when autoneg or autotry is enabled | |
1854 | */ | |
1855 | s32 ixgbe_get_link_capabilities_X550em(struct ixgbe_hw *hw, | |
1856 | ixgbe_link_speed *speed, | |
1857 | bool *autoneg) | |
1858 | { | |
1859 | DEBUGFUNC("ixgbe_get_link_capabilities_X550em"); | |
1860 | ||
1861 | ||
1862 | /* SFP */ | |
1863 | if (hw->phy.media_type == ixgbe_media_type_fiber) { | |
1864 | ||
1865 | /* CS4227 SFP must not enable auto-negotiation */ | |
1866 | *autoneg = false; | |
1867 | ||
1868 | /* Check if 1G SFP module. */ | |
1869 | if (hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 || | |
1870 | hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1 | |
1871 | || hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core0 || | |
1872 | hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core1) { | |
1873 | *speed = IXGBE_LINK_SPEED_1GB_FULL; | |
1874 | return IXGBE_SUCCESS; | |
1875 | } | |
1876 | ||
1877 | /* Link capabilities are based on SFP */ | |
1878 | if (hw->phy.multispeed_fiber) | |
1879 | *speed = IXGBE_LINK_SPEED_10GB_FULL | | |
1880 | IXGBE_LINK_SPEED_1GB_FULL; | |
1881 | else | |
1882 | *speed = IXGBE_LINK_SPEED_10GB_FULL; | |
1883 | } else { | |
1884 | switch (hw->phy.type) { | |
1885 | case ixgbe_phy_m88: | |
1886 | *speed = IXGBE_LINK_SPEED_1GB_FULL | | |
1887 | IXGBE_LINK_SPEED_100_FULL | | |
1888 | IXGBE_LINK_SPEED_10_FULL; | |
1889 | break; | |
1890 | case ixgbe_phy_sgmii: | |
1891 | *speed = IXGBE_LINK_SPEED_1GB_FULL; | |
1892 | break; | |
1893 | case ixgbe_phy_x550em_kr: | |
1894 | if (hw->mac.type == ixgbe_mac_X550EM_a) { | |
1895 | /* check different backplane modes */ | |
1896 | if (hw->phy.nw_mng_if_sel & | |
1897 | IXGBE_NW_MNG_IF_SEL_PHY_SPEED_2_5G) { | |
1898 | *speed = IXGBE_LINK_SPEED_2_5GB_FULL; | |
1899 | break; | |
1900 | } else if (hw->device_id == | |
1901 | IXGBE_DEV_ID_X550EM_A_KR_L) { | |
1902 | *speed = IXGBE_LINK_SPEED_1GB_FULL; | |
1903 | break; | |
1904 | } | |
1905 | } | |
1906 | /* fall through */ | |
1907 | default: | |
1908 | *speed = IXGBE_LINK_SPEED_10GB_FULL | | |
1909 | IXGBE_LINK_SPEED_1GB_FULL; | |
1910 | break; | |
1911 | } | |
1912 | *autoneg = true; | |
1913 | } | |
1914 | ||
1915 | return IXGBE_SUCCESS; | |
1916 | } | |
1917 | ||
1918 | /** | |
1919 | * ixgbe_get_lasi_ext_t_x550em - Determime external Base T PHY interrupt cause | |
1920 | * @hw: pointer to hardware structure | |
1921 | * @lsc: pointer to boolean flag which indicates whether external Base T | |
1922 | * PHY interrupt is lsc | |
1923 | * | |
1924 | * Determime if external Base T PHY interrupt cause is high temperature | |
1925 | * failure alarm or link status change. | |
1926 | * | |
1927 | * Return IXGBE_ERR_OVERTEMP if interrupt is high temperature | |
1928 | * failure alarm, else return PHY access status. | |
1929 | */ | |
1930 | STATIC s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc) | |
1931 | { | |
1932 | u32 status; | |
1933 | u16 reg; | |
1934 | ||
1935 | *lsc = false; | |
1936 | ||
1937 | /* Vendor alarm triggered */ | |
1938 | status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_CHIP_STD_INT_FLAG, | |
1939 | IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, | |
1940 | ®); | |
1941 | ||
1942 | if (status != IXGBE_SUCCESS || | |
1943 | !(reg & IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN)) | |
1944 | return status; | |
1945 | ||
1946 | /* Vendor Auto-Neg alarm triggered or Global alarm 1 triggered */ | |
1947 | status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_FLAG, | |
1948 | IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, | |
1949 | ®); | |
1950 | ||
1951 | if (status != IXGBE_SUCCESS || | |
1952 | !(reg & (IXGBE_MDIO_GLOBAL_AN_VEN_ALM_INT_EN | | |
1953 | IXGBE_MDIO_GLOBAL_ALARM_1_INT))) | |
1954 | return status; | |
1955 | ||
1956 | /* Global alarm triggered */ | |
1957 | status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_ALARM_1, | |
1958 | IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, | |
1959 | ®); | |
1960 | ||
1961 | if (status != IXGBE_SUCCESS) | |
1962 | return status; | |
1963 | ||
1964 | /* If high temperature failure, then return over temp error and exit */ | |
1965 | if (reg & IXGBE_MDIO_GLOBAL_ALM_1_HI_TMP_FAIL) { | |
1966 | /* power down the PHY in case the PHY FW didn't already */ | |
1967 | ixgbe_set_copper_phy_power(hw, false); | |
1968 | return IXGBE_ERR_OVERTEMP; | |
1969 | } else if (reg & IXGBE_MDIO_GLOBAL_ALM_1_DEV_FAULT) { | |
1970 | /* device fault alarm triggered */ | |
1971 | status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_FAULT_MSG, | |
1972 | IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, | |
1973 | ®); | |
1974 | ||
1975 | if (status != IXGBE_SUCCESS) | |
1976 | return status; | |
1977 | ||
1978 | /* if device fault was due to high temp alarm handle and exit */ | |
1979 | if (reg == IXGBE_MDIO_GLOBAL_FAULT_MSG_HI_TMP) { | |
1980 | /* power down the PHY in case the PHY FW didn't */ | |
1981 | ixgbe_set_copper_phy_power(hw, false); | |
1982 | return IXGBE_ERR_OVERTEMP; | |
1983 | } | |
1984 | } | |
1985 | ||
1986 | /* Vendor alarm 2 triggered */ | |
1987 | status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_CHIP_STD_INT_FLAG, | |
1988 | IXGBE_MDIO_AUTO_NEG_DEV_TYPE, ®); | |
1989 | ||
1990 | if (status != IXGBE_SUCCESS || | |
1991 | !(reg & IXGBE_MDIO_GLOBAL_STD_ALM2_INT)) | |
1992 | return status; | |
1993 | ||
1994 | /* link connect/disconnect event occurred */ | |
1995 | status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM2, | |
1996 | IXGBE_MDIO_AUTO_NEG_DEV_TYPE, ®); | |
1997 | ||
1998 | if (status != IXGBE_SUCCESS) | |
1999 | return status; | |
2000 | ||
2001 | /* Indicate LSC */ | |
2002 | if (reg & IXGBE_MDIO_AUTO_NEG_VEN_LSC) | |
2003 | *lsc = true; | |
2004 | ||
2005 | return IXGBE_SUCCESS; | |
2006 | } | |
2007 | ||
2008 | /** | |
2009 | * ixgbe_enable_lasi_ext_t_x550em - Enable external Base T PHY interrupts | |
2010 | * @hw: pointer to hardware structure | |
2011 | * | |
2012 | * Enable link status change and temperature failure alarm for the external | |
2013 | * Base T PHY | |
2014 | * | |
2015 | * Returns PHY access status | |
2016 | */ | |
2017 | STATIC s32 ixgbe_enable_lasi_ext_t_x550em(struct ixgbe_hw *hw) | |
2018 | { | |
2019 | u32 status; | |
2020 | u16 reg; | |
2021 | bool lsc; | |
2022 | ||
2023 | /* Clear interrupt flags */ | |
2024 | status = ixgbe_get_lasi_ext_t_x550em(hw, &lsc); | |
2025 | ||
2026 | /* Enable link status change alarm */ | |
2027 | status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK, | |
2028 | IXGBE_MDIO_AUTO_NEG_DEV_TYPE, ®); | |
2029 | ||
2030 | if (status != IXGBE_SUCCESS) | |
2031 | return status; | |
2032 | ||
2033 | reg |= IXGBE_MDIO_PMA_TX_VEN_LASI_INT_EN; | |
2034 | ||
2035 | status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK, | |
2036 | IXGBE_MDIO_AUTO_NEG_DEV_TYPE, reg); | |
2037 | ||
2038 | if (status != IXGBE_SUCCESS) | |
2039 | return status; | |
2040 | ||
2041 | /* Enable high temperature failure and global fault alarms */ | |
2042 | status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_MASK, | |
2043 | IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, | |
2044 | ®); | |
2045 | ||
2046 | if (status != IXGBE_SUCCESS) | |
2047 | return status; | |
2048 | ||
2049 | reg |= (IXGBE_MDIO_GLOBAL_INT_HI_TEMP_EN | | |
2050 | IXGBE_MDIO_GLOBAL_INT_DEV_FAULT_EN); | |
2051 | ||
2052 | status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_MASK, | |
2053 | IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, | |
2054 | reg); | |
2055 | ||
2056 | if (status != IXGBE_SUCCESS) | |
2057 | return status; | |
2058 | ||
2059 | /* Enable vendor Auto-Neg alarm and Global Interrupt Mask 1 alarm */ | |
2060 | status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK, | |
2061 | IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, | |
2062 | ®); | |
2063 | ||
2064 | if (status != IXGBE_SUCCESS) | |
2065 | return status; | |
2066 | ||
2067 | reg |= (IXGBE_MDIO_GLOBAL_AN_VEN_ALM_INT_EN | | |
2068 | IXGBE_MDIO_GLOBAL_ALARM_1_INT); | |
2069 | ||
2070 | status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK, | |
2071 | IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, | |
2072 | reg); | |
2073 | ||
2074 | if (status != IXGBE_SUCCESS) | |
2075 | return status; | |
2076 | ||
2077 | /* Enable chip-wide vendor alarm */ | |
2078 | status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_STD_MASK, | |
2079 | IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, | |
2080 | ®); | |
2081 | ||
2082 | if (status != IXGBE_SUCCESS) | |
2083 | return status; | |
2084 | ||
2085 | reg |= IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN; | |
2086 | ||
2087 | status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_STD_MASK, | |
2088 | IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, | |
2089 | reg); | |
2090 | ||
2091 | return status; | |
2092 | } | |
2093 | ||
2094 | /** | |
2095 | * ixgbe_setup_kr_speed_x550em - Configure the KR PHY for link speed. | |
2096 | * @hw: pointer to hardware structure | |
2097 | * @speed: link speed | |
2098 | * | |
2099 | * Configures the integrated KR PHY. | |
2100 | **/ | |
2101 | STATIC s32 ixgbe_setup_kr_speed_x550em(struct ixgbe_hw *hw, | |
2102 | ixgbe_link_speed speed) | |
2103 | { | |
2104 | s32 status; | |
2105 | u32 reg_val; | |
2106 | ||
2107 | status = hw->mac.ops.read_iosf_sb_reg(hw, | |
2108 | IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), | |
2109 | IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); | |
2110 | if (status) | |
2111 | return status; | |
2112 | ||
2113 | reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; | |
2114 | reg_val &= ~(IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR | | |
2115 | IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX); | |
2116 | ||
2117 | /* Advertise 10G support. */ | |
2118 | if (speed & IXGBE_LINK_SPEED_10GB_FULL) | |
2119 | reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR; | |
2120 | ||
2121 | /* Advertise 1G support. */ | |
2122 | if (speed & IXGBE_LINK_SPEED_1GB_FULL) | |
2123 | reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX; | |
2124 | ||
2125 | status = hw->mac.ops.write_iosf_sb_reg(hw, | |
2126 | IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), | |
2127 | IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); | |
2128 | ||
2129 | if (hw->mac.type == ixgbe_mac_X550EM_a) { | |
2130 | /* Set lane mode to KR auto negotiation */ | |
2131 | status = hw->mac.ops.read_iosf_sb_reg(hw, | |
2132 | IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), | |
2133 | IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); | |
2134 | ||
2135 | if (status) | |
2136 | return status; | |
2137 | ||
2138 | reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK; | |
2139 | reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_AN; | |
2140 | reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN; | |
2141 | reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN; | |
2142 | reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN; | |
2143 | ||
2144 | status = hw->mac.ops.write_iosf_sb_reg(hw, | |
2145 | IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), | |
2146 | IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); | |
2147 | } | |
2148 | ||
2149 | return ixgbe_restart_an_internal_phy_x550em(hw); | |
2150 | } | |
2151 | ||
2152 | /** | |
2153 | * ixgbe_setup_m88 - setup m88 PHY | |
2154 | * @hw: pointer to hardware structure | |
2155 | */ | |
2156 | STATIC s32 ixgbe_setup_m88(struct ixgbe_hw *hw) | |
2157 | { | |
2158 | u32 mask = hw->phy.phy_semaphore_mask | IXGBE_GSSR_TOKEN_SM; | |
2159 | u16 reg; | |
2160 | s32 rc; | |
2161 | ||
2162 | if (hw->phy.reset_disable || ixgbe_check_reset_blocked(hw)) | |
2163 | return IXGBE_SUCCESS; | |
2164 | ||
2165 | rc = hw->mac.ops.acquire_swfw_sync(hw, mask); | |
2166 | if (rc) | |
2167 | return rc; | |
2168 | ||
2169 | rc = hw->phy.ops.read_reg_mdi(hw, IXGBE_M88E1500_COPPER_CTRL, 0, ®); | |
2170 | if (rc) | |
2171 | goto out; | |
2172 | if (reg & IXGBE_M88E1500_COPPER_CTRL_POWER_DOWN) { | |
2173 | reg &= ~IXGBE_M88E1500_COPPER_CTRL_POWER_DOWN; | |
2174 | hw->phy.ops.write_reg_mdi(hw, IXGBE_M88E1500_COPPER_CTRL, 0, | |
2175 | reg); | |
2176 | } | |
2177 | ||
2178 | rc = hw->phy.ops.read_reg_mdi(hw, IXGBE_M88E1500_MAC_CTRL_1, 0, ®); | |
2179 | if (rc) | |
2180 | goto out; | |
2181 | if (reg & IXGBE_M88E1500_MAC_CTRL_1_POWER_DOWN) { | |
2182 | reg &= ~IXGBE_M88E1500_MAC_CTRL_1_POWER_DOWN; | |
2183 | hw->phy.ops.write_reg_mdi(hw, IXGBE_M88E1500_MAC_CTRL_1, 0, | |
2184 | reg); | |
2185 | } | |
2186 | ||
2187 | rc = hw->phy.ops.write_reg_mdi(hw, IXGBE_M88E1500_PAGE_ADDR, 0, 2); | |
2188 | if (rc) | |
2189 | goto out; | |
2190 | ||
2191 | rc = hw->phy.ops.read_reg_mdi(hw, IXGBE_M88E1500_MAC_SPEC_CTRL, 0, | |
2192 | ®); | |
2193 | if (rc) | |
2194 | goto out; | |
2195 | if (reg & IXGBE_M88E1500_MAC_SPEC_CTRL_POWER_DOWN) { | |
2196 | reg &= ~IXGBE_M88E1500_MAC_SPEC_CTRL_POWER_DOWN; | |
2197 | hw->phy.ops.write_reg_mdi(hw, IXGBE_M88E1500_MAC_SPEC_CTRL, 0, | |
2198 | reg); | |
2199 | rc = hw->phy.ops.write_reg_mdi(hw, IXGBE_M88E1500_PAGE_ADDR, 0, | |
2200 | 0); | |
2201 | if (rc) | |
2202 | goto out; | |
2203 | rc = hw->phy.ops.read_reg_mdi(hw, IXGBE_M88E1500_COPPER_CTRL, 0, | |
2204 | ®); | |
2205 | if (rc) | |
2206 | goto out; | |
2207 | reg |= IXGBE_M88E1500_COPPER_CTRL_RESET; | |
2208 | hw->phy.ops.write_reg_mdi(hw, IXGBE_M88E1500_COPPER_CTRL, 0, | |
2209 | reg); | |
2210 | usec_delay(50); | |
2211 | } else { | |
2212 | rc = hw->phy.ops.write_reg_mdi(hw, IXGBE_M88E1500_PAGE_ADDR, 0, | |
2213 | 0); | |
2214 | if (rc) | |
2215 | goto out; | |
2216 | } | |
2217 | ||
2218 | rc = hw->phy.ops.read_reg_mdi(hw, IXGBE_M88E1500_COPPER_CTRL, 0, ®); | |
2219 | if (rc) | |
2220 | goto out; | |
2221 | ||
2222 | if (!(reg & IXGBE_M88E1500_COPPER_CTRL_AN_EN)) { | |
2223 | reg |= IXGBE_M88E1500_COPPER_CTRL_AN_EN; | |
2224 | hw->phy.ops.write_reg_mdi(hw, IXGBE_M88E1500_COPPER_CTRL, 0, | |
2225 | reg); | |
2226 | } | |
2227 | ||
2228 | rc = hw->phy.ops.read_reg_mdi(hw, IXGBE_M88E1500_1000T_CTRL, 0, ®); | |
2229 | if (rc) | |
2230 | goto out; | |
2231 | reg &= ~IXGBE_M88E1500_1000T_CTRL_HALF_DUPLEX; | |
2232 | reg &= ~IXGBE_M88E1500_1000T_CTRL_FULL_DUPLEX; | |
2233 | if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL) | |
2234 | reg |= IXGBE_M88E1500_1000T_CTRL_FULL_DUPLEX; | |
2235 | hw->phy.ops.write_reg_mdi(hw, IXGBE_M88E1500_1000T_CTRL, 0, reg); | |
2236 | ||
2237 | rc = hw->phy.ops.read_reg_mdi(hw, IXGBE_M88E1500_COPPER_AN, 0, ®); | |
2238 | if (rc) | |
2239 | goto out; | |
2240 | reg &= ~IXGBE_M88E1500_COPPER_AN_T4; | |
2241 | reg &= ~IXGBE_M88E1500_COPPER_AN_100TX_FD; | |
2242 | reg &= ~IXGBE_M88E1500_COPPER_AN_100TX_HD; | |
2243 | reg &= ~IXGBE_M88E1500_COPPER_AN_10TX_FD; | |
2244 | reg &= ~IXGBE_M88E1500_COPPER_AN_10TX_HD; | |
2245 | ||
2246 | /* Flow control auto negotiation configuration was moved from here to | |
2247 | * the function ixgbe_setup_fc_sgmii_x550em_a() | |
2248 | */ | |
2249 | ||
2250 | if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_100_FULL) | |
2251 | reg |= IXGBE_M88E1500_COPPER_AN_100TX_FD; | |
2252 | if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10_FULL) | |
2253 | reg |= IXGBE_M88E1500_COPPER_AN_10TX_FD; | |
2254 | hw->phy.ops.write_reg_mdi(hw, IXGBE_M88E1500_COPPER_AN, 0, reg); | |
2255 | ||
2256 | rc = hw->phy.ops.read_reg_mdi(hw, IXGBE_M88E1500_COPPER_CTRL, 0, ®); | |
2257 | if (rc) | |
2258 | goto out; | |
2259 | reg |= IXGBE_M88E1500_COPPER_CTRL_RESTART_AN; | |
2260 | hw->phy.ops.write_reg_mdi(hw, IXGBE_M88E1500_COPPER_CTRL, 0, reg); | |
2261 | ||
2262 | ||
2263 | hw->mac.ops.release_swfw_sync(hw, mask); | |
2264 | return rc; | |
2265 | ||
2266 | out: | |
2267 | hw->phy.ops.write_reg_mdi(hw, IXGBE_M88E1500_PAGE_ADDR, 0, 0); | |
2268 | hw->mac.ops.release_swfw_sync(hw, mask); | |
2269 | return rc; | |
2270 | } | |
2271 | ||
2272 | /** | |
2273 | * ixgbe_reset_phy_m88e1500 - Reset m88e1500 PHY | |
2274 | * @hw: pointer to hardware structure | |
2275 | * | |
2276 | * The PHY token must be held when calling this function. | |
2277 | */ | |
2278 | static s32 ixgbe_reset_phy_m88e1500(struct ixgbe_hw *hw) | |
2279 | { | |
2280 | u16 reg; | |
2281 | s32 rc; | |
2282 | ||
2283 | rc = hw->phy.ops.write_reg_mdi(hw, IXGBE_M88E1500_PAGE_ADDR, 0, 0); | |
2284 | if (rc) | |
2285 | return rc; | |
2286 | ||
2287 | rc = hw->phy.ops.read_reg_mdi(hw, IXGBE_M88E1500_COPPER_CTRL, 0, ®); | |
2288 | if (rc) | |
2289 | return rc; | |
2290 | ||
2291 | reg |= IXGBE_M88E1500_COPPER_CTRL_RESET; | |
2292 | rc = hw->phy.ops.write_reg_mdi(hw, IXGBE_M88E1500_COPPER_CTRL, 0, reg); | |
2293 | ||
2294 | usec_delay(10); | |
2295 | ||
2296 | return rc; | |
2297 | } | |
2298 | ||
2299 | /** | |
2300 | * ixgbe_reset_phy_m88e1543 - Reset m88e1543 PHY | |
2301 | * @hw: pointer to hardware structure | |
2302 | * | |
2303 | * The PHY token must be held when calling this function. | |
2304 | */ | |
2305 | static s32 ixgbe_reset_phy_m88e1543(struct ixgbe_hw *hw) | |
2306 | { | |
2307 | return hw->phy.ops.write_reg_mdi(hw, IXGBE_M88E1500_PAGE_ADDR, 0, 0); | |
2308 | } | |
2309 | ||
2310 | /** | |
2311 | * ixgbe_reset_phy_m88 - Reset m88 PHY | |
2312 | * @hw: pointer to hardware structure | |
2313 | */ | |
2314 | STATIC s32 ixgbe_reset_phy_m88(struct ixgbe_hw *hw) | |
2315 | { | |
2316 | u32 mask = hw->phy.phy_semaphore_mask | IXGBE_GSSR_TOKEN_SM; | |
2317 | u16 reg; | |
2318 | s32 rc; | |
2319 | ||
2320 | if (hw->phy.reset_disable || ixgbe_check_reset_blocked(hw)) | |
2321 | return IXGBE_SUCCESS; | |
2322 | ||
2323 | rc = hw->mac.ops.acquire_swfw_sync(hw, mask); | |
2324 | if (rc) | |
2325 | return rc; | |
2326 | ||
2327 | switch (hw->phy.id) { | |
2328 | case IXGBE_M88E1500_E_PHY_ID: | |
2329 | rc = ixgbe_reset_phy_m88e1500(hw); | |
2330 | break; | |
2331 | case IXGBE_M88E1543_E_PHY_ID: | |
2332 | rc = ixgbe_reset_phy_m88e1543(hw); | |
2333 | break; | |
2334 | default: | |
2335 | rc = IXGBE_ERR_PHY; | |
2336 | break; | |
2337 | } | |
2338 | ||
2339 | rc = hw->phy.ops.write_reg_mdi(hw, IXGBE_M88E1500_PAGE_ADDR, 0, 1); | |
2340 | if (rc) | |
2341 | goto out; | |
2342 | ||
2343 | reg = IXGBE_M88E1500_FIBER_CTRL_RESET | | |
2344 | IXGBE_M88E1500_FIBER_CTRL_DUPLEX_FULL | | |
2345 | IXGBE_M88E1500_FIBER_CTRL_SPEED_MSB; | |
2346 | rc = hw->phy.ops.write_reg_mdi(hw, IXGBE_M88E1500_FIBER_CTRL, 0, reg); | |
2347 | if (rc) | |
2348 | goto out; | |
2349 | ||
2350 | rc = hw->phy.ops.write_reg_mdi(hw, IXGBE_M88E1500_PAGE_ADDR, 0, 18); | |
2351 | if (rc) | |
2352 | goto out; | |
2353 | ||
2354 | reg = IXGBE_M88E1500_GEN_CTRL_RESET | | |
2355 | IXGBE_M88E1500_GEN_CTRL_MODE_SGMII_COPPER; | |
2356 | rc = hw->phy.ops.write_reg_mdi(hw, IXGBE_M88E1500_GEN_CTRL, 0, reg); | |
2357 | if (rc) | |
2358 | goto out; | |
2359 | ||
2360 | rc = hw->phy.ops.write_reg_mdi(hw, IXGBE_M88E1500_PAGE_ADDR, 0, 1); | |
2361 | if (rc) | |
2362 | goto out; | |
2363 | ||
2364 | reg = IXGBE_M88E1500_FIBER_CTRL_RESET | | |
2365 | IXGBE_M88E1500_FIBER_CTRL_AN_EN | | |
2366 | IXGBE_M88E1500_FIBER_CTRL_DUPLEX_FULL | | |
2367 | IXGBE_M88E1500_FIBER_CTRL_SPEED_MSB; | |
2368 | rc = hw->phy.ops.write_reg_mdi(hw, IXGBE_M88E1500_FIBER_CTRL, 0, reg); | |
2369 | if (rc) | |
2370 | goto out; | |
2371 | ||
2372 | rc = hw->phy.ops.write_reg_mdi(hw, IXGBE_M88E1500_PAGE_ADDR, 0, 0); | |
2373 | if (rc) | |
2374 | goto out; | |
2375 | ||
2376 | reg = (IXGBE_M88E1500_MAC_CTRL_1_DWN_4X << | |
2377 | IXGBE_M88E1500_MAC_CTRL_1_DWN_SHIFT) | | |
2378 | (IXGBE_M88E1500_MAC_CTRL_1_ED_TM << | |
2379 | IXGBE_M88E1500_MAC_CTRL_1_ED_SHIFT) | | |
2380 | (IXGBE_M88E1500_MAC_CTRL_1_MDIX_AUTO << | |
2381 | IXGBE_M88E1500_MAC_CTRL_1_MDIX_SHIFT); | |
2382 | rc = hw->phy.ops.write_reg_mdi(hw, IXGBE_M88E1500_MAC_CTRL_1, 0, reg); | |
2383 | if (rc) | |
2384 | goto out; | |
2385 | ||
2386 | reg = IXGBE_M88E1500_COPPER_CTRL_RESET | | |
2387 | IXGBE_M88E1500_COPPER_CTRL_AN_EN | | |
2388 | IXGBE_M88E1500_COPPER_CTRL_RESTART_AN | | |
2389 | IXGBE_M88E1500_COPPER_CTRL_FULL_DUPLEX | | |
2390 | IXGBE_M88E1500_COPPER_CTRL_SPEED_MSB; | |
2391 | rc = hw->phy.ops.write_reg_mdi(hw, IXGBE_M88E1500_COPPER_CTRL, 0, reg); | |
2392 | if (rc) | |
2393 | goto out; | |
2394 | ||
2395 | hw->mac.ops.release_swfw_sync(hw, mask); | |
2396 | ||
2397 | /* In case of first reset set advertised speeds to default value */ | |
2398 | if (!hw->phy.autoneg_advertised) | |
2399 | hw->phy.autoneg_advertised = IXGBE_LINK_SPEED_1GB_FULL | | |
2400 | IXGBE_LINK_SPEED_100_FULL | | |
2401 | IXGBE_LINK_SPEED_10_FULL; | |
2402 | ||
2403 | return ixgbe_setup_m88(hw); | |
2404 | ||
2405 | out: | |
2406 | hw->phy.ops.write_reg_mdi(hw, IXGBE_M88E1500_PAGE_ADDR, 0, 0); | |
2407 | hw->mac.ops.release_swfw_sync(hw, mask); | |
2408 | return rc; | |
2409 | } | |
2410 | ||
2411 | /** | |
2412 | * ixgbe_read_mng_if_sel_x550em - Read NW_MNG_IF_SEL register | |
2413 | * @hw: pointer to hardware structure | |
2414 | * | |
2415 | * Read NW_MNG_IF_SEL register and save field values, and check for valid field | |
2416 | * values. | |
2417 | **/ | |
2418 | STATIC s32 ixgbe_read_mng_if_sel_x550em(struct ixgbe_hw *hw) | |
2419 | { | |
2420 | /* Save NW management interface connected on board. This is used | |
2421 | * to determine internal PHY mode. | |
2422 | */ | |
2423 | hw->phy.nw_mng_if_sel = IXGBE_READ_REG(hw, IXGBE_NW_MNG_IF_SEL); | |
2424 | ||
2425 | /* If X552 (X550EM_a) and MDIO is connected to external PHY, then set | |
2426 | * PHY address. This register field was has only been used for X552. | |
2427 | */ | |
2428 | if (hw->mac.type == ixgbe_mac_X550EM_a && | |
2429 | hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_MDIO_ACT) { | |
2430 | hw->phy.addr = (hw->phy.nw_mng_if_sel & | |
2431 | IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD) >> | |
2432 | IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD_SHIFT; | |
2433 | } | |
2434 | ||
2435 | return IXGBE_SUCCESS; | |
2436 | } | |
2437 | ||
2438 | /** | |
2439 | * ixgbe_init_phy_ops_X550em - PHY/SFP specific init | |
2440 | * @hw: pointer to hardware structure | |
2441 | * | |
2442 | * Initialize any function pointers that were not able to be | |
2443 | * set during init_shared_code because the PHY/SFP type was | |
2444 | * not known. Perform the SFP init if necessary. | |
2445 | */ | |
2446 | s32 ixgbe_init_phy_ops_X550em(struct ixgbe_hw *hw) | |
2447 | { | |
2448 | struct ixgbe_phy_info *phy = &hw->phy; | |
2449 | s32 ret_val; | |
2450 | ||
2451 | DEBUGFUNC("ixgbe_init_phy_ops_X550em"); | |
2452 | ||
2453 | if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber) { | |
2454 | phy->phy_semaphore_mask = IXGBE_GSSR_SHARED_I2C_SM; | |
2455 | ixgbe_setup_mux_ctl(hw); | |
2456 | phy->ops.identify_sfp = ixgbe_identify_sfp_module_X550em; | |
2457 | } | |
2458 | ||
2459 | switch (hw->device_id) { | |
2460 | case IXGBE_DEV_ID_X550EM_A_1G_T: | |
2461 | case IXGBE_DEV_ID_X550EM_A_1G_T_L: | |
2462 | phy->ops.read_reg_mdi = ixgbe_read_phy_reg_mdi_22; | |
2463 | phy->ops.write_reg_mdi = ixgbe_write_phy_reg_mdi_22; | |
2464 | hw->phy.ops.read_reg = ixgbe_read_phy_reg_x550a; | |
2465 | hw->phy.ops.write_reg = ixgbe_write_phy_reg_x550a; | |
2466 | if (hw->bus.lan_id) | |
2467 | hw->phy.phy_semaphore_mask |= IXGBE_GSSR_PHY1_SM; | |
2468 | else | |
2469 | hw->phy.phy_semaphore_mask |= IXGBE_GSSR_PHY0_SM; | |
2470 | ||
2471 | break; | |
2472 | case IXGBE_DEV_ID_X550EM_A_10G_T: | |
2473 | case IXGBE_DEV_ID_X550EM_A_SFP: | |
2474 | hw->phy.ops.read_reg = ixgbe_read_phy_reg_x550a; | |
2475 | hw->phy.ops.write_reg = ixgbe_write_phy_reg_x550a; | |
2476 | if (hw->bus.lan_id) | |
2477 | hw->phy.phy_semaphore_mask |= IXGBE_GSSR_PHY1_SM; | |
2478 | else | |
2479 | hw->phy.phy_semaphore_mask |= IXGBE_GSSR_PHY0_SM; | |
2480 | break; | |
2481 | case IXGBE_DEV_ID_X550EM_X_SFP: | |
2482 | /* set up for CS4227 usage */ | |
2483 | hw->phy.phy_semaphore_mask = IXGBE_GSSR_SHARED_I2C_SM; | |
2484 | break; | |
2485 | default: | |
2486 | break; | |
2487 | } | |
2488 | ||
2489 | /* Identify the PHY or SFP module */ | |
2490 | ret_val = phy->ops.identify(hw); | |
2491 | if (ret_val == IXGBE_ERR_SFP_NOT_SUPPORTED) | |
2492 | return ret_val; | |
2493 | ||
2494 | /* Setup function pointers based on detected hardware */ | |
2495 | ixgbe_init_mac_link_ops_X550em(hw); | |
2496 | if (phy->sfp_type != ixgbe_sfp_type_unknown) | |
2497 | phy->ops.reset = NULL; | |
2498 | ||
2499 | /* Set functions pointers based on phy type */ | |
2500 | switch (hw->phy.type) { | |
2501 | case ixgbe_phy_x550em_kx4: | |
2502 | phy->ops.setup_link = NULL; | |
2503 | phy->ops.read_reg = ixgbe_read_phy_reg_x550em; | |
2504 | phy->ops.write_reg = ixgbe_write_phy_reg_x550em; | |
2505 | break; | |
2506 | case ixgbe_phy_x550em_kr: | |
2507 | phy->ops.setup_link = ixgbe_setup_kr_x550em; | |
2508 | phy->ops.read_reg = ixgbe_read_phy_reg_x550em; | |
2509 | phy->ops.write_reg = ixgbe_write_phy_reg_x550em; | |
2510 | break; | |
2511 | case ixgbe_phy_x550em_ext_t: | |
2512 | /* If internal link mode is XFI, then setup iXFI internal link, | |
2513 | * else setup KR now. | |
2514 | */ | |
2515 | phy->ops.setup_internal_link = | |
2516 | ixgbe_setup_internal_phy_t_x550em; | |
2517 | ||
2518 | /* setup SW LPLU only for first revision of X550EM_x */ | |
2519 | if ((hw->mac.type == ixgbe_mac_X550EM_x) && | |
2520 | !(IXGBE_FUSES0_REV_MASK & | |
2521 | IXGBE_READ_REG(hw, IXGBE_FUSES0_GROUP(0)))) | |
2522 | phy->ops.enter_lplu = ixgbe_enter_lplu_t_x550em; | |
2523 | ||
2524 | phy->ops.handle_lasi = ixgbe_handle_lasi_ext_t_x550em; | |
2525 | phy->ops.reset = ixgbe_reset_phy_t_X550em; | |
2526 | break; | |
2527 | case ixgbe_phy_sgmii: | |
2528 | phy->ops.setup_link = NULL; | |
2529 | break; | |
2530 | case ixgbe_phy_m88: | |
2531 | phy->ops.setup_link = ixgbe_setup_m88; | |
2532 | phy->ops.reset = ixgbe_reset_phy_m88; | |
2533 | break; | |
2534 | default: | |
2535 | break; | |
2536 | } | |
2537 | return ret_val; | |
2538 | } | |
2539 | ||
2540 | /** | |
2541 | * ixgbe_set_mdio_speed - Set MDIO clock speed | |
2542 | * @hw: pointer to hardware structure | |
2543 | */ | |
2544 | STATIC void ixgbe_set_mdio_speed(struct ixgbe_hw *hw) | |
2545 | { | |
2546 | u32 hlreg0; | |
2547 | ||
2548 | switch (hw->device_id) { | |
2549 | case IXGBE_DEV_ID_X550EM_X_10G_T: | |
2550 | case IXGBE_DEV_ID_X550EM_A_SGMII: | |
2551 | case IXGBE_DEV_ID_X550EM_A_SGMII_L: | |
2552 | case IXGBE_DEV_ID_X550EM_A_1G_T: | |
2553 | case IXGBE_DEV_ID_X550EM_A_1G_T_L: | |
2554 | case IXGBE_DEV_ID_X550EM_A_10G_T: | |
2555 | case IXGBE_DEV_ID_X550EM_A_SFP: | |
2556 | case IXGBE_DEV_ID_X550EM_A_QSFP: | |
2557 | /* Config MDIO clock speed before the first MDIO PHY access */ | |
2558 | hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0); | |
2559 | hlreg0 &= ~IXGBE_HLREG0_MDCSPD; | |
2560 | IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0); | |
2561 | break; | |
2562 | default: | |
2563 | break; | |
2564 | } | |
2565 | } | |
2566 | ||
2567 | /** | |
2568 | * ixgbe_reset_hw_X550em - Perform hardware reset | |
2569 | * @hw: pointer to hardware structure | |
2570 | * | |
2571 | * Resets the hardware by resetting the transmit and receive units, masks | |
2572 | * and clears all interrupts, perform a PHY reset, and perform a link (MAC) | |
2573 | * reset. | |
2574 | */ | |
2575 | s32 ixgbe_reset_hw_X550em(struct ixgbe_hw *hw) | |
2576 | { | |
2577 | ixgbe_link_speed link_speed; | |
2578 | s32 status; | |
2579 | u32 ctrl = 0; | |
2580 | u32 i; | |
2581 | bool link_up = false; | |
2582 | ||
2583 | DEBUGFUNC("ixgbe_reset_hw_X550em"); | |
2584 | ||
2585 | /* Call adapter stop to disable Tx/Rx and clear interrupts */ | |
2586 | status = hw->mac.ops.stop_adapter(hw); | |
2587 | if (status != IXGBE_SUCCESS) | |
2588 | return status; | |
2589 | ||
2590 | /* flush pending Tx transactions */ | |
2591 | ixgbe_clear_tx_pending(hw); | |
2592 | ||
2593 | ixgbe_set_mdio_speed(hw); | |
2594 | ||
2595 | /* PHY ops must be identified and initialized prior to reset */ | |
2596 | status = hw->phy.ops.init(hw); | |
2597 | ||
2598 | if (status == IXGBE_ERR_SFP_NOT_SUPPORTED) | |
2599 | return status; | |
2600 | ||
2601 | /* start the external PHY */ | |
2602 | if (hw->phy.type == ixgbe_phy_x550em_ext_t) { | |
2603 | status = ixgbe_init_ext_t_x550em(hw); | |
2604 | if (status) | |
2605 | return status; | |
2606 | } | |
2607 | ||
2608 | /* Setup SFP module if there is one present. */ | |
2609 | if (hw->phy.sfp_setup_needed) { | |
2610 | status = hw->mac.ops.setup_sfp(hw); | |
2611 | hw->phy.sfp_setup_needed = false; | |
2612 | } | |
2613 | ||
2614 | if (status == IXGBE_ERR_SFP_NOT_SUPPORTED) | |
2615 | return status; | |
2616 | ||
2617 | /* Reset PHY */ | |
2618 | if (!hw->phy.reset_disable && hw->phy.ops.reset) | |
2619 | hw->phy.ops.reset(hw); | |
2620 | ||
2621 | mac_reset_top: | |
2622 | /* Issue global reset to the MAC. Needs to be SW reset if link is up. | |
2623 | * If link reset is used when link is up, it might reset the PHY when | |
2624 | * mng is using it. If link is down or the flag to force full link | |
2625 | * reset is set, then perform link reset. | |
2626 | */ | |
2627 | ctrl = IXGBE_CTRL_LNK_RST; | |
2628 | if (!hw->force_full_reset) { | |
2629 | hw->mac.ops.check_link(hw, &link_speed, &link_up, false); | |
2630 | if (link_up) | |
2631 | ctrl = IXGBE_CTRL_RST; | |
2632 | } | |
2633 | ||
2634 | ctrl |= IXGBE_READ_REG(hw, IXGBE_CTRL); | |
2635 | IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl); | |
2636 | IXGBE_WRITE_FLUSH(hw); | |
2637 | ||
2638 | /* Poll for reset bit to self-clear meaning reset is complete */ | |
2639 | for (i = 0; i < 10; i++) { | |
2640 | usec_delay(1); | |
2641 | ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL); | |
2642 | if (!(ctrl & IXGBE_CTRL_RST_MASK)) | |
2643 | break; | |
2644 | } | |
2645 | ||
2646 | if (ctrl & IXGBE_CTRL_RST_MASK) { | |
2647 | status = IXGBE_ERR_RESET_FAILED; | |
2648 | DEBUGOUT("Reset polling failed to complete.\n"); | |
2649 | } | |
2650 | ||
2651 | msec_delay(50); | |
2652 | ||
2653 | /* Double resets are required for recovery from certain error | |
2654 | * conditions. Between resets, it is necessary to stall to | |
2655 | * allow time for any pending HW events to complete. | |
2656 | */ | |
2657 | if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) { | |
2658 | hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED; | |
2659 | goto mac_reset_top; | |
2660 | } | |
2661 | ||
2662 | /* Store the permanent mac address */ | |
2663 | hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr); | |
2664 | ||
2665 | /* Store MAC address from RAR0, clear receive address registers, and | |
2666 | * clear the multicast table. Also reset num_rar_entries to 128, | |
2667 | * since we modify this value when programming the SAN MAC address. | |
2668 | */ | |
2669 | hw->mac.num_rar_entries = 128; | |
2670 | hw->mac.ops.init_rx_addrs(hw); | |
2671 | ||
2672 | ixgbe_set_mdio_speed(hw); | |
2673 | ||
2674 | if (hw->device_id == IXGBE_DEV_ID_X550EM_X_SFP) | |
2675 | ixgbe_setup_mux_ctl(hw); | |
2676 | ||
2677 | return status; | |
2678 | } | |
2679 | ||
2680 | /** | |
2681 | * ixgbe_init_ext_t_x550em - Start (unstall) the external Base T PHY. | |
2682 | * @hw: pointer to hardware structure | |
2683 | */ | |
2684 | s32 ixgbe_init_ext_t_x550em(struct ixgbe_hw *hw) | |
2685 | { | |
2686 | u32 status; | |
2687 | u16 reg; | |
2688 | ||
2689 | status = hw->phy.ops.read_reg(hw, | |
2690 | IXGBE_MDIO_TX_VENDOR_ALARMS_3, | |
2691 | IXGBE_MDIO_PMA_PMD_DEV_TYPE, | |
2692 | ®); | |
2693 | ||
2694 | if (status != IXGBE_SUCCESS) | |
2695 | return status; | |
2696 | ||
2697 | /* If PHY FW reset completed bit is set then this is the first | |
2698 | * SW instance after a power on so the PHY FW must be un-stalled. | |
2699 | */ | |
2700 | if (reg & IXGBE_MDIO_TX_VENDOR_ALARMS_3_RST_MASK) { | |
2701 | status = hw->phy.ops.read_reg(hw, | |
2702 | IXGBE_MDIO_GLOBAL_RES_PR_10, | |
2703 | IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, | |
2704 | ®); | |
2705 | ||
2706 | if (status != IXGBE_SUCCESS) | |
2707 | return status; | |
2708 | ||
2709 | reg &= ~IXGBE_MDIO_POWER_UP_STALL; | |
2710 | ||
2711 | status = hw->phy.ops.write_reg(hw, | |
2712 | IXGBE_MDIO_GLOBAL_RES_PR_10, | |
2713 | IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, | |
2714 | reg); | |
2715 | ||
2716 | if (status != IXGBE_SUCCESS) | |
2717 | return status; | |
2718 | } | |
2719 | ||
2720 | return status; | |
2721 | } | |
2722 | ||
2723 | /** | |
2724 | * ixgbe_setup_kr_x550em - Configure the KR PHY. | |
2725 | * @hw: pointer to hardware structure | |
2726 | * | |
2727 | * Configures the integrated KR PHY for X550EM_x. | |
2728 | **/ | |
2729 | s32 ixgbe_setup_kr_x550em(struct ixgbe_hw *hw) | |
2730 | { | |
2731 | if (hw->mac.type != ixgbe_mac_X550EM_x) | |
2732 | return IXGBE_SUCCESS; | |
2733 | ||
2734 | return ixgbe_setup_kr_speed_x550em(hw, hw->phy.autoneg_advertised); | |
2735 | } | |
2736 | ||
2737 | /** | |
2738 | * ixgbe_setup_mac_link_sfp_x550em - Setup internal/external the PHY for SFP | |
2739 | * @hw: pointer to hardware structure | |
2740 | * | |
2741 | * Configure the external PHY and the integrated KR PHY for SFP support. | |
2742 | **/ | |
2743 | s32 ixgbe_setup_mac_link_sfp_x550em(struct ixgbe_hw *hw, | |
2744 | ixgbe_link_speed speed, | |
2745 | bool autoneg_wait_to_complete) | |
2746 | { | |
2747 | s32 ret_val; | |
2748 | u16 reg_slice, reg_val; | |
2749 | bool setup_linear = false; | |
2750 | UNREFERENCED_1PARAMETER(autoneg_wait_to_complete); | |
2751 | ||
2752 | /* Check if SFP module is supported and linear */ | |
2753 | ret_val = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear); | |
2754 | ||
2755 | /* If no SFP module present, then return success. Return success since | |
2756 | * there is no reason to configure CS4227 and SFP not present error is | |
2757 | * not excepted in the setup MAC link flow. | |
2758 | */ | |
2759 | if (ret_val == IXGBE_ERR_SFP_NOT_PRESENT) | |
2760 | return IXGBE_SUCCESS; | |
2761 | ||
2762 | if (ret_val != IXGBE_SUCCESS) | |
2763 | return ret_val; | |
2764 | ||
2765 | if (!(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE)) { | |
2766 | /* Configure CS4227 LINE side to 10G SR. */ | |
2767 | reg_slice = IXGBE_CS4227_LINE_SPARE22_MSB + | |
2768 | (hw->bus.lan_id << 12); | |
2769 | reg_val = IXGBE_CS4227_SPEED_10G; | |
2770 | ret_val = hw->link.ops.write_link(hw, hw->link.addr, reg_slice, | |
2771 | reg_val); | |
2772 | ||
2773 | reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB + | |
2774 | (hw->bus.lan_id << 12); | |
2775 | reg_val = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1; | |
2776 | ret_val = hw->link.ops.write_link(hw, hw->link.addr, reg_slice, | |
2777 | reg_val); | |
2778 | ||
2779 | /* Configure CS4227 for HOST connection rate then type. */ | |
2780 | reg_slice = IXGBE_CS4227_HOST_SPARE22_MSB + | |
2781 | (hw->bus.lan_id << 12); | |
2782 | reg_val = (speed & IXGBE_LINK_SPEED_10GB_FULL) ? | |
2783 | IXGBE_CS4227_SPEED_10G : IXGBE_CS4227_SPEED_1G; | |
2784 | ret_val = hw->link.ops.write_link(hw, hw->link.addr, reg_slice, | |
2785 | reg_val); | |
2786 | ||
2787 | reg_slice = IXGBE_CS4227_HOST_SPARE24_LSB + | |
2788 | (hw->bus.lan_id << 12); | |
2789 | if (setup_linear) | |
2790 | reg_val = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1; | |
2791 | else | |
2792 | reg_val = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1; | |
2793 | ret_val = hw->link.ops.write_link(hw, hw->link.addr, reg_slice, | |
2794 | reg_val); | |
2795 | ||
2796 | /* Setup XFI internal link. */ | |
2797 | ret_val = ixgbe_setup_ixfi_x550em(hw, &speed); | |
2798 | } else { | |
2799 | /* Configure internal PHY for KR/KX. */ | |
2800 | ixgbe_setup_kr_speed_x550em(hw, speed); | |
2801 | ||
2802 | /* Configure CS4227 LINE side to proper mode. */ | |
2803 | reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB + | |
2804 | (hw->bus.lan_id << 12); | |
2805 | if (setup_linear) | |
2806 | reg_val = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1; | |
2807 | else | |
2808 | reg_val = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1; | |
2809 | ret_val = hw->link.ops.write_link(hw, hw->link.addr, reg_slice, | |
2810 | reg_val); | |
2811 | } | |
2812 | return ret_val; | |
2813 | } | |
2814 | ||
2815 | /** | |
2816 | * ixgbe_setup_sfi_x550a - Configure the internal PHY for native SFI mode | |
2817 | * @hw: pointer to hardware structure | |
2818 | * @speed: the link speed to force | |
2819 | * | |
2820 | * Configures the integrated PHY for native SFI mode. Used to connect the | |
2821 | * internal PHY directly to an SFP cage, without autonegotiation. | |
2822 | **/ | |
2823 | STATIC s32 ixgbe_setup_sfi_x550a(struct ixgbe_hw *hw, ixgbe_link_speed *speed) | |
2824 | { | |
2825 | struct ixgbe_mac_info *mac = &hw->mac; | |
2826 | s32 status; | |
2827 | u32 reg_val; | |
2828 | ||
2829 | /* Disable all AN and force speed to 10G Serial. */ | |
2830 | status = mac->ops.read_iosf_sb_reg(hw, | |
2831 | IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), | |
2832 | IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); | |
2833 | if (status != IXGBE_SUCCESS) | |
2834 | return status; | |
2835 | ||
2836 | reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN; | |
2837 | reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN; | |
2838 | reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN; | |
2839 | reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK; | |
2840 | ||
2841 | /* Select forced link speed for internal PHY. */ | |
2842 | switch (*speed) { | |
2843 | case IXGBE_LINK_SPEED_10GB_FULL: | |
2844 | reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_10G; | |
2845 | break; | |
2846 | case IXGBE_LINK_SPEED_1GB_FULL: | |
2847 | reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_1G; | |
2848 | break; | |
2849 | default: | |
2850 | /* Other link speeds are not supported by internal PHY. */ | |
2851 | return IXGBE_ERR_LINK_SETUP; | |
2852 | } | |
2853 | ||
2854 | status = mac->ops.write_iosf_sb_reg(hw, | |
2855 | IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), | |
2856 | IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); | |
2857 | ||
2858 | /* Toggle port SW reset by AN reset. */ | |
2859 | status = ixgbe_restart_an_internal_phy_x550em(hw); | |
2860 | ||
2861 | return status; | |
2862 | } | |
2863 | ||
2864 | /** | |
2865 | * ixgbe_setup_mac_link_sfp_x550a - Setup internal PHY for SFP | |
2866 | * @hw: pointer to hardware structure | |
2867 | * | |
2868 | * Configure the the integrated PHY for SFP support. | |
2869 | **/ | |
2870 | s32 ixgbe_setup_mac_link_sfp_x550a(struct ixgbe_hw *hw, | |
2871 | ixgbe_link_speed speed, | |
2872 | bool autoneg_wait_to_complete) | |
2873 | { | |
2874 | s32 ret_val; | |
2875 | u16 reg_phy_ext; | |
2876 | bool setup_linear = false; | |
2877 | u32 reg_slice, reg_phy_int, slice_offset; | |
2878 | ||
2879 | UNREFERENCED_1PARAMETER(autoneg_wait_to_complete); | |
2880 | ||
2881 | /* Check if SFP module is supported and linear */ | |
2882 | ret_val = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear); | |
2883 | ||
2884 | /* If no SFP module present, then return success. Return success since | |
2885 | * SFP not present error is not excepted in the setup MAC link flow. | |
2886 | */ | |
2887 | if (ret_val == IXGBE_ERR_SFP_NOT_PRESENT) | |
2888 | return IXGBE_SUCCESS; | |
2889 | ||
2890 | if (ret_val != IXGBE_SUCCESS) | |
2891 | return ret_val; | |
2892 | ||
2893 | if (hw->device_id == IXGBE_DEV_ID_X550EM_A_SFP_N) { | |
2894 | /* Configure internal PHY for native SFI based on module type */ | |
2895 | ret_val = hw->mac.ops.read_iosf_sb_reg(hw, | |
2896 | IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), | |
2897 | IXGBE_SB_IOSF_TARGET_KR_PHY, ®_phy_int); | |
2898 | ||
2899 | if (ret_val != IXGBE_SUCCESS) | |
2900 | return ret_val; | |
2901 | ||
2902 | reg_phy_int &= IXGBE_KRM_PMD_FLX_MASK_ST20_SFI_10G_DA; | |
2903 | if (!setup_linear) | |
2904 | reg_phy_int |= IXGBE_KRM_PMD_FLX_MASK_ST20_SFI_10G_SR; | |
2905 | ||
2906 | ret_val = hw->mac.ops.write_iosf_sb_reg(hw, | |
2907 | IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id), | |
2908 | IXGBE_SB_IOSF_TARGET_KR_PHY, reg_phy_int); | |
2909 | ||
2910 | if (ret_val != IXGBE_SUCCESS) | |
2911 | return ret_val; | |
2912 | ||
2913 | /* Setup SFI internal link. */ | |
2914 | ret_val = ixgbe_setup_sfi_x550a(hw, &speed); | |
2915 | } else { | |
2916 | /* Configure internal PHY for KR/KX. */ | |
2917 | ixgbe_setup_kr_speed_x550em(hw, speed); | |
2918 | ||
2919 | if (hw->phy.addr == 0x0 || hw->phy.addr == 0xFFFF) { | |
2920 | /* Find Address */ | |
2921 | DEBUGOUT("Invalid NW_MNG_IF_SEL.MDIO_PHY_ADD value\n"); | |
2922 | return IXGBE_ERR_PHY_ADDR_INVALID; | |
2923 | } | |
2924 | ||
2925 | /* Get external PHY device id */ | |
2926 | ret_val = hw->phy.ops.read_reg(hw, IXGBE_CS4227_GLOBAL_ID_MSB, | |
2927 | IXGBE_MDIO_ZERO_DEV_TYPE, ®_phy_ext); | |
2928 | ||
2929 | if (ret_val != IXGBE_SUCCESS) | |
2930 | return ret_val; | |
2931 | ||
2932 | /* When configuring quad port CS4223, the MAC instance is part | |
2933 | * of the slice offset. | |
2934 | */ | |
2935 | if (reg_phy_ext == IXGBE_CS4223_PHY_ID) | |
2936 | slice_offset = (hw->bus.lan_id + | |
2937 | (hw->bus.instance_id << 1)) << 12; | |
2938 | else | |
2939 | slice_offset = hw->bus.lan_id << 12; | |
2940 | ||
2941 | /* Configure CS4227/CS4223 LINE side to proper mode. */ | |
2942 | reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB + slice_offset; | |
2943 | if (setup_linear) | |
2944 | reg_phy_ext = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1; | |
2945 | else | |
2946 | reg_phy_ext = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1; | |
2947 | ret_val = hw->phy.ops.write_reg(hw, reg_slice, | |
2948 | IXGBE_MDIO_ZERO_DEV_TYPE, reg_phy_ext); | |
2949 | } | |
2950 | return ret_val; | |
2951 | } | |
2952 | ||
2953 | /** | |
2954 | * ixgbe_setup_ixfi_x550em_x - MAC specific iXFI configuration | |
2955 | * @hw: pointer to hardware structure | |
2956 | * | |
2957 | * iXfI configuration needed for ixgbe_mac_X550EM_x devices. | |
2958 | **/ | |
2959 | STATIC s32 ixgbe_setup_ixfi_x550em_x(struct ixgbe_hw *hw) | |
2960 | { | |
2961 | struct ixgbe_mac_info *mac = &hw->mac; | |
2962 | s32 status; | |
2963 | u32 reg_val; | |
2964 | ||
2965 | /* Disable training protocol FSM. */ | |
2966 | status = mac->ops.read_iosf_sb_reg(hw, | |
2967 | IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id), | |
2968 | IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); | |
2969 | if (status != IXGBE_SUCCESS) | |
2970 | return status; | |
2971 | reg_val |= IXGBE_KRM_RX_TRN_LINKUP_CTRL_CONV_WO_PROTOCOL; | |
2972 | status = mac->ops.write_iosf_sb_reg(hw, | |
2973 | IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id), | |
2974 | IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); | |
2975 | if (status != IXGBE_SUCCESS) | |
2976 | return status; | |
2977 | ||
2978 | /* Disable Flex from training TXFFE. */ | |
2979 | status = mac->ops.read_iosf_sb_reg(hw, | |
2980 | IXGBE_KRM_DSP_TXFFE_STATE_4(hw->bus.lan_id), | |
2981 | IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); | |
2982 | if (status != IXGBE_SUCCESS) | |
2983 | return status; | |
2984 | reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_C0_EN; | |
2985 | reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN; | |
2986 | reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CO_ADAPT_EN; | |
2987 | status = mac->ops.write_iosf_sb_reg(hw, | |
2988 | IXGBE_KRM_DSP_TXFFE_STATE_4(hw->bus.lan_id), | |
2989 | IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); | |
2990 | if (status != IXGBE_SUCCESS) | |
2991 | return status; | |
2992 | status = mac->ops.read_iosf_sb_reg(hw, | |
2993 | IXGBE_KRM_DSP_TXFFE_STATE_5(hw->bus.lan_id), | |
2994 | IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); | |
2995 | if (status != IXGBE_SUCCESS) | |
2996 | return status; | |
2997 | reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_C0_EN; | |
2998 | reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN; | |
2999 | reg_val &= ~IXGBE_KRM_DSP_TXFFE_STATE_CO_ADAPT_EN; | |
3000 | status = mac->ops.write_iosf_sb_reg(hw, | |
3001 | IXGBE_KRM_DSP_TXFFE_STATE_5(hw->bus.lan_id), | |
3002 | IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); | |
3003 | if (status != IXGBE_SUCCESS) | |
3004 | return status; | |
3005 | ||
3006 | /* Enable override for coefficients. */ | |
3007 | status = mac->ops.read_iosf_sb_reg(hw, | |
3008 | IXGBE_KRM_TX_COEFF_CTRL_1(hw->bus.lan_id), | |
3009 | IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); | |
3010 | if (status != IXGBE_SUCCESS) | |
3011 | return status; | |
3012 | reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_OVRRD_EN; | |
3013 | reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CZERO_EN; | |
3014 | reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CPLUS1_OVRRD_EN; | |
3015 | reg_val |= IXGBE_KRM_TX_COEFF_CTRL_1_CMINUS1_OVRRD_EN; | |
3016 | status = mac->ops.write_iosf_sb_reg(hw, | |
3017 | IXGBE_KRM_TX_COEFF_CTRL_1(hw->bus.lan_id), | |
3018 | IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); | |
3019 | return status; | |
3020 | } | |
3021 | ||
3022 | /** | |
3023 | * ixgbe_setup_ixfi_x550em - Configure the KR PHY for iXFI mode. | |
3024 | * @hw: pointer to hardware structure | |
3025 | * @speed: the link speed to force | |
3026 | * | |
3027 | * Configures the integrated KR PHY to use iXFI mode. Used to connect an | |
3028 | * internal and external PHY at a specific speed, without autonegotiation. | |
3029 | **/ | |
3030 | STATIC s32 ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed) | |
3031 | { | |
3032 | struct ixgbe_mac_info *mac = &hw->mac; | |
3033 | s32 status; | |
3034 | u32 reg_val; | |
3035 | ||
3036 | /* Disable AN and force speed to 10G Serial. */ | |
3037 | status = mac->ops.read_iosf_sb_reg(hw, | |
3038 | IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), | |
3039 | IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); | |
3040 | if (status != IXGBE_SUCCESS) | |
3041 | return status; | |
3042 | ||
3043 | reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; | |
3044 | reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK; | |
3045 | ||
3046 | /* Select forced link speed for internal PHY. */ | |
3047 | switch (*speed) { | |
3048 | case IXGBE_LINK_SPEED_10GB_FULL: | |
3049 | reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_10G; | |
3050 | break; | |
3051 | case IXGBE_LINK_SPEED_1GB_FULL: | |
3052 | reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G; | |
3053 | break; | |
3054 | default: | |
3055 | /* Other link speeds are not supported by internal KR PHY. */ | |
3056 | return IXGBE_ERR_LINK_SETUP; | |
3057 | } | |
3058 | ||
3059 | status = mac->ops.write_iosf_sb_reg(hw, | |
3060 | IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), | |
3061 | IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); | |
3062 | if (status != IXGBE_SUCCESS) | |
3063 | return status; | |
3064 | ||
3065 | /* Additional configuration needed for x550em_x */ | |
3066 | if (hw->mac.type == ixgbe_mac_X550EM_x) { | |
3067 | status = ixgbe_setup_ixfi_x550em_x(hw); | |
3068 | if (status != IXGBE_SUCCESS) | |
3069 | return status; | |
3070 | } | |
3071 | ||
3072 | /* Toggle port SW reset by AN reset. */ | |
3073 | status = ixgbe_restart_an_internal_phy_x550em(hw); | |
3074 | ||
3075 | return status; | |
3076 | } | |
3077 | ||
3078 | /** | |
3079 | * ixgbe_ext_phy_t_x550em_get_link - Get ext phy link status | |
3080 | * @hw: address of hardware structure | |
3081 | * @link_up: address of boolean to indicate link status | |
3082 | * | |
3083 | * Returns error code if unable to get link status. | |
3084 | */ | |
3085 | STATIC s32 ixgbe_ext_phy_t_x550em_get_link(struct ixgbe_hw *hw, bool *link_up) | |
3086 | { | |
3087 | u32 ret; | |
3088 | u16 autoneg_status; | |
3089 | ||
3090 | *link_up = false; | |
3091 | ||
3092 | /* read this twice back to back to indicate current status */ | |
3093 | ret = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS, | |
3094 | IXGBE_MDIO_AUTO_NEG_DEV_TYPE, | |
3095 | &autoneg_status); | |
3096 | if (ret != IXGBE_SUCCESS) | |
3097 | return ret; | |
3098 | ||
3099 | ret = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS, | |
3100 | IXGBE_MDIO_AUTO_NEG_DEV_TYPE, | |
3101 | &autoneg_status); | |
3102 | if (ret != IXGBE_SUCCESS) | |
3103 | return ret; | |
3104 | ||
3105 | *link_up = !!(autoneg_status & IXGBE_MDIO_AUTO_NEG_LINK_STATUS); | |
3106 | ||
3107 | return IXGBE_SUCCESS; | |
3108 | } | |
3109 | ||
3110 | /** | |
3111 | * ixgbe_setup_internal_phy_t_x550em - Configure KR PHY to X557 link | |
3112 | * @hw: point to hardware structure | |
3113 | * | |
3114 | * Configures the link between the integrated KR PHY and the external X557 PHY | |
3115 | * The driver will call this function when it gets a link status change | |
3116 | * interrupt from the X557 PHY. This function configures the link speed | |
3117 | * between the PHYs to match the link speed of the BASE-T link. | |
3118 | * | |
3119 | * A return of a non-zero value indicates an error, and the base driver should | |
3120 | * not report link up. | |
3121 | */ | |
3122 | s32 ixgbe_setup_internal_phy_t_x550em(struct ixgbe_hw *hw) | |
3123 | { | |
3124 | ixgbe_link_speed force_speed; | |
3125 | bool link_up; | |
3126 | u32 status; | |
3127 | u16 speed; | |
3128 | ||
3129 | if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_copper) | |
3130 | return IXGBE_ERR_CONFIG; | |
3131 | ||
3132 | if (!(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE)) { | |
3133 | /* If link is down, there is no setup necessary so return */ | |
3134 | status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up); | |
3135 | if (status != IXGBE_SUCCESS) | |
3136 | return status; | |
3137 | ||
3138 | if (!link_up) | |
3139 | return IXGBE_SUCCESS; | |
3140 | ||
3141 | status = hw->phy.ops.read_reg(hw, | |
3142 | IXGBE_MDIO_AUTO_NEG_VENDOR_STAT, | |
3143 | IXGBE_MDIO_AUTO_NEG_DEV_TYPE, | |
3144 | &speed); | |
3145 | if (status != IXGBE_SUCCESS) | |
3146 | return status; | |
3147 | ||
3148 | /* If link is still down - no setup is required so return */ | |
3149 | status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up); | |
3150 | if (status != IXGBE_SUCCESS) | |
3151 | return status; | |
3152 | if (!link_up) | |
3153 | return IXGBE_SUCCESS; | |
3154 | ||
3155 | /* clear everything but the speed and duplex bits */ | |
3156 | speed &= IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_MASK; | |
3157 | ||
3158 | switch (speed) { | |
3159 | case IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB_FULL: | |
3160 | force_speed = IXGBE_LINK_SPEED_10GB_FULL; | |
3161 | break; | |
3162 | case IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_1GB_FULL: | |
3163 | force_speed = IXGBE_LINK_SPEED_1GB_FULL; | |
3164 | break; | |
3165 | default: | |
3166 | /* Internal PHY does not support anything else */ | |
3167 | return IXGBE_ERR_INVALID_LINK_SETTINGS; | |
3168 | } | |
3169 | ||
3170 | return ixgbe_setup_ixfi_x550em(hw, &force_speed); | |
3171 | } else { | |
3172 | speed = IXGBE_LINK_SPEED_10GB_FULL | | |
3173 | IXGBE_LINK_SPEED_1GB_FULL; | |
3174 | return ixgbe_setup_kr_speed_x550em(hw, speed); | |
3175 | } | |
3176 | } | |
3177 | ||
3178 | /** | |
3179 | * ixgbe_setup_phy_loopback_x550em - Configure the KR PHY for loopback. | |
3180 | * @hw: pointer to hardware structure | |
3181 | * | |
3182 | * Configures the integrated KR PHY to use internal loopback mode. | |
3183 | **/ | |
3184 | s32 ixgbe_setup_phy_loopback_x550em(struct ixgbe_hw *hw) | |
3185 | { | |
3186 | s32 status; | |
3187 | u32 reg_val; | |
3188 | ||
3189 | /* Disable AN and force speed to 10G Serial. */ | |
3190 | status = hw->mac.ops.read_iosf_sb_reg(hw, | |
3191 | IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), | |
3192 | IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); | |
3193 | if (status != IXGBE_SUCCESS) | |
3194 | return status; | |
3195 | reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE; | |
3196 | reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK; | |
3197 | reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_10G; | |
3198 | status = hw->mac.ops.write_iosf_sb_reg(hw, | |
3199 | IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id), | |
3200 | IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); | |
3201 | if (status != IXGBE_SUCCESS) | |
3202 | return status; | |
3203 | ||
3204 | /* Set near-end loopback clocks. */ | |
3205 | status = hw->mac.ops.read_iosf_sb_reg(hw, | |
3206 | IXGBE_KRM_PORT_CAR_GEN_CTRL(hw->bus.lan_id), | |
3207 | IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); | |
3208 | if (status != IXGBE_SUCCESS) | |
3209 | return status; | |
3210 | reg_val |= IXGBE_KRM_PORT_CAR_GEN_CTRL_NELB_32B; | |
3211 | reg_val |= IXGBE_KRM_PORT_CAR_GEN_CTRL_NELB_KRPCS; | |
3212 | status = hw->mac.ops.write_iosf_sb_reg(hw, | |
3213 | IXGBE_KRM_PORT_CAR_GEN_CTRL(hw->bus.lan_id), | |
3214 | IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); | |
3215 | if (status != IXGBE_SUCCESS) | |
3216 | return status; | |
3217 | ||
3218 | /* Set loopback enable. */ | |
3219 | status = hw->mac.ops.read_iosf_sb_reg(hw, | |
3220 | IXGBE_KRM_PMD_DFX_BURNIN(hw->bus.lan_id), | |
3221 | IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); | |
3222 | if (status != IXGBE_SUCCESS) | |
3223 | return status; | |
3224 | reg_val |= IXGBE_KRM_PMD_DFX_BURNIN_TX_RX_KR_LB_MASK; | |
3225 | status = hw->mac.ops.write_iosf_sb_reg(hw, | |
3226 | IXGBE_KRM_PMD_DFX_BURNIN(hw->bus.lan_id), | |
3227 | IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); | |
3228 | if (status != IXGBE_SUCCESS) | |
3229 | return status; | |
3230 | ||
3231 | /* Training bypass. */ | |
3232 | status = hw->mac.ops.read_iosf_sb_reg(hw, | |
3233 | IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id), | |
3234 | IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); | |
3235 | if (status != IXGBE_SUCCESS) | |
3236 | return status; | |
3237 | reg_val |= IXGBE_KRM_RX_TRN_LINKUP_CTRL_PROTOCOL_BYPASS; | |
3238 | status = hw->mac.ops.write_iosf_sb_reg(hw, | |
3239 | IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id), | |
3240 | IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); | |
3241 | ||
3242 | return status; | |
3243 | } | |
3244 | ||
3245 | /** | |
3246 | * ixgbe_read_ee_hostif_X550 - Read EEPROM word using a host interface command | |
3247 | * assuming that the semaphore is already obtained. | |
3248 | * @hw: pointer to hardware structure | |
3249 | * @offset: offset of word in the EEPROM to read | |
3250 | * @data: word read from the EEPROM | |
3251 | * | |
3252 | * Reads a 16 bit word from the EEPROM using the hostif. | |
3253 | **/ | |
3254 | s32 ixgbe_read_ee_hostif_X550(struct ixgbe_hw *hw, u16 offset, u16 *data) | |
3255 | { | |
3256 | const u32 mask = IXGBE_GSSR_SW_MNG_SM | IXGBE_GSSR_EEP_SM; | |
3257 | struct ixgbe_hic_read_shadow_ram buffer; | |
3258 | s32 status; | |
3259 | ||
3260 | DEBUGFUNC("ixgbe_read_ee_hostif_X550"); | |
3261 | buffer.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD; | |
3262 | buffer.hdr.req.buf_lenh = 0; | |
3263 | buffer.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN; | |
3264 | buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM; | |
3265 | ||
3266 | /* convert offset from words to bytes */ | |
3267 | buffer.address = IXGBE_CPU_TO_BE32(offset * 2); | |
3268 | /* one word */ | |
3269 | buffer.length = IXGBE_CPU_TO_BE16(sizeof(u16)); | |
3270 | ||
3271 | status = hw->mac.ops.acquire_swfw_sync(hw, mask); | |
3272 | if (status) | |
3273 | return status; | |
3274 | ||
3275 | status = ixgbe_hic_unlocked(hw, (u32 *)&buffer, sizeof(buffer), | |
3276 | IXGBE_HI_COMMAND_TIMEOUT); | |
3277 | if (!status) { | |
3278 | *data = (u16)IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, | |
3279 | FW_NVM_DATA_OFFSET); | |
3280 | } | |
3281 | ||
3282 | hw->mac.ops.release_swfw_sync(hw, mask); | |
3283 | return status; | |
3284 | } | |
3285 | ||
3286 | /** | |
3287 | * ixgbe_read_ee_hostif_buffer_X550- Read EEPROM word(s) using hostif | |
3288 | * @hw: pointer to hardware structure | |
3289 | * @offset: offset of word in the EEPROM to read | |
3290 | * @words: number of words | |
3291 | * @data: word(s) read from the EEPROM | |
3292 | * | |
3293 | * Reads a 16 bit word(s) from the EEPROM using the hostif. | |
3294 | **/ | |
3295 | s32 ixgbe_read_ee_hostif_buffer_X550(struct ixgbe_hw *hw, | |
3296 | u16 offset, u16 words, u16 *data) | |
3297 | { | |
3298 | const u32 mask = IXGBE_GSSR_SW_MNG_SM | IXGBE_GSSR_EEP_SM; | |
3299 | struct ixgbe_hic_read_shadow_ram buffer; | |
3300 | u32 current_word = 0; | |
3301 | u16 words_to_read; | |
3302 | s32 status; | |
3303 | u32 i; | |
3304 | ||
3305 | DEBUGFUNC("ixgbe_read_ee_hostif_buffer_X550"); | |
3306 | ||
3307 | /* Take semaphore for the entire operation. */ | |
3308 | status = hw->mac.ops.acquire_swfw_sync(hw, mask); | |
3309 | if (status) { | |
3310 | DEBUGOUT("EEPROM read buffer - semaphore failed\n"); | |
3311 | return status; | |
3312 | } | |
3313 | ||
3314 | while (words) { | |
3315 | if (words > FW_MAX_READ_BUFFER_SIZE / 2) | |
3316 | words_to_read = FW_MAX_READ_BUFFER_SIZE / 2; | |
3317 | else | |
3318 | words_to_read = words; | |
3319 | ||
3320 | buffer.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD; | |
3321 | buffer.hdr.req.buf_lenh = 0; | |
3322 | buffer.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN; | |
3323 | buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM; | |
3324 | ||
3325 | /* convert offset from words to bytes */ | |
3326 | buffer.address = IXGBE_CPU_TO_BE32((offset + current_word) * 2); | |
3327 | buffer.length = IXGBE_CPU_TO_BE16(words_to_read * 2); | |
3328 | ||
3329 | status = ixgbe_hic_unlocked(hw, (u32 *)&buffer, sizeof(buffer), | |
3330 | IXGBE_HI_COMMAND_TIMEOUT); | |
3331 | ||
3332 | if (status) { | |
3333 | DEBUGOUT("Host interface command failed\n"); | |
3334 | goto out; | |
3335 | } | |
3336 | ||
3337 | for (i = 0; i < words_to_read; i++) { | |
3338 | u32 reg = IXGBE_FLEX_MNG + (FW_NVM_DATA_OFFSET << 2) + | |
3339 | 2 * i; | |
3340 | u32 value = IXGBE_READ_REG(hw, reg); | |
3341 | ||
3342 | data[current_word] = (u16)(value & 0xffff); | |
3343 | current_word++; | |
3344 | i++; | |
3345 | if (i < words_to_read) { | |
3346 | value >>= 16; | |
3347 | data[current_word] = (u16)(value & 0xffff); | |
3348 | current_word++; | |
3349 | } | |
3350 | } | |
3351 | words -= words_to_read; | |
3352 | } | |
3353 | ||
3354 | out: | |
3355 | hw->mac.ops.release_swfw_sync(hw, mask); | |
3356 | return status; | |
3357 | } | |
3358 | ||
3359 | /** | |
3360 | * ixgbe_write_ee_hostif_X550 - Write EEPROM word using hostif | |
3361 | * @hw: pointer to hardware structure | |
3362 | * @offset: offset of word in the EEPROM to write | |
3363 | * @data: word write to the EEPROM | |
3364 | * | |
3365 | * Write a 16 bit word to the EEPROM using the hostif. | |
3366 | **/ | |
3367 | s32 ixgbe_write_ee_hostif_data_X550(struct ixgbe_hw *hw, u16 offset, | |
3368 | u16 data) | |
3369 | { | |
3370 | s32 status; | |
3371 | struct ixgbe_hic_write_shadow_ram buffer; | |
3372 | ||
3373 | DEBUGFUNC("ixgbe_write_ee_hostif_data_X550"); | |
3374 | ||
3375 | buffer.hdr.req.cmd = FW_WRITE_SHADOW_RAM_CMD; | |
3376 | buffer.hdr.req.buf_lenh = 0; | |
3377 | buffer.hdr.req.buf_lenl = FW_WRITE_SHADOW_RAM_LEN; | |
3378 | buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM; | |
3379 | ||
3380 | /* one word */ | |
3381 | buffer.length = IXGBE_CPU_TO_BE16(sizeof(u16)); | |
3382 | buffer.data = data; | |
3383 | buffer.address = IXGBE_CPU_TO_BE32(offset * 2); | |
3384 | ||
3385 | status = ixgbe_host_interface_command(hw, (u32 *)&buffer, | |
3386 | sizeof(buffer), | |
3387 | IXGBE_HI_COMMAND_TIMEOUT, false); | |
3388 | ||
3389 | return status; | |
3390 | } | |
3391 | ||
3392 | /** | |
3393 | * ixgbe_write_ee_hostif_X550 - Write EEPROM word using hostif | |
3394 | * @hw: pointer to hardware structure | |
3395 | * @offset: offset of word in the EEPROM to write | |
3396 | * @data: word write to the EEPROM | |
3397 | * | |
3398 | * Write a 16 bit word to the EEPROM using the hostif. | |
3399 | **/ | |
3400 | s32 ixgbe_write_ee_hostif_X550(struct ixgbe_hw *hw, u16 offset, | |
3401 | u16 data) | |
3402 | { | |
3403 | s32 status = IXGBE_SUCCESS; | |
3404 | ||
3405 | DEBUGFUNC("ixgbe_write_ee_hostif_X550"); | |
3406 | ||
3407 | if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == | |
3408 | IXGBE_SUCCESS) { | |
3409 | status = ixgbe_write_ee_hostif_data_X550(hw, offset, data); | |
3410 | hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); | |
3411 | } else { | |
3412 | DEBUGOUT("write ee hostif failed to get semaphore"); | |
3413 | status = IXGBE_ERR_SWFW_SYNC; | |
3414 | } | |
3415 | ||
3416 | return status; | |
3417 | } | |
3418 | ||
3419 | /** | |
3420 | * ixgbe_write_ee_hostif_buffer_X550 - Write EEPROM word(s) using hostif | |
3421 | * @hw: pointer to hardware structure | |
3422 | * @offset: offset of word in the EEPROM to write | |
3423 | * @words: number of words | |
3424 | * @data: word(s) write to the EEPROM | |
3425 | * | |
3426 | * Write a 16 bit word(s) to the EEPROM using the hostif. | |
3427 | **/ | |
3428 | s32 ixgbe_write_ee_hostif_buffer_X550(struct ixgbe_hw *hw, | |
3429 | u16 offset, u16 words, u16 *data) | |
3430 | { | |
3431 | s32 status = IXGBE_SUCCESS; | |
3432 | u32 i = 0; | |
3433 | ||
3434 | DEBUGFUNC("ixgbe_write_ee_hostif_buffer_X550"); | |
3435 | ||
3436 | /* Take semaphore for the entire operation. */ | |
3437 | status = hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM); | |
3438 | if (status != IXGBE_SUCCESS) { | |
3439 | DEBUGOUT("EEPROM write buffer - semaphore failed\n"); | |
3440 | goto out; | |
3441 | } | |
3442 | ||
3443 | for (i = 0; i < words; i++) { | |
3444 | status = ixgbe_write_ee_hostif_data_X550(hw, offset + i, | |
3445 | data[i]); | |
3446 | ||
3447 | if (status != IXGBE_SUCCESS) { | |
3448 | DEBUGOUT("Eeprom buffered write failed\n"); | |
3449 | break; | |
3450 | } | |
3451 | } | |
3452 | ||
3453 | hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM); | |
3454 | out: | |
3455 | ||
3456 | return status; | |
3457 | } | |
3458 | ||
3459 | /** | |
3460 | * ixgbe_checksum_ptr_x550 - Checksum one pointer region | |
3461 | * @hw: pointer to hardware structure | |
3462 | * @ptr: pointer offset in eeprom | |
3463 | * @size: size of section pointed by ptr, if 0 first word will be used as size | |
3464 | * @csum: address of checksum to update | |
3465 | * | |
3466 | * Returns error status for any failure | |
3467 | */ | |
3468 | STATIC s32 ixgbe_checksum_ptr_x550(struct ixgbe_hw *hw, u16 ptr, | |
3469 | u16 size, u16 *csum, u16 *buffer, | |
3470 | u32 buffer_size) | |
3471 | { | |
3472 | u16 buf[256]; | |
3473 | s32 status; | |
3474 | u16 length, bufsz, i, start; | |
3475 | u16 *local_buffer; | |
3476 | ||
3477 | bufsz = sizeof(buf) / sizeof(buf[0]); | |
3478 | ||
3479 | /* Read a chunk at the pointer location */ | |
3480 | if (!buffer) { | |
3481 | status = ixgbe_read_ee_hostif_buffer_X550(hw, ptr, bufsz, buf); | |
3482 | if (status) { | |
3483 | DEBUGOUT("Failed to read EEPROM image\n"); | |
3484 | return status; | |
3485 | } | |
3486 | local_buffer = buf; | |
3487 | } else { | |
3488 | if (buffer_size < ptr) | |
3489 | return IXGBE_ERR_PARAM; | |
3490 | local_buffer = &buffer[ptr]; | |
3491 | } | |
3492 | ||
3493 | if (size) { | |
3494 | start = 0; | |
3495 | length = size; | |
3496 | } else { | |
3497 | start = 1; | |
3498 | length = local_buffer[0]; | |
3499 | ||
3500 | /* Skip pointer section if length is invalid. */ | |
3501 | if (length == 0xFFFF || length == 0 || | |
3502 | (ptr + length) >= hw->eeprom.word_size) | |
3503 | return IXGBE_SUCCESS; | |
3504 | } | |
3505 | ||
3506 | if (buffer && ((u32)start + (u32)length > buffer_size)) | |
3507 | return IXGBE_ERR_PARAM; | |
3508 | ||
3509 | for (i = start; length; i++, length--) { | |
3510 | if (i == bufsz && !buffer) { | |
3511 | ptr += bufsz; | |
3512 | i = 0; | |
3513 | if (length < bufsz) | |
3514 | bufsz = length; | |
3515 | ||
3516 | /* Read a chunk at the pointer location */ | |
3517 | status = ixgbe_read_ee_hostif_buffer_X550(hw, ptr, | |
3518 | bufsz, buf); | |
3519 | if (status) { | |
3520 | DEBUGOUT("Failed to read EEPROM image\n"); | |
3521 | return status; | |
3522 | } | |
3523 | } | |
3524 | *csum += local_buffer[i]; | |
3525 | } | |
3526 | return IXGBE_SUCCESS; | |
3527 | } | |
3528 | ||
3529 | /** | |
3530 | * ixgbe_calc_checksum_X550 - Calculates and returns the checksum | |
3531 | * @hw: pointer to hardware structure | |
3532 | * @buffer: pointer to buffer containing calculated checksum | |
3533 | * @buffer_size: size of buffer | |
3534 | * | |
3535 | * Returns a negative error code on error, or the 16-bit checksum | |
3536 | **/ | |
3537 | s32 ixgbe_calc_checksum_X550(struct ixgbe_hw *hw, u16 *buffer, u32 buffer_size) | |
3538 | { | |
3539 | u16 eeprom_ptrs[IXGBE_EEPROM_LAST_WORD + 1]; | |
3540 | u16 *local_buffer; | |
3541 | s32 status; | |
3542 | u16 checksum = 0; | |
3543 | u16 pointer, i, size; | |
3544 | ||
3545 | DEBUGFUNC("ixgbe_calc_eeprom_checksum_X550"); | |
3546 | ||
3547 | hw->eeprom.ops.init_params(hw); | |
3548 | ||
3549 | if (!buffer) { | |
3550 | /* Read pointer area */ | |
3551 | status = ixgbe_read_ee_hostif_buffer_X550(hw, 0, | |
3552 | IXGBE_EEPROM_LAST_WORD + 1, | |
3553 | eeprom_ptrs); | |
3554 | if (status) { | |
3555 | DEBUGOUT("Failed to read EEPROM image\n"); | |
3556 | return status; | |
3557 | } | |
3558 | local_buffer = eeprom_ptrs; | |
3559 | } else { | |
3560 | if (buffer_size < IXGBE_EEPROM_LAST_WORD) | |
3561 | return IXGBE_ERR_PARAM; | |
3562 | local_buffer = buffer; | |
3563 | } | |
3564 | ||
3565 | /* | |
3566 | * For X550 hardware include 0x0-0x41 in the checksum, skip the | |
3567 | * checksum word itself | |
3568 | */ | |
3569 | for (i = 0; i <= IXGBE_EEPROM_LAST_WORD; i++) | |
3570 | if (i != IXGBE_EEPROM_CHECKSUM) | |
3571 | checksum += local_buffer[i]; | |
3572 | ||
3573 | /* | |
3574 | * Include all data from pointers 0x3, 0x6-0xE. This excludes the | |
3575 | * FW, PHY module, and PCIe Expansion/Option ROM pointers. | |
3576 | */ | |
3577 | for (i = IXGBE_PCIE_ANALOG_PTR_X550; i < IXGBE_FW_PTR; i++) { | |
3578 | if (i == IXGBE_PHY_PTR || i == IXGBE_OPTION_ROM_PTR) | |
3579 | continue; | |
3580 | ||
3581 | pointer = local_buffer[i]; | |
3582 | ||
3583 | /* Skip pointer section if the pointer is invalid. */ | |
3584 | if (pointer == 0xFFFF || pointer == 0 || | |
3585 | pointer >= hw->eeprom.word_size) | |
3586 | continue; | |
3587 | ||
3588 | switch (i) { | |
3589 | case IXGBE_PCIE_GENERAL_PTR: | |
3590 | size = IXGBE_IXGBE_PCIE_GENERAL_SIZE; | |
3591 | break; | |
3592 | case IXGBE_PCIE_CONFIG0_PTR: | |
3593 | case IXGBE_PCIE_CONFIG1_PTR: | |
3594 | size = IXGBE_PCIE_CONFIG_SIZE; | |
3595 | break; | |
3596 | default: | |
3597 | size = 0; | |
3598 | break; | |
3599 | } | |
3600 | ||
3601 | status = ixgbe_checksum_ptr_x550(hw, pointer, size, &checksum, | |
3602 | buffer, buffer_size); | |
3603 | if (status) | |
3604 | return status; | |
3605 | } | |
3606 | ||
3607 | checksum = (u16)IXGBE_EEPROM_SUM - checksum; | |
3608 | ||
3609 | return (s32)checksum; | |
3610 | } | |
3611 | ||
3612 | /** | |
3613 | * ixgbe_calc_eeprom_checksum_X550 - Calculates and returns the checksum | |
3614 | * @hw: pointer to hardware structure | |
3615 | * | |
3616 | * Returns a negative error code on error, or the 16-bit checksum | |
3617 | **/ | |
3618 | s32 ixgbe_calc_eeprom_checksum_X550(struct ixgbe_hw *hw) | |
3619 | { | |
3620 | return ixgbe_calc_checksum_X550(hw, NULL, 0); | |
3621 | } | |
3622 | ||
3623 | /** | |
3624 | * ixgbe_validate_eeprom_checksum_X550 - Validate EEPROM checksum | |
3625 | * @hw: pointer to hardware structure | |
3626 | * @checksum_val: calculated checksum | |
3627 | * | |
3628 | * Performs checksum calculation and validates the EEPROM checksum. If the | |
3629 | * caller does not need checksum_val, the value can be NULL. | |
3630 | **/ | |
3631 | s32 ixgbe_validate_eeprom_checksum_X550(struct ixgbe_hw *hw, u16 *checksum_val) | |
3632 | { | |
3633 | s32 status; | |
3634 | u16 checksum; | |
3635 | u16 read_checksum = 0; | |
3636 | ||
3637 | DEBUGFUNC("ixgbe_validate_eeprom_checksum_X550"); | |
3638 | ||
3639 | /* Read the first word from the EEPROM. If this times out or fails, do | |
3640 | * not continue or we could be in for a very long wait while every | |
3641 | * EEPROM read fails | |
3642 | */ | |
3643 | status = hw->eeprom.ops.read(hw, 0, &checksum); | |
3644 | if (status) { | |
3645 | DEBUGOUT("EEPROM read failed\n"); | |
3646 | return status; | |
3647 | } | |
3648 | ||
3649 | status = hw->eeprom.ops.calc_checksum(hw); | |
3650 | if (status < 0) | |
3651 | return status; | |
3652 | ||
3653 | checksum = (u16)(status & 0xffff); | |
3654 | ||
3655 | status = ixgbe_read_ee_hostif_X550(hw, IXGBE_EEPROM_CHECKSUM, | |
3656 | &read_checksum); | |
3657 | if (status) | |
3658 | return status; | |
3659 | ||
3660 | /* Verify read checksum from EEPROM is the same as | |
3661 | * calculated checksum | |
3662 | */ | |
3663 | if (read_checksum != checksum) { | |
3664 | status = IXGBE_ERR_EEPROM_CHECKSUM; | |
3665 | ERROR_REPORT1(IXGBE_ERROR_INVALID_STATE, | |
3666 | "Invalid EEPROM checksum"); | |
3667 | } | |
3668 | ||
3669 | /* If the user cares, return the calculated checksum */ | |
3670 | if (checksum_val) | |
3671 | *checksum_val = checksum; | |
3672 | ||
3673 | return status; | |
3674 | } | |
3675 | ||
3676 | /** | |
3677 | * ixgbe_update_eeprom_checksum_X550 - Updates the EEPROM checksum and flash | |
3678 | * @hw: pointer to hardware structure | |
3679 | * | |
3680 | * After writing EEPROM to shadow RAM using EEWR register, software calculates | |
3681 | * checksum and updates the EEPROM and instructs the hardware to update | |
3682 | * the flash. | |
3683 | **/ | |
3684 | s32 ixgbe_update_eeprom_checksum_X550(struct ixgbe_hw *hw) | |
3685 | { | |
3686 | s32 status; | |
3687 | u16 checksum = 0; | |
3688 | ||
3689 | DEBUGFUNC("ixgbe_update_eeprom_checksum_X550"); | |
3690 | ||
3691 | /* Read the first word from the EEPROM. If this times out or fails, do | |
3692 | * not continue or we could be in for a very long wait while every | |
3693 | * EEPROM read fails | |
3694 | */ | |
3695 | status = ixgbe_read_ee_hostif_X550(hw, 0, &checksum); | |
3696 | if (status) { | |
3697 | DEBUGOUT("EEPROM read failed\n"); | |
3698 | return status; | |
3699 | } | |
3700 | ||
3701 | status = ixgbe_calc_eeprom_checksum_X550(hw); | |
3702 | if (status < 0) | |
3703 | return status; | |
3704 | ||
3705 | checksum = (u16)(status & 0xffff); | |
3706 | ||
3707 | status = ixgbe_write_ee_hostif_X550(hw, IXGBE_EEPROM_CHECKSUM, | |
3708 | checksum); | |
3709 | if (status) | |
3710 | return status; | |
3711 | ||
3712 | status = ixgbe_update_flash_X550(hw); | |
3713 | ||
3714 | return status; | |
3715 | } | |
3716 | ||
3717 | /** | |
3718 | * ixgbe_update_flash_X550 - Instruct HW to copy EEPROM to Flash device | |
3719 | * @hw: pointer to hardware structure | |
3720 | * | |
3721 | * Issue a shadow RAM dump to FW to copy EEPROM from shadow RAM to the flash. | |
3722 | **/ | |
3723 | s32 ixgbe_update_flash_X550(struct ixgbe_hw *hw) | |
3724 | { | |
3725 | s32 status = IXGBE_SUCCESS; | |
3726 | union ixgbe_hic_hdr2 buffer; | |
3727 | ||
3728 | DEBUGFUNC("ixgbe_update_flash_X550"); | |
3729 | ||
3730 | buffer.req.cmd = FW_SHADOW_RAM_DUMP_CMD; | |
3731 | buffer.req.buf_lenh = 0; | |
3732 | buffer.req.buf_lenl = FW_SHADOW_RAM_DUMP_LEN; | |
3733 | buffer.req.checksum = FW_DEFAULT_CHECKSUM; | |
3734 | ||
3735 | status = ixgbe_host_interface_command(hw, (u32 *)&buffer, | |
3736 | sizeof(buffer), | |
3737 | IXGBE_HI_COMMAND_TIMEOUT, false); | |
3738 | ||
3739 | return status; | |
3740 | } | |
3741 | ||
3742 | /** | |
3743 | * ixgbe_get_supported_physical_layer_X550em - Returns physical layer type | |
3744 | * @hw: pointer to hardware structure | |
3745 | * | |
3746 | * Determines physical layer capabilities of the current configuration. | |
3747 | **/ | |
3748 | u32 ixgbe_get_supported_physical_layer_X550em(struct ixgbe_hw *hw) | |
3749 | { | |
3750 | u32 physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN; | |
3751 | u16 ext_ability = 0; | |
3752 | ||
3753 | DEBUGFUNC("ixgbe_get_supported_physical_layer_X550em"); | |
3754 | ||
3755 | hw->phy.ops.identify(hw); | |
3756 | ||
3757 | switch (hw->phy.type) { | |
3758 | case ixgbe_phy_x550em_kr: | |
3759 | physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_KR | | |
3760 | IXGBE_PHYSICAL_LAYER_1000BASE_KX; | |
3761 | break; | |
3762 | case ixgbe_phy_x550em_kx4: | |
3763 | physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_KX4 | | |
3764 | IXGBE_PHYSICAL_LAYER_1000BASE_KX; | |
3765 | break; | |
3766 | case ixgbe_phy_x550em_ext_t: | |
3767 | hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_EXT_ABILITY, | |
3768 | IXGBE_MDIO_PMA_PMD_DEV_TYPE, | |
3769 | &ext_ability); | |
3770 | if (ext_ability & IXGBE_MDIO_PHY_10GBASET_ABILITY) | |
3771 | physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_T; | |
3772 | if (ext_ability & IXGBE_MDIO_PHY_1000BASET_ABILITY) | |
3773 | physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_T; | |
3774 | break; | |
3775 | default: | |
3776 | break; | |
3777 | } | |
3778 | ||
3779 | if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber) | |
3780 | physical_layer = ixgbe_get_supported_phy_sfp_layer_generic(hw); | |
3781 | ||
3782 | return physical_layer; | |
3783 | } | |
3784 | ||
3785 | /** | |
3786 | * ixgbe_get_bus_info_x550em - Set PCI bus info | |
3787 | * @hw: pointer to hardware structure | |
3788 | * | |
3789 | * Sets bus link width and speed to unknown because X550em is | |
3790 | * not a PCI device. | |
3791 | **/ | |
3792 | s32 ixgbe_get_bus_info_X550em(struct ixgbe_hw *hw) | |
3793 | { | |
3794 | ||
3795 | DEBUGFUNC("ixgbe_get_bus_info_x550em"); | |
3796 | ||
3797 | hw->bus.width = ixgbe_bus_width_unknown; | |
3798 | hw->bus.speed = ixgbe_bus_speed_unknown; | |
3799 | ||
3800 | hw->mac.ops.set_lan_id(hw); | |
3801 | ||
3802 | return IXGBE_SUCCESS; | |
3803 | } | |
3804 | ||
3805 | /** | |
3806 | * ixgbe_disable_rx_x550 - Disable RX unit | |
3807 | * | |
3808 | * Enables the Rx DMA unit for x550 | |
3809 | **/ | |
3810 | void ixgbe_disable_rx_x550(struct ixgbe_hw *hw) | |
3811 | { | |
3812 | u32 rxctrl, pfdtxgswc; | |
3813 | s32 status; | |
3814 | struct ixgbe_hic_disable_rxen fw_cmd; | |
3815 | ||
3816 | DEBUGFUNC("ixgbe_enable_rx_dma_x550"); | |
3817 | ||
3818 | rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); | |
3819 | if (rxctrl & IXGBE_RXCTRL_RXEN) { | |
3820 | pfdtxgswc = IXGBE_READ_REG(hw, IXGBE_PFDTXGSWC); | |
3821 | if (pfdtxgswc & IXGBE_PFDTXGSWC_VT_LBEN) { | |
3822 | pfdtxgswc &= ~IXGBE_PFDTXGSWC_VT_LBEN; | |
3823 | IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, pfdtxgswc); | |
3824 | hw->mac.set_lben = true; | |
3825 | } else { | |
3826 | hw->mac.set_lben = false; | |
3827 | } | |
3828 | ||
3829 | fw_cmd.hdr.cmd = FW_DISABLE_RXEN_CMD; | |
3830 | fw_cmd.hdr.buf_len = FW_DISABLE_RXEN_LEN; | |
3831 | fw_cmd.hdr.checksum = FW_DEFAULT_CHECKSUM; | |
3832 | fw_cmd.port_number = (u8)hw->bus.lan_id; | |
3833 | ||
3834 | status = ixgbe_host_interface_command(hw, (u32 *)&fw_cmd, | |
3835 | sizeof(struct ixgbe_hic_disable_rxen), | |
3836 | IXGBE_HI_COMMAND_TIMEOUT, true); | |
3837 | ||
3838 | /* If we fail - disable RX using register write */ | |
3839 | if (status) { | |
3840 | rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); | |
3841 | if (rxctrl & IXGBE_RXCTRL_RXEN) { | |
3842 | rxctrl &= ~IXGBE_RXCTRL_RXEN; | |
3843 | IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl); | |
3844 | } | |
3845 | } | |
3846 | } | |
3847 | } | |
3848 | ||
3849 | /** | |
3850 | * ixgbe_enter_lplu_x550em - Transition to low power states | |
3851 | * @hw: pointer to hardware structure | |
3852 | * | |
3853 | * Configures Low Power Link Up on transition to low power states | |
3854 | * (from D0 to non-D0). Link is required to enter LPLU so avoid resetting the | |
3855 | * X557 PHY immediately prior to entering LPLU. | |
3856 | **/ | |
3857 | s32 ixgbe_enter_lplu_t_x550em(struct ixgbe_hw *hw) | |
3858 | { | |
3859 | u16 an_10g_cntl_reg, autoneg_reg, speed; | |
3860 | s32 status; | |
3861 | ixgbe_link_speed lcd_speed; | |
3862 | u32 save_autoneg; | |
3863 | bool link_up; | |
3864 | ||
3865 | /* SW LPLU not required on later HW revisions. */ | |
3866 | if ((hw->mac.type == ixgbe_mac_X550EM_x) && | |
3867 | (IXGBE_FUSES0_REV_MASK & | |
3868 | IXGBE_READ_REG(hw, IXGBE_FUSES0_GROUP(0)))) | |
3869 | return IXGBE_SUCCESS; | |
3870 | ||
3871 | /* If blocked by MNG FW, then don't restart AN */ | |
3872 | if (ixgbe_check_reset_blocked(hw)) | |
3873 | return IXGBE_SUCCESS; | |
3874 | ||
3875 | status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up); | |
3876 | if (status != IXGBE_SUCCESS) | |
3877 | return status; | |
3878 | ||
3879 | status = ixgbe_read_eeprom(hw, NVM_INIT_CTRL_3, &hw->eeprom.ctrl_word_3); | |
3880 | ||
3881 | if (status != IXGBE_SUCCESS) | |
3882 | return status; | |
3883 | ||
3884 | /* If link is down, LPLU disabled in NVM, WoL disabled, or manageability | |
3885 | * disabled, then force link down by entering low power mode. | |
3886 | */ | |
3887 | if (!link_up || !(hw->eeprom.ctrl_word_3 & NVM_INIT_CTRL_3_LPLU) || | |
3888 | !(hw->wol_enabled || ixgbe_mng_present(hw))) | |
3889 | return ixgbe_set_copper_phy_power(hw, FALSE); | |
3890 | ||
3891 | /* Determine LCD */ | |
3892 | status = ixgbe_get_lcd_t_x550em(hw, &lcd_speed); | |
3893 | ||
3894 | if (status != IXGBE_SUCCESS) | |
3895 | return status; | |
3896 | ||
3897 | /* If no valid LCD link speed, then force link down and exit. */ | |
3898 | if (lcd_speed == IXGBE_LINK_SPEED_UNKNOWN) | |
3899 | return ixgbe_set_copper_phy_power(hw, FALSE); | |
3900 | ||
3901 | status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_STAT, | |
3902 | IXGBE_MDIO_AUTO_NEG_DEV_TYPE, | |
3903 | &speed); | |
3904 | ||
3905 | if (status != IXGBE_SUCCESS) | |
3906 | return status; | |
3907 | ||
3908 | /* If no link now, speed is invalid so take link down */ | |
3909 | status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up); | |
3910 | if (status != IXGBE_SUCCESS) | |
3911 | return ixgbe_set_copper_phy_power(hw, false); | |
3912 | ||
3913 | /* clear everything but the speed bits */ | |
3914 | speed &= IXGBE_MDIO_AUTO_NEG_VEN_STAT_SPEED_MASK; | |
3915 | ||
3916 | /* If current speed is already LCD, then exit. */ | |
3917 | if (((speed == IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_1GB) && | |
3918 | (lcd_speed == IXGBE_LINK_SPEED_1GB_FULL)) || | |
3919 | ((speed == IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB) && | |
3920 | (lcd_speed == IXGBE_LINK_SPEED_10GB_FULL))) | |
3921 | return status; | |
3922 | ||
3923 | /* Clear AN completed indication */ | |
3924 | status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM, | |
3925 | IXGBE_MDIO_AUTO_NEG_DEV_TYPE, | |
3926 | &autoneg_reg); | |
3927 | ||
3928 | if (status != IXGBE_SUCCESS) | |
3929 | return status; | |
3930 | ||
3931 | status = hw->phy.ops.read_reg(hw, IXGBE_MII_10GBASE_T_AUTONEG_CTRL_REG, | |
3932 | IXGBE_MDIO_AUTO_NEG_DEV_TYPE, | |
3933 | &an_10g_cntl_reg); | |
3934 | ||
3935 | if (status != IXGBE_SUCCESS) | |
3936 | return status; | |
3937 | ||
3938 | status = hw->phy.ops.read_reg(hw, | |
3939 | IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG, | |
3940 | IXGBE_MDIO_AUTO_NEG_DEV_TYPE, | |
3941 | &autoneg_reg); | |
3942 | ||
3943 | if (status != IXGBE_SUCCESS) | |
3944 | return status; | |
3945 | ||
3946 | save_autoneg = hw->phy.autoneg_advertised; | |
3947 | ||
3948 | /* Setup link at least common link speed */ | |
3949 | status = hw->mac.ops.setup_link(hw, lcd_speed, false); | |
3950 | ||
3951 | /* restore autoneg from before setting lplu speed */ | |
3952 | hw->phy.autoneg_advertised = save_autoneg; | |
3953 | ||
3954 | return status; | |
3955 | } | |
3956 | ||
3957 | /** | |
3958 | * ixgbe_get_lcd_x550em - Determine lowest common denominator | |
3959 | * @hw: pointer to hardware structure | |
3960 | * @lcd_speed: pointer to lowest common link speed | |
3961 | * | |
3962 | * Determine lowest common link speed with link partner. | |
3963 | **/ | |
3964 | s32 ixgbe_get_lcd_t_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *lcd_speed) | |
3965 | { | |
3966 | u16 an_lp_status; | |
3967 | s32 status; | |
3968 | u16 word = hw->eeprom.ctrl_word_3; | |
3969 | ||
3970 | *lcd_speed = IXGBE_LINK_SPEED_UNKNOWN; | |
3971 | ||
3972 | status = hw->phy.ops.read_reg(hw, IXGBE_AUTO_NEG_LP_STATUS, | |
3973 | IXGBE_MDIO_AUTO_NEG_DEV_TYPE, | |
3974 | &an_lp_status); | |
3975 | ||
3976 | if (status != IXGBE_SUCCESS) | |
3977 | return status; | |
3978 | ||
3979 | /* If link partner advertised 1G, return 1G */ | |
3980 | if (an_lp_status & IXGBE_AUTO_NEG_LP_1000BASE_CAP) { | |
3981 | *lcd_speed = IXGBE_LINK_SPEED_1GB_FULL; | |
3982 | return status; | |
3983 | } | |
3984 | ||
3985 | /* If 10G disabled for LPLU via NVM D10GMP, then return no valid LCD */ | |
3986 | if ((hw->bus.lan_id && (word & NVM_INIT_CTRL_3_D10GMP_PORT1)) || | |
3987 | (word & NVM_INIT_CTRL_3_D10GMP_PORT0)) | |
3988 | return status; | |
3989 | ||
3990 | /* Link partner not capable of lower speeds, return 10G */ | |
3991 | *lcd_speed = IXGBE_LINK_SPEED_10GB_FULL; | |
3992 | return status; | |
3993 | } | |
3994 | ||
3995 | /** | |
3996 | * ixgbe_setup_fc_X550em - Set up flow control | |
3997 | * @hw: pointer to hardware structure | |
3998 | * | |
3999 | * Called at init time to set up flow control. | |
4000 | **/ | |
4001 | s32 ixgbe_setup_fc_X550em(struct ixgbe_hw *hw) | |
4002 | { | |
4003 | s32 ret_val = IXGBE_SUCCESS; | |
4004 | u32 pause, asm_dir, reg_val; | |
4005 | ||
4006 | DEBUGFUNC("ixgbe_setup_fc_X550em"); | |
4007 | ||
4008 | /* Validate the requested mode */ | |
4009 | if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) { | |
4010 | ERROR_REPORT1(IXGBE_ERROR_UNSUPPORTED, | |
4011 | "ixgbe_fc_rx_pause not valid in strict IEEE mode\n"); | |
4012 | ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS; | |
4013 | goto out; | |
4014 | } | |
4015 | ||
4016 | /* 10gig parts do not have a word in the EEPROM to determine the | |
4017 | * default flow control setting, so we explicitly set it to full. | |
4018 | */ | |
4019 | if (hw->fc.requested_mode == ixgbe_fc_default) | |
4020 | hw->fc.requested_mode = ixgbe_fc_full; | |
4021 | ||
4022 | /* Determine PAUSE and ASM_DIR bits. */ | |
4023 | switch (hw->fc.requested_mode) { | |
4024 | case ixgbe_fc_none: | |
4025 | pause = 0; | |
4026 | asm_dir = 0; | |
4027 | break; | |
4028 | case ixgbe_fc_tx_pause: | |
4029 | pause = 0; | |
4030 | asm_dir = 1; | |
4031 | break; | |
4032 | case ixgbe_fc_rx_pause: | |
4033 | /* Rx Flow control is enabled and Tx Flow control is | |
4034 | * disabled by software override. Since there really | |
4035 | * isn't a way to advertise that we are capable of RX | |
4036 | * Pause ONLY, we will advertise that we support both | |
4037 | * symmetric and asymmetric Rx PAUSE, as such we fall | |
4038 | * through to the fc_full statement. Later, we will | |
4039 | * disable the adapter's ability to send PAUSE frames. | |
4040 | */ | |
4041 | case ixgbe_fc_full: | |
4042 | pause = 1; | |
4043 | asm_dir = 1; | |
4044 | break; | |
4045 | default: | |
4046 | ERROR_REPORT1(IXGBE_ERROR_ARGUMENT, | |
4047 | "Flow control param set incorrectly\n"); | |
4048 | ret_val = IXGBE_ERR_CONFIG; | |
4049 | goto out; | |
4050 | } | |
4051 | ||
4052 | switch (hw->device_id) { | |
4053 | case IXGBE_DEV_ID_X550EM_X_KR: | |
4054 | case IXGBE_DEV_ID_X550EM_A_KR: | |
4055 | case IXGBE_DEV_ID_X550EM_A_KR_L: | |
4056 | ret_val = hw->mac.ops.read_iosf_sb_reg(hw, | |
4057 | IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id), | |
4058 | IXGBE_SB_IOSF_TARGET_KR_PHY, ®_val); | |
4059 | if (ret_val != IXGBE_SUCCESS) | |
4060 | goto out; | |
4061 | reg_val &= ~(IXGBE_KRM_AN_CNTL_1_SYM_PAUSE | | |
4062 | IXGBE_KRM_AN_CNTL_1_ASM_PAUSE); | |
4063 | if (pause) | |
4064 | reg_val |= IXGBE_KRM_AN_CNTL_1_SYM_PAUSE; | |
4065 | if (asm_dir) | |
4066 | reg_val |= IXGBE_KRM_AN_CNTL_1_ASM_PAUSE; | |
4067 | ret_val = hw->mac.ops.write_iosf_sb_reg(hw, | |
4068 | IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id), | |
4069 | IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val); | |
4070 | ||
4071 | /* This device does not fully support AN. */ | |
4072 | hw->fc.disable_fc_autoneg = true; | |
4073 | break; | |
4074 | default: | |
4075 | break; | |
4076 | } | |
4077 | ||
4078 | out: | |
4079 | return ret_val; | |
4080 | } | |
4081 | ||
4082 | /** | |
4083 | * ixgbe_fc_autoneg_backplane_x550em_a - Enable flow control IEEE clause 37 | |
4084 | * @hw: pointer to hardware structure | |
4085 | * | |
4086 | * Enable flow control according to IEEE clause 37. | |
4087 | **/ | |
4088 | void ixgbe_fc_autoneg_backplane_x550em_a(struct ixgbe_hw *hw) | |
4089 | { | |
4090 | u32 link_s1, lp_an_page_low, an_cntl_1; | |
4091 | s32 status = IXGBE_ERR_FC_NOT_NEGOTIATED; | |
4092 | ixgbe_link_speed speed; | |
4093 | bool link_up; | |
4094 | ||
4095 | /* AN should have completed when the cable was plugged in. | |
4096 | * Look for reasons to bail out. Bail out if: | |
4097 | * - FC autoneg is disabled, or if | |
4098 | * - link is not up. | |
4099 | */ | |
4100 | if (hw->fc.disable_fc_autoneg) { | |
4101 | ERROR_REPORT1(IXGBE_ERROR_UNSUPPORTED, | |
4102 | "Flow control autoneg is disabled"); | |
4103 | goto out; | |
4104 | } | |
4105 | ||
4106 | hw->mac.ops.check_link(hw, &speed, &link_up, false); | |
4107 | if (!link_up) { | |
4108 | ERROR_REPORT1(IXGBE_ERROR_SOFTWARE, "The link is down"); | |
4109 | goto out; | |
4110 | } | |
4111 | ||
4112 | /* Check at auto-negotiation has completed */ | |
4113 | status = hw->mac.ops.read_iosf_sb_reg(hw, | |
4114 | IXGBE_KRM_LINK_S1(hw->bus.lan_id), | |
4115 | IXGBE_SB_IOSF_TARGET_KR_PHY, &link_s1); | |
4116 | ||
4117 | if (status != IXGBE_SUCCESS || | |
4118 | (link_s1 & IXGBE_KRM_LINK_S1_MAC_AN_COMPLETE) == 0) { | |
4119 | DEBUGOUT("Auto-Negotiation did not complete\n"); | |
4120 | status = IXGBE_ERR_FC_NOT_NEGOTIATED; | |
4121 | goto out; | |
4122 | } | |
4123 | ||
4124 | /* Read the 10g AN autoc and LP ability registers and resolve | |
4125 | * local flow control settings accordingly | |
4126 | */ | |
4127 | status = hw->mac.ops.read_iosf_sb_reg(hw, | |
4128 | IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id), | |
4129 | IXGBE_SB_IOSF_TARGET_KR_PHY, &an_cntl_1); | |
4130 | ||
4131 | if (status != IXGBE_SUCCESS) { | |
4132 | DEBUGOUT("Auto-Negotiation did not complete\n"); | |
4133 | goto out; | |
4134 | } | |
4135 | ||
4136 | status = hw->mac.ops.read_iosf_sb_reg(hw, | |
4137 | IXGBE_KRM_LP_BASE_PAGE_HIGH(hw->bus.lan_id), | |
4138 | IXGBE_SB_IOSF_TARGET_KR_PHY, &lp_an_page_low); | |
4139 | ||
4140 | if (status != IXGBE_SUCCESS) { | |
4141 | DEBUGOUT("Auto-Negotiation did not complete\n"); | |
4142 | goto out; | |
4143 | } | |
4144 | ||
4145 | status = ixgbe_negotiate_fc(hw, an_cntl_1, lp_an_page_low, | |
4146 | IXGBE_KRM_AN_CNTL_1_SYM_PAUSE, | |
4147 | IXGBE_KRM_AN_CNTL_1_ASM_PAUSE, | |
4148 | IXGBE_KRM_LP_BASE_PAGE_HIGH_SYM_PAUSE, | |
4149 | IXGBE_KRM_LP_BASE_PAGE_HIGH_ASM_PAUSE); | |
4150 | ||
4151 | out: | |
4152 | if (status == IXGBE_SUCCESS) { | |
4153 | hw->fc.fc_was_autonegged = true; | |
4154 | } else { | |
4155 | hw->fc.fc_was_autonegged = false; | |
4156 | hw->fc.current_mode = hw->fc.requested_mode; | |
4157 | } | |
4158 | } | |
4159 | ||
4160 | /** | |
4161 | * ixgbe_fc_autoneg_fiber_x550em_a - passthrough FC settings | |
4162 | * @hw: pointer to hardware structure | |
4163 | * | |
4164 | **/ | |
4165 | void ixgbe_fc_autoneg_fiber_x550em_a(struct ixgbe_hw *hw) | |
4166 | { | |
4167 | hw->fc.fc_was_autonegged = false; | |
4168 | hw->fc.current_mode = hw->fc.requested_mode; | |
4169 | } | |
4170 | ||
4171 | /** | |
4172 | * ixgbe_fc_autoneg_sgmii_x550em_a - Enable flow control IEEE clause 37 | |
4173 | * @hw: pointer to hardware structure | |
4174 | * | |
4175 | * Enable flow control according to IEEE clause 37. | |
4176 | **/ | |
4177 | void ixgbe_fc_autoneg_sgmii_x550em_a(struct ixgbe_hw *hw) | |
4178 | { | |
4179 | s32 status = IXGBE_ERR_FC_NOT_NEGOTIATED; | |
4180 | u16 reg, pcs_an_lp, pcs_an; | |
4181 | ixgbe_link_speed speed; | |
4182 | bool link_up; | |
4183 | ||
4184 | /* AN should have completed when the cable was plugged in. | |
4185 | * Look for reasons to bail out. Bail out if: | |
4186 | * - FC autoneg is disabled, or if | |
4187 | * - link is not up. | |
4188 | */ | |
4189 | if (hw->fc.disable_fc_autoneg) { | |
4190 | ERROR_REPORT1(IXGBE_ERROR_UNSUPPORTED, | |
4191 | "Flow control autoneg is disabled"); | |
4192 | goto out; | |
4193 | } | |
4194 | ||
4195 | hw->mac.ops.check_link(hw, &speed, &link_up, false); | |
4196 | if (!link_up) { | |
4197 | ERROR_REPORT1(IXGBE_ERROR_SOFTWARE, "The link is down"); | |
4198 | goto out; | |
4199 | } | |
4200 | ||
4201 | /* Check if auto-negotiation has completed */ | |
4202 | status = hw->phy.ops.read_reg(hw, IXGBE_M88E1500_COPPER_STATUS, | |
4203 | IXGBE_MDIO_ZERO_DEV_TYPE, ®); | |
4204 | if (status != IXGBE_SUCCESS || | |
4205 | (reg & IXGBE_M88E1500_COPPER_STATUS_AN_DONE) == 0) { | |
4206 | DEBUGOUT("Auto-Negotiation did not complete\n"); | |
4207 | status = IXGBE_ERR_FC_NOT_NEGOTIATED; | |
4208 | goto out; | |
4209 | } | |
4210 | ||
4211 | /* Get the advertized flow control */ | |
4212 | status = hw->phy.ops.read_reg(hw, IXGBE_M88E1500_COPPER_AN, | |
4213 | IXGBE_MDIO_ZERO_DEV_TYPE, &pcs_an); | |
4214 | if (status != IXGBE_SUCCESS) | |
4215 | goto out; | |
4216 | ||
4217 | /* Get link partner's flow control */ | |
4218 | status = hw->phy.ops.read_reg(hw, | |
4219 | IXGBE_M88E1500_COPPER_AN_LP_ABILITY, | |
4220 | IXGBE_MDIO_ZERO_DEV_TYPE, &pcs_an_lp); | |
4221 | if (status != IXGBE_SUCCESS) | |
4222 | goto out; | |
4223 | ||
4224 | /* Negotiate the flow control */ | |
4225 | status = ixgbe_negotiate_fc(hw, (u32)pcs_an, (u32)pcs_an_lp, | |
4226 | IXGBE_M88E1500_COPPER_AN_PAUSE, | |
4227 | IXGBE_M88E1500_COPPER_AN_AS_PAUSE, | |
4228 | IXGBE_M88E1500_COPPER_AN_LP_PAUSE, | |
4229 | IXGBE_M88E1500_COPPER_AN_LP_AS_PAUSE); | |
4230 | ||
4231 | out: | |
4232 | if (status == IXGBE_SUCCESS) { | |
4233 | hw->fc.fc_was_autonegged = true; | |
4234 | } else { | |
4235 | hw->fc.fc_was_autonegged = false; | |
4236 | hw->fc.current_mode = hw->fc.requested_mode; | |
4237 | } | |
4238 | } | |
4239 | ||
4240 | /** | |
4241 | * ixgbe_setup_fc_sgmii_x550em_a - Set up flow control | |
4242 | * @hw: pointer to hardware structure | |
4243 | * | |
4244 | * Called at init time to set up flow control. | |
4245 | **/ | |
4246 | s32 ixgbe_setup_fc_sgmii_x550em_a(struct ixgbe_hw *hw) | |
4247 | { | |
4248 | u16 reg; | |
4249 | s32 rc; | |
4250 | ||
4251 | /* Validate the requested mode */ | |
4252 | if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) { | |
4253 | ERROR_REPORT1(IXGBE_ERROR_UNSUPPORTED, | |
4254 | "ixgbe_fc_rx_pause not valid in strict IEEE mode\n"); | |
4255 | return IXGBE_ERR_INVALID_LINK_SETTINGS; | |
4256 | } | |
4257 | ||
4258 | if (hw->fc.requested_mode == ixgbe_fc_default) | |
4259 | hw->fc.requested_mode = ixgbe_fc_full; | |
4260 | ||
4261 | /* Read contents of the Auto-Negotiation register, page 0 reg 4 */ | |
4262 | rc = hw->phy.ops.read_reg(hw, IXGBE_M88E1500_COPPER_AN, | |
4263 | IXGBE_MDIO_ZERO_DEV_TYPE, ®); | |
4264 | if (rc) | |
4265 | goto out; | |
4266 | ||
4267 | /* Disable all the settings related to Flow control Auto-negotiation */ | |
4268 | reg &= ~IXGBE_M88E1500_COPPER_AN_AS_PAUSE; | |
4269 | reg &= ~IXGBE_M88E1500_COPPER_AN_PAUSE; | |
4270 | ||
4271 | /* Configure the Asymmetric and symmetric pause according to the user | |
4272 | * requested mode. | |
4273 | */ | |
4274 | switch (hw->fc.requested_mode) { | |
4275 | case ixgbe_fc_full: | |
4276 | reg |= IXGBE_M88E1500_COPPER_AN_PAUSE; | |
4277 | reg |= IXGBE_M88E1500_COPPER_AN_AS_PAUSE; | |
4278 | break; | |
4279 | case ixgbe_fc_rx_pause: | |
4280 | reg |= IXGBE_M88E1500_COPPER_AN_PAUSE; | |
4281 | reg |= IXGBE_M88E1500_COPPER_AN_AS_PAUSE; | |
4282 | break; | |
4283 | case ixgbe_fc_tx_pause: | |
4284 | reg |= IXGBE_M88E1500_COPPER_AN_AS_PAUSE; | |
4285 | break; | |
4286 | default: | |
4287 | break; | |
4288 | } | |
4289 | ||
4290 | /* Write back to the Auto-Negotiation register with newly configured | |
4291 | * fields | |
4292 | */ | |
4293 | hw->phy.ops.write_reg(hw, IXGBE_M88E1500_COPPER_AN, | |
4294 | IXGBE_MDIO_ZERO_DEV_TYPE, reg); | |
4295 | ||
4296 | /* In this section of the code we restart Auto-negotiation */ | |
4297 | ||
4298 | /* Read the CONTROL register, Page 0 reg 0 */ | |
4299 | rc = hw->phy.ops.read_reg(hw, IXGBE_M88E1500_COPPER_CTRL, | |
4300 | IXGBE_MDIO_ZERO_DEV_TYPE, ®); | |
4301 | if (rc) | |
4302 | goto out; | |
4303 | ||
4304 | /* Set the bit to restart Auto-Neg. The bit to enable Auto-neg is ON | |
4305 | * by default | |
4306 | */ | |
4307 | reg |= IXGBE_M88E1500_COPPER_CTRL_RESTART_AN; | |
4308 | ||
4309 | /* write the new values to the register to restart Auto-Negotiation */ | |
4310 | hw->phy.ops.write_reg(hw, IXGBE_M88E1500_COPPER_CTRL, | |
4311 | IXGBE_MDIO_ZERO_DEV_TYPE, reg); | |
4312 | ||
4313 | out: | |
4314 | return rc; | |
4315 | } | |
4316 | ||
4317 | /** | |
4318 | * ixgbe_setup_fc_backplane_x550em_a - Set up flow control | |
4319 | * @hw: pointer to hardware structure | |
4320 | * | |
4321 | * Called at init time to set up flow control. | |
4322 | **/ | |
4323 | s32 ixgbe_setup_fc_backplane_x550em_a(struct ixgbe_hw *hw) | |
4324 | { | |
4325 | s32 status = IXGBE_SUCCESS; | |
4326 | u32 an_cntl = 0; | |
4327 | ||
4328 | DEBUGFUNC("ixgbe_setup_fc_backplane_x550em_a"); | |
4329 | ||
4330 | /* Validate the requested mode */ | |
4331 | if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) { | |
4332 | ERROR_REPORT1(IXGBE_ERROR_UNSUPPORTED, | |
4333 | "ixgbe_fc_rx_pause not valid in strict IEEE mode\n"); | |
4334 | return IXGBE_ERR_INVALID_LINK_SETTINGS; | |
4335 | } | |
4336 | ||
4337 | if (hw->fc.requested_mode == ixgbe_fc_default) | |
4338 | hw->fc.requested_mode = ixgbe_fc_full; | |
4339 | ||
4340 | /* Set up the 1G and 10G flow control advertisement registers so the | |
4341 | * HW will be able to do FC autoneg once the cable is plugged in. If | |
4342 | * we link at 10G, the 1G advertisement is harmless and vice versa. | |
4343 | */ | |
4344 | status = hw->mac.ops.read_iosf_sb_reg(hw, | |
4345 | IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id), | |
4346 | IXGBE_SB_IOSF_TARGET_KR_PHY, &an_cntl); | |
4347 | ||
4348 | if (status != IXGBE_SUCCESS) { | |
4349 | DEBUGOUT("Auto-Negotiation did not complete\n"); | |
4350 | return status; | |
4351 | } | |
4352 | ||
4353 | /* The possible values of fc.requested_mode are: | |
4354 | * 0: Flow control is completely disabled | |
4355 | * 1: Rx flow control is enabled (we can receive pause frames, | |
4356 | * but not send pause frames). | |
4357 | * 2: Tx flow control is enabled (we can send pause frames but | |
4358 | * we do not support receiving pause frames). | |
4359 | * 3: Both Rx and Tx flow control (symmetric) are enabled. | |
4360 | * other: Invalid. | |
4361 | */ | |
4362 | switch (hw->fc.requested_mode) { | |
4363 | case ixgbe_fc_none: | |
4364 | /* Flow control completely disabled by software override. */ | |
4365 | an_cntl &= ~(IXGBE_KRM_AN_CNTL_1_SYM_PAUSE | | |
4366 | IXGBE_KRM_AN_CNTL_1_ASM_PAUSE); | |
4367 | break; | |
4368 | case ixgbe_fc_tx_pause: | |
4369 | /* Tx Flow control is enabled, and Rx Flow control is | |
4370 | * disabled by software override. | |
4371 | */ | |
4372 | an_cntl |= IXGBE_KRM_AN_CNTL_1_ASM_PAUSE; | |
4373 | an_cntl &= ~IXGBE_KRM_AN_CNTL_1_SYM_PAUSE; | |
4374 | break; | |
4375 | case ixgbe_fc_rx_pause: | |
4376 | /* Rx Flow control is enabled and Tx Flow control is | |
4377 | * disabled by software override. Since there really | |
4378 | * isn't a way to advertise that we are capable of RX | |
4379 | * Pause ONLY, we will advertise that we support both | |
4380 | * symmetric and asymmetric Rx PAUSE, as such we fall | |
4381 | * through to the fc_full statement. Later, we will | |
4382 | * disable the adapter's ability to send PAUSE frames. | |
4383 | */ | |
4384 | case ixgbe_fc_full: | |
4385 | /* Flow control (both Rx and Tx) is enabled by SW override. */ | |
4386 | an_cntl |= IXGBE_KRM_AN_CNTL_1_SYM_PAUSE | | |
4387 | IXGBE_KRM_AN_CNTL_1_ASM_PAUSE; | |
4388 | break; | |
4389 | default: | |
4390 | ERROR_REPORT1(IXGBE_ERROR_ARGUMENT, | |
4391 | "Flow control param set incorrectly\n"); | |
4392 | return IXGBE_ERR_CONFIG; | |
4393 | } | |
4394 | ||
4395 | status = hw->mac.ops.write_iosf_sb_reg(hw, | |
4396 | IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id), | |
4397 | IXGBE_SB_IOSF_TARGET_KR_PHY, an_cntl); | |
4398 | ||
4399 | /* Restart auto-negotiation. */ | |
4400 | status = ixgbe_restart_an_internal_phy_x550em(hw); | |
4401 | ||
4402 | return status; | |
4403 | } | |
4404 | ||
4405 | /** | |
4406 | * ixgbe_set_mux - Set mux for port 1 access with CS4227 | |
4407 | * @hw: pointer to hardware structure | |
4408 | * @state: set mux if 1, clear if 0 | |
4409 | */ | |
4410 | STATIC void ixgbe_set_mux(struct ixgbe_hw *hw, u8 state) | |
4411 | { | |
4412 | u32 esdp; | |
4413 | ||
4414 | if (!hw->bus.lan_id) | |
4415 | return; | |
4416 | esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); | |
4417 | if (state) | |
4418 | esdp |= IXGBE_ESDP_SDP1; | |
4419 | else | |
4420 | esdp &= ~IXGBE_ESDP_SDP1; | |
4421 | IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); | |
4422 | IXGBE_WRITE_FLUSH(hw); | |
4423 | } | |
4424 | ||
4425 | /** | |
4426 | * ixgbe_acquire_swfw_sync_X550em - Acquire SWFW semaphore | |
4427 | * @hw: pointer to hardware structure | |
4428 | * @mask: Mask to specify which semaphore to acquire | |
4429 | * | |
4430 | * Acquires the SWFW semaphore and sets the I2C MUX | |
4431 | **/ | |
4432 | s32 ixgbe_acquire_swfw_sync_X550em(struct ixgbe_hw *hw, u32 mask) | |
4433 | { | |
4434 | s32 status; | |
4435 | ||
4436 | DEBUGFUNC("ixgbe_acquire_swfw_sync_X550em"); | |
4437 | ||
4438 | status = ixgbe_acquire_swfw_sync_X540(hw, mask); | |
4439 | if (status) | |
4440 | return status; | |
4441 | ||
4442 | if (mask & IXGBE_GSSR_I2C_MASK) | |
4443 | ixgbe_set_mux(hw, 1); | |
4444 | ||
4445 | return IXGBE_SUCCESS; | |
4446 | } | |
4447 | ||
4448 | /** | |
4449 | * ixgbe_release_swfw_sync_X550em - Release SWFW semaphore | |
4450 | * @hw: pointer to hardware structure | |
4451 | * @mask: Mask to specify which semaphore to release | |
4452 | * | |
4453 | * Releases the SWFW semaphore and sets the I2C MUX | |
4454 | **/ | |
4455 | void ixgbe_release_swfw_sync_X550em(struct ixgbe_hw *hw, u32 mask) | |
4456 | { | |
4457 | DEBUGFUNC("ixgbe_release_swfw_sync_X550em"); | |
4458 | ||
4459 | if (mask & IXGBE_GSSR_I2C_MASK) | |
4460 | ixgbe_set_mux(hw, 0); | |
4461 | ||
4462 | ixgbe_release_swfw_sync_X540(hw, mask); | |
4463 | } | |
4464 | ||
4465 | /** | |
4466 | * ixgbe_acquire_swfw_sync_X550a - Acquire SWFW semaphore | |
4467 | * @hw: pointer to hardware structure | |
4468 | * @mask: Mask to specify which semaphore to acquire | |
4469 | * | |
4470 | * Acquires the SWFW semaphore and get the shared phy token as needed | |
4471 | */ | |
4472 | STATIC s32 ixgbe_acquire_swfw_sync_X550a(struct ixgbe_hw *hw, u32 mask) | |
4473 | { | |
4474 | u32 hmask = mask & ~IXGBE_GSSR_TOKEN_SM; | |
4475 | int retries = FW_PHY_TOKEN_RETRIES; | |
4476 | s32 status = IXGBE_SUCCESS; | |
4477 | ||
4478 | DEBUGFUNC("ixgbe_acquire_swfw_sync_X550a"); | |
4479 | ||
4480 | while (--retries) { | |
4481 | status = IXGBE_SUCCESS; | |
4482 | if (hmask) | |
4483 | status = ixgbe_acquire_swfw_sync_X540(hw, hmask); | |
4484 | if (status) | |
4485 | return status; | |
4486 | if (!(mask & IXGBE_GSSR_TOKEN_SM)) | |
4487 | return IXGBE_SUCCESS; | |
4488 | ||
4489 | status = ixgbe_get_phy_token(hw); | |
4490 | if (status == IXGBE_SUCCESS) | |
4491 | return IXGBE_SUCCESS; | |
4492 | ||
4493 | if (hmask) | |
4494 | ixgbe_release_swfw_sync_X540(hw, hmask); | |
4495 | if (status != IXGBE_ERR_TOKEN_RETRY) | |
4496 | return status; | |
4497 | } | |
4498 | ||
4499 | return status; | |
4500 | } | |
4501 | ||
4502 | /** | |
4503 | * ixgbe_release_swfw_sync_X550a - Release SWFW semaphore | |
4504 | * @hw: pointer to hardware structure | |
4505 | * @mask: Mask to specify which semaphore to release | |
4506 | * | |
4507 | * Releases the SWFW semaphore and puts the shared phy token as needed | |
4508 | */ | |
4509 | STATIC void ixgbe_release_swfw_sync_X550a(struct ixgbe_hw *hw, u32 mask) | |
4510 | { | |
4511 | u32 hmask = mask & ~IXGBE_GSSR_TOKEN_SM; | |
4512 | ||
4513 | DEBUGFUNC("ixgbe_release_swfw_sync_X550a"); | |
4514 | ||
4515 | if (mask & IXGBE_GSSR_TOKEN_SM) | |
4516 | ixgbe_put_phy_token(hw); | |
4517 | ||
4518 | if (hmask) | |
4519 | ixgbe_release_swfw_sync_X540(hw, hmask); | |
4520 | } | |
4521 | ||
4522 | /** | |
4523 | * ixgbe_read_phy_reg_x550a - Reads specified PHY register | |
4524 | * @hw: pointer to hardware structure | |
4525 | * @reg_addr: 32 bit address of PHY register to read | |
4526 | * @phy_data: Pointer to read data from PHY register | |
4527 | * | |
4528 | * Reads a value from a specified PHY register using the SWFW lock and PHY | |
4529 | * Token. The PHY Token is needed since the MDIO is shared between to MAC | |
4530 | * instances. | |
4531 | **/ | |
4532 | s32 ixgbe_read_phy_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr, | |
4533 | u32 device_type, u16 *phy_data) | |
4534 | { | |
4535 | s32 status; | |
4536 | u32 mask = hw->phy.phy_semaphore_mask | IXGBE_GSSR_TOKEN_SM; | |
4537 | ||
4538 | DEBUGFUNC("ixgbe_read_phy_reg_x550a"); | |
4539 | ||
4540 | if (hw->mac.ops.acquire_swfw_sync(hw, mask)) | |
4541 | return IXGBE_ERR_SWFW_SYNC; | |
4542 | ||
4543 | status = hw->phy.ops.read_reg_mdi(hw, reg_addr, device_type, phy_data); | |
4544 | ||
4545 | hw->mac.ops.release_swfw_sync(hw, mask); | |
4546 | ||
4547 | return status; | |
4548 | } | |
4549 | ||
4550 | /** | |
4551 | * ixgbe_write_phy_reg_x550a - Writes specified PHY register | |
4552 | * @hw: pointer to hardware structure | |
4553 | * @reg_addr: 32 bit PHY register to write | |
4554 | * @device_type: 5 bit device type | |
4555 | * @phy_data: Data to write to the PHY register | |
4556 | * | |
4557 | * Writes a value to specified PHY register using the SWFW lock and PHY Token. | |
4558 | * The PHY Token is needed since the MDIO is shared between to MAC instances. | |
4559 | **/ | |
4560 | s32 ixgbe_write_phy_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr, | |
4561 | u32 device_type, u16 phy_data) | |
4562 | { | |
4563 | s32 status; | |
4564 | u32 mask = hw->phy.phy_semaphore_mask | IXGBE_GSSR_TOKEN_SM; | |
4565 | ||
4566 | DEBUGFUNC("ixgbe_write_phy_reg_x550a"); | |
4567 | ||
4568 | if (hw->mac.ops.acquire_swfw_sync(hw, mask) == IXGBE_SUCCESS) { | |
4569 | status = hw->phy.ops.write_reg_mdi(hw, reg_addr, device_type, | |
4570 | phy_data); | |
4571 | hw->mac.ops.release_swfw_sync(hw, mask); | |
4572 | } else { | |
4573 | status = IXGBE_ERR_SWFW_SYNC; | |
4574 | } | |
4575 | ||
4576 | return status; | |
4577 | } | |
4578 | ||
4579 | /** | |
4580 | * ixgbe_handle_lasi_ext_t_x550em - Handle external Base T PHY interrupt | |
4581 | * @hw: pointer to hardware structure | |
4582 | * | |
4583 | * Handle external Base T PHY interrupt. If high temperature | |
4584 | * failure alarm then return error, else if link status change | |
4585 | * then setup internal/external PHY link | |
4586 | * | |
4587 | * Return IXGBE_ERR_OVERTEMP if interrupt is high temperature | |
4588 | * failure alarm, else return PHY access status. | |
4589 | */ | |
4590 | s32 ixgbe_handle_lasi_ext_t_x550em(struct ixgbe_hw *hw) | |
4591 | { | |
4592 | bool lsc; | |
4593 | u32 status; | |
4594 | ||
4595 | status = ixgbe_get_lasi_ext_t_x550em(hw, &lsc); | |
4596 | ||
4597 | if (status != IXGBE_SUCCESS) | |
4598 | return status; | |
4599 | ||
4600 | if (lsc) | |
4601 | return ixgbe_setup_internal_phy(hw); | |
4602 | ||
4603 | return IXGBE_SUCCESS; | |
4604 | } | |
4605 | ||
4606 | /** | |
4607 | * ixgbe_setup_mac_link_t_X550em - Sets the auto advertised link speed | |
4608 | * @hw: pointer to hardware structure | |
4609 | * @speed: new link speed | |
4610 | * @autoneg_wait_to_complete: true when waiting for completion is needed | |
4611 | * | |
4612 | * Setup internal/external PHY link speed based on link speed, then set | |
4613 | * external PHY auto advertised link speed. | |
4614 | * | |
4615 | * Returns error status for any failure | |
4616 | **/ | |
4617 | s32 ixgbe_setup_mac_link_t_X550em(struct ixgbe_hw *hw, | |
4618 | ixgbe_link_speed speed, | |
4619 | bool autoneg_wait_to_complete) | |
4620 | { | |
4621 | s32 status; | |
4622 | ixgbe_link_speed force_speed; | |
4623 | ||
4624 | DEBUGFUNC("ixgbe_setup_mac_link_t_X550em"); | |
4625 | ||
4626 | /* Setup internal/external PHY link speed to iXFI (10G), unless | |
4627 | * only 1G is auto advertised then setup KX link. | |
4628 | */ | |
4629 | if (speed & IXGBE_LINK_SPEED_10GB_FULL) | |
4630 | force_speed = IXGBE_LINK_SPEED_10GB_FULL; | |
4631 | else | |
4632 | force_speed = IXGBE_LINK_SPEED_1GB_FULL; | |
4633 | ||
4634 | /* If internal link mode is XFI, then setup XFI internal link. */ | |
4635 | if (!(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE)) { | |
4636 | status = ixgbe_setup_ixfi_x550em(hw, &force_speed); | |
4637 | ||
4638 | if (status != IXGBE_SUCCESS) | |
4639 | return status; | |
4640 | } | |
4641 | ||
4642 | return hw->phy.ops.setup_link_speed(hw, speed, autoneg_wait_to_complete); | |
4643 | } | |
4644 | ||
4645 | /** | |
4646 | * ixgbe_check_link_t_X550em - Determine link and speed status | |
4647 | * @hw: pointer to hardware structure | |
4648 | * @speed: pointer to link speed | |
4649 | * @link_up: true when link is up | |
4650 | * @link_up_wait_to_complete: bool used to wait for link up or not | |
4651 | * | |
4652 | * Check that both the MAC and X557 external PHY have link. | |
4653 | **/ | |
4654 | s32 ixgbe_check_link_t_X550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed, | |
4655 | bool *link_up, bool link_up_wait_to_complete) | |
4656 | { | |
4657 | u32 status; | |
4658 | u16 autoneg_status; | |
4659 | ||
4660 | if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_copper) | |
4661 | return IXGBE_ERR_CONFIG; | |
4662 | ||
4663 | status = ixgbe_check_mac_link_generic(hw, speed, link_up, | |
4664 | link_up_wait_to_complete); | |
4665 | ||
4666 | /* If check link fails or MAC link is not up, then return */ | |
4667 | if (status != IXGBE_SUCCESS || !(*link_up)) | |
4668 | return status; | |
4669 | ||
4670 | /* MAC link is up, so check external PHY link. | |
4671 | * Read this twice back to back to indicate current status. | |
4672 | */ | |
4673 | status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS, | |
4674 | IXGBE_MDIO_AUTO_NEG_DEV_TYPE, | |
4675 | &autoneg_status); | |
4676 | ||
4677 | if (status != IXGBE_SUCCESS) | |
4678 | return status; | |
4679 | ||
4680 | status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS, | |
4681 | IXGBE_MDIO_AUTO_NEG_DEV_TYPE, | |
4682 | &autoneg_status); | |
4683 | ||
4684 | if (status != IXGBE_SUCCESS) | |
4685 | return status; | |
4686 | ||
4687 | /* If external PHY link is not up, then indicate link not up */ | |
4688 | if (!(autoneg_status & IXGBE_MDIO_AUTO_NEG_LINK_STATUS)) | |
4689 | *link_up = false; | |
4690 | ||
4691 | return IXGBE_SUCCESS; | |
4692 | } | |
4693 | ||
4694 | /** | |
4695 | * ixgbe_reset_phy_t_X550em - Performs X557 PHY reset and enables LASI | |
4696 | * @hw: pointer to hardware structure | |
4697 | **/ | |
4698 | s32 ixgbe_reset_phy_t_X550em(struct ixgbe_hw *hw) | |
4699 | { | |
4700 | s32 status; | |
4701 | ||
4702 | status = ixgbe_reset_phy_generic(hw); | |
4703 | ||
4704 | if (status != IXGBE_SUCCESS) | |
4705 | return status; | |
4706 | ||
4707 | /* Configure Link Status Alarm and Temperature Threshold interrupts */ | |
4708 | return ixgbe_enable_lasi_ext_t_x550em(hw); | |
4709 | } | |
4710 | ||
4711 | /** | |
4712 | * ixgbe_led_on_t_X550em - Turns on the software controllable LEDs. | |
4713 | * @hw: pointer to hardware structure | |
4714 | * @led_idx: led number to turn on | |
4715 | **/ | |
4716 | s32 ixgbe_led_on_t_X550em(struct ixgbe_hw *hw, u32 led_idx) | |
4717 | { | |
4718 | u16 phy_data; | |
4719 | ||
4720 | DEBUGFUNC("ixgbe_led_on_t_X550em"); | |
4721 | ||
4722 | if (led_idx >= IXGBE_X557_MAX_LED_INDEX) | |
4723 | return IXGBE_ERR_PARAM; | |
4724 | ||
4725 | /* To turn on the LED, set mode to ON. */ | |
4726 | ixgbe_read_phy_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx, | |
4727 | IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, &phy_data); | |
4728 | phy_data |= IXGBE_X557_LED_MANUAL_SET_MASK; | |
4729 | ixgbe_write_phy_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx, | |
4730 | IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, phy_data); | |
4731 | ||
4732 | return IXGBE_SUCCESS; | |
4733 | } | |
4734 | ||
4735 | /** | |
4736 | * ixgbe_led_off_t_X550em - Turns off the software controllable LEDs. | |
4737 | * @hw: pointer to hardware structure | |
4738 | * @led_idx: led number to turn off | |
4739 | **/ | |
4740 | s32 ixgbe_led_off_t_X550em(struct ixgbe_hw *hw, u32 led_idx) | |
4741 | { | |
4742 | u16 phy_data; | |
4743 | ||
4744 | DEBUGFUNC("ixgbe_led_off_t_X550em"); | |
4745 | ||
4746 | if (led_idx >= IXGBE_X557_MAX_LED_INDEX) | |
4747 | return IXGBE_ERR_PARAM; | |
4748 | ||
4749 | /* To turn on the LED, set mode to ON. */ | |
4750 | ixgbe_read_phy_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx, | |
4751 | IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, &phy_data); | |
4752 | phy_data &= ~IXGBE_X557_LED_MANUAL_SET_MASK; | |
4753 | ixgbe_write_phy_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx, | |
4754 | IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, phy_data); | |
4755 | ||
4756 | return IXGBE_SUCCESS; | |
4757 | } |