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 if (eeprom->type != ngbe_eeprom_unknown) 24 return 0; 25 26 eeprom->type = ngbe_eeprom_none; 27 /* Set default semaphore delay to 10ms which is a well 28 * tested value 29 */ 30 eeprom->semaphore_delay = 10; /*ms*/ 31 /* Clear EEPROM page size, it will be initialized as needed */ 32 eeprom->word_page_size = 0; 33 34 /* 35 * Check for EEPROM present first. 36 * If not present leave as none 37 */ 38 eec = rd32(hw, NGBE_SPISTAT); 39 if (!(eec & NGBE_SPISTAT_BPFLASH)) { 40 eeprom->type = ngbe_eeprom_flash; 41 42 /* 43 * SPI EEPROM is assumed here. This code would need to 44 * change if a future EEPROM is not SPI. 45 */ 46 eeprom_size = 4096; 47 eeprom->word_size = eeprom_size >> 1; 48 } 49 50 eeprom->address_bits = 16; 51 eeprom->sw_addr = 0x80; 52 53 DEBUGOUT("eeprom params: type = %d, size = %d, address bits: %d %d", 54 eeprom->type, eeprom->word_size, 55 eeprom->address_bits, eeprom->sw_addr); 56 57 return 0; 58 } 59 60 /** 61 * ngbe_get_eeprom_semaphore - Get hardware semaphore 62 * @hw: pointer to hardware structure 63 * 64 * Sets the hardware semaphores so EEPROM access can occur for bit-bang method 65 **/ 66 s32 ngbe_get_eeprom_semaphore(struct ngbe_hw *hw) 67 { 68 s32 status = NGBE_ERR_EEPROM; 69 u32 timeout = 2000; 70 u32 i; 71 u32 swsm; 72 73 /* Get SMBI software semaphore between device drivers first */ 74 for (i = 0; i < timeout; i++) { 75 /* 76 * If the SMBI bit is 0 when we read it, then the bit will be 77 * set and we have the semaphore 78 */ 79 swsm = rd32(hw, NGBE_SWSEM); 80 if (!(swsm & NGBE_SWSEM_PF)) { 81 status = 0; 82 break; 83 } 84 usec_delay(50); 85 } 86 87 if (i == timeout) { 88 DEBUGOUT("Driver can't access the eeprom - SMBI Semaphore not granted."); 89 /* 90 * this release is particularly important because our attempts 91 * above to get the semaphore may have succeeded, and if there 92 * was a timeout, we should unconditionally clear the semaphore 93 * bits to free the driver to make progress 94 */ 95 ngbe_release_eeprom_semaphore(hw); 96 97 usec_delay(50); 98 /* 99 * one last try 100 * If the SMBI bit is 0 when we read it, then the bit will be 101 * set and we have the semaphore 102 */ 103 swsm = rd32(hw, NGBE_SWSEM); 104 if (!(swsm & NGBE_SWSEM_PF)) 105 status = 0; 106 } 107 108 /* Now get the semaphore between SW/FW through the SWESMBI bit */ 109 if (status == 0) { 110 for (i = 0; i < timeout; i++) { 111 /* Set the SW EEPROM semaphore bit to request access */ 112 wr32m(hw, NGBE_MNGSWSYNC, 113 NGBE_MNGSWSYNC_REQ, NGBE_MNGSWSYNC_REQ); 114 115 /* 116 * If we set the bit successfully then we got the 117 * semaphore. 118 */ 119 swsm = rd32(hw, NGBE_MNGSWSYNC); 120 if (swsm & NGBE_MNGSWSYNC_REQ) 121 break; 122 123 usec_delay(50); 124 } 125 126 /* 127 * Release semaphores and return error if SW EEPROM semaphore 128 * was not granted because we don't have access to the EEPROM 129 */ 130 if (i >= timeout) { 131 DEBUGOUT("SWESMBI Software EEPROM semaphore not granted."); 132 ngbe_release_eeprom_semaphore(hw); 133 status = NGBE_ERR_EEPROM; 134 } 135 } else { 136 DEBUGOUT("Software semaphore SMBI between device drivers not granted."); 137 } 138 139 return status; 140 } 141 142 /** 143 * ngbe_release_eeprom_semaphore - Release hardware semaphore 144 * @hw: pointer to hardware structure 145 * 146 * This function clears hardware semaphore bits. 147 **/ 148 void ngbe_release_eeprom_semaphore(struct ngbe_hw *hw) 149 { 150 wr32m(hw, NGBE_MNGSWSYNC, NGBE_MNGSWSYNC_REQ, 0); 151 wr32m(hw, NGBE_SWSEM, NGBE_SWSEM_PF, 0); 152 ngbe_flush(hw); 153 } 154 155 /** 156 * ngbe_ee_read_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 ngbe_ee_readw_buffer(struct ngbe_hw *hw, 165 u32 offset, u32 words, void *data) 166 { 167 const u32 mask = NGBE_MNGSEM_SWMBX | NGBE_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 <= NGBE_PMMBX_DATA_SIZE 179 ? len : NGBE_PMMBX_DATA_SIZE); 180 181 err = ngbe_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 * ngbe_ee_read32 - Read EEPROM word using a host interface cmd 196 * @hw: pointer to hardware structure 197 * @offset: offset of word in the EEPROM to read 198 * @data: word read from the EEPROM 199 * 200 * Reads a 32 bit word from the EEPROM using the hostif. 201 **/ 202 s32 ngbe_ee_read32(struct ngbe_hw *hw, u32 addr, u32 *data) 203 { 204 const u32 mask = NGBE_MNGSEM_SWMBX | NGBE_MNGSEM_SWFLASH; 205 int err; 206 207 err = hw->mac.acquire_swfw_sync(hw, mask); 208 if (err) 209 return err; 210 211 err = ngbe_hic_sr_read(hw, addr, (u8 *)data, 4); 212 213 hw->mac.release_swfw_sync(hw, mask); 214 215 return err; 216 } 217 218 /** 219 * ngbe_ee_write_buffer - Write EEPROM word(s) using hostif 220 * @hw: pointer to hardware structure 221 * @offset: offset of word in the EEPROM to write 222 * @words: number of words 223 * @data: word(s) write to the EEPROM 224 * 225 * Write a 16 bit word(s) to the EEPROM using the hostif. 226 **/ 227 s32 ngbe_ee_writew_buffer(struct ngbe_hw *hw, 228 u32 offset, u32 words, void *data) 229 { 230 const u32 mask = NGBE_MNGSEM_SWMBX | NGBE_MNGSEM_SWFLASH; 231 u32 addr = (offset << 1); 232 u32 len = (words << 1); 233 u8 *buf = (u8 *)data; 234 int err; 235 236 err = hw->mac.acquire_swfw_sync(hw, mask); 237 if (err) 238 return err; 239 240 while (len) { 241 u32 seg = (len <= NGBE_PMMBX_DATA_SIZE 242 ? len : NGBE_PMMBX_DATA_SIZE); 243 244 err = ngbe_hic_sr_write(hw, addr, buf, seg); 245 if (err) 246 break; 247 248 len -= seg; 249 buf += seg; 250 } 251 252 hw->mac.release_swfw_sync(hw, mask); 253 return err; 254 } 255 256 /** 257 * ngbe_validate_eeprom_checksum_em - Validate EEPROM checksum 258 * @hw: pointer to hardware structure 259 * @checksum_val: calculated checksum 260 * 261 * Performs checksum calculation and validates the EEPROM checksum. If the 262 * caller does not need checksum_val, the value can be NULL. 263 **/ 264 s32 ngbe_validate_eeprom_checksum_em(struct ngbe_hw *hw, 265 u16 *checksum_val) 266 { 267 u32 eeprom_cksum_devcap = 0; 268 int err = 0; 269 270 UNREFERENCED_PARAMETER(checksum_val); 271 272 /* Check EEPROM only once */ 273 if (hw->bus.lan_id == 0) { 274 wr32(hw, NGBE_CALSUM_CAP_STATUS, 0x0); 275 wr32(hw, NGBE_EEPROM_VERSION_STORE_REG, 0x0); 276 } else { 277 eeprom_cksum_devcap = rd32(hw, NGBE_CALSUM_CAP_STATUS); 278 hw->rom.saved_version = rd32(hw, NGBE_EEPROM_VERSION_STORE_REG); 279 } 280 281 if (hw->bus.lan_id == 0 || eeprom_cksum_devcap == 0) { 282 err = ngbe_hic_check_cap(hw); 283 if (err != 0) { 284 PMD_INIT_LOG(ERR, 285 "The EEPROM checksum is not valid: %d", err); 286 return -EIO; 287 } 288 } 289 290 hw->rom.cksum_devcap = eeprom_cksum_devcap & 0xffff; 291 292 return err; 293 } 294 295 /** 296 * ngbe_save_eeprom_version 297 * @hw: pointer to hardware structure 298 * 299 * Save off EEPROM version number and Option Rom version which 300 * together make a unique identify for the eeprom 301 */ 302 s32 ngbe_save_eeprom_version(struct ngbe_hw *hw) 303 { 304 u32 eeprom_verl = 0; 305 u32 etrack_id = 0; 306 u32 offset = (hw->rom.sw_addr + NGBE_EEPROM_VERSION_L) << 1; 307 308 if (hw->bus.lan_id == 0) { 309 hw->rom.read32(hw, offset, &eeprom_verl); 310 etrack_id = eeprom_verl; 311 wr32(hw, NGBE_EEPROM_VERSION_STORE_REG, etrack_id); 312 wr32(hw, NGBE_CALSUM_CAP_STATUS, 313 hw->rom.cksum_devcap | 0x10000); 314 } else if (hw->rom.cksum_devcap) { 315 etrack_id = hw->rom.saved_version; 316 } else { 317 hw->rom.read32(hw, offset, &eeprom_verl); 318 etrack_id = eeprom_verl; 319 } 320 321 hw->eeprom_id = etrack_id; 322 323 return 0; 324 } 325