1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2018-2021 Beijing WangXun Technology Co., Ltd. 3 * Copyright(c) 2010-2017 Intel Corporation 4 */ 5 6 #include "ngbe_hw.h" 7 #include "ngbe_mng.h" 8 #include "ngbe_eeprom.h" 9 10 /** 11 * ngbe_init_eeprom_params - Initialize EEPROM params 12 * @hw: pointer to hardware structure 13 * 14 * Initializes the EEPROM parameters ngbe_rom_info within the 15 * ngbe_hw struct in order to set up EEPROM access. 16 **/ 17 s32 ngbe_init_eeprom_params(struct ngbe_hw *hw) 18 { 19 struct ngbe_rom_info *eeprom = &hw->rom; 20 u32 eec; 21 u16 eeprom_size; 22 23 DEBUGFUNC("ngbe_init_eeprom_params"); 24 25 if (eeprom->type != ngbe_eeprom_unknown) 26 return 0; 27 28 eeprom->type = ngbe_eeprom_none; 29 /* Set default semaphore delay to 10ms which is a well 30 * tested value 31 */ 32 eeprom->semaphore_delay = 10; /*ms*/ 33 /* Clear EEPROM page size, it will be initialized as needed */ 34 eeprom->word_page_size = 0; 35 36 /* 37 * Check for EEPROM present first. 38 * If not present leave as none 39 */ 40 eec = rd32(hw, NGBE_SPISTAT); 41 if (!(eec & NGBE_SPISTAT_BPFLASH)) { 42 eeprom->type = ngbe_eeprom_flash; 43 44 /* 45 * SPI EEPROM is assumed here. This code would need to 46 * change if a future EEPROM is not SPI. 47 */ 48 eeprom_size = 4096; 49 eeprom->word_size = eeprom_size >> 1; 50 } 51 52 eeprom->address_bits = 16; 53 eeprom->sw_addr = 0x80; 54 55 DEBUGOUT("eeprom params: type = %d, size = %d, address bits: " 56 "%d %d\n", eeprom->type, eeprom->word_size, 57 eeprom->address_bits, eeprom->sw_addr); 58 59 return 0; 60 } 61 62 /** 63 * ngbe_get_eeprom_semaphore - Get hardware semaphore 64 * @hw: pointer to hardware structure 65 * 66 * Sets the hardware semaphores so EEPROM access can occur for bit-bang method 67 **/ 68 s32 ngbe_get_eeprom_semaphore(struct ngbe_hw *hw) 69 { 70 s32 status = NGBE_ERR_EEPROM; 71 u32 timeout = 2000; 72 u32 i; 73 u32 swsm; 74 75 DEBUGFUNC("ngbe_get_eeprom_semaphore"); 76 77 78 /* Get SMBI software semaphore between device drivers first */ 79 for (i = 0; i < timeout; i++) { 80 /* 81 * If the SMBI bit is 0 when we read it, then the bit will be 82 * set and we have the semaphore 83 */ 84 swsm = rd32(hw, NGBE_SWSEM); 85 if (!(swsm & NGBE_SWSEM_PF)) { 86 status = 0; 87 break; 88 } 89 usec_delay(50); 90 } 91 92 if (i == timeout) { 93 DEBUGOUT("Driver can't access the eeprom - SMBI Semaphore " 94 "not granted.\n"); 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 ngbe_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, NGBE_SWSEM); 110 if (!(swsm & NGBE_SWSEM_PF)) 111 status = 0; 112 } 113 114 /* Now get the semaphore between SW/FW through the SWESMBI bit */ 115 if (status == 0) { 116 for (i = 0; i < timeout; i++) { 117 /* Set the SW EEPROM semaphore bit to request access */ 118 wr32m(hw, NGBE_MNGSWSYNC, 119 NGBE_MNGSWSYNC_REQ, NGBE_MNGSWSYNC_REQ); 120 121 /* 122 * If we set the bit successfully then we got the 123 * semaphore. 124 */ 125 swsm = rd32(hw, NGBE_MNGSWSYNC); 126 if (swsm & NGBE_MNGSWSYNC_REQ) 127 break; 128 129 usec_delay(50); 130 } 131 132 /* 133 * Release semaphores and return error if SW EEPROM semaphore 134 * was not granted because we don't have access to the EEPROM 135 */ 136 if (i >= timeout) { 137 DEBUGOUT("SWESMBI Software EEPROM semaphore not granted.\n"); 138 ngbe_release_eeprom_semaphore(hw); 139 status = NGBE_ERR_EEPROM; 140 } 141 } else { 142 DEBUGOUT("Software semaphore SMBI between device drivers " 143 "not granted.\n"); 144 } 145 146 return status; 147 } 148 149 /** 150 * ngbe_release_eeprom_semaphore - Release hardware semaphore 151 * @hw: pointer to hardware structure 152 * 153 * This function clears hardware semaphore bits. 154 **/ 155 void ngbe_release_eeprom_semaphore(struct ngbe_hw *hw) 156 { 157 DEBUGFUNC("ngbe_release_eeprom_semaphore"); 158 159 wr32m(hw, NGBE_MNGSWSYNC, NGBE_MNGSWSYNC_REQ, 0); 160 wr32m(hw, NGBE_SWSEM, NGBE_SWSEM_PF, 0); 161 ngbe_flush(hw); 162 } 163 164 /** 165 * ngbe_ee_read_buffer- Read EEPROM word(s) using hostif 166 * @hw: pointer to hardware structure 167 * @offset: offset of word in the EEPROM to read 168 * @words: number of words 169 * @data: word(s) read from the EEPROM 170 * 171 * Reads a 16 bit word(s) from the EEPROM using the hostif. 172 **/ 173 s32 ngbe_ee_readw_buffer(struct ngbe_hw *hw, 174 u32 offset, u32 words, void *data) 175 { 176 const u32 mask = NGBE_MNGSEM_SWMBX | NGBE_MNGSEM_SWFLASH; 177 u32 addr = (offset << 1); 178 u32 len = (words << 1); 179 u8 *buf = (u8 *)data; 180 int err; 181 182 err = hw->mac.acquire_swfw_sync(hw, mask); 183 if (err) 184 return err; 185 186 while (len) { 187 u32 seg = (len <= NGBE_PMMBX_DATA_SIZE 188 ? len : NGBE_PMMBX_DATA_SIZE); 189 190 err = ngbe_hic_sr_read(hw, addr, buf, seg); 191 if (err) 192 break; 193 194 len -= seg; 195 addr += seg; 196 buf += seg; 197 } 198 199 hw->mac.release_swfw_sync(hw, mask); 200 return err; 201 } 202 203 /** 204 * ngbe_ee_read32 - Read EEPROM word using a host interface cmd 205 * @hw: pointer to hardware structure 206 * @offset: offset of word in the EEPROM to read 207 * @data: word read from the EEPROM 208 * 209 * Reads a 32 bit word from the EEPROM using the hostif. 210 **/ 211 s32 ngbe_ee_read32(struct ngbe_hw *hw, u32 addr, u32 *data) 212 { 213 const u32 mask = NGBE_MNGSEM_SWMBX | NGBE_MNGSEM_SWFLASH; 214 int err; 215 216 err = hw->mac.acquire_swfw_sync(hw, mask); 217 if (err) 218 return err; 219 220 err = ngbe_hic_sr_read(hw, addr, (u8 *)data, 4); 221 222 hw->mac.release_swfw_sync(hw, mask); 223 224 return err; 225 } 226 227 /** 228 * ngbe_ee_write_buffer - Write EEPROM word(s) using hostif 229 * @hw: pointer to hardware structure 230 * @offset: offset of word in the EEPROM to write 231 * @words: number of words 232 * @data: word(s) write to the EEPROM 233 * 234 * Write a 16 bit word(s) to the EEPROM using the hostif. 235 **/ 236 s32 ngbe_ee_writew_buffer(struct ngbe_hw *hw, 237 u32 offset, u32 words, void *data) 238 { 239 const u32 mask = NGBE_MNGSEM_SWMBX | NGBE_MNGSEM_SWFLASH; 240 u32 addr = (offset << 1); 241 u32 len = (words << 1); 242 u8 *buf = (u8 *)data; 243 int err; 244 245 err = hw->mac.acquire_swfw_sync(hw, mask); 246 if (err) 247 return err; 248 249 while (len) { 250 u32 seg = (len <= NGBE_PMMBX_DATA_SIZE 251 ? len : NGBE_PMMBX_DATA_SIZE); 252 253 err = ngbe_hic_sr_write(hw, addr, buf, seg); 254 if (err) 255 break; 256 257 len -= seg; 258 buf += seg; 259 } 260 261 hw->mac.release_swfw_sync(hw, mask); 262 return err; 263 } 264 265 /** 266 * ngbe_validate_eeprom_checksum_em - Validate EEPROM checksum 267 * @hw: pointer to hardware structure 268 * @checksum_val: calculated checksum 269 * 270 * Performs checksum calculation and validates the EEPROM checksum. If the 271 * caller does not need checksum_val, the value can be NULL. 272 **/ 273 s32 ngbe_validate_eeprom_checksum_em(struct ngbe_hw *hw, 274 u16 *checksum_val) 275 { 276 u32 eeprom_cksum_devcap = 0; 277 int err = 0; 278 279 DEBUGFUNC("ngbe_validate_eeprom_checksum_em"); 280 UNREFERENCED_PARAMETER(checksum_val); 281 282 /* Check EEPROM only once */ 283 if (hw->bus.lan_id == 0) { 284 wr32(hw, NGBE_CALSUM_CAP_STATUS, 0x0); 285 wr32(hw, NGBE_EEPROM_VERSION_STORE_REG, 0x0); 286 } else { 287 eeprom_cksum_devcap = rd32(hw, NGBE_CALSUM_CAP_STATUS); 288 hw->rom.saved_version = rd32(hw, NGBE_EEPROM_VERSION_STORE_REG); 289 } 290 291 if (hw->bus.lan_id == 0 || eeprom_cksum_devcap == 0) { 292 err = ngbe_hic_check_cap(hw); 293 if (err != 0) { 294 PMD_INIT_LOG(ERR, 295 "The EEPROM checksum is not valid: %d", err); 296 return -EIO; 297 } 298 } 299 300 hw->rom.cksum_devcap = eeprom_cksum_devcap & 0xffff; 301 302 return err; 303 } 304 305 /** 306 * ngbe_save_eeprom_version 307 * @hw: pointer to hardware structure 308 * 309 * Save off EEPROM version number and Option Rom version which 310 * together make a unique identify for the eeprom 311 */ 312 s32 ngbe_save_eeprom_version(struct ngbe_hw *hw) 313 { 314 u32 eeprom_verl = 0; 315 u32 etrack_id = 0; 316 u32 offset = (hw->rom.sw_addr + NGBE_EEPROM_VERSION_L) << 1; 317 318 DEBUGFUNC("ngbe_save_eeprom_version"); 319 320 if (hw->bus.lan_id == 0) { 321 hw->rom.read32(hw, offset, &eeprom_verl); 322 etrack_id = eeprom_verl; 323 wr32(hw, NGBE_EEPROM_VERSION_STORE_REG, etrack_id); 324 wr32(hw, NGBE_CALSUM_CAP_STATUS, 325 hw->rom.cksum_devcap | 0x10000); 326 } else if (hw->rom.cksum_devcap) { 327 etrack_id = hw->rom.saved_version; 328 } else { 329 hw->rom.read32(hw, offset, &eeprom_verl); 330 etrack_id = eeprom_verl; 331 } 332 333 hw->eeprom_id = etrack_id; 334 335 return 0; 336 } 337