1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2015-2020 Beijing WangXun Technology Co., Ltd. 3 * Copyright(c) 2010-2017 Intel Corporation 4 */ 5 6 #include "txgbe_hw.h" 7 #include "txgbe_mng.h" 8 #include "txgbe_eeprom.h" 9 10 /** 11 * txgbe_init_eeprom_params - Initialize EEPROM params 12 * @hw: pointer to hardware structure 13 * 14 * Initializes the EEPROM parameters txgbe_rom_info within the 15 * txgbe_hw struct in order to set up EEPROM access. 16 **/ 17 s32 txgbe_init_eeprom_params(struct txgbe_hw *hw) 18 { 19 struct txgbe_rom_info *eeprom = &hw->rom; 20 u32 eec; 21 u16 eeprom_size; 22 int err = 0; 23 24 if (eeprom->type != txgbe_eeprom_unknown) 25 return 0; 26 27 eeprom->type = txgbe_eeprom_none; 28 /* Set default semaphore delay to 10ms which is a well 29 * tested value 30 */ 31 eeprom->semaphore_delay = 10; /*ms*/ 32 /* Clear EEPROM page size, it will be initialized as needed */ 33 eeprom->word_page_size = 0; 34 35 /* 36 * Check for EEPROM present first. 37 * If not present leave as none 38 */ 39 eec = rd32(hw, TXGBE_SPISTAT); 40 if (!(eec & TXGBE_SPISTAT_BPFLASH)) { 41 eeprom->type = txgbe_eeprom_flash; 42 43 /* 44 * SPI EEPROM is assumed here. This code would need to 45 * change if a future EEPROM is not SPI. 46 */ 47 eeprom_size = 4096; 48 eeprom->word_size = eeprom_size >> 1; 49 } 50 51 eeprom->address_bits = 16; 52 53 err = eeprom->read32(hw, TXGBE_SW_REGION_PTR << 1, &eeprom->sw_addr); 54 if (err) { 55 DEBUGOUT("EEPROM read failed."); 56 return err; 57 } 58 59 DEBUGOUT("eeprom params: type = %d, size = %d, address bits: %d %d", 60 eeprom->type, eeprom->word_size, 61 eeprom->address_bits, eeprom->sw_addr); 62 63 return 0; 64 } 65 66 /** 67 * txgbe_get_eeprom_semaphore - Get hardware semaphore 68 * @hw: pointer to hardware structure 69 * 70 * Sets the hardware semaphores so EEPROM access can occur for bit-bang method 71 **/ 72 s32 txgbe_get_eeprom_semaphore(struct txgbe_hw *hw) 73 { 74 s32 status = TXGBE_ERR_EEPROM; 75 u32 timeout = 2000; 76 u32 i; 77 u32 swsm; 78 79 /* Get SMBI software semaphore between device drivers first */ 80 for (i = 0; i < timeout; i++) { 81 /* 82 * If the SMBI bit is 0 when we read it, then the bit will be 83 * set and we have the semaphore 84 */ 85 swsm = rd32(hw, TXGBE_SWSEM); 86 if (!(swsm & TXGBE_SWSEM_PF)) { 87 status = 0; 88 break; 89 } 90 usec_delay(50); 91 } 92 93 if (i == timeout) { 94 DEBUGOUT("Driver can't access the eeprom - SMBI Semaphore not granted."); 95 /* 96 * this release is particularly important because our attempts 97 * above to get the semaphore may have succeeded, and if there 98 * was a timeout, we should unconditionally clear the semaphore 99 * bits to free the driver to make progress 100 */ 101 txgbe_release_eeprom_semaphore(hw); 102 103 usec_delay(50); 104 /* 105 * one last try 106 * If the SMBI bit is 0 when we read it, then the bit will be 107 * set and we have the semaphore 108 */ 109 swsm = rd32(hw, TXGBE_SWSEM); 110 if (!(swsm & TXGBE_SWSEM_PF)) 111 status = 0; 112 } 113 114 return status; 115 } 116 117 /** 118 * txgbe_release_eeprom_semaphore - Release hardware semaphore 119 * @hw: pointer to hardware structure 120 * 121 * This function clears hardware semaphore bits. 122 **/ 123 void txgbe_release_eeprom_semaphore(struct txgbe_hw *hw) 124 { 125 wr32m(hw, TXGBE_SWSEM, TXGBE_SWSEM_PF, 0); 126 txgbe_flush(hw); 127 } 128 129 /** 130 * txgbe_ee_read - Read EEPROM word using a host interface cmd 131 * @hw: pointer to hardware structure 132 * @offset: offset of word in the EEPROM to read 133 * @data: word read from the EEPROM 134 * 135 * Reads a 16 bit word from the EEPROM using the hostif. 136 **/ 137 s32 txgbe_ee_read16(struct txgbe_hw *hw, u32 offset, 138 u16 *data) 139 { 140 const u32 mask = TXGBE_MNGSEM_SWMBX | TXGBE_MNGSEM_SWFLASH; 141 u32 addr = (offset << 1); 142 int err; 143 144 err = hw->mac.acquire_swfw_sync(hw, mask); 145 if (err) 146 return err; 147 148 err = txgbe_hic_sr_read(hw, addr, (u8 *)data, 2); 149 150 hw->mac.release_swfw_sync(hw, mask); 151 152 return err; 153 } 154 155 /** 156 * txgbe_ee_readw_buffer- Read EEPROM word(s) using hostif 157 * @hw: pointer to hardware structure 158 * @offset: offset of word in the EEPROM to read 159 * @words: number of words 160 * @data: word(s) read from the EEPROM 161 * 162 * Reads a 16 bit word(s) from the EEPROM using the hostif. 163 **/ 164 s32 txgbe_ee_readw_buffer(struct txgbe_hw *hw, 165 u32 offset, u32 words, void *data) 166 { 167 const u32 mask = TXGBE_MNGSEM_SWMBX | TXGBE_MNGSEM_SWFLASH; 168 u32 addr = (offset << 1); 169 u32 len = (words << 1); 170 u8 *buf = (u8 *)data; 171 int err; 172 173 err = hw->mac.acquire_swfw_sync(hw, mask); 174 if (err) 175 return err; 176 177 while (len) { 178 u32 seg = (len <= TXGBE_PMMBX_DATA_SIZE 179 ? len : TXGBE_PMMBX_DATA_SIZE); 180 181 err = txgbe_hic_sr_read(hw, addr, buf, seg); 182 if (err) 183 break; 184 185 len -= seg; 186 addr += seg; 187 buf += seg; 188 } 189 190 hw->mac.release_swfw_sync(hw, mask); 191 return err; 192 } 193 194 195 s32 txgbe_ee_readw_sw(struct txgbe_hw *hw, u32 offset, 196 u16 *data) 197 { 198 const u32 mask = TXGBE_MNGSEM_SWMBX | TXGBE_MNGSEM_SWFLASH; 199 u32 addr = hw->rom.sw_addr + (offset << 1); 200 int err; 201 202 err = hw->mac.acquire_swfw_sync(hw, mask); 203 if (err) 204 return err; 205 206 err = txgbe_hic_sr_read(hw, addr, (u8 *)data, 2); 207 208 hw->mac.release_swfw_sync(hw, mask); 209 210 return err; 211 } 212 213 /** 214 * txgbe_ee_read32 - Read EEPROM word using a host interface cmd 215 * @hw: pointer to hardware structure 216 * @offset: offset of word in the EEPROM to read 217 * @data: word read from the EEPROM 218 * 219 * Reads a 32 bit word from the EEPROM using the hostif. 220 **/ 221 s32 txgbe_ee_read32(struct txgbe_hw *hw, u32 addr, u32 *data) 222 { 223 const u32 mask = TXGBE_MNGSEM_SWMBX | TXGBE_MNGSEM_SWFLASH; 224 int err; 225 226 err = hw->mac.acquire_swfw_sync(hw, mask); 227 if (err) 228 return err; 229 230 err = txgbe_hic_sr_read(hw, addr, (u8 *)data, 4); 231 232 hw->mac.release_swfw_sync(hw, mask); 233 234 return err; 235 } 236 237 /** 238 * txgbe_ee_write - Write EEPROM word using hostif 239 * @hw: pointer to hardware structure 240 * @offset: offset of word in the EEPROM to write 241 * @data: word write to the EEPROM 242 * 243 * Write a 16 bit word to the EEPROM using the hostif. 244 **/ 245 s32 txgbe_ee_write16(struct txgbe_hw *hw, u32 offset, 246 u16 data) 247 { 248 const u32 mask = TXGBE_MNGSEM_SWMBX | TXGBE_MNGSEM_SWFLASH; 249 u32 addr = (offset << 1); 250 int err; 251 252 err = hw->mac.acquire_swfw_sync(hw, mask); 253 if (err) 254 return err; 255 256 err = txgbe_hic_sr_write(hw, addr, (u8 *)&data, 2); 257 258 hw->mac.release_swfw_sync(hw, mask); 259 260 return err; 261 } 262 263 /** 264 * txgbe_ee_writew_buffer - Write EEPROM word(s) using hostif 265 * @hw: pointer to hardware structure 266 * @offset: offset of word in the EEPROM to write 267 * @words: number of words 268 * @data: word(s) write to the EEPROM 269 * 270 * Write a 16 bit word(s) to the EEPROM using the hostif. 271 **/ 272 s32 txgbe_ee_writew_buffer(struct txgbe_hw *hw, 273 u32 offset, u32 words, void *data) 274 { 275 const u32 mask = TXGBE_MNGSEM_SWMBX | TXGBE_MNGSEM_SWFLASH; 276 u32 addr = (offset << 1); 277 u32 len = (words << 1); 278 u8 *buf = (u8 *)data; 279 int err; 280 281 err = hw->mac.acquire_swfw_sync(hw, mask); 282 if (err) 283 return err; 284 285 while (len) { 286 u32 seg = (len <= TXGBE_PMMBX_DATA_SIZE 287 ? len : TXGBE_PMMBX_DATA_SIZE); 288 289 err = txgbe_hic_sr_write(hw, addr, buf, seg); 290 if (err) 291 break; 292 293 len -= seg; 294 buf += seg; 295 } 296 297 hw->mac.release_swfw_sync(hw, mask); 298 return err; 299 } 300 301 s32 txgbe_ee_writew_sw(struct txgbe_hw *hw, u32 offset, 302 u16 data) 303 { 304 const u32 mask = TXGBE_MNGSEM_SWMBX | TXGBE_MNGSEM_SWFLASH; 305 u32 addr = hw->rom.sw_addr + (offset << 1); 306 int err; 307 308 err = hw->mac.acquire_swfw_sync(hw, mask); 309 if (err) 310 return err; 311 312 err = txgbe_hic_sr_write(hw, addr, (u8 *)&data, 2); 313 314 hw->mac.release_swfw_sync(hw, mask); 315 316 return err; 317 } 318 319 /** 320 * txgbe_ee_write32 - Read EEPROM word using a host interface cmd 321 * @hw: pointer to hardware structure 322 * @offset: offset of word in the EEPROM to read 323 * @data: word read from the EEPROM 324 * 325 * Reads a 32 bit word from the EEPROM using the hostif. 326 **/ 327 s32 txgbe_ee_write32(struct txgbe_hw *hw, u32 addr, u32 data) 328 { 329 const u32 mask = TXGBE_MNGSEM_SWMBX | TXGBE_MNGSEM_SWFLASH; 330 int err; 331 332 err = hw->mac.acquire_swfw_sync(hw, mask); 333 if (err) 334 return err; 335 336 err = txgbe_hic_sr_write(hw, addr, (u8 *)&data, 4); 337 338 hw->mac.release_swfw_sync(hw, mask); 339 340 return err; 341 } 342 343 /** 344 * txgbe_calc_eeprom_checksum - Calculates and returns the checksum 345 * @hw: pointer to hardware structure 346 * 347 * Returns a negative error code on error, or the 16-bit checksum 348 **/ 349 #define BUFF_SIZE 64 350 s32 txgbe_calc_eeprom_checksum(struct txgbe_hw *hw) 351 { 352 u16 checksum = 0, read_checksum = 0; 353 int i, j, seg; 354 int err; 355 u16 buffer[BUFF_SIZE]; 356 357 err = hw->rom.readw_sw(hw, TXGBE_EEPROM_CHECKSUM, &read_checksum); 358 if (err) { 359 DEBUGOUT("EEPROM read failed"); 360 return err; 361 } 362 363 for (i = 0; i < TXGBE_EE_CSUM_MAX; i += seg) { 364 seg = (i + BUFF_SIZE < TXGBE_EE_CSUM_MAX 365 ? BUFF_SIZE : TXGBE_EE_CSUM_MAX - i); 366 err = hw->rom.readw_buffer(hw, i, seg, buffer); 367 if (err) 368 return err; 369 for (j = 0; j < seg; j++) 370 checksum += buffer[j]; 371 } 372 373 checksum = (u16)TXGBE_EEPROM_SUM - checksum + read_checksum; 374 375 return (s32)checksum; 376 } 377 378 /** 379 * txgbe_validate_eeprom_checksum - Validate EEPROM checksum 380 * @hw: pointer to hardware structure 381 * @checksum_val: calculated checksum 382 * 383 * Performs checksum calculation and validates the EEPROM checksum. If the 384 * caller does not need checksum_val, the value can be NULL. 385 **/ 386 s32 txgbe_validate_eeprom_checksum(struct txgbe_hw *hw, 387 u16 *checksum_val) 388 { 389 u16 checksum; 390 u16 read_checksum = 0; 391 int err; 392 393 /* Read the first word from the EEPROM. If this times out or fails, do 394 * not continue or we could be in for a very long wait while every 395 * EEPROM read fails 396 */ 397 err = hw->rom.read16(hw, 0, &checksum); 398 if (err) { 399 DEBUGOUT("EEPROM read failed"); 400 return err; 401 } 402 403 err = hw->rom.calc_checksum(hw); 404 if (err < 0) 405 return err; 406 407 checksum = (u16)(err & 0xffff); 408 409 err = hw->rom.readw_sw(hw, TXGBE_EEPROM_CHECKSUM, &read_checksum); 410 if (err) { 411 DEBUGOUT("EEPROM read failed"); 412 return err; 413 } 414 415 /* Verify read checksum from EEPROM is the same as 416 * calculated checksum 417 */ 418 if (read_checksum != checksum) { 419 err = TXGBE_ERR_EEPROM_CHECKSUM; 420 DEBUGOUT("EEPROM checksum error"); 421 } 422 423 /* If the user cares, return the calculated checksum */ 424 if (checksum_val) 425 *checksum_val = checksum; 426 427 return err; 428 } 429 430 /** 431 * txgbe_update_eeprom_checksum - Updates the EEPROM checksum 432 * @hw: pointer to hardware structure 433 **/ 434 s32 txgbe_update_eeprom_checksum(struct txgbe_hw *hw) 435 { 436 s32 status; 437 u16 checksum; 438 439 /* Read the first word from the EEPROM. If this times out or fails, do 440 * not continue or we could be in for a very long wait while every 441 * EEPROM read fails 442 */ 443 status = hw->rom.read16(hw, 0, &checksum); 444 if (status) { 445 DEBUGOUT("EEPROM read failed"); 446 return status; 447 } 448 449 status = hw->rom.calc_checksum(hw); 450 if (status < 0) 451 return status; 452 453 checksum = (u16)(status & 0xffff); 454 455 status = hw->rom.writew_sw(hw, TXGBE_EEPROM_CHECKSUM, checksum); 456 457 return status; 458 } 459 460