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 void igc_reload_nvm_generic(struct igc_hw *hw);
8 : :
9 : : /**
10 : : * igc_init_nvm_ops_generic - Initialize NVM function pointers
11 : : * @hw: pointer to the HW structure
12 : : *
13 : : * Setups up the function pointers to no-op functions
14 : : **/
15 : 0 : void igc_init_nvm_ops_generic(struct igc_hw *hw)
16 : : {
17 : : struct igc_nvm_info *nvm = &hw->nvm;
18 : 0 : DEBUGFUNC("igc_init_nvm_ops_generic");
19 : :
20 : : /* Initialize function pointers */
21 : 0 : nvm->ops.init_params = igc_null_ops_generic;
22 : 0 : nvm->ops.acquire = igc_null_ops_generic;
23 : 0 : nvm->ops.read = igc_null_read_nvm;
24 : 0 : nvm->ops.release = igc_null_nvm_generic;
25 : 0 : nvm->ops.reload = igc_reload_nvm_generic;
26 : 0 : nvm->ops.update = igc_null_ops_generic;
27 : 0 : nvm->ops.valid_led_default = igc_null_led_default;
28 : 0 : nvm->ops.validate = igc_null_ops_generic;
29 : 0 : nvm->ops.write = igc_null_write_nvm;
30 : 0 : }
31 : :
32 : : /**
33 : : * igc_null_nvm_read - No-op function, return 0
34 : : * @hw: pointer to the HW structure
35 : : * @a: dummy variable
36 : : * @b: dummy variable
37 : : * @c: dummy variable
38 : : **/
39 : 0 : s32 igc_null_read_nvm(struct igc_hw IGC_UNUSEDARG * hw,
40 : : u16 IGC_UNUSEDARG a, u16 IGC_UNUSEDARG b,
41 : : u16 IGC_UNUSEDARG * c)
42 : : {
43 : 0 : DEBUGFUNC("igc_null_read_nvm");
44 : : UNREFERENCED_4PARAMETER(hw, a, b, c);
45 : 0 : return IGC_SUCCESS;
46 : : }
47 : :
48 : : /**
49 : : * igc_null_nvm_generic - No-op function, return void
50 : : * @hw: pointer to the HW structure
51 : : **/
52 : 0 : void igc_null_nvm_generic(struct igc_hw IGC_UNUSEDARG * hw)
53 : : {
54 : 0 : DEBUGFUNC("igc_null_nvm_generic");
55 : : UNREFERENCED_1PARAMETER(hw);
56 : 0 : }
57 : :
58 : : /**
59 : : * igc_null_led_default - No-op function, return 0
60 : : * @hw: pointer to the HW structure
61 : : * @data: dummy variable
62 : : **/
63 : 0 : s32 igc_null_led_default(struct igc_hw IGC_UNUSEDARG * hw,
64 : : u16 IGC_UNUSEDARG * data)
65 : : {
66 : 0 : DEBUGFUNC("igc_null_led_default");
67 : : UNREFERENCED_2PARAMETER(hw, data);
68 : 0 : return IGC_SUCCESS;
69 : : }
70 : :
71 : : /**
72 : : * igc_null_write_nvm - No-op function, return 0
73 : : * @hw: pointer to the HW structure
74 : : * @a: dummy variable
75 : : * @b: dummy variable
76 : : * @c: dummy variable
77 : : **/
78 : 0 : s32 igc_null_write_nvm(struct igc_hw IGC_UNUSEDARG * hw,
79 : : u16 IGC_UNUSEDARG a, u16 IGC_UNUSEDARG b,
80 : : u16 IGC_UNUSEDARG * c)
81 : : {
82 : 0 : DEBUGFUNC("igc_null_write_nvm");
83 : : UNREFERENCED_4PARAMETER(hw, a, b, c);
84 : 0 : return IGC_SUCCESS;
85 : : }
86 : :
87 : : /**
88 : : * igc_raise_eec_clk - Raise EEPROM clock
89 : : * @hw: pointer to the HW structure
90 : : * @eecd: pointer to the EEPROM
91 : : *
92 : : * Enable/Raise the EEPROM clock bit.
93 : : **/
94 : : static void igc_raise_eec_clk(struct igc_hw *hw, u32 *eecd)
95 : : {
96 : 0 : *eecd = *eecd | IGC_EECD_SK;
97 : 0 : IGC_WRITE_REG(hw, IGC_EECD, *eecd);
98 : 0 : IGC_WRITE_FLUSH(hw);
99 : 0 : usec_delay(hw->nvm.delay_usec);
100 : : }
101 : :
102 : : /**
103 : : * igc_lower_eec_clk - Lower EEPROM clock
104 : : * @hw: pointer to the HW structure
105 : : * @eecd: pointer to the EEPROM
106 : : *
107 : : * Clear/Lower the EEPROM clock bit.
108 : : **/
109 : : static void igc_lower_eec_clk(struct igc_hw *hw, u32 *eecd)
110 : : {
111 : 0 : *eecd = *eecd & ~IGC_EECD_SK;
112 : 0 : IGC_WRITE_REG(hw, IGC_EECD, *eecd);
113 : 0 : IGC_WRITE_FLUSH(hw);
114 : 0 : usec_delay(hw->nvm.delay_usec);
115 : 0 : }
116 : :
117 : : /**
118 : : * igc_shift_out_eec_bits - Shift data bits our to the EEPROM
119 : : * @hw: pointer to the HW structure
120 : : * @data: data to send to the EEPROM
121 : : * @count: number of bits to shift out
122 : : *
123 : : * We need to shift 'count' bits out to the EEPROM. So, the value in the
124 : : * "data" parameter will be shifted out to the EEPROM one bit at a time.
125 : : * In order to do this, "data" must be broken down into bits.
126 : : **/
127 : 0 : static void igc_shift_out_eec_bits(struct igc_hw *hw, u16 data, u16 count)
128 : : {
129 : : struct igc_nvm_info *nvm = &hw->nvm;
130 : 0 : u32 eecd = IGC_READ_REG(hw, IGC_EECD);
131 : : u32 mask;
132 : :
133 : 0 : DEBUGFUNC("igc_shift_out_eec_bits");
134 : :
135 : 0 : mask = 0x01 << (count - 1);
136 [ # # ]: 0 : if (nvm->type == igc_nvm_eeprom_microwire)
137 : 0 : eecd &= ~IGC_EECD_DO;
138 [ # # ]: 0 : else if (nvm->type == igc_nvm_eeprom_spi)
139 : 0 : eecd |= IGC_EECD_DO;
140 : :
141 : : do {
142 : 0 : eecd &= ~IGC_EECD_DI;
143 : :
144 [ # # ]: 0 : if (data & mask)
145 : 0 : eecd |= IGC_EECD_DI;
146 : :
147 : 0 : IGC_WRITE_REG(hw, IGC_EECD, eecd);
148 : 0 : IGC_WRITE_FLUSH(hw);
149 : :
150 : 0 : usec_delay(nvm->delay_usec);
151 : :
152 : : igc_raise_eec_clk(hw, &eecd);
153 : : igc_lower_eec_clk(hw, &eecd);
154 : :
155 : 0 : mask >>= 1;
156 [ # # ]: 0 : } while (mask);
157 : :
158 : 0 : eecd &= ~IGC_EECD_DI;
159 : 0 : IGC_WRITE_REG(hw, IGC_EECD, eecd);
160 : 0 : }
161 : :
162 : : /**
163 : : * igc_shift_in_eec_bits - Shift data bits in from the EEPROM
164 : : * @hw: pointer to the HW structure
165 : : * @count: number of bits to shift in
166 : : *
167 : : * In order to read a register from the EEPROM, we need to shift 'count' bits
168 : : * in from the EEPROM. Bits are "shifted in" by raising the clock input to
169 : : * the EEPROM (setting the SK bit), and then reading the value of the data out
170 : : * "DO" bit. During this "shifting in" process the data in "DI" bit should
171 : : * always be clear.
172 : : **/
173 : 0 : static u16 igc_shift_in_eec_bits(struct igc_hw *hw, u16 count)
174 : : {
175 : : u32 eecd;
176 : : u32 i;
177 : : u16 data;
178 : :
179 : 0 : DEBUGFUNC("igc_shift_in_eec_bits");
180 : :
181 : 0 : eecd = IGC_READ_REG(hw, IGC_EECD);
182 : :
183 : 0 : eecd &= ~(IGC_EECD_DO | IGC_EECD_DI);
184 : : data = 0;
185 : :
186 [ # # ]: 0 : for (i = 0; i < count; i++) {
187 : 0 : data <<= 1;
188 : : igc_raise_eec_clk(hw, &eecd);
189 : :
190 : 0 : eecd = IGC_READ_REG(hw, IGC_EECD);
191 : :
192 : : eecd &= ~IGC_EECD_DI;
193 [ # # ]: 0 : if (eecd & IGC_EECD_DO)
194 : 0 : data |= 1;
195 : :
196 : : igc_lower_eec_clk(hw, &eecd);
197 : : }
198 : :
199 : 0 : return data;
200 : : }
201 : :
202 : : /**
203 : : * igc_poll_eerd_eewr_done - Poll for EEPROM read/write completion
204 : : * @hw: pointer to the HW structure
205 : : * @ee_reg: EEPROM flag for polling
206 : : *
207 : : * Polls the EEPROM status bit for either read or write completion based
208 : : * upon the value of 'ee_reg'.
209 : : **/
210 : 0 : s32 igc_poll_eerd_eewr_done(struct igc_hw *hw, int ee_reg)
211 : : {
212 : : u32 attempts = 100000;
213 : : u32 i, reg = 0;
214 : :
215 : 0 : DEBUGFUNC("igc_poll_eerd_eewr_done");
216 : :
217 [ # # ]: 0 : for (i = 0; i < attempts; i++) {
218 [ # # ]: 0 : if (ee_reg == IGC_NVM_POLL_READ)
219 : 0 : reg = IGC_READ_REG(hw, IGC_EERD);
220 : : else
221 : 0 : reg = IGC_READ_REG(hw, IGC_EEWR);
222 : :
223 [ # # ]: 0 : if (reg & IGC_NVM_RW_REG_DONE)
224 : : return IGC_SUCCESS;
225 : :
226 : 0 : usec_delay(5);
227 : : }
228 : :
229 : : return -IGC_ERR_NVM;
230 : : }
231 : :
232 : : /**
233 : : * igc_acquire_nvm_generic - Generic request for access to EEPROM
234 : : * @hw: pointer to the HW structure
235 : : *
236 : : * Set the EEPROM access request bit and wait for EEPROM access grant bit.
237 : : * Return successful if access grant bit set, else clear the request for
238 : : * EEPROM access and return -IGC_ERR_NVM (-1).
239 : : **/
240 : 0 : s32 igc_acquire_nvm_generic(struct igc_hw *hw)
241 : : {
242 : 0 : u32 eecd = IGC_READ_REG(hw, IGC_EECD);
243 : : s32 timeout = IGC_NVM_GRANT_ATTEMPTS;
244 : :
245 : 0 : DEBUGFUNC("igc_acquire_nvm_generic");
246 : :
247 : 0 : IGC_WRITE_REG(hw, IGC_EECD, eecd | IGC_EECD_REQ);
248 : 0 : eecd = IGC_READ_REG(hw, IGC_EECD);
249 : :
250 [ # # ]: 0 : while (timeout) {
251 [ # # ]: 0 : if (eecd & IGC_EECD_GNT)
252 : : break;
253 : 0 : usec_delay(5);
254 : 0 : eecd = IGC_READ_REG(hw, IGC_EECD);
255 : 0 : timeout--;
256 : : }
257 : :
258 [ # # ]: 0 : if (!timeout) {
259 : 0 : eecd &= ~IGC_EECD_REQ;
260 : 0 : IGC_WRITE_REG(hw, IGC_EECD, eecd);
261 : 0 : DEBUGOUT("Could not acquire NVM grant\n");
262 : 0 : return -IGC_ERR_NVM;
263 : : }
264 : :
265 : : return IGC_SUCCESS;
266 : : }
267 : :
268 : : /**
269 : : * igc_standby_nvm - Return EEPROM to standby state
270 : : * @hw: pointer to the HW structure
271 : : *
272 : : * Return the EEPROM to a standby state.
273 : : **/
274 : 0 : static void igc_standby_nvm(struct igc_hw *hw)
275 : : {
276 : : struct igc_nvm_info *nvm = &hw->nvm;
277 : 0 : u32 eecd = IGC_READ_REG(hw, IGC_EECD);
278 : :
279 : 0 : DEBUGFUNC("igc_standby_nvm");
280 : :
281 [ # # ]: 0 : if (nvm->type == igc_nvm_eeprom_microwire) {
282 : 0 : eecd &= ~(IGC_EECD_CS | IGC_EECD_SK);
283 : 0 : IGC_WRITE_REG(hw, IGC_EECD, eecd);
284 : 0 : IGC_WRITE_FLUSH(hw);
285 : 0 : usec_delay(nvm->delay_usec);
286 : :
287 : : igc_raise_eec_clk(hw, &eecd);
288 : :
289 : : /* Select EEPROM */
290 : 0 : eecd |= IGC_EECD_CS;
291 : 0 : IGC_WRITE_REG(hw, IGC_EECD, eecd);
292 : 0 : IGC_WRITE_FLUSH(hw);
293 : 0 : usec_delay(nvm->delay_usec);
294 : :
295 : : igc_lower_eec_clk(hw, &eecd);
296 [ # # ]: 0 : } else if (nvm->type == igc_nvm_eeprom_spi) {
297 : : /* Toggle CS to flush commands */
298 : 0 : eecd |= IGC_EECD_CS;
299 : 0 : IGC_WRITE_REG(hw, IGC_EECD, eecd);
300 : 0 : IGC_WRITE_FLUSH(hw);
301 : 0 : usec_delay(nvm->delay_usec);
302 : : eecd &= ~IGC_EECD_CS;
303 : 0 : IGC_WRITE_REG(hw, IGC_EECD, eecd);
304 : 0 : IGC_WRITE_FLUSH(hw);
305 : 0 : usec_delay(nvm->delay_usec);
306 : : }
307 : 0 : }
308 : :
309 : : /**
310 : : * igc_stop_nvm - Terminate EEPROM command
311 : : * @hw: pointer to the HW structure
312 : : *
313 : : * Terminates the current command by inverting the EEPROM's chip select pin.
314 : : **/
315 : 0 : void igc_stop_nvm(struct igc_hw *hw)
316 : : {
317 : : u32 eecd;
318 : :
319 : 0 : DEBUGFUNC("igc_stop_nvm");
320 : :
321 : 0 : eecd = IGC_READ_REG(hw, IGC_EECD);
322 [ # # ]: 0 : if (hw->nvm.type == igc_nvm_eeprom_spi) {
323 : : /* Pull CS high */
324 : : eecd |= IGC_EECD_CS;
325 : : igc_lower_eec_clk(hw, &eecd);
326 [ # # ]: 0 : } else if (hw->nvm.type == igc_nvm_eeprom_microwire) {
327 : : /* CS on Microwire is active-high */
328 : 0 : eecd &= ~(IGC_EECD_CS | IGC_EECD_DI);
329 : 0 : IGC_WRITE_REG(hw, IGC_EECD, eecd);
330 : : igc_raise_eec_clk(hw, &eecd);
331 : : igc_lower_eec_clk(hw, &eecd);
332 : : }
333 : 0 : }
334 : :
335 : : /**
336 : : * igc_release_nvm_generic - Release exclusive access to EEPROM
337 : : * @hw: pointer to the HW structure
338 : : *
339 : : * Stop any current commands to the EEPROM and clear the EEPROM request bit.
340 : : **/
341 : 0 : void igc_release_nvm_generic(struct igc_hw *hw)
342 : : {
343 : : u32 eecd;
344 : :
345 : 0 : DEBUGFUNC("igc_release_nvm_generic");
346 : :
347 : 0 : igc_stop_nvm(hw);
348 : :
349 : 0 : eecd = IGC_READ_REG(hw, IGC_EECD);
350 : 0 : eecd &= ~IGC_EECD_REQ;
351 : 0 : IGC_WRITE_REG(hw, IGC_EECD, eecd);
352 : 0 : }
353 : :
354 : : /**
355 : : * igc_ready_nvm_eeprom - Prepares EEPROM for read/write
356 : : * @hw: pointer to the HW structure
357 : : *
358 : : * Setups the EEPROM for reading and writing.
359 : : **/
360 : 0 : static s32 igc_ready_nvm_eeprom(struct igc_hw *hw)
361 : : {
362 : : struct igc_nvm_info *nvm = &hw->nvm;
363 : 0 : u32 eecd = IGC_READ_REG(hw, IGC_EECD);
364 : : u8 spi_stat_reg;
365 : :
366 : 0 : DEBUGFUNC("igc_ready_nvm_eeprom");
367 : :
368 [ # # ]: 0 : if (nvm->type == igc_nvm_eeprom_microwire) {
369 : : /* Clear SK and DI */
370 : 0 : eecd &= ~(IGC_EECD_DI | IGC_EECD_SK);
371 : 0 : IGC_WRITE_REG(hw, IGC_EECD, eecd);
372 : : /* Set CS */
373 : 0 : eecd |= IGC_EECD_CS;
374 : 0 : IGC_WRITE_REG(hw, IGC_EECD, eecd);
375 [ # # ]: 0 : } else if (nvm->type == igc_nvm_eeprom_spi) {
376 : : u16 timeout = NVM_MAX_RETRY_SPI;
377 : :
378 : : /* Clear SK and CS */
379 : 0 : eecd &= ~(IGC_EECD_CS | IGC_EECD_SK);
380 : 0 : IGC_WRITE_REG(hw, IGC_EECD, eecd);
381 : 0 : IGC_WRITE_FLUSH(hw);
382 : 0 : usec_delay(1);
383 : :
384 : : /* Read "Status Register" repeatedly until the LSB is cleared.
385 : : * The EEPROM will signal that the command has been completed
386 : : * by clearing bit 0 of the internal status register. If it's
387 : : * not cleared within 'timeout', then error out.
388 : : */
389 [ # # ]: 0 : while (timeout) {
390 : 0 : igc_shift_out_eec_bits(hw, NVM_RDSR_OPCODE_SPI,
391 : 0 : hw->nvm.opcode_bits);
392 : 0 : spi_stat_reg = (u8)igc_shift_in_eec_bits(hw, 8);
393 [ # # ]: 0 : if (!(spi_stat_reg & NVM_STATUS_RDY_SPI))
394 : : break;
395 : :
396 : 0 : usec_delay(5);
397 : 0 : igc_standby_nvm(hw);
398 : 0 : timeout--;
399 : : }
400 : :
401 [ # # ]: 0 : if (!timeout) {
402 : 0 : DEBUGOUT("SPI NVM Status error\n");
403 : 0 : return -IGC_ERR_NVM;
404 : : }
405 : : }
406 : :
407 : : return IGC_SUCCESS;
408 : : }
409 : :
410 : : /**
411 : : * igc_read_nvm_spi - Read EEPROM's using SPI
412 : : * @hw: pointer to the HW structure
413 : : * @offset: offset of word in the EEPROM to read
414 : : * @words: number of words to read
415 : : * @data: word read from the EEPROM
416 : : *
417 : : * Reads a 16 bit word from the EEPROM.
418 : : **/
419 : 0 : s32 igc_read_nvm_spi(struct igc_hw *hw, u16 offset, u16 words, u16 *data)
420 : : {
421 : : struct igc_nvm_info *nvm = &hw->nvm;
422 : : u32 i = 0;
423 : : s32 ret_val;
424 : : u16 word_in;
425 : : u8 read_opcode = NVM_READ_OPCODE_SPI;
426 : :
427 : 0 : DEBUGFUNC("igc_read_nvm_spi");
428 : :
429 : : /* A check for invalid values: offset too large, too many words,
430 : : * and not enough words.
431 : : */
432 [ # # # # : 0 : if (offset >= nvm->word_size || words > (nvm->word_size - offset) ||
# # ]
433 : : words == 0) {
434 : 0 : DEBUGOUT("nvm parameter(s) out of bounds\n");
435 : 0 : return -IGC_ERR_NVM;
436 : : }
437 : :
438 : 0 : ret_val = nvm->ops.acquire(hw);
439 [ # # ]: 0 : if (ret_val)
440 : : return ret_val;
441 : :
442 : 0 : ret_val = igc_ready_nvm_eeprom(hw);
443 [ # # ]: 0 : if (ret_val)
444 : 0 : goto release;
445 : :
446 : 0 : igc_standby_nvm(hw);
447 : :
448 [ # # # # ]: 0 : if (nvm->address_bits == 8 && offset >= 128)
449 : : read_opcode |= NVM_A8_OPCODE_SPI;
450 : :
451 : : /* Send the READ command (opcode + addr) */
452 : 0 : igc_shift_out_eec_bits(hw, read_opcode, nvm->opcode_bits);
453 : 0 : igc_shift_out_eec_bits(hw, (u16)(offset * 2), nvm->address_bits);
454 : :
455 : : /* Read the data. SPI NVMs increment the address with each byte
456 : : * read and will roll over if reading beyond the end. This allows
457 : : * us to read the whole NVM from any offset
458 : : */
459 [ # # ]: 0 : for (i = 0; i < words; i++) {
460 : 0 : word_in = igc_shift_in_eec_bits(hw, 16);
461 : 0 : data[i] = (word_in >> 8) | (word_in << 8);
462 : : }
463 : :
464 : 0 : release:
465 : 0 : nvm->ops.release(hw);
466 : :
467 : 0 : return ret_val;
468 : : }
469 : :
470 : : /**
471 : : * igc_read_nvm_microwire - Reads EEPROM's using microwire
472 : : * @hw: pointer to the HW structure
473 : : * @offset: offset of word in the EEPROM to read
474 : : * @words: number of words to read
475 : : * @data: word read from the EEPROM
476 : : *
477 : : * Reads a 16 bit word from the EEPROM.
478 : : **/
479 : 0 : s32 igc_read_nvm_microwire(struct igc_hw *hw, u16 offset, u16 words,
480 : : u16 *data)
481 : : {
482 : : struct igc_nvm_info *nvm = &hw->nvm;
483 : : u32 i = 0;
484 : : s32 ret_val;
485 : : u8 read_opcode = NVM_READ_OPCODE_MICROWIRE;
486 : :
487 : 0 : DEBUGFUNC("igc_read_nvm_microwire");
488 : :
489 : : /* A check for invalid values: offset too large, too many words,
490 : : * and not enough words.
491 : : */
492 [ # # # # : 0 : if (offset >= nvm->word_size || words > (nvm->word_size - offset) ||
# # ]
493 : : words == 0) {
494 : 0 : DEBUGOUT("nvm parameter(s) out of bounds\n");
495 : 0 : return -IGC_ERR_NVM;
496 : : }
497 : :
498 : 0 : ret_val = nvm->ops.acquire(hw);
499 [ # # ]: 0 : if (ret_val)
500 : : return ret_val;
501 : :
502 : 0 : ret_val = igc_ready_nvm_eeprom(hw);
503 [ # # ]: 0 : if (ret_val)
504 : 0 : goto release;
505 : :
506 [ # # ]: 0 : for (i = 0; i < words; i++) {
507 : : /* Send the READ command (opcode + addr) */
508 : 0 : igc_shift_out_eec_bits(hw, read_opcode, nvm->opcode_bits);
509 : 0 : igc_shift_out_eec_bits(hw, (u16)(offset + i),
510 : 0 : nvm->address_bits);
511 : :
512 : : /* Read the data. For microwire, each word requires the
513 : : * overhead of setup and tear-down.
514 : : */
515 : 0 : data[i] = igc_shift_in_eec_bits(hw, 16);
516 : 0 : igc_standby_nvm(hw);
517 : : }
518 : :
519 : 0 : release:
520 : 0 : nvm->ops.release(hw);
521 : :
522 : 0 : return ret_val;
523 : : }
524 : :
525 : : /**
526 : : * igc_read_nvm_eerd - Reads EEPROM using EERD register
527 : : * @hw: pointer to the HW structure
528 : : * @offset: offset of word in the EEPROM to read
529 : : * @words: number of words to read
530 : : * @data: word read from the EEPROM
531 : : *
532 : : * Reads a 16 bit word from the EEPROM using the EERD register.
533 : : **/
534 : 0 : s32 igc_read_nvm_eerd(struct igc_hw *hw, u16 offset, u16 words, u16 *data)
535 : : {
536 : : struct igc_nvm_info *nvm = &hw->nvm;
537 : : u32 i, eerd = 0;
538 : : s32 ret_val = IGC_SUCCESS;
539 : :
540 : 0 : DEBUGFUNC("igc_read_nvm_eerd");
541 : :
542 : : /* A check for invalid values: offset too large, too many words,
543 : : * too many words for the offset, and not enough words.
544 : : */
545 [ # # # # : 0 : if (offset >= nvm->word_size || words > (nvm->word_size - offset) ||
# # ]
546 : : words == 0) {
547 : 0 : DEBUGOUT("nvm parameter(s) out of bounds\n");
548 : 0 : return -IGC_ERR_NVM;
549 : : }
550 : :
551 [ # # ]: 0 : for (i = 0; i < words; i++) {
552 : 0 : eerd = ((offset + i) << IGC_NVM_RW_ADDR_SHIFT) +
553 : : IGC_NVM_RW_REG_START;
554 : :
555 : 0 : IGC_WRITE_REG(hw, IGC_EERD, eerd);
556 : 0 : ret_val = igc_poll_eerd_eewr_done(hw, IGC_NVM_POLL_READ);
557 [ # # ]: 0 : if (ret_val)
558 : : break;
559 : :
560 : 0 : data[i] = (IGC_READ_REG(hw, IGC_EERD) >>
561 : : IGC_NVM_RW_REG_DATA);
562 : : }
563 : :
564 [ # # ]: 0 : if (ret_val)
565 : 0 : DEBUGOUT1("NVM read error: %d\n", ret_val);
566 : :
567 : : return ret_val;
568 : : }
569 : :
570 : : /**
571 : : * igc_write_nvm_spi - Write to EEPROM using SPI
572 : : * @hw: pointer to the HW structure
573 : : * @offset: offset within the EEPROM to be written to
574 : : * @words: number of words to write
575 : : * @data: 16 bit word(s) to be written to the EEPROM
576 : : *
577 : : * Writes data to EEPROM at offset using SPI interface.
578 : : *
579 : : * If igc_update_nvm_checksum is not called after this function , the
580 : : * EEPROM will most likely contain an invalid checksum.
581 : : **/
582 : 0 : s32 igc_write_nvm_spi(struct igc_hw *hw, u16 offset, u16 words, u16 *data)
583 : : {
584 : : struct igc_nvm_info *nvm = &hw->nvm;
585 : : s32 ret_val = -IGC_ERR_NVM;
586 : : u16 widx = 0;
587 : :
588 : 0 : DEBUGFUNC("igc_write_nvm_spi");
589 : :
590 : : /* A check for invalid values: offset too large, too many words,
591 : : * and not enough words.
592 : : */
593 [ # # # # : 0 : if (offset >= nvm->word_size || words > (nvm->word_size - offset) ||
# # ]
594 : : words == 0) {
595 : 0 : DEBUGOUT("nvm parameter(s) out of bounds\n");
596 : 0 : return -IGC_ERR_NVM;
597 : : }
598 : :
599 [ # # ]: 0 : while (widx < words) {
600 : : u8 write_opcode = NVM_WRITE_OPCODE_SPI;
601 : :
602 : 0 : ret_val = nvm->ops.acquire(hw);
603 [ # # ]: 0 : if (ret_val)
604 : 0 : return ret_val;
605 : :
606 : 0 : ret_val = igc_ready_nvm_eeprom(hw);
607 [ # # ]: 0 : if (ret_val) {
608 : 0 : nvm->ops.release(hw);
609 : 0 : return ret_val;
610 : : }
611 : :
612 : 0 : igc_standby_nvm(hw);
613 : :
614 : : /* Send the WRITE ENABLE command (8 bit opcode) */
615 : 0 : igc_shift_out_eec_bits(hw, NVM_WREN_OPCODE_SPI,
616 : 0 : nvm->opcode_bits);
617 : :
618 : 0 : igc_standby_nvm(hw);
619 : :
620 : : /* Some SPI eeproms use the 8th address bit embedded in the
621 : : * opcode
622 : : */
623 [ # # # # ]: 0 : if (nvm->address_bits == 8 && offset >= 128)
624 : : write_opcode |= NVM_A8_OPCODE_SPI;
625 : :
626 : : /* Send the Write command (8-bit opcode + addr) */
627 : 0 : igc_shift_out_eec_bits(hw, write_opcode, nvm->opcode_bits);
628 : 0 : igc_shift_out_eec_bits(hw, (u16)((offset + widx) * 2),
629 : 0 : nvm->address_bits);
630 : :
631 : : /* Loop to allow for up to whole page write of eeprom */
632 [ # # ]: 0 : while (widx < words) {
633 : 0 : u16 word_out = data[widx];
634 : 0 : word_out = (word_out >> 8) | (word_out << 8);
635 : 0 : igc_shift_out_eec_bits(hw, word_out, 16);
636 : 0 : widx++;
637 : :
638 [ # # ]: 0 : if ((((offset + widx) * 2) % nvm->page_size) == 0) {
639 : 0 : igc_standby_nvm(hw);
640 : 0 : break;
641 : : }
642 : : }
643 : 0 : msec_delay(10);
644 : 0 : nvm->ops.release(hw);
645 : : }
646 : :
647 : : return ret_val;
648 : : }
649 : :
650 : : /**
651 : : * igc_write_nvm_microwire - Writes EEPROM using microwire
652 : : * @hw: pointer to the HW structure
653 : : * @offset: offset within the EEPROM to be written to
654 : : * @words: number of words to write
655 : : * @data: 16 bit word(s) to be written to the EEPROM
656 : : *
657 : : * Writes data to EEPROM at offset using microwire interface.
658 : : *
659 : : * If igc_update_nvm_checksum is not called after this function , the
660 : : * EEPROM will most likely contain an invalid checksum.
661 : : **/
662 : 0 : s32 igc_write_nvm_microwire(struct igc_hw *hw, u16 offset, u16 words,
663 : : u16 *data)
664 : : {
665 : : struct igc_nvm_info *nvm = &hw->nvm;
666 : : s32 ret_val;
667 : : u32 eecd;
668 : : u16 words_written = 0;
669 : : u16 widx = 0;
670 : :
671 : 0 : DEBUGFUNC("igc_write_nvm_microwire");
672 : :
673 : : /* A check for invalid values: offset too large, too many words,
674 : : * and not enough words.
675 : : */
676 [ # # # # : 0 : if (offset >= nvm->word_size || words > (nvm->word_size - offset) ||
# # ]
677 : : words == 0) {
678 : 0 : DEBUGOUT("nvm parameter(s) out of bounds\n");
679 : 0 : return -IGC_ERR_NVM;
680 : : }
681 : :
682 : 0 : ret_val = nvm->ops.acquire(hw);
683 [ # # ]: 0 : if (ret_val)
684 : : return ret_val;
685 : :
686 : 0 : ret_val = igc_ready_nvm_eeprom(hw);
687 [ # # ]: 0 : if (ret_val)
688 : 0 : goto release;
689 : :
690 : 0 : igc_shift_out_eec_bits(hw, NVM_EWEN_OPCODE_MICROWIRE,
691 : 0 : (u16)(nvm->opcode_bits + 2));
692 : :
693 : 0 : igc_shift_out_eec_bits(hw, 0, (u16)(nvm->address_bits - 2));
694 : :
695 : 0 : igc_standby_nvm(hw);
696 : :
697 [ # # ]: 0 : while (words_written < words) {
698 : 0 : igc_shift_out_eec_bits(hw, NVM_WRITE_OPCODE_MICROWIRE,
699 : 0 : nvm->opcode_bits);
700 : :
701 : 0 : igc_shift_out_eec_bits(hw, (u16)(offset + words_written),
702 : 0 : nvm->address_bits);
703 : :
704 : 0 : igc_shift_out_eec_bits(hw, data[words_written], 16);
705 : :
706 : 0 : igc_standby_nvm(hw);
707 : :
708 [ # # ]: 0 : for (widx = 0; widx < 200; widx++) {
709 : 0 : eecd = IGC_READ_REG(hw, IGC_EECD);
710 [ # # ]: 0 : if (eecd & IGC_EECD_DO)
711 : : break;
712 : 0 : usec_delay(50);
713 : : }
714 : :
715 [ # # ]: 0 : if (widx == 200) {
716 : 0 : DEBUGOUT("NVM Write did not complete\n");
717 : : ret_val = -IGC_ERR_NVM;
718 : 0 : goto release;
719 : : }
720 : :
721 : 0 : igc_standby_nvm(hw);
722 : :
723 : 0 : words_written++;
724 : : }
725 : :
726 : 0 : igc_shift_out_eec_bits(hw, NVM_EWDS_OPCODE_MICROWIRE,
727 : 0 : (u16)(nvm->opcode_bits + 2));
728 : :
729 : 0 : igc_shift_out_eec_bits(hw, 0, (u16)(nvm->address_bits - 2));
730 : :
731 : 0 : release:
732 : 0 : nvm->ops.release(hw);
733 : :
734 : 0 : return ret_val;
735 : : }
736 : :
737 : : /**
738 : : * igc_read_pba_string_generic - Read device part number
739 : : * @hw: pointer to the HW structure
740 : : * @pba_num: pointer to device part number
741 : : * @pba_num_size: size of part number buffer
742 : : *
743 : : * Reads the product board assembly (PBA) number from the EEPROM and stores
744 : : * the value in pba_num.
745 : : **/
746 : 0 : s32 igc_read_pba_string_generic(struct igc_hw *hw, u8 *pba_num,
747 : : u32 pba_num_size)
748 : : {
749 : : s32 ret_val;
750 : : u16 nvm_data;
751 : : u16 pba_ptr;
752 : : u16 offset;
753 : : u16 length;
754 : :
755 : 0 : DEBUGFUNC("igc_read_pba_string_generic");
756 : :
757 [ # # ]: 0 : if (pba_num == NULL) {
758 : 0 : DEBUGOUT("PBA string buffer was null\n");
759 : 0 : return -IGC_ERR_INVALID_ARGUMENT;
760 : : }
761 : :
762 : 0 : ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_0, 1, &nvm_data);
763 [ # # ]: 0 : if (ret_val) {
764 : 0 : DEBUGOUT("NVM Read Error\n");
765 : 0 : return ret_val;
766 : : }
767 : :
768 : 0 : ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_1, 1, &pba_ptr);
769 [ # # ]: 0 : if (ret_val) {
770 : 0 : DEBUGOUT("NVM Read Error\n");
771 : 0 : return ret_val;
772 : : }
773 : :
774 : : /* if nvm_data is not ptr guard the PBA must be in legacy format which
775 : : * means pba_ptr is actually our second data word for the PBA number
776 : : * and we can decode it into an ascii string
777 : : */
778 [ # # ]: 0 : if (nvm_data != NVM_PBA_PTR_GUARD) {
779 : 0 : DEBUGOUT("NVM PBA number is not stored as string\n");
780 : :
781 : : /* make sure callers buffer is big enough to store the PBA */
782 [ # # ]: 0 : if (pba_num_size < IGC_PBANUM_LENGTH) {
783 : 0 : DEBUGOUT("PBA string buffer too small\n");
784 : 0 : return IGC_ERR_NO_SPACE;
785 : : }
786 : :
787 : : /* extract hex string from data and pba_ptr */
788 : 0 : pba_num[0] = (nvm_data >> 12) & 0xF;
789 : 0 : pba_num[1] = (nvm_data >> 8) & 0xF;
790 : 0 : pba_num[2] = (nvm_data >> 4) & 0xF;
791 : 0 : pba_num[3] = nvm_data & 0xF;
792 : 0 : pba_num[4] = (pba_ptr >> 12) & 0xF;
793 : 0 : pba_num[5] = (pba_ptr >> 8) & 0xF;
794 : 0 : pba_num[6] = '-';
795 : 0 : pba_num[7] = 0;
796 : 0 : pba_num[8] = (pba_ptr >> 4) & 0xF;
797 : 0 : pba_num[9] = pba_ptr & 0xF;
798 : :
799 : : /* put a null character on the end of our string */
800 : 0 : pba_num[10] = '\0';
801 : :
802 : : /* switch all the data but the '-' to hex char */
803 [ # # ]: 0 : for (offset = 0; offset < 10; offset++) {
804 [ # # ]: 0 : if (pba_num[offset] < 0xA)
805 : 0 : pba_num[offset] += '0';
806 [ # # ]: 0 : else if (pba_num[offset] < 0x10)
807 : 0 : pba_num[offset] += 'A' - 0xA;
808 : : }
809 : :
810 : : return IGC_SUCCESS;
811 : : }
812 : :
813 : 0 : ret_val = hw->nvm.ops.read(hw, pba_ptr, 1, &length);
814 [ # # ]: 0 : if (ret_val) {
815 : 0 : DEBUGOUT("NVM Read Error\n");
816 : 0 : return ret_val;
817 : : }
818 : :
819 [ # # ]: 0 : if (length == 0xFFFF || length == 0) {
820 : 0 : DEBUGOUT("NVM PBA number section invalid length\n");
821 : 0 : return -IGC_ERR_NVM_PBA_SECTION;
822 : : }
823 : : /* check if pba_num buffer is big enough */
824 [ # # ]: 0 : if (pba_num_size < (((u32)length * 2) - 1)) {
825 : 0 : DEBUGOUT("PBA string buffer too small\n");
826 : 0 : return -IGC_ERR_NO_SPACE;
827 : : }
828 : :
829 : : /* trim pba length from start of string */
830 : 0 : pba_ptr++;
831 : 0 : length--;
832 : :
833 [ # # ]: 0 : for (offset = 0; offset < length; offset++) {
834 : 0 : ret_val = hw->nvm.ops.read(hw, pba_ptr + offset, 1, &nvm_data);
835 [ # # ]: 0 : if (ret_val) {
836 : 0 : DEBUGOUT("NVM Read Error\n");
837 : 0 : return ret_val;
838 : : }
839 : 0 : pba_num[offset * 2] = (u8)(nvm_data >> 8);
840 : 0 : pba_num[(offset * 2) + 1] = (u8)(nvm_data & 0xFF);
841 : : }
842 : 0 : pba_num[offset * 2] = '\0';
843 : :
844 : 0 : return IGC_SUCCESS;
845 : : }
846 : :
847 : : /**
848 : : * igc_read_pba_length_generic - Read device part number length
849 : : * @hw: pointer to the HW structure
850 : : * @pba_num_size: size of part number buffer
851 : : *
852 : : * Reads the product board assembly (PBA) number length from the EEPROM and
853 : : * stores the value in pba_num_size.
854 : : **/
855 : 0 : s32 igc_read_pba_length_generic(struct igc_hw *hw, u32 *pba_num_size)
856 : : {
857 : : s32 ret_val;
858 : : u16 nvm_data;
859 : : u16 pba_ptr;
860 : : u16 length;
861 : :
862 : 0 : DEBUGFUNC("igc_read_pba_length_generic");
863 : :
864 [ # # ]: 0 : if (pba_num_size == NULL) {
865 : 0 : DEBUGOUT("PBA buffer size was null\n");
866 : 0 : return -IGC_ERR_INVALID_ARGUMENT;
867 : : }
868 : :
869 : 0 : ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_0, 1, &nvm_data);
870 [ # # ]: 0 : if (ret_val) {
871 : 0 : DEBUGOUT("NVM Read Error\n");
872 : 0 : return ret_val;
873 : : }
874 : :
875 : 0 : ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_1, 1, &pba_ptr);
876 [ # # ]: 0 : if (ret_val) {
877 : 0 : DEBUGOUT("NVM Read Error\n");
878 : 0 : return ret_val;
879 : : }
880 : :
881 : : /* if data is not ptr guard the PBA must be in legacy format */
882 [ # # ]: 0 : if (nvm_data != NVM_PBA_PTR_GUARD) {
883 : 0 : *pba_num_size = IGC_PBANUM_LENGTH;
884 : 0 : return IGC_SUCCESS;
885 : : }
886 : :
887 : 0 : ret_val = hw->nvm.ops.read(hw, pba_ptr, 1, &length);
888 [ # # ]: 0 : if (ret_val) {
889 : 0 : DEBUGOUT("NVM Read Error\n");
890 : 0 : return ret_val;
891 : : }
892 : :
893 [ # # ]: 0 : if (length == 0xFFFF || length == 0) {
894 : 0 : DEBUGOUT("NVM PBA number section invalid length\n");
895 : 0 : return -IGC_ERR_NVM_PBA_SECTION;
896 : : }
897 : :
898 : : /* Convert from length in u16 values to u8 chars, add 1 for NULL,
899 : : * and subtract 2 because length field is included in length.
900 : : */
901 : 0 : *pba_num_size = ((u32)length * 2) - 1;
902 : :
903 : 0 : return IGC_SUCCESS;
904 : : }
905 : :
906 : : /**
907 : : * igc_read_pba_num_generic - Read device part number
908 : : * @hw: pointer to the HW structure
909 : : * @pba_num: pointer to device part number
910 : : *
911 : : * Reads the product board assembly (PBA) number from the EEPROM and stores
912 : : * the value in pba_num.
913 : : **/
914 : 0 : s32 igc_read_pba_num_generic(struct igc_hw *hw, u32 *pba_num)
915 : : {
916 : : s32 ret_val;
917 : : u16 nvm_data;
918 : :
919 : 0 : DEBUGFUNC("igc_read_pba_num_generic");
920 : :
921 : 0 : ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_0, 1, &nvm_data);
922 [ # # ]: 0 : if (ret_val) {
923 : 0 : DEBUGOUT("NVM Read Error\n");
924 : 0 : return ret_val;
925 [ # # ]: 0 : } else if (nvm_data == NVM_PBA_PTR_GUARD) {
926 : 0 : DEBUGOUT("NVM Not Supported\n");
927 : 0 : return -IGC_NOT_IMPLEMENTED;
928 : : }
929 : 0 : *pba_num = (u32)(nvm_data << 16);
930 : :
931 : 0 : ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_1, 1, &nvm_data);
932 [ # # ]: 0 : if (ret_val) {
933 : 0 : DEBUGOUT("NVM Read Error\n");
934 : 0 : return ret_val;
935 : : }
936 : 0 : *pba_num |= nvm_data;
937 : :
938 : 0 : return IGC_SUCCESS;
939 : : }
940 : :
941 : :
942 : : /**
943 : : * igc_read_pba_raw
944 : : * @hw: pointer to the HW structure
945 : : * @eeprom_buf: optional pointer to EEPROM image
946 : : * @eeprom_buf_size: size of EEPROM image in words
947 : : * @max_pba_block_size: PBA block size limit
948 : : * @pba: pointer to output PBA structure
949 : : *
950 : : * Reads PBA from EEPROM image when eeprom_buf is not NULL.
951 : : * Reads PBA from physical EEPROM device when eeprom_buf is NULL.
952 : : *
953 : : **/
954 : 0 : s32 igc_read_pba_raw(struct igc_hw *hw, u16 *eeprom_buf,
955 : : u32 eeprom_buf_size, u16 max_pba_block_size,
956 : : struct igc_pba *pba)
957 : : {
958 : : s32 ret_val;
959 : : u16 pba_block_size;
960 : :
961 [ # # ]: 0 : if (pba == NULL)
962 : : return -IGC_ERR_PARAM;
963 : :
964 [ # # ]: 0 : if (eeprom_buf == NULL) {
965 : 0 : ret_val = igc_read_nvm(hw, NVM_PBA_OFFSET_0, 2,
966 : : &pba->word[0]);
967 [ # # ]: 0 : if (ret_val)
968 : : return ret_val;
969 : : } else {
970 [ # # ]: 0 : if (eeprom_buf_size > NVM_PBA_OFFSET_1) {
971 : 0 : pba->word[0] = eeprom_buf[NVM_PBA_OFFSET_0];
972 : 0 : pba->word[1] = eeprom_buf[NVM_PBA_OFFSET_1];
973 : : } else {
974 : : return -IGC_ERR_PARAM;
975 : : }
976 : : }
977 : :
978 [ # # ]: 0 : if (pba->word[0] == NVM_PBA_PTR_GUARD) {
979 [ # # ]: 0 : if (pba->pba_block == NULL)
980 : : return -IGC_ERR_PARAM;
981 : :
982 : 0 : ret_val = igc_get_pba_block_size(hw, eeprom_buf,
983 : : eeprom_buf_size,
984 : : &pba_block_size);
985 [ # # ]: 0 : if (ret_val)
986 : : return ret_val;
987 : :
988 [ # # ]: 0 : if (pba_block_size > max_pba_block_size)
989 : : return -IGC_ERR_PARAM;
990 : :
991 [ # # ]: 0 : if (eeprom_buf == NULL) {
992 : 0 : ret_val = igc_read_nvm(hw, pba->word[1],
993 : : pba_block_size,
994 : : pba->pba_block);
995 [ # # ]: 0 : if (ret_val)
996 : 0 : return ret_val;
997 : : } else {
998 [ # # ]: 0 : if (eeprom_buf_size > (u32)(pba->word[1] +
999 : : pba_block_size)) {
1000 : 0 : memcpy(pba->pba_block,
1001 : 0 : &eeprom_buf[pba->word[1]],
1002 : : pba_block_size * sizeof(u16));
1003 : : } else {
1004 : : return -IGC_ERR_PARAM;
1005 : : }
1006 : : }
1007 : : }
1008 : :
1009 : : return IGC_SUCCESS;
1010 : : }
1011 : :
1012 : : /**
1013 : : * igc_write_pba_raw
1014 : : * @hw: pointer to the HW structure
1015 : : * @eeprom_buf: optional pointer to EEPROM image
1016 : : * @eeprom_buf_size: size of EEPROM image in words
1017 : : * @pba: pointer to PBA structure
1018 : : *
1019 : : * Writes PBA to EEPROM image when eeprom_buf is not NULL.
1020 : : * Writes PBA to physical EEPROM device when eeprom_buf is NULL.
1021 : : *
1022 : : **/
1023 : 0 : s32 igc_write_pba_raw(struct igc_hw *hw, u16 *eeprom_buf,
1024 : : u32 eeprom_buf_size, struct igc_pba *pba)
1025 : : {
1026 : : s32 ret_val;
1027 : :
1028 [ # # ]: 0 : if (pba == NULL)
1029 : : return -IGC_ERR_PARAM;
1030 : :
1031 [ # # ]: 0 : if (eeprom_buf == NULL) {
1032 : 0 : ret_val = igc_write_nvm(hw, NVM_PBA_OFFSET_0, 2,
1033 : : &pba->word[0]);
1034 [ # # ]: 0 : if (ret_val)
1035 : : return ret_val;
1036 : : } else {
1037 [ # # ]: 0 : if (eeprom_buf_size > NVM_PBA_OFFSET_1) {
1038 : 0 : eeprom_buf[NVM_PBA_OFFSET_0] = pba->word[0];
1039 : 0 : eeprom_buf[NVM_PBA_OFFSET_1] = pba->word[1];
1040 : : } else {
1041 : : return -IGC_ERR_PARAM;
1042 : : }
1043 : : }
1044 : :
1045 [ # # ]: 0 : if (pba->word[0] == NVM_PBA_PTR_GUARD) {
1046 [ # # ]: 0 : if (pba->pba_block == NULL)
1047 : : return -IGC_ERR_PARAM;
1048 : :
1049 [ # # ]: 0 : if (eeprom_buf == NULL) {
1050 : 0 : ret_val = igc_write_nvm(hw, pba->word[1],
1051 : 0 : pba->pba_block[0],
1052 : : pba->pba_block);
1053 [ # # ]: 0 : if (ret_val)
1054 : 0 : return ret_val;
1055 : : } else {
1056 : 0 : if (eeprom_buf_size > (u32)(pba->word[1] +
1057 [ # # ]: 0 : pba->pba_block[0])) {
1058 : 0 : memcpy(&eeprom_buf[pba->word[1]],
1059 : : pba->pba_block,
1060 : 0 : pba->pba_block[0] * sizeof(u16));
1061 : : } else {
1062 : : return -IGC_ERR_PARAM;
1063 : : }
1064 : : }
1065 : : }
1066 : :
1067 : : return IGC_SUCCESS;
1068 : : }
1069 : :
1070 : : /**
1071 : : * igc_get_pba_block_size
1072 : : * @hw: pointer to the HW structure
1073 : : * @eeprom_buf: optional pointer to EEPROM image
1074 : : * @eeprom_buf_size: size of EEPROM image in words
1075 : : * @pba_data_size: pointer to output variable
1076 : : *
1077 : : * Returns the size of the PBA block in words. Function operates on EEPROM
1078 : : * image if the eeprom_buf pointer is not NULL otherwise it accesses physical
1079 : : * EEPROM device.
1080 : : *
1081 : : **/
1082 : 0 : s32 igc_get_pba_block_size(struct igc_hw *hw, u16 *eeprom_buf,
1083 : : u32 eeprom_buf_size, u16 *pba_block_size)
1084 : : {
1085 : : s32 ret_val;
1086 : : u16 pba_word[2];
1087 : : u16 length;
1088 : :
1089 : 0 : DEBUGFUNC("igc_get_pba_block_size");
1090 : :
1091 [ # # ]: 0 : if (eeprom_buf == NULL) {
1092 : 0 : ret_val = igc_read_nvm(hw, NVM_PBA_OFFSET_0, 2, &pba_word[0]);
1093 [ # # ]: 0 : if (ret_val)
1094 : : return ret_val;
1095 : : } else {
1096 [ # # ]: 0 : if (eeprom_buf_size > NVM_PBA_OFFSET_1) {
1097 : 0 : pba_word[0] = eeprom_buf[NVM_PBA_OFFSET_0];
1098 : 0 : pba_word[1] = eeprom_buf[NVM_PBA_OFFSET_1];
1099 : : } else {
1100 : : return -IGC_ERR_PARAM;
1101 : : }
1102 : : }
1103 : :
1104 [ # # ]: 0 : if (pba_word[0] == NVM_PBA_PTR_GUARD) {
1105 [ # # ]: 0 : if (eeprom_buf == NULL) {
1106 : 0 : ret_val = igc_read_nvm(hw, pba_word[1] + 0, 1,
1107 : : &length);
1108 [ # # ]: 0 : if (ret_val)
1109 : : return ret_val;
1110 : : } else {
1111 [ # # ]: 0 : if (eeprom_buf_size > pba_word[1])
1112 : 0 : length = eeprom_buf[pba_word[1] + 0];
1113 : : else
1114 : : return -IGC_ERR_PARAM;
1115 : : }
1116 : :
1117 [ # # ]: 0 : if (length == 0xFFFF || length == 0)
1118 : : return -IGC_ERR_NVM_PBA_SECTION;
1119 : : } else {
1120 : : /* PBA number in legacy format, there is no PBA Block. */
1121 : 0 : length = 0;
1122 : : }
1123 : :
1124 [ # # ]: 0 : if (pba_block_size != NULL)
1125 : 0 : *pba_block_size = length;
1126 : :
1127 : : return IGC_SUCCESS;
1128 : : }
1129 : :
1130 : : /**
1131 : : * igc_read_mac_addr_generic - Read device MAC address
1132 : : * @hw: pointer to the HW structure
1133 : : *
1134 : : * Reads the device MAC address from the EEPROM and stores the value.
1135 : : * Since devices with two ports use the same EEPROM, we increment the
1136 : : * last bit in the MAC address for the second port.
1137 : : **/
1138 : 0 : s32 igc_read_mac_addr_generic(struct igc_hw *hw)
1139 : : {
1140 : : u32 rar_high;
1141 : : u32 rar_low;
1142 : : u16 i;
1143 : :
1144 : 0 : rar_high = IGC_READ_REG(hw, IGC_RAH(0));
1145 : 0 : rar_low = IGC_READ_REG(hw, IGC_RAL(0));
1146 : :
1147 [ # # ]: 0 : for (i = 0; i < IGC_RAL_MAC_ADDR_LEN; i++)
1148 : 0 : hw->mac.perm_addr[i] = (u8)(rar_low >> (i * 8));
1149 : :
1150 [ # # ]: 0 : for (i = 0; i < IGC_RAH_MAC_ADDR_LEN; i++)
1151 : 0 : hw->mac.perm_addr[i + 4] = (u8)(rar_high >> (i * 8));
1152 : :
1153 [ # # ]: 0 : for (i = 0; i < ETH_ADDR_LEN; i++)
1154 : 0 : hw->mac.addr[i] = hw->mac.perm_addr[i];
1155 : :
1156 : 0 : return IGC_SUCCESS;
1157 : : }
1158 : :
1159 : : /**
1160 : : * igc_validate_nvm_checksum_generic - Validate EEPROM checksum
1161 : : * @hw: pointer to the HW structure
1162 : : *
1163 : : * Calculates the EEPROM checksum by reading/adding each word of the EEPROM
1164 : : * and then verifies that the sum of the EEPROM is equal to 0xBABA.
1165 : : **/
1166 : 0 : s32 igc_validate_nvm_checksum_generic(struct igc_hw *hw)
1167 : : {
1168 : : s32 ret_val;
1169 : : u16 checksum = 0;
1170 : : u16 i, nvm_data;
1171 : :
1172 : 0 : DEBUGFUNC("igc_validate_nvm_checksum_generic");
1173 : :
1174 [ # # ]: 0 : for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) {
1175 : 0 : ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data);
1176 [ # # ]: 0 : if (ret_val) {
1177 : 0 : DEBUGOUT("NVM Read Error\n");
1178 : 0 : return ret_val;
1179 : : }
1180 : 0 : checksum += nvm_data;
1181 : : }
1182 : :
1183 [ # # ]: 0 : if (checksum != (u16)NVM_SUM) {
1184 : 0 : DEBUGOUT("NVM Checksum Invalid\n");
1185 : 0 : return -IGC_ERR_NVM;
1186 : : }
1187 : :
1188 : : return IGC_SUCCESS;
1189 : : }
1190 : :
1191 : : /**
1192 : : * igc_update_nvm_checksum_generic - Update EEPROM checksum
1193 : : * @hw: pointer to the HW structure
1194 : : *
1195 : : * Updates the EEPROM checksum by reading/adding each word of the EEPROM
1196 : : * up to the checksum. Then calculates the EEPROM checksum and writes the
1197 : : * value to the EEPROM.
1198 : : **/
1199 : 0 : s32 igc_update_nvm_checksum_generic(struct igc_hw *hw)
1200 : : {
1201 : : s32 ret_val;
1202 : 0 : u16 checksum = 0;
1203 : : u16 i, nvm_data;
1204 : :
1205 : 0 : DEBUGFUNC("igc_update_nvm_checksum");
1206 : :
1207 [ # # ]: 0 : for (i = 0; i < NVM_CHECKSUM_REG; i++) {
1208 : 0 : ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data);
1209 [ # # ]: 0 : if (ret_val) {
1210 : 0 : DEBUGOUT("NVM Read Error while updating checksum.\n");
1211 : 0 : return ret_val;
1212 : : }
1213 : 0 : checksum += nvm_data;
1214 : : }
1215 : 0 : checksum = (u16)NVM_SUM - checksum;
1216 : 0 : ret_val = hw->nvm.ops.write(hw, NVM_CHECKSUM_REG, 1, &checksum);
1217 [ # # ]: 0 : if (ret_val)
1218 : 0 : DEBUGOUT("NVM Write Error while updating checksum.\n");
1219 : :
1220 : : return ret_val;
1221 : : }
1222 : :
1223 : : /**
1224 : : * igc_reload_nvm_generic - Reloads EEPROM
1225 : : * @hw: pointer to the HW structure
1226 : : *
1227 : : * Reloads the EEPROM by setting the "Reinitialize from EEPROM" bit in the
1228 : : * extended control register.
1229 : : **/
1230 : 0 : static void igc_reload_nvm_generic(struct igc_hw *hw)
1231 : : {
1232 : : u32 ctrl_ext;
1233 : :
1234 : 0 : DEBUGFUNC("igc_reload_nvm_generic");
1235 : :
1236 : 0 : usec_delay(10);
1237 : 0 : ctrl_ext = IGC_READ_REG(hw, IGC_CTRL_EXT);
1238 : 0 : ctrl_ext |= IGC_CTRL_EXT_EE_RST;
1239 : 0 : IGC_WRITE_REG(hw, IGC_CTRL_EXT, ctrl_ext);
1240 : 0 : IGC_WRITE_FLUSH(hw);
1241 : 0 : }
1242 : :
1243 : : /**
1244 : : * igc_get_fw_version - Get firmware version information
1245 : : * @hw: pointer to the HW structure
1246 : : * @fw_vers: pointer to output version structure
1247 : : *
1248 : : * unsupported/not present features return 0 in version structure
1249 : : **/
1250 [ # # ]: 0 : void igc_get_fw_version(struct igc_hw *hw, struct igc_fw_version *fw_vers)
1251 : : {
1252 : : u16 eeprom_verh, eeprom_verl, etrack_test, fw_version;
1253 : : u8 q, hval, rem, result;
1254 : : u16 comb_verh, comb_verl, comb_offset;
1255 : :
1256 : : memset(fw_vers, 0, sizeof(struct igc_fw_version));
1257 : :
1258 : : /*
1259 : : * basic eeprom version numbers, bits used vary by part and by tool
1260 : : * used to create the nvm images. Check which data format we have.
1261 : : */
1262 [ # # ]: 0 : switch (hw->mac.type) {
1263 : 0 : case igc_i225:
1264 : 0 : hw->nvm.ops.read(hw, NVM_ETRACK_HIWORD, 1, &etrack_test);
1265 : : /* find combo image version */
1266 : 0 : hw->nvm.ops.read(hw, NVM_COMB_VER_PTR, 1, &comb_offset);
1267 [ # # ]: 0 : if (comb_offset && comb_offset != NVM_VER_INVALID) {
1268 : 0 : hw->nvm.ops.read(hw, NVM_COMB_VER_OFF + comb_offset + 1,
1269 : : 1, &comb_verh);
1270 : 0 : hw->nvm.ops.read(hw, NVM_COMB_VER_OFF + comb_offset,
1271 : : 1, &comb_verl);
1272 : :
1273 : : /* get Option Rom version if it exists and is valid */
1274 [ # # # # : 0 : if (comb_verh && comb_verl &&
# # ]
1275 [ # # ]: 0 : comb_verh != NVM_VER_INVALID &&
1276 : : comb_verl != NVM_VER_INVALID) {
1277 : 0 : fw_vers->or_valid = true;
1278 : 0 : fw_vers->or_major = comb_verl >>
1279 : : NVM_COMB_VER_SHFT;
1280 : 0 : fw_vers->or_build = (comb_verl <<
1281 : 0 : NVM_COMB_VER_SHFT) |
1282 : : (comb_verh >>
1283 : : NVM_COMB_VER_SHFT);
1284 : 0 : fw_vers->or_patch = comb_verh &
1285 : : NVM_COMB_VER_MASK;
1286 : : }
1287 : : }
1288 : : break;
1289 : 0 : default:
1290 : 0 : hw->nvm.ops.read(hw, NVM_ETRACK_HIWORD, 1, &etrack_test);
1291 : 0 : return;
1292 : : }
1293 : 0 : hw->nvm.ops.read(hw, NVM_VERSION, 1, &fw_version);
1294 : 0 : fw_vers->eep_major = (fw_version & NVM_MAJOR_MASK)
1295 : 0 : >> NVM_MAJOR_SHIFT;
1296 : :
1297 : : /* check for old style version format in newer images*/
1298 [ # # ]: 0 : if ((fw_version & NVM_NEW_DEC_MASK) == 0x0) {
1299 : 0 : eeprom_verl = (fw_version & NVM_COMB_VER_MASK);
1300 : : } else {
1301 : 0 : eeprom_verl = (fw_version & NVM_MINOR_MASK)
1302 : 0 : >> NVM_MINOR_SHIFT;
1303 : : }
1304 : : /* Convert minor value to hex before assigning to output struct
1305 : : * Val to be converted will not be higher than 99, per tool output
1306 : : */
1307 : 0 : q = eeprom_verl / NVM_HEX_CONV;
1308 : 0 : hval = q * NVM_HEX_TENS;
1309 : 0 : rem = eeprom_verl % NVM_HEX_CONV;
1310 : 0 : result = hval + rem;
1311 : 0 : fw_vers->eep_minor = result;
1312 : :
1313 [ # # ]: 0 : if ((etrack_test & NVM_MAJOR_MASK) == NVM_ETRACK_VALID) {
1314 : 0 : hw->nvm.ops.read(hw, NVM_ETRACK_WORD, 1, &eeprom_verl);
1315 : 0 : hw->nvm.ops.read(hw, (NVM_ETRACK_WORD + 1), 1, &eeprom_verh);
1316 : 0 : fw_vers->etrack_id = (eeprom_verh << NVM_ETRACK_SHIFT)
1317 : 0 : | eeprom_verl;
1318 [ # # ]: 0 : } else if ((etrack_test & NVM_ETRACK_VALID) == 0) {
1319 : 0 : hw->nvm.ops.read(hw, NVM_ETRACK_WORD, 1, &eeprom_verh);
1320 : 0 : hw->nvm.ops.read(hw, (NVM_ETRACK_WORD + 1), 1, &eeprom_verl);
1321 : 0 : fw_vers->etrack_id = (eeprom_verh << NVM_ETRACK_SHIFT) |
1322 : : eeprom_verl;
1323 : : }
1324 : : }
|