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