Commit e98cac44 authored by Bruce Allan's avatar Bruce Allan Committed by David S. Miller

e1000e: Fix/cleanup PHY reset code for ICHx/PCHx

i) Fixes a bug where e1000_sw_lcd_config_ich8lan() was calling
e1000_lan_init_done_ich8lan() to poll the STATUS.LAN_INIT_DONE bit to
make sure the MAC had completed the PHY configuration.  However,
e1000_lan_init_done_ich8lan() had already been called in one of the two
places where PHY reset occurs for ICHx/PCHx parts, which caused the second
call to busy-wait for 150 msec because the LAN_INIT_DONE bit had already
been checked and cleared.

ii) Cleanup the two separate PHY reset code paths, i.e. the full-chip reset
in e1000_reset_hw_ich8lan() and the PHY-only reset in
e1000_phy_hw_reset_ich8lan().  There was duplicate code in both paths to be
performed post-reset that are now combined into one new function -
e1000_post_phy_reset_ich8lan().  This cleanup also included moving the
clearing of the PHY Reset Asserted bit in the STATUS register (now done for
all ICH/PCH parts) and the check for the indication from h/w that basic
configuration has completed back to where it previously was in
e1000_get_cfg_done_ich8lan().

iii) Corrected a few comments
Signed-off-by: default avatarBruce Allan <bruce.w.allan@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a305595b
...@@ -850,9 +850,6 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw) ...@@ -850,9 +850,6 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw)
if (!(data & sw_cfg_mask)) if (!(data & sw_cfg_mask))
goto out; goto out;
/* Wait for basic configuration completes before proceeding */
e1000_lan_init_done_ich8lan(hw);
/* /*
* Make sure HW does not configure LCD from PHY * Make sure HW does not configure LCD from PHY
* extended configuration before SW configuration * extended configuration before SW configuration
...@@ -1260,30 +1257,26 @@ static void e1000_lan_init_done_ich8lan(struct e1000_hw *hw) ...@@ -1260,30 +1257,26 @@ static void e1000_lan_init_done_ich8lan(struct e1000_hw *hw)
} }
/** /**
* e1000_phy_hw_reset_ich8lan - Performs a PHY reset * e1000_post_phy_reset_ich8lan - Perform steps required after a PHY reset
* @hw: pointer to the HW structure * @hw: pointer to the HW structure
*
* Resets the PHY
* This is a function pointer entry point called by drivers
* or other shared routines.
**/ **/
static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw) static s32 e1000_post_phy_reset_ich8lan(struct e1000_hw *hw)
{ {
s32 ret_val = 0; s32 ret_val = 0;
u16 reg; u16 reg;
ret_val = e1000e_phy_hw_reset_generic(hw); if (e1000_check_reset_block(hw))
if (ret_val) goto out;
return ret_val;
/* Allow time for h/w to get to a quiescent state after reset */
mdelay(10);
/* Perform any necessary post-reset workarounds */ /* Perform any necessary post-reset workarounds */
if (hw->mac.type == e1000_pchlan) { switch (hw->mac.type) {
case e1000_pchlan:
ret_val = e1000_hv_phy_workarounds_ich8lan(hw); ret_val = e1000_hv_phy_workarounds_ich8lan(hw);
if (ret_val) if (ret_val)
return ret_val; goto out;
break;
default:
break;
} }
/* Dummy read to clear the phy wakeup bit after lcd reset */ /* Dummy read to clear the phy wakeup bit after lcd reset */
...@@ -1296,11 +1289,32 @@ static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw) ...@@ -1296,11 +1289,32 @@ static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw)
goto out; goto out;
/* Configure the LCD with the OEM bits in NVM */ /* Configure the LCD with the OEM bits in NVM */
if (hw->mac.type == e1000_pchlan)
ret_val = e1000_oem_bits_config_ich8lan(hw, true); ret_val = e1000_oem_bits_config_ich8lan(hw, true);
out: out:
return 0; return ret_val;
}
/**
* e1000_phy_hw_reset_ich8lan - Performs a PHY reset
* @hw: pointer to the HW structure
*
* Resets the PHY
* This is a function pointer entry point called by drivers
* or other shared routines.
**/
static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw)
{
s32 ret_val = 0;
ret_val = e1000e_phy_hw_reset_generic(hw);
if (ret_val)
goto out;
ret_val = e1000_post_phy_reset_ich8lan(hw);
out:
return ret_val;
} }
/** /**
...@@ -2511,9 +2525,8 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) ...@@ -2511,9 +2525,8 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
* on the last TLP read/write transaction when MAC is reset. * on the last TLP read/write transaction when MAC is reset.
*/ */
ret_val = e1000e_disable_pcie_master(hw); ret_val = e1000e_disable_pcie_master(hw);
if (ret_val) { if (ret_val)
e_dbg("PCI-E Master disable polling has failed.\n"); e_dbg("PCI-E Master disable polling has failed.\n");
}
e_dbg("Masking off all interrupts\n"); e_dbg("Masking off all interrupts\n");
ew32(IMC, 0xffffffff); ew32(IMC, 0xffffffff);
...@@ -2552,14 +2565,8 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) ...@@ -2552,14 +2565,8 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
ctrl = er32(CTRL); ctrl = er32(CTRL);
if (!e1000_check_reset_block(hw)) { if (!e1000_check_reset_block(hw)) {
/* Clear PHY Reset Asserted bit */
if (hw->mac.type >= e1000_pchlan) {
u32 status = er32(STATUS);
ew32(STATUS, status & ~E1000_STATUS_PHYRA);
}
/* /*
* PHY HW reset requires MAC CORE reset at the same * Full-chip reset requires MAC and PHY reset at the same
* time to make sure the interface between MAC and the * time to make sure the interface between MAC and the
* external PHY is reset. * external PHY is reset.
*/ */
...@@ -2573,39 +2580,16 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) ...@@ -2573,39 +2580,16 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
if (!ret_val) if (!ret_val)
e1000_release_swflag_ich8lan(hw); e1000_release_swflag_ich8lan(hw);
/* Perform any necessary post-reset workarounds */ if (ctrl & E1000_CTRL_PHY_RST) {
if (hw->mac.type == e1000_pchlan)
ret_val = e1000_hv_phy_workarounds_ich8lan(hw);
if (ctrl & E1000_CTRL_PHY_RST)
ret_val = hw->phy.ops.get_cfg_done(hw); ret_val = hw->phy.ops.get_cfg_done(hw);
if (hw->mac.type >= e1000_ich10lan) {
e1000_lan_init_done_ich8lan(hw);
} else {
ret_val = e1000e_get_auto_rd_done(hw);
if (ret_val) {
/*
* When auto config read does not complete, do not
* return with an error. This can happen in situations
* where there is no eeprom and prevents getting link.
*/
e_dbg("Auto Read Done did not complete\n");
}
}
/* Dummy read to clear the phy wakeup bit after lcd reset */
if (hw->mac.type == e1000_pchlan)
e1e_rphy(hw, BM_WUC, &reg);
ret_val = e1000_sw_lcd_config_ich8lan(hw);
if (ret_val) if (ret_val)
goto out; goto out;
if (hw->mac.type == e1000_pchlan) { ret_val = e1000_post_phy_reset_ich8lan(hw);
ret_val = e1000_oem_bits_config_ich8lan(hw, true);
if (ret_val) if (ret_val)
goto out; goto out;
} }
/* /*
* For PCH, this write will make sure that any noise * For PCH, this write will make sure that any noise
* will be detected as a CRC error and be dropped rather than show up * will be detected as a CRC error and be dropped rather than show up
...@@ -3291,33 +3275,50 @@ static s32 e1000_led_off_pchlan(struct e1000_hw *hw) ...@@ -3291,33 +3275,50 @@ static s32 e1000_led_off_pchlan(struct e1000_hw *hw)
} }
/** /**
* e1000_get_cfg_done_ich8lan - Read config done bit * e1000_get_cfg_done_ich8lan - Read config done bit after Full or PHY reset
* @hw: pointer to the HW structure * @hw: pointer to the HW structure
* *
* Read the management control register for the config done bit for * Read appropriate register for the config done bit for completion status
* completion status. NOTE: silicon which is EEPROM-less will fail trying * and configure the PHY through s/w for EEPROM-less parts.
* to read the config done bit, so an error is *ONLY* logged and returns *
* 0. If we were to return with error, EEPROM-less silicon * NOTE: some silicon which is EEPROM-less will fail trying to read the
* would not be able to be reset or change link. * config done bit, so only an error is logged and continues. If we were
* to return with error, EEPROM-less silicon would not be able to be reset
* or change link.
**/ **/
static s32 e1000_get_cfg_done_ich8lan(struct e1000_hw *hw) static s32 e1000_get_cfg_done_ich8lan(struct e1000_hw *hw)
{ {
s32 ret_val = 0;
u32 bank = 0; u32 bank = 0;
u32 status;
e1000e_get_cfg_done(hw);
if (hw->mac.type >= e1000_pchlan) { /* Wait for indication from h/w that it has completed basic config */
u32 status = er32(STATUS); if (hw->mac.type >= e1000_ich10lan) {
e1000_lan_init_done_ich8lan(hw);
} else {
ret_val = e1000e_get_auto_rd_done(hw);
if (ret_val) {
/*
* When auto config read does not complete, do not
* return with an error. This can happen in situations
* where there is no eeprom and prevents getting link.
*/
e_dbg("Auto Read Done did not complete\n");
ret_val = 0;
}
}
/* Clear PHY Reset Asserted bit */
status = er32(STATUS);
if (status & E1000_STATUS_PHYRA) if (status & E1000_STATUS_PHYRA)
ew32(STATUS, status & ~E1000_STATUS_PHYRA); ew32(STATUS, status & ~E1000_STATUS_PHYRA);
else else
e_dbg("PHY Reset Asserted not set - needs delay\n"); e_dbg("PHY Reset Asserted not set - needs delay\n");
}
e1000e_get_cfg_done(hw);
/* If EEPROM is not marked present, init the IGP 3 PHY manually */ /* If EEPROM is not marked present, init the IGP 3 PHY manually */
if ((hw->mac.type != e1000_ich10lan) && if (hw->mac.type <= e1000_ich9lan) {
(hw->mac.type != e1000_pchlan)) {
if (((er32(EECD) & E1000_EECD_PRES) == 0) && if (((er32(EECD) & E1000_EECD_PRES) == 0) &&
(hw->phy.type == e1000_phy_igp_3)) { (hw->phy.type == e1000_phy_igp_3)) {
e1000e_phy_init_script_igp3(hw); e1000e_phy_init_script_igp3(hw);
...@@ -3326,11 +3327,11 @@ static s32 e1000_get_cfg_done_ich8lan(struct e1000_hw *hw) ...@@ -3326,11 +3327,11 @@ static s32 e1000_get_cfg_done_ich8lan(struct e1000_hw *hw)
if (e1000_valid_nvm_bank_detect_ich8lan(hw, &bank)) { if (e1000_valid_nvm_bank_detect_ich8lan(hw, &bank)) {
/* Maybe we should do a basic PHY config */ /* Maybe we should do a basic PHY config */
e_dbg("EEPROM not present\n"); e_dbg("EEPROM not present\n");
return -E1000_ERR_CONFIG; ret_val = -E1000_ERR_CONFIG;
} }
} }
return 0; return ret_val;
} }
/** /**
......
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