diff options
author | Huang, Xiong <xiong@qca.qualcomm.com> | 2012-04-18 22:01:28 (GMT) |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-04-20 00:14:20 (GMT) |
commit | 024e1e4dcde98eff0fa5bf2881e4b304c147bd86 (patch) | |
tree | 31ae0fcb37f8dce374e2fe3b361cd604775407bf /drivers/net/ethernet/atheros/atl1c/atl1c_main.c | |
parent | 5cbdcc2f49b4a8372052952799d2cb1de387443b (diff) | |
download | linux-fsl-qoriq-024e1e4dcde98eff0fa5bf2881e4b304c147bd86.tar.xz |
atl1c: refine/update ASPM configuration
some platforms(BIOS or OS) may change ASPM configuration in
PCI Express Link Control Register directly and dynamically
regardless the device driver installation.
Checking if ASPM support during the driver init phase by reading
PCI Express Link Contrl Register doesn't make sense.
This refine/update assume L0S/L1 is defalut enabled as hw->ctrl_flags
inited. atl1c_set_aspm will set real configuration based on chip
capability to hardware register.
atl1c_disable_l0s_l1 and register definition of REG_PM_CTRL are
refined as well.
Signed-off-by: xiong <xiong@qca.qualcomm.com>
Tested-by: Liu David <dwliu@qca.qualcomm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/atheros/atl1c/atl1c_main.c')
-rw-r--r-- | drivers/net/ethernet/atheros/atl1c/atl1c_main.c | 167 |
1 files changed, 68 insertions, 99 deletions
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c index 9783afc..47fe6ad 100644 --- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c +++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c @@ -64,7 +64,7 @@ static int atl1c_stop_mac(struct atl1c_hw *hw); static void atl1c_enable_rx_ctrl(struct atl1c_hw *hw); static void atl1c_enable_tx_ctrl(struct atl1c_hw *hw); static void atl1c_disable_l0s_l1(struct atl1c_hw *hw); -static void atl1c_set_aspm(struct atl1c_hw *hw, bool linkup); +static void atl1c_set_aspm(struct atl1c_hw *hw, u16 link_speed); static void atl1c_setup_mac_ctrl(struct atl1c_adapter *adapter); static void atl1c_clean_rx_irq(struct atl1c_adapter *adapter, int *work_done, int work_to_do); @@ -255,7 +255,7 @@ static void atl1c_check_link_status(struct atl1c_adapter *adapter) if (atl1c_stop_mac(hw) != 0) if (netif_msg_hw(adapter)) dev_warn(&pdev->dev, "stop mac failed\n"); - atl1c_set_aspm(hw, false); + atl1c_set_aspm(hw, SPEED_0); netif_carrier_off(netdev); netif_stop_queue(netdev); atl1c_phy_reset(hw); @@ -273,7 +273,7 @@ static void atl1c_check_link_status(struct atl1c_adapter *adapter) adapter->link_duplex != duplex) { adapter->link_speed = speed; adapter->link_duplex = duplex; - atl1c_set_aspm(hw, true); + atl1c_set_aspm(hw, speed); atl1c_enable_tx_ctrl(hw); atl1c_enable_rx_ctrl(hw); atl1c_setup_mac_ctrl(adapter); @@ -691,12 +691,8 @@ static int atl1c_setup_mac_funcs(struct atl1c_hw *hw) hw->ctrl_flags = ATL1C_INTR_MODRT_ENABLE | ATL1C_TXQ_MODE_ENHANCE; - if (link_ctrl_data & LINK_CTRL_L0S_EN) - hw->ctrl_flags |= ATL1C_ASPM_L0S_SUPPORT; - if (link_ctrl_data & LINK_CTRL_L1_EN) - hw->ctrl_flags |= ATL1C_ASPM_L1_SUPPORT; - if (link_ctrl_data & LINK_CTRL_EXT_SYNC) - hw->ctrl_flags |= ATL1C_LINK_EXT_SYNC; + hw->ctrl_flags |= ATL1C_ASPM_L0S_SUPPORT | + ATL1C_ASPM_L1_SUPPORT; hw->ctrl_flags |= ATL1C_ASPM_CTRL_MON; if (hw->nic_type == athr_l1c || @@ -1203,112 +1199,83 @@ static int atl1c_reset_mac(struct atl1c_hw *hw) static void atl1c_disable_l0s_l1(struct atl1c_hw *hw) { - u32 pm_ctrl_data; + u16 ctrl_flags = hw->ctrl_flags; - AT_READ_REG(hw, REG_PM_CTRL, &pm_ctrl_data); - pm_ctrl_data &= ~(PM_CTRL_L1_ENTRY_TIMER_MASK << - PM_CTRL_L1_ENTRY_TIMER_SHIFT); - pm_ctrl_data &= ~PM_CTRL_CLK_SWH_L1; - pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN; - pm_ctrl_data &= ~PM_CTRL_ASPM_L1_EN; - pm_ctrl_data &= ~PM_CTRL_MAC_ASPM_CHK; - pm_ctrl_data &= ~PM_CTRL_SERDES_PD_EX_L1; - - pm_ctrl_data |= PM_CTRL_SERDES_BUDS_RX_L1_EN; - pm_ctrl_data |= PM_CTRL_SERDES_PLL_L1_EN; - pm_ctrl_data |= PM_CTRL_SERDES_L1_EN; - AT_WRITE_REG(hw, REG_PM_CTRL, pm_ctrl_data); + hw->ctrl_flags &= ~(ATL1C_ASPM_L0S_SUPPORT | ATL1C_ASPM_L1_SUPPORT); + atl1c_set_aspm(hw, SPEED_0); + hw->ctrl_flags = ctrl_flags; } /* * Set ASPM state. * Enable/disable L0s/L1 depend on link state. */ -static void atl1c_set_aspm(struct atl1c_hw *hw, bool linkup) +static void atl1c_set_aspm(struct atl1c_hw *hw, u16 link_speed) { u32 pm_ctrl_data; - u32 link_ctrl_data; - u32 link_l1_timer = 0xF; + u32 link_l1_timer; AT_READ_REG(hw, REG_PM_CTRL, &pm_ctrl_data); - AT_READ_REG(hw, REG_LINK_CTRL, &link_ctrl_data); + pm_ctrl_data &= ~(PM_CTRL_ASPM_L1_EN | + PM_CTRL_ASPM_L0S_EN | + PM_CTRL_MAC_ASPM_CHK); + /* L1 timer */ + if (hw->nic_type == athr_l2c_b2 || hw->nic_type == athr_l1d_2) { + pm_ctrl_data &= ~PMCTRL_TXL1_AFTER_L0S; + link_l1_timer = + link_speed == SPEED_1000 || link_speed == SPEED_100 ? + L1D_PMCTRL_L1_ENTRY_TM_16US : 1; + pm_ctrl_data = FIELD_SETX(pm_ctrl_data, + L1D_PMCTRL_L1_ENTRY_TM, link_l1_timer); + } else { + link_l1_timer = hw->nic_type == athr_l2c_b ? + L2CB1_PM_CTRL_L1_ENTRY_TM : L1C_PM_CTRL_L1_ENTRY_TM; + if (link_speed != SPEED_1000 && link_speed != SPEED_100) + link_l1_timer = 1; + pm_ctrl_data = FIELD_SETX(pm_ctrl_data, + PM_CTRL_L1_ENTRY_TIMER, link_l1_timer); + } - pm_ctrl_data &= ~PM_CTRL_SERDES_PD_EX_L1; - pm_ctrl_data &= ~(PM_CTRL_L1_ENTRY_TIMER_MASK << - PM_CTRL_L1_ENTRY_TIMER_SHIFT); - pm_ctrl_data &= ~(PM_CTRL_LCKDET_TIMER_MASK << - PM_CTRL_LCKDET_TIMER_SHIFT); - pm_ctrl_data |= AT_LCKDET_TIMER << PM_CTRL_LCKDET_TIMER_SHIFT; + /* L0S/L1 enable */ + if (hw->ctrl_flags & ATL1C_ASPM_L0S_SUPPORT) + pm_ctrl_data |= PM_CTRL_ASPM_L0S_EN | PM_CTRL_MAC_ASPM_CHK; + if (hw->ctrl_flags & ATL1C_ASPM_L1_SUPPORT) + pm_ctrl_data |= PM_CTRL_ASPM_L1_EN | PM_CTRL_MAC_ASPM_CHK; + /* l2cb & l1d & l2cb2 & l1d2 */ if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l1d || - hw->nic_type == athr_l2c_b2 || hw->nic_type == athr_l1d_2) { - link_ctrl_data &= ~LINK_CTRL_EXT_SYNC; - if (!(hw->ctrl_flags & ATL1C_APS_MODE_ENABLE)) { - if (hw->nic_type == athr_l2c_b && hw->revision_id == L2CB_V10) - link_ctrl_data |= LINK_CTRL_EXT_SYNC; - } - - AT_WRITE_REG(hw, REG_LINK_CTRL, link_ctrl_data); - - pm_ctrl_data |= PM_CTRL_RCVR_WT_TIMER; - pm_ctrl_data &= ~(PM_CTRL_PM_REQ_TIMER_MASK << - PM_CTRL_PM_REQ_TIMER_SHIFT); - pm_ctrl_data |= AT_ASPM_L1_TIMER << - PM_CTRL_PM_REQ_TIMER_SHIFT; - pm_ctrl_data &= ~PM_CTRL_SA_DLY_EN; - pm_ctrl_data &= ~PM_CTRL_HOTRST; - pm_ctrl_data |= 1 << PM_CTRL_L1_ENTRY_TIMER_SHIFT; - pm_ctrl_data |= PM_CTRL_SERDES_PD_EX_L1; - } - pm_ctrl_data |= PM_CTRL_MAC_ASPM_CHK; - if (linkup) { - pm_ctrl_data &= ~PM_CTRL_ASPM_L1_EN; - pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN; - if (hw->ctrl_flags & ATL1C_ASPM_L1_SUPPORT) - pm_ctrl_data |= PM_CTRL_ASPM_L1_EN; - if (hw->ctrl_flags & ATL1C_ASPM_L0S_SUPPORT) - pm_ctrl_data |= PM_CTRL_ASPM_L0S_EN; - - if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l1d || - hw->nic_type == athr_l2c_b2 || hw->nic_type == athr_l1d_2) { - if (hw->nic_type == athr_l2c_b) - if (!(hw->ctrl_flags & ATL1C_APS_MODE_ENABLE)) - pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN; - pm_ctrl_data &= ~PM_CTRL_SERDES_L1_EN; - pm_ctrl_data &= ~PM_CTRL_SERDES_PLL_L1_EN; - pm_ctrl_data &= ~PM_CTRL_SERDES_BUDS_RX_L1_EN; - pm_ctrl_data |= PM_CTRL_CLK_SWH_L1; - if (hw->adapter->link_speed == SPEED_100 || - hw->adapter->link_speed == SPEED_1000) { - pm_ctrl_data &= ~(PM_CTRL_L1_ENTRY_TIMER_MASK << - PM_CTRL_L1_ENTRY_TIMER_SHIFT); - if (hw->nic_type == athr_l2c_b) - link_l1_timer = 7; - else if (hw->nic_type == athr_l2c_b2 || - hw->nic_type == athr_l1d_2) - link_l1_timer = 4; - pm_ctrl_data |= link_l1_timer << - PM_CTRL_L1_ENTRY_TIMER_SHIFT; - } - } else { - pm_ctrl_data |= PM_CTRL_SERDES_L1_EN; - pm_ctrl_data |= PM_CTRL_SERDES_PLL_L1_EN; - pm_ctrl_data |= PM_CTRL_SERDES_BUDS_RX_L1_EN; - pm_ctrl_data &= ~PM_CTRL_CLK_SWH_L1; + hw->nic_type == athr_l2c_b2 || hw->nic_type == athr_l1d_2) { + pm_ctrl_data = FIELD_SETX(pm_ctrl_data, + PM_CTRL_PM_REQ_TIMER, PM_CTRL_PM_REQ_TO_DEF); + pm_ctrl_data |= PM_CTRL_RCVR_WT_TIMER | + PM_CTRL_SERDES_PD_EX_L1 | + PM_CTRL_CLK_SWH_L1; + pm_ctrl_data &= ~(PM_CTRL_SERDES_L1_EN | + PM_CTRL_SERDES_PLL_L1_EN | + PM_CTRL_SERDES_BUFS_RX_L1_EN | + PM_CTRL_SA_DLY_EN | + PM_CTRL_HOTRST); + /* disable l0s if link down or l2cb */ + if (link_speed == SPEED_0 || hw->nic_type == athr_l2c_b) pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN; - pm_ctrl_data &= ~PM_CTRL_ASPM_L1_EN; - + } else { /* l1c */ + pm_ctrl_data = + FIELD_SETX(pm_ctrl_data, PM_CTRL_L1_ENTRY_TIMER, 0); + if (link_speed != SPEED_0) { + pm_ctrl_data |= PM_CTRL_SERDES_L1_EN | + PM_CTRL_SERDES_PLL_L1_EN | + PM_CTRL_SERDES_BUFS_RX_L1_EN; + pm_ctrl_data &= ~(PM_CTRL_SERDES_PD_EX_L1 | + PM_CTRL_CLK_SWH_L1 | + PM_CTRL_ASPM_L0S_EN | + PM_CTRL_ASPM_L1_EN); + } else { /* link down */ + pm_ctrl_data |= PM_CTRL_CLK_SWH_L1; + pm_ctrl_data &= ~(PM_CTRL_SERDES_L1_EN | + PM_CTRL_SERDES_PLL_L1_EN | + PM_CTRL_SERDES_BUFS_RX_L1_EN | + PM_CTRL_ASPM_L0S_EN); } - } else { - pm_ctrl_data &= ~PM_CTRL_SERDES_L1_EN; - pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN; - pm_ctrl_data &= ~PM_CTRL_SERDES_PLL_L1_EN; - pm_ctrl_data |= PM_CTRL_CLK_SWH_L1; - - if (hw->ctrl_flags & ATL1C_ASPM_L1_SUPPORT) - pm_ctrl_data |= PM_CTRL_ASPM_L1_EN; - else - pm_ctrl_data &= ~PM_CTRL_ASPM_L1_EN; } AT_WRITE_REG(hw, REG_PM_CTRL, pm_ctrl_data); @@ -2235,6 +2202,8 @@ static void atl1c_down(struct atl1c_adapter *adapter) napi_disable(&adapter->napi); atl1c_irq_disable(adapter); atl1c_free_irq(adapter); + /* disable ASPM if device inactive */ + atl1c_disable_l0s_l1(&adapter->hw); /* reset MAC to disable all RX/TX */ atl1c_reset_mac(&adapter->hw); msleep(1); |