|
@@ -275,6 +275,19 @@ 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)
|
|
|
+{
|
|
|
+ u32 ctrl;
|
|
|
+
|
|
|
+ ctrl = er32(CTRL);
|
|
|
+ ctrl |= E1000_CTRL_LANPHYPC_OVERRIDE;
|
|
|
+ ctrl &= ~E1000_CTRL_LANPHYPC_VALUE;
|
|
|
+ ew32(CTRL, ctrl);
|
|
|
+ udelay(10);
|
|
|
+ ctrl &= ~E1000_CTRL_LANPHYPC_OVERRIDE;
|
|
|
+ ew32(CTRL, ctrl);
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* e1000_init_phy_params_pchlan - Initialize PHY function pointers
|
|
|
* @hw: pointer to the HW structure
|
|
@@ -284,7 +297,7 @@ static inline void __ew32flash(struct e1000_hw *hw, unsigned long reg, u32 val)
|
|
|
static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)
|
|
|
{
|
|
|
struct e1000_phy_info *phy = &hw->phy;
|
|
|
- u32 ctrl, fwsm;
|
|
|
+ u32 fwsm;
|
|
|
s32 ret_val = 0;
|
|
|
|
|
|
phy->addr = 1;
|
|
@@ -308,13 +321,7 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)
|
|
|
*/
|
|
|
fwsm = er32(FWSM);
|
|
|
if (!(fwsm & E1000_ICH_FWSM_FW_VALID) && !e1000_check_reset_block(hw)) {
|
|
|
- ctrl = er32(CTRL);
|
|
|
- ctrl |= E1000_CTRL_LANPHYPC_OVERRIDE;
|
|
|
- ctrl &= ~E1000_CTRL_LANPHYPC_VALUE;
|
|
|
- ew32(CTRL, ctrl);
|
|
|
- udelay(10);
|
|
|
- ctrl &= ~E1000_CTRL_LANPHYPC_OVERRIDE;
|
|
|
- ew32(CTRL, ctrl);
|
|
|
+ e1000_toggle_lanphypc_value_ich8lan(hw);
|
|
|
msleep(50);
|
|
|
|
|
|
/*
|
|
@@ -3586,17 +3593,16 @@ void e1000e_gig_downshift_workaround_ich8lan(struct e1000_hw *hw)
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * e1000e_disable_gig_wol_ich8lan - disable gig during WoL
|
|
|
+ * e1000_suspend_workarounds_ich8lan - workarounds needed during S0->Sx
|
|
|
* @hw: pointer to the HW structure
|
|
|
*
|
|
|
* During S0 to Sx transition, it is possible the link remains at gig
|
|
|
* instead of negotiating to a lower speed. Before going to Sx, set
|
|
|
* 'LPLU Enabled' and 'Gig Disable' to force link speed negotiation
|
|
|
- * to a lower speed.
|
|
|
- *
|
|
|
- * Should only be called for applicable parts.
|
|
|
+ * to a lower speed. For PCH and newer parts, the OEM bits PHY register
|
|
|
+ * (LED, GbE disable and LPLU configurations) also needs to be written.
|
|
|
**/
|
|
|
-void e1000e_disable_gig_wol_ich8lan(struct e1000_hw *hw)
|
|
|
+void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw)
|
|
|
{
|
|
|
u32 phy_ctrl;
|
|
|
s32 ret_val;
|
|
@@ -3615,6 +3621,60 @@ void e1000e_disable_gig_wol_ich8lan(struct e1000_hw *hw)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * e1000_resume_workarounds_pchlan - workarounds needed during Sx->S0
|
|
|
+ * @hw: pointer to the HW structure
|
|
|
+ *
|
|
|
+ * During Sx to S0 transitions on non-managed devices or managed devices
|
|
|
+ * 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.
|
|
|
+ **/
|
|
|
+void e1000_resume_workarounds_pchlan(struct e1000_hw *hw)
|
|
|
+{
|
|
|
+ u32 fwsm;
|
|
|
+
|
|
|
+ if (hw->mac.type != e1000_pch2lan)
|
|
|
+ return;
|
|
|
+
|
|
|
+ fwsm = er32(FWSM);
|
|
|
+ if (!(fwsm & E1000_ICH_FWSM_FW_VALID) || !e1000_check_reset_block(hw)) {
|
|
|
+ u16 phy_id1, phy_id2;
|
|
|
+ s32 ret_val;
|
|
|
+
|
|
|
+ ret_val = hw->phy.ops.acquire(hw);
|
|
|
+ if (ret_val) {
|
|
|
+ e_dbg("Failed to acquire PHY semaphore in resume\n");
|
|
|
+ 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;
|
|
|
+
|
|
|
+ e1000_toggle_lanphypc_value_ich8lan(hw);
|
|
|
+
|
|
|
+ hw->phy.ops.release(hw);
|
|
|
+ msleep(50);
|
|
|
+ e1000_phy_hw_reset(hw);
|
|
|
+ msleep(50);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+release:
|
|
|
+ hw->phy.ops.release(hw);
|
|
|
+
|
|
|
+ return;
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* e1000_cleanup_led_ich8lan - Restore the default LED operation
|
|
|
* @hw: pointer to the HW structure
|