Commit ef3a0092 authored by Carolyn Wyborny's avatar Carolyn Wyborny Committed by Jeff Kirsher

igb: Refactor NVM read functions to accommodate devices with no flash

This patch refactors NVM read functions in order to accommodate i210 devices
that do not have a flash.  Previously, this was not supported on i210
devices.
Signed-off-by: default avatarCarolyn Wyborny <carolyn.wyborny@intel.com>
Tested-by: default avatarAaron Brown <aaron.f.brown@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
parent 5a823d8c
...@@ -628,6 +628,11 @@ ...@@ -628,6 +628,11 @@
#define E1000_I210_FIFO_SEL_TX_LEGACY E1000_I210_FIFO_SEL_TX_QAV(0) #define E1000_I210_FIFO_SEL_TX_LEGACY E1000_I210_FIFO_SEL_TX_QAV(0)
#define E1000_I210_FIFO_SEL_BMC2OS_TX 0x06 #define E1000_I210_FIFO_SEL_BMC2OS_TX 0x06
#define E1000_I210_FIFO_SEL_BMC2OS_RX 0x01 #define E1000_I210_FIFO_SEL_BMC2OS_RX 0x01
#define E1000_I210_FLASH_SECTOR_SIZE 0x1000 /* 4KB FLASH sector unit size */
/* Secure FLASH mode requires removing MSb */
#define E1000_I210_FW_PTR_MASK 0x7FFF
/* Firmware code revision field word offset*/
#define E1000_I210_FW_VER_OFFSET 328
#define E1000_EECD_FLUPD_I210 0x00800000 /* Update FLASH */ #define E1000_EECD_FLUPD_I210 0x00800000 /* Update FLASH */
#define E1000_EECD_FLUDONE_I210 0x04000000 /* Update FLASH done*/ #define E1000_EECD_FLUDONE_I210 0x04000000 /* Update FLASH done*/
#define E1000_FLUDONE_ATTEMPTS 20000 #define E1000_FLUDONE_ATTEMPTS 20000
......
...@@ -335,57 +335,101 @@ s32 igb_write_nvm_srwr_i210(struct e1000_hw *hw, u16 offset, u16 words, ...@@ -335,57 +335,101 @@ s32 igb_write_nvm_srwr_i210(struct e1000_hw *hw, u16 offset, u16 words,
} }
/** /**
* igb_read_nvm_i211 - Read NVM wrapper function for I211 * igb_read_invm_word_i210 - Reads OTP
* @hw: pointer to the HW structure
* @address: the word address (aka eeprom offset) to read
* @data: pointer to the data read
*
* Reads 16-bit words from the OTP. Return error when the word is not
* stored in OTP.
**/
static s32 igb_read_invm_word_i210(struct e1000_hw *hw, u8 address, u16 *data)
{
s32 status = -E1000_ERR_INVM_VALUE_NOT_FOUND;
u32 invm_dword;
u16 i;
u8 record_type, word_address;
for (i = 0; i < E1000_INVM_SIZE; i++) {
invm_dword = rd32(E1000_INVM_DATA_REG(i));
/* Get record type */
record_type = INVM_DWORD_TO_RECORD_TYPE(invm_dword);
if (record_type == E1000_INVM_UNINITIALIZED_STRUCTURE)
break;
if (record_type == E1000_INVM_CSR_AUTOLOAD_STRUCTURE)
i += E1000_INVM_CSR_AUTOLOAD_DATA_SIZE_IN_DWORDS;
if (record_type == E1000_INVM_RSA_KEY_SHA256_STRUCTURE)
i += E1000_INVM_RSA_KEY_SHA256_DATA_SIZE_IN_DWORDS;
if (record_type == E1000_INVM_WORD_AUTOLOAD_STRUCTURE) {
word_address = INVM_DWORD_TO_WORD_ADDRESS(invm_dword);
if (word_address == address) {
*data = INVM_DWORD_TO_WORD_DATA(invm_dword);
hw_dbg("Read INVM Word 0x%02x = %x",
address, *data);
status = E1000_SUCCESS;
break;
}
}
}
if (status != E1000_SUCCESS)
hw_dbg("Requested word 0x%02x not found in OTP\n", address);
return status;
}
/**
* igb_read_invm_i210 - Read invm wrapper function for I210/I211
* @hw: pointer to the HW structure * @hw: pointer to the HW structure
* @words: number of words to read * @words: number of words to read
* @data: pointer to the data read * @data: pointer to the data read
* *
* Wrapper function to return data formerly found in the NVM. * Wrapper function to return data formerly found in the NVM.
**/ **/
s32 igb_read_nvm_i211(struct e1000_hw *hw, u16 offset, u16 words, static s32 igb_read_invm_i210(struct e1000_hw *hw, u16 offset,
u16 *data) u16 words __always_unused, u16 *data)
{ {
s32 ret_val = E1000_SUCCESS; s32 ret_val = E1000_SUCCESS;
/* Only the MAC addr is required to be present in the iNVM */ /* Only the MAC addr is required to be present in the iNVM */
switch (offset) { switch (offset) {
case NVM_MAC_ADDR: case NVM_MAC_ADDR:
ret_val = igb_read_invm_i211(hw, offset, &data[0]); ret_val = igb_read_invm_word_i210(hw, (u8)offset, &data[0]);
ret_val |= igb_read_invm_i211(hw, offset+1, &data[1]); ret_val |= igb_read_invm_word_i210(hw, (u8)offset+1,
ret_val |= igb_read_invm_i211(hw, offset+2, &data[2]); &data[1]);
ret_val |= igb_read_invm_word_i210(hw, (u8)offset+2,
&data[2]);
if (ret_val != E1000_SUCCESS) if (ret_val != E1000_SUCCESS)
hw_dbg("MAC Addr not found in iNVM\n"); hw_dbg("MAC Addr not found in iNVM\n");
break; break;
case NVM_INIT_CTRL_2: case NVM_INIT_CTRL_2:
ret_val = igb_read_invm_i211(hw, (u8)offset, data); ret_val = igb_read_invm_word_i210(hw, (u8)offset, data);
if (ret_val != E1000_SUCCESS) { if (ret_val != E1000_SUCCESS) {
*data = NVM_INIT_CTRL_2_DEFAULT_I211; *data = NVM_INIT_CTRL_2_DEFAULT_I211;
ret_val = E1000_SUCCESS; ret_val = E1000_SUCCESS;
} }
break; break;
case NVM_INIT_CTRL_4: case NVM_INIT_CTRL_4:
ret_val = igb_read_invm_i211(hw, (u8)offset, data); ret_val = igb_read_invm_word_i210(hw, (u8)offset, data);
if (ret_val != E1000_SUCCESS) { if (ret_val != E1000_SUCCESS) {
*data = NVM_INIT_CTRL_4_DEFAULT_I211; *data = NVM_INIT_CTRL_4_DEFAULT_I211;
ret_val = E1000_SUCCESS; ret_val = E1000_SUCCESS;
} }
break; break;
case NVM_LED_1_CFG: case NVM_LED_1_CFG:
ret_val = igb_read_invm_i211(hw, (u8)offset, data); ret_val = igb_read_invm_word_i210(hw, (u8)offset, data);
if (ret_val != E1000_SUCCESS) { if (ret_val != E1000_SUCCESS) {
*data = NVM_LED_1_CFG_DEFAULT_I211; *data = NVM_LED_1_CFG_DEFAULT_I211;
ret_val = E1000_SUCCESS; ret_val = E1000_SUCCESS;
} }
break; break;
case NVM_LED_0_2_CFG: case NVM_LED_0_2_CFG:
igb_read_invm_i211(hw, offset, data); ret_val = igb_read_invm_word_i210(hw, (u8)offset, data);
if (ret_val != E1000_SUCCESS) { if (ret_val != E1000_SUCCESS) {
*data = NVM_LED_0_2_CFG_DEFAULT_I211; *data = NVM_LED_0_2_CFG_DEFAULT_I211;
ret_val = E1000_SUCCESS; ret_val = E1000_SUCCESS;
} }
break; break;
case NVM_ID_LED_SETTINGS: case NVM_ID_LED_SETTINGS:
ret_val = igb_read_invm_i211(hw, (u8)offset, data); ret_val = igb_read_invm_word_i210(hw, (u8)offset, data);
if (ret_val != E1000_SUCCESS) { if (ret_val != E1000_SUCCESS) {
*data = ID_LED_RESERVED_FFFF; *data = ID_LED_RESERVED_FFFF;
ret_val = E1000_SUCCESS; ret_val = E1000_SUCCESS;
...@@ -410,48 +454,6 @@ s32 igb_read_nvm_i211(struct e1000_hw *hw, u16 offset, u16 words, ...@@ -410,48 +454,6 @@ s32 igb_read_nvm_i211(struct e1000_hw *hw, u16 offset, u16 words,
return ret_val; return ret_val;
} }
/**
* igb_read_invm_i211 - Reads OTP
* @hw: pointer to the HW structure
* @address: the word address (aka eeprom offset) to read
* @data: pointer to the data read
*
* Reads 16-bit words from the OTP. Return error when the word is not
* stored in OTP.
**/
s32 igb_read_invm_i211(struct e1000_hw *hw, u16 address, u16 *data)
{
s32 status = -E1000_ERR_INVM_VALUE_NOT_FOUND;
u32 invm_dword;
u16 i;
u8 record_type, word_address;
for (i = 0; i < E1000_INVM_SIZE; i++) {
invm_dword = rd32(E1000_INVM_DATA_REG(i));
/* Get record type */
record_type = INVM_DWORD_TO_RECORD_TYPE(invm_dword);
if (record_type == E1000_INVM_UNINITIALIZED_STRUCTURE)
break;
if (record_type == E1000_INVM_CSR_AUTOLOAD_STRUCTURE)
i += E1000_INVM_CSR_AUTOLOAD_DATA_SIZE_IN_DWORDS;
if (record_type == E1000_INVM_RSA_KEY_SHA256_STRUCTURE)
i += E1000_INVM_RSA_KEY_SHA256_DATA_SIZE_IN_DWORDS;
if (record_type == E1000_INVM_WORD_AUTOLOAD_STRUCTURE) {
word_address = INVM_DWORD_TO_WORD_ADDRESS(invm_dword);
if (word_address == (u8)address) {
*data = INVM_DWORD_TO_WORD_DATA(invm_dword);
hw_dbg("Read INVM Word 0x%02x = %x",
address, *data);
status = E1000_SUCCESS;
break;
}
}
}
if (status != E1000_SUCCESS)
hw_dbg("Requested word 0x%02x not found in OTP\n", address);
return status;
}
/** /**
* igb_read_invm_version - Reads iNVM version and image type * igb_read_invm_version - Reads iNVM version and image type
* @hw: pointer to the HW structure * @hw: pointer to the HW structure
...@@ -826,7 +828,7 @@ s32 igb_init_nvm_params_i210(struct e1000_hw *hw) ...@@ -826,7 +828,7 @@ s32 igb_init_nvm_params_i210(struct e1000_hw *hw)
nvm->ops.update = igb_update_nvm_checksum_i210; nvm->ops.update = igb_update_nvm_checksum_i210;
} else { } else {
hw->nvm.type = e1000_nvm_invm; hw->nvm.type = e1000_nvm_invm;
nvm->ops.read = igb_read_nvm_i211; nvm->ops.read = igb_read_invm_i210;
nvm->ops.write = NULL; nvm->ops.write = NULL;
nvm->ops.validate = NULL; nvm->ops.validate = NULL;
nvm->ops.update = NULL; nvm->ops.update = NULL;
......
...@@ -35,14 +35,11 @@ extern s32 igb_write_nvm_srwr_i210(struct e1000_hw *hw, u16 offset, ...@@ -35,14 +35,11 @@ extern s32 igb_write_nvm_srwr_i210(struct e1000_hw *hw, u16 offset,
u16 words, u16 *data); u16 words, u16 *data);
extern s32 igb_read_nvm_srrd_i210(struct e1000_hw *hw, u16 offset, extern s32 igb_read_nvm_srrd_i210(struct e1000_hw *hw, u16 offset,
u16 words, u16 *data); u16 words, u16 *data);
extern s32 igb_read_invm_i211(struct e1000_hw *hw, u16 address, u16 *data);
extern s32 igb_acquire_swfw_sync_i210(struct e1000_hw *hw, u16 mask); extern s32 igb_acquire_swfw_sync_i210(struct e1000_hw *hw, u16 mask);
extern void igb_release_swfw_sync_i210(struct e1000_hw *hw, u16 mask); extern void igb_release_swfw_sync_i210(struct e1000_hw *hw, u16 mask);
extern s32 igb_acquire_nvm_i210(struct e1000_hw *hw); extern s32 igb_acquire_nvm_i210(struct e1000_hw *hw);
extern void igb_release_nvm_i210(struct e1000_hw *hw); extern void igb_release_nvm_i210(struct e1000_hw *hw);
extern s32 igb_valid_led_default_i210(struct e1000_hw *hw, u16 *data); extern s32 igb_valid_led_default_i210(struct e1000_hw *hw, u16 *data);
extern s32 igb_read_nvm_i211(struct e1000_hw *hw, u16 offset, u16 words,
u16 *data);
extern s32 igb_read_invm_version(struct e1000_hw *hw, extern s32 igb_read_invm_version(struct e1000_hw *hw,
struct e1000_fw_version *invm_ver); struct e1000_fw_version *invm_ver);
extern s32 igb_read_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr, extern s32 igb_read_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr,
......
...@@ -2166,15 +2166,28 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -2166,15 +2166,28 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
*/ */
hw->mac.ops.reset_hw(hw); hw->mac.ops.reset_hw(hw);
/* make sure the NVM is good , i211 parts have special NVM that /* make sure the NVM is good , i211/i210 parts can have special NVM
* doesn't contain a checksum * that doesn't contain a checksum
*/ */
if (hw->mac.type != e1000_i211) { switch (hw->mac.type) {
case e1000_i210:
case e1000_i211:
if (igb_get_flash_presence_i210(hw)) {
if (hw->nvm.ops.validate(hw) < 0) {
dev_err(&pdev->dev,
"The NVM Checksum Is Not Valid\n");
err = -EIO;
goto err_eeprom;
}
}
break;
default:
if (hw->nvm.ops.validate(hw) < 0) { if (hw->nvm.ops.validate(hw) < 0) {
dev_err(&pdev->dev, "The NVM Checksum Is Not Valid\n"); dev_err(&pdev->dev, "The NVM Checksum Is Not Valid\n");
err = -EIO; err = -EIO;
goto err_eeprom; goto err_eeprom;
} }
break;
} }
/* copy the MAC address out of the NVM */ /* copy the MAC address out of the NVM */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment