diff options
author | Huang, Xiong <xiong@qca.qualcomm.com> | 2012-04-18 18:01:29 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-04-19 20:14:20 -0400 |
commit | ebe22ed960024385d935620910c1dd9d2c36bf23 (patch) | |
tree | b71465aaa9c58c9befaca23ef8c10c89d3086fd3 | |
parent | 024e1e4dcde98eff0fa5bf2881e4b304c147bd86 (diff) |
atl1c: refine atl1c_pcie_patch
bit PCIE_PHYMISC_FORCE_RCV_DET is only for l1c&l2c to fix WoL issue,
other chips set bit5 of REG_MASTER_CTRL --- this way could save more
power than the former, and the bit should be kept all time.
l2cb 1.x has special setting for L0S/L1
l2cb 1.x & l1d 1.x should clear Vendor Message on some platforms,
otherwise it will cause the root complex hang.
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>
-rw-r--r-- | drivers/net/ethernet/atheros/atl1c/atl1c_hw.h | 17 | ||||
-rw-r--r-- | drivers/net/ethernet/atheros/atl1c/atl1c_main.c | 49 |
2 files changed, 48 insertions, 18 deletions
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h index 5e49ea28d33b..59051e71068f 100644 --- a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h +++ b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.h | |||
@@ -96,17 +96,24 @@ int atl1c_phy_power_saving(struct atl1c_hw *hw); | |||
96 | #define PCIE_DEV_MISC_SERDES_SEL_DIN 0x10 | 96 | #define PCIE_DEV_MISC_SERDES_SEL_DIN 0x10 |
97 | 97 | ||
98 | #define REG_PCIE_PHYMISC 0x1000 | 98 | #define REG_PCIE_PHYMISC 0x1000 |
99 | #define PCIE_PHYMISC_FORCE_RCV_DET 0x4 | 99 | #define PCIE_PHYMISC_FORCE_RCV_DET BIT(2) |
100 | #define PCIE_PHYMISC_NFTS_MASK 0xFFUL | ||
101 | #define PCIE_PHYMISC_NFTS_SHIFT 16 | ||
100 | 102 | ||
101 | #define REG_PCIE_PHYMISC2 0x1004 | 103 | #define REG_PCIE_PHYMISC2 0x1004 |
102 | #define PCIE_PHYMISC2_SERDES_CDR_MASK 0x3 | 104 | #define PCIE_PHYMISC2_L0S_TH_MASK 0x3UL |
103 | #define PCIE_PHYMISC2_SERDES_CDR_SHIFT 16 | 105 | #define PCIE_PHYMISC2_L0S_TH_SHIFT 18 |
104 | #define PCIE_PHYMISC2_SERDES_TH_MASK 0x3 | 106 | #define L2CB1_PCIE_PHYMISC2_L0S_TH 3 |
105 | #define PCIE_PHYMISC2_SERDES_TH_SHIFT 18 | 107 | #define PCIE_PHYMISC2_CDR_BW_MASK 0x3UL |
108 | #define PCIE_PHYMISC2_CDR_BW_SHIFT 16 | ||
109 | #define L2CB1_PCIE_PHYMISC2_CDR_BW 3 | ||
106 | 110 | ||
107 | #define REG_TWSI_DEBUG 0x1108 | 111 | #define REG_TWSI_DEBUG 0x1108 |
108 | #define TWSI_DEBUG_DEV_EXIST 0x20000000 | 112 | #define TWSI_DEBUG_DEV_EXIST 0x20000000 |
109 | 113 | ||
114 | #define REG_DMA_DBG 0x1114 | ||
115 | #define DMA_DBG_VENDOR_MSG BIT(0) | ||
116 | |||
110 | #define REG_EEPROM_CTRL 0x12C0 | 117 | #define REG_EEPROM_CTRL 0x12C0 |
111 | #define EEPROM_CTRL_DATA_HI_MASK 0xFFFF | 118 | #define EEPROM_CTRL_DATA_HI_MASK 0xFFFF |
112 | #define EEPROM_CTRL_DATA_HI_SHIFT 0 | 119 | #define EEPROM_CTRL_DATA_HI_SHIFT 0 |
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c index 47fe6adf0f45..17b91dbf5e15 100644 --- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c +++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c | |||
@@ -87,20 +87,37 @@ static void atl1c_pcie_patch(struct atl1c_hw *hw) | |||
87 | mst_data &= ~MASTER_CTRL_CLK_SEL_DIS; | 87 | mst_data &= ~MASTER_CTRL_CLK_SEL_DIS; |
88 | AT_WRITE_REG(hw, REG_MASTER_CTRL, mst_data); | 88 | AT_WRITE_REG(hw, REG_MASTER_CTRL, mst_data); |
89 | 89 | ||
90 | AT_READ_REG(hw, REG_PCIE_PHYMISC, &data); | 90 | /* WoL/PCIE related settings */ |
91 | data |= PCIE_PHYMISC_FORCE_RCV_DET; | 91 | if (hw->nic_type == athr_l1c || hw->nic_type == athr_l2c) { |
92 | AT_WRITE_REG(hw, REG_PCIE_PHYMISC, data); | 92 | AT_READ_REG(hw, REG_PCIE_PHYMISC, &data); |
93 | 93 | data |= PCIE_PHYMISC_FORCE_RCV_DET; | |
94 | AT_WRITE_REG(hw, REG_PCIE_PHYMISC, data); | ||
95 | } else { /* new dev set bit5 of MASTER */ | ||
96 | if (!(mst_data & MASTER_CTRL_WAKEN_25M)) | ||
97 | AT_WRITE_REG(hw, REG_MASTER_CTRL, | ||
98 | mst_data | MASTER_CTRL_WAKEN_25M); | ||
99 | } | ||
100 | /* aspm/PCIE setting only for l2cb 1.0 */ | ||
94 | if (hw->nic_type == athr_l2c_b && hw->revision_id == L2CB_V10) { | 101 | if (hw->nic_type == athr_l2c_b && hw->revision_id == L2CB_V10) { |
95 | AT_READ_REG(hw, REG_PCIE_PHYMISC2, &data); | 102 | AT_READ_REG(hw, REG_PCIE_PHYMISC2, &data); |
96 | 103 | data = FIELD_SETX(data, PCIE_PHYMISC2_CDR_BW, | |
97 | data &= ~(PCIE_PHYMISC2_SERDES_CDR_MASK << | 104 | L2CB1_PCIE_PHYMISC2_CDR_BW); |
98 | PCIE_PHYMISC2_SERDES_CDR_SHIFT); | 105 | data = FIELD_SETX(data, PCIE_PHYMISC2_L0S_TH, |
99 | data |= 3 << PCIE_PHYMISC2_SERDES_CDR_SHIFT; | 106 | L2CB1_PCIE_PHYMISC2_L0S_TH); |
100 | data &= ~(PCIE_PHYMISC2_SERDES_TH_MASK << | ||
101 | PCIE_PHYMISC2_SERDES_TH_SHIFT); | ||
102 | data |= 3 << PCIE_PHYMISC2_SERDES_TH_SHIFT; | ||
103 | AT_WRITE_REG(hw, REG_PCIE_PHYMISC2, data); | 107 | AT_WRITE_REG(hw, REG_PCIE_PHYMISC2, data); |
108 | /* extend L1 sync timer */ | ||
109 | AT_READ_REG(hw, REG_LINK_CTRL, &data); | ||
110 | data |= LINK_CTRL_EXT_SYNC; | ||
111 | AT_WRITE_REG(hw, REG_LINK_CTRL, data); | ||
112 | } | ||
113 | /* l2cb 1.x & l1d 1.x */ | ||
114 | if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l1d) { | ||
115 | AT_READ_REG(hw, REG_PM_CTRL, &data); | ||
116 | data |= PM_CTRL_L0S_BUFSRX_EN; | ||
117 | AT_WRITE_REG(hw, REG_PM_CTRL, data); | ||
118 | /* clear vendor msg */ | ||
119 | AT_READ_REG(hw, REG_DMA_DBG, &data); | ||
120 | AT_WRITE_REG(hw, REG_DMA_DBG, data & ~DMA_DBG_VENDOR_MSG); | ||
104 | } | 121 | } |
105 | } | 122 | } |
106 | 123 | ||
@@ -1181,8 +1198,8 @@ static int atl1c_reset_mac(struct atl1c_hw *hw) | |||
1181 | */ | 1198 | */ |
1182 | AT_READ_REG(hw, REG_MASTER_CTRL, &master_ctrl_data); | 1199 | AT_READ_REG(hw, REG_MASTER_CTRL, &master_ctrl_data); |
1183 | master_ctrl_data |= MASTER_CTRL_OOB_DIS; | 1200 | master_ctrl_data |= MASTER_CTRL_OOB_DIS; |
1184 | AT_WRITE_REGW(hw, REG_MASTER_CTRL, ((master_ctrl_data | MASTER_CTRL_SOFT_RST) | 1201 | AT_WRITE_REG(hw, REG_MASTER_CTRL, |
1185 | & 0xFFFF)); | 1202 | master_ctrl_data | MASTER_CTRL_SOFT_RST); |
1186 | 1203 | ||
1187 | AT_WRITE_FLUSH(hw); | 1204 | AT_WRITE_FLUSH(hw); |
1188 | msleep(10); | 1205 | msleep(10); |
@@ -1194,6 +1211,8 @@ static int atl1c_reset_mac(struct atl1c_hw *hw) | |||
1194 | " disabled for 10ms second\n"); | 1211 | " disabled for 10ms second\n"); |
1195 | return -1; | 1212 | return -1; |
1196 | } | 1213 | } |
1214 | AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl_data); | ||
1215 | |||
1197 | return 0; | 1216 | return 0; |
1198 | } | 1217 | } |
1199 | 1218 | ||
@@ -1338,6 +1357,10 @@ static int atl1c_configure(struct atl1c_adapter *adapter) | |||
1338 | u32 intr_modrt_data; | 1357 | u32 intr_modrt_data; |
1339 | u32 data; | 1358 | u32 data; |
1340 | 1359 | ||
1360 | AT_READ_REG(hw, REG_MASTER_CTRL, &master_ctrl_data); | ||
1361 | master_ctrl_data &= ~(MASTER_CTRL_TX_ITIMER_EN | | ||
1362 | MASTER_CTRL_RX_ITIMER_EN | | ||
1363 | MASTER_CTRL_INT_RDCLR); | ||
1341 | /* clear interrupt status */ | 1364 | /* clear interrupt status */ |
1342 | AT_WRITE_REG(hw, REG_ISR, 0xFFFFFFFF); | 1365 | AT_WRITE_REG(hw, REG_ISR, 0xFFFFFFFF); |
1343 | /* Clear any WOL status */ | 1366 | /* Clear any WOL status */ |