1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2015-2020 Beijing WangXun Technology Co., Ltd.
3 * Copyright(c) 2010-2017 Intel Corporation
8 #include "txgbe_eeprom.h"
11 * txgbe_init_eeprom_params - Initialize EEPROM params
12 * @hw: pointer to hardware structure
14 * Initializes the EEPROM parameters txgbe_rom_info within the
15 * txgbe_hw struct in order to set up EEPROM access.
17 s32 txgbe_init_eeprom_params(struct txgbe_hw *hw)
19 struct txgbe_rom_info *eeprom = &hw->rom;
24 DEBUGFUNC("txgbe_init_eeprom_params");
26 if (eeprom->type != txgbe_eeprom_unknown)
29 eeprom->type = txgbe_eeprom_none;
30 /* Set default semaphore delay to 10ms which is a well
33 eeprom->semaphore_delay = 10; /*ms*/
34 /* Clear EEPROM page size, it will be initialized as needed */
35 eeprom->word_page_size = 0;
38 * Check for EEPROM present first.
39 * If not present leave as none
41 eec = rd32(hw, TXGBE_SPISTAT);
42 if (!(eec & TXGBE_SPISTAT_BPFLASH)) {
43 eeprom->type = txgbe_eeprom_flash;
46 * SPI EEPROM is assumed here. This code would need to
47 * change if a future EEPROM is not SPI.
50 eeprom->word_size = eeprom_size >> 1;
53 eeprom->address_bits = 16;
55 err = eeprom->read32(hw, TXGBE_SW_REGION_PTR << 1, &eeprom->sw_addr);
57 DEBUGOUT("EEPROM read failed.\n");
61 DEBUGOUT("eeprom params: type = %d, size = %d, address bits: "
62 "%d %d\n", eeprom->type, eeprom->word_size,
63 eeprom->address_bits, eeprom->sw_addr);
69 * txgbe_get_eeprom_semaphore - Get hardware semaphore
70 * @hw: pointer to hardware structure
72 * Sets the hardware semaphores so EEPROM access can occur for bit-bang method
74 s32 txgbe_get_eeprom_semaphore(struct txgbe_hw *hw)
76 s32 status = TXGBE_ERR_EEPROM;
81 DEBUGFUNC("txgbe_get_eeprom_semaphore");
84 /* Get SMBI software semaphore between device drivers first */
85 for (i = 0; i < timeout; i++) {
87 * If the SMBI bit is 0 when we read it, then the bit will be
88 * set and we have the semaphore
90 swsm = rd32(hw, TXGBE_SWSEM);
91 if (!(swsm & TXGBE_SWSEM_PF)) {
99 DEBUGOUT("Driver can't access the eeprom - SMBI Semaphore "
102 * this release is particularly important because our attempts
103 * above to get the semaphore may have succeeded, and if there
104 * was a timeout, we should unconditionally clear the semaphore
105 * bits to free the driver to make progress
107 txgbe_release_eeprom_semaphore(hw);
112 * If the SMBI bit is 0 when we read it, then the bit will be
113 * set and we have the semaphore
115 swsm = rd32(hw, TXGBE_SWSEM);
116 if (!(swsm & TXGBE_SWSEM_PF))
120 /* Now get the semaphore between SW/FW through the SWESMBI bit */
122 for (i = 0; i < timeout; i++) {
123 /* Set the SW EEPROM semaphore bit to request access */
124 wr32m(hw, TXGBE_MNGSWSYNC,
125 TXGBE_MNGSWSYNC_REQ, TXGBE_MNGSWSYNC_REQ);
128 * If we set the bit successfully then we got the
131 swsm = rd32(hw, TXGBE_MNGSWSYNC);
132 if (swsm & TXGBE_MNGSWSYNC_REQ)
139 * Release semaphores and return error if SW EEPROM semaphore
140 * was not granted because we don't have access to the EEPROM
143 DEBUGOUT("SWESMBI Software EEPROM semaphore not granted.\n");
144 txgbe_release_eeprom_semaphore(hw);
145 status = TXGBE_ERR_EEPROM;
148 DEBUGOUT("Software semaphore SMBI between device drivers "
156 * txgbe_release_eeprom_semaphore - Release hardware semaphore
157 * @hw: pointer to hardware structure
159 * This function clears hardware semaphore bits.
161 void txgbe_release_eeprom_semaphore(struct txgbe_hw *hw)
163 DEBUGFUNC("txgbe_release_eeprom_semaphore");
165 wr32m(hw, TXGBE_MNGSWSYNC, TXGBE_MNGSWSYNC_REQ, 0);
166 wr32m(hw, TXGBE_SWSEM, TXGBE_SWSEM_PF, 0);
171 * txgbe_ee_read - Read EEPROM word using a host interface cmd
172 * @hw: pointer to hardware structure
173 * @offset: offset of word in the EEPROM to read
174 * @data: word read from the EEPROM
176 * Reads a 16 bit word from the EEPROM using the hostif.
178 s32 txgbe_ee_read16(struct txgbe_hw *hw, u32 offset,
181 const u32 mask = TXGBE_MNGSEM_SWMBX | TXGBE_MNGSEM_SWFLASH;
182 u32 addr = (offset << 1);
185 err = hw->mac.acquire_swfw_sync(hw, mask);
189 err = txgbe_hic_sr_read(hw, addr, (u8 *)data, 2);
191 hw->mac.release_swfw_sync(hw, mask);
197 * txgbe_ee_readw_buffer- Read EEPROM word(s) using hostif
198 * @hw: pointer to hardware structure
199 * @offset: offset of word in the EEPROM to read
200 * @words: number of words
201 * @data: word(s) read from the EEPROM
203 * Reads a 16 bit word(s) from the EEPROM using the hostif.
205 s32 txgbe_ee_readw_buffer(struct txgbe_hw *hw,
206 u32 offset, u32 words, void *data)
208 const u32 mask = TXGBE_MNGSEM_SWMBX | TXGBE_MNGSEM_SWFLASH;
209 u32 addr = (offset << 1);
210 u32 len = (words << 1);
211 u8 *buf = (u8 *)data;
214 err = hw->mac.acquire_swfw_sync(hw, mask);
219 u32 seg = (len <= TXGBE_PMMBX_DATA_SIZE
220 ? len : TXGBE_PMMBX_DATA_SIZE);
222 err = txgbe_hic_sr_read(hw, addr, buf, seg);
231 hw->mac.release_swfw_sync(hw, mask);
236 s32 txgbe_ee_readw_sw(struct txgbe_hw *hw, u32 offset,
239 const u32 mask = TXGBE_MNGSEM_SWMBX | TXGBE_MNGSEM_SWFLASH;
240 u32 addr = hw->rom.sw_addr + (offset << 1);
243 err = hw->mac.acquire_swfw_sync(hw, mask);
247 err = txgbe_hic_sr_read(hw, addr, (u8 *)data, 2);
249 hw->mac.release_swfw_sync(hw, mask);
255 * txgbe_ee_read32 - Read EEPROM word using a host interface cmd
256 * @hw: pointer to hardware structure
257 * @offset: offset of word in the EEPROM to read
258 * @data: word read from the EEPROM
260 * Reads a 32 bit word from the EEPROM using the hostif.
262 s32 txgbe_ee_read32(struct txgbe_hw *hw, u32 addr, u32 *data)
264 const u32 mask = TXGBE_MNGSEM_SWMBX | TXGBE_MNGSEM_SWFLASH;
267 err = hw->mac.acquire_swfw_sync(hw, mask);
271 err = txgbe_hic_sr_read(hw, addr, (u8 *)data, 4);
273 hw->mac.release_swfw_sync(hw, mask);
279 * txgbe_ee_write - Write EEPROM word using hostif
280 * @hw: pointer to hardware structure
281 * @offset: offset of word in the EEPROM to write
282 * @data: word write to the EEPROM
284 * Write a 16 bit word to the EEPROM using the hostif.
286 s32 txgbe_ee_write16(struct txgbe_hw *hw, u32 offset,
289 const u32 mask = TXGBE_MNGSEM_SWMBX | TXGBE_MNGSEM_SWFLASH;
290 u32 addr = (offset << 1);
295 err = hw->mac.acquire_swfw_sync(hw, mask);
299 err = txgbe_hic_sr_write(hw, addr, (u8 *)&data, 2);
301 hw->mac.release_swfw_sync(hw, mask);
307 * txgbe_ee_writew_buffer - Write EEPROM word(s) using hostif
308 * @hw: pointer to hardware structure
309 * @offset: offset of word in the EEPROM to write
310 * @words: number of words
311 * @data: word(s) write to the EEPROM
313 * Write a 16 bit word(s) to the EEPROM using the hostif.
315 s32 txgbe_ee_writew_buffer(struct txgbe_hw *hw,
316 u32 offset, u32 words, void *data)
318 const u32 mask = TXGBE_MNGSEM_SWMBX | TXGBE_MNGSEM_SWFLASH;
319 u32 addr = (offset << 1);
320 u32 len = (words << 1);
321 u8 *buf = (u8 *)data;
324 err = hw->mac.acquire_swfw_sync(hw, mask);
329 u32 seg = (len <= TXGBE_PMMBX_DATA_SIZE
330 ? len : TXGBE_PMMBX_DATA_SIZE);
332 err = txgbe_hic_sr_write(hw, addr, buf, seg);
340 hw->mac.release_swfw_sync(hw, mask);
344 s32 txgbe_ee_writew_sw(struct txgbe_hw *hw, u32 offset,
347 const u32 mask = TXGBE_MNGSEM_SWMBX | TXGBE_MNGSEM_SWFLASH;
348 u32 addr = hw->rom.sw_addr + (offset << 1);
353 err = hw->mac.acquire_swfw_sync(hw, mask);
357 err = txgbe_hic_sr_write(hw, addr, (u8 *)&data, 2);
359 hw->mac.release_swfw_sync(hw, mask);
365 * txgbe_ee_write32 - Read EEPROM word using a host interface cmd
366 * @hw: pointer to hardware structure
367 * @offset: offset of word in the EEPROM to read
368 * @data: word read from the EEPROM
370 * Reads a 32 bit word from the EEPROM using the hostif.
372 s32 txgbe_ee_write32(struct txgbe_hw *hw, u32 addr, u32 data)
374 const u32 mask = TXGBE_MNGSEM_SWMBX | TXGBE_MNGSEM_SWFLASH;
377 err = hw->mac.acquire_swfw_sync(hw, mask);
381 err = txgbe_hic_sr_write(hw, addr, (u8 *)&data, 4);
383 hw->mac.release_swfw_sync(hw, mask);
389 * txgbe_calc_eeprom_checksum - Calculates and returns the checksum
390 * @hw: pointer to hardware structure
392 * Returns a negative error code on error, or the 16-bit checksum
395 s32 txgbe_calc_eeprom_checksum(struct txgbe_hw *hw)
397 u16 checksum = 0, read_checksum = 0;
400 u16 buffer[BUFF_SIZE];
402 DEBUGFUNC("txgbe_calc_eeprom_checksum");
404 err = hw->rom.readw_sw(hw, TXGBE_EEPROM_CHECKSUM, &read_checksum);
406 DEBUGOUT("EEPROM read failed\n");
410 for (i = 0; i < TXGBE_EE_CSUM_MAX; i += seg) {
411 seg = (i + BUFF_SIZE < TXGBE_EE_CSUM_MAX
412 ? BUFF_SIZE : TXGBE_EE_CSUM_MAX - i);
413 err = hw->rom.readw_buffer(hw, i, seg, buffer);
416 for (j = 0; j < seg; j++)
417 checksum += buffer[j];
420 checksum = (u16)TXGBE_EEPROM_SUM - checksum + read_checksum;
422 return (s32)checksum;
426 * txgbe_validate_eeprom_checksum - Validate EEPROM checksum
427 * @hw: pointer to hardware structure
428 * @checksum_val: calculated checksum
430 * Performs checksum calculation and validates the EEPROM checksum. If the
431 * caller does not need checksum_val, the value can be NULL.
433 s32 txgbe_validate_eeprom_checksum(struct txgbe_hw *hw,
437 u16 read_checksum = 0;
440 DEBUGFUNC("txgbe_validate_eeprom_checksum");
442 /* Read the first word from the EEPROM. If this times out or fails, do
443 * not continue or we could be in for a very long wait while every
446 err = hw->rom.read16(hw, 0, &checksum);
448 DEBUGOUT("EEPROM read failed\n");
452 err = hw->rom.calc_checksum(hw);
456 checksum = (u16)(err & 0xffff);
458 err = hw->rom.readw_sw(hw, TXGBE_EEPROM_CHECKSUM, &read_checksum);
460 DEBUGOUT("EEPROM read failed\n");
464 /* Verify read checksum from EEPROM is the same as
465 * calculated checksum
467 if (read_checksum != checksum) {
468 err = TXGBE_ERR_EEPROM_CHECKSUM;
469 DEBUGOUT("EEPROM checksum error\n");
472 /* If the user cares, return the calculated checksum */
474 *checksum_val = checksum;
480 * txgbe_update_eeprom_checksum - Updates the EEPROM checksum
481 * @hw: pointer to hardware structure
483 s32 txgbe_update_eeprom_checksum(struct txgbe_hw *hw)
488 DEBUGFUNC("txgbe_update_eeprom_checksum");
490 /* Read the first word from the EEPROM. If this times out or fails, do
491 * not continue or we could be in for a very long wait while every
494 status = hw->rom.read16(hw, 0, &checksum);
496 DEBUGOUT("EEPROM read failed\n");
500 status = hw->rom.calc_checksum(hw);
504 checksum = (u16)(status & 0xffff);
506 status = hw->rom.writew_sw(hw, TXGBE_EEPROM_CHECKSUM, checksum);