net/e1000/base: enable new I219 devices
authorWenzhuo Lu <wenzhuo.lu@intel.com>
Wed, 23 Nov 2016 17:22:55 +0000 (12:22 -0500)
committerFerruh Yigit <ferruh.yigit@intel.com>
Tue, 17 Jan 2017 18:36:48 +0000 (19:36 +0100)
Enable the support of new I219 devices.
Also define some registers for future usage.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
drivers/net/e1000/base/e1000_api.c
drivers/net/e1000/base/e1000_defines.h
drivers/net/e1000/base/e1000_hw.h
drivers/net/e1000/base/e1000_ich8lan.c
drivers/net/e1000/base/e1000_ich8lan.h
drivers/net/e1000/base/e1000_regs.h

index bbfcae8..2abe8db 100644 (file)
@@ -298,6 +298,17 @@ s32 e1000_set_mac_type(struct e1000_hw *hw)
        case E1000_DEV_ID_PCH_I218_V3:
                mac->type = e1000_pch_lpt;
                break;
+       case E1000_DEV_ID_PCH_SPT_I219_LM:
+       case E1000_DEV_ID_PCH_SPT_I219_V:
+       case E1000_DEV_ID_PCH_SPT_I219_LM2:
+       case E1000_DEV_ID_PCH_SPT_I219_V2:
+       case E1000_DEV_ID_PCH_LBG_I219_LM3:
+       case E1000_DEV_ID_PCH_SPT_I219_LM4:
+       case E1000_DEV_ID_PCH_SPT_I219_V4:
+       case E1000_DEV_ID_PCH_SPT_I219_LM5:
+       case E1000_DEV_ID_PCH_SPT_I219_V5:
+               mac->type = e1000_pch_spt;
+               break;
        case E1000_DEV_ID_82575EB_COPPER:
        case E1000_DEV_ID_82575EB_FIBER_SERDES:
        case E1000_DEV_ID_82575GB_QUAD_COPPER:
@@ -448,6 +459,7 @@ s32 e1000_setup_init_funcs(struct e1000_hw *hw, bool init_device)
        case e1000_pchlan:
        case e1000_pch2lan:
        case e1000_pch_lpt:
+       case e1000_pch_spt:
                e1000_init_function_pointers_ich8lan(hw);
                break;
        case e1000_82575:
index 7d70ba6..dbc2bbb 100644 (file)
@@ -198,6 +198,7 @@ POSSIBILITY OF SUCH DAMAGE.
 #define E1000_RCTL_DTYP_PS     0x00000400 /* Packet Split descriptor */
 #define E1000_RCTL_RDMTS_HALF  0x00000000 /* Rx desc min thresh size */
 #define E1000_RCTL_RDMTS_HEX   0x00010000
+#define E1000_RCTL_RDMTS1_HEX  E1000_RCTL_RDMTS_HEX
 #define E1000_RCTL_MO_SHIFT    12 /* multicast offset shift */
 #define E1000_RCTL_MO_3                0x00003000 /* multicast offset 15:4 */
 #define E1000_RCTL_BAM         0x00008000 /* broadcast enable */
@@ -753,6 +754,12 @@ POSSIBILITY OF SUCH DAMAGE.
 #define E1000_TSYNCTXCTL_VALID         0x00000001 /* Tx timestamp valid */
 #define E1000_TSYNCTXCTL_ENABLED       0x00000010 /* enable Tx timestamping */
 
+/* HH Time Sync */
+#define E1000_TSYNCTXCTL_MAX_ALLOWED_DLY_MASK  0x0000F000 /* max delay */
+#define E1000_TSYNCTXCTL_SYNC_COMP_ERR         0x20000000 /* sync err */
+#define E1000_TSYNCTXCTL_SYNC_COMP             0x40000000 /* sync complete */
+#define E1000_TSYNCTXCTL_START_SYNC            0x80000000 /* initiate sync */
+
 #define E1000_TSYNCRXCTL_VALID         0x00000001 /* Rx timestamp valid */
 #define E1000_TSYNCRXCTL_TYPE_MASK     0x0000000E /* Rx type mask */
 #define E1000_TSYNCRXCTL_TYPE_L2_V2    0x00
index e4e4f76..14e2e87 100644 (file)
@@ -136,6 +136,15 @@ struct e1000_hw;
 #define E1000_DEV_ID_PCH_I218_V2               0x15A1
 #define E1000_DEV_ID_PCH_I218_LM3              0x15A2 /* Wildcat Point PCH */
 #define E1000_DEV_ID_PCH_I218_V3               0x15A3 /* Wildcat Point PCH */
+#define E1000_DEV_ID_PCH_SPT_I219_LM           0x156F /* Sunrise Point PCH */
+#define E1000_DEV_ID_PCH_SPT_I219_V            0x1570 /* Sunrise Point PCH */
+#define E1000_DEV_ID_PCH_SPT_I219_LM2          0x15B7 /* Sunrise Point-H PCH */
+#define E1000_DEV_ID_PCH_SPT_I219_V2           0x15B8 /* Sunrise Point-H PCH */
+#define E1000_DEV_ID_PCH_LBG_I219_LM3          0x15B9 /* LEWISBURG PCH */
+#define E1000_DEV_ID_PCH_SPT_I219_LM4          0x15D7
+#define E1000_DEV_ID_PCH_SPT_I219_V4           0x15D8
+#define E1000_DEV_ID_PCH_SPT_I219_LM5          0x15E3
+#define E1000_DEV_ID_PCH_SPT_I219_V5           0x15D6
 #define E1000_DEV_ID_82576                     0x10C9
 #define E1000_DEV_ID_82576_FIBER               0x10E6
 #define E1000_DEV_ID_82576_SERDES              0x10E7
@@ -221,6 +230,7 @@ enum e1000_mac_type {
        e1000_pchlan,
        e1000_pch2lan,
        e1000_pch_lpt,
+       e1000_pch_spt,
        e1000_82575,
        e1000_82576,
        e1000_82580,
@@ -954,7 +964,10 @@ struct e1000_dev_spec_ich8lan {
        u16 eee_lp_ability;
 #ifdef ULP_SUPPORT
        enum e1000_ulp_state ulp_state;
-#endif /* NAHUM6LP_HW && ULP_SUPPORT */
+       bool ulp_capability_disabled;
+       bool during_suspend_flow;
+       bool during_dpg_exit;
+#endif /* ULP_SUPPORT */
        u16 lat_enc;
        u16 max_ltr_enc;
        bool smbus_disable;
index 0837a40..7ab0f7c 100644 (file)
@@ -94,10 +94,13 @@ STATIC s32  e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw,
                                            bool active);
 STATIC s32  e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset,
                                   u16 words, u16 *data);
+STATIC s32  e1000_read_nvm_spt(struct e1000_hw *hw, u16 offset, u16 words,
+                              u16 *data);
 STATIC s32  e1000_write_nvm_ich8lan(struct e1000_hw *hw, u16 offset,
                                    u16 words, u16 *data);
 STATIC s32  e1000_validate_nvm_checksum_ich8lan(struct e1000_hw *hw);
 STATIC s32  e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw);
+STATIC s32  e1000_update_nvm_checksum_spt(struct e1000_hw *hw);
 STATIC s32  e1000_valid_led_default_ich8lan(struct e1000_hw *hw,
                                            u16 *data);
 STATIC s32 e1000_id_led_init_pchlan(struct e1000_hw *hw);
@@ -125,6 +128,14 @@ STATIC s32  e1000_read_flash_byte_ich8lan(struct e1000_hw *hw,
                                          u32 offset, u8 *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_read_flash_word_ich8lan(struct e1000_hw *hw,
                                          u32 offset, u16 *data);
 STATIC s32  e1000_retry_write_flash_byte_ich8lan(struct e1000_hw *hw,
@@ -233,7 +244,7 @@ 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) {
                /* Only unforce SMBus if ME is not active */
                if (!(E1000_READ_REG(hw, E1000_FWSM) &
                    E1000_ICH_FWSM_FW_VALID)) {
@@ -334,6 +345,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;
 
@@ -481,6 +493,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.
                         */
@@ -623,36 +636,57 @@ 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;
 
        DEBUGFUNC("e1000_init_nvm_params_ich8lan");
 
-       /* Can't read flash registers if the register set isn't mapped. */
        nvm->type = e1000_nvm_flash_sw;
-       if (!hw->flash_address) {
-               DEBUGOUT("ERROR: Flash registers not mapped\n");
-               return -E1000_ERR_CONFIG;
-       }
 
-       gfpreg = E1000_READ_FLASH_REG(hw, ICH_FLASH_GFPREG);
+       if (hw->mac.type >= e1000_pch_spt) {
+               /* in SPT, gfpreg doesn't exist. NVM size is taken from the
+                * STRAP register. This is because in SPT the GbE Flash region
+                * is no longer accessed through the flash registers. Instead,
+                * the mechanism has changed, and the Flash region access
+                * registers are now implemented in GbE memory space.
+                */
+               nvm->flash_base_addr = 0;
+               nvm_size =
+                   (((E1000_READ_REG(hw, E1000_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 {
+               /* Can't read flash registers if register set isn't mapped. */
+               if (!hw->flash_address) {
+                       DEBUGOUT("ERROR: Flash registers not mapped\n");
+                       return -E1000_ERR_CONFIG;
+               }
 
-       /* sector_X_addr is a "sector"-aligned address (4096 bytes)
-        * Add 1 to sector_end_addr since this sector is included in
-        * the overall size.
-        */
-       sector_base_addr = gfpreg & FLASH_GFPREG_BASE_MASK;
-       sector_end_addr = ((gfpreg >> 16) & FLASH_GFPREG_BASE_MASK) + 1;
+               gfpreg = E1000_READ_FLASH_REG(hw, ICH_FLASH_GFPREG);
+
+               /* sector_X_addr is a "sector"-aligned address (4096 bytes)
+                * Add 1 to sector_end_addr since this sector is included in
+                * the overall size.
+                */
+               sector_base_addr = gfpreg & FLASH_GFPREG_BASE_MASK;
+               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;
+               /* flash_base_addr is byte-aligned */
+               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.
-        */
-       nvm->flash_bank_size = ((sector_end_addr - sector_base_addr)
-                               << FLASH_SECTOR_ADDR_SHIFT);
-       nvm->flash_bank_size /= 2;
-       /* Adjust to word count */
-       nvm->flash_bank_size /= sizeof(u16);
+               /* find total size of the NVM, then cut in half since the total
+                * size represents two separate NVM banks.
+                */
+               nvm->flash_bank_size = ((sector_end_addr - sector_base_addr)
+                                       << FLASH_SECTOR_ADDR_SHIFT);
+               nvm->flash_bank_size /= 2;
+               /* Adjust to word count */
+               nvm->flash_bank_size /= sizeof(u16);
+       }
 
        nvm->word_size = E1000_SHADOW_RAM_WORDS;
 
@@ -668,8 +702,13 @@ STATIC s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw)
        /* Function Pointers */
        nvm->ops.acquire        = e1000_acquire_nvm_ich8lan;
        nvm->ops.release        = e1000_release_nvm_ich8lan;
-       nvm->ops.read           = e1000_read_nvm_ich8lan;
-       nvm->ops.update         = e1000_update_nvm_checksum_ich8lan;
+       if (hw->mac.type >= e1000_pch_spt) {
+               nvm->ops.read   = e1000_read_nvm_spt;
+               nvm->ops.update = e1000_update_nvm_checksum_spt;
+       } else {
+               nvm->ops.read   = e1000_read_nvm_ich8lan;
+               nvm->ops.update = e1000_update_nvm_checksum_ich8lan;
+       }
        nvm->ops.valid_led_default = e1000_valid_led_default_ich8lan;
        nvm->ops.validate       = e1000_validate_nvm_checksum_ich8lan;
        nvm->ops.write          = e1000_write_nvm_ich8lan;
@@ -758,6 +797,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:
 #ifndef NO_NON_BLOCKING_PHY_MTA_UPDATE_SUPPORT
                /* multicast address update for pch2 */
                mac->ops.update_mc_addr_list =
@@ -768,7 +808,13 @@ STATIC s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw)
 #if defined(QV_RELEASE) || !defined(NO_PCH_LPT_B0_SUPPORT)
                /* save PCH revision_id */
                e1000_read_pci_cfg(hw, E1000_PCI_REVISION_ID_REG, &pci_cfg);
-               hw->revision_id = (u8)(pci_cfg &= 0x000F);
+               /* SPT uses full byte for revision ID,
+                * as opposed to previous generations
+                */
+               if (hw->mac.type >= e1000_pch_spt)
+                       hw->revision_id = (u8)(pci_cfg &= 0x00FF);
+               else
+                       hw->revision_id = (u8)(pci_cfg &= 0x000F);
 #endif /* QV_RELEASE || !defined(NO_PCH_LPT_B0_SUPPORT) */
                /* check management mode */
                mac->ops.check_mng_mode = e1000_check_mng_mode_pchlan;
@@ -786,7 +832,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->rar_entry_count = E1000_PCH_LPT_RAR_ENTRIES;
                mac->ops.rar_set = e1000_rar_set_pch_lpt;
                mac->ops.setup_physical_interface = e1000_setup_copper_link_pch_lpt;
@@ -1015,8 +1061,9 @@ release:
                /* clear FEXTNVM6 bit 8 on link down or 10/100 */
                fextnvm6 &= ~E1000_FEXTNVM6_REQ_PLL_CLK;
 
-               if (!link || ((status & E1000_STATUS_SPEED_100) &&
-                             (status & E1000_STATUS_FD)))
+               if ((hw->phy.revision > 5) || !link ||
+                   ((status & E1000_STATUS_SPEED_100) &&
+                    (status & E1000_STATUS_FD)))
                        goto update_fextnvm6;
 
                ret_val = hw->phy.ops.read_reg(hw, I217_INBAND_CTRL, &reg);
@@ -1490,8 +1537,7 @@ STATIC s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
         * aggressive resulting in many collisions. To avoid this, increase
         * the IPG and reduce Rx latency in the PHY.
         */
-       if (((hw->mac.type == e1000_pch2lan) ||
-            (hw->mac.type == e1000_pch_lpt)) && link) {
+       if ((hw->mac.type >= e1000_pch2lan) && link) {
                u16 speed, duplex;
 
                e1000_get_speed_and_duplex_copper_generic(hw, &speed, &duplex);
@@ -1502,6 +1548,10 @@ STATIC s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
                        tipg_reg |= 0xFF;
                        /* Reduce Rx latency in analog PHY */
                        emi_val = 0;
+               } else if (hw->mac.type >= e1000_pch_spt &&
+                          duplex == FULL_DUPLEX && speed != SPEED_1000) {
+                       tipg_reg |= 0xC;
+                       emi_val = 1;
                } else {
                        /* Roll back the default values */
                        tipg_reg |= 0x08;
@@ -1539,6 +1589,49 @@ STATIC s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
 
                if (ret_val)
                        return ret_val;
+
+               if (hw->mac.type >= e1000_pch_spt) {
+                       u16 data;
+                       u16 ptr_gap;
+
+                       if (speed == SPEED_1000) {
+                               ret_val = hw->phy.ops.acquire(hw);
+                               if (ret_val)
+                                       return ret_val;
+
+                               ret_val = hw->phy.ops.read_reg_locked(hw,
+                                                             PHY_REG(776, 20),
+                                                             &data);
+                               if (ret_val) {
+                                       hw->phy.ops.release(hw);
+                                       return ret_val;
+                               }
+
+                               ptr_gap = (data & (0x3FF << 2)) >> 2;
+                               if (ptr_gap < 0x18) {
+                                       data &= ~(0x3FF << 2);
+                                       data |= (0x18 << 2);
+                                       ret_val =
+                                               hw->phy.ops.write_reg_locked(hw,
+                                                       PHY_REG(776, 20), data);
+                               }
+                               hw->phy.ops.release(hw);
+                               if (ret_val)
+                                       return ret_val;
+                       } else {
+                               ret_val = hw->phy.ops.acquire(hw);
+                               if (ret_val)
+                                       return ret_val;
+
+                               ret_val = hw->phy.ops.write_reg_locked(hw,
+                                                            PHY_REG(776, 20),
+                                                            0xC023);
+                               hw->phy.ops.release(hw);
+                               if (ret_val)
+                                       return ret_val;
+
+                       }
+               }
        }
 
        /* I217 Packet Loss issue:
@@ -1546,7 +1639,7 @@ STATIC s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
         * on power up.
         * Set the Beacon Duration for I217 to 8 usec
         */
-       if (hw->mac.type == e1000_pch_lpt) {
+       if (hw->mac.type >= e1000_pch_lpt) {
                u32 mac_reg;
 
                mac_reg = E1000_READ_REG(hw, E1000_FEXTNVM4);
@@ -1568,10 +1661,26 @@ STATIC s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
        hw->dev_spec.ich8lan.eee_lp_ability = 0;
 
        /* Configure K0s minimum time */
-       if (hw->mac.type == e1000_pch_lpt) {
+       if (hw->mac.type >= e1000_pch_lpt) {
                e1000_configure_k0s_lpt(hw, K1_ENTRY_LATENCY, K1_MIN_TIME);
        }
 
+       if (hw->mac.type >= e1000_pch_lpt) {
+               u32 fextnvm6 = E1000_READ_REG(hw, E1000_FEXTNVM6);
+
+               if (hw->mac.type == e1000_pch_spt) {
+                       /* FEXTNVM6 K1-off workaround - for SPT only */
+                       u32 pcieanacfg = E1000_READ_REG(hw, E1000_PCIEANACFG);
+
+                       if (pcieanacfg & E1000_FEXTNVM6_K1_OFF_ENABLE)
+                               fextnvm6 |= E1000_FEXTNVM6_K1_OFF_ENABLE;
+                       else
+                               fextnvm6 &= ~E1000_FEXTNVM6_K1_OFF_ENABLE;
+               }
+
+               E1000_WRITE_REG(hw, E1000_FEXTNVM6, fextnvm6);
+       }
+
        if (!link)
                return E1000_SUCCESS; /* No link detected */
 
@@ -1665,6 +1774,7 @@ void e1000_init_function_pointers_ich8lan(struct e1000_hw *hw)
        case e1000_pchlan:
        case e1000_pch2lan:
        case e1000_pch_lpt:
+       case e1000_pch_spt:
                hw->phy.ops.init_params = e1000_init_phy_params_pchlan;
                break;
        default:
@@ -2130,6 +2240,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:
@@ -3253,6 +3364,40 @@ STATIC s32 e1000_valid_nvm_bank_detect_ich8lan(struct e1000_hw *hw, u32 *bank)
        DEBUGFUNC("e1000_valid_nvm_bank_detect_ich8lan");
 
        switch (hw->mac.type) {
+       case e1000_pch_spt:
+               bank1_offset = nvm->flash_bank_size;
+               act_offset = E1000_ICH_NVM_SIG_WORD;
+
+               /* set bank to 0 in case flash read fails */
+               *bank = 0;
+
+               /* Check bank 0 */
+               ret_val = e1000_read_flash_dword_ich8lan(hw, act_offset,
+                                                        &nvm_dword);
+               if (ret_val)
+                       return ret_val;
+               sig_byte = (u8)((nvm_dword & 0xFF00) >> 8);
+               if ((sig_byte & E1000_ICH_NVM_VALID_SIG_MASK) ==
+                   E1000_ICH_NVM_SIG_VALUE) {
+                       *bank = 0;
+                       return E1000_SUCCESS;
+               }
+
+               /* Check bank 1 */
+               ret_val = e1000_read_flash_dword_ich8lan(hw, act_offset +
+                                                        bank1_offset,
+                                                        &nvm_dword);
+               if (ret_val)
+                       return ret_val;
+               sig_byte = (u8)((nvm_dword & 0xFF00) >> 8);
+               if ((sig_byte & E1000_ICH_NVM_VALID_SIG_MASK) ==
+                   E1000_ICH_NVM_SIG_VALUE) {
+                       *bank = 1;
+                       return E1000_SUCCESS;
+               }
+
+               DEBUGOUT("ERROR: No valid NVM bank present\n");
+               return -E1000_ERR_NVM;
        case e1000_ich8lan:
        case e1000_ich9lan:
                eecd = E1000_READ_REG(hw, E1000_EECD);
@@ -3299,6 +3444,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 = E1000_SUCCESS;
+       u32 bank = 0;
+       u32 dword = 0;
+       u16 offset_to_read;
+       u16 i;
+
+       DEBUGFUNC("e1000_read_nvm_spt");
+
+       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;
+       }
+
+       nvm->ops.acquire(hw);
+
+       ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank);
+       if (ret_val != E1000_SUCCESS) {
+               DEBUGOUT("Could not detect valid bank, assuming bank 0\n");
+               bank = 0;
+       }
+
+       act_offset = (bank) ? nvm->flash_bank_size : 0;
+       act_offset += offset;
+
+       ret_val = E1000_SUCCESS;
+
+       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)
+               DEBUGOUT1("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
@@ -3386,7 +3624,11 @@ 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;
-       E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFSTS, hsfsts.regval);
+       if (hw->mac.type >= e1000_pch_spt)
+               E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS,
+                                     hsfsts.regval & 0xFFFF);
+       else
+               E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFSTS, hsfsts.regval);
 
        /* Either we should have a hardware SPI cycle in progress
         * bit to check against, in order to start a new cycle or
@@ -3402,7 +3644,12 @@ STATIC s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw)
                 * Begin by setting Flash Cycle Done.
                 */
                hsfsts.hsf_status.flcdone = 1;
-               E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFSTS, hsfsts.regval);
+               if (hw->mac.type >= e1000_pch_spt)
+                       E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS,
+                                             hsfsts.regval & 0xFFFF);
+               else
+                       E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFSTS,
+                                               hsfsts.regval);
                ret_val = E1000_SUCCESS;
        } else {
                s32 i;
@@ -3424,8 +3671,12 @@ STATIC s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw)
                         * now set the Flash Cycle Done.
                         */
                        hsfsts.hsf_status.flcdone = 1;
-                       E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFSTS,
-                                               hsfsts.regval);
+                       if (hw->mac.type >= e1000_pch_spt)
+                               E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS,
+                                                     hsfsts.regval & 0xFFFF);
+                       else
+                               E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFSTS,
+                                                       hsfsts.regval);
                } else {
                        DEBUGOUT("Flash controller busy, cannot get access\n");
                }
@@ -3450,10 +3701,17 @@ STATIC s32 e1000_flash_cycle_ich8lan(struct e1000_hw *hw, u32 timeout)
        DEBUGFUNC("e1000_flash_cycle_ich8lan");
 
        /* Start a cycle by writing 1 in Flash Cycle Go in Hw Flash Control */
-       hsflctl.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFCTL);
+       if (hw->mac.type >= e1000_pch_spt)
+               hsflctl.regval = E1000_READ_FLASH_REG(hw, ICH_FLASH_HSFSTS)>>16;
+       else
+               hsflctl.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFCTL);
        hsflctl.hsf_ctrl.flcgo = 1;
 
-       E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL, hsflctl.regval);
+       if (hw->mac.type >= e1000_pch_spt)
+               E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS,
+                                     hsflctl.regval << 16);
+       else
+               E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL, hsflctl.regval);
 
        /* wait till FDONE bit is set to 1 */
        do {
@@ -3469,6 +3727,29 @@ 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)
+{
+       DEBUGFUNC("e1000_read_flash_dword_ich8lan");
+
+       if (!data)
+               return -E1000_ERR_NVM;
+
+       /* 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
@@ -3506,7 +3787,13 @@ STATIC s32 e1000_read_flash_byte_ich8lan(struct e1000_hw *hw, u32 offset,
        s32 ret_val;
        u16 word = 0;
 
-       ret_val = e1000_read_flash_data_ich8lan(hw, offset, 1, &word);
+       /* 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;
@@ -3592,6 +3879,83 @@ 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;
+
+       DEBUGFUNC("e1000_read_flash_data_ich8lan");
+
+               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 {
+               usec_delay(1);
+               /* Steps */
+               ret_val = e1000_flash_cycle_init_ich8lan(hw);
+               if (ret_val != E1000_SUCCESS)
+                       break;
+               /* In SPT, This register is in Lan memory space, not flash.
+                * Therefore, only 32 bit access is supported
+                */
+               hsflctl.regval = E1000_READ_FLASH_REG(hw, 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
+                */
+               E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS,
+                                     (u32)hsflctl.regval << 16);
+               E1000_WRITE_FLASH_REG(hw, 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 == E1000_SUCCESS) {
+                       *data = E1000_READ_FLASH_REG(hw, 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 = E1000_READ_FLASH_REG16(hw,
+                                                             ICH_FLASH_HSFSTS);
+                       if (hsfsts.hsf_status.flcerr) {
+                               /* Repeat for some time before giving up. */
+                               continue;
+                       } else if (!hsfsts.hsf_status.flcdone) {
+                               DEBUGOUT("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
@@ -3629,6 +3993,175 @@ STATIC s32 e1000_write_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words,
        return E1000_SUCCESS;
 }
 
+/**
+ *  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,
+ *  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_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;
+       u32 dword = 0;
+
+       DEBUGFUNC("e1000_update_nvm_checksum_spt");
+
+       ret_val = e1000_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 != E1000_SUCCESS) {
+               DEBUGOUT("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_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;
+
+               usec_delay(100);
+
+               /* 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) {
+               DEBUGOUT("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_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);
+               msec_delay(10);
+       }
+
+out:
+       if (ret_val)
+               DEBUGOUT1("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
@@ -3806,6 +4339,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;
@@ -3853,8 +4387,13 @@ STATIC s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
 
        DEBUGFUNC("e1000_write_ich8_data");
 
-       if (size < 1 || size > 2 || offset > ICH_FLASH_LINEAR_ADDR_MASK)
-               return -E1000_ERR_NVM;
+       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);
@@ -3865,12 +4404,29 @@ STATIC s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
                ret_val = e1000_flash_cycle_init_ich8lan(hw);
                if (ret_val != E1000_SUCCESS)
                        break;
-               hsflctl.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFCTL);
+               /* 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 =
+                           E1000_READ_FLASH_REG(hw, ICH_FLASH_HSFSTS)>>16;
+               else
+                       hsflctl.regval =
+                           E1000_READ_FLASH_REG16(hw, 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;
-               E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL, hsflctl.regval);
+               /* 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)
+                       E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS,
+                                             hsflctl.regval << 16);
+               else
+                       E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL,
+                                               hsflctl.regval);
 
                E1000_WRITE_FLASH_REG(hw, ICH_FLASH_FADDR, flash_linear_addr);
 
@@ -3908,6 +4464,94 @@ 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;
+
+       DEBUGFUNC("e1000_write_flash_data32_ich8lan");
+
+       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 {
+               usec_delay(1);
+               /* Steps */
+               ret_val = e1000_flash_cycle_init_ich8lan(hw);
+               if (ret_val != E1000_SUCCESS)
+                       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 = E1000_READ_FLASH_REG(hw,
+                                                             ICH_FLASH_HSFSTS)
+                                        >> 16;
+               else
+                       hsflctl.regval = E1000_READ_FLASH_REG16(hw,
+                                                             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)
+                       E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS,
+                                             hsflctl.regval << 16);
+               else
+                       E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL,
+                                               hsflctl.regval);
+
+               E1000_WRITE_FLASH_REG(hw, ICH_FLASH_FADDR, flash_linear_addr);
+
+               E1000_WRITE_FLASH_REG(hw, 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 == E1000_SUCCESS)
+                       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 = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFSTS);
+
+               if (hsfsts.hsf_status.flcerr)
+                       /* Repeat for some time before giving up. */
+                       continue;
+               if (!hsfsts.hsf_status.flcdone) {
+                       DEBUGOUT("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
@@ -3927,7 +4571,42 @@ 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;
+
+       DEBUGFUNC("e1000_retry_write_flash_dword_ich8lan");
+
+       /* 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++) {
+               DEBUGOUT2("Retrying Byte %8.8X at offset %u\n", dword, offset);
+               usec_delay(100);
+               ret_val = e1000_write_flash_data32_ich8lan(hw, offset, dword);
+               if (ret_val == E1000_SUCCESS)
+                       break;
+       }
+       if (program_retries == 100)
+               return -E1000_ERR_NVM;
+
+       return E1000_SUCCESS;
+}
 
 /**
  *  e1000_retry_write_flash_byte_ich8lan - Writes a single byte to NVM
@@ -4037,12 +4716,22 @@ 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
                         */
-                       hsflctl.regval =
-                           E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFCTL);
+                       if (hw->mac.type >= e1000_pch_spt)
+                               hsflctl.regval =
+                                   E1000_READ_FLASH_REG(hw,
+                                                        ICH_FLASH_HSFSTS)>>16;
+                       else
+                               hsflctl.regval =
+                                   E1000_READ_FLASH_REG16(hw,
+                                                          ICH_FLASH_HSFCTL);
 
                        hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_ERASE;
-                       E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL,
-                                               hsflctl.regval);
+                       if (hw->mac.type >= e1000_pch_spt)
+                               E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS,
+                                                     hsflctl.regval << 16);
+                       else
+                               E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL,
+                                                       hsflctl.regval);
 
                        /* Write the last 24 bits of an index within the
                         * block into Flash Linear address field in Flash
@@ -4475,7 +5164,7 @@ STATIC void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw)
        E1000_WRITE_REG(hw, E1000_RFCTL, reg);
 
        /* Enable ECC on Lynxpoint */
-       if (hw->mac.type == e1000_pch_lpt) {
+       if (hw->mac.type >= e1000_pch_lpt) {
                reg = E1000_READ_REG(hw, E1000_PBECCSTS);
                reg |= E1000_PBECCSTS_ECC_ENABLE;
                E1000_WRITE_REG(hw, E1000_PBECCSTS, reg);
@@ -4907,7 +5596,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 = E1000_READ_REG(hw, E1000_FEXTNVM6);
 
                        E1000_WRITE_REG(hw, E1000_FEXTNVM6,
index 352b959..50e0e79 100644 (file)
@@ -121,6 +121,18 @@ POSSIBILITY OF SUCH DAMAGE.
 #if !defined(EXTERNAL_RELEASE) || defined(ULP_SUPPORT)
 #define E1000_FEXTNVM7_DISABLE_SMB_PERST       0x00000020
 #endif /* !EXTERNAL_RELEASE || ULP_SUPPORT */
+#define E1000_FEXTNVM9_IOSFSB_CLKGATE_DIS      0x00000800
+#define E1000_FEXTNVM9_IOSFSB_CLKREQ_DIS       0x00001000
+#define E1000_FEXTNVM11_DISABLE_PB_READ                0x00000200
+#define E1000_FEXTNVM11_DISABLE_MULR_FIX       0x00002000
+
+/* bit24: RXDCTL thresholds granularity: 0 - cache lines, 1 - descriptors */
+#define E1000_RXDCTL_THRESH_UNIT_DESC  0x01000000
+
+#define NVM_SIZE_MULTIPLIER 4096  /*multiplier for NVMS field*/
+#define E1000_FLASH_BASE_ADDR 0xE000 /*offset of NVM access regs*/
+#define E1000_CTRL_EXT_NVMVS 0x3 /*NVM valid sector */
+#define E1000_TARC0_CB_MULTIQ_3_REQ    (1 << 28 | 1 << 29)
 #define PCIE_ICH8_SNOOP_ALL    PCIE_NO_SNOOP_ALL
 
 #define E1000_ICH_RAR_ENTRIES  7
index 84531a9..364a726 100644 (file)
@@ -66,6 +66,8 @@ POSSIBILITY OF SUCH DAMAGE.
 #define E1000_FEXTNVM4 0x00024  /* Future Extended NVM 4 - RW */
 #define E1000_FEXTNVM6 0x00010  /* Future Extended NVM 6 - RW */
 #define E1000_FEXTNVM7 0x000E4  /* Future Extended NVM 7 - RW */
+#define E1000_FEXTNVM9 0x5BB4  /* Future Extended NVM 9 - RW */
+#define E1000_FEXTNVM11        0x5BBC  /* Future Extended NVM 11 - RW */
 #define E1000_PCIEANACFG       0x00F18 /* PCIE Analog Config */
 #define E1000_FCT      0x00030  /* Flow Control Type - RW */
 #define E1000_CONNSW   0x00034  /* Copper/Fiber switch control - RW */
@@ -109,6 +111,7 @@ POSSIBILITY OF SUCH DAMAGE.
 #define E1000_PBA      0x01000  /* Packet Buffer Allocation - RW */
 #define E1000_PBS      0x01008  /* Packet Buffer Size */
 #define E1000_PBECCSTS 0x0100C  /* Packet Buffer ECC Status - RW */
+#define E1000_IOSFPC   0x00F28  /* TX corrupted data  */
 #define E1000_EEMNGCTL 0x01010  /* MNG EEprom Control */
 #define E1000_EEMNGCTL_I210    0x01010  /* i210 MNG EEprom Mode Control */
 #define E1000_EEARBC   0x01024  /* EEPROM Auto Read Bus Control */
@@ -591,6 +594,10 @@ POSSIBILITY OF SUCH DAMAGE.
 #define E1000_TIMADJL  0x0B60C /* Time sync time adjustment offset Low - RW */
 #define E1000_TIMADJH  0x0B610 /* Time sync time adjustment offset High - RW */
 #define E1000_TSAUXC   0x0B640 /* Timesync Auxiliary Control register */
+#define        E1000_SYSSTMPL  0x0B648 /* HH Timesync system stamp low register */
+#define        E1000_SYSSTMPH  0x0B64C /* HH Timesync system stamp hi register */
+#define        E1000_PLTSTMPL  0x0B640 /* HH Timesync platform stamp low register */
+#define        E1000_PLTSTMPH  0x0B644 /* HH Timesync platform stamp hi register */
 #define E1000_SYSTIMR  0x0B6F8 /* System time register Residue */
 #define E1000_TSICR    0x0B66C /* Interrupt Cause Register */
 #define E1000_TSIM     0x0B674 /* Interrupt Mask Register */