Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2001-2020 Intel Corporation
3 : : */
4 : :
5 : : #include "igc_api.h"
6 : :
7 : : static s32 igc_init_nvm_params_i225(struct igc_hw *hw);
8 : : static s32 igc_init_mac_params_i225(struct igc_hw *hw);
9 : : static s32 igc_init_phy_params_i225(struct igc_hw *hw);
10 : : static s32 igc_reset_hw_i225(struct igc_hw *hw);
11 : : static s32 igc_acquire_nvm_i225(struct igc_hw *hw);
12 : : static void igc_release_nvm_i225(struct igc_hw *hw);
13 : : static s32 igc_get_hw_semaphore_i225(struct igc_hw *hw);
14 : : static s32 __igc_write_nvm_srwr(struct igc_hw *hw, u16 offset, u16 words,
15 : : u16 *data);
16 : : static s32 igc_pool_flash_update_done_i225(struct igc_hw *hw);
17 : : static s32 igc_valid_led_default_i225(struct igc_hw *hw, u16 *data);
18 : :
19 : : /**
20 : : * igc_init_nvm_params_i225 - Init NVM func ptrs.
21 : : * @hw: pointer to the HW structure
22 : : **/
23 : 0 : static s32 igc_init_nvm_params_i225(struct igc_hw *hw)
24 : : {
25 : : struct igc_nvm_info *nvm = &hw->nvm;
26 : 0 : u32 eecd = IGC_READ_REG(hw, IGC_EECD);
27 : : u16 size;
28 : :
29 : 0 : DEBUGFUNC("igc_init_nvm_params_i225");
30 : :
31 : 0 : size = (u16)((eecd & IGC_EECD_SIZE_EX_MASK) >>
32 : : IGC_EECD_SIZE_EX_SHIFT);
33 : : /*
34 : : * Added to a constant, "size" becomes the left-shift value
35 : : * for setting word_size.
36 : : */
37 : 0 : size += NVM_WORD_SIZE_BASE_SHIFT;
38 : :
39 : : /* Just in case size is out of range, cap it to the largest
40 : : * EEPROM size supported
41 : : */
42 : : if (size > 15)
43 : : size = 15;
44 : :
45 : 0 : nvm->word_size = 1 << size;
46 : 0 : nvm->opcode_bits = 8;
47 : 0 : nvm->delay_usec = 1;
48 : 0 : nvm->type = igc_nvm_eeprom_spi;
49 : :
50 : :
51 [ # # ]: 0 : nvm->page_size = eecd & IGC_EECD_ADDR_BITS ? 32 : 8;
52 [ # # ]: 0 : nvm->address_bits = eecd & IGC_EECD_ADDR_BITS ?
53 : : 16 : 8;
54 : :
55 [ # # ]: 0 : if (nvm->word_size == (1 << 15))
56 : 0 : nvm->page_size = 128;
57 : :
58 : 0 : nvm->ops.acquire = igc_acquire_nvm_i225;
59 : 0 : nvm->ops.release = igc_release_nvm_i225;
60 : 0 : nvm->ops.valid_led_default = igc_valid_led_default_i225;
61 [ # # ]: 0 : if (igc_get_flash_presence_i225(hw)) {
62 : 0 : hw->nvm.type = igc_nvm_flash_hw;
63 : 0 : nvm->ops.read = igc_read_nvm_srrd_i225;
64 : 0 : nvm->ops.write = igc_write_nvm_srwr_i225;
65 : 0 : nvm->ops.validate = igc_validate_nvm_checksum_i225;
66 : 0 : nvm->ops.update = igc_update_nvm_checksum_i225;
67 : : } else {
68 : 0 : hw->nvm.type = igc_nvm_invm;
69 : 0 : nvm->ops.write = igc_null_write_nvm;
70 : 0 : nvm->ops.validate = igc_null_ops_generic;
71 : 0 : nvm->ops.update = igc_null_ops_generic;
72 : : }
73 : :
74 : 0 : return IGC_SUCCESS;
75 : : }
76 : :
77 : : /**
78 : : * igc_init_mac_params_i225 - Init MAC func ptrs.
79 : : * @hw: pointer to the HW structure
80 : : **/
81 : 0 : static s32 igc_init_mac_params_i225(struct igc_hw *hw)
82 : : {
83 : : struct igc_mac_info *mac = &hw->mac;
84 : : struct igc_dev_spec_i225 *dev_spec = &hw->dev_spec._i225;
85 : :
86 : 0 : DEBUGFUNC("igc_init_mac_params_i225");
87 : :
88 : : /* Initialize function pointer */
89 : 0 : igc_init_mac_ops_generic(hw);
90 : :
91 : : /* Set media type */
92 : 0 : hw->phy.media_type = igc_media_type_copper;
93 : : /* Set mta register count */
94 : 0 : mac->mta_reg_count = 128;
95 : : /* Set rar entry count */
96 : 0 : mac->rar_entry_count = IGC_RAR_ENTRIES_BASE;
97 : :
98 : : /* reset */
99 : 0 : mac->ops.reset_hw = igc_reset_hw_i225;
100 : : /* hw initialization */
101 : 0 : mac->ops.init_hw = igc_init_hw_i225;
102 : : /* link setup */
103 : 0 : mac->ops.setup_link = igc_setup_link_generic;
104 : : /* check for link */
105 : 0 : mac->ops.check_for_link = igc_check_for_link_i225;
106 : : /* link info */
107 : 0 : mac->ops.get_link_up_info = igc_get_speed_and_duplex_copper_generic;
108 : : /* acquire SW_FW sync */
109 : 0 : mac->ops.acquire_swfw_sync = igc_acquire_swfw_sync_i225;
110 : : /* release SW_FW sync */
111 : 0 : mac->ops.release_swfw_sync = igc_release_swfw_sync_i225;
112 : :
113 : : /* Allow a single clear of the SW semaphore on I225 */
114 : 0 : dev_spec->clear_semaphore_once = true;
115 : 0 : mac->ops.setup_physical_interface = igc_setup_copper_link_i225;
116 : :
117 : : /* Set if part includes ASF firmware */
118 : 0 : mac->asf_firmware_present = true;
119 : :
120 : : /* multicast address update */
121 : 0 : mac->ops.update_mc_addr_list = igc_update_mc_addr_list_generic;
122 : :
123 : 0 : mac->ops.write_vfta = igc_write_vfta_generic;
124 : :
125 : : /* Disable EEE by default */
126 : 0 : dev_spec->eee_disable = true;
127 : :
128 : 0 : return IGC_SUCCESS;
129 : : }
130 : :
131 : : /**
132 : : * igc_init_phy_params_i225 - Init PHY func ptrs.
133 : : * @hw: pointer to the HW structure
134 : : **/
135 : 0 : static s32 igc_init_phy_params_i225(struct igc_hw *hw)
136 : : {
137 : : struct igc_phy_info *phy = &hw->phy;
138 : : s32 ret_val = IGC_SUCCESS;
139 : : u32 ctrl_ext;
140 : :
141 : 0 : DEBUGFUNC("igc_init_phy_params_i225");
142 : :
143 : 0 : phy->ops.read_i2c_byte = igc_read_i2c_byte_generic;
144 : 0 : phy->ops.write_i2c_byte = igc_write_i2c_byte_generic;
145 : :
146 [ # # ]: 0 : if (hw->phy.media_type != igc_media_type_copper) {
147 : 0 : phy->type = igc_phy_none;
148 : 0 : goto out;
149 : : }
150 : :
151 : 0 : phy->ops.power_up = igc_power_up_phy_copper;
152 : 0 : phy->ops.power_down = igc_power_down_phy_copper_base;
153 : :
154 : 0 : phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT_2500;
155 : :
156 : 0 : phy->reset_delay_us = 100;
157 : :
158 : 0 : phy->ops.acquire = igc_acquire_phy_base;
159 : 0 : phy->ops.check_reset_block = igc_check_reset_block_generic;
160 : 0 : phy->ops.commit = igc_phy_sw_reset_generic;
161 : 0 : phy->ops.release = igc_release_phy_base;
162 : :
163 : 0 : ctrl_ext = IGC_READ_REG(hw, IGC_CTRL_EXT);
164 : :
165 : : /* Make sure the PHY is in a good state. Several people have reported
166 : : * firmware leaving the PHY's page select register set to something
167 : : * other than the default of zero, which causes the PHY ID read to
168 : : * access something other than the intended register.
169 : : */
170 : 0 : ret_val = hw->phy.ops.reset(hw);
171 [ # # ]: 0 : if (ret_val)
172 : 0 : goto out;
173 : :
174 : 0 : IGC_WRITE_REG(hw, IGC_CTRL_EXT, ctrl_ext);
175 : 0 : phy->ops.read_reg = igc_read_phy_reg_gpy;
176 : 0 : phy->ops.write_reg = igc_write_phy_reg_gpy;
177 : :
178 : 0 : ret_val = igc_get_phy_id(hw);
179 : 0 : phy->type = igc_phy_i225;
180 : :
181 : :
182 : 0 : out:
183 : 0 : return ret_val;
184 : : }
185 : :
186 : : /**
187 : : * igc_reset_hw_i225 - Reset hardware
188 : : * @hw: pointer to the HW structure
189 : : *
190 : : * This resets the hardware into a known state.
191 : : **/
192 : 0 : static s32 igc_reset_hw_i225(struct igc_hw *hw)
193 : : {
194 : : u32 ctrl;
195 : : s32 ret_val;
196 : :
197 : 0 : DEBUGFUNC("igc_reset_hw_i225");
198 : :
199 : : /*
200 : : * Prevent the PCI-E bus from sticking if there is no TLP connection
201 : : * on the last TLP read/write transaction when MAC is reset.
202 : : */
203 : 0 : ret_val = igc_disable_pcie_master_generic(hw);
204 [ # # ]: 0 : if (ret_val)
205 : 0 : DEBUGOUT("PCI-E Master disable polling has failed.\n");
206 : :
207 : 0 : DEBUGOUT("Masking off all interrupts\n");
208 : 0 : IGC_WRITE_REG(hw, IGC_IMC, 0xffffffff);
209 : :
210 : 0 : IGC_WRITE_REG(hw, IGC_RCTL, 0);
211 : 0 : IGC_WRITE_REG(hw, IGC_TCTL, IGC_TCTL_PSP);
212 : 0 : IGC_WRITE_FLUSH(hw);
213 : :
214 : 0 : msec_delay(10);
215 : :
216 : 0 : ctrl = IGC_READ_REG(hw, IGC_CTRL);
217 : :
218 : 0 : DEBUGOUT("Issuing a global reset to MAC\n");
219 : 0 : IGC_WRITE_REG(hw, IGC_CTRL, ctrl | IGC_CTRL_RST);
220 : :
221 : 0 : ret_val = igc_get_auto_rd_done_generic(hw);
222 [ # # ]: 0 : if (ret_val) {
223 : : /*
224 : : * When auto config read does not complete, do not
225 : : * return with an error. This can happen in situations
226 : : * where there is no eeprom and prevents getting link.
227 : : */
228 : 0 : DEBUGOUT("Auto Read Done did not complete\n");
229 : : }
230 : :
231 : : /* Clear any pending interrupt events. */
232 : 0 : IGC_WRITE_REG(hw, IGC_IMC, 0xffffffff);
233 : 0 : IGC_READ_REG(hw, IGC_ICR);
234 : :
235 : : /* Install any alternate MAC address into RAR0 */
236 : 0 : ret_val = igc_check_alt_mac_addr_generic(hw);
237 : :
238 : 0 : return ret_val;
239 : : }
240 : :
241 : : /* igc_acquire_nvm_i225 - Request for access to EEPROM
242 : : * @hw: pointer to the HW structure
243 : : *
244 : : * Acquire the necessary semaphores for exclusive access to the EEPROM.
245 : : * Set the EEPROM access request bit and wait for EEPROM access grant bit.
246 : : * Return successful if access grant bit set, else clear the request for
247 : : * EEPROM access and return -IGC_ERR_NVM (-1).
248 : : */
249 : 0 : static s32 igc_acquire_nvm_i225(struct igc_hw *hw)
250 : : {
251 : : s32 ret_val;
252 : :
253 : 0 : DEBUGFUNC("igc_acquire_nvm_i225");
254 : :
255 : 0 : ret_val = igc_acquire_swfw_sync_i225(hw, IGC_SWFW_EEP_SM);
256 : :
257 : 0 : return ret_val;
258 : : }
259 : :
260 : : /* igc_release_nvm_i225 - Release exclusive access to EEPROM
261 : : * @hw: pointer to the HW structure
262 : : *
263 : : * Stop any current commands to the EEPROM and clear the EEPROM request bit,
264 : : * then release the semaphores acquired.
265 : : */
266 : 0 : static void igc_release_nvm_i225(struct igc_hw *hw)
267 : : {
268 : 0 : DEBUGFUNC("igc_release_nvm_i225");
269 : :
270 : 0 : igc_release_swfw_sync_i225(hw, IGC_SWFW_EEP_SM);
271 : 0 : }
272 : :
273 : : /* igc_acquire_swfw_sync_i225 - Acquire SW/FW semaphore
274 : : * @hw: pointer to the HW structure
275 : : * @mask: specifies which semaphore to acquire
276 : : *
277 : : * Acquire the SW/FW semaphore to access the PHY or NVM. The mask
278 : : * will also specify which port we're acquiring the lock for.
279 : : */
280 : 0 : s32 igc_acquire_swfw_sync_i225(struct igc_hw *hw, u16 mask)
281 : : {
282 : : u32 swfw_sync;
283 : 0 : u32 swmask = mask;
284 : 0 : u32 fwmask = mask << 16;
285 : : s32 ret_val = IGC_SUCCESS;
286 : : s32 i = 0, timeout = 200; /* FIXME: find real value to use here */
287 : :
288 : 0 : DEBUGFUNC("igc_acquire_swfw_sync_i225");
289 : :
290 [ # # ]: 0 : while (i < timeout) {
291 [ # # ]: 0 : if (igc_get_hw_semaphore_i225(hw)) {
292 : : ret_val = -IGC_ERR_SWFW_SYNC;
293 : 0 : goto out;
294 : : }
295 : :
296 : 0 : swfw_sync = IGC_READ_REG(hw, IGC_SW_FW_SYNC);
297 [ # # ]: 0 : if (!(swfw_sync & (fwmask | swmask)))
298 : : break;
299 : :
300 : : /* Firmware currently using resource (fwmask)
301 : : * or other software thread using resource (swmask)
302 : : */
303 : 0 : igc_put_hw_semaphore_generic(hw);
304 : 0 : msec_delay_irq(5);
305 : 0 : i++;
306 : : }
307 : :
308 [ # # ]: 0 : if (i == timeout) {
309 : 0 : DEBUGOUT("Driver can't access resource, SW_FW_SYNC timeout.\n");
310 : : ret_val = -IGC_ERR_SWFW_SYNC;
311 : 0 : goto out;
312 : : }
313 : :
314 : 0 : swfw_sync |= swmask;
315 : 0 : IGC_WRITE_REG(hw, IGC_SW_FW_SYNC, swfw_sync);
316 : :
317 : 0 : igc_put_hw_semaphore_generic(hw);
318 : :
319 : 0 : out:
320 : 0 : return ret_val;
321 : : }
322 : :
323 : : /* igc_release_swfw_sync_i225 - Release SW/FW semaphore
324 : : * @hw: pointer to the HW structure
325 : : * @mask: specifies which semaphore to acquire
326 : : *
327 : : * Release the SW/FW semaphore used to access the PHY or NVM. The mask
328 : : * will also specify which port we're releasing the lock for.
329 : : */
330 : 0 : void igc_release_swfw_sync_i225(struct igc_hw *hw, u16 mask)
331 : : {
332 : : u32 swfw_sync;
333 : :
334 : 0 : DEBUGFUNC("igc_release_swfw_sync_i225");
335 : :
336 [ # # ]: 0 : while (igc_get_hw_semaphore_i225(hw) != IGC_SUCCESS)
337 : : ; /* Empty */
338 : :
339 : 0 : swfw_sync = IGC_READ_REG(hw, IGC_SW_FW_SYNC);
340 : 0 : swfw_sync &= ~mask;
341 : 0 : IGC_WRITE_REG(hw, IGC_SW_FW_SYNC, swfw_sync);
342 : :
343 : 0 : igc_put_hw_semaphore_generic(hw);
344 : 0 : }
345 : :
346 : : /*
347 : : * igc_setup_copper_link_i225 - Configure copper link settings
348 : : * @hw: pointer to the HW structure
349 : : *
350 : : * Configures the link for auto-neg or forced speed and duplex. Then we check
351 : : * for link, once link is established calls to configure collision distance
352 : : * and flow control are called.
353 : : */
354 : 0 : s32 igc_setup_copper_link_i225(struct igc_hw *hw)
355 : : {
356 : : u32 phpm_reg;
357 : : s32 ret_val;
358 : : u32 ctrl;
359 : :
360 : 0 : DEBUGFUNC("igc_setup_copper_link_i225");
361 : :
362 : 0 : ctrl = IGC_READ_REG(hw, IGC_CTRL);
363 : : ctrl |= IGC_CTRL_SLU;
364 : 0 : ctrl &= ~(IGC_CTRL_FRCSPD | IGC_CTRL_FRCDPX);
365 : 0 : IGC_WRITE_REG(hw, IGC_CTRL, ctrl);
366 : :
367 : 0 : phpm_reg = IGC_READ_REG(hw, IGC_I225_PHPM);
368 : 0 : phpm_reg &= ~IGC_I225_PHPM_GO_LINKD;
369 : 0 : IGC_WRITE_REG(hw, IGC_I225_PHPM, phpm_reg);
370 : :
371 : 0 : ret_val = igc_setup_copper_link_generic(hw);
372 : :
373 : 0 : return ret_val;
374 : : }
375 : :
376 : : /* igc_get_hw_semaphore_i225 - Acquire hardware semaphore
377 : : * @hw: pointer to the HW structure
378 : : *
379 : : * Acquire the HW semaphore to access the PHY or NVM
380 : : */
381 : 0 : static s32 igc_get_hw_semaphore_i225(struct igc_hw *hw)
382 : : {
383 : : u32 swsm;
384 : 0 : s32 timeout = hw->nvm.word_size + 1;
385 : : s32 i = 0;
386 : :
387 : 0 : DEBUGFUNC("igc_get_hw_semaphore_i225");
388 : :
389 : : /* Get the SW semaphore */
390 [ # # ]: 0 : while (i < timeout) {
391 : 0 : swsm = IGC_READ_REG(hw, IGC_SWSM);
392 [ # # ]: 0 : if (!(swsm & IGC_SWSM_SMBI))
393 : : break;
394 : :
395 : 0 : usec_delay(50);
396 : 0 : i++;
397 : : }
398 : :
399 [ # # ]: 0 : if (i == timeout) {
400 : : /* In rare circumstances, the SW semaphore may already be held
401 : : * unintentionally. Clear the semaphore once before giving up.
402 : : */
403 [ # # ]: 0 : if (hw->dev_spec._i225.clear_semaphore_once) {
404 : 0 : hw->dev_spec._i225.clear_semaphore_once = false;
405 : 0 : igc_put_hw_semaphore_generic(hw);
406 [ # # ]: 0 : for (i = 0; i < timeout; i++) {
407 : 0 : swsm = IGC_READ_REG(hw, IGC_SWSM);
408 [ # # ]: 0 : if (!(swsm & IGC_SWSM_SMBI))
409 : : break;
410 : :
411 : 0 : usec_delay(50);
412 : : }
413 : : }
414 : :
415 : : /* If we do not have the semaphore here, we have to give up. */
416 [ # # ]: 0 : if (i == timeout) {
417 : 0 : DEBUGOUT("Driver can't access device -\n");
418 : 0 : DEBUGOUT("SMBI bit is set.\n");
419 : 0 : return -IGC_ERR_NVM;
420 : : }
421 : : }
422 : :
423 : : /* Get the FW semaphore. */
424 [ # # ]: 0 : for (i = 0; i < timeout; i++) {
425 : 0 : swsm = IGC_READ_REG(hw, IGC_SWSM);
426 : 0 : IGC_WRITE_REG(hw, IGC_SWSM, swsm | IGC_SWSM_SWESMBI);
427 : :
428 : : /* Semaphore acquired if bit latched */
429 [ # # ]: 0 : if (IGC_READ_REG(hw, IGC_SWSM) & IGC_SWSM_SWESMBI)
430 : : break;
431 : :
432 : 0 : usec_delay(50);
433 : : }
434 : :
435 [ # # ]: 0 : if (i == timeout) {
436 : : /* Release semaphores */
437 : 0 : igc_put_hw_semaphore_generic(hw);
438 : 0 : DEBUGOUT("Driver can't access the NVM\n");
439 : 0 : return -IGC_ERR_NVM;
440 : : }
441 : :
442 : : return IGC_SUCCESS;
443 : : }
444 : :
445 : : /* igc_read_nvm_srrd_i225 - Reads Shadow Ram using EERD register
446 : : * @hw: pointer to the HW structure
447 : : * @offset: offset of word in the Shadow Ram to read
448 : : * @words: number of words to read
449 : : * @data: word read from the Shadow Ram
450 : : *
451 : : * Reads a 16 bit word from the Shadow Ram using the EERD register.
452 : : * Uses necessary synchronization semaphores.
453 : : */
454 : 0 : s32 igc_read_nvm_srrd_i225(struct igc_hw *hw, u16 offset, u16 words,
455 : : u16 *data)
456 : : {
457 : : s32 status = IGC_SUCCESS;
458 : : u16 i, count;
459 : :
460 : 0 : DEBUGFUNC("igc_read_nvm_srrd_i225");
461 : :
462 : : /* We cannot hold synchronization semaphores for too long,
463 : : * because of forceful takeover procedure. However it is more efficient
464 : : * to read in bursts than synchronizing access for each word.
465 : : */
466 [ # # ]: 0 : for (i = 0; i < words; i += IGC_EERD_EEWR_MAX_COUNT) {
467 : 0 : count = (words - i) / IGC_EERD_EEWR_MAX_COUNT > 0 ?
468 : 0 : IGC_EERD_EEWR_MAX_COUNT : (words - i);
469 [ # # ]: 0 : if (hw->nvm.ops.acquire(hw) == IGC_SUCCESS) {
470 : 0 : status = igc_read_nvm_eerd(hw, offset, count,
471 : 0 : data + i);
472 : 0 : hw->nvm.ops.release(hw);
473 : : } else {
474 : : status = IGC_ERR_SWFW_SYNC;
475 : : }
476 : :
477 [ # # ]: 0 : if (status != IGC_SUCCESS)
478 : : break;
479 : : }
480 : :
481 : 0 : return status;
482 : : }
483 : :
484 : : /* igc_write_nvm_srwr_i225 - Write to Shadow RAM using EEWR
485 : : * @hw: pointer to the HW structure
486 : : * @offset: offset within the Shadow RAM to be written to
487 : : * @words: number of words to write
488 : : * @data: 16 bit word(s) to be written to the Shadow RAM
489 : : *
490 : : * Writes data to Shadow RAM at offset using EEWR register.
491 : : *
492 : : * If igc_update_nvm_checksum is not called after this function , the
493 : : * data will not be committed to FLASH and also Shadow RAM will most likely
494 : : * contain an invalid checksum.
495 : : *
496 : : * If error code is returned, data and Shadow RAM may be inconsistent - buffer
497 : : * partially written.
498 : : */
499 : 0 : s32 igc_write_nvm_srwr_i225(struct igc_hw *hw, u16 offset, u16 words,
500 : : u16 *data)
501 : : {
502 : : s32 status = IGC_SUCCESS;
503 : : u16 i, count;
504 : :
505 : 0 : DEBUGFUNC("igc_write_nvm_srwr_i225");
506 : :
507 : : /* We cannot hold synchronization semaphores for too long,
508 : : * because of forceful takeover procedure. However it is more efficient
509 : : * to write in bursts than synchronizing access for each word.
510 : : */
511 [ # # ]: 0 : for (i = 0; i < words; i += IGC_EERD_EEWR_MAX_COUNT) {
512 : 0 : count = (words - i) / IGC_EERD_EEWR_MAX_COUNT > 0 ?
513 : 0 : IGC_EERD_EEWR_MAX_COUNT : (words - i);
514 [ # # ]: 0 : if (hw->nvm.ops.acquire(hw) == IGC_SUCCESS) {
515 : 0 : status = __igc_write_nvm_srwr(hw, offset, count,
516 : 0 : data + i);
517 : 0 : hw->nvm.ops.release(hw);
518 : : } else {
519 : : status = IGC_ERR_SWFW_SYNC;
520 : : }
521 : :
522 [ # # ]: 0 : if (status != IGC_SUCCESS)
523 : : break;
524 : : }
525 : :
526 : 0 : return status;
527 : : }
528 : :
529 : : /* __igc_write_nvm_srwr - Write to Shadow Ram using EEWR
530 : : * @hw: pointer to the HW structure
531 : : * @offset: offset within the Shadow Ram to be written to
532 : : * @words: number of words to write
533 : : * @data: 16 bit word(s) to be written to the Shadow Ram
534 : : *
535 : : * Writes data to Shadow Ram at offset using EEWR register.
536 : : *
537 : : * If igc_update_nvm_checksum is not called after this function , the
538 : : * Shadow Ram will most likely contain an invalid checksum.
539 : : */
540 : 0 : static s32 __igc_write_nvm_srwr(struct igc_hw *hw, u16 offset, u16 words,
541 : : u16 *data)
542 : : {
543 : : struct igc_nvm_info *nvm = &hw->nvm;
544 : : u32 i, k, eewr = 0;
545 : : u32 attempts = 100000;
546 : : s32 ret_val = IGC_SUCCESS;
547 : :
548 : 0 : DEBUGFUNC("__igc_write_nvm_srwr");
549 : :
550 : : /* A check for invalid values: offset too large, too many words,
551 : : * too many words for the offset, and not enough words.
552 : : */
553 [ # # # # : 0 : if (offset >= nvm->word_size || words > (nvm->word_size - offset) ||
# # ]
554 : : words == 0) {
555 : 0 : DEBUGOUT("nvm parameter(s) out of bounds\n");
556 : : ret_val = -IGC_ERR_NVM;
557 : 0 : goto out;
558 : : }
559 : :
560 [ # # ]: 0 : for (i = 0; i < words; i++) {
561 : 0 : eewr = ((offset + i) << IGC_NVM_RW_ADDR_SHIFT) |
562 : 0 : (data[i] << IGC_NVM_RW_REG_DATA) |
563 : : IGC_NVM_RW_REG_START;
564 : :
565 : 0 : IGC_WRITE_REG(hw, IGC_SRWR, eewr);
566 : :
567 [ # # ]: 0 : for (k = 0; k < attempts; k++) {
568 [ # # ]: 0 : if (IGC_NVM_RW_REG_DONE &
569 : 0 : IGC_READ_REG(hw, IGC_SRWR)) {
570 : : ret_val = IGC_SUCCESS;
571 : : break;
572 : : }
573 : 0 : usec_delay(5);
574 : : }
575 : :
576 : : if (ret_val != IGC_SUCCESS) {
577 : : DEBUGOUT("Shadow RAM write EEWR timed out\n");
578 : : break;
579 : : }
580 : : }
581 : :
582 : 0 : out:
583 : 0 : return ret_val;
584 : : }
585 : :
586 : : /* igc_read_invm_version_i225 - Reads iNVM version and image type
587 : : * @hw: pointer to the HW structure
588 : : * @invm_ver: version structure for the version read
589 : : *
590 : : * Reads iNVM version and image type.
591 : : */
592 : 0 : s32 igc_read_invm_version_i225(struct igc_hw *hw,
593 : : struct igc_fw_version *invm_ver)
594 : : {
595 : : u32 *record = NULL;
596 : : u32 *next_record = NULL;
597 : : u32 i = 0;
598 : : u32 invm_dword = 0;
599 : : u32 invm_blocks = IGC_INVM_SIZE - (IGC_INVM_ULT_BYTES_SIZE /
600 : : IGC_INVM_RECORD_SIZE_IN_BYTES);
601 : : u32 buffer[IGC_INVM_SIZE];
602 : : s32 status = -IGC_ERR_INVM_VALUE_NOT_FOUND;
603 : : u16 version = 0;
604 : :
605 : 0 : DEBUGFUNC("igc_read_invm_version_i225");
606 : :
607 : : /* Read iNVM memory */
608 [ # # ]: 0 : for (i = 0; i < IGC_INVM_SIZE; i++) {
609 : 0 : invm_dword = IGC_READ_REG(hw, IGC_INVM_DATA_REG(i));
610 : 0 : buffer[i] = invm_dword;
611 : : }
612 : :
613 : : /* Read version number */
614 [ # # ]: 0 : for (i = 1; i < invm_blocks; i++) {
615 : 0 : record = &buffer[invm_blocks - i];
616 : 0 : next_record = &buffer[invm_blocks - i + 1];
617 : :
618 : : /* Check if we have first version location used */
619 [ # # # # ]: 0 : if (i == 1 && (*record & IGC_INVM_VER_FIELD_ONE) == 0) {
620 : : version = 0;
621 : : status = IGC_SUCCESS;
622 : : break;
623 : : }
624 : : /* Check if we have second version location used */
625 [ # # ]: 0 : else if ((i == 1) &&
626 [ # # ]: 0 : ((*record & IGC_INVM_VER_FIELD_TWO) == 0)) {
627 : 0 : version = (*record & IGC_INVM_VER_FIELD_ONE) >> 3;
628 : : status = IGC_SUCCESS;
629 : : break;
630 : : }
631 : : /* Check if we have odd version location
632 : : * used and it is the last one used
633 : : */
634 [ # # ]: 0 : else if ((((*record & IGC_INVM_VER_FIELD_ONE) == 0) &&
635 [ # # # # ]: 0 : ((*record & 0x3) == 0)) || (((*record & 0x3) != 0) &&
636 : : (i != 1))) {
637 : 0 : version = (*next_record & IGC_INVM_VER_FIELD_TWO)
638 : 0 : >> 13;
639 : : status = IGC_SUCCESS;
640 : : break;
641 : : }
642 : : /* Check if we have even version location
643 : : * used and it is the last one used
644 : : */
645 [ # # ]: 0 : else if (((*record & IGC_INVM_VER_FIELD_TWO) == 0) &&
646 : : ((*record & 0x3) == 0)) {
647 : 0 : version = (*record & IGC_INVM_VER_FIELD_ONE) >> 3;
648 : : status = IGC_SUCCESS;
649 : : break;
650 : : }
651 : : }
652 : :
653 [ # # ]: 0 : if (status == IGC_SUCCESS) {
654 : 0 : invm_ver->invm_major = (version & IGC_INVM_MAJOR_MASK)
655 : 0 : >> IGC_INVM_MAJOR_SHIFT;
656 : 0 : invm_ver->invm_minor = version & IGC_INVM_MINOR_MASK;
657 : : }
658 : : /* Read Image Type */
659 [ # # ]: 0 : for (i = 1; i < invm_blocks; i++) {
660 : 0 : record = &buffer[invm_blocks - i];
661 : 0 : next_record = &buffer[invm_blocks - i + 1];
662 : :
663 : : /* Check if we have image type in first location used */
664 [ # # # # ]: 0 : if (i == 1 && (*record & IGC_INVM_IMGTYPE_FIELD) == 0) {
665 : 0 : invm_ver->invm_img_type = 0;
666 : : status = IGC_SUCCESS;
667 : 0 : break;
668 : : }
669 : : /* Check if we have image type in first location used */
670 [ # # ]: 0 : else if ((((*record & 0x3) == 0) &&
671 : 0 : ((*record & IGC_INVM_IMGTYPE_FIELD) == 0)) ||
672 [ # # # # ]: 0 : ((((*record & 0x3) != 0) && (i != 1)))) {
673 : 0 : invm_ver->invm_img_type =
674 : 0 : (*next_record & IGC_INVM_IMGTYPE_FIELD) >> 23;
675 : : status = IGC_SUCCESS;
676 : 0 : break;
677 : : }
678 : : }
679 : 0 : return status;
680 : : }
681 : :
682 : : /* igc_validate_nvm_checksum_i225 - Validate EEPROM checksum
683 : : * @hw: pointer to the HW structure
684 : : *
685 : : * Calculates the EEPROM checksum by reading/adding each word of the EEPROM
686 : : * and then verifies that the sum of the EEPROM is equal to 0xBABA.
687 : : */
688 : 0 : s32 igc_validate_nvm_checksum_i225(struct igc_hw *hw)
689 : : {
690 : : s32 status = IGC_SUCCESS;
691 : : s32 (*read_op_ptr)(struct igc_hw *hw, u16 offset,
692 : : u16 count, u16 *data);
693 : :
694 : 0 : DEBUGFUNC("igc_validate_nvm_checksum_i225");
695 : :
696 [ # # ]: 0 : if (hw->nvm.ops.acquire(hw) == IGC_SUCCESS) {
697 : : /* Replace the read function with semaphore grabbing with
698 : : * the one that skips this for a while.
699 : : * We have semaphore taken already here.
700 : : */
701 : 0 : read_op_ptr = hw->nvm.ops.read;
702 : 0 : hw->nvm.ops.read = igc_read_nvm_eerd;
703 : :
704 : 0 : status = igc_validate_nvm_checksum_generic(hw);
705 : :
706 : : /* Revert original read operation. */
707 : 0 : hw->nvm.ops.read = read_op_ptr;
708 : :
709 : 0 : hw->nvm.ops.release(hw);
710 : : } else {
711 : : status = IGC_ERR_SWFW_SYNC;
712 : : }
713 : :
714 : 0 : return status;
715 : : }
716 : :
717 : : /* igc_update_nvm_checksum_i225 - Update EEPROM checksum
718 : : * @hw: pointer to the HW structure
719 : : *
720 : : * Updates the EEPROM checksum by reading/adding each word of the EEPROM
721 : : * up to the checksum. Then calculates the EEPROM checksum and writes the
722 : : * value to the EEPROM. Next commit EEPROM data onto the Flash.
723 : : */
724 : 0 : s32 igc_update_nvm_checksum_i225(struct igc_hw *hw)
725 : : {
726 : : s32 ret_val;
727 : 0 : u16 checksum = 0;
728 : : u16 i, nvm_data;
729 : :
730 : 0 : DEBUGFUNC("igc_update_nvm_checksum_i225");
731 : :
732 : : /* Read the first word from the EEPROM. If this times out or fails, do
733 : : * not continue or we could be in for a very long wait while every
734 : : * EEPROM read fails
735 : : */
736 : 0 : ret_val = igc_read_nvm_eerd(hw, 0, 1, &nvm_data);
737 [ # # ]: 0 : if (ret_val != IGC_SUCCESS) {
738 : 0 : DEBUGOUT("EEPROM read failed\n");
739 : 0 : goto out;
740 : : }
741 : :
742 [ # # ]: 0 : if (hw->nvm.ops.acquire(hw) == IGC_SUCCESS) {
743 : : /* Do not use hw->nvm.ops.write, hw->nvm.ops.read
744 : : * because we do not want to take the synchronization
745 : : * semaphores twice here.
746 : : */
747 : :
748 [ # # ]: 0 : for (i = 0; i < NVM_CHECKSUM_REG; i++) {
749 : 0 : ret_val = igc_read_nvm_eerd(hw, i, 1, &nvm_data);
750 [ # # ]: 0 : if (ret_val) {
751 : 0 : hw->nvm.ops.release(hw);
752 : 0 : DEBUGOUT("NVM Read Error while updating\n");
753 : 0 : DEBUGOUT("checksum.\n");
754 : 0 : goto out;
755 : : }
756 : 0 : checksum += nvm_data;
757 : : }
758 : 0 : checksum = (u16)NVM_SUM - checksum;
759 : 0 : ret_val = __igc_write_nvm_srwr(hw, NVM_CHECKSUM_REG, 1,
760 : : &checksum);
761 [ # # ]: 0 : if (ret_val != IGC_SUCCESS) {
762 : 0 : hw->nvm.ops.release(hw);
763 : 0 : DEBUGOUT("NVM Write Error while updating checksum.\n");
764 : 0 : goto out;
765 : : }
766 : :
767 : 0 : hw->nvm.ops.release(hw);
768 : :
769 : 0 : ret_val = igc_update_flash_i225(hw);
770 : : } else {
771 : : ret_val = IGC_ERR_SWFW_SYNC;
772 : : }
773 : 0 : out:
774 : 0 : return ret_val;
775 : : }
776 : :
777 : : /* igc_get_flash_presence_i225 - Check if flash device is detected.
778 : : * @hw: pointer to the HW structure
779 : : */
780 : 0 : bool igc_get_flash_presence_i225(struct igc_hw *hw)
781 : : {
782 : : u32 eec = 0;
783 : : bool ret_val = false;
784 : :
785 : 0 : DEBUGFUNC("igc_get_flash_presence_i225");
786 : :
787 : 0 : eec = IGC_READ_REG(hw, IGC_EECD);
788 : :
789 [ # # ]: 0 : if (eec & IGC_EECD_FLASH_DETECTED_I225)
790 : : ret_val = true;
791 : :
792 : 0 : return ret_val;
793 : : }
794 : :
795 : : /* igc_set_flsw_flash_burst_counter_i225 - sets FLSW NVM Burst
796 : : * Counter in FLSWCNT register.
797 : : *
798 : : * @hw: pointer to the HW structure
799 : : * @burst_counter: size in bytes of the Flash burst to read or write
800 : : */
801 : 0 : s32 igc_set_flsw_flash_burst_counter_i225(struct igc_hw *hw,
802 : : u32 burst_counter)
803 : : {
804 : : s32 ret_val = IGC_SUCCESS;
805 : :
806 : 0 : DEBUGFUNC("igc_set_flsw_flash_burst_counter_i225");
807 : :
808 : : /* Validate input data */
809 [ # # ]: 0 : if (burst_counter < IGC_I225_SHADOW_RAM_SIZE) {
810 : : /* Write FLSWCNT - burst counter */
811 : 0 : IGC_WRITE_REG(hw, IGC_I225_FLSWCNT, burst_counter);
812 : : } else {
813 : : ret_val = IGC_ERR_INVALID_ARGUMENT;
814 : : }
815 : :
816 : 0 : return ret_val;
817 : : }
818 : :
819 : : /* igc_write_erase_flash_command_i225 - write/erase to a sector
820 : : * region on a given address.
821 : : *
822 : : * @hw: pointer to the HW structure
823 : : * @opcode: opcode to be used for the write command
824 : : * @address: the offset to write into the FLASH image
825 : : */
826 : 0 : s32 igc_write_erase_flash_command_i225(struct igc_hw *hw, u32 opcode,
827 : : u32 address)
828 : : {
829 : : u32 flswctl = 0;
830 : : s32 timeout = IGC_NVM_GRANT_ATTEMPTS;
831 : : s32 ret_val = IGC_SUCCESS;
832 : :
833 : 0 : DEBUGFUNC("igc_write_erase_flash_command_i225");
834 : :
835 : 0 : flswctl = IGC_READ_REG(hw, IGC_I225_FLSWCTL);
836 : : /* Polling done bit on FLSWCTL register */
837 [ # # ]: 0 : while (timeout) {
838 [ # # ]: 0 : if (flswctl & IGC_FLSWCTL_DONE)
839 : : break;
840 : 0 : usec_delay(5);
841 : 0 : flswctl = IGC_READ_REG(hw, IGC_I225_FLSWCTL);
842 : 0 : timeout--;
843 : : }
844 : :
845 [ # # ]: 0 : if (!timeout) {
846 : 0 : DEBUGOUT("Flash transaction was not done\n");
847 : 0 : return -IGC_ERR_NVM;
848 : : }
849 : :
850 : : /* Build and issue command on FLSWCTL register */
851 : 0 : flswctl = address | opcode;
852 : 0 : IGC_WRITE_REG(hw, IGC_I225_FLSWCTL, flswctl);
853 : :
854 : : /* Check if issued command is valid on FLSWCTL register */
855 : 0 : flswctl = IGC_READ_REG(hw, IGC_I225_FLSWCTL);
856 [ # # ]: 0 : if (!(flswctl & IGC_FLSWCTL_CMDV)) {
857 : 0 : DEBUGOUT("Write flash command failed\n");
858 : : ret_val = IGC_ERR_INVALID_ARGUMENT;
859 : : }
860 : :
861 : : return ret_val;
862 : : }
863 : :
864 : : /* igc_update_flash_i225 - Commit EEPROM to the flash
865 : : * if fw_valid_bit is set, FW is active. setting FLUPD bit in EEC
866 : : * register makes the FW load the internal shadow RAM into the flash.
867 : : * Otherwise, fw_valid_bit is 0. if FL_SECU.block_prtotected_sw = 0
868 : : * then FW is not active so the SW is responsible shadow RAM dump.
869 : : *
870 : : * @hw: pointer to the HW structure
871 : : */
872 : 0 : s32 igc_update_flash_i225(struct igc_hw *hw)
873 : : {
874 : 0 : u16 current_offset_data = 0;
875 : : u32 block_sw_protect = 1;
876 : : u16 base_address = 0x0;
877 : : u32 i, fw_valid_bit;
878 : : u16 current_offset;
879 : : s32 ret_val = 0;
880 : : u32 flup;
881 : :
882 : 0 : DEBUGFUNC("igc_update_flash_i225");
883 : :
884 : 0 : block_sw_protect = IGC_READ_REG(hw, IGC_I225_FLSECU) &
885 : : IGC_FLSECU_BLK_SW_ACCESS_I225;
886 : 0 : fw_valid_bit = IGC_READ_REG(hw, IGC_FWSM) &
887 : : IGC_FWSM_FW_VALID_I225;
888 [ # # ]: 0 : if (fw_valid_bit) {
889 : 0 : ret_val = igc_pool_flash_update_done_i225(hw);
890 [ # # ]: 0 : if (ret_val == -IGC_ERR_NVM) {
891 : 0 : DEBUGOUT("Flash update time out\n");
892 : 0 : goto out;
893 : : }
894 : :
895 : 0 : flup = IGC_READ_REG(hw, IGC_EECD) | IGC_EECD_FLUPD_I225;
896 : 0 : IGC_WRITE_REG(hw, IGC_EECD, flup);
897 : :
898 : 0 : ret_val = igc_pool_flash_update_done_i225(hw);
899 [ # # ]: 0 : if (ret_val == IGC_SUCCESS)
900 : 0 : DEBUGOUT("Flash update complete\n");
901 : : else
902 : 0 : DEBUGOUT("Flash update time out\n");
903 [ # # ]: 0 : } else if (!block_sw_protect) {
904 : : /* FW is not active and security protection is disabled.
905 : : * therefore, SW is in charge of shadow RAM dump.
906 : : * Check which sector is valid. if sector 0 is valid,
907 : : * base address remains 0x0. otherwise, sector 1 is
908 : : * valid and it's base address is 0x1000
909 : : */
910 [ # # ]: 0 : if (IGC_READ_REG(hw, IGC_EECD) & IGC_EECD_SEC1VAL_I225)
911 : : base_address = 0x1000;
912 : :
913 : : /* Valid sector erase */
914 : 0 : ret_val = igc_write_erase_flash_command_i225(hw,
915 : : IGC_I225_ERASE_CMD_OPCODE,
916 : : base_address);
917 [ # # ]: 0 : if (!ret_val) {
918 : 0 : DEBUGOUT("Sector erase failed\n");
919 : 0 : goto out;
920 : : }
921 : :
922 : : current_offset = base_address;
923 : :
924 : : /* Write */
925 [ # # ]: 0 : for (i = 0; i < IGC_I225_SHADOW_RAM_SIZE / 2; i++) {
926 : : /* Set burst write length */
927 : 0 : ret_val = igc_set_flsw_flash_burst_counter_i225(hw,
928 : : 0x2);
929 [ # # ]: 0 : if (ret_val != IGC_SUCCESS)
930 : : break;
931 : :
932 : : /* Set address and opcode */
933 : 0 : ret_val = igc_write_erase_flash_command_i225(hw,
934 : : IGC_I225_WRITE_CMD_OPCODE,
935 : 0 : 2 * current_offset);
936 [ # # ]: 0 : if (ret_val != IGC_SUCCESS)
937 : : break;
938 : :
939 : 0 : ret_val = igc_read_nvm_eerd(hw, current_offset,
940 : : 1, ¤t_offset_data);
941 [ # # ]: 0 : if (ret_val) {
942 : 0 : DEBUGOUT("Failed to read from EEPROM\n");
943 : 0 : goto out;
944 : : }
945 : :
946 : : /* Write CurrentOffseData to FLSWDATA register */
947 : 0 : IGC_WRITE_REG(hw, IGC_I225_FLSWDATA,
948 : : current_offset_data);
949 : 0 : current_offset++;
950 : :
951 : : /* Wait till operation has finished */
952 : 0 : ret_val = igc_poll_eerd_eewr_done(hw,
953 : : IGC_NVM_POLL_READ);
954 [ # # ]: 0 : if (ret_val)
955 : : break;
956 : :
957 : 0 : usec_delay(1000);
958 : : }
959 : : }
960 : 0 : out:
961 : 0 : return ret_val;
962 : : }
963 : :
964 : : /* igc_pool_flash_update_done_i225 - Pool FLUDONE status.
965 : : * @hw: pointer to the HW structure
966 : : */
967 : 0 : s32 igc_pool_flash_update_done_i225(struct igc_hw *hw)
968 : : {
969 : : s32 ret_val = -IGC_ERR_NVM;
970 : : u32 i, reg;
971 : :
972 : 0 : DEBUGFUNC("igc_pool_flash_update_done_i225");
973 : :
974 [ # # ]: 0 : for (i = 0; i < IGC_FLUDONE_ATTEMPTS; i++) {
975 : 0 : reg = IGC_READ_REG(hw, IGC_EECD);
976 [ # # ]: 0 : if (reg & IGC_EECD_FLUDONE_I225) {
977 : : ret_val = IGC_SUCCESS;
978 : : break;
979 : : }
980 : 0 : usec_delay(5);
981 : : }
982 : :
983 : 0 : return ret_val;
984 : : }
985 : :
986 : : /* igc_set_ltr_i225 - Set Latency Tolerance Reporting thresholds.
987 : : * @hw: pointer to the HW structure
988 : : * @link: bool indicating link status
989 : : *
990 : : * Set the LTR thresholds based on the link speed (Mbps), EEE, and DMAC
991 : : * settings, otherwise specify that there is no LTR requirement.
992 : : */
993 : 0 : static s32 igc_set_ltr_i225(struct igc_hw *hw, bool link)
994 : : {
995 : : u16 speed, duplex;
996 : : u32 tw_system, ltrc, ltrv, ltr_min, ltr_max, scale_min, scale_max;
997 : : s32 size;
998 : :
999 : 0 : DEBUGFUNC("igc_set_ltr_i225");
1000 : :
1001 : : /* If we do not have link, LTR thresholds are zero. */
1002 [ # # ]: 0 : if (link) {
1003 : 0 : hw->mac.ops.get_link_up_info(hw, &speed, &duplex);
1004 : :
1005 : : /* Check if using copper interface with EEE enabled or if the
1006 : : * link speed is 10 Mbps.
1007 : : */
1008 [ # # ]: 0 : if (hw->phy.media_type == igc_media_type_copper &&
1009 [ # # ]: 0 : !hw->dev_spec._i225.eee_disable &&
1010 [ # # ]: 0 : speed != SPEED_10) {
1011 : : /* EEE enabled, so send LTRMAX threshold. */
1012 : 0 : ltrc = IGC_READ_REG(hw, IGC_LTRC) |
1013 : : IGC_LTRC_EEEMS_EN;
1014 : 0 : IGC_WRITE_REG(hw, IGC_LTRC, ltrc);
1015 : :
1016 : : /* Calculate tw_system (nsec). */
1017 [ # # ]: 0 : if (speed == SPEED_100)
1018 : 0 : tw_system = ((IGC_READ_REG(hw, IGC_EEE_SU) &
1019 : 0 : IGC_TW_SYSTEM_100_MASK) >>
1020 : : IGC_TW_SYSTEM_100_SHIFT) * 500;
1021 : : else
1022 : 0 : tw_system = (IGC_READ_REG(hw, IGC_EEE_SU) &
1023 : : IGC_TW_SYSTEM_1000_MASK) * 500;
1024 : : } else {
1025 : : tw_system = 0;
1026 : : }
1027 : :
1028 : : /* Get the Rx packet buffer size. */
1029 : 0 : size = IGC_READ_REG(hw, IGC_RXPBS) &
1030 : : IGC_RXPBS_SIZE_I225_MASK;
1031 : :
1032 : : /* Calculations vary based on DMAC settings. */
1033 [ # # ]: 0 : if (IGC_READ_REG(hw, IGC_DMACR) & IGC_DMACR_DMAC_EN) {
1034 : 0 : size -= (IGC_READ_REG(hw, IGC_DMACR) &
1035 : 0 : IGC_DMACR_DMACTHR_MASK) >>
1036 : : IGC_DMACR_DMACTHR_SHIFT;
1037 : : /* Convert size to bits. */
1038 : 0 : size *= 1024 * 8;
1039 : : } else {
1040 : : /* Convert size to bytes, subtract the MTU, and then
1041 : : * convert the size to bits.
1042 : : */
1043 : 0 : size *= 1024;
1044 : 0 : size -= hw->dev_spec._i225.mtu;
1045 : 0 : size *= 8;
1046 : : }
1047 : :
1048 [ # # ]: 0 : if (size < 0) {
1049 : 0 : DEBUGOUT1("Invalid effective Rx buffer size %d\n",
1050 : : size);
1051 : 0 : return -IGC_ERR_CONFIG;
1052 : : }
1053 : :
1054 : : /* Calculate the thresholds. Since speed is in Mbps, simplify
1055 : : * the calculation by multiplying size/speed by 1000 for result
1056 : : * to be in nsec before dividing by the scale in nsec. Set the
1057 : : * scale such that the LTR threshold fits in the register.
1058 : : */
1059 : 0 : ltr_min = (1000 * size) / speed;
1060 : 0 : ltr_max = ltr_min + tw_system;
1061 [ # # ]: 0 : scale_min = (ltr_min / 1024) < 1024 ? IGC_LTRMINV_SCALE_1024 :
1062 : : IGC_LTRMINV_SCALE_32768;
1063 [ # # ]: 0 : scale_max = (ltr_max / 1024) < 1024 ? IGC_LTRMAXV_SCALE_1024 :
1064 : : IGC_LTRMAXV_SCALE_32768;
1065 [ # # ]: 0 : ltr_min /= scale_min == IGC_LTRMINV_SCALE_1024 ? 1024 : 32768;
1066 [ # # ]: 0 : ltr_max /= scale_max == IGC_LTRMAXV_SCALE_1024 ? 1024 : 32768;
1067 : :
1068 : : /* Only write the LTR thresholds if they differ from before. */
1069 : 0 : ltrv = IGC_READ_REG(hw, IGC_LTRMINV);
1070 [ # # ]: 0 : if (ltr_min != (ltrv & IGC_LTRMINV_LTRV_MASK)) {
1071 : 0 : ltrv = IGC_LTRMINV_LSNP_REQ | ltr_min |
1072 : 0 : (scale_min << IGC_LTRMINV_SCALE_SHIFT);
1073 : 0 : IGC_WRITE_REG(hw, IGC_LTRMINV, ltrv);
1074 : : }
1075 : :
1076 : 0 : ltrv = IGC_READ_REG(hw, IGC_LTRMAXV);
1077 [ # # ]: 0 : if (ltr_max != (ltrv & IGC_LTRMAXV_LTRV_MASK)) {
1078 : 0 : ltrv = IGC_LTRMAXV_LSNP_REQ | ltr_max |
1079 : 0 : (scale_min << IGC_LTRMAXV_SCALE_SHIFT);
1080 : 0 : IGC_WRITE_REG(hw, IGC_LTRMAXV, ltrv);
1081 : : }
1082 : : }
1083 : :
1084 : : return IGC_SUCCESS;
1085 : : }
1086 : :
1087 : : /* igc_check_for_link_i225 - Check for link
1088 : : * @hw: pointer to the HW structure
1089 : : *
1090 : : * Checks to see of the link status of the hardware has changed. If a
1091 : : * change in link status has been detected, then we read the PHY registers
1092 : : * to get the current speed/duplex if link exists.
1093 : : */
1094 : 0 : s32 igc_check_for_link_i225(struct igc_hw *hw)
1095 : : {
1096 : : struct igc_mac_info *mac = &hw->mac;
1097 : : s32 ret_val;
1098 : 0 : bool link = false;
1099 : :
1100 : 0 : DEBUGFUNC("igc_check_for_link_i225");
1101 : :
1102 : : /* We only want to go out to the PHY registers to see if
1103 : : * Auto-Neg has completed and/or if our link status has
1104 : : * changed. The get_link_status flag is set upon receiving
1105 : : * a Link Status Change or Rx Sequence Error interrupt.
1106 : : */
1107 [ # # ]: 0 : if (!mac->get_link_status) {
1108 : : ret_val = IGC_SUCCESS;
1109 : 0 : goto out;
1110 : : }
1111 : :
1112 : : /* First we want to see if the MII Status Register reports
1113 : : * link. If so, then we want to get the current speed/duplex
1114 : : * of the PHY.
1115 : : */
1116 : 0 : ret_val = igc_phy_has_link_generic(hw, 1, 0, &link);
1117 [ # # ]: 0 : if (ret_val)
1118 : 0 : goto out;
1119 : :
1120 [ # # ]: 0 : if (!link)
1121 : 0 : goto out; /* No link detected */
1122 : :
1123 : 0 : mac->get_link_status = false;
1124 : :
1125 : : /* Check if there was DownShift, must be checked
1126 : : * immediately after link-up
1127 : : */
1128 : 0 : igc_check_downshift_generic(hw);
1129 : :
1130 : : /* If we are forcing speed/duplex, then we simply return since
1131 : : * we have already determined whether we have link or not.
1132 : : */
1133 [ # # ]: 0 : if (!mac->autoneg)
1134 : 0 : goto out;
1135 : :
1136 : : /* Auto-Neg is enabled. Auto Speed Detection takes care
1137 : : * of MAC speed/duplex configuration. So we only need to
1138 : : * configure Collision Distance in the MAC.
1139 : : */
1140 : 0 : mac->ops.config_collision_dist(hw);
1141 : :
1142 : : /* Configure Flow Control now that Auto-Neg has completed.
1143 : : * First, we need to restore the desired flow control
1144 : : * settings because we may have had to re-autoneg with a
1145 : : * different link partner.
1146 : : */
1147 : 0 : ret_val = igc_config_fc_after_link_up_generic(hw);
1148 [ # # ]: 0 : if (ret_val)
1149 : 0 : DEBUGOUT("Error configuring flow control\n");
1150 : 0 : out:
1151 : : /* Now that we are aware of our link settings, we can set the LTR
1152 : : * thresholds.
1153 : : */
1154 : 0 : ret_val = igc_set_ltr_i225(hw, link);
1155 : :
1156 : 0 : return ret_val;
1157 : : }
1158 : :
1159 : : /* igc_init_function_pointers_i225 - Init func ptrs.
1160 : : * @hw: pointer to the HW structure
1161 : : *
1162 : : * Called to initialize all function pointers and parameters.
1163 : : */
1164 : 0 : void igc_init_function_pointers_i225(struct igc_hw *hw)
1165 : : {
1166 : 0 : igc_init_mac_ops_generic(hw);
1167 : 0 : igc_init_phy_ops_generic(hw);
1168 : 0 : igc_init_nvm_ops_generic(hw);
1169 : 0 : hw->mac.ops.init_params = igc_init_mac_params_i225;
1170 : 0 : hw->nvm.ops.init_params = igc_init_nvm_params_i225;
1171 : 0 : hw->phy.ops.init_params = igc_init_phy_params_i225;
1172 : 0 : }
1173 : :
1174 : : /* igc_valid_led_default_i225 - Verify a valid default LED config
1175 : : * @hw: pointer to the HW structure
1176 : : * @data: pointer to the NVM (EEPROM)
1177 : : *
1178 : : * Read the EEPROM for the current default LED configuration. If the
1179 : : * LED configuration is not valid, set to a valid LED configuration.
1180 : : */
1181 : 0 : static s32 igc_valid_led_default_i225(struct igc_hw *hw, u16 *data)
1182 : : {
1183 : : s32 ret_val;
1184 : :
1185 : 0 : DEBUGFUNC("igc_valid_led_default_i225");
1186 : :
1187 : 0 : ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data);
1188 [ # # ]: 0 : if (ret_val) {
1189 : 0 : DEBUGOUT("NVM Read Error\n");
1190 : 0 : goto out;
1191 : : }
1192 : :
1193 [ # # ]: 0 : if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) {
1194 [ # # ]: 0 : switch (hw->phy.media_type) {
1195 : 0 : case igc_media_type_internal_serdes:
1196 : 0 : *data = ID_LED_DEFAULT_I225_SERDES;
1197 : 0 : break;
1198 : 0 : case igc_media_type_copper:
1199 : : default:
1200 : 0 : *data = ID_LED_DEFAULT_I225;
1201 : 0 : break;
1202 : : }
1203 : : }
1204 : 0 : out:
1205 : 0 : return ret_val;
1206 : : }
1207 : :
1208 : : /* igc_get_cfg_done_i225 - Read config done bit
1209 : : * @hw: pointer to the HW structure
1210 : : *
1211 : : * Read the management control register for the config done bit for
1212 : : * completion status. NOTE: silicon which is EEPROM-less will fail trying
1213 : : * to read the config done bit, so an error is *ONLY* logged and returns
1214 : : * IGC_SUCCESS. If we were to return with error, EEPROM-less silicon
1215 : : * would not be able to be reset or change link.
1216 : : */
1217 : 0 : static s32 igc_get_cfg_done_i225(struct igc_hw *hw)
1218 : : {
1219 : : s32 timeout = PHY_CFG_TIMEOUT;
1220 : : u32 mask = IGC_NVM_CFG_DONE_PORT_0;
1221 : :
1222 : 0 : DEBUGFUNC("igc_get_cfg_done_i225");
1223 : :
1224 [ # # ]: 0 : while (timeout) {
1225 [ # # ]: 0 : if (IGC_READ_REG(hw, IGC_EEMNGCTL_I225) & mask)
1226 : : break;
1227 : 0 : msec_delay(1);
1228 : 0 : timeout--;
1229 : : }
1230 [ # # ]: 0 : if (!timeout)
1231 : 0 : DEBUGOUT("MNG configuration cycle has not completed.\n");
1232 : :
1233 : 0 : return IGC_SUCCESS;
1234 : : }
1235 : :
1236 : : /* igc_init_hw_i225 - Init hw for I225
1237 : : * @hw: pointer to the HW structure
1238 : : *
1239 : : * Called to initialize hw for i225 hw family.
1240 : : */
1241 : 0 : s32 igc_init_hw_i225(struct igc_hw *hw)
1242 : : {
1243 : : s32 ret_val;
1244 : :
1245 : 0 : DEBUGFUNC("igc_init_hw_i225");
1246 : :
1247 : 0 : hw->phy.ops.get_cfg_done = igc_get_cfg_done_i225;
1248 : 0 : ret_val = igc_init_hw_base(hw);
1249 : 0 : igc_set_eee_i225(hw, false, false, false);
1250 : 0 : return ret_val;
1251 : : }
1252 : :
1253 : : /*
1254 : : * igc_set_d0_lplu_state_i225 - Set Low-Power-Link-Up (LPLU) D0 state
1255 : : * @hw: pointer to the HW structure
1256 : : * @active: true to enable LPLU, false to disable
1257 : : *
1258 : : * Note: since I225 does not actually support LPLU, this function
1259 : : * simply enables/disables 1G and 2.5G speeds in D0.
1260 : : */
1261 : 0 : s32 igc_set_d0_lplu_state_i225(struct igc_hw *hw, bool active)
1262 : : {
1263 : : u32 data;
1264 : :
1265 : 0 : DEBUGFUNC("igc_set_d0_lplu_state_i225");
1266 : :
1267 : 0 : data = IGC_READ_REG(hw, IGC_I225_PHPM);
1268 : :
1269 [ # # ]: 0 : if (active) {
1270 : : data |= IGC_I225_PHPM_DIS_1000;
1271 : 0 : data |= IGC_I225_PHPM_DIS_2500;
1272 : : } else {
1273 : : data &= ~IGC_I225_PHPM_DIS_1000;
1274 : 0 : data &= ~IGC_I225_PHPM_DIS_2500;
1275 : : }
1276 : :
1277 : 0 : IGC_WRITE_REG(hw, IGC_I225_PHPM, data);
1278 : 0 : return IGC_SUCCESS;
1279 : : }
1280 : :
1281 : : /*
1282 : : * igc_set_d3_lplu_state_i225 - Set Low-Power-Link-Up (LPLU) D3 state
1283 : : * @hw: pointer to the HW structure
1284 : : * @active: true to enable LPLU, false to disable
1285 : : *
1286 : : * Note: since I225 does not actually support LPLU, this function
1287 : : * simply enables/disables 100M, 1G and 2.5G speeds in D3.
1288 : : */
1289 : 0 : s32 igc_set_d3_lplu_state_i225(struct igc_hw *hw, bool active)
1290 : : {
1291 : : u32 data;
1292 : :
1293 : 0 : DEBUGFUNC("igc_set_d3_lplu_state_i225");
1294 : :
1295 : 0 : data = IGC_READ_REG(hw, IGC_I225_PHPM);
1296 : :
1297 [ # # ]: 0 : if (active) {
1298 : : data |= IGC_I225_PHPM_DIS_100_D3;
1299 : : data |= IGC_I225_PHPM_DIS_1000_D3;
1300 : 0 : data |= IGC_I225_PHPM_DIS_2500_D3;
1301 : : } else {
1302 : : data &= ~IGC_I225_PHPM_DIS_100_D3;
1303 : : data &= ~IGC_I225_PHPM_DIS_1000_D3;
1304 : 0 : data &= ~IGC_I225_PHPM_DIS_2500_D3;
1305 : : }
1306 : :
1307 : 0 : IGC_WRITE_REG(hw, IGC_I225_PHPM, data);
1308 : 0 : return IGC_SUCCESS;
1309 : : }
1310 : :
1311 : : /**
1312 : : * igc_set_eee_i225 - Enable/disable EEE support
1313 : : * @hw: pointer to the HW structure
1314 : : * @adv2p5G: boolean flag enabling 2.5G EEE advertisement
1315 : : * @adv1G: boolean flag enabling 1G EEE advertisement
1316 : : * @adv100M: boolean flag enabling 100M EEE advertisement
1317 : : *
1318 : : * Enable/disable EEE based on setting in dev_spec structure.
1319 : : *
1320 : : **/
1321 : 0 : s32 igc_set_eee_i225(struct igc_hw *hw, bool adv2p5G, bool adv1G,
1322 : : bool adv100M)
1323 : : {
1324 : : u32 ipcnfg, eeer;
1325 : :
1326 : 0 : DEBUGFUNC("igc_set_eee_i225");
1327 : :
1328 [ # # ]: 0 : if (hw->mac.type != igc_i225 ||
1329 [ # # ]: 0 : hw->phy.media_type != igc_media_type_copper)
1330 : 0 : goto out;
1331 : 0 : ipcnfg = IGC_READ_REG(hw, IGC_IPCNFG);
1332 : 0 : eeer = IGC_READ_REG(hw, IGC_EEER);
1333 : :
1334 : : /* enable or disable per user setting */
1335 [ # # ]: 0 : if (!(hw->dev_spec._i225.eee_disable)) {
1336 : 0 : u32 eee_su = IGC_READ_REG(hw, IGC_EEE_SU);
1337 : :
1338 [ # # ]: 0 : if (adv100M)
1339 : 0 : ipcnfg |= IGC_IPCNFG_EEE_100M_AN;
1340 : : else
1341 : 0 : ipcnfg &= ~IGC_IPCNFG_EEE_100M_AN;
1342 : :
1343 [ # # ]: 0 : if (adv1G)
1344 : 0 : ipcnfg |= IGC_IPCNFG_EEE_1G_AN;
1345 : : else
1346 : 0 : ipcnfg &= ~IGC_IPCNFG_EEE_1G_AN;
1347 : :
1348 [ # # ]: 0 : if (adv2p5G)
1349 : 0 : ipcnfg |= IGC_IPCNFG_EEE_2_5G_AN;
1350 : : else
1351 : 0 : ipcnfg &= ~IGC_IPCNFG_EEE_2_5G_AN;
1352 : :
1353 : 0 : eeer |= (IGC_EEER_TX_LPI_EN | IGC_EEER_RX_LPI_EN |
1354 : : IGC_EEER_LPI_FC);
1355 : :
1356 : : /* This bit should not be set in normal operation. */
1357 [ # # ]: 0 : if (eee_su & IGC_EEE_SU_LPI_CLK_STP)
1358 : 0 : DEBUGOUT("LPI Clock Stop Bit should not be set!\n");
1359 : : } else {
1360 : 0 : ipcnfg &= ~(IGC_IPCNFG_EEE_2_5G_AN | IGC_IPCNFG_EEE_1G_AN |
1361 : : IGC_IPCNFG_EEE_100M_AN);
1362 : 0 : eeer &= ~(IGC_EEER_TX_LPI_EN | IGC_EEER_RX_LPI_EN |
1363 : : IGC_EEER_LPI_FC);
1364 : : }
1365 : 0 : IGC_WRITE_REG(hw, IGC_IPCNFG, ipcnfg);
1366 : 0 : IGC_WRITE_REG(hw, IGC_EEER, eeer);
1367 : 0 : IGC_READ_REG(hw, IGC_IPCNFG);
1368 : 0 : IGC_READ_REG(hw, IGC_EEER);
1369 : 0 : out:
1370 : :
1371 : 0 : return IGC_SUCCESS;
1372 : : }
|