Commit 6607c99e authored by Yanir Lubetkin's avatar Yanir Lubetkin Committed by Jeff Kirsher

e1000e: i219 - fix to enable both ULP and EEE in Sx state

In i219, there is a hardware bug that prevented ULP entry.
A side effect of the original software fix for this was that EEE in
Sx couldn't be enabled.
This patch implements a modified flow that allows both ULP and EEE in Sx.
Signed-off-by: default avatarYanir Lubetkin <yanirx.lubetkin@intel.com>
Tested-by: default avatarAaron Brown <aaron.f.brown@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
parent beee8072
...@@ -1089,6 +1089,7 @@ s32 e1000_enable_ulp_lpt_lp(struct e1000_hw *hw, bool to_sx) ...@@ -1089,6 +1089,7 @@ s32 e1000_enable_ulp_lpt_lp(struct e1000_hw *hw, bool to_sx)
u32 mac_reg; u32 mac_reg;
s32 ret_val = 0; s32 ret_val = 0;
u16 phy_reg; u16 phy_reg;
u16 oem_reg = 0;
if ((hw->mac.type < e1000_pch_lpt) || if ((hw->mac.type < e1000_pch_lpt) ||
(hw->adapter->pdev->device == E1000_DEV_ID_PCH_LPT_I217_LM) || (hw->adapter->pdev->device == E1000_DEV_ID_PCH_LPT_I217_LM) ||
...@@ -1130,33 +1131,37 @@ s32 e1000_enable_ulp_lpt_lp(struct e1000_hw *hw, bool to_sx) ...@@ -1130,33 +1131,37 @@ s32 e1000_enable_ulp_lpt_lp(struct e1000_hw *hw, bool to_sx)
if (ret_val) if (ret_val)
goto out; goto out;
/* Force SMBus mode in PHY */
ret_val = e1000_read_phy_reg_hv_locked(hw, CV_SMB_CTRL, &phy_reg);
if (ret_val)
goto release;
phy_reg |= CV_SMB_CTRL_FORCE_SMBUS;
e1000_write_phy_reg_hv_locked(hw, CV_SMB_CTRL, phy_reg);
/* Force SMBus mode in MAC */
mac_reg = er32(CTRL_EXT);
mac_reg |= E1000_CTRL_EXT_FORCE_SMBUS;
ew32(CTRL_EXT, mac_reg);
/* Si workaround for ULP entry flow on i127/rev6 h/w. Enable /* Si workaround for ULP entry flow on i127/rev6 h/w. Enable
* LPLU and disable Gig speed when entering ULP * LPLU and disable Gig speed when entering ULP
*/ */
if ((hw->phy.type == e1000_phy_i217) && (hw->phy.revision == 6)) { if ((hw->phy.type == e1000_phy_i217) && (hw->phy.revision == 6)) {
ret_val = e1000_read_phy_reg_hv_locked(hw, HV_OEM_BITS, ret_val = e1000_read_phy_reg_hv_locked(hw, HV_OEM_BITS,
&phy_reg); &oem_reg);
if (ret_val) if (ret_val)
goto release; goto release;
phy_reg = oem_reg;
phy_reg |= HV_OEM_BITS_LPLU | HV_OEM_BITS_GBE_DIS; phy_reg |= HV_OEM_BITS_LPLU | HV_OEM_BITS_GBE_DIS;
ret_val = e1000_write_phy_reg_hv_locked(hw, HV_OEM_BITS, ret_val = e1000_write_phy_reg_hv_locked(hw, HV_OEM_BITS,
phy_reg); phy_reg);
if (ret_val) if (ret_val)
goto release; goto release;
} }
/* Force SMBus mode in PHY */
ret_val = e1000_read_phy_reg_hv_locked(hw, CV_SMB_CTRL, &phy_reg);
if (ret_val)
goto release;
phy_reg |= CV_SMB_CTRL_FORCE_SMBUS;
e1000_write_phy_reg_hv_locked(hw, CV_SMB_CTRL, phy_reg);
/* Force SMBus mode in MAC */
mac_reg = er32(CTRL_EXT);
mac_reg |= E1000_CTRL_EXT_FORCE_SMBUS;
ew32(CTRL_EXT, mac_reg);
/* Set Inband ULP Exit, Reset to SMBus mode and /* Set Inband ULP Exit, Reset to SMBus mode and
* Disable SMBus Release on PERST# in PHY * Disable SMBus Release on PERST# in PHY
*/ */
...@@ -1168,10 +1173,15 @@ s32 e1000_enable_ulp_lpt_lp(struct e1000_hw *hw, bool to_sx) ...@@ -1168,10 +1173,15 @@ s32 e1000_enable_ulp_lpt_lp(struct e1000_hw *hw, bool to_sx)
if (to_sx) { if (to_sx) {
if (er32(WUFC) & E1000_WUFC_LNKC) if (er32(WUFC) & E1000_WUFC_LNKC)
phy_reg |= I218_ULP_CONFIG1_WOL_HOST; phy_reg |= I218_ULP_CONFIG1_WOL_HOST;
else
phy_reg &= ~I218_ULP_CONFIG1_WOL_HOST;
phy_reg |= I218_ULP_CONFIG1_STICKY_ULP; phy_reg |= I218_ULP_CONFIG1_STICKY_ULP;
phy_reg &= ~I218_ULP_CONFIG1_INBAND_EXIT;
} else { } else {
phy_reg |= I218_ULP_CONFIG1_INBAND_EXIT; phy_reg |= I218_ULP_CONFIG1_INBAND_EXIT;
phy_reg &= ~I218_ULP_CONFIG1_STICKY_ULP;
phy_reg &= ~I218_ULP_CONFIG1_WOL_HOST;
} }
e1000_write_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, phy_reg); e1000_write_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, phy_reg);
...@@ -1183,6 +1193,15 @@ s32 e1000_enable_ulp_lpt_lp(struct e1000_hw *hw, bool to_sx) ...@@ -1183,6 +1193,15 @@ s32 e1000_enable_ulp_lpt_lp(struct e1000_hw *hw, bool to_sx)
/* Commit ULP changes in PHY by starting auto ULP configuration */ /* Commit ULP changes in PHY by starting auto ULP configuration */
phy_reg |= I218_ULP_CONFIG1_START; phy_reg |= I218_ULP_CONFIG1_START;
e1000_write_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, phy_reg); e1000_write_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, phy_reg);
if ((hw->phy.type == e1000_phy_i217) && (hw->phy.revision == 6) &&
to_sx && (er32(STATUS) & E1000_STATUS_LU)) {
ret_val = e1000_write_phy_reg_hv_locked(hw, HV_OEM_BITS,
oem_reg);
if (ret_val)
goto release;
}
release: release:
hw->phy.ops.release(hw); hw->phy.ops.release(hw);
out: out:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment