]>
Commit | Line | Data |
---|---|---|
b3950e6a LR |
1 | /* |
2 | * Copyright (c) 2008-2010 Atheros Communications Inc. | |
3 | * | |
4 | * Permission to use, copy, modify, and/or distribute this software for any | |
5 | * purpose with or without fee is hereby granted, provided that the above | |
6 | * copyright notice and this permission notice appear in all copies. | |
7 | * | |
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
15 | */ | |
16 | ||
17 | #include "hw.h" | |
18 | #include "ar5008_initvals.h" | |
19 | #include "ar9001_initvals.h" | |
20 | #include "ar9002_initvals.h" | |
e9141f71 | 21 | #include "ar9002_phy.h" |
b3950e6a | 22 | |
e36b27af LR |
23 | int modparam_force_new_ani; |
24 | module_param_named(force_new_ani, modparam_force_new_ani, int, 0444); | |
33af8813 | 25 | MODULE_PARM_DESC(force_new_ani, "Force new ANI for AR5008, AR9001, AR9002"); |
e36b27af | 26 | |
b3950e6a LR |
27 | /* General hardware code for the A5008/AR9001/AR9002 hadware families */ |
28 | ||
b3950e6a LR |
29 | static void ar9002_hw_init_mode_regs(struct ath_hw *ah) |
30 | { | |
31 | if (AR_SREV_9271(ah)) { | |
32 | INIT_INI_ARRAY(&ah->iniModes, ar9271Modes_9271, | |
33 | ARRAY_SIZE(ar9271Modes_9271), 6); | |
34 | INIT_INI_ARRAY(&ah->iniCommon, ar9271Common_9271, | |
35 | ARRAY_SIZE(ar9271Common_9271), 2); | |
36 | INIT_INI_ARRAY(&ah->iniCommon_normal_cck_fir_coeff_9271, | |
37 | ar9271Common_normal_cck_fir_coeff_9271, | |
38 | ARRAY_SIZE(ar9271Common_normal_cck_fir_coeff_9271), 2); | |
39 | INIT_INI_ARRAY(&ah->iniCommon_japan_2484_cck_fir_coeff_9271, | |
40 | ar9271Common_japan_2484_cck_fir_coeff_9271, | |
41 | ARRAY_SIZE(ar9271Common_japan_2484_cck_fir_coeff_9271), 2); | |
42 | INIT_INI_ARRAY(&ah->iniModes_9271_1_0_only, | |
43 | ar9271Modes_9271_1_0_only, | |
44 | ARRAY_SIZE(ar9271Modes_9271_1_0_only), 6); | |
45 | INIT_INI_ARRAY(&ah->iniModes_9271_ANI_reg, ar9271Modes_9271_ANI_reg, | |
46 | ARRAY_SIZE(ar9271Modes_9271_ANI_reg), 6); | |
47 | INIT_INI_ARRAY(&ah->iniModes_high_power_tx_gain_9271, | |
48 | ar9271Modes_high_power_tx_gain_9271, | |
49 | ARRAY_SIZE(ar9271Modes_high_power_tx_gain_9271), 6); | |
50 | INIT_INI_ARRAY(&ah->iniModes_normal_power_tx_gain_9271, | |
51 | ar9271Modes_normal_power_tx_gain_9271, | |
52 | ARRAY_SIZE(ar9271Modes_normal_power_tx_gain_9271), 6); | |
53 | return; | |
54 | } | |
55 | ||
56 | if (AR_SREV_9287_11_OR_LATER(ah)) { | |
57 | INIT_INI_ARRAY(&ah->iniModes, ar9287Modes_9287_1_1, | |
58 | ARRAY_SIZE(ar9287Modes_9287_1_1), 6); | |
59 | INIT_INI_ARRAY(&ah->iniCommon, ar9287Common_9287_1_1, | |
60 | ARRAY_SIZE(ar9287Common_9287_1_1), 2); | |
61 | if (ah->config.pcie_clock_req) | |
62 | INIT_INI_ARRAY(&ah->iniPcieSerdes, | |
63 | ar9287PciePhy_clkreq_off_L1_9287_1_1, | |
64 | ARRAY_SIZE(ar9287PciePhy_clkreq_off_L1_9287_1_1), 2); | |
65 | else | |
66 | INIT_INI_ARRAY(&ah->iniPcieSerdes, | |
67 | ar9287PciePhy_clkreq_always_on_L1_9287_1_1, | |
68 | ARRAY_SIZE(ar9287PciePhy_clkreq_always_on_L1_9287_1_1), | |
69 | 2); | |
b3950e6a LR |
70 | } else if (AR_SREV_9285_12_OR_LATER(ah)) { |
71 | ||
72 | ||
73 | INIT_INI_ARRAY(&ah->iniModes, ar9285Modes_9285_1_2, | |
74 | ARRAY_SIZE(ar9285Modes_9285_1_2), 6); | |
75 | INIT_INI_ARRAY(&ah->iniCommon, ar9285Common_9285_1_2, | |
76 | ARRAY_SIZE(ar9285Common_9285_1_2), 2); | |
77 | ||
78 | if (ah->config.pcie_clock_req) { | |
79 | INIT_INI_ARRAY(&ah->iniPcieSerdes, | |
80 | ar9285PciePhy_clkreq_off_L1_9285_1_2, | |
81 | ARRAY_SIZE(ar9285PciePhy_clkreq_off_L1_9285_1_2), 2); | |
82 | } else { | |
83 | INIT_INI_ARRAY(&ah->iniPcieSerdes, | |
84 | ar9285PciePhy_clkreq_always_on_L1_9285_1_2, | |
85 | ARRAY_SIZE(ar9285PciePhy_clkreq_always_on_L1_9285_1_2), | |
86 | 2); | |
87 | } | |
b3950e6a LR |
88 | } else if (AR_SREV_9280_20_OR_LATER(ah)) { |
89 | INIT_INI_ARRAY(&ah->iniModes, ar9280Modes_9280_2, | |
90 | ARRAY_SIZE(ar9280Modes_9280_2), 6); | |
91 | INIT_INI_ARRAY(&ah->iniCommon, ar9280Common_9280_2, | |
92 | ARRAY_SIZE(ar9280Common_9280_2), 2); | |
93 | ||
94 | if (ah->config.pcie_clock_req) { | |
95 | INIT_INI_ARRAY(&ah->iniPcieSerdes, | |
96 | ar9280PciePhy_clkreq_off_L1_9280, | |
97 | ARRAY_SIZE(ar9280PciePhy_clkreq_off_L1_9280), 2); | |
98 | } else { | |
99 | INIT_INI_ARRAY(&ah->iniPcieSerdes, | |
100 | ar9280PciePhy_clkreq_always_on_L1_9280, | |
101 | ARRAY_SIZE(ar9280PciePhy_clkreq_always_on_L1_9280), 2); | |
102 | } | |
103 | INIT_INI_ARRAY(&ah->iniModesAdditional, | |
104 | ar9280Modes_fast_clock_9280_2, | |
105 | ARRAY_SIZE(ar9280Modes_fast_clock_9280_2), 3); | |
b3950e6a LR |
106 | } else if (AR_SREV_9160_10_OR_LATER(ah)) { |
107 | INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9160, | |
108 | ARRAY_SIZE(ar5416Modes_9160), 6); | |
109 | INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9160, | |
110 | ARRAY_SIZE(ar5416Common_9160), 2); | |
111 | INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0_9160, | |
112 | ARRAY_SIZE(ar5416Bank0_9160), 2); | |
113 | INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain_9160, | |
114 | ARRAY_SIZE(ar5416BB_RfGain_9160), 3); | |
115 | INIT_INI_ARRAY(&ah->iniBank1, ar5416Bank1_9160, | |
116 | ARRAY_SIZE(ar5416Bank1_9160), 2); | |
117 | INIT_INI_ARRAY(&ah->iniBank2, ar5416Bank2_9160, | |
118 | ARRAY_SIZE(ar5416Bank2_9160), 2); | |
119 | INIT_INI_ARRAY(&ah->iniBank3, ar5416Bank3_9160, | |
120 | ARRAY_SIZE(ar5416Bank3_9160), 3); | |
121 | INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6_9160, | |
122 | ARRAY_SIZE(ar5416Bank6_9160), 3); | |
123 | INIT_INI_ARRAY(&ah->iniBank6TPC, ar5416Bank6TPC_9160, | |
124 | ARRAY_SIZE(ar5416Bank6TPC_9160), 3); | |
125 | INIT_INI_ARRAY(&ah->iniBank7, ar5416Bank7_9160, | |
126 | ARRAY_SIZE(ar5416Bank7_9160), 2); | |
127 | if (AR_SREV_9160_11(ah)) { | |
128 | INIT_INI_ARRAY(&ah->iniAddac, | |
f504f5f6 FF |
129 | ar5416Addac_9160_1_1, |
130 | ARRAY_SIZE(ar5416Addac_9160_1_1), 2); | |
b3950e6a LR |
131 | } else { |
132 | INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac_9160, | |
133 | ARRAY_SIZE(ar5416Addac_9160), 2); | |
134 | } | |
135 | } else if (AR_SREV_9100_OR_LATER(ah)) { | |
136 | INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9100, | |
137 | ARRAY_SIZE(ar5416Modes_9100), 6); | |
138 | INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9100, | |
139 | ARRAY_SIZE(ar5416Common_9100), 2); | |
140 | INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0_9100, | |
141 | ARRAY_SIZE(ar5416Bank0_9100), 2); | |
142 | INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain_9100, | |
143 | ARRAY_SIZE(ar5416BB_RfGain_9100), 3); | |
144 | INIT_INI_ARRAY(&ah->iniBank1, ar5416Bank1_9100, | |
145 | ARRAY_SIZE(ar5416Bank1_9100), 2); | |
146 | INIT_INI_ARRAY(&ah->iniBank2, ar5416Bank2_9100, | |
147 | ARRAY_SIZE(ar5416Bank2_9100), 2); | |
148 | INIT_INI_ARRAY(&ah->iniBank3, ar5416Bank3_9100, | |
149 | ARRAY_SIZE(ar5416Bank3_9100), 3); | |
150 | INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6_9100, | |
151 | ARRAY_SIZE(ar5416Bank6_9100), 3); | |
152 | INIT_INI_ARRAY(&ah->iniBank6TPC, ar5416Bank6TPC_9100, | |
153 | ARRAY_SIZE(ar5416Bank6TPC_9100), 3); | |
154 | INIT_INI_ARRAY(&ah->iniBank7, ar5416Bank7_9100, | |
155 | ARRAY_SIZE(ar5416Bank7_9100), 2); | |
156 | INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac_9100, | |
157 | ARRAY_SIZE(ar5416Addac_9100), 2); | |
158 | } else { | |
159 | INIT_INI_ARRAY(&ah->iniModes, ar5416Modes, | |
160 | ARRAY_SIZE(ar5416Modes), 6); | |
161 | INIT_INI_ARRAY(&ah->iniCommon, ar5416Common, | |
162 | ARRAY_SIZE(ar5416Common), 2); | |
163 | INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0, | |
164 | ARRAY_SIZE(ar5416Bank0), 2); | |
165 | INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain, | |
166 | ARRAY_SIZE(ar5416BB_RfGain), 3); | |
167 | INIT_INI_ARRAY(&ah->iniBank1, ar5416Bank1, | |
168 | ARRAY_SIZE(ar5416Bank1), 2); | |
169 | INIT_INI_ARRAY(&ah->iniBank2, ar5416Bank2, | |
170 | ARRAY_SIZE(ar5416Bank2), 2); | |
171 | INIT_INI_ARRAY(&ah->iniBank3, ar5416Bank3, | |
172 | ARRAY_SIZE(ar5416Bank3), 3); | |
173 | INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6, | |
174 | ARRAY_SIZE(ar5416Bank6), 3); | |
175 | INIT_INI_ARRAY(&ah->iniBank6TPC, ar5416Bank6TPC, | |
176 | ARRAY_SIZE(ar5416Bank6TPC), 3); | |
177 | INIT_INI_ARRAY(&ah->iniBank7, ar5416Bank7, | |
178 | ARRAY_SIZE(ar5416Bank7), 2); | |
179 | INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac, | |
180 | ARRAY_SIZE(ar5416Addac), 2); | |
181 | } | |
182 | } | |
183 | ||
d8f492b7 LR |
184 | /* Support for Japan ch.14 (2484) spread */ |
185 | void ar9002_hw_cck_chan14_spread(struct ath_hw *ah) | |
186 | { | |
187 | if (AR_SREV_9287_11_OR_LATER(ah)) { | |
188 | INIT_INI_ARRAY(&ah->iniCckfirNormal, | |
f504f5f6 FF |
189 | ar9287Common_normal_cck_fir_coeff_9287_1_1, |
190 | ARRAY_SIZE(ar9287Common_normal_cck_fir_coeff_9287_1_1), | |
d8f492b7 LR |
191 | 2); |
192 | INIT_INI_ARRAY(&ah->iniCckfirJapan2484, | |
f504f5f6 FF |
193 | ar9287Common_japan_2484_cck_fir_coeff_9287_1_1, |
194 | ARRAY_SIZE(ar9287Common_japan_2484_cck_fir_coeff_9287_1_1), | |
d8f492b7 LR |
195 | 2); |
196 | } | |
197 | } | |
198 | ||
991312d8 LR |
199 | static void ar9280_20_hw_init_rxgain_ini(struct ath_hw *ah) |
200 | { | |
201 | u32 rxgain_type; | |
202 | ||
203 | if (ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV) >= | |
204 | AR5416_EEP_MINOR_VER_17) { | |
205 | rxgain_type = ah->eep_ops->get_eeprom(ah, EEP_RXGAIN_TYPE); | |
206 | ||
207 | if (rxgain_type == AR5416_EEP_RXGAIN_13DB_BACKOFF) | |
208 | INIT_INI_ARRAY(&ah->iniModesRxGain, | |
209 | ar9280Modes_backoff_13db_rxgain_9280_2, | |
210 | ARRAY_SIZE(ar9280Modes_backoff_13db_rxgain_9280_2), 6); | |
211 | else if (rxgain_type == AR5416_EEP_RXGAIN_23DB_BACKOFF) | |
212 | INIT_INI_ARRAY(&ah->iniModesRxGain, | |
213 | ar9280Modes_backoff_23db_rxgain_9280_2, | |
214 | ARRAY_SIZE(ar9280Modes_backoff_23db_rxgain_9280_2), 6); | |
215 | else | |
216 | INIT_INI_ARRAY(&ah->iniModesRxGain, | |
217 | ar9280Modes_original_rxgain_9280_2, | |
218 | ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 6); | |
219 | } else { | |
220 | INIT_INI_ARRAY(&ah->iniModesRxGain, | |
221 | ar9280Modes_original_rxgain_9280_2, | |
222 | ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 6); | |
223 | } | |
224 | } | |
225 | ||
226 | static void ar9280_20_hw_init_txgain_ini(struct ath_hw *ah) | |
227 | { | |
228 | u32 txgain_type; | |
229 | ||
230 | if (ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV) >= | |
231 | AR5416_EEP_MINOR_VER_19) { | |
232 | txgain_type = ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE); | |
233 | ||
234 | if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER) | |
235 | INIT_INI_ARRAY(&ah->iniModesTxGain, | |
236 | ar9280Modes_high_power_tx_gain_9280_2, | |
237 | ARRAY_SIZE(ar9280Modes_high_power_tx_gain_9280_2), 6); | |
238 | else | |
239 | INIT_INI_ARRAY(&ah->iniModesTxGain, | |
240 | ar9280Modes_original_tx_gain_9280_2, | |
241 | ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 6); | |
242 | } else { | |
243 | INIT_INI_ARRAY(&ah->iniModesTxGain, | |
244 | ar9280Modes_original_tx_gain_9280_2, | |
245 | ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 6); | |
246 | } | |
247 | } | |
248 | ||
249 | static void ar9002_hw_init_mode_gain_regs(struct ath_hw *ah) | |
250 | { | |
251 | if (AR_SREV_9287_11_OR_LATER(ah)) | |
252 | INIT_INI_ARRAY(&ah->iniModesRxGain, | |
253 | ar9287Modes_rx_gain_9287_1_1, | |
254 | ARRAY_SIZE(ar9287Modes_rx_gain_9287_1_1), 6); | |
991312d8 LR |
255 | else if (AR_SREV_9280_20(ah)) |
256 | ar9280_20_hw_init_rxgain_ini(ah); | |
257 | ||
258 | if (AR_SREV_9287_11_OR_LATER(ah)) { | |
259 | INIT_INI_ARRAY(&ah->iniModesTxGain, | |
260 | ar9287Modes_tx_gain_9287_1_1, | |
261 | ARRAY_SIZE(ar9287Modes_tx_gain_9287_1_1), 6); | |
991312d8 LR |
262 | } else if (AR_SREV_9280_20(ah)) { |
263 | ar9280_20_hw_init_txgain_ini(ah); | |
264 | } else if (AR_SREV_9285_12_OR_LATER(ah)) { | |
265 | u32 txgain_type = ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE); | |
266 | ||
267 | /* txgain table */ | |
268 | if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER) { | |
269 | if (AR_SREV_9285E_20(ah)) { | |
270 | INIT_INI_ARRAY(&ah->iniModesTxGain, | |
271 | ar9285Modes_XE2_0_high_power, | |
272 | ARRAY_SIZE( | |
273 | ar9285Modes_XE2_0_high_power), 6); | |
274 | } else { | |
275 | INIT_INI_ARRAY(&ah->iniModesTxGain, | |
276 | ar9285Modes_high_power_tx_gain_9285_1_2, | |
277 | ARRAY_SIZE( | |
278 | ar9285Modes_high_power_tx_gain_9285_1_2), 6); | |
279 | } | |
280 | } else { | |
281 | if (AR_SREV_9285E_20(ah)) { | |
282 | INIT_INI_ARRAY(&ah->iniModesTxGain, | |
283 | ar9285Modes_XE2_0_normal_power, | |
284 | ARRAY_SIZE( | |
285 | ar9285Modes_XE2_0_normal_power), 6); | |
286 | } else { | |
287 | INIT_INI_ARRAY(&ah->iniModesTxGain, | |
288 | ar9285Modes_original_tx_gain_9285_1_2, | |
289 | ARRAY_SIZE( | |
290 | ar9285Modes_original_tx_gain_9285_1_2), 6); | |
291 | } | |
292 | } | |
293 | } | |
294 | } | |
295 | ||
b3950e6a LR |
296 | /* |
297 | * Helper for ASPM support. | |
298 | * | |
299 | * Disable PLL when in L0s as well as receiver clock when in L1. | |
300 | * This power saving option must be enabled through the SerDes. | |
301 | * | |
302 | * Programming the SerDes must go through the same 288 bit serial shift | |
303 | * register as the other analog registers. Hence the 9 writes. | |
304 | */ | |
305 | static void ar9002_hw_configpcipowersave(struct ath_hw *ah, | |
306 | int restore, | |
307 | int power_off) | |
308 | { | |
309 | u8 i; | |
310 | u32 val; | |
311 | ||
312 | if (ah->is_pciexpress != true) | |
313 | return; | |
314 | ||
315 | /* Do not touch SerDes registers */ | |
316 | if (ah->config.pcie_powersave_enable == 2) | |
317 | return; | |
318 | ||
319 | /* Nothing to do on restore for 11N */ | |
320 | if (!restore) { | |
321 | if (AR_SREV_9280_20_OR_LATER(ah)) { | |
322 | /* | |
323 | * AR9280 2.0 or later chips use SerDes values from the | |
324 | * initvals.h initialized depending on chipset during | |
325 | * __ath9k_hw_init() | |
326 | */ | |
327 | for (i = 0; i < ah->iniPcieSerdes.ia_rows; i++) { | |
328 | REG_WRITE(ah, INI_RA(&ah->iniPcieSerdes, i, 0), | |
329 | INI_RA(&ah->iniPcieSerdes, i, 1)); | |
330 | } | |
b3950e6a | 331 | } else { |
d5e347bf S |
332 | ENABLE_REGWRITE_BUFFER(ah); |
333 | ||
b3950e6a LR |
334 | REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00); |
335 | REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924); | |
336 | ||
337 | /* RX shut off when elecidle is asserted */ | |
338 | REG_WRITE(ah, AR_PCIE_SERDES, 0x28000039); | |
339 | REG_WRITE(ah, AR_PCIE_SERDES, 0x53160824); | |
340 | REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980579); | |
341 | ||
342 | /* | |
343 | * Ignore ah->ah_config.pcie_clock_req setting for | |
344 | * pre-AR9280 11n | |
345 | */ | |
346 | REG_WRITE(ah, AR_PCIE_SERDES, 0x001defff); | |
347 | ||
348 | REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40); | |
349 | REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554); | |
350 | REG_WRITE(ah, AR_PCIE_SERDES, 0x000e3007); | |
351 | ||
352 | /* Load the new settings */ | |
353 | REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000); | |
d5e347bf S |
354 | |
355 | REGWRITE_BUFFER_FLUSH(ah); | |
b3950e6a LR |
356 | } |
357 | ||
358 | udelay(1000); | |
15ae733b | 359 | } |
b3950e6a | 360 | |
15ae733b S |
361 | if (power_off) { |
362 | /* clear bit 19 to disable L1 */ | |
363 | REG_CLR_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA); | |
364 | ||
365 | val = REG_READ(ah, AR_WA); | |
b3950e6a | 366 | |
15ae733b S |
367 | /* |
368 | * Set PCIe workaround bits | |
369 | * In AR9280 and AR9285, bit 14 in WA register (disable L1) | |
370 | * should only be set when device enters D3 and be | |
371 | * cleared when device comes back to D0. | |
372 | */ | |
373 | if (ah->config.pcie_waen) { | |
374 | if (ah->config.pcie_waen & AR_WA_D3_L1_DISABLE) | |
375 | val |= AR_WA_D3_L1_DISABLE; | |
376 | } else { | |
377 | if (((AR_SREV_9285(ah) || | |
378 | AR_SREV_9271(ah) || | |
379 | AR_SREV_9287(ah)) && | |
380 | (AR9285_WA_DEFAULT & AR_WA_D3_L1_DISABLE)) || | |
381 | (AR_SREV_9280(ah) && | |
382 | (AR9280_WA_DEFAULT & AR_WA_D3_L1_DISABLE))) { | |
383 | val |= AR_WA_D3_L1_DISABLE; | |
384 | } | |
385 | } | |
386 | ||
387 | if (AR_SREV_9280(ah) || AR_SREV_9285(ah) || AR_SREV_9287(ah)) { | |
388 | /* | |
389 | * Disable bit 6 and 7 before entering D3 to | |
390 | * prevent system hang. | |
391 | */ | |
392 | val &= ~(AR_WA_BIT6 | AR_WA_BIT7); | |
393 | } | |
394 | ||
f119da30 VT |
395 | if (AR_SREV_9280(ah)) |
396 | val |= AR_WA_BIT22; | |
397 | ||
15ae733b S |
398 | if (AR_SREV_9285E_20(ah)) |
399 | val |= AR_WA_BIT23; | |
400 | ||
401 | REG_WRITE(ah, AR_WA, val); | |
402 | } else { | |
b3950e6a LR |
403 | if (ah->config.pcie_waen) { |
404 | val = ah->config.pcie_waen; | |
405 | if (!power_off) | |
406 | val &= (~AR_WA_D3_L1_DISABLE); | |
407 | } else { | |
15ae733b S |
408 | if (AR_SREV_9285(ah) || |
409 | AR_SREV_9271(ah) || | |
b3950e6a LR |
410 | AR_SREV_9287(ah)) { |
411 | val = AR9285_WA_DEFAULT; | |
412 | if (!power_off) | |
413 | val &= (~AR_WA_D3_L1_DISABLE); | |
15ae733b S |
414 | } |
415 | else if (AR_SREV_9280(ah)) { | |
b3950e6a | 416 | /* |
15ae733b S |
417 | * For AR9280 chips, bit 22 of 0x4004 |
418 | * needs to be set. | |
b3950e6a LR |
419 | */ |
420 | val = AR9280_WA_DEFAULT; | |
421 | if (!power_off) | |
422 | val &= (~AR_WA_D3_L1_DISABLE); | |
15ae733b | 423 | } else { |
b3950e6a | 424 | val = AR_WA_DEFAULT; |
15ae733b S |
425 | } |
426 | } | |
427 | ||
428 | /* WAR for ASPM system hang */ | |
429 | if (AR_SREV_9280(ah) || AR_SREV_9285(ah) || AR_SREV_9287(ah)) { | |
430 | val |= (AR_WA_BIT6 | AR_WA_BIT7); | |
b3950e6a LR |
431 | } |
432 | ||
15ae733b S |
433 | if (AR_SREV_9285E_20(ah)) |
434 | val |= AR_WA_BIT23; | |
435 | ||
b3950e6a | 436 | REG_WRITE(ah, AR_WA, val); |
b3950e6a | 437 | |
15ae733b S |
438 | /* set bit 19 to allow forcing of pcie core into L1 state */ |
439 | REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA); | |
b3950e6a LR |
440 | } |
441 | } | |
442 | ||
ebd5a14a LR |
443 | static int ar9002_hw_get_radiorev(struct ath_hw *ah) |
444 | { | |
445 | u32 val; | |
446 | int i; | |
447 | ||
7d0d0df0 | 448 | ENABLE_REGWRITE_BUFFER(ah); |
ebd5a14a | 449 | |
7d0d0df0 | 450 | REG_WRITE(ah, AR_PHY(0x36), 0x00007058); |
ebd5a14a LR |
451 | for (i = 0; i < 8; i++) |
452 | REG_WRITE(ah, AR_PHY(0x20), 0x00010000); | |
7d0d0df0 S |
453 | |
454 | REGWRITE_BUFFER_FLUSH(ah); | |
7d0d0df0 | 455 | |
ebd5a14a LR |
456 | val = (REG_READ(ah, AR_PHY(256)) >> 24) & 0xff; |
457 | val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4); | |
458 | ||
459 | return ath9k_hw_reverse_bits(val, 8); | |
460 | } | |
461 | ||
462 | int ar9002_hw_rf_claim(struct ath_hw *ah) | |
463 | { | |
464 | u32 val; | |
465 | ||
466 | REG_WRITE(ah, AR_PHY(0), 0x00000007); | |
467 | ||
468 | val = ar9002_hw_get_radiorev(ah); | |
469 | switch (val & AR_RADIO_SREV_MAJOR) { | |
470 | case 0: | |
471 | val = AR_RAD5133_SREV_MAJOR; | |
472 | break; | |
473 | case AR_RAD5133_SREV_MAJOR: | |
474 | case AR_RAD5122_SREV_MAJOR: | |
475 | case AR_RAD2133_SREV_MAJOR: | |
476 | case AR_RAD2122_SREV_MAJOR: | |
477 | break; | |
478 | default: | |
3800276a JP |
479 | ath_err(ath9k_hw_common(ah), |
480 | "Radio Chip Rev 0x%02X not supported\n", | |
481 | val & AR_RADIO_SREV_MAJOR); | |
ebd5a14a LR |
482 | return -EOPNOTSUPP; |
483 | } | |
484 | ||
485 | ah->hw_version.analog5GhzRev = val; | |
486 | ||
487 | return 0; | |
488 | } | |
489 | ||
e9141f71 S |
490 | void ar9002_hw_enable_async_fifo(struct ath_hw *ah) |
491 | { | |
492 | if (AR_SREV_9287_13_OR_LATER(ah)) { | |
493 | REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3, | |
494 | AR_MAC_PCU_ASYNC_FIFO_REG3_DATAPATH_SEL); | |
495 | REG_SET_BIT(ah, AR_PHY_MODE, AR_PHY_MODE_ASYNCFIFO); | |
496 | REG_CLR_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3, | |
497 | AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET); | |
498 | REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3, | |
499 | AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET); | |
500 | } | |
501 | } | |
502 | ||
78ec2677 | 503 | /* |
78ec2677 LR |
504 | * If Async FIFO is enabled, the following counters change as MAC now runs |
505 | * at 117 Mhz instead of 88/44MHz when async FIFO is disabled. | |
506 | * | |
507 | * The values below tested for ht40 2 chain. | |
508 | * Overwrite the delay/timeouts initialized in process ini. | |
509 | */ | |
e9141f71 | 510 | void ar9002_hw_update_async_fifo(struct ath_hw *ah) |
78ec2677 | 511 | { |
e9141f71 | 512 | if (AR_SREV_9287_13_OR_LATER(ah)) { |
78ec2677 LR |
513 | REG_WRITE(ah, AR_D_GBL_IFS_SIFS, |
514 | AR_D_GBL_IFS_SIFS_ASYNC_FIFO_DUR); | |
515 | REG_WRITE(ah, AR_D_GBL_IFS_SLOT, | |
516 | AR_D_GBL_IFS_SLOT_ASYNC_FIFO_DUR); | |
517 | REG_WRITE(ah, AR_D_GBL_IFS_EIFS, | |
518 | AR_D_GBL_IFS_EIFS_ASYNC_FIFO_DUR); | |
519 | ||
520 | REG_WRITE(ah, AR_TIME_OUT, AR_TIME_OUT_ACK_CTS_ASYNC_FIFO_DUR); | |
521 | REG_WRITE(ah, AR_USEC, AR_USEC_ASYNC_FIFO_DUR); | |
522 | ||
523 | REG_SET_BIT(ah, AR_MAC_PCU_LOGIC_ANALYZER, | |
524 | AR_MAC_PCU_LOGIC_ANALYZER_DISBUG20768); | |
525 | REG_RMW_FIELD(ah, AR_AHB_MODE, AR_AHB_CUSTOM_BURST_EN, | |
526 | AR_AHB_CUSTOM_BURST_ASYNC_FIFO_VAL); | |
527 | } | |
528 | } | |
529 | ||
6c94fdc9 LR |
530 | /* |
531 | * We don't enable WEP aggregation on mac80211 but we keep this | |
532 | * around for HAL unification purposes. | |
533 | */ | |
534 | void ar9002_hw_enable_wep_aggregation(struct ath_hw *ah) | |
535 | { | |
e9141f71 | 536 | if (AR_SREV_9287_13_OR_LATER(ah)) { |
6c94fdc9 | 537 | REG_SET_BIT(ah, AR_PCU_MISC_MODE2, |
e9141f71 | 538 | AR_PCU_MISC_MODE2_ENABLE_AGGWEP); |
6c94fdc9 LR |
539 | } |
540 | } | |
541 | ||
b3950e6a LR |
542 | /* Sets up the AR5008/AR9001/AR9002 hardware familiy callbacks */ |
543 | void ar9002_hw_attach_ops(struct ath_hw *ah) | |
544 | { | |
545 | struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); | |
546 | struct ath_hw_ops *ops = ath9k_hw_ops(ah); | |
547 | ||
548 | priv_ops->init_mode_regs = ar9002_hw_init_mode_regs; | |
991312d8 | 549 | priv_ops->init_mode_gain_regs = ar9002_hw_init_mode_gain_regs; |
b3950e6a LR |
550 | |
551 | ops->config_pci_powersave = ar9002_hw_configpcipowersave; | |
552 | ||
553 | ar5008_hw_attach_phy_ops(ah); | |
7a37081e | 554 | if (AR_SREV_9280_20_OR_LATER(ah)) |
b3950e6a LR |
555 | ar9002_hw_attach_phy_ops(ah); |
556 | ||
557 | ar9002_hw_attach_calib_ops(ah); | |
558 | ar9002_hw_attach_mac_ops(ah); | |
559 | } | |
c2ba3342 RM |
560 | |
561 | void ar9002_hw_load_ani_reg(struct ath_hw *ah, struct ath9k_channel *chan) | |
562 | { | |
563 | u32 modesIndex; | |
564 | int i; | |
565 | ||
566 | switch (chan->chanmode) { | |
567 | case CHANNEL_A: | |
568 | case CHANNEL_A_HT20: | |
569 | modesIndex = 1; | |
570 | break; | |
571 | case CHANNEL_A_HT40PLUS: | |
572 | case CHANNEL_A_HT40MINUS: | |
573 | modesIndex = 2; | |
574 | break; | |
575 | case CHANNEL_G: | |
576 | case CHANNEL_G_HT20: | |
577 | case CHANNEL_B: | |
578 | modesIndex = 4; | |
579 | break; | |
580 | case CHANNEL_G_HT40PLUS: | |
581 | case CHANNEL_G_HT40MINUS: | |
582 | modesIndex = 3; | |
583 | break; | |
584 | ||
585 | default: | |
586 | return; | |
587 | } | |
588 | ||
589 | ENABLE_REGWRITE_BUFFER(ah); | |
590 | ||
591 | for (i = 0; i < ah->iniModes_9271_ANI_reg.ia_rows; i++) { | |
592 | u32 reg = INI_RA(&ah->iniModes_9271_ANI_reg, i, 0); | |
593 | u32 val = INI_RA(&ah->iniModes_9271_ANI_reg, i, modesIndex); | |
594 | u32 val_orig; | |
595 | ||
596 | if (reg == AR_PHY_CCK_DETECT) { | |
597 | val_orig = REG_READ(ah, reg); | |
598 | val &= AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK; | |
599 | val_orig &= ~AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK; | |
600 | ||
601 | REG_WRITE(ah, reg, val|val_orig); | |
602 | } else | |
603 | REG_WRITE(ah, reg, val); | |
604 | } | |
605 | ||
606 | REGWRITE_BUFFER_FLUSH(ah); | |
c2ba3342 | 607 | } |