|
|
|
@ -123,6 +123,14 @@ static s32 e1000_read_flash_word_ich8lan(struct e1000_hw *hw, u32 offset,
|
|
|
|
|
u16 *data);
|
|
|
|
|
static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
|
|
|
|
|
u8 size, u16 *data);
|
|
|
|
|
static s32 e1000_read_flash_data32_ich8lan(struct e1000_hw *hw, u32 offset,
|
|
|
|
|
u32 *data);
|
|
|
|
|
static s32 e1000_read_flash_dword_ich8lan(struct e1000_hw *hw,
|
|
|
|
|
u32 offset, u32 *data);
|
|
|
|
|
static s32 e1000_write_flash_data32_ich8lan(struct e1000_hw *hw,
|
|
|
|
|
u32 offset, u32 data);
|
|
|
|
|
static s32 e1000_retry_write_flash_dword_ich8lan(struct e1000_hw *hw,
|
|
|
|
|
u32 offset, u32 dword);
|
|
|
|
|
static s32 e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw);
|
|
|
|
|
static s32 e1000_cleanup_led_ich8lan(struct e1000_hw *hw);
|
|
|
|
|
static s32 e1000_led_on_ich8lan(struct e1000_hw *hw);
|
|
|
|
@ -229,7 +237,8 @@ static bool e1000_phy_is_accessible_pchlan(struct e1000_hw *hw)
|
|
|
|
|
if (ret_val)
|
|
|
|
|
return false;
|
|
|
|
|
out:
|
|
|
|
|
if (hw->mac.type == e1000_pch_lpt) {
|
|
|
|
|
if ((hw->mac.type == e1000_pch_lpt) ||
|
|
|
|
|
(hw->mac.type == e1000_pch_spt)) {
|
|
|
|
|
/* Unforce SMBus mode in PHY */
|
|
|
|
|
e1e_rphy_locked(hw, CV_SMB_CTRL, &phy_reg);
|
|
|
|
|
phy_reg &= ~CV_SMB_CTRL_FORCE_SMBUS;
|
|
|
|
@ -321,6 +330,7 @@ static s32 e1000_init_phy_workarounds_pchlan(struct e1000_hw *hw)
|
|
|
|
|
*/
|
|
|
|
|
switch (hw->mac.type) {
|
|
|
|
|
case e1000_pch_lpt:
|
|
|
|
|
case e1000_pch_spt:
|
|
|
|
|
if (e1000_phy_is_accessible_pchlan(hw))
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
@ -461,6 +471,7 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)
|
|
|
|
|
/* fall-through */
|
|
|
|
|
case e1000_pch2lan:
|
|
|
|
|
case e1000_pch_lpt:
|
|
|
|
|
case e1000_pch_spt:
|
|
|
|
|
/* In case the PHY needs to be in mdio slow mode,
|
|
|
|
|
* set slow mode and try to get the PHY id again.
|
|
|
|
|
*/
|
|
|
|
@ -590,15 +601,28 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw)
|
|
|
|
|
struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
|
|
|
|
|
u32 gfpreg, sector_base_addr, sector_end_addr;
|
|
|
|
|
u16 i;
|
|
|
|
|
u32 nvm_size;
|
|
|
|
|
|
|
|
|
|
/* Can't read flash registers if the register set isn't mapped. */
|
|
|
|
|
nvm->type = e1000_nvm_flash_sw;
|
|
|
|
|
/* in SPT, gfpreg doesn't exist. NVM size is taken from the
|
|
|
|
|
* STRAP register
|
|
|
|
|
*/
|
|
|
|
|
if (hw->mac.type == e1000_pch_spt) {
|
|
|
|
|
nvm->flash_base_addr = 0;
|
|
|
|
|
nvm_size = (((er32(STRAP) >> 1) & 0x1F) + 1)
|
|
|
|
|
* NVM_SIZE_MULTIPLIER;
|
|
|
|
|
nvm->flash_bank_size = nvm_size / 2;
|
|
|
|
|
/* Adjust to word count */
|
|
|
|
|
nvm->flash_bank_size /= sizeof(u16);
|
|
|
|
|
/* Set the base address for flash register access */
|
|
|
|
|
hw->flash_address = hw->hw_addr + E1000_FLASH_BASE_ADDR;
|
|
|
|
|
} else {
|
|
|
|
|
if (!hw->flash_address) {
|
|
|
|
|
e_dbg("ERROR: Flash registers not mapped\n");
|
|
|
|
|
return -E1000_ERR_CONFIG;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nvm->type = e1000_nvm_flash_sw;
|
|
|
|
|
|
|
|
|
|
gfpreg = er32flash(ICH_FLASH_GFPREG);
|
|
|
|
|
|
|
|
|
|
/* sector_X_addr is a "sector"-aligned address (4096 bytes)
|
|
|
|
@ -609,7 +633,8 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw)
|
|
|
|
|
sector_end_addr = ((gfpreg >> 16) & FLASH_GFPREG_BASE_MASK) + 1;
|
|
|
|
|
|
|
|
|
|
/* flash_base_addr is byte-aligned */
|
|
|
|
|
nvm->flash_base_addr = sector_base_addr << FLASH_SECTOR_ADDR_SHIFT;
|
|
|
|
|
nvm->flash_base_addr = sector_base_addr
|
|
|
|
|
<< FLASH_SECTOR_ADDR_SHIFT;
|
|
|
|
|
|
|
|
|
|
/* find total size of the NVM, then cut in half since the total
|
|
|
|
|
* size represents two separate NVM banks.
|
|
|
|
@ -619,6 +644,7 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw)
|
|
|
|
|
nvm->flash_bank_size /= 2;
|
|
|
|
|
/* Adjust to word count */
|
|
|
|
|
nvm->flash_bank_size /= sizeof(u16);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nvm->word_size = E1000_ICH8_SHADOW_RAM_WORDS;
|
|
|
|
|
|
|
|
|
@ -682,6 +708,7 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw)
|
|
|
|
|
mac->ops.rar_set = e1000_rar_set_pch2lan;
|
|
|
|
|
/* fall-through */
|
|
|
|
|
case e1000_pch_lpt:
|
|
|
|
|
case e1000_pch_spt:
|
|
|
|
|
case e1000_pchlan:
|
|
|
|
|
/* check management mode */
|
|
|
|
|
mac->ops.check_mng_mode = e1000_check_mng_mode_pchlan;
|
|
|
|
@ -699,7 +726,7 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (mac->type == e1000_pch_lpt) {
|
|
|
|
|
if ((mac->type == e1000_pch_lpt) || (mac->type == e1000_pch_spt)) {
|
|
|
|
|
mac->rar_entry_count = E1000_PCH_LPT_RAR_ENTRIES;
|
|
|
|
|
mac->ops.rar_set = e1000_rar_set_pch_lpt;
|
|
|
|
|
mac->ops.setup_physical_interface =
|
|
|
|
@ -919,7 +946,8 @@ release:
|
|
|
|
|
/* clear FEXTNVM6 bit 8 on link down or 10/100 */
|
|
|
|
|
fextnvm6 &= ~E1000_FEXTNVM6_REQ_PLL_CLK;
|
|
|
|
|
|
|
|
|
|
if (!link || ((status & E1000_STATUS_SPEED_100) &&
|
|
|
|
|
if ((hw->phy.revision > 5) || !link ||
|
|
|
|
|
((status & E1000_STATUS_SPEED_100) &&
|
|
|
|
|
(status & E1000_STATUS_FD)))
|
|
|
|
|
goto update_fextnvm6;
|
|
|
|
|
|
|
|
|
@ -1100,6 +1128,21 @@ s32 e1000_enable_ulp_lpt_lp(struct e1000_hw *hw, bool to_sx)
|
|
|
|
|
if (ret_val)
|
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
|
|
/* Si workaround for ULP entry flow on i127/rev6 h/w. Enable
|
|
|
|
|
* LPLU and disable Gig speed when entering ULP
|
|
|
|
|
*/
|
|
|
|
|
if ((hw->phy.type == e1000_phy_i217) && (hw->phy.revision == 6)) {
|
|
|
|
|
ret_val = e1000_read_phy_reg_hv_locked(hw, HV_OEM_BITS,
|
|
|
|
|
&phy_reg);
|
|
|
|
|
if (ret_val)
|
|
|
|
|
goto release;
|
|
|
|
|
phy_reg |= HV_OEM_BITS_LPLU | HV_OEM_BITS_GBE_DIS;
|
|
|
|
|
ret_val = e1000_write_phy_reg_hv_locked(hw, HV_OEM_BITS,
|
|
|
|
|
phy_reg);
|
|
|
|
|
if (ret_val)
|
|
|
|
|
goto release;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Force SMBus mode in PHY */
|
|
|
|
|
ret_val = e1000_read_phy_reg_hv_locked(hw, CV_SMB_CTRL, &phy_reg);
|
|
|
|
|
if (ret_val)
|
|
|
|
@ -1302,7 +1345,8 @@ out:
|
|
|
|
|
static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
|
|
|
|
|
{
|
|
|
|
|
struct e1000_mac_info *mac = &hw->mac;
|
|
|
|
|
s32 ret_val;
|
|
|
|
|
s32 ret_val, tipg_reg = 0;
|
|
|
|
|
u16 emi_addr, emi_val = 0;
|
|
|
|
|
bool link;
|
|
|
|
|
u16 phy_reg;
|
|
|
|
|
|
|
|
|
@ -1333,19 +1377,27 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
|
|
|
|
|
* the IPG and reduce Rx latency in the PHY.
|
|
|
|
|
*/
|
|
|
|
|
if (((hw->mac.type == e1000_pch2lan) ||
|
|
|
|
|
(hw->mac.type == e1000_pch_lpt)) && link) {
|
|
|
|
|
(hw->mac.type == e1000_pch_lpt) ||
|
|
|
|
|
(hw->mac.type == e1000_pch_spt)) && link) {
|
|
|
|
|
u32 reg;
|
|
|
|
|
|
|
|
|
|
reg = er32(STATUS);
|
|
|
|
|
tipg_reg = er32(TIPG);
|
|
|
|
|
tipg_reg &= ~E1000_TIPG_IPGT_MASK;
|
|
|
|
|
|
|
|
|
|
if (!(reg & (E1000_STATUS_FD | E1000_STATUS_SPEED_MASK))) {
|
|
|
|
|
u16 emi_addr;
|
|
|
|
|
|
|
|
|
|
reg = er32(TIPG);
|
|
|
|
|
reg &= ~E1000_TIPG_IPGT_MASK;
|
|
|
|
|
reg |= 0xFF;
|
|
|
|
|
ew32(TIPG, reg);
|
|
|
|
|
|
|
|
|
|
tipg_reg |= 0xFF;
|
|
|
|
|
/* Reduce Rx latency in analog PHY */
|
|
|
|
|
emi_val = 0;
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
/* Roll back the default values */
|
|
|
|
|
tipg_reg |= 0x08;
|
|
|
|
|
emi_val = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ew32(TIPG, tipg_reg);
|
|
|
|
|
|
|
|
|
|
ret_val = hw->phy.ops.acquire(hw);
|
|
|
|
|
if (ret_val)
|
|
|
|
|
return ret_val;
|
|
|
|
@ -1354,27 +1406,26 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
|
|
|
|
|
emi_addr = I82579_RX_CONFIG;
|
|
|
|
|
else
|
|
|
|
|
emi_addr = I217_RX_CONFIG;
|
|
|
|
|
|
|
|
|
|
ret_val = e1000_write_emi_reg_locked(hw, emi_addr, 0);
|
|
|
|
|
ret_val = e1000_write_emi_reg_locked(hw, emi_addr, emi_val);
|
|
|
|
|
|
|
|
|
|
hw->phy.ops.release(hw);
|
|
|
|
|
|
|
|
|
|
if (ret_val)
|
|
|
|
|
return ret_val;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Work-around I218 hang issue */
|
|
|
|
|
if ((hw->adapter->pdev->device == E1000_DEV_ID_PCH_LPTLP_I218_LM) ||
|
|
|
|
|
(hw->adapter->pdev->device == E1000_DEV_ID_PCH_LPTLP_I218_V) ||
|
|
|
|
|
(hw->adapter->pdev->device == E1000_DEV_ID_PCH_I218_LM3) ||
|
|
|
|
|
(hw->adapter->pdev->device == E1000_DEV_ID_PCH_I218_V3)) {
|
|
|
|
|
(hw->adapter->pdev->device == E1000_DEV_ID_PCH_I218_V3) ||
|
|
|
|
|
(hw->mac.type == e1000_pch_spt)) {
|
|
|
|
|
ret_val = e1000_k1_workaround_lpt_lp(hw, link);
|
|
|
|
|
if (ret_val)
|
|
|
|
|
return ret_val;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (hw->mac.type == e1000_pch_lpt) {
|
|
|
|
|
if ((hw->mac.type == e1000_pch_lpt) ||
|
|
|
|
|
(hw->mac.type == e1000_pch_spt)) {
|
|
|
|
|
/* Set platform power management values for
|
|
|
|
|
* Latency Tolerance Reporting (LTR)
|
|
|
|
|
*/
|
|
|
|
@ -1386,6 +1437,19 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
|
|
|
|
|
/* Clear link partner's EEE ability */
|
|
|
|
|
hw->dev_spec.ich8lan.eee_lp_ability = 0;
|
|
|
|
|
|
|
|
|
|
/* FEXTNVM6 K1-off workaround */
|
|
|
|
|
if (hw->mac.type == e1000_pch_spt) {
|
|
|
|
|
u32 pcieanacfg = er32(PCIEANACFG);
|
|
|
|
|
u32 fextnvm6 = er32(FEXTNVM6);
|
|
|
|
|
|
|
|
|
|
if (pcieanacfg & E1000_FEXTNVM6_K1_OFF_ENABLE)
|
|
|
|
|
fextnvm6 |= E1000_FEXTNVM6_K1_OFF_ENABLE;
|
|
|
|
|
else
|
|
|
|
|
fextnvm6 &= ~E1000_FEXTNVM6_K1_OFF_ENABLE;
|
|
|
|
|
|
|
|
|
|
ew32(FEXTNVM6, fextnvm6);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!link)
|
|
|
|
|
return 0; /* No link detected */
|
|
|
|
|
|
|
|
|
@ -1479,6 +1543,7 @@ static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter)
|
|
|
|
|
case e1000_pchlan:
|
|
|
|
|
case e1000_pch2lan:
|
|
|
|
|
case e1000_pch_lpt:
|
|
|
|
|
case e1000_pch_spt:
|
|
|
|
|
rc = e1000_init_phy_params_pchlan(hw);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
@ -1929,6 +1994,7 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw)
|
|
|
|
|
case e1000_pchlan:
|
|
|
|
|
case e1000_pch2lan:
|
|
|
|
|
case e1000_pch_lpt:
|
|
|
|
|
case e1000_pch_spt:
|
|
|
|
|
sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG_ICH8M;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
@ -2961,6 +3027,20 @@ static s32 e1000_valid_nvm_bank_detect_ich8lan(struct e1000_hw *hw, u32 *bank)
|
|
|
|
|
s32 ret_val;
|
|
|
|
|
|
|
|
|
|
switch (hw->mac.type) {
|
|
|
|
|
/* In SPT, read from the CTRL_EXT reg instead of
|
|
|
|
|
* accessing the sector valid bits from the nvm
|
|
|
|
|
*/
|
|
|
|
|
case e1000_pch_spt:
|
|
|
|
|
*bank = er32(CTRL_EXT)
|
|
|
|
|
& E1000_CTRL_EXT_NVMVS;
|
|
|
|
|
if ((*bank == 0) || (*bank == 1)) {
|
|
|
|
|
e_dbg("ERROR: No valid NVM bank present\n");
|
|
|
|
|
return -E1000_ERR_NVM;
|
|
|
|
|
} else {
|
|
|
|
|
*bank = *bank - 2;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case e1000_ich8lan:
|
|
|
|
|
case e1000_ich9lan:
|
|
|
|
|
eecd = er32(EECD);
|
|
|
|
@ -3007,6 +3087,99 @@ static s32 e1000_valid_nvm_bank_detect_ich8lan(struct e1000_hw *hw, u32 *bank)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* e1000_read_nvm_spt - NVM access for SPT
|
|
|
|
|
* @hw: pointer to the HW structure
|
|
|
|
|
* @offset: The offset (in bytes) of the word(s) to read.
|
|
|
|
|
* @words: Size of data to read in words.
|
|
|
|
|
* @data: pointer to the word(s) to read at offset.
|
|
|
|
|
*
|
|
|
|
|
* Reads a word(s) from the NVM
|
|
|
|
|
**/
|
|
|
|
|
static s32 e1000_read_nvm_spt(struct e1000_hw *hw, u16 offset, u16 words,
|
|
|
|
|
u16 *data)
|
|
|
|
|
{
|
|
|
|
|
struct e1000_nvm_info *nvm = &hw->nvm;
|
|
|
|
|
struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
|
|
|
|
|
u32 act_offset;
|
|
|
|
|
s32 ret_val = 0;
|
|
|
|
|
u32 bank = 0;
|
|
|
|
|
u32 dword = 0;
|
|
|
|
|
u16 offset_to_read;
|
|
|
|
|
u16 i;
|
|
|
|
|
|
|
|
|
|
if ((offset >= nvm->word_size) || (words > nvm->word_size - offset) ||
|
|
|
|
|
(words == 0)) {
|
|
|
|
|
e_dbg("nvm parameter(s) out of bounds\n");
|
|
|
|
|
ret_val = -E1000_ERR_NVM;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nvm->ops.acquire(hw);
|
|
|
|
|
|
|
|
|
|
ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank);
|
|
|
|
|
if (ret_val) {
|
|
|
|
|
e_dbg("Could not detect valid bank, assuming bank 0\n");
|
|
|
|
|
bank = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
act_offset = (bank) ? nvm->flash_bank_size : 0;
|
|
|
|
|
act_offset += offset;
|
|
|
|
|
|
|
|
|
|
ret_val = 0;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < words; i += 2) {
|
|
|
|
|
if (words - i == 1) {
|
|
|
|
|
if (dev_spec->shadow_ram[offset + i].modified) {
|
|
|
|
|
data[i] =
|
|
|
|
|
dev_spec->shadow_ram[offset + i].value;
|
|
|
|
|
} else {
|
|
|
|
|
offset_to_read = act_offset + i -
|
|
|
|
|
((act_offset + i) % 2);
|
|
|
|
|
ret_val =
|
|
|
|
|
e1000_read_flash_dword_ich8lan(hw,
|
|
|
|
|
offset_to_read,
|
|
|
|
|
&dword);
|
|
|
|
|
if (ret_val)
|
|
|
|
|
break;
|
|
|
|
|
if ((act_offset + i) % 2 == 0)
|
|
|
|
|
data[i] = (u16)(dword & 0xFFFF);
|
|
|
|
|
else
|
|
|
|
|
data[i] = (u16)((dword >> 16) & 0xFFFF);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
offset_to_read = act_offset + i;
|
|
|
|
|
if (!(dev_spec->shadow_ram[offset + i].modified) ||
|
|
|
|
|
!(dev_spec->shadow_ram[offset + i + 1].modified)) {
|
|
|
|
|
ret_val =
|
|
|
|
|
e1000_read_flash_dword_ich8lan(hw,
|
|
|
|
|
offset_to_read,
|
|
|
|
|
&dword);
|
|
|
|
|
if (ret_val)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (dev_spec->shadow_ram[offset + i].modified)
|
|
|
|
|
data[i] =
|
|
|
|
|
dev_spec->shadow_ram[offset + i].value;
|
|
|
|
|
else
|
|
|
|
|
data[i] = (u16)(dword & 0xFFFF);
|
|
|
|
|
if (dev_spec->shadow_ram[offset + i].modified)
|
|
|
|
|
data[i + 1] =
|
|
|
|
|
dev_spec->shadow_ram[offset + i + 1].value;
|
|
|
|
|
else
|
|
|
|
|
data[i + 1] = (u16)(dword >> 16 & 0xFFFF);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nvm->ops.release(hw);
|
|
|
|
|
|
|
|
|
|
out:
|
|
|
|
|
if (ret_val)
|
|
|
|
|
e_dbg("NVM read error: %d\n", ret_val);
|
|
|
|
|
|
|
|
|
|
return ret_val;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* e1000_read_nvm_ich8lan - Read word(s) from the NVM
|
|
|
|
|
* @hw: pointer to the HW structure
|
|
|
|
@ -3090,7 +3263,9 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw)
|
|
|
|
|
/* Clear FCERR and DAEL in hw status by writing 1 */
|
|
|
|
|
hsfsts.hsf_status.flcerr = 1;
|
|
|
|
|
hsfsts.hsf_status.dael = 1;
|
|
|
|
|
|
|
|
|
|
if (hw->mac.type == e1000_pch_spt)
|
|
|
|
|
ew32flash(ICH_FLASH_HSFSTS, hsfsts.regval & 0xFFFF);
|
|
|
|
|
else
|
|
|
|
|
ew16flash(ICH_FLASH_HSFSTS, hsfsts.regval);
|
|
|
|
|
|
|
|
|
|
/* Either we should have a hardware SPI cycle in progress
|
|
|
|
@ -3107,6 +3282,9 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw)
|
|
|
|
|
* Begin by setting Flash Cycle Done.
|
|
|
|
|
*/
|
|
|
|
|
hsfsts.hsf_status.flcdone = 1;
|
|
|
|
|
if (hw->mac.type == e1000_pch_spt)
|
|
|
|
|
ew32flash(ICH_FLASH_HSFSTS, hsfsts.regval & 0xFFFF);
|
|
|
|
|
else
|
|
|
|
|
ew16flash(ICH_FLASH_HSFSTS, hsfsts.regval);
|
|
|
|
|
ret_val = 0;
|
|
|
|
|
} else {
|
|
|
|
@ -3128,6 +3306,10 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw)
|
|
|
|
|
* now set the Flash Cycle Done.
|
|
|
|
|
*/
|
|
|
|
|
hsfsts.hsf_status.flcdone = 1;
|
|
|
|
|
if (hw->mac.type == e1000_pch_spt)
|
|
|
|
|
ew32flash(ICH_FLASH_HSFSTS,
|
|
|
|
|
hsfsts.regval & 0xFFFF);
|
|
|
|
|
else
|
|
|
|
|
ew16flash(ICH_FLASH_HSFSTS, hsfsts.regval);
|
|
|
|
|
} else {
|
|
|
|
|
e_dbg("Flash controller busy, cannot get access\n");
|
|
|
|
@ -3151,8 +3333,15 @@ static s32 e1000_flash_cycle_ich8lan(struct e1000_hw *hw, u32 timeout)
|
|
|
|
|
u32 i = 0;
|
|
|
|
|
|
|
|
|
|
/* Start a cycle by writing 1 in Flash Cycle Go in Hw Flash Control */
|
|
|
|
|
if (hw->mac.type == e1000_pch_spt)
|
|
|
|
|
hsflctl.regval = er32flash(ICH_FLASH_HSFSTS) >> 16;
|
|
|
|
|
else
|
|
|
|
|
hsflctl.regval = er16flash(ICH_FLASH_HSFCTL);
|
|
|
|
|
hsflctl.hsf_ctrl.flcgo = 1;
|
|
|
|
|
|
|
|
|
|
if (hw->mac.type == e1000_pch_spt)
|
|
|
|
|
ew32flash(ICH_FLASH_HSFSTS, hsflctl.regval << 16);
|
|
|
|
|
else
|
|
|
|
|
ew16flash(ICH_FLASH_HSFCTL, hsflctl.regval);
|
|
|
|
|
|
|
|
|
|
/* wait till FDONE bit is set to 1 */
|
|
|
|
@ -3169,6 +3358,23 @@ static s32 e1000_flash_cycle_ich8lan(struct e1000_hw *hw, u32 timeout)
|
|
|
|
|
return -E1000_ERR_NVM;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* e1000_read_flash_dword_ich8lan - Read dword from flash
|
|
|
|
|
* @hw: pointer to the HW structure
|
|
|
|
|
* @offset: offset to data location
|
|
|
|
|
* @data: pointer to the location for storing the data
|
|
|
|
|
*
|
|
|
|
|
* Reads the flash dword at offset into data. Offset is converted
|
|
|
|
|
* to bytes before read.
|
|
|
|
|
**/
|
|
|
|
|
static s32 e1000_read_flash_dword_ich8lan(struct e1000_hw *hw, u32 offset,
|
|
|
|
|
u32 *data)
|
|
|
|
|
{
|
|
|
|
|
/* Must convert word offset into bytes. */
|
|
|
|
|
offset <<= 1;
|
|
|
|
|
return e1000_read_flash_data32_ich8lan(hw, offset, data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* e1000_read_flash_word_ich8lan - Read word from flash
|
|
|
|
|
* @hw: pointer to the HW structure
|
|
|
|
@ -3201,7 +3407,14 @@ static s32 e1000_read_flash_byte_ich8lan(struct e1000_hw *hw, u32 offset,
|
|
|
|
|
s32 ret_val;
|
|
|
|
|
u16 word = 0;
|
|
|
|
|
|
|
|
|
|
/* In SPT, only 32 bits access is supported,
|
|
|
|
|
* so this function should not be called.
|
|
|
|
|
*/
|
|
|
|
|
if (hw->mac.type == e1000_pch_spt)
|
|
|
|
|
return -E1000_ERR_NVM;
|
|
|
|
|
else
|
|
|
|
|
ret_val = e1000_read_flash_data_ich8lan(hw, offset, 1, &word);
|
|
|
|
|
|
|
|
|
|
if (ret_val)
|
|
|
|
|
return ret_val;
|
|
|
|
|
|
|
|
|
@ -3286,6 +3499,82 @@ static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
|
|
|
|
|
return ret_val;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* e1000_read_flash_data32_ich8lan - Read dword from NVM
|
|
|
|
|
* @hw: pointer to the HW structure
|
|
|
|
|
* @offset: The offset (in bytes) of the dword to read.
|
|
|
|
|
* @data: Pointer to the dword to store the value read.
|
|
|
|
|
*
|
|
|
|
|
* Reads a byte or word from the NVM using the flash access registers.
|
|
|
|
|
**/
|
|
|
|
|
|
|
|
|
|
static s32 e1000_read_flash_data32_ich8lan(struct e1000_hw *hw, u32 offset,
|
|
|
|
|
u32 *data)
|
|
|
|
|
{
|
|
|
|
|
union ich8_hws_flash_status hsfsts;
|
|
|
|
|
union ich8_hws_flash_ctrl hsflctl;
|
|
|
|
|
u32 flash_linear_addr;
|
|
|
|
|
s32 ret_val = -E1000_ERR_NVM;
|
|
|
|
|
u8 count = 0;
|
|
|
|
|
|
|
|
|
|
if (offset > ICH_FLASH_LINEAR_ADDR_MASK ||
|
|
|
|
|
hw->mac.type != e1000_pch_spt)
|
|
|
|
|
return -E1000_ERR_NVM;
|
|
|
|
|
flash_linear_addr = ((ICH_FLASH_LINEAR_ADDR_MASK & offset) +
|
|
|
|
|
hw->nvm.flash_base_addr);
|
|
|
|
|
|
|
|
|
|
do {
|
|
|
|
|
udelay(1);
|
|
|
|
|
/* Steps */
|
|
|
|
|
ret_val = e1000_flash_cycle_init_ich8lan(hw);
|
|
|
|
|
if (ret_val)
|
|
|
|
|
break;
|
|
|
|
|
/* In SPT, This register is in Lan memory space, not flash.
|
|
|
|
|
* Therefore, only 32 bit access is supported
|
|
|
|
|
*/
|
|
|
|
|
hsflctl.regval = er32flash(ICH_FLASH_HSFSTS) >> 16;
|
|
|
|
|
|
|
|
|
|
/* 0b/1b corresponds to 1 or 2 byte size, respectively. */
|
|
|
|
|
hsflctl.hsf_ctrl.fldbcount = sizeof(u32) - 1;
|
|
|
|
|
hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_READ;
|
|
|
|
|
/* In SPT, This register is in Lan memory space, not flash.
|
|
|
|
|
* Therefore, only 32 bit access is supported
|
|
|
|
|
*/
|
|
|
|
|
ew32flash(ICH_FLASH_HSFSTS, (u32)hsflctl.regval << 16);
|
|
|
|
|
ew32flash(ICH_FLASH_FADDR, flash_linear_addr);
|
|
|
|
|
|
|
|
|
|
ret_val =
|
|
|
|
|
e1000_flash_cycle_ich8lan(hw,
|
|
|
|
|
ICH_FLASH_READ_COMMAND_TIMEOUT);
|
|
|
|
|
|
|
|
|
|
/* Check if FCERR is set to 1, if set to 1, clear it
|
|
|
|
|
* and try the whole sequence a few more times, else
|
|
|
|
|
* read in (shift in) the Flash Data0, the order is
|
|
|
|
|
* least significant byte first msb to lsb
|
|
|
|
|
*/
|
|
|
|
|
if (!ret_val) {
|
|
|
|
|
*data = er32flash(ICH_FLASH_FDATA0);
|
|
|
|
|
break;
|
|
|
|
|
} else {
|
|
|
|
|
/* If we've gotten here, then things are probably
|
|
|
|
|
* completely hosed, but if the error condition is
|
|
|
|
|
* detected, it won't hurt to give it another try...
|
|
|
|
|
* ICH_FLASH_CYCLE_REPEAT_COUNT times.
|
|
|
|
|
*/
|
|
|
|
|
hsfsts.regval = er16flash(ICH_FLASH_HSFSTS);
|
|
|
|
|
if (hsfsts.hsf_status.flcerr) {
|
|
|
|
|
/* Repeat for some time before giving up. */
|
|
|
|
|
continue;
|
|
|
|
|
} else if (!hsfsts.hsf_status.flcdone) {
|
|
|
|
|
e_dbg("Timeout error - flash cycle did not complete.\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} while (count++ < ICH_FLASH_CYCLE_REPEAT_COUNT);
|
|
|
|
|
|
|
|
|
|
return ret_val;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* e1000_write_nvm_ich8lan - Write word(s) to the NVM
|
|
|
|
|
* @hw: pointer to the HW structure
|
|
|
|
@ -3321,7 +3610,7 @@ static s32 e1000_write_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* e1000_update_nvm_checksum_ich8lan - Update the checksum for NVM
|
|
|
|
|
* e1000_update_nvm_checksum_spt - Update the checksum for NVM
|
|
|
|
|
* @hw: pointer to the HW structure
|
|
|
|
|
*
|
|
|
|
|
* The NVM checksum is updated by calling the generic update_nvm_checksum,
|
|
|
|
@ -3331,13 +3620,13 @@ static s32 e1000_write_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words,
|
|
|
|
|
* After a successful commit, the shadow ram is cleared and is ready for
|
|
|
|
|
* future writes.
|
|
|
|
|
**/
|
|
|
|
|
static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
|
|
|
|
|
static s32 e1000_update_nvm_checksum_spt(struct e1000_hw *hw)
|
|
|
|
|
{
|
|
|
|
|
struct e1000_nvm_info *nvm = &hw->nvm;
|
|
|
|
|
struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
|
|
|
|
|
u32 i, act_offset, new_bank_offset, old_bank_offset, bank;
|
|
|
|
|
s32 ret_val;
|
|
|
|
|
u16 data;
|
|
|
|
|
u32 dword = 0;
|
|
|
|
|
|
|
|
|
|
ret_val = e1000e_update_nvm_checksum_generic(hw);
|
|
|
|
|
if (ret_val)
|
|
|
|
@ -3371,12 +3660,175 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
|
|
|
|
|
if (ret_val)
|
|
|
|
|
goto release;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < E1000_ICH8_SHADOW_RAM_WORDS; i++) {
|
|
|
|
|
for (i = 0; i < E1000_ICH8_SHADOW_RAM_WORDS; i += 2) {
|
|
|
|
|
/* Determine whether to write the value stored
|
|
|
|
|
* in the other NVM bank or a modified value stored
|
|
|
|
|
* in the shadow RAM
|
|
|
|
|
*/
|
|
|
|
|
ret_val = e1000_read_flash_dword_ich8lan(hw,
|
|
|
|
|
i + old_bank_offset,
|
|
|
|
|
&dword);
|
|
|
|
|
|
|
|
|
|
if (dev_spec->shadow_ram[i].modified) {
|
|
|
|
|
dword &= 0xffff0000;
|
|
|
|
|
dword |= (dev_spec->shadow_ram[i].value & 0xffff);
|
|
|
|
|
}
|
|
|
|
|
if (dev_spec->shadow_ram[i + 1].modified) {
|
|
|
|
|
dword &= 0x0000ffff;
|
|
|
|
|
dword |= ((dev_spec->shadow_ram[i + 1].value & 0xffff)
|
|
|
|
|
<< 16);
|
|
|
|
|
}
|
|
|
|
|
if (ret_val)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
/* If the word is 0x13, then make sure the signature bits
|
|
|
|
|
* (15:14) are 11b until the commit has completed.
|
|
|
|
|
* This will allow us to write 10b which indicates the
|
|
|
|
|
* signature is valid. We want to do this after the write
|
|
|
|
|
* has completed so that we don't mark the segment valid
|
|
|
|
|
* while the write is still in progress
|
|
|
|
|
*/
|
|
|
|
|
if (i == E1000_ICH_NVM_SIG_WORD - 1)
|
|
|
|
|
dword |= E1000_ICH_NVM_SIG_MASK << 16;
|
|
|
|
|
|
|
|
|
|
/* Convert offset to bytes. */
|
|
|
|
|
act_offset = (i + new_bank_offset) << 1;
|
|
|
|
|
|
|
|
|
|
usleep_range(100, 200);
|
|
|
|
|
|
|
|
|
|
/* Write the data to the new bank. Offset in words */
|
|
|
|
|
act_offset = i + new_bank_offset;
|
|
|
|
|
ret_val = e1000_retry_write_flash_dword_ich8lan(hw, act_offset,
|
|
|
|
|
dword);
|
|
|
|
|
if (ret_val)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Don't bother writing the segment valid bits if sector
|
|
|
|
|
* programming failed.
|
|
|
|
|
*/
|
|
|
|
|
if (ret_val) {
|
|
|
|
|
/* Possibly read-only, see e1000e_write_protect_nvm_ich8lan() */
|
|
|
|
|
e_dbg("Flash commit failed.\n");
|
|
|
|
|
goto release;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Finally validate the new segment by setting bit 15:14
|
|
|
|
|
* to 10b in word 0x13 , this can be done without an
|
|
|
|
|
* erase as well since these bits are 11 to start with
|
|
|
|
|
* and we need to change bit 14 to 0b
|
|
|
|
|
*/
|
|
|
|
|
act_offset = new_bank_offset + E1000_ICH_NVM_SIG_WORD;
|
|
|
|
|
|
|
|
|
|
/*offset in words but we read dword */
|
|
|
|
|
--act_offset;
|
|
|
|
|
ret_val = e1000_read_flash_dword_ich8lan(hw, act_offset, &dword);
|
|
|
|
|
|
|
|
|
|
if (ret_val)
|
|
|
|
|
goto release;
|
|
|
|
|
|
|
|
|
|
dword &= 0xBFFFFFFF;
|
|
|
|
|
ret_val = e1000_retry_write_flash_dword_ich8lan(hw, act_offset, dword);
|
|
|
|
|
|
|
|
|
|
if (ret_val)
|
|
|
|
|
goto release;
|
|
|
|
|
|
|
|
|
|
/* And invalidate the previously valid segment by setting
|
|
|
|
|
* its signature word (0x13) high_byte to 0b. This can be
|
|
|
|
|
* done without an erase because flash erase sets all bits
|
|
|
|
|
* to 1's. We can write 1's to 0's without an erase
|
|
|
|
|
*/
|
|
|
|
|
act_offset = (old_bank_offset + E1000_ICH_NVM_SIG_WORD) * 2 + 1;
|
|
|
|
|
|
|
|
|
|
/* offset in words but we read dword */
|
|
|
|
|
act_offset = old_bank_offset + E1000_ICH_NVM_SIG_WORD - 1;
|
|
|
|
|
ret_val = e1000_read_flash_dword_ich8lan(hw, act_offset, &dword);
|
|
|
|
|
|
|
|
|
|
if (ret_val)
|
|
|
|
|
goto release;
|
|
|
|
|
|
|
|
|
|
dword &= 0x00FFFFFF;
|
|
|
|
|
ret_val = e1000_retry_write_flash_dword_ich8lan(hw, act_offset, dword);
|
|
|
|
|
|
|
|
|
|
if (ret_val)
|
|
|
|
|
goto release;
|
|
|
|
|
|
|
|
|
|
/* Great! Everything worked, we can now clear the cached entries. */
|
|
|
|
|
for (i = 0; i < E1000_ICH8_SHADOW_RAM_WORDS; i++) {
|
|
|
|
|
dev_spec->shadow_ram[i].modified = false;
|
|
|
|
|
dev_spec->shadow_ram[i].value = 0xFFFF;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
release:
|
|
|
|
|
nvm->ops.release(hw);
|
|
|
|
|
|
|
|
|
|
/* Reload the EEPROM, or else modifications will not appear
|
|
|
|
|
* until after the next adapter reset.
|
|
|
|
|
*/
|
|
|
|
|
if (!ret_val) {
|
|
|
|
|
nvm->ops.reload(hw);
|
|
|
|
|
usleep_range(10000, 20000);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
out:
|
|
|
|
|
if (ret_val)
|
|
|
|
|
e_dbg("NVM update error: %d\n", ret_val);
|
|
|
|
|
|
|
|
|
|
return ret_val;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* e1000_update_nvm_checksum_ich8lan - Update the checksum for NVM
|
|
|
|
|
* @hw: pointer to the HW structure
|
|
|
|
|
*
|
|
|
|
|
* The NVM checksum is updated by calling the generic update_nvm_checksum,
|
|
|
|
|
* which writes the checksum to the shadow ram. The changes in the shadow
|
|
|
|
|
* ram are then committed to the EEPROM by processing each bank at a time
|
|
|
|
|
* checking for the modified bit and writing only the pending changes.
|
|
|
|
|
* After a successful commit, the shadow ram is cleared and is ready for
|
|
|
|
|
* future writes.
|
|
|
|
|
**/
|
|
|
|
|
static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
|
|
|
|
|
{
|
|
|
|
|
struct e1000_nvm_info *nvm = &hw->nvm;
|
|
|
|
|
struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
|
|
|
|
|
u32 i, act_offset, new_bank_offset, old_bank_offset, bank;
|
|
|
|
|
s32 ret_val;
|
|
|
|
|
u16 data = 0;
|
|
|
|
|
|
|
|
|
|
ret_val = e1000e_update_nvm_checksum_generic(hw);
|
|
|
|
|
if (ret_val)
|
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
|
|
if (nvm->type != e1000_nvm_flash_sw)
|
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
|
|
nvm->ops.acquire(hw);
|
|
|
|
|
|
|
|
|
|
/* We're writing to the opposite bank so if we're on bank 1,
|
|
|
|
|
* write to bank 0 etc. We also need to erase the segment that
|
|
|
|
|
* is going to be written
|
|
|
|
|
*/
|
|
|
|
|
ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank);
|
|
|
|
|
if (ret_val) {
|
|
|
|
|
e_dbg("Could not detect valid bank, assuming bank 0\n");
|
|
|
|
|
bank = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (bank == 0) {
|
|
|
|
|
new_bank_offset = nvm->flash_bank_size;
|
|
|
|
|
old_bank_offset = 0;
|
|
|
|
|
ret_val = e1000_erase_flash_bank_ich8lan(hw, 1);
|
|
|
|
|
if (ret_val)
|
|
|
|
|
goto release;
|
|
|
|
|
} else {
|
|
|
|
|
old_bank_offset = nvm->flash_bank_size;
|
|
|
|
|
new_bank_offset = 0;
|
|
|
|
|
ret_val = e1000_erase_flash_bank_ich8lan(hw, 0);
|
|
|
|
|
if (ret_val)
|
|
|
|
|
goto release;
|
|
|
|
|
}
|
|
|
|
|
for (i = 0; i < E1000_ICH8_SHADOW_RAM_WORDS; i++) {
|
|
|
|
|
if (dev_spec->shadow_ram[i].modified) {
|
|
|
|
|
data = dev_spec->shadow_ram[i].value;
|
|
|
|
|
} else {
|
|
|
|
@ -3498,6 +3950,7 @@ static s32 e1000_validate_nvm_checksum_ich8lan(struct e1000_hw *hw)
|
|
|
|
|
*/
|
|
|
|
|
switch (hw->mac.type) {
|
|
|
|
|
case e1000_pch_lpt:
|
|
|
|
|
case e1000_pch_spt:
|
|
|
|
|
word = NVM_COMPAT;
|
|
|
|
|
valid_csum_mask = NVM_COMPAT_VALID_CSUM;
|
|
|
|
|
break;
|
|
|
|
@ -3583,9 +4036,13 @@ static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
|
|
|
|
|
s32 ret_val;
|
|
|
|
|
u8 count = 0;
|
|
|
|
|
|
|
|
|
|
if (size < 1 || size > 2 || data > size * 0xff ||
|
|
|
|
|
offset > ICH_FLASH_LINEAR_ADDR_MASK)
|
|
|
|
|
if (hw->mac.type == e1000_pch_spt) {
|
|
|
|
|
if (size != 4 || offset > ICH_FLASH_LINEAR_ADDR_MASK)
|
|
|
|
|
return -E1000_ERR_NVM;
|
|
|
|
|
} else {
|
|
|
|
|
if (size < 1 || size > 2 || offset > ICH_FLASH_LINEAR_ADDR_MASK)
|
|
|
|
|
return -E1000_ERR_NVM;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
flash_linear_addr = ((ICH_FLASH_LINEAR_ADDR_MASK & offset) +
|
|
|
|
|
hw->nvm.flash_base_addr);
|
|
|
|
@ -3596,11 +4053,24 @@ static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
|
|
|
|
|
ret_val = e1000_flash_cycle_init_ich8lan(hw);
|
|
|
|
|
if (ret_val)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
/* In SPT, This register is in Lan memory space, not
|
|
|
|
|
* flash. Therefore, only 32 bit access is supported
|
|
|
|
|
*/
|
|
|
|
|
if (hw->mac.type == e1000_pch_spt)
|
|
|
|
|
hsflctl.regval = er32flash(ICH_FLASH_HSFSTS) >> 16;
|
|
|
|
|
else
|
|
|
|
|
hsflctl.regval = er16flash(ICH_FLASH_HSFCTL);
|
|
|
|
|
|
|
|
|
|
/* 0b/1b corresponds to 1 or 2 byte size, respectively. */
|
|
|
|
|
hsflctl.hsf_ctrl.fldbcount = size - 1;
|
|
|
|
|
hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_WRITE;
|
|
|
|
|
/* In SPT, This register is in Lan memory space,
|
|
|
|
|
* not flash. Therefore, only 32 bit access is
|
|
|
|
|
* supported
|
|
|
|
|
*/
|
|
|
|
|
if (hw->mac.type == e1000_pch_spt)
|
|
|
|
|
ew32flash(ICH_FLASH_HSFSTS, hsflctl.regval << 16);
|
|
|
|
|
else
|
|
|
|
|
ew16flash(ICH_FLASH_HSFCTL, hsflctl.regval);
|
|
|
|
|
|
|
|
|
|
ew32flash(ICH_FLASH_FADDR, flash_linear_addr);
|
|
|
|
@ -3639,6 +4109,90 @@ static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
|
|
|
|
|
return ret_val;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* e1000_write_flash_data32_ich8lan - Writes 4 bytes to the NVM
|
|
|
|
|
* @hw: pointer to the HW structure
|
|
|
|
|
* @offset: The offset (in bytes) of the dwords to read.
|
|
|
|
|
* @data: The 4 bytes to write to the NVM.
|
|
|
|
|
*
|
|
|
|
|
* Writes one/two/four bytes to the NVM using the flash access registers.
|
|
|
|
|
**/
|
|
|
|
|
static s32 e1000_write_flash_data32_ich8lan(struct e1000_hw *hw, u32 offset,
|
|
|
|
|
u32 data)
|
|
|
|
|
{
|
|
|
|
|
union ich8_hws_flash_status hsfsts;
|
|
|
|
|
union ich8_hws_flash_ctrl hsflctl;
|
|
|
|
|
u32 flash_linear_addr;
|
|
|
|
|
s32 ret_val;
|
|
|
|
|
u8 count = 0;
|
|
|
|
|
|
|
|
|
|
if (hw->mac.type == e1000_pch_spt) {
|
|
|
|
|
if (offset > ICH_FLASH_LINEAR_ADDR_MASK)
|
|
|
|
|
return -E1000_ERR_NVM;
|
|
|
|
|
}
|
|
|
|
|
flash_linear_addr = ((ICH_FLASH_LINEAR_ADDR_MASK & offset) +
|
|
|
|
|
hw->nvm.flash_base_addr);
|
|
|
|
|
do {
|
|
|
|
|
udelay(1);
|
|
|
|
|
/* Steps */
|
|
|
|
|
ret_val = e1000_flash_cycle_init_ich8lan(hw);
|
|
|
|
|
if (ret_val)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
/* In SPT, This register is in Lan memory space, not
|
|
|
|
|
* flash. Therefore, only 32 bit access is supported
|
|
|
|
|
*/
|
|
|
|
|
if (hw->mac.type == e1000_pch_spt)
|
|
|
|
|
hsflctl.regval = er32flash(ICH_FLASH_HSFSTS)
|
|
|
|
|
>> 16;
|
|
|
|
|
else
|
|
|
|
|
hsflctl.regval = er16flash(ICH_FLASH_HSFCTL);
|
|
|
|
|
|
|
|
|
|
hsflctl.hsf_ctrl.fldbcount = sizeof(u32) - 1;
|
|
|
|
|
hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_WRITE;
|
|
|
|
|
|
|
|
|
|
/* In SPT, This register is in Lan memory space,
|
|
|
|
|
* not flash. Therefore, only 32 bit access is
|
|
|
|
|
* supported
|
|
|
|
|
*/
|
|
|
|
|
if (hw->mac.type == e1000_pch_spt)
|
|
|
|
|
ew32flash(ICH_FLASH_HSFSTS, hsflctl.regval << 16);
|
|
|
|
|
else
|
|
|
|
|
ew16flash(ICH_FLASH_HSFCTL, hsflctl.regval);
|
|
|
|
|
|
|
|
|
|
ew32flash(ICH_FLASH_FADDR, flash_linear_addr);
|
|
|
|
|
|
|
|
|
|
ew32flash(ICH_FLASH_FDATA0, data);
|
|
|
|
|
|
|
|
|
|
/* check if FCERR is set to 1 , if set to 1, clear it
|
|
|
|
|
* and try the whole sequence a few more times else done
|
|
|
|
|
*/
|
|
|
|
|
ret_val =
|
|
|
|
|
e1000_flash_cycle_ich8lan(hw,
|
|
|
|
|
ICH_FLASH_WRITE_COMMAND_TIMEOUT);
|
|
|
|
|
|
|
|
|
|
if (!ret_val)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
/* If we're here, then things are most likely
|
|
|
|
|
* completely hosed, but if the error condition
|
|
|
|
|
* is detected, it won't hurt to give it another
|
|
|
|
|
* try...ICH_FLASH_CYCLE_REPEAT_COUNT times.
|
|
|
|
|
*/
|
|
|
|
|
hsfsts.regval = er16flash(ICH_FLASH_HSFSTS);
|
|
|
|
|
|
|
|
|
|
if (hsfsts.hsf_status.flcerr)
|
|
|
|
|
/* Repeat for some time before giving up. */
|
|
|
|
|
continue;
|
|
|
|
|
if (!hsfsts.hsf_status.flcdone) {
|
|
|
|
|
e_dbg("Timeout error - flash cycle did not complete.\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
} while (count++ < ICH_FLASH_CYCLE_REPEAT_COUNT);
|
|
|
|
|
|
|
|
|
|
return ret_val;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* e1000_write_flash_byte_ich8lan - Write a single byte to NVM
|
|
|
|
|
* @hw: pointer to the HW structure
|
|
|
|
@ -3655,6 +4209,40 @@ static s32 e1000_write_flash_byte_ich8lan(struct e1000_hw *hw, u32 offset,
|
|
|
|
|
return e1000_write_flash_data_ich8lan(hw, offset, 1, word);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* e1000_retry_write_flash_dword_ich8lan - Writes a dword to NVM
|
|
|
|
|
* @hw: pointer to the HW structure
|
|
|
|
|
* @offset: The offset of the word to write.
|
|
|
|
|
* @dword: The dword to write to the NVM.
|
|
|
|
|
*
|
|
|
|
|
* Writes a single dword to the NVM using the flash access registers.
|
|
|
|
|
* Goes through a retry algorithm before giving up.
|
|
|
|
|
**/
|
|
|
|
|
static s32 e1000_retry_write_flash_dword_ich8lan(struct e1000_hw *hw,
|
|
|
|
|
u32 offset, u32 dword)
|
|
|
|
|
{
|
|
|
|
|
s32 ret_val;
|
|
|
|
|
u16 program_retries;
|
|
|
|
|
|
|
|
|
|
/* Must convert word offset into bytes. */
|
|
|
|
|
offset <<= 1;
|
|
|
|
|
ret_val = e1000_write_flash_data32_ich8lan(hw, offset, dword);
|
|
|
|
|
|
|
|
|
|
if (!ret_val)
|
|
|
|
|
return ret_val;
|
|
|
|
|
for (program_retries = 0; program_retries < 100; program_retries++) {
|
|
|
|
|
e_dbg("Retrying Byte %8.8X at offset %u\n", dword, offset);
|
|
|
|
|
usleep_range(100, 200);
|
|
|
|
|
ret_val = e1000_write_flash_data32_ich8lan(hw, offset, dword);
|
|
|
|
|
if (!ret_val)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (program_retries == 100)
|
|
|
|
|
return -E1000_ERR_NVM;
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* e1000_retry_write_flash_byte_ich8lan - Writes a single byte to NVM
|
|
|
|
|
* @hw: pointer to the HW structure
|
|
|
|
@ -3759,8 +4347,17 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank)
|
|
|
|
|
/* Write a value 11 (block Erase) in Flash
|
|
|
|
|
* Cycle field in hw flash control
|
|
|
|
|
*/
|
|
|
|
|
if (hw->mac.type == e1000_pch_spt)
|
|
|
|
|
hsflctl.regval =
|
|
|
|
|
er32flash(ICH_FLASH_HSFSTS) >> 16;
|
|
|
|
|
else
|
|
|
|
|
hsflctl.regval = er16flash(ICH_FLASH_HSFCTL);
|
|
|
|
|
|
|
|
|
|
hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_ERASE;
|
|
|
|
|
if (hw->mac.type == e1000_pch_spt)
|
|
|
|
|
ew32flash(ICH_FLASH_HSFSTS,
|
|
|
|
|
hsflctl.regval << 16);
|
|
|
|
|
else
|
|
|
|
|
ew16flash(ICH_FLASH_HSFCTL, hsflctl.regval);
|
|
|
|
|
|
|
|
|
|
/* Write the last 24 bits of an index within the
|
|
|
|
@ -4180,7 +4777,8 @@ static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw)
|
|
|
|
|
ew32(RFCTL, reg);
|
|
|
|
|
|
|
|
|
|
/* Enable ECC on Lynxpoint */
|
|
|
|
|
if (hw->mac.type == e1000_pch_lpt) {
|
|
|
|
|
if ((hw->mac.type == e1000_pch_lpt) ||
|
|
|
|
|
(hw->mac.type == e1000_pch_spt)) {
|
|
|
|
|
reg = er32(PBECCSTS);
|
|
|
|
|
reg |= E1000_PBECCSTS_ECC_ENABLE;
|
|
|
|
|
ew32(PBECCSTS, reg);
|
|
|
|
@ -4583,7 +5181,8 @@ void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw)
|
|
|
|
|
if ((device_id == E1000_DEV_ID_PCH_LPTLP_I218_LM) ||
|
|
|
|
|
(device_id == E1000_DEV_ID_PCH_LPTLP_I218_V) ||
|
|
|
|
|
(device_id == E1000_DEV_ID_PCH_I218_LM3) ||
|
|
|
|
|
(device_id == E1000_DEV_ID_PCH_I218_V3)) {
|
|
|
|
|
(device_id == E1000_DEV_ID_PCH_I218_V3) ||
|
|
|
|
|
(hw->mac.type == e1000_pch_spt)) {
|
|
|
|
|
u32 fextnvm6 = er32(FEXTNVM6);
|
|
|
|
|
|
|
|
|
|
ew32(FEXTNVM6, fextnvm6 & ~E1000_FEXTNVM6_REQ_PLL_CLK);
|
|
|
|
@ -5058,6 +5657,17 @@ static const struct e1000_nvm_operations ich8_nvm_ops = {
|
|
|
|
|
.write = e1000_write_nvm_ich8lan,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const struct e1000_nvm_operations spt_nvm_ops = {
|
|
|
|
|
.acquire = e1000_acquire_nvm_ich8lan,
|
|
|
|
|
.release = e1000_release_nvm_ich8lan,
|
|
|
|
|
.read = e1000_read_nvm_spt,
|
|
|
|
|
.update = e1000_update_nvm_checksum_spt,
|
|
|
|
|
.reload = e1000e_reload_nvm_generic,
|
|
|
|
|
.valid_led_default = e1000_valid_led_default_ich8lan,
|
|
|
|
|
.validate = e1000_validate_nvm_checksum_ich8lan,
|
|
|
|
|
.write = e1000_write_nvm_ich8lan,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const struct e1000_info e1000_ich8_info = {
|
|
|
|
|
.mac = e1000_ich8lan,
|
|
|
|
|
.flags = FLAG_HAS_WOL
|
|
|
|
@ -5166,3 +5776,23 @@ const struct e1000_info e1000_pch_lpt_info = {
|
|
|
|
|
.phy_ops = &ich8_phy_ops,
|
|
|
|
|
.nvm_ops = &ich8_nvm_ops,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const struct e1000_info e1000_pch_spt_info = {
|
|
|
|
|
.mac = e1000_pch_spt,
|
|
|
|
|
.flags = FLAG_IS_ICH
|
|
|
|
|
| FLAG_HAS_WOL
|
|
|
|
|
| FLAG_HAS_HW_TIMESTAMP
|
|
|
|
|
| FLAG_HAS_CTRLEXT_ON_LOAD
|
|
|
|
|
| FLAG_HAS_AMT
|
|
|
|
|
| FLAG_HAS_FLASH
|
|
|
|
|
| FLAG_HAS_JUMBO_FRAMES
|
|
|
|
|
| FLAG_APME_IN_WUC,
|
|
|
|
|
.flags2 = FLAG2_HAS_PHY_STATS
|
|
|
|
|
| FLAG2_HAS_EEE,
|
|
|
|
|
.pba = 26,
|
|
|
|
|
.max_hw_frame_size = 9018,
|
|
|
|
|
.get_variants = e1000_get_variants_ich8lan,
|
|
|
|
|
.mac_ops = &ich8_mac_ops,
|
|
|
|
|
.phy_ops = &ich8_phy_ops,
|
|
|
|
|
.nvm_ops = &spt_nvm_ops,
|
|
|
|
|
};
|
|
|
|
|