1 /******************************************************************************
3 Copyright (c) 2013-2014, Intel Corporation
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions are met:
9 1. Redistributions of source code must retain the above copyright notice,
10 this list of conditions and the following disclaimer.
12 2. Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
16 3. Neither the name of the Intel Corporation nor the names of its
17 contributors may be used to endorse or promote products derived from
18 this software without specific prior written permission.
20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 POSSIBILITY OF SUCH DAMAGE.
32 ******************************************************************************/
35 #include "i40e_prototype.h"
38 * i40e_init_nvm_ops - Initialize NVM function pointers
39 * @hw: pointer to the HW structure
41 * Setup the function pointers and the NVM info structure. Should be called
42 * once per NVM initialization, e.g. inside the i40e_init_shared_code().
43 * Please notice that the NVM term is used here (& in all methods covered
44 * in this file) as an equivalent of the FLASH part mapped into the SR.
45 * We are accessing FLASH always thru the Shadow RAM.
47 enum i40e_status_code i40e_init_nvm(struct i40e_hw *hw)
49 struct i40e_nvm_info *nvm = &hw->nvm;
50 enum i40e_status_code ret_code = I40E_SUCCESS;
54 DEBUGFUNC("i40e_init_nvm");
56 /* The SR size is stored regardless of the nvm programming mode
57 * as the blank mode may be used in the factory line.
59 gens = rd32(hw, I40E_GLNVM_GENS);
60 sr_size = ((gens & I40E_GLNVM_GENS_SR_SIZE_MASK) >>
61 I40E_GLNVM_GENS_SR_SIZE_SHIFT);
62 /* Switching to words (sr_size contains power of 2KB) */
63 nvm->sr_size = (1 << sr_size) * I40E_SR_WORDS_IN_1KB;
65 /* Check if we are in the normal or blank NVM programming mode */
66 fla = rd32(hw, I40E_GLNVM_FLA);
67 if (fla & I40E_GLNVM_FLA_LOCKED_MASK) { /* Normal programming mode */
69 nvm->timeout = I40E_MAX_NVM_TIMEOUT;
70 nvm->blank_nvm_mode = FALSE;
71 } else { /* Blank programming mode */
72 nvm->blank_nvm_mode = TRUE;
73 ret_code = I40E_ERR_NVM_BLANK_MODE;
74 DEBUGOUT("NVM init error: unsupported blank mode.\n");
81 * i40e_acquire_nvm - Generic request for acquiring the NVM ownership
82 * @hw: pointer to the HW structure
83 * @access: NVM access type (read or write)
85 * This function will request NVM ownership for reading
86 * via the proper Admin Command.
88 enum i40e_status_code i40e_acquire_nvm(struct i40e_hw *hw,
89 enum i40e_aq_resource_access_type access)
91 enum i40e_status_code ret_code = I40E_SUCCESS;
95 DEBUGFUNC("i40e_acquire_nvm");
97 if (hw->nvm.blank_nvm_mode)
98 goto i40e_i40e_acquire_nvm_exit;
100 ret_code = i40e_aq_request_resource(hw, I40E_NVM_RESOURCE_ID, access,
102 /* Reading the Global Device Timer */
103 gtime = rd32(hw, I40E_GLVFGEN_TIMER);
105 /* Store the timeout */
106 hw->nvm.hw_semaphore_timeout = I40E_MS_TO_GTIME(time) + gtime;
108 if (ret_code != I40E_SUCCESS) {
109 /* Set the polling timeout */
110 if (time > I40E_MAX_NVM_TIMEOUT)
111 timeout = I40E_MS_TO_GTIME(I40E_MAX_NVM_TIMEOUT)
114 timeout = hw->nvm.hw_semaphore_timeout;
115 /* Poll until the current NVM owner timeouts */
116 while (gtime < timeout) {
118 ret_code = i40e_aq_request_resource(hw,
119 I40E_NVM_RESOURCE_ID,
122 if (ret_code == I40E_SUCCESS) {
123 hw->nvm.hw_semaphore_timeout =
124 I40E_MS_TO_GTIME(time) + gtime;
127 gtime = rd32(hw, I40E_GLVFGEN_TIMER);
129 if (ret_code != I40E_SUCCESS) {
130 hw->nvm.hw_semaphore_timeout = 0;
131 hw->nvm.hw_semaphore_wait =
132 I40E_MS_TO_GTIME(time) + gtime;
133 DEBUGOUT1("NVM acquire timed out, wait %llu ms before trying again.\n",
138 i40e_i40e_acquire_nvm_exit:
143 * i40e_release_nvm - Generic request for releasing the NVM ownership
144 * @hw: pointer to the HW structure
146 * This function will release NVM resource via the proper Admin Command.
148 void i40e_release_nvm(struct i40e_hw *hw)
150 DEBUGFUNC("i40e_release_nvm");
152 if (!hw->nvm.blank_nvm_mode)
153 i40e_aq_release_resource(hw, I40E_NVM_RESOURCE_ID, 0, NULL);
157 * i40e_poll_sr_srctl_done_bit - Polls the GLNVM_SRCTL done bit
158 * @hw: pointer to the HW structure
160 * Polls the SRCTL Shadow RAM register done bit.
162 static enum i40e_status_code i40e_poll_sr_srctl_done_bit(struct i40e_hw *hw)
164 enum i40e_status_code ret_code = I40E_ERR_TIMEOUT;
167 DEBUGFUNC("i40e_poll_sr_srctl_done_bit");
169 /* Poll the I40E_GLNVM_SRCTL until the done bit is set */
170 for (wait_cnt = 0; wait_cnt < I40E_SRRD_SRCTL_ATTEMPTS; wait_cnt++) {
171 srctl = rd32(hw, I40E_GLNVM_SRCTL);
172 if (srctl & I40E_GLNVM_SRCTL_DONE_MASK) {
173 ret_code = I40E_SUCCESS;
178 if (ret_code == I40E_ERR_TIMEOUT)
179 DEBUGOUT("Done bit in GLNVM_SRCTL not set");
184 * i40e_read_nvm_word - Reads Shadow RAM
185 * @hw: pointer to the HW structure
186 * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF)
187 * @data: word read from the Shadow RAM
189 * Reads one 16 bit word from the Shadow RAM using the GLNVM_SRCTL register.
191 enum i40e_status_code i40e_read_nvm_word(struct i40e_hw *hw, u16 offset,
194 enum i40e_status_code ret_code = I40E_ERR_TIMEOUT;
197 DEBUGFUNC("i40e_read_nvm_srctl");
199 if (offset >= hw->nvm.sr_size) {
200 DEBUGOUT("NVM read error: Offset beyond Shadow RAM limit.\n");
201 ret_code = I40E_ERR_PARAM;
205 /* Poll the done bit first */
206 ret_code = i40e_poll_sr_srctl_done_bit(hw);
207 if (ret_code == I40E_SUCCESS) {
208 /* Write the address and start reading */
209 sr_reg = (u32)(offset << I40E_GLNVM_SRCTL_ADDR_SHIFT) |
210 (1 << I40E_GLNVM_SRCTL_START_SHIFT);
211 wr32(hw, I40E_GLNVM_SRCTL, sr_reg);
213 /* Poll I40E_GLNVM_SRCTL until the done bit is set */
214 ret_code = i40e_poll_sr_srctl_done_bit(hw);
215 if (ret_code == I40E_SUCCESS) {
216 sr_reg = rd32(hw, I40E_GLNVM_SRDATA);
217 *data = (u16)((sr_reg &
218 I40E_GLNVM_SRDATA_RDDATA_MASK)
219 >> I40E_GLNVM_SRDATA_RDDATA_SHIFT);
222 if (ret_code != I40E_SUCCESS)
223 DEBUGOUT1("NVM read error: Couldn't access Shadow RAM address: 0x%x\n",
231 * i40e_read_nvm_buffer - Reads Shadow RAM buffer
232 * @hw: pointer to the HW structure
233 * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF).
234 * @words: (in) number of words to read; (out) number of words actually read
235 * @data: words read from the Shadow RAM
237 * Reads 16 bit words (data buffer) from the SR using the i40e_read_nvm_srrd()
238 * method. The buffer read is preceded by the NVM ownership take
239 * and followed by the release.
241 enum i40e_status_code i40e_read_nvm_buffer(struct i40e_hw *hw, u16 offset,
242 u16 *words, u16 *data)
244 enum i40e_status_code ret_code = I40E_SUCCESS;
247 DEBUGFUNC("i40e_read_nvm_buffer");
249 /* Loop thru the selected region */
250 for (word = 0; word < *words; word++) {
251 index = offset + word;
252 ret_code = i40e_read_nvm_word(hw, index, &data[word]);
253 if (ret_code != I40E_SUCCESS)
257 /* Update the number of words read from the Shadow RAM */
263 * i40e_write_nvm_aq - Writes Shadow RAM.
264 * @hw: pointer to the HW structure.
265 * @module_pointer: module pointer location in words from the NVM beginning
266 * @offset: offset in words from module start
267 * @words: number of words to write
268 * @data: buffer with words to write to the Shadow RAM
269 * @last_command: tells the AdminQ that this is the last command
271 * Writes a 16 bit words buffer to the Shadow RAM using the admin command.
273 enum i40e_status_code i40e_write_nvm_aq(struct i40e_hw *hw, u8 module_pointer,
274 u32 offset, u16 words, void *data,
277 enum i40e_status_code ret_code = I40E_ERR_NVM;
279 DEBUGFUNC("i40e_write_nvm_aq");
281 /* Here we are checking the SR limit only for the flat memory model.
282 * We cannot do it for the module-based model, as we did not acquire
283 * the NVM resource yet (we cannot get the module pointer value).
284 * Firmware will check the module-based model.
286 if ((offset + words) > hw->nvm.sr_size)
287 DEBUGOUT("NVM write error: offset beyond Shadow RAM limit.\n");
288 else if (words > I40E_SR_SECTOR_SIZE_IN_WORDS)
289 /* We can write only up to 4KB (one sector), in one AQ write */
290 DEBUGOUT("NVM write fail error: cannot write more than 4KB in a single write.\n");
291 else if (((offset + (words - 1)) / I40E_SR_SECTOR_SIZE_IN_WORDS)
292 != (offset / I40E_SR_SECTOR_SIZE_IN_WORDS))
293 /* A single write cannot spread over two sectors */
294 DEBUGOUT("NVM write error: cannot spread over two sectors in a single write.\n");
296 ret_code = i40e_aq_update_nvm(hw, module_pointer,
297 2 * offset, /*bytes*/
299 data, last_command, NULL);
305 * i40e_write_nvm_word - Writes Shadow RAM word
306 * @hw: pointer to the HW structure
307 * @offset: offset of the Shadow RAM word to write
308 * @data: word to write to the Shadow RAM
310 * Writes a 16 bit word to the SR using the i40e_write_nvm_aq() method.
311 * NVM ownership have to be acquired and released (on ARQ completion event
312 * reception) by caller. To commit SR to NVM update checksum function
315 enum i40e_status_code i40e_write_nvm_word(struct i40e_hw *hw, u32 offset,
318 DEBUGFUNC("i40e_write_nvm_word");
320 /* Value 0x00 below means that we treat SR as a flat mem */
321 return i40e_write_nvm_aq(hw, 0x00, offset, 1, data, FALSE);
325 * i40e_write_nvm_buffer - Writes Shadow RAM buffer
326 * @hw: pointer to the HW structure
327 * @module_pointer: module pointer location in words from the NVM beginning
328 * @offset: offset of the Shadow RAM buffer to write
329 * @words: number of words to write
330 * @data: words to write to the Shadow RAM
332 * Writes a 16 bit words buffer to the Shadow RAM using the admin command.
333 * NVM ownership must be acquired before calling this function and released
334 * on ARQ completion event reception by caller. To commit SR to NVM update
335 * checksum function should be called.
337 enum i40e_status_code i40e_write_nvm_buffer(struct i40e_hw *hw,
338 u8 module_pointer, u32 offset,
339 u16 words, void *data)
341 DEBUGFUNC("i40e_write_nvm_buffer");
343 /* Here we will only write one buffer as the size of the modules
344 * mirrored in the Shadow RAM is always less than 4K.
346 return i40e_write_nvm_aq(hw, module_pointer, offset, words,
351 * i40e_calc_nvm_checksum - Calculates and returns the checksum
352 * @hw: pointer to hardware structure
353 * @checksum: pointer to the checksum
355 * This function calculates SW Checksum that covers the whole 64kB shadow RAM
356 * except the VPD and PCIe ALT Auto-load modules. The structure and size of VPD
357 * is customer specific and unknown. Therefore, this function skips all maximum
358 * possible size of VPD (1kB).
360 enum i40e_status_code i40e_calc_nvm_checksum(struct i40e_hw *hw, u16 *checksum)
362 enum i40e_status_code ret_code = I40E_SUCCESS;
363 u16 pcie_alt_module = 0;
364 u16 checksum_local = 0;
369 DEBUGFUNC("i40e_calc_nvm_checksum");
371 /* read pointer to VPD area */
372 ret_code = i40e_read_nvm_word(hw, I40E_SR_VPD_PTR, &vpd_module);
373 if (ret_code != I40E_SUCCESS) {
374 ret_code = I40E_ERR_NVM_CHECKSUM;
375 goto i40e_calc_nvm_checksum_exit;
378 /* read pointer to PCIe Alt Auto-load module */
379 ret_code = i40e_read_nvm_word(hw, I40E_SR_PCIE_ALT_AUTO_LOAD_PTR,
381 if (ret_code != I40E_SUCCESS) {
382 ret_code = I40E_ERR_NVM_CHECKSUM;
383 goto i40e_calc_nvm_checksum_exit;
386 /* Calculate SW checksum that covers the whole 64kB shadow RAM
387 * except the VPD and PCIe ALT Auto-load modules
389 for (i = 0; i < hw->nvm.sr_size; i++) {
390 /* Skip Checksum word */
391 if (i == I40E_SR_SW_CHECKSUM_WORD)
393 /* Skip VPD module (convert byte size to word count) */
394 if (i == (u32)vpd_module) {
395 i += (I40E_SR_VPD_MODULE_MAX_SIZE / 2);
396 if (i >= hw->nvm.sr_size)
399 /* Skip PCIe ALT module (convert byte size to word count) */
400 if (i == (u32)pcie_alt_module) {
401 i += (I40E_SR_PCIE_ALT_MODULE_MAX_SIZE / 2);
402 if (i >= hw->nvm.sr_size)
406 ret_code = i40e_read_nvm_word(hw, (u16)i, &word);
407 if (ret_code != I40E_SUCCESS) {
408 ret_code = I40E_ERR_NVM_CHECKSUM;
409 goto i40e_calc_nvm_checksum_exit;
411 checksum_local += word;
414 *checksum = (u16)I40E_SR_SW_CHECKSUM_BASE - checksum_local;
416 i40e_calc_nvm_checksum_exit:
421 * i40e_update_nvm_checksum - Updates the NVM checksum
422 * @hw: pointer to hardware structure
424 * NVM ownership must be acquired before calling this function and released
425 * on ARQ completion event reception by caller.
426 * This function will commit SR to NVM.
428 enum i40e_status_code i40e_update_nvm_checksum(struct i40e_hw *hw)
430 enum i40e_status_code ret_code = I40E_SUCCESS;
433 DEBUGFUNC("i40e_update_nvm_checksum");
435 ret_code = i40e_calc_nvm_checksum(hw, &checksum);
436 if (ret_code == I40E_SUCCESS)
437 ret_code = i40e_write_nvm_aq(hw, 0x00, I40E_SR_SW_CHECKSUM_WORD,
444 * i40e_validate_nvm_checksum - Validate EEPROM checksum
445 * @hw: pointer to hardware structure
446 * @checksum: calculated checksum
448 * Performs checksum calculation and validates the NVM SW checksum. If the
449 * caller does not need checksum, the value can be NULL.
451 enum i40e_status_code i40e_validate_nvm_checksum(struct i40e_hw *hw,
454 enum i40e_status_code ret_code = I40E_SUCCESS;
456 u16 checksum_local = 0;
458 DEBUGFUNC("i40e_validate_nvm_checksum");
460 ret_code = i40e_calc_nvm_checksum(hw, &checksum_local);
461 if (ret_code != I40E_SUCCESS)
462 goto i40e_validate_nvm_checksum_exit;
464 /* Do not use i40e_read_nvm_word() because we do not want to take
465 * the synchronization semaphores twice here.
467 i40e_read_nvm_word(hw, I40E_SR_SW_CHECKSUM_WORD, &checksum_sr);
469 /* Verify read checksum from EEPROM is the same as
470 * calculated checksum
472 if (checksum_local != checksum_sr)
473 ret_code = I40E_ERR_NVM_CHECKSUM;
475 /* If the user cares, return the calculated checksum */
477 *checksum = checksum_local;
479 i40e_validate_nvm_checksum_exit: