📄 e1000_nvm.c
字号:
/** * e1000_read_nvm_microwire - Reads EEPROM's using microwire * @hw: pointer to the HW structure * @offset: offset of word in the EEPROM to read * @words: number of words to read * @data: word read from the EEPROM * * Reads a 16 bit word from the EEPROM. **/s32 e1000_read_nvm_microwire(struct e1000_hw *hw, u16 offset, u16 words, u16 *data){ struct e1000_nvm_info *nvm = &hw->nvm; u32 i = 0; s32 ret_val; u8 read_opcode = NVM_READ_OPCODE_MICROWIRE; DEBUGFUNC("e1000_read_nvm_microwire"); /* * A check for invalid values: offset too large, too many words, * and not enough words. */ if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || (words == 0)) { DEBUGOUT("nvm parameter(s) out of bounds\n"); ret_val = -E1000_ERR_NVM; goto out; } ret_val = nvm->ops.acquire(hw); if (ret_val) goto out; ret_val = e1000_ready_nvm_eeprom(hw); if (ret_val) goto release; for (i = 0; i < words; i++) { /* Send the READ command (opcode + addr) */ e1000_shift_out_eec_bits(hw, read_opcode, nvm->opcode_bits); e1000_shift_out_eec_bits(hw, (u16)(offset + i), nvm->address_bits); /* * Read the data. For microwire, each word requires the * overhead of setup and tear-down. */ data[i] = e1000_shift_in_eec_bits(hw, 16); e1000_standby_nvm(hw); }release: nvm->ops.release(hw);out: return ret_val;}/** * e1000_read_nvm_eerd - Reads EEPROM using EERD register * @hw: pointer to the HW structure * @offset: offset of word in the EEPROM to read * @words: number of words to read * @data: word read from the EEPROM * * Reads a 16 bit word from the EEPROM using the EERD register. **/s32 e1000_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data){ struct e1000_nvm_info *nvm = &hw->nvm; u32 i, eerd = 0; s32 ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_read_nvm_eerd"); /* * A check for invalid values: offset too large, too many words, * too many words for the offset, and not enough words. */ if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || (words == 0)) { DEBUGOUT("nvm parameter(s) out of bounds\n"); ret_val = -E1000_ERR_NVM; goto out; } for (i = 0; i < words; i++) { eerd = ((offset+i) << E1000_NVM_RW_ADDR_SHIFT) + E1000_NVM_RW_REG_START; E1000_WRITE_REG(hw, E1000_EERD, eerd); ret_val = e1000_poll_eerd_eewr_done(hw, E1000_NVM_POLL_READ); if (ret_val) break; data[i] = (E1000_READ_REG(hw, E1000_EERD) >> E1000_NVM_RW_REG_DATA); }out: return ret_val;}/** * e1000_write_nvm_spi - Write to EEPROM using SPI * @hw: pointer to the HW structure * @offset: offset within the EEPROM to be written to * @words: number of words to write * @data: 16 bit word(s) to be written to the EEPROM * * Writes data to EEPROM at offset using SPI interface. * * If e1000_update_nvm_checksum is not called after this function , the * EEPROM will most likely contain an invalid checksum. **/s32 e1000_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data){ struct e1000_nvm_info *nvm = &hw->nvm; s32 ret_val; u16 widx = 0; DEBUGFUNC("e1000_write_nvm_spi"); /* * A check for invalid values: offset too large, too many words, * and not enough words. */ if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || (words == 0)) { DEBUGOUT("nvm parameter(s) out of bounds\n"); ret_val = -E1000_ERR_NVM; goto out; } ret_val = nvm->ops.acquire(hw); if (ret_val) goto out; while (widx < words) { u8 write_opcode = NVM_WRITE_OPCODE_SPI; ret_val = e1000_ready_nvm_eeprom(hw); if (ret_val) goto release; e1000_standby_nvm(hw); /* Send the WRITE ENABLE command (8 bit opcode) */ e1000_shift_out_eec_bits(hw, NVM_WREN_OPCODE_SPI, nvm->opcode_bits); e1000_standby_nvm(hw); /* * Some SPI eeproms use the 8th address bit embedded in the * opcode */ if ((nvm->address_bits == 8) && (offset >= 128)) write_opcode |= NVM_A8_OPCODE_SPI; /* Send the Write command (8-bit opcode + addr) */ e1000_shift_out_eec_bits(hw, write_opcode, nvm->opcode_bits); e1000_shift_out_eec_bits(hw, (u16)((offset + widx) * 2), nvm->address_bits); /* Loop to allow for up to whole page write of eeprom */ while (widx < words) { u16 word_out = data[widx]; word_out = (word_out >> 8) | (word_out << 8); e1000_shift_out_eec_bits(hw, word_out, 16); widx++; if ((((offset + widx) * 2) % nvm->page_size) == 0) { e1000_standby_nvm(hw); break; } } } msec_delay(nvm->semaphore_delay);release: nvm->ops.release(hw);out: return ret_val;}/** * e1000_write_nvm_microwire - Writes EEPROM using microwire * @hw: pointer to the HW structure * @offset: offset within the EEPROM to be written to * @words: number of words to write * @data: 16 bit word(s) to be written to the EEPROM * * Writes data to EEPROM at offset using microwire interface. * * If e1000_update_nvm_checksum is not called after this function , the * EEPROM will most likely contain an invalid checksum. **/s32 e1000_write_nvm_microwire(struct e1000_hw *hw, u16 offset, u16 words, u16 *data){ struct e1000_nvm_info *nvm = &hw->nvm; s32 ret_val; u32 eecd; u16 words_written = 0; u16 widx = 0; DEBUGFUNC("e1000_write_nvm_microwire"); /* * A check for invalid values: offset too large, too many words, * and not enough words. */ if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || (words == 0)) { DEBUGOUT("nvm parameter(s) out of bounds\n"); ret_val = -E1000_ERR_NVM; goto out; } ret_val = nvm->ops.acquire(hw); if (ret_val) goto out; ret_val = e1000_ready_nvm_eeprom(hw); if (ret_val) goto release; e1000_shift_out_eec_bits(hw, NVM_EWEN_OPCODE_MICROWIRE, (u16)(nvm->opcode_bits + 2)); e1000_shift_out_eec_bits(hw, 0, (u16)(nvm->address_bits - 2)); e1000_standby_nvm(hw); while (words_written < words) { e1000_shift_out_eec_bits(hw, NVM_WRITE_OPCODE_MICROWIRE, nvm->opcode_bits); e1000_shift_out_eec_bits(hw, (u16)(offset + words_written), nvm->address_bits); e1000_shift_out_eec_bits(hw, data[words_written], 16); e1000_standby_nvm(hw); for (widx = 0; widx < 200; widx++) { eecd = E1000_READ_REG(hw, E1000_EECD); if (eecd & E1000_EECD_DO) break; usec_delay(50); } if (widx == 200) { DEBUGOUT("NVM Write did not complete\n"); ret_val = -E1000_ERR_NVM; goto release; } e1000_standby_nvm(hw); words_written++; } e1000_shift_out_eec_bits(hw, NVM_EWDS_OPCODE_MICROWIRE, (u16)(nvm->opcode_bits + 2)); e1000_shift_out_eec_bits(hw, 0, (u16)(nvm->address_bits - 2));release: nvm->ops.release(hw);out: return ret_val;}/** * e1000_read_pba_num_generic - Read device part number * @hw: pointer to the HW structure * @pba_num: pointer to device part number * * Reads the product board assembly (PBA) number from the EEPROM and stores * the value in pba_num. **/s32 e1000_read_pba_num_generic(struct e1000_hw *hw, u32 *pba_num){ s32 ret_val; u16 nvm_data; DEBUGFUNC("e1000_read_pba_num_generic"); ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_0, 1, &nvm_data); if (ret_val) { DEBUGOUT("NVM Read Error\n"); goto out; } *pba_num = (u32)(nvm_data << 16); ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_1, 1, &nvm_data); if (ret_val) { DEBUGOUT("NVM Read Error\n"); goto out; } *pba_num |= nvm_data;out: return ret_val;}/** * e1000_read_mac_addr_generic - Read device MAC address * @hw: pointer to the HW structure * * Reads the device MAC address from the EEPROM and stores the value. * Since devices with two ports use the same EEPROM, we increment the * last bit in the MAC address for the second port. **/s32 e1000_read_mac_addr_generic(struct e1000_hw *hw){ s32 ret_val = E1000_SUCCESS; u16 offset, nvm_data, i; DEBUGFUNC("e1000_read_mac_addr"); for (i = 0; i < ETH_ADDR_LEN; i += 2) { offset = i >> 1; ret_val = hw->nvm.ops.read(hw, offset, 1, &nvm_data); if (ret_val) { DEBUGOUT("NVM Read Error\n"); goto out; } hw->mac.perm_addr[i] = (u8)(nvm_data & 0xFF); hw->mac.perm_addr[i+1] = (u8)(nvm_data >> 8); } /* Flip last bit of mac address if we're on second port */ if (hw->bus.func == E1000_FUNC_1) hw->mac.perm_addr[5] ^= 1; for (i = 0; i < ETH_ADDR_LEN; i++) hw->mac.addr[i] = hw->mac.perm_addr[i];out: return ret_val;}/** * e1000_validate_nvm_checksum_generic - Validate EEPROM checksum * @hw: pointer to the HW structure * * Calculates the EEPROM checksum by reading/adding each word of the EEPROM * and then verifies that the sum of the EEPROM is equal to 0xBABA. **/s32 e1000_validate_nvm_checksum_generic(struct e1000_hw *hw){ s32 ret_val = E1000_SUCCESS; u16 checksum = 0; u16 i, nvm_data; DEBUGFUNC("e1000_validate_nvm_checksum_generic"); for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) { ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data); if (ret_val) { DEBUGOUT("NVM Read Error\n"); goto out; } checksum += nvm_data; } if (checksum != (u16) NVM_SUM) { DEBUGOUT("NVM Checksum Invalid\n"); ret_val = -E1000_ERR_NVM; goto out; }out: return ret_val;}/** * e1000_update_nvm_checksum_generic - Update EEPROM checksum * @hw: pointer to the HW structure * * Updates the EEPROM checksum by reading/adding each word of the EEPROM * up to the checksum. Then calculates the EEPROM checksum and writes the * value to the EEPROM. **/s32 e1000_update_nvm_checksum_generic(struct e1000_hw *hw){ s32 ret_val; u16 checksum = 0; u16 i, nvm_data; DEBUGFUNC("e1000_update_nvm_checksum"); for (i = 0; i < NVM_CHECKSUM_REG; i++) { ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data); if (ret_val) { DEBUGOUT("NVM Read Error while updating checksum.\n"); goto out; } checksum += nvm_data; } checksum = (u16) NVM_SUM - checksum; ret_val = hw->nvm.ops.write(hw, NVM_CHECKSUM_REG, 1, &checksum); if (ret_val) { DEBUGOUT("NVM Write Error while updating checksum.\n"); }out: return ret_val;}/** * e1000_reload_nvm_generic - Reloads EEPROM * @hw: pointer to the HW structure * * Reloads the EEPROM by setting the "Reinitialize from EEPROM" bit in the * extended control register. **/void e1000_reload_nvm_generic(struct e1000_hw *hw){ u32 ctrl_ext; DEBUGFUNC("e1000_reload_nvm_generic"); usec_delay(10); ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); ctrl_ext |= E1000_CTRL_EXT_EE_RST; E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); E1000_WRITE_FLUSH(hw);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -