1 /******************************************************************************* 2 * 3 * Intel Ethernet Controller XL710 Family Linux Driver 4 * Copyright(c) 2013 Intel Corporation. 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms and conditions of the GNU General Public License, 8 * version 2, as published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 * more details. 14 * 15 * You should have received a copy of the GNU General Public License along with 16 * this program; if not, write to the Free Software Foundation, Inc., 17 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * The full GNU General Public License is included in this distribution in 20 * the file called "COPYING". 21 * 22 * Contact Information: 23 * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net> 24 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 25 * 26 ******************************************************************************/ 27 28 #include "i40e_prototype.h" 29 30 /** 31 * i40e_init_nvm_ops - Initialize NVM function pointers. 32 * @hw: pointer to the HW structure. 33 * 34 * Setups the function pointers and the NVM info structure. Should be called 35 * once per NVM initialization, e.g. inside the i40e_init_shared_code(). 36 * Please notice that the NVM term is used here (& in all methods covered 37 * in this file) as an equivalent of the FLASH part mapped into the SR. 38 * We are accessing FLASH always thru the Shadow RAM. 39 **/ 40 i40e_status i40e_init_nvm(struct i40e_hw *hw) 41 { 42 struct i40e_nvm_info *nvm = &hw->nvm; 43 i40e_status ret_code = 0; 44 u32 fla, gens; 45 u8 sr_size; 46 47 /* The SR size is stored regardless of the nvm programming mode 48 * as the blank mode may be used in the factory line. 49 */ 50 gens = rd32(hw, I40E_GLNVM_GENS); 51 sr_size = ((gens & I40E_GLNVM_GENS_SR_SIZE_MASK) >> 52 I40E_GLNVM_GENS_SR_SIZE_SHIFT); 53 /* Switching to words (sr_size contains power of 2KB). */ 54 nvm->sr_size = (1 << sr_size) * I40E_SR_WORDS_IN_1KB; 55 56 /* Check if we are in the normal or blank NVM programming mode. */ 57 fla = rd32(hw, I40E_GLNVM_FLA); 58 if (fla & I40E_GLNVM_FLA_LOCKED_MASK) { /* Normal programming mode. */ 59 /* Max NVM timeout. */ 60 nvm->timeout = I40E_MAX_NVM_TIMEOUT; 61 nvm->blank_nvm_mode = false; 62 } else { /* Blank programming mode. */ 63 nvm->blank_nvm_mode = true; 64 ret_code = I40E_ERR_NVM_BLANK_MODE; 65 hw_dbg(hw, "NVM init error: unsupported blank mode.\n"); 66 } 67 68 return ret_code; 69 } 70 71 /** 72 * i40e_acquire_nvm - Generic request for acquiring the NVM ownership. 73 * @hw: pointer to the HW structure. 74 * @access: NVM access type (read or write). 75 * 76 * This function will request NVM ownership for reading 77 * via the proper Admin Command. 78 **/ 79 i40e_status i40e_acquire_nvm(struct i40e_hw *hw, 80 enum i40e_aq_resource_access_type access) 81 { 82 i40e_status ret_code = 0; 83 u64 gtime, timeout; 84 u64 time = 0; 85 86 if (hw->nvm.blank_nvm_mode) 87 goto i40e_i40e_acquire_nvm_exit; 88 89 ret_code = i40e_aq_request_resource(hw, I40E_NVM_RESOURCE_ID, access, 90 0, &time, NULL); 91 /* Reading the Global Device Timer. */ 92 gtime = rd32(hw, I40E_GLVFGEN_TIMER); 93 94 /* Store the timeout. */ 95 hw->nvm.hw_semaphore_timeout = I40E_MS_TO_GTIME(time) + gtime; 96 97 if (ret_code) { 98 /* Set the polling timeout. */ 99 if (time > I40E_MAX_NVM_TIMEOUT) 100 timeout = I40E_MS_TO_GTIME(I40E_MAX_NVM_TIMEOUT) 101 + gtime; 102 else 103 timeout = hw->nvm.hw_semaphore_timeout; 104 /* Poll until the current NVM owner timeouts. */ 105 while (gtime < timeout) { 106 usleep_range(10000, 20000); 107 ret_code = i40e_aq_request_resource(hw, 108 I40E_NVM_RESOURCE_ID, 109 access, 0, &time, 110 NULL); 111 if (!ret_code) { 112 hw->nvm.hw_semaphore_timeout = 113 I40E_MS_TO_GTIME(time) + gtime; 114 break; 115 } 116 gtime = rd32(hw, I40E_GLVFGEN_TIMER); 117 } 118 if (ret_code) { 119 hw->nvm.hw_semaphore_timeout = 0; 120 hw->nvm.hw_semaphore_wait = 121 I40E_MS_TO_GTIME(time) + gtime; 122 hw_dbg(hw, "NVM acquire timed out, wait %llu ms before trying again.\n", 123 time); 124 } 125 } 126 127 i40e_i40e_acquire_nvm_exit: 128 return ret_code; 129 } 130 131 /** 132 * i40e_release_nvm - Generic request for releasing the NVM ownership. 133 * @hw: pointer to the HW structure. 134 * 135 * This function will release NVM resource via the proper Admin Command. 136 **/ 137 void i40e_release_nvm(struct i40e_hw *hw) 138 { 139 if (!hw->nvm.blank_nvm_mode) 140 i40e_aq_release_resource(hw, I40E_NVM_RESOURCE_ID, 0, NULL); 141 } 142 143 /** 144 * i40e_poll_sr_srctl_done_bit - Polls the GLNVM_SRCTL done bit. 145 * @hw: pointer to the HW structure. 146 * 147 * Polls the SRCTL Shadow RAM register done bit. 148 **/ 149 static i40e_status i40e_poll_sr_srctl_done_bit(struct i40e_hw *hw) 150 { 151 i40e_status ret_code = I40E_ERR_TIMEOUT; 152 u32 srctl, wait_cnt; 153 154 /* Poll the I40E_GLNVM_SRCTL until the done bit is set. */ 155 for (wait_cnt = 0; wait_cnt < I40E_SRRD_SRCTL_ATTEMPTS; wait_cnt++) { 156 srctl = rd32(hw, I40E_GLNVM_SRCTL); 157 if (srctl & I40E_GLNVM_SRCTL_DONE_MASK) { 158 ret_code = 0; 159 break; 160 } 161 udelay(5); 162 } 163 if (ret_code == I40E_ERR_TIMEOUT) 164 hw_dbg(hw, "Done bit in GLNVM_SRCTL not set"); 165 return ret_code; 166 } 167 168 /** 169 * i40e_read_nvm_srctl - Reads Shadow RAM. 170 * @hw: pointer to the HW structure. 171 * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF). 172 * @data: word read from the Shadow RAM. 173 * 174 * Reads 16 bit word from the Shadow RAM using the GLNVM_SRCTL register. 175 **/ 176 static i40e_status i40e_read_nvm_srctl(struct i40e_hw *hw, u16 offset, 177 u16 *data) 178 { 179 i40e_status ret_code = I40E_ERR_TIMEOUT; 180 u32 sr_reg; 181 182 if (offset >= hw->nvm.sr_size) { 183 hw_dbg(hw, "NVM read error: Offset beyond Shadow RAM limit.\n"); 184 ret_code = I40E_ERR_PARAM; 185 goto read_nvm_exit; 186 } 187 188 /* Poll the done bit first. */ 189 ret_code = i40e_poll_sr_srctl_done_bit(hw); 190 if (!ret_code) { 191 /* Write the address and start reading. */ 192 sr_reg = (u32)(offset << I40E_GLNVM_SRCTL_ADDR_SHIFT) | 193 (1 << I40E_GLNVM_SRCTL_START_SHIFT); 194 wr32(hw, I40E_GLNVM_SRCTL, sr_reg); 195 196 /* Poll I40E_GLNVM_SRCTL until the done bit is set. */ 197 ret_code = i40e_poll_sr_srctl_done_bit(hw); 198 if (!ret_code) { 199 sr_reg = rd32(hw, I40E_GLNVM_SRDATA); 200 *data = (u16)((sr_reg & 201 I40E_GLNVM_SRDATA_RDDATA_MASK) 202 >> I40E_GLNVM_SRDATA_RDDATA_SHIFT); 203 } 204 } 205 if (ret_code) 206 hw_dbg(hw, "NVM read error: Couldn't access Shadow RAM address: 0x%x\n", 207 offset); 208 209 read_nvm_exit: 210 return ret_code; 211 } 212 213 /** 214 * i40e_read_nvm_word - Reads Shadow RAM word. 215 * @hw: pointer to the HW structure. 216 * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF). 217 * @data: word read from the Shadow RAM. 218 * 219 * Reads 16 bit word from the Shadow RAM. Each read is preceded 220 * with the NVM ownership taking and followed by the release. 221 **/ 222 i40e_status i40e_read_nvm_word(struct i40e_hw *hw, u16 offset, 223 u16 *data) 224 { 225 i40e_status ret_code = 0; 226 227 ret_code = i40e_acquire_nvm(hw, I40E_RESOURCE_READ); 228 if (!ret_code) { 229 ret_code = i40e_read_nvm_srctl(hw, offset, data); 230 i40e_release_nvm(hw); 231 } 232 233 return ret_code; 234 } 235 236 /** 237 * i40e_read_nvm_buffer - Reads Shadow RAM buffer. 238 * @hw: pointer to the HW structure. 239 * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF). 240 * @words: number of words to read (in) & 241 * number of words read before the NVM ownership timeout (out). 242 * @data: words read from the Shadow RAM. 243 * 244 * Reads 16 bit words (data buffer) from the SR using the i40e_read_nvm_srrd() 245 * method. The buffer read is preceded by the NVM ownership take 246 * and followed by the release. 247 **/ 248 i40e_status i40e_read_nvm_buffer(struct i40e_hw *hw, u16 offset, 249 u16 *words, u16 *data) 250 { 251 i40e_status ret_code = 0; 252 u16 index, word; 253 u32 time; 254 255 ret_code = i40e_acquire_nvm(hw, I40E_RESOURCE_READ); 256 if (!ret_code) { 257 /* Loop thru the selected region. */ 258 for (word = 0; word < *words; word++) { 259 index = offset + word; 260 ret_code = i40e_read_nvm_srctl(hw, index, &data[word]); 261 if (ret_code) 262 break; 263 /* Check if we didn't exceeded the semaphore timeout. */ 264 time = rd32(hw, I40E_GLVFGEN_TIMER); 265 if (time >= hw->nvm.hw_semaphore_timeout) { 266 ret_code = I40E_ERR_TIMEOUT; 267 hw_dbg(hw, "NVM read error: timeout.\n"); 268 break; 269 } 270 } 271 /* Update the number of words read from the Shadow RAM. */ 272 *words = word; 273 /* Release the NVM ownership. */ 274 i40e_release_nvm(hw); 275 } 276 277 return ret_code; 278 } 279 280 /** 281 * i40e_calc_nvm_checksum - Calculates and returns the checksum 282 * @hw: pointer to hardware structure 283 * 284 * This function calculate SW Checksum that covers the whole 64kB shadow RAM 285 * except the VPD and PCIe ALT Auto-load modules. The structure and size of VPD 286 * is customer specific and unknown. Therefore, this function skips all maximum 287 * possible size of VPD (1kB). 288 **/ 289 static i40e_status i40e_calc_nvm_checksum(struct i40e_hw *hw, 290 u16 *checksum) 291 { 292 i40e_status ret_code = 0; 293 u16 pcie_alt_module = 0; 294 u16 checksum_local = 0; 295 u16 vpd_module = 0; 296 u16 word = 0; 297 u32 i = 0; 298 299 /* read pointer to VPD area */ 300 ret_code = i40e_read_nvm_srctl(hw, I40E_SR_VPD_PTR, &vpd_module); 301 if (ret_code) { 302 ret_code = I40E_ERR_NVM_CHECKSUM; 303 goto i40e_calc_nvm_checksum_exit; 304 } 305 306 /* read pointer to PCIe Alt Auto-load module */ 307 ret_code = i40e_read_nvm_srctl(hw, I40E_SR_PCIE_ALT_AUTO_LOAD_PTR, 308 &pcie_alt_module); 309 if (ret_code) { 310 ret_code = I40E_ERR_NVM_CHECKSUM; 311 goto i40e_calc_nvm_checksum_exit; 312 } 313 314 /* Calculate SW checksum that covers the whole 64kB shadow RAM 315 * except the VPD and PCIe ALT Auto-load modules 316 */ 317 for (i = 0; i < hw->nvm.sr_size; i++) { 318 /* Skip Checksum word */ 319 if (i == I40E_SR_SW_CHECKSUM_WORD) 320 i++; 321 /* Skip VPD module (convert byte size to word count) */ 322 if (i == (u32)vpd_module) { 323 i += (I40E_SR_VPD_MODULE_MAX_SIZE / 2); 324 if (i >= hw->nvm.sr_size) 325 break; 326 } 327 /* Skip PCIe ALT module (convert byte size to word count) */ 328 if (i == (u32)pcie_alt_module) { 329 i += (I40E_SR_PCIE_ALT_MODULE_MAX_SIZE / 2); 330 if (i >= hw->nvm.sr_size) 331 break; 332 } 333 334 ret_code = i40e_read_nvm_srctl(hw, (u16)i, &word); 335 if (ret_code) { 336 ret_code = I40E_ERR_NVM_CHECKSUM; 337 goto i40e_calc_nvm_checksum_exit; 338 } 339 checksum_local += word; 340 } 341 342 *checksum = (u16)I40E_SR_SW_CHECKSUM_BASE - checksum_local; 343 344 i40e_calc_nvm_checksum_exit: 345 return ret_code; 346 } 347 348 /** 349 * i40e_validate_nvm_checksum - Validate EEPROM checksum 350 * @hw: pointer to hardware structure 351 * @checksum: calculated checksum 352 * 353 * Performs checksum calculation and validates the NVM SW checksum. If the 354 * caller does not need checksum, the value can be NULL. 355 **/ 356 i40e_status i40e_validate_nvm_checksum(struct i40e_hw *hw, 357 u16 *checksum) 358 { 359 i40e_status ret_code = 0; 360 u16 checksum_sr = 0; 361 u16 checksum_local; 362 363 ret_code = i40e_acquire_nvm(hw, I40E_RESOURCE_READ); 364 if (ret_code) 365 goto i40e_validate_nvm_checksum_exit; 366 367 ret_code = i40e_calc_nvm_checksum(hw, &checksum_local); 368 if (ret_code) 369 goto i40e_validate_nvm_checksum_free; 370 371 /* Do not use i40e_read_nvm_word() because we do not want to take 372 * the synchronization semaphores twice here. 373 */ 374 i40e_read_nvm_srctl(hw, I40E_SR_SW_CHECKSUM_WORD, &checksum_sr); 375 376 /* Verify read checksum from EEPROM is the same as 377 * calculated checksum 378 */ 379 if (checksum_local != checksum_sr) 380 ret_code = I40E_ERR_NVM_CHECKSUM; 381 382 /* If the user cares, return the calculated checksum */ 383 if (checksum) 384 *checksum = checksum_local; 385 386 i40e_validate_nvm_checksum_free: 387 i40e_release_nvm(hw); 388 389 i40e_validate_nvm_checksum_exit: 390 return ret_code; 391 } 392