e1000e: initial support for i219
authorDavid Ertman <david.m.ertman@intel.com>
Tue, 10 Feb 2015 09:10:43 +0000 (09:10 +0000)
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>
Tue, 24 Feb 2015 01:11:53 +0000 (17:11 -0800)
i219 is the next-generation LOM that will be available on systems with the
Sunrise Point Platform Controller Hub (PCH) chipset from Intel.  This patch
provides the initial support for the device.

Signed-off-by: Dave Ertman <david.m.ertman@intel.com>
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Tested-by: Carmen Edwards <carmenx.edwards@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
drivers/net/ethernet/intel/e1000e/defines.h
drivers/net/ethernet/intel/e1000e/e1000.h
drivers/net/ethernet/intel/e1000e/ethtool.c
drivers/net/ethernet/intel/e1000e/hw.h
drivers/net/ethernet/intel/e1000e/ich8lan.c
drivers/net/ethernet/intel/e1000e/ich8lan.h
drivers/net/ethernet/intel/e1000e/netdev.c
drivers/net/ethernet/intel/e1000e/ptp.c
drivers/net/ethernet/intel/e1000e/regs.h

index bb7ab3c..0570c66 100644 (file)
 #define E1000_RCTL_LBM_TCVR       0x000000C0    /* tcvr loopback mode */
 #define E1000_RCTL_DTYP_PS        0x00000400    /* Packet Split descriptor */
 #define E1000_RCTL_RDMTS_HALF     0x00000000    /* Rx desc min threshold size */
+#define E1000_RCTL_RDMTS_HEX      0x00010000
 #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 */
index 9416e5a..a69f09e 100644 (file)
@@ -132,6 +132,7 @@ enum e1000_boards {
        board_pchlan,
        board_pch2lan,
        board_pch_lpt,
+       board_pch_spt
 };
 
 struct e1000_ps_page {
@@ -501,6 +502,7 @@ extern const struct e1000_info e1000_ich10_info;
 extern const struct e1000_info e1000_pch_info;
 extern const struct e1000_info e1000_pch2_info;
 extern const struct e1000_info e1000_pch_lpt_info;
+extern const struct e1000_info e1000_pch_spt_info;
 extern const struct e1000_info e1000_es2_info;
 
 void e1000e_ptp_init(struct e1000_adapter *adapter);
index 865ce45..11f486e 100644 (file)
@@ -896,18 +896,20 @@ static int e1000_reg_test(struct e1000_adapter *adapter, u64 *data)
        case e1000_pchlan:
        case e1000_pch2lan:
        case e1000_pch_lpt:
+       case e1000_pch_spt:
                mask |= (1 << 18);
                break;
        default:
                break;
        }
 
-       if (mac->type == e1000_pch_lpt)
+       if ((mac->type == e1000_pch_lpt) || (mac->type == e1000_pch_spt))
                wlock_mac = (er32(FWSM) & E1000_FWSM_WLOCK_MAC_MASK) >>
                    E1000_FWSM_WLOCK_MAC_SHIFT;
 
        for (i = 0; i < mac->rar_entry_count; i++) {
-               if (mac->type == e1000_pch_lpt) {
+               if ((mac->type == e1000_pch_lpt) ||
+                   (mac->type == e1000_pch_spt)) {
                        /* Cannot test write-protected SHRAL[n] registers */
                        if ((wlock_mac == 1) || (wlock_mac && (i > wlock_mac)))
                                continue;
index 72f5475..19e8c48 100644 (file)
@@ -87,6 +87,10 @@ 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  /* SPT PCH */
+#define E1000_DEV_ID_PCH_SPT_I219_V            0x1570  /* SPT PCH */
+#define E1000_DEV_ID_PCH_SPT_I219_LM2          0x15B7  /* SPT-H PCH */
+#define E1000_DEV_ID_PCH_SPT_I219_V2           0x15B8  /* SPT-H PCH */
 
 #define E1000_REVISION_4       4
 
@@ -108,6 +112,7 @@ enum e1000_mac_type {
        e1000_pchlan,
        e1000_pch2lan,
        e1000_pch_lpt,
+       e1000_pch_spt,
 };
 
 enum e1000_media_type {
@@ -153,6 +158,7 @@ enum e1000_bus_width {
        e1000_bus_width_pcie_x1,
        e1000_bus_width_pcie_x2,
        e1000_bus_width_pcie_x4 = 4,
+       e1000_bus_width_pcie_x8 = 8,
        e1000_bus_width_32,
        e1000_bus_width_64,
        e1000_bus_width_reserved
index 48b74a5..7523f51 100644 (file)
@@ -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,35 +601,50 @@ 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. */
-       if (!hw->flash_address) {
-               e_dbg("ERROR: Flash registers not mapped\n");
-               return -E1000_ERR_CONFIG;
-       }
-
        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;
+               }
 
-       gfpreg = er32flash(ICH_FLASH_GFPREG);
+               gfpreg = er32flash(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;
+               /* 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_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,8 +946,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 = e1e_rphy(hw, I217_INBAND_CTRL, &reg);
@@ -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,48 +1377,55 @@ 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;
+                       tipg_reg |= 0xFF;
+                       /* Reduce Rx latency in analog PHY */
+                       emi_val = 0;
+               } else {
 
-                       reg = er32(TIPG);
-                       reg &= ~E1000_TIPG_IPGT_MASK;
-                       reg |= 0xFF;
-                       ew32(TIPG, reg);
+                       /* Roll back the default values */
+                       tipg_reg |= 0x08;
+                       emi_val = 1;
+               }
 
-                       /* Reduce Rx latency in analog PHY */
-                       ret_val = hw->phy.ops.acquire(hw);
-                       if (ret_val)
-                               return ret_val;
+               ew32(TIPG, tipg_reg);
 
-                       if (hw->mac.type == e1000_pch2lan)
-                               emi_addr = I82579_RX_CONFIG;
-                       else
-                               emi_addr = I217_RX_CONFIG;
+               ret_val = hw->phy.ops.acquire(hw);
+               if (ret_val)
+                       return ret_val;
 
-                       ret_val = e1000_write_emi_reg_locked(hw, emi_addr, 0);
+               if (hw->mac.type == e1000_pch2lan)
+                       emi_addr = I82579_RX_CONFIG;
+               else
+                       emi_addr = I217_RX_CONFIG;
+               ret_val = e1000_write_emi_reg_locked(hw, emi_addr, emi_val);
 
-                       hw->phy.ops.release(hw);
+               hw->phy.ops.release(hw);
 
-                       if (ret_val)
-                               return ret_val;
-               }
+               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,8 +3263,10 @@ 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;
-
-       ew16flash(ICH_FLASH_HSFSTS, hsfsts.regval);
+       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
         * bit to check against, in order to start a new cycle or
@@ -3107,7 +3282,10 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw)
                 * Begin by setting Flash Cycle Done.
                 */
                hsfsts.hsf_status.flcdone = 1;
-               ew16flash(ICH_FLASH_HSFSTS, hsfsts.regval);
+               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 {
                s32 i;
@@ -3128,7 +3306,11 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw)
                         * now set the Flash Cycle Done.
                         */
                        hsfsts.hsf_status.flcdone = 1;
-                       ew16flash(ICH_FLASH_HSFSTS, hsfsts.regval);
+                       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,9 +3333,16 @@ 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 */
-       hsflctl.regval = er16flash(ICH_FLASH_HSFCTL);
+       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;
-       ew16flash(ICH_FLASH_HSFCTL, hsflctl.regval);
+
+       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 */
        do {
@@ -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;
 
-       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;
 
@@ -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)
-               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);
@@ -3596,12 +4053,25 @@ 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);
 
-               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;
-               ew16flash(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)
+                       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,9 +4347,18 @@ 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 = er16flash(ICH_FLASH_HSFCTL);
+                       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;
-                       ew16flash(ICH_FLASH_HSFCTL, hsflctl.regval);
+                       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
                         * block into Flash Linear address field in Flash
@@ -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,
+};
index 8066a49..770a573 100644 (file)
 
 #define E1000_FEXTNVM6_REQ_PLL_CLK     0x00000100
 #define E1000_FEXTNVM6_ENABLE_K1_ENTRY_CONDITION       0x00000200
+#define E1000_FEXTNVM6_K1_OFF_ENABLE   0x80000000
+/* bit for disabling packet buffer read */
+#define E1000_FEXTNVM7_DISABLE_PB_READ 0x00040000
 
 #define E1000_FEXTNVM7_DISABLE_SMB_PERST       0x00000020
 
+#define K1_ENTRY_LATENCY       0
+#define K1_MIN_TIME            1
+#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 PCIE_ICH8_SNOOP_ALL    PCIE_NO_SNOOP_ALL
 
 #define E1000_ICH_RAR_ENTRIES  7
index 1e8c40f..6fa4fc0 100644 (file)
@@ -70,6 +70,7 @@ static const struct e1000_info *e1000_info_tbl[] = {
        [board_pchlan]          = &e1000_pch_info,
        [board_pch2lan]         = &e1000_pch2_info,
        [board_pch_lpt]         = &e1000_pch_lpt_info,
+       [board_pch_spt]         = &e1000_pch_spt_info,
 };
 
 struct e1000_reg_info {
@@ -1796,7 +1797,8 @@ static irqreturn_t e1000_intr_msi(int __always_unused irq, void *data)
        }
 
        /* Reset on uncorrectable ECC error */
-       if ((icr & E1000_ICR_ECCER) && (hw->mac.type == e1000_pch_lpt)) {
+       if ((icr & E1000_ICR_ECCER) && ((hw->mac.type == e1000_pch_lpt) ||
+                                       (hw->mac.type == e1000_pch_spt))) {
                u32 pbeccsts = er32(PBECCSTS);
 
                adapter->corr_errors +=
@@ -1876,7 +1878,8 @@ static irqreturn_t e1000_intr(int __always_unused irq, void *data)
        }
 
        /* Reset on uncorrectable ECC error */
-       if ((icr & E1000_ICR_ECCER) && (hw->mac.type == e1000_pch_lpt)) {
+       if ((icr & E1000_ICR_ECCER) && ((hw->mac.type == e1000_pch_lpt) ||
+                                       (hw->mac.type == e1000_pch_spt))) {
                u32 pbeccsts = er32(PBECCSTS);
 
                adapter->corr_errors +=
@@ -2257,7 +2260,8 @@ static void e1000_irq_enable(struct e1000_adapter *adapter)
        if (adapter->msix_entries) {
                ew32(EIAC_82574, adapter->eiac_mask & E1000_EIAC_MASK_82574);
                ew32(IMS, adapter->eiac_mask | E1000_IMS_OTHER | E1000_IMS_LSC);
-       } else if (hw->mac.type == e1000_pch_lpt) {
+       } else if ((hw->mac.type == e1000_pch_lpt) ||
+                  (hw->mac.type == e1000_pch_spt)) {
                ew32(IMS, IMS_ENABLE_MASK | E1000_IMS_ECCER);
        } else {
                ew32(IMS, IMS_ENABLE_MASK);
@@ -3014,6 +3018,19 @@ static void e1000_configure_tx(struct e1000_adapter *adapter)
        ew32(TCTL, tctl);
 
        hw->mac.ops.config_collision_dist(hw);
+
+       /* SPT Si errata workaround to avoid data corruption */
+       if (hw->mac.type == e1000_pch_spt) {
+               u32 reg_val;
+
+               reg_val = er32(IOSFPC);
+               reg_val |= E1000_RCTL_RDMTS_HEX;
+               ew32(IOSFPC, reg_val);
+
+               reg_val = er32(TARC(0));
+               reg_val |= E1000_TARC0_CB_MULTIQ_3_REQ;
+               ew32(TARC(0), reg_val);
+       }
 }
 
 /**
@@ -3490,8 +3507,11 @@ s32 e1000e_get_base_timinca(struct e1000_adapter *adapter, u32 *timinca)
        struct e1000_hw *hw = &adapter->hw;
        u32 incvalue, incperiod, shift;
 
-       /* Make sure clock is enabled on I217 before checking the frequency */
-       if ((hw->mac.type == e1000_pch_lpt) &&
+       /* Make sure clock is enabled on I217/I218/I219  before checking
+        * the frequency
+        */
+       if (((hw->mac.type == e1000_pch_lpt) ||
+            (hw->mac.type == e1000_pch_spt)) &&
            !(er32(TSYNCTXCTL) & E1000_TSYNCTXCTL_ENABLED) &&
            !(er32(TSYNCRXCTL) & E1000_TSYNCRXCTL_ENABLED)) {
                u32 fextnvm7 = er32(FEXTNVM7);
@@ -3505,10 +3525,13 @@ s32 e1000e_get_base_timinca(struct e1000_adapter *adapter, u32 *timinca)
        switch (hw->mac.type) {
        case e1000_pch2lan:
        case e1000_pch_lpt:
-               /* On I217, the clock frequency is 25MHz or 96MHz as
-                * indicated by the System Clock Frequency Indication
+       case e1000_pch_spt:
+               /* On I217, I218 and I219, the clock frequency is 25MHz
+                * or 96MHz as indicated by the System Clock Frequency
+                * Indication
                 */
-               if ((hw->mac.type != e1000_pch_lpt) ||
+               if (((hw->mac.type != e1000_pch_lpt) &&
+                    (hw->mac.type != e1000_pch_spt)) ||
                    (er32(TSYNCRXCTL) & E1000_TSYNCRXCTL_SYSCFI)) {
                        /* Stable 96MHz frequency */
                        incperiod = INCPERIOD_96MHz;
@@ -3875,6 +3898,7 @@ void e1000e_reset(struct e1000_adapter *adapter)
                break;
        case e1000_pch2lan:
        case e1000_pch_lpt:
+       case e1000_pch_spt:
                fc->refresh_time = 0x0400;
 
                if (adapter->netdev->mtu <= ETH_DATA_LEN) {
@@ -4759,7 +4783,8 @@ static void e1000e_update_stats(struct e1000_adapter *adapter)
        adapter->stats.mgpdc += er32(MGTPDC);
 
        /* Correctable ECC Errors */
-       if (hw->mac.type == e1000_pch_lpt) {
+       if ((hw->mac.type == e1000_pch_lpt) ||
+           (hw->mac.type == e1000_pch_spt)) {
                u32 pbeccsts = er32(PBECCSTS);
 
                adapter->corr_errors +=
@@ -6144,7 +6169,8 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool runtime)
 
        if (adapter->hw.phy.type == e1000_phy_igp_3) {
                e1000e_igp3_phy_powerdown_workaround_ich8lan(&adapter->hw);
-       } else if (hw->mac.type == e1000_pch_lpt) {
+       } else if ((hw->mac.type == e1000_pch_lpt) ||
+                  (hw->mac.type == e1000_pch_spt)) {
                if (!(wufc & (E1000_WUFC_EX | E1000_WUFC_MC | E1000_WUFC_BC)))
                        /* ULP does not support wake from unicast, multicast
                         * or broadcast.
@@ -7213,6 +7239,10 @@ static const struct pci_device_id e1000_pci_tbl[] = {
        { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_I218_V2), board_pch_lpt },
        { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_I218_LM3), board_pch_lpt },
        { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_I218_V3), board_pch_lpt },
+       { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_SPT_I219_LM), board_pch_spt },
+       { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_SPT_I219_V), board_pch_spt },
+       { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_SPT_I219_LM2), board_pch_spt },
+       { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_SPT_I219_V2), board_pch_spt },
 
        { 0, 0, 0, 0, 0, 0, 0 } /* terminate list */
 };
index 978ef9c..1490f1e 100644 (file)
@@ -221,7 +221,9 @@ void e1000e_ptp_init(struct e1000_adapter *adapter)
        switch (hw->mac.type) {
        case e1000_pch2lan:
        case e1000_pch_lpt:
-               if ((hw->mac.type != e1000_pch_lpt) ||
+       case e1000_pch_spt:
+               if (((hw->mac.type != e1000_pch_lpt) &&
+                    (hw->mac.type != e1000_pch_spt)) ||
                    (er32(TSYNCRXCTL) & E1000_TSYNCRXCTL_SYSCFI)) {
                        adapter->ptp_clock_info.max_adj = 24000000 - 1;
                        break;
index ea235bb..85eefc4 100644 (file)
@@ -38,6 +38,7 @@
 #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_PCIEANACFG       0x00F18 /* PCIE Analog Config */
 #define E1000_FCT      0x00030 /* Flow Control Type - RW */
 #define E1000_VET      0x00038 /* VLAN Ether Type - RW */
 #define E1000_ICR      0x000C0 /* Interrupt Cause Read - R/clr */
@@ -67,6 +68,7 @@
 #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_EEWR     0x0102C /* EEPROM Write Register - RW */
 #define E1000_FLOP     0x0103C /* FLASH Opcode Register */
                                 (0x054E4 + ((_i - 16) * 8)))
 #define E1000_SHRAL(_i)                (0x05438 + ((_i) * 8))
 #define E1000_SHRAH(_i)                (0x0543C + ((_i) * 8))
+#define E1000_TARC0_CB_MULTIQ_3_REQ    (1 << 28 | 1 << 29)
 #define E1000_TDFH             0x03410 /* Tx Data FIFO Head - RW */
 #define E1000_TDFT             0x03418 /* Tx Data FIFO Tail - RW */
 #define E1000_TDFHS            0x03420 /* Tx Data FIFO Head Saved - RW */