aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/intel/e1000e/ich8lan.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/intel/e1000e/ich8lan.c')
-rw-r--r--drivers/net/ethernet/intel/e1000e/ich8lan.c795
1 files changed, 636 insertions, 159 deletions
diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.c b/drivers/net/ethernet/intel/e1000e/ich8lan.c
index 64c76443a7aa..bbf70ba367da 100644
--- a/drivers/net/ethernet/intel/e1000e/ich8lan.c
+++ b/drivers/net/ethernet/intel/e1000e/ich8lan.c
@@ -105,6 +105,9 @@
#define E1000_FEXTNVM_SW_CONFIG 1
#define E1000_FEXTNVM_SW_CONFIG_ICH8M (1 << 27) /* Bit redefined for ICH8M :/ */
+#define E1000_FEXTNVM3_PHY_CFG_COUNTER_MASK 0x0C000000
+#define E1000_FEXTNVM3_PHY_CFG_COUNTER_50MSEC 0x08000000
+
#define E1000_FEXTNVM4_BEACON_DURATION_MASK 0x7
#define E1000_FEXTNVM4_BEACON_DURATION_8USEC 0x7
#define E1000_FEXTNVM4_BEACON_DURATION_16USEC 0x3
@@ -112,6 +115,8 @@
#define PCIE_ICH8_SNOOP_ALL PCIE_NO_SNOOP_ALL
#define E1000_ICH_RAR_ENTRIES 7
+#define E1000_PCH2_RAR_ENTRIES 5 /* RAR[0], SHRA[0-3] */
+#define E1000_PCH_LPT_RAR_ENTRIES 12 /* RAR[0], SHRA[0-10] */
#define PHY_PAGE_SHIFT 5
#define PHY_REG(page, reg) (((page) << PHY_PAGE_SHIFT) | \
@@ -127,14 +132,22 @@
#define SW_FLAG_TIMEOUT 1000 /* SW Semaphore flag timeout in milliseconds */
+/* SMBus Control Phy Register */
+#define CV_SMB_CTRL PHY_REG(769, 23)
+#define CV_SMB_CTRL_FORCE_SMBUS 0x0001
+
/* SMBus Address Phy Register */
#define HV_SMB_ADDR PHY_REG(768, 26)
#define HV_SMB_ADDR_MASK 0x007F
#define HV_SMB_ADDR_PEC_EN 0x0200
#define HV_SMB_ADDR_VALID 0x0080
+#define HV_SMB_ADDR_FREQ_MASK 0x1100
+#define HV_SMB_ADDR_FREQ_LOW_SHIFT 8
+#define HV_SMB_ADDR_FREQ_HIGH_SHIFT 12
/* PHY Power Management Control */
#define HV_PM_CTRL PHY_REG(770, 17)
+#define HV_PM_CTRL_PLL_STOP_IN_K1_GIGA 0x100
/* PHY Low Power Idle Control */
#define I82579_LPI_CTRL PHY_REG(772, 20)
@@ -147,11 +160,26 @@
#define I82579_LPI_UPDATE_TIMER 0x4805 /* in 40ns units + 40 ns base value */
#define I82579_MSE_THRESHOLD 0x084F /* Mean Square Error Threshold */
#define I82579_MSE_LINK_DOWN 0x2411 /* MSE count before dropping link */
+#define I217_EEE_ADVERTISEMENT 0x8001 /* IEEE MMD Register 7.60 */
+#define I217_EEE_LP_ABILITY 0x8002 /* IEEE MMD Register 7.61 */
+#define I217_EEE_100_SUPPORTED (1 << 1) /* 100BaseTx EEE supported */
+
+/* Intel Rapid Start Technology Support */
+#define I217_PROXY_CTRL PHY_REG(BM_WUC_PAGE, 70)
+#define I217_PROXY_CTRL_AUTO_DISABLE 0x0080
+#define I217_SxCTRL PHY_REG(BM_PORT_CTRL_PAGE, 28)
+#define I217_SxCTRL_MASK 0x1000
+#define I217_CGFREG PHY_REG(772, 29)
+#define I217_CGFREG_MASK 0x0002
+#define I217_MEMPWR PHY_REG(772, 26)
+#define I217_MEMPWR_MASK 0x0010
/* Strapping Option Register - RO */
#define E1000_STRAP 0x0000C
#define E1000_STRAP_SMBUS_ADDRESS_MASK 0x00FE0000
#define E1000_STRAP_SMBUS_ADDRESS_SHIFT 17
+#define E1000_STRAP_SMT_FREQ_MASK 0x00003000
+#define E1000_STRAP_SMT_FREQ_SHIFT 12
/* OEM Bits Phy Register */
#define HV_OEM_BITS PHY_REG(768, 25)
@@ -255,6 +283,8 @@ static s32 e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link);
static s32 e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw);
static bool e1000_check_mng_mode_ich8lan(struct e1000_hw *hw);
static bool e1000_check_mng_mode_pchlan(struct e1000_hw *hw);
+static void e1000_rar_set_pch2lan(struct e1000_hw *hw, u8 *addr, u32 index);
+static void e1000_rar_set_pch_lpt(struct e1000_hw *hw, u8 *addr, u32 index);
static s32 e1000_k1_workaround_lv(struct e1000_hw *hw);
static void e1000_gate_hw_phy_config_ich8lan(struct e1000_hw *hw, bool gate);
@@ -283,18 +313,161 @@ static inline void __ew32flash(struct e1000_hw *hw, unsigned long reg, u32 val)
#define ew16flash(reg, val) __ew16flash(hw, (reg), (val))
#define ew32flash(reg, val) __ew32flash(hw, (reg), (val))
-static void e1000_toggle_lanphypc_value_ich8lan(struct e1000_hw *hw)
+/**
+ * e1000_phy_is_accessible_pchlan - Check if able to access PHY registers
+ * @hw: pointer to the HW structure
+ *
+ * Test access to the PHY registers by reading the PHY ID registers. If
+ * the PHY ID is already known (e.g. resume path) compare it with known ID,
+ * otherwise assume the read PHY ID is correct if it is valid.
+ *
+ * Assumes the sw/fw/hw semaphore is already acquired.
+ **/
+static bool e1000_phy_is_accessible_pchlan(struct e1000_hw *hw)
{
- u32 ctrl;
+ u16 phy_reg;
+ u32 phy_id;
- ctrl = er32(CTRL);
- ctrl |= E1000_CTRL_LANPHYPC_OVERRIDE;
- ctrl &= ~E1000_CTRL_LANPHYPC_VALUE;
- ew32(CTRL, ctrl);
- e1e_flush();
- udelay(10);
- ctrl &= ~E1000_CTRL_LANPHYPC_OVERRIDE;
- ew32(CTRL, ctrl);
+ e1e_rphy_locked(hw, PHY_ID1, &phy_reg);
+ phy_id = (u32)(phy_reg << 16);
+ e1e_rphy_locked(hw, PHY_ID2, &phy_reg);
+ phy_id |= (u32)(phy_reg & PHY_REVISION_MASK);
+
+ if (hw->phy.id) {
+ if (hw->phy.id == phy_id)
+ return true;
+ } else {
+ if ((phy_id != 0) && (phy_id != PHY_REVISION_MASK))
+ hw->phy.id = phy_id;
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * e1000_init_phy_workarounds_pchlan - PHY initialization workarounds
+ * @hw: pointer to the HW structure
+ *
+ * Workarounds/flow necessary for PHY initialization during driver load
+ * and resume paths.
+ **/
+static s32 e1000_init_phy_workarounds_pchlan(struct e1000_hw *hw)
+{
+ u32 mac_reg, fwsm = er32(FWSM);
+ s32 ret_val;
+ u16 phy_reg;
+
+ ret_val = hw->phy.ops.acquire(hw);
+ if (ret_val) {
+ e_dbg("Failed to initialize PHY flow\n");
+ return ret_val;
+ }
+
+ /*
+ * The MAC-PHY interconnect may be in SMBus mode. If the PHY is
+ * inaccessible and resetting the PHY is not blocked, toggle the
+ * LANPHYPC Value bit to force the interconnect to PCIe mode.
+ */
+ switch (hw->mac.type) {
+ case e1000_pch_lpt:
+ if (e1000_phy_is_accessible_pchlan(hw))
+ break;
+
+ /*
+ * Before toggling LANPHYPC, see if PHY is accessible by
+ * forcing MAC to SMBus mode first.
+ */
+ mac_reg = er32(CTRL_EXT);
+ mac_reg |= E1000_CTRL_EXT_FORCE_SMBUS;
+ ew32(CTRL_EXT, mac_reg);
+
+ /* fall-through */
+ case e1000_pch2lan:
+ /*
+ * Gate automatic PHY configuration by hardware on
+ * non-managed 82579
+ */
+ if ((hw->mac.type == e1000_pch2lan) &&
+ !(fwsm & E1000_ICH_FWSM_FW_VALID))
+ e1000_gate_hw_phy_config_ich8lan(hw, true);
+
+ if (e1000_phy_is_accessible_pchlan(hw)) {
+ if (hw->mac.type == e1000_pch_lpt) {
+ /* Unforce SMBus mode in PHY */
+ e1e_rphy_locked(hw, CV_SMB_CTRL, &phy_reg);
+ phy_reg &= ~CV_SMB_CTRL_FORCE_SMBUS;
+ e1e_wphy_locked(hw, CV_SMB_CTRL, phy_reg);
+
+ /* Unforce SMBus mode in MAC */
+ mac_reg = er32(CTRL_EXT);
+ mac_reg &= ~E1000_CTRL_EXT_FORCE_SMBUS;
+ ew32(CTRL_EXT, mac_reg);
+ }
+ break;
+ }
+
+ /* fall-through */
+ case e1000_pchlan:
+ if ((hw->mac.type == e1000_pchlan) &&
+ (fwsm & E1000_ICH_FWSM_FW_VALID))
+ break;
+
+ if (hw->phy.ops.check_reset_block(hw)) {
+ e_dbg("Required LANPHYPC toggle blocked by ME\n");
+ break;
+ }
+
+ e_dbg("Toggling LANPHYPC\n");
+
+ /* Set Phy Config Counter to 50msec */
+ mac_reg = er32(FEXTNVM3);
+ mac_reg &= ~E1000_FEXTNVM3_PHY_CFG_COUNTER_MASK;
+ mac_reg |= E1000_FEXTNVM3_PHY_CFG_COUNTER_50MSEC;
+ ew32(FEXTNVM3, mac_reg);
+
+ /* Toggle LANPHYPC Value bit */
+ mac_reg = er32(CTRL);
+ mac_reg |= E1000_CTRL_LANPHYPC_OVERRIDE;
+ mac_reg &= ~E1000_CTRL_LANPHYPC_VALUE;
+ ew32(CTRL, mac_reg);
+ e1e_flush();
+ udelay(10);
+ mac_reg &= ~E1000_CTRL_LANPHYPC_OVERRIDE;
+ ew32(CTRL, mac_reg);
+ e1e_flush();
+ if (hw->mac.type < e1000_pch_lpt) {
+ msleep(50);
+ } else {
+ u16 count = 20;
+ do {
+ usleep_range(5000, 10000);
+ } while (!(er32(CTRL_EXT) &
+ E1000_CTRL_EXT_LPCD) && count--);
+ }
+ break;
+ default:
+ break;
+ }
+
+ hw->phy.ops.release(hw);
+
+ /*
+ * Reset the PHY before any access to it. Doing so, ensures
+ * that the PHY is in a known good state before we read/write
+ * PHY registers. The generic reset is sufficient here,
+ * because we haven't determined the PHY type yet.
+ */
+ ret_val = e1000e_phy_hw_reset_generic(hw);
+
+ /* Ungate automatic PHY configuration on non-managed 82579 */
+ if ((hw->mac.type == e1000_pch2lan) &&
+ !(fwsm & E1000_ICH_FWSM_FW_VALID)) {
+ usleep_range(10000, 20000);
+ e1000_gate_hw_phy_config_ich8lan(hw, false);
+ }
+
+ return ret_val;
}
/**
@@ -324,70 +497,41 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)
phy->ops.power_down = e1000_power_down_phy_copper_ich8lan;
phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT;
- if (!hw->phy.ops.check_reset_block(hw)) {
- u32 fwsm = er32(FWSM);
-
- /*
- * The MAC-PHY interconnect may still be in SMBus mode after
- * Sx->S0. If resetting the PHY is not blocked, toggle the
- * LANPHYPC Value bit to force the interconnect to PCIe mode.
- */
- e1000_toggle_lanphypc_value_ich8lan(hw);
- msleep(50);
-
- /*
- * Gate automatic PHY configuration by hardware on
- * non-managed 82579
- */
- if ((hw->mac.type == e1000_pch2lan) &&
- !(fwsm & E1000_ICH_FWSM_FW_VALID))
- e1000_gate_hw_phy_config_ich8lan(hw, true);
-
- /*
- * Reset the PHY before any access to it. Doing so, ensures
- * that the PHY is in a known good state before we read/write
- * PHY registers. The generic reset is sufficient here,
- * because we haven't determined the PHY type yet.
- */
- ret_val = e1000e_phy_hw_reset_generic(hw);
- if (ret_val)
- return ret_val;
+ phy->id = e1000_phy_unknown;
- /* Ungate automatic PHY configuration on non-managed 82579 */
- if ((hw->mac.type == e1000_pch2lan) &&
- !(fwsm & E1000_ICH_FWSM_FW_VALID)) {
- usleep_range(10000, 20000);
- e1000_gate_hw_phy_config_ich8lan(hw, false);
- }
- }
+ ret_val = e1000_init_phy_workarounds_pchlan(hw);
+ if (ret_val)
+ return ret_val;
- phy->id = e1000_phy_unknown;
- switch (hw->mac.type) {
- default:
- ret_val = e1000e_get_phy_id(hw);
- if (ret_val)
- return ret_val;
- if ((phy->id != 0) && (phy->id != PHY_REVISION_MASK))
+ if (phy->id == e1000_phy_unknown)
+ switch (hw->mac.type) {
+ default:
+ ret_val = e1000e_get_phy_id(hw);
+ if (ret_val)
+ return ret_val;
+ if ((phy->id != 0) && (phy->id != PHY_REVISION_MASK))
+ break;
+ /* fall-through */
+ case e1000_pch2lan:
+ case e1000_pch_lpt:
+ /*
+ * In case the PHY needs to be in mdio slow mode,
+ * set slow mode and try to get the PHY id again.
+ */
+ ret_val = e1000_set_mdio_slow_mode_hv(hw);
+ if (ret_val)
+ return ret_val;
+ ret_val = e1000e_get_phy_id(hw);
+ if (ret_val)
+ return ret_val;
break;
- /* fall-through */
- case e1000_pch2lan:
- /*
- * In case the PHY needs to be in mdio slow mode,
- * set slow mode and try to get the PHY id again.
- */
- ret_val = e1000_set_mdio_slow_mode_hv(hw);
- if (ret_val)
- return ret_val;
- ret_val = e1000e_get_phy_id(hw);
- if (ret_val)
- return ret_val;
- break;
- }
+ }
phy->type = e1000e_get_phy_type_from_id(phy->id);
switch (phy->type) {
case e1000_phy_82577:
case e1000_phy_82579:
+ case e1000_phy_i217:
phy->ops.check_polarity = e1000_check_polarity_82577;
phy->ops.force_speed_duplex =
e1000_phy_force_speed_duplex_82577;
@@ -572,7 +716,7 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw)
/* Adaptive IFS supported */
mac->adaptive_ifs = true;
- /* LED operations */
+ /* LED and other operations */
switch (mac->type) {
case e1000_ich8lan:
case e1000_ich9lan:
@@ -591,8 +735,12 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw)
mac->ops.led_on = e1000_led_on_ich8lan;
mac->ops.led_off = e1000_led_off_ich8lan;
break;
- case e1000_pchlan:
case e1000_pch2lan:
+ mac->rar_entry_count = E1000_PCH2_RAR_ENTRIES;
+ mac->ops.rar_set = e1000_rar_set_pch2lan;
+ /* fall-through */
+ case e1000_pch_lpt:
+ case e1000_pchlan:
/* check management mode */
mac->ops.check_mng_mode = e1000_check_mng_mode_pchlan;
/* ID LED init */
@@ -609,12 +757,20 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw)
break;
}
+ if (mac->type == e1000_pch_lpt) {
+ mac->rar_entry_count = E1000_PCH_LPT_RAR_ENTRIES;
+ mac->ops.rar_set = e1000_rar_set_pch_lpt;
+ }
+
/* Enable PCS Lock-loss workaround for ICH8 */
if (mac->type == e1000_ich8lan)
e1000e_set_kmrn_lock_loss_workaround_ich8lan(hw, true);
- /* Gate automatic PHY configuration by hardware on managed 82579 */
- if ((mac->type == e1000_pch2lan) &&
+ /*
+ * Gate automatic PHY configuration by hardware on managed
+ * 82579 and i217
+ */
+ if ((mac->type == e1000_pch2lan || mac->type == e1000_pch_lpt) &&
(er32(FWSM) & E1000_ICH_FWSM_FW_VALID))
e1000_gate_hw_phy_config_ich8lan(hw, true);
@@ -630,22 +786,50 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw)
**/
static s32 e1000_set_eee_pchlan(struct e1000_hw *hw)
{
+ struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
s32 ret_val = 0;
u16 phy_reg;
- if (hw->phy.type != e1000_phy_82579)
+ if ((hw->phy.type != e1000_phy_82579) &&
+ (hw->phy.type != e1000_phy_i217))
return 0;
ret_val = e1e_rphy(hw, I82579_LPI_CTRL, &phy_reg);
if (ret_val)
return ret_val;
- if (hw->dev_spec.ich8lan.eee_disable)
+ if (dev_spec->eee_disable)
phy_reg &= ~I82579_LPI_CTRL_ENABLE_MASK;
else
phy_reg |= I82579_LPI_CTRL_ENABLE_MASK;
- return e1e_wphy(hw, I82579_LPI_CTRL, phy_reg);
+ ret_val = e1e_wphy(hw, I82579_LPI_CTRL, phy_reg);
+ if (ret_val)
+ return ret_val;
+
+ if ((hw->phy.type == e1000_phy_i217) && !dev_spec->eee_disable) {
+ /* Save off link partner's EEE ability */
+ ret_val = hw->phy.ops.acquire(hw);
+ if (ret_val)
+ return ret_val;
+ ret_val = e1e_wphy_locked(hw, I82579_EMI_ADDR,
+ I217_EEE_LP_ABILITY);
+ if (ret_val)
+ goto release;
+ e1e_rphy_locked(hw, I82579_EMI_DATA, &dev_spec->eee_lp_ability);
+
+ /*
+ * EEE is not supported in 100Half, so ignore partner's EEE
+ * in 100 ability if full-duplex is not advertised.
+ */
+ e1e_rphy_locked(hw, PHY_LP_ABILITY, &phy_reg);
+ if (!(phy_reg & NWAY_LPAR_100TX_FD_CAPS))
+ dev_spec->eee_lp_ability &= ~I217_EEE_100_SUPPORTED;
+release:
+ hw->phy.ops.release(hw);
+ }
+
+ return 0;
}
/**
@@ -687,6 +871,9 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
return ret_val;
}
+ /* Clear link partner's EEE ability */
+ hw->dev_spec.ich8lan.eee_lp_ability = 0;
+
if (!link)
return 0; /* No link detected */
@@ -782,6 +969,7 @@ static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter)
break;
case e1000_pchlan:
case e1000_pch2lan:
+ case e1000_pch_lpt:
rc = e1000_init_phy_params_pchlan(hw);
break;
default:
@@ -967,6 +1155,145 @@ static bool e1000_check_mng_mode_pchlan(struct e1000_hw *hw)
}
/**
+ * e1000_rar_set_pch2lan - Set receive address register
+ * @hw: pointer to the HW structure
+ * @addr: pointer to the receive address
+ * @index: receive address array register
+ *
+ * Sets the receive address array register at index to the address passed
+ * in by addr. For 82579, RAR[0] is the base address register that is to
+ * contain the MAC address but RAR[1-6] are reserved for manageability (ME).
+ * Use SHRA[0-3] in place of those reserved for ME.
+ **/
+static void e1000_rar_set_pch2lan(struct e1000_hw *hw, u8 *addr, u32 index)
+{
+ u32 rar_low, rar_high;
+
+ /*
+ * HW expects these in little endian so we reverse the byte order
+ * from network order (big endian) to little endian
+ */
+ rar_low = ((u32)addr[0] |
+ ((u32)addr[1] << 8) |
+ ((u32)addr[2] << 16) | ((u32)addr[3] << 24));
+
+ rar_high = ((u32)addr[4] | ((u32)addr[5] << 8));
+
+ /* If MAC address zero, no need to set the AV bit */
+ if (rar_low || rar_high)
+ rar_high |= E1000_RAH_AV;
+
+ if (index == 0) {
+ ew32(RAL(index), rar_low);
+ e1e_flush();
+ ew32(RAH(index), rar_high);
+ e1e_flush();
+ return;
+ }
+
+ if (index < hw->mac.rar_entry_count) {
+ s32 ret_val;
+
+ ret_val = e1000_acquire_swflag_ich8lan(hw);
+ if (ret_val)
+ goto out;
+
+ ew32(SHRAL(index - 1), rar_low);
+ e1e_flush();
+ ew32(SHRAH(index - 1), rar_high);
+ e1e_flush();
+
+ e1000_release_swflag_ich8lan(hw);
+
+ /* verify the register updates */
+ if ((er32(SHRAL(index - 1)) == rar_low) &&
+ (er32(SHRAH(index - 1)) == rar_high))
+ return;
+
+ e_dbg("SHRA[%d] might be locked by ME - FWSM=0x%8.8x\n",
+ (index - 1), er32(FWSM));
+ }
+
+out:
+ e_dbg("Failed to write receive address at index %d\n", index);
+}
+
+/**
+ * e1000_rar_set_pch_lpt - Set receive address registers
+ * @hw: pointer to the HW structure
+ * @addr: pointer to the receive address
+ * @index: receive address array register
+ *
+ * Sets the receive address register array at index to the address passed
+ * in by addr. For LPT, RAR[0] is the base address register that is to
+ * contain the MAC address. SHRA[0-10] are the shared receive address
+ * registers that are shared between the Host and manageability engine (ME).
+ **/
+static void e1000_rar_set_pch_lpt(struct e1000_hw *hw, u8 *addr, u32 index)
+{
+ u32 rar_low, rar_high;
+ u32 wlock_mac;
+
+ /*
+ * HW expects these in little endian so we reverse the byte order
+ * from network order (big endian) to little endian
+ */
+ rar_low = ((u32)addr[0] | ((u32)addr[1] << 8) |
+ ((u32)addr[2] << 16) | ((u32)addr[3] << 24));
+
+ rar_high = ((u32)addr[4] | ((u32)addr[5] << 8));
+
+ /* If MAC address zero, no need to set the AV bit */
+ if (rar_low || rar_high)
+ rar_high |= E1000_RAH_AV;
+
+ if (index == 0) {
+ ew32(RAL(index), rar_low);
+ e1e_flush();
+ ew32(RAH(index), rar_high);
+ e1e_flush();
+ return;
+ }
+
+ /*
+ * The manageability engine (ME) can lock certain SHRAR registers that
+ * it is using - those registers are unavailable for use.
+ */
+ if (index < hw->mac.rar_entry_count) {
+ wlock_mac = er32(FWSM) & E1000_FWSM_WLOCK_MAC_MASK;
+ wlock_mac >>= E1000_FWSM_WLOCK_MAC_SHIFT;
+
+ /* Check if all SHRAR registers are locked */
+ if (wlock_mac == 1)
+ goto out;
+
+ if ((wlock_mac == 0) || (index <= wlock_mac)) {
+ s32 ret_val;
+
+ ret_val = e1000_acquire_swflag_ich8lan(hw);
+
+ if (ret_val)
+ goto out;
+
+ ew32(SHRAL_PCH_LPT(index - 1), rar_low);
+ e1e_flush();
+ ew32(SHRAH_PCH_LPT(index - 1), rar_high);
+ e1e_flush();
+
+ e1000_release_swflag_ich8lan(hw);
+
+ /* verify the register updates */
+ if ((er32(SHRAL_PCH_LPT(index - 1)) == rar_low) &&
+ (er32(SHRAH_PCH_LPT(index - 1)) == rar_high))
+ return;
+ }
+ }
+
+out:
+ e_dbg("Failed to write receive address at index %d\n", index);
+}
+
+/**
* e1000_check_reset_block_ich8lan - Check if PHY reset is blocked
* @hw: pointer to the HW structure
*
@@ -994,6 +1321,8 @@ static s32 e1000_write_smbus_addr(struct e1000_hw *hw)
{
u16 phy_data;
u32 strap = er32(STRAP);
+ u32 freq = (strap & E1000_STRAP_SMT_FREQ_MASK) >>
+ E1000_STRAP_SMT_FREQ_SHIFT;
s32 ret_val = 0;
strap &= E1000_STRAP_SMBUS_ADDRESS_MASK;
@@ -1006,6 +1335,19 @@ static s32 e1000_write_smbus_addr(struct e1000_hw *hw)
phy_data |= (strap >> E1000_STRAP_SMBUS_ADDRESS_SHIFT);
phy_data |= HV_SMB_ADDR_PEC_EN | HV_SMB_ADDR_VALID;
+ if (hw->phy.type == e1000_phy_i217) {
+ /* Restore SMBus frequency */
+ if (freq--) {
+ phy_data &= ~HV_SMB_ADDR_FREQ_MASK;
+ phy_data |= (freq & (1 << 0)) <<
+ HV_SMB_ADDR_FREQ_LOW_SHIFT;
+ phy_data |= (freq & (1 << 1)) <<
+ (HV_SMB_ADDR_FREQ_HIGH_SHIFT - 1);
+ } else {
+ e_dbg("Unsupported SMB frequency in PHY\n");
+ }
+ }
+
return e1000_write_phy_reg_hv_locked(hw, HV_SMB_ADDR, phy_data);
}
@@ -1043,6 +1385,7 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw)
/* Fall-thru */
case e1000_pchlan:
case e1000_pch2lan:
+ case e1000_pch_lpt:
sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG_ICH8M;
break;
default:
@@ -1062,10 +1405,9 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw)
* extended configuration before SW configuration
*/
data = er32(EXTCNF_CTRL);
- if (!(hw->mac.type == e1000_pch2lan)) {
- if (data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE)
- goto release;
- }
+ if ((hw->mac.type < e1000_pch2lan) &&
+ (data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE))
+ goto release;
cnf_size = er32(EXTCNF_SIZE);
cnf_size &= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK;
@@ -1076,9 +1418,9 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw)
cnf_base_addr = data & E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK;
cnf_base_addr >>= E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT;
- if ((!(data & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE) &&
- (hw->mac.type == e1000_pchlan)) ||
- (hw->mac.type == e1000_pch2lan)) {
+ if (((hw->mac.type == e1000_pchlan) &&
+ !(data & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE)) ||
+ (hw->mac.type > e1000_pchlan)) {
/*
* HW configures the SMBus address and LEDs when the
* OEM and LCD Write Enable bits are set in the NVM.
@@ -1121,8 +1463,7 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw)
reg_addr &= PHY_REG_MASK;
reg_addr |= phy_page;
- ret_val = phy->ops.write_reg_locked(hw, (u32)reg_addr,
- reg_data);
+ ret_val = e1e_wphy_locked(hw, (u32)reg_addr, reg_data);
if (ret_val)
goto release;
}
@@ -1159,8 +1500,8 @@ static s32 e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link)
/* Disable K1 when link is 1Gbps, otherwise use the NVM setting */
if (link) {
if (hw->phy.type == e1000_phy_82578) {
- ret_val = hw->phy.ops.read_reg_locked(hw, BM_CS_STATUS,
- &status_reg);
+ ret_val = e1e_rphy_locked(hw, BM_CS_STATUS,
+ &status_reg);
if (ret_val)
goto release;
@@ -1175,8 +1516,7 @@ static s32 e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link)
}
if (hw->phy.type == e1000_phy_82577) {
- ret_val = hw->phy.ops.read_reg_locked(hw, HV_M_STATUS,
- &status_reg);
+ ret_val = e1e_rphy_locked(hw, HV_M_STATUS, &status_reg);
if (ret_val)
goto release;
@@ -1191,15 +1531,13 @@ static s32 e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link)
}
/* Link stall fix for link up */
- ret_val = hw->phy.ops.write_reg_locked(hw, PHY_REG(770, 19),
- 0x0100);
+ ret_val = e1e_wphy_locked(hw, PHY_REG(770, 19), 0x0100);
if (ret_val)
goto release;
} else {
/* Link stall fix for link down */
- ret_val = hw->phy.ops.write_reg_locked(hw, PHY_REG(770, 19),
- 0x4100);
+ ret_val = e1e_wphy_locked(hw, PHY_REG(770, 19), 0x4100);
if (ret_val)
goto release;
}
@@ -1279,14 +1617,14 @@ static s32 e1000_oem_bits_config_ich8lan(struct e1000_hw *hw, bool d0_state)
u32 mac_reg;
u16 oem_reg;
- if ((hw->mac.type != e1000_pch2lan) && (hw->mac.type != e1000_pchlan))
+ if (hw->mac.type < e1000_pchlan)
return ret_val;
ret_val = hw->phy.ops.acquire(hw);
if (ret_val)
return ret_val;
- if (!(hw->mac.type == e1000_pch2lan)) {
+ if (hw->mac.type == e1000_pchlan) {
mac_reg = er32(EXTCNF_CTRL);
if (mac_reg & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE)
goto release;
@@ -1298,7 +1636,7 @@ static s32 e1000_oem_bits_config_ich8lan(struct e1000_hw *hw, bool d0_state)
mac_reg = er32(PHY_CTRL);
- ret_val = hw->phy.ops.read_reg_locked(hw, HV_OEM_BITS, &oem_reg);
+ ret_val = e1e_rphy_locked(hw, HV_OEM_BITS, &oem_reg);
if (ret_val)
goto release;
@@ -1310,10 +1648,6 @@ static s32 e1000_oem_bits_config_ich8lan(struct e1000_hw *hw, bool d0_state)
if (mac_reg & E1000_PHY_CTRL_D0A_LPLU)
oem_reg |= HV_OEM_BITS_LPLU;
-
- /* Set Restart auto-neg to activate the bits */
- if (!hw->phy.ops.check_reset_block(hw))
- oem_reg |= HV_OEM_BITS_RESTART_AN;
} else {
if (mac_reg & (E1000_PHY_CTRL_GBE_DISABLE |
E1000_PHY_CTRL_NOND0A_GBE_DISABLE))
@@ -1324,7 +1658,12 @@ static s32 e1000_oem_bits_config_ich8lan(struct e1000_hw *hw, bool d0_state)
oem_reg |= HV_OEM_BITS_LPLU;
}
- ret_val = hw->phy.ops.write_reg_locked(hw, HV_OEM_BITS, oem_reg);
+ /* Set Restart auto-neg to activate the bits */
+ if ((d0_state || (hw->mac.type != e1000_pchlan)) &&
+ !hw->phy.ops.check_reset_block(hw))
+ oem_reg |= HV_OEM_BITS_RESTART_AN;
+
+ ret_val = e1e_wphy_locked(hw, HV_OEM_BITS, oem_reg);
release:
hw->phy.ops.release(hw);
@@ -1420,11 +1759,10 @@ static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw)
ret_val = hw->phy.ops.acquire(hw);
if (ret_val)
return ret_val;
- ret_val = hw->phy.ops.read_reg_locked(hw, BM_PORT_GEN_CFG, &phy_data);
+ ret_val = e1e_rphy_locked(hw, BM_PORT_GEN_CFG, &phy_data);
if (ret_val)
goto release;
- ret_val = hw->phy.ops.write_reg_locked(hw, BM_PORT_GEN_CFG,
- phy_data & 0x00FF);
+ ret_val = e1e_wphy_locked(hw, BM_PORT_GEN_CFG, phy_data & 0x00FF);
release:
hw->phy.ops.release(hw);
@@ -1483,7 +1821,7 @@ s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable)
u32 mac_reg;
u16 i;
- if (hw->mac.type != e1000_pch2lan)
+ if (hw->mac.type < e1000_pch2lan)
return 0;
/* disable Rx path while enabling/disabling workaround */
@@ -1656,20 +1994,18 @@ static s32 e1000_lv_phy_workarounds_ich8lan(struct e1000_hw *hw)
ret_val = hw->phy.ops.acquire(hw);
if (ret_val)
return ret_val;
- ret_val = hw->phy.ops.write_reg_locked(hw, I82579_EMI_ADDR,
- I82579_MSE_THRESHOLD);
+ ret_val = e1e_wphy_locked(hw, I82579_EMI_ADDR, I82579_MSE_THRESHOLD);
if (ret_val)
goto release;
/* set MSE higher to enable link to stay up when noise is high */
- ret_val = hw->phy.ops.write_reg_locked(hw, I82579_EMI_DATA, 0x0034);
+ ret_val = e1e_wphy_locked(hw, I82579_EMI_DATA, 0x0034);
if (ret_val)
goto release;
- ret_val = hw->phy.ops.write_reg_locked(hw, I82579_EMI_ADDR,
- I82579_MSE_LINK_DOWN);
+ ret_val = e1e_wphy_locked(hw, I82579_EMI_ADDR, I82579_MSE_LINK_DOWN);
if (ret_val)
goto release;
/* drop link after 5 times MSE threshold was reached */
- ret_val = hw->phy.ops.write_reg_locked(hw, I82579_EMI_DATA, 0x0005);
+ ret_val = e1e_wphy_locked(hw, I82579_EMI_DATA, 0x0005);
release:
hw->phy.ops.release(hw);
@@ -1707,8 +2043,18 @@ static s32 e1000_k1_workaround_lv(struct e1000_hw *hw)
return ret_val;
if (status_reg & HV_M_STATUS_SPEED_1000) {
+ u16 pm_phy_reg;
+
mac_reg |= E1000_FEXTNVM4_BEACON_DURATION_8USEC;
phy_reg &= ~I82579_LPI_CTRL_FORCE_PLL_LOCK_COUNT;
+ /* LV 1G Packet drop issue wa */
+ ret_val = e1e_rphy(hw, HV_PM_CTRL, &pm_phy_reg);
+ if (ret_val)
+ return ret_val;
+ pm_phy_reg &= ~HV_PM_CTRL_PLL_STOP_IN_K1_GIGA;
+ ret_val = e1e_wphy(hw, HV_PM_CTRL, pm_phy_reg);
+ if (ret_val)
+ return ret_val;
} else {
mac_reg |= E1000_FEXTNVM4_BEACON_DURATION_16USEC;
phy_reg |= I82579_LPI_CTRL_FORCE_PLL_LOCK_COUNT;
@@ -1732,7 +2078,7 @@ static void e1000_gate_hw_phy_config_ich8lan(struct e1000_hw *hw, bool gate)
{
u32 extcnf_ctrl;
- if (hw->mac.type != e1000_pch2lan)
+ if (hw->mac.type < e1000_pch2lan)
return;
extcnf_ctrl = er32(EXTCNF_CTRL);
@@ -1834,12 +2180,10 @@ static s32 e1000_post_phy_reset_ich8lan(struct e1000_hw *hw)
ret_val = hw->phy.ops.acquire(hw);
if (ret_val)
return ret_val;
- ret_val = hw->phy.ops.write_reg_locked(hw, I82579_EMI_ADDR,
- I82579_LPI_UPDATE_TIMER);
+ ret_val = e1e_wphy_locked(hw, I82579_EMI_ADDR,
+ I82579_LPI_UPDATE_TIMER);
if (!ret_val)
- ret_val = hw->phy.ops.write_reg_locked(hw,
- I82579_EMI_DATA,
- 0x1387);
+ ret_val = e1e_wphy_locked(hw, I82579_EMI_DATA, 0x1387);
hw->phy.ops.release(hw);
}
@@ -2212,7 +2556,7 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw)
hsfsts.regval = er16flash(ICH_FLASH_HSFSTS);
/* Check if the flash descriptor is valid */
- if (hsfsts.hsf_status.fldesvalid == 0) {
+ if (!hsfsts.hsf_status.fldesvalid) {
e_dbg("Flash descriptor invalid. SW Sequencing must be used.\n");
return -E1000_ERR_NVM;
}
@@ -2232,7 +2576,7 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw)
* completed.
*/
- if (hsfsts.hsf_status.flcinprog == 0) {
+ if (!hsfsts.hsf_status.flcinprog) {
/*
* There is no cycle running at present,
* so we can start a cycle.
@@ -2250,7 +2594,7 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw)
*/
for (i = 0; i < ICH_FLASH_READ_COMMAND_TIMEOUT; i++) {
hsfsts.regval = er16flash(ICH_FLASH_HSFSTS);
- if (hsfsts.hsf_status.flcinprog == 0) {
+ if (!hsfsts.hsf_status.flcinprog) {
ret_val = 0;
break;
}
@@ -2292,12 +2636,12 @@ static s32 e1000_flash_cycle_ich8lan(struct e1000_hw *hw, u32 timeout)
/* wait till FDONE bit is set to 1 */
do {
hsfsts.regval = er16flash(ICH_FLASH_HSFSTS);
- if (hsfsts.hsf_status.flcdone == 1)
+ if (hsfsts.hsf_status.flcdone)
break;
udelay(1);
} while (i++ < timeout);
- if (hsfsts.hsf_status.flcdone == 1 && hsfsts.hsf_status.flcerr == 0)
+ if (hsfsts.hsf_status.flcdone && !hsfsts.hsf_status.flcerr)
return 0;
return -E1000_ERR_NVM;
@@ -2408,10 +2752,10 @@ static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
* ICH_FLASH_CYCLE_REPEAT_COUNT times.
*/
hsfsts.regval = er16flash(ICH_FLASH_HSFSTS);
- if (hsfsts.hsf_status.flcerr == 1) {
+ if (hsfsts.hsf_status.flcerr) {
/* Repeat for some time before giving up. */
continue;
- } else if (hsfsts.hsf_status.flcdone == 0) {
+ } else if (!hsfsts.hsf_status.flcdone) {
e_dbg("Timeout error - flash cycle did not complete.\n");
break;
}
@@ -2641,7 +2985,7 @@ static s32 e1000_validate_nvm_checksum_ich8lan(struct e1000_hw *hw)
if (ret_val)
return ret_val;
- if ((data & 0x40) == 0) {
+ if (!(data & 0x40)) {
data |= 0x40;
ret_val = e1000_write_nvm(hw, 0x19, 1, &data);
if (ret_val)
@@ -2759,10 +3103,10 @@ static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
* try...ICH_FLASH_CYCLE_REPEAT_COUNT times.
*/
hsfsts.regval = er16flash(ICH_FLASH_HSFSTS);
- if (hsfsts.hsf_status.flcerr == 1)
+ if (hsfsts.hsf_status.flcerr)
/* Repeat for some time before giving up. */
continue;
- if (hsfsts.hsf_status.flcdone == 0) {
+ if (!hsfsts.hsf_status.flcdone) {
e_dbg("Timeout error - flash cycle did not complete.\n");
break;
}
@@ -2914,10 +3258,10 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank)
* a few more times else Done
*/
hsfsts.regval = er16flash(ICH_FLASH_HSFSTS);
- if (hsfsts.hsf_status.flcerr == 1)
+ if (hsfsts.hsf_status.flcerr)
/* repeat for some time before giving up */
continue;
- else if (hsfsts.hsf_status.flcdone == 0)
+ else if (!hsfsts.hsf_status.flcdone)
return ret_val;
} while (++count < ICH_FLASH_CYCLE_REPEAT_COUNT);
}
@@ -3059,8 +3403,8 @@ static s32 e1000_get_bus_info_ich8lan(struct e1000_hw *hw)
static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
{
struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
- u16 reg;
- u32 ctrl, kab;
+ u16 kum_cfg;
+ u32 ctrl, reg;
s32 ret_val;
/*
@@ -3094,12 +3438,12 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
}
if (hw->mac.type == e1000_pchlan) {
- /* Save the NVM K1 bit setting*/
- ret_val = e1000_read_nvm(hw, E1000_NVM_K1_CONFIG, 1, &reg);
+ /* Save the NVM K1 bit setting */
+ ret_val = e1000_read_nvm(hw, E1000_NVM_K1_CONFIG, 1, &kum_cfg);
if (ret_val)
return ret_val;
- if (reg & E1000_NVM_K1_ENABLE)
+ if (kum_cfg & E1000_NVM_K1_ENABLE)
dev_spec->nvm_k1_enabled = true;
else
dev_spec->nvm_k1_enabled = false;
@@ -3129,6 +3473,14 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
/* cannot issue a flush here because it hangs the hardware */
msleep(20);
+ /* Set Phy Config Counter to 50msec */
+ if (hw->mac.type == e1000_pch2lan) {
+ reg = er32(FEXTNVM3);
+ reg &= ~E1000_FEXTNVM3_PHY_CFG_COUNTER_MASK;
+ reg |= E1000_FEXTNVM3_PHY_CFG_COUNTER_50MSEC;
+ ew32(FEXTNVM3, reg);
+ }
+
if (!ret_val)
clear_bit(__E1000_ACCESS_SHARED_RESOURCE, &hw->adapter->state);
@@ -3153,9 +3505,9 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
ew32(IMC, 0xffffffff);
er32(ICR);
- kab = er32(KABGTXD);
- kab |= E1000_KABGTXD_BGSQLBIAS;
- ew32(KABGTXD, kab);
+ reg = er32(KABGTXD);
+ reg |= E1000_KABGTXD_BGSQLBIAS;
+ ew32(KABGTXD, reg);
return 0;
}
@@ -3308,6 +3660,13 @@ static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw)
*/
reg = er32(RFCTL);
reg |= (E1000_RFCTL_NFSW_DIS | E1000_RFCTL_NFSR_DIS);
+
+ /*
+ * Disable IPv6 extension header parsing because some malformed
+ * IPv6 headers can hang the Rx.
+ */
+ if (hw->mac.type == e1000_ich8lan)
+ reg |= (E1000_RFCTL_IPV6_EX_DIS | E1000_RFCTL_NEW_IPV6_EXT_DIS);
ew32(RFCTL, reg);
}
@@ -3358,6 +3717,7 @@ static s32 e1000_setup_link_ich8lan(struct e1000_hw *hw)
ew32(FCTTV, hw->fc.pause_time);
if ((hw->phy.type == e1000_phy_82578) ||
(hw->phy.type == e1000_phy_82579) ||
+ (hw->phy.type == e1000_phy_i217) ||
(hw->phy.type == e1000_phy_82577)) {
ew32(FCRTV_PCH, hw->fc.refresh_time);
@@ -3421,6 +3781,7 @@ static s32 e1000_setup_copper_link_ich8lan(struct e1000_hw *hw)
break;
case e1000_phy_82577:
case e1000_phy_82579:
+ case e1000_phy_i217:
ret_val = e1000_copper_link_setup_82577(hw);
if (ret_val)
return ret_val;
@@ -3667,14 +4028,88 @@ void e1000e_gig_downshift_workaround_ich8lan(struct e1000_hw *hw)
* the LPLU setting in the NVM or custom setting. For PCH and newer parts,
* the OEM bits PHY register (LED, GbE disable and LPLU configurations) also
* needs to be written.
+ * Parts that support (and are linked to a partner which support) EEE in
+ * 100Mbps should disable LPLU since 100Mbps w/ EEE requires less power
+ * than 10Mbps w/o EEE.
**/
void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw)
{
+ struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
u32 phy_ctrl;
s32 ret_val;
phy_ctrl = er32(PHY_CTRL);
phy_ctrl |= E1000_PHY_CTRL_GBE_DISABLE;
+ if (hw->phy.type == e1000_phy_i217) {
+ u16 phy_reg;
+
+ ret_val = hw->phy.ops.acquire(hw);
+ if (ret_val)
+ goto out;
+
+ if (!dev_spec->eee_disable) {
+ u16 eee_advert;
+
+ ret_val = e1e_wphy_locked(hw, I82579_EMI_ADDR,
+ I217_EEE_ADVERTISEMENT);
+ if (ret_val)
+ goto release;
+ e1e_rphy_locked(hw, I82579_EMI_DATA, &eee_advert);
+
+ /*
+ * Disable LPLU if both link partners support 100BaseT
+ * EEE and 100Full is advertised on both ends of the
+ * link.
+ */
+ if ((eee_advert & I217_EEE_100_SUPPORTED) &&
+ (dev_spec->eee_lp_ability &
+ I217_EEE_100_SUPPORTED) &&
+ (hw->phy.autoneg_advertised & ADVERTISE_100_FULL))
+ phy_ctrl &= ~(E1000_PHY_CTRL_D0A_LPLU |
+ E1000_PHY_CTRL_NOND0A_LPLU);
+ }
+
+ /*
+ * For i217 Intel Rapid Start Technology support,
+ * when the system is going into Sx and no manageability engine
+ * is present, the driver must configure proxy to reset only on
+ * power good. LPI (Low Power Idle) state must also reset only
+ * on power good, as well as the MTA (Multicast table array).
+ * The SMBus release must also be disabled on LCD reset.
+ */
+ if (!(er32(FWSM) & E1000_ICH_FWSM_FW_VALID)) {
+
+ /* Enable proxy to reset only on power good. */
+ e1e_rphy_locked(hw, I217_PROXY_CTRL, &phy_reg);
+ phy_reg |= I217_PROXY_CTRL_AUTO_DISABLE;
+ e1e_wphy_locked(hw, I217_PROXY_CTRL, phy_reg);
+
+ /*
+ * Set bit enable LPI (EEE) to reset only on
+ * power good.
+ */
+ e1e_rphy_locked(hw, I217_SxCTRL, &phy_reg);
+ phy_reg |= I217_SxCTRL_MASK;
+ e1e_wphy_locked(hw, I217_SxCTRL, phy_reg);
+
+ /* Disable the SMB release on LCD reset. */
+ e1e_rphy_locked(hw, I217_MEMPWR, &phy_reg);
+ phy_reg &= ~I217_MEMPWR;
+ e1e_wphy_locked(hw, I217_MEMPWR, phy_reg);
+ }
+
+ /*
+ * Enable MTA to reset for Intel Rapid Start Technology
+ * Support
+ */
+ e1e_rphy_locked(hw, I217_CGFREG, &phy_reg);
+ phy_reg |= I217_CGFREG_MASK;
+ e1e_wphy_locked(hw, I217_CGFREG, phy_reg);
+
+release:
+ hw->phy.ops.release(hw);
+ }
+out:
ew32(PHY_CTRL, phy_ctrl);
if (hw->mac.type == e1000_ich8lan)
@@ -3682,7 +4117,11 @@ void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw)
if (hw->mac.type >= e1000_pchlan) {
e1000_oem_bits_config_ich8lan(hw, false);
- e1000_phy_hw_reset_ich8lan(hw);
+
+ /* Reset PHY to activate OEM bits on 82577/8 */
+ if (hw->mac.type == e1000_pchlan)
+ e1000e_phy_hw_reset_generic(hw);
+
ret_val = hw->phy.ops.acquire(hw);
if (ret_val)
return;
@@ -3699,44 +4138,61 @@ void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw)
* on which PHY resets are not blocked, if the PHY registers cannot be
* accessed properly by the s/w toggle the LANPHYPC value to power cycle
* the PHY.
+ * On i217, setup Intel Rapid Start Technology.
**/
void e1000_resume_workarounds_pchlan(struct e1000_hw *hw)
{
- u16 phy_id1, phy_id2;
s32 ret_val;
- if ((hw->mac.type != e1000_pch2lan) ||
- hw->phy.ops.check_reset_block(hw))
+ if (hw->mac.type < e1000_pch2lan)
return;
- ret_val = hw->phy.ops.acquire(hw);
+ ret_val = e1000_init_phy_workarounds_pchlan(hw);
if (ret_val) {
- e_dbg("Failed to acquire PHY semaphore in resume\n");
+ e_dbg("Failed to init PHY flow ret_val=%d\n", ret_val);
return;
}
- /* Test access to the PHY registers by reading the ID regs */
- ret_val = hw->phy.ops.read_reg_locked(hw, PHY_ID1, &phy_id1);
- if (ret_val)
- goto release;
- ret_val = hw->phy.ops.read_reg_locked(hw, PHY_ID2, &phy_id2);
- if (ret_val)
- goto release;
-
- if (hw->phy.id == ((u32)(phy_id1 << 16) |
- (u32)(phy_id2 & PHY_REVISION_MASK)))
- goto release;
+ /*
+ * For i217 Intel Rapid Start Technology support when the system
+ * is transitioning from Sx and no manageability engine is present
+ * configure SMBus to restore on reset, disable proxy, and enable
+ * the reset on MTA (Multicast table array).
+ */
+ if (hw->phy.type == e1000_phy_i217) {
+ u16 phy_reg;
- e1000_toggle_lanphypc_value_ich8lan(hw);
+ ret_val = hw->phy.ops.acquire(hw);
+ if (ret_val) {
+ e_dbg("Failed to setup iRST\n");
+ return;
+ }
- hw->phy.ops.release(hw);
- msleep(50);
- e1000_phy_hw_reset(hw);
- msleep(50);
- return;
+ if (!(er32(FWSM) & E1000_ICH_FWSM_FW_VALID)) {
+ /*
+ * Restore clear on SMB if no manageability engine
+ * is present
+ */
+ ret_val = e1e_rphy_locked(hw, I217_MEMPWR, &phy_reg);
+ if (ret_val)
+ goto release;
+ phy_reg |= I217_MEMPWR_MASK;
+ e1e_wphy_locked(hw, I217_MEMPWR, phy_reg);
+ /* Disable Proxy */
+ e1e_wphy_locked(hw, I217_PROXY_CTRL, 0);
+ }
+ /* Enable reset on MTA */
+ ret_val = e1e_rphy_locked(hw, I217_CGFREG, &phy_reg);
+ if (ret_val)
+ goto release;
+ phy_reg &= ~I217_CGFREG_MASK;
+ e1e_wphy_locked(hw, I217_CGFREG, phy_reg);
release:
- hw->phy.ops.release(hw);
+ if (ret_val)
+ e_dbg("Error %d in resume workarounds\n", ret_val);
+ hw->phy.ops.release(hw);
+ }
}
/**
@@ -3916,7 +4372,7 @@ static s32 e1000_get_cfg_done_ich8lan(struct e1000_hw *hw)
/* If EEPROM is not marked present, init the IGP 3 PHY manually */
if (hw->mac.type <= e1000_ich9lan) {
- if (((er32(EECD) & E1000_EECD_PRES) == 0) &&
+ if (!(er32(EECD) & E1000_EECD_PRES) &&
(hw->phy.type == e1000_phy_igp_3)) {
e1000e_phy_init_script_igp3(hw);
}
@@ -3977,6 +4433,7 @@ static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw)
/* Clear PHY statistics registers */
if ((hw->phy.type == e1000_phy_82578) ||
(hw->phy.type == e1000_phy_82579) ||
+ (hw->phy.type == e1000_phy_i217) ||
(hw->phy.type == e1000_phy_82577)) {
ret_val = hw->phy.ops.acquire(hw);
if (ret_val)
@@ -4021,6 +4478,7 @@ static const struct e1000_mac_operations ich8_mac_ops = {
.setup_physical_interface= e1000_setup_copper_link_ich8lan,
/* id_led_init dependent on mac type */
.config_collision_dist = e1000e_config_collision_dist_generic,
+ .rar_set = e1000e_rar_set_generic,
};
static const struct e1000_phy_operations ich8_phy_ops = {
@@ -4135,3 +4593,22 @@ const struct e1000_info e1000_pch2_info = {
.phy_ops = &ich8_phy_ops,
.nvm_ops = &ich8_nvm_ops,
};
+
+const struct e1000_info e1000_pch_lpt_info = {
+ .mac = e1000_pch_lpt,
+ .flags = FLAG_IS_ICH
+ | FLAG_HAS_WOL
+ | 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 = DEFAULT_JUMBO,
+ .get_variants = e1000_get_variants_ich8lan,
+ .mac_ops = &ich8_mac_ops,
+ .phy_ops = &ich8_phy_ops,
+ .nvm_ops = &ich8_nvm_ops,
+};