1 /****************************************************************************** 2 3 Copyright (c) 2013-2014, Intel Corporation 4 All rights reserved. 5 6 Redistribution and use in source and binary forms, with or without 7 modification, are permitted provided that the following conditions are met: 8 9 1. Redistributions of source code must retain the above copyright notice, 10 this list of conditions and the following disclaimer. 11 12 2. Redistributions in binary form must reproduce the above copyright 13 notice, this list of conditions and the following disclaimer in the 14 documentation and/or other materials provided with the distribution. 15 16 3. Neither the name of the Intel Corporation nor the names of its 17 contributors may be used to endorse or promote products derived from 18 this software without specific prior written permission. 19 20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 24 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 POSSIBILITY OF SUCH DAMAGE. 31 32 ******************************************************************************/ 33 /*$FreeBSD$*/ 34 35 #include "i40e_prototype.h" 36 37 /** 38 * i40e_init_nvm_ops - Initialize NVM function pointers 39 * @hw: pointer to the HW structure 40 * 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. 46 **/ 47 enum i40e_status_code i40e_init_nvm(struct i40e_hw *hw) 48 { 49 struct i40e_nvm_info *nvm = &hw->nvm; 50 enum i40e_status_code ret_code = I40E_SUCCESS; 51 u32 fla, gens; 52 u8 sr_size; 53 54 DEBUGFUNC("i40e_init_nvm"); 55 56 /* The SR size is stored regardless of the nvm programming mode 57 * as the blank mode may be used in the factory line. 58 */ 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; 64 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 */ 68 /* Max NVM timeout */ 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"); 75 } 76 77 return ret_code; 78 } 79 80 /** 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) 84 * 85 * This function will request NVM ownership for reading 86 * via the proper Admin Command. 87 **/ 88 enum i40e_status_code i40e_acquire_nvm(struct i40e_hw *hw, 89 enum i40e_aq_resource_access_type access) 90 { 91 enum i40e_status_code ret_code = I40E_SUCCESS; 92 u64 gtime, timeout; 93 u64 time = 0; 94 95 DEBUGFUNC("i40e_acquire_nvm"); 96 97 if (hw->nvm.blank_nvm_mode) 98 goto i40e_i40e_acquire_nvm_exit; 99 100 ret_code = i40e_aq_request_resource(hw, I40E_NVM_RESOURCE_ID, access, 101 0, &time, NULL); 102 /* Reading the Global Device Timer */ 103 gtime = rd32(hw, I40E_GLVFGEN_TIMER); 104 105 /* Store the timeout */ 106 hw->nvm.hw_semaphore_timeout = I40E_MS_TO_GTIME(time) + gtime; 107 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) 112 + gtime; 113 else 114 timeout = hw->nvm.hw_semaphore_timeout; 115 /* Poll until the current NVM owner timeouts */ 116 while (gtime < timeout) { 117 i40e_msec_delay(10); 118 ret_code = i40e_aq_request_resource(hw, 119 I40E_NVM_RESOURCE_ID, 120 access, 0, &time, 121 NULL); 122 if (ret_code == I40E_SUCCESS) { 123 hw->nvm.hw_semaphore_timeout = 124 I40E_MS_TO_GTIME(time) + gtime; 125 break; 126 } 127 gtime = rd32(hw, I40E_GLVFGEN_TIMER); 128 } 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", 134 time); 135 } 136 } 137 138 i40e_i40e_acquire_nvm_exit: 139 return ret_code; 140 } 141 142 /** 143 * i40e_release_nvm - Generic request for releasing the NVM ownership 144 * @hw: pointer to the HW structure 145 * 146 * This function will release NVM resource via the proper Admin Command. 147 **/ 148 void i40e_release_nvm(struct i40e_hw *hw) 149 { 150 DEBUGFUNC("i40e_release_nvm"); 151 152 if (!hw->nvm.blank_nvm_mode) 153 i40e_aq_release_resource(hw, I40E_NVM_RESOURCE_ID, 0, NULL); 154 } 155 156 /** 157 * i40e_poll_sr_srctl_done_bit - Polls the GLNVM_SRCTL done bit 158 * @hw: pointer to the HW structure 159 * 160 * Polls the SRCTL Shadow RAM register done bit. 161 **/ 162 static enum i40e_status_code i40e_poll_sr_srctl_done_bit(struct i40e_hw *hw) 163 { 164 enum i40e_status_code ret_code = I40E_ERR_TIMEOUT; 165 u32 srctl, wait_cnt; 166 167 DEBUGFUNC("i40e_poll_sr_srctl_done_bit"); 168 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; 174 break; 175 } 176 i40e_usec_delay(5); 177 } 178 if (ret_code == I40E_ERR_TIMEOUT) 179 DEBUGOUT("Done bit in GLNVM_SRCTL not set"); 180 return ret_code; 181 } 182 183 /** 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 188 * 189 * Reads one 16 bit word from the Shadow RAM using the GLNVM_SRCTL register. 190 **/ 191 enum i40e_status_code i40e_read_nvm_word(struct i40e_hw *hw, u16 offset, 192 u16 *data) 193 { 194 enum i40e_status_code ret_code = I40E_ERR_TIMEOUT; 195 u32 sr_reg; 196 197 DEBUGFUNC("i40e_read_nvm_srctl"); 198 199 if (offset >= hw->nvm.sr_size) { 200 DEBUGOUT("NVM read error: Offset beyond Shadow RAM limit.\n"); 201 ret_code = I40E_ERR_PARAM; 202 goto read_nvm_exit; 203 } 204 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); 212 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); 220 } 221 } 222 if (ret_code != I40E_SUCCESS) 223 DEBUGOUT1("NVM read error: Couldn't access Shadow RAM address: 0x%x\n", 224 offset); 225 226 read_nvm_exit: 227 return ret_code; 228 } 229 230 /** 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 236 * 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. 240 **/ 241 enum i40e_status_code i40e_read_nvm_buffer(struct i40e_hw *hw, u16 offset, 242 u16 *words, u16 *data) 243 { 244 enum i40e_status_code ret_code = I40E_SUCCESS; 245 u16 index, word; 246 247 DEBUGFUNC("i40e_read_nvm_buffer"); 248 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) 254 break; 255 } 256 257 /* Update the number of words read from the Shadow RAM */ 258 *words = word; 259 260 return ret_code; 261 } 262 /** 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 270 * 271 * Writes a 16 bit words buffer to the Shadow RAM using the admin command. 272 **/ 273 enum i40e_status_code i40e_write_nvm_aq(struct i40e_hw *hw, u8 module_pointer, 274 u32 offset, u16 words, void *data, 275 bool last_command) 276 { 277 enum i40e_status_code ret_code = I40E_ERR_NVM; 278 279 DEBUGFUNC("i40e_write_nvm_aq"); 280 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. 285 */ 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"); 295 else 296 ret_code = i40e_aq_update_nvm(hw, module_pointer, 297 2 * offset, /*bytes*/ 298 2 * words, /*bytes*/ 299 data, last_command, NULL); 300 301 return ret_code; 302 } 303 304 /** 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 309 * 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 313 * should be called. 314 **/ 315 enum i40e_status_code i40e_write_nvm_word(struct i40e_hw *hw, u32 offset, 316 void *data) 317 { 318 DEBUGFUNC("i40e_write_nvm_word"); 319 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); 322 } 323 324 /** 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 331 * 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. 336 **/ 337 enum i40e_status_code i40e_write_nvm_buffer(struct i40e_hw *hw, 338 u8 module_pointer, u32 offset, 339 u16 words, void *data) 340 { 341 DEBUGFUNC("i40e_write_nvm_buffer"); 342 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. 345 */ 346 return i40e_write_nvm_aq(hw, module_pointer, offset, words, 347 data, FALSE); 348 } 349 350 /** 351 * i40e_calc_nvm_checksum - Calculates and returns the checksum 352 * @hw: pointer to hardware structure 353 * @checksum: pointer to the checksum 354 * 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). 359 **/ 360 enum i40e_status_code i40e_calc_nvm_checksum(struct i40e_hw *hw, u16 *checksum) 361 { 362 enum i40e_status_code ret_code = I40E_SUCCESS; 363 u16 pcie_alt_module = 0; 364 u16 checksum_local = 0; 365 u16 vpd_module = 0; 366 u16 word = 0; 367 u32 i = 0; 368 369 DEBUGFUNC("i40e_calc_nvm_checksum"); 370 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; 376 } 377 378 /* read pointer to PCIe Alt Auto-load module */ 379 ret_code = i40e_read_nvm_word(hw, I40E_SR_PCIE_ALT_AUTO_LOAD_PTR, 380 &pcie_alt_module); 381 if (ret_code != I40E_SUCCESS) { 382 ret_code = I40E_ERR_NVM_CHECKSUM; 383 goto i40e_calc_nvm_checksum_exit; 384 } 385 386 /* Calculate SW checksum that covers the whole 64kB shadow RAM 387 * except the VPD and PCIe ALT Auto-load modules 388 */ 389 for (i = 0; i < hw->nvm.sr_size; i++) { 390 /* Skip Checksum word */ 391 if (i == I40E_SR_SW_CHECKSUM_WORD) 392 i++; 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) 397 break; 398 } 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) 403 break; 404 } 405 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; 410 } 411 checksum_local += word; 412 } 413 414 *checksum = (u16)I40E_SR_SW_CHECKSUM_BASE - checksum_local; 415 416 i40e_calc_nvm_checksum_exit: 417 return ret_code; 418 } 419 420 /** 421 * i40e_update_nvm_checksum - Updates the NVM checksum 422 * @hw: pointer to hardware structure 423 * 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. 427 **/ 428 enum i40e_status_code i40e_update_nvm_checksum(struct i40e_hw *hw) 429 { 430 enum i40e_status_code ret_code = I40E_SUCCESS; 431 u16 checksum; 432 433 DEBUGFUNC("i40e_update_nvm_checksum"); 434 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, 438 1, &checksum, TRUE); 439 440 return ret_code; 441 } 442 443 /** 444 * i40e_validate_nvm_checksum - Validate EEPROM checksum 445 * @hw: pointer to hardware structure 446 * @checksum: calculated checksum 447 * 448 * Performs checksum calculation and validates the NVM SW checksum. If the 449 * caller does not need checksum, the value can be NULL. 450 **/ 451 enum i40e_status_code i40e_validate_nvm_checksum(struct i40e_hw *hw, 452 u16 *checksum) 453 { 454 enum i40e_status_code ret_code = I40E_SUCCESS; 455 u16 checksum_sr = 0; 456 u16 checksum_local = 0; 457 458 DEBUGFUNC("i40e_validate_nvm_checksum"); 459 460 ret_code = i40e_calc_nvm_checksum(hw, &checksum_local); 461 if (ret_code != I40E_SUCCESS) 462 goto i40e_validate_nvm_checksum_exit; 463 464 /* Do not use i40e_read_nvm_word() because we do not want to take 465 * the synchronization semaphores twice here. 466 */ 467 i40e_read_nvm_word(hw, I40E_SR_SW_CHECKSUM_WORD, &checksum_sr); 468 469 /* Verify read checksum from EEPROM is the same as 470 * calculated checksum 471 */ 472 if (checksum_local != checksum_sr) 473 ret_code = I40E_ERR_NVM_CHECKSUM; 474 475 /* If the user cares, return the calculated checksum */ 476 if (checksum) 477 *checksum = checksum_local; 478 479 i40e_validate_nvm_checksum_exit: 480 return ret_code; 481 } 482