Commit | Line | Data |
---|---|---|
b3950e6a | 1 | /* |
5b68138e | 2 | * Copyright (c) 2008-2011 Atheros Communications Inc. |
b3950e6a LR |
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 | ||
6eb07caf | 17 | #include <linux/moduleparam.h> |
b3950e6a LR |
18 | #include "hw.h" |
19 | #include "ar5008_initvals.h" | |
20 | #include "ar9001_initvals.h" | |
21 | #include "ar9002_initvals.h" | |
e9141f71 | 22 | #include "ar9002_phy.h" |
b3950e6a LR |
23 | |
24 | /* General hardware code for the A5008/AR9001/AR9002 hadware families */ | |
25 | ||
6aaacd86 | 26 | static int ar9002_hw_init_mode_regs(struct ath_hw *ah) |
b3950e6a LR |
27 | { |
28 | if (AR_SREV_9271(ah)) { | |
a364517b FF |
29 | INIT_INI_ARRAY(&ah->iniModes, ar9271Modes_9271); |
30 | INIT_INI_ARRAY(&ah->iniCommon, ar9271Common_9271); | |
31 | INIT_INI_ARRAY(&ah->iniModes_9271_ANI_reg, ar9271Modes_9271_ANI_reg); | |
6aaacd86 | 32 | return 0; |
b3950e6a LR |
33 | } |
34 | ||
787e0536 FF |
35 | INIT_INI_ARRAY(&ah->iniPcieSerdes, |
36 | ar9280PciePhy_clkreq_always_on_L1_9280); | |
14fec8d9 | 37 | |
b3950e6a | 38 | if (AR_SREV_9287_11_OR_LATER(ah)) { |
a364517b FF |
39 | INIT_INI_ARRAY(&ah->iniModes, ar9287Modes_9287_1_1); |
40 | INIT_INI_ARRAY(&ah->iniCommon, ar9287Common_9287_1_1); | |
b3950e6a | 41 | } else if (AR_SREV_9285_12_OR_LATER(ah)) { |
a364517b FF |
42 | INIT_INI_ARRAY(&ah->iniModes, ar9285Modes_9285_1_2); |
43 | INIT_INI_ARRAY(&ah->iniCommon, ar9285Common_9285_1_2); | |
b3950e6a | 44 | } else if (AR_SREV_9280_20_OR_LATER(ah)) { |
a364517b FF |
45 | INIT_INI_ARRAY(&ah->iniModes, ar9280Modes_9280_2); |
46 | INIT_INI_ARRAY(&ah->iniCommon, ar9280Common_9280_2); | |
b3950e6a | 47 | |
c7d36f9f | 48 | INIT_INI_ARRAY(&ah->iniModesFastClock, |
a364517b | 49 | ar9280Modes_fast_clock_9280_2); |
b3950e6a | 50 | } else if (AR_SREV_9160_10_OR_LATER(ah)) { |
a364517b FF |
51 | INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9160); |
52 | INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9160); | |
b3950e6a LR |
53 | if (AR_SREV_9160_11(ah)) { |
54 | INIT_INI_ARRAY(&ah->iniAddac, | |
a364517b | 55 | ar5416Addac_9160_1_1); |
b3950e6a | 56 | } else { |
a364517b | 57 | INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac_9160); |
b3950e6a LR |
58 | } |
59 | } else if (AR_SREV_9100_OR_LATER(ah)) { | |
a364517b FF |
60 | INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9100); |
61 | INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9100); | |
a364517b | 62 | INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac_9100); |
b3950e6a | 63 | } else { |
a364517b FF |
64 | INIT_INI_ARRAY(&ah->iniModes, ar5416Modes); |
65 | INIT_INI_ARRAY(&ah->iniCommon, ar5416Common); | |
a364517b | 66 | INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac); |
14fec8d9 FF |
67 | } |
68 | ||
69 | if (!AR_SREV_9280_20_OR_LATER(ah)) { | |
70 | /* Common for AR5416, AR913x, AR9160 */ | |
a364517b | 71 | INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain); |
14fec8d9 | 72 | |
14fec8d9 FF |
73 | /* Common for AR913x, AR9160 */ |
74 | if (!AR_SREV_5416(ah)) | |
37c62fec FF |
75 | INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6TPC_9100); |
76 | else | |
77 | INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6TPC); | |
b3950e6a | 78 | } |
9bbb8168 FF |
79 | |
80 | /* iniAddac needs to be modified for these chips */ | |
81 | if (AR_SREV_9160(ah) || !AR_SREV_5416_22_OR_LATER(ah)) { | |
82 | struct ar5416IniArray *addac = &ah->iniAddac; | |
83 | u32 size = sizeof(u32) * addac->ia_rows * addac->ia_columns; | |
84 | u32 *data; | |
85 | ||
c1b976d2 | 86 | data = devm_kzalloc(ah->dev, size, GFP_KERNEL); |
9bbb8168 | 87 | if (!data) |
6aaacd86 | 88 | return -ENOMEM; |
9bbb8168 FF |
89 | |
90 | memcpy(data, addac->ia_array, size); | |
91 | addac->ia_array = data; | |
92 | ||
93 | if (!AR_SREV_5416_22_OR_LATER(ah)) { | |
94 | /* override CLKDRV value */ | |
95 | INI_RA(addac, 31,1) = 0; | |
96 | } | |
97 | } | |
d8f492b7 LR |
98 | if (AR_SREV_9287_11_OR_LATER(ah)) { |
99 | INIT_INI_ARRAY(&ah->iniCckfirNormal, | |
a364517b | 100 | ar9287Common_normal_cck_fir_coeff_9287_1_1); |
d8f492b7 | 101 | INIT_INI_ARRAY(&ah->iniCckfirJapan2484, |
a364517b | 102 | ar9287Common_japan_2484_cck_fir_coeff_9287_1_1); |
d8f492b7 | 103 | } |
6aaacd86 | 104 | return 0; |
d8f492b7 LR |
105 | } |
106 | ||
991312d8 LR |
107 | static void ar9280_20_hw_init_rxgain_ini(struct ath_hw *ah) |
108 | { | |
109 | u32 rxgain_type; | |
110 | ||
111 | if (ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV) >= | |
112 | AR5416_EEP_MINOR_VER_17) { | |
113 | rxgain_type = ah->eep_ops->get_eeprom(ah, EEP_RXGAIN_TYPE); | |
114 | ||
115 | if (rxgain_type == AR5416_EEP_RXGAIN_13DB_BACKOFF) | |
116 | INIT_INI_ARRAY(&ah->iniModesRxGain, | |
a364517b | 117 | ar9280Modes_backoff_13db_rxgain_9280_2); |
991312d8 LR |
118 | else if (rxgain_type == AR5416_EEP_RXGAIN_23DB_BACKOFF) |
119 | INIT_INI_ARRAY(&ah->iniModesRxGain, | |
a364517b | 120 | ar9280Modes_backoff_23db_rxgain_9280_2); |
991312d8 LR |
121 | else |
122 | INIT_INI_ARRAY(&ah->iniModesRxGain, | |
a364517b | 123 | ar9280Modes_original_rxgain_9280_2); |
991312d8 LR |
124 | } else { |
125 | INIT_INI_ARRAY(&ah->iniModesRxGain, | |
a364517b | 126 | ar9280Modes_original_rxgain_9280_2); |
991312d8 LR |
127 | } |
128 | } | |
129 | ||
aa0e5786 | 130 | static void ar9280_20_hw_init_txgain_ini(struct ath_hw *ah, u32 txgain_type) |
991312d8 | 131 | { |
991312d8 LR |
132 | if (ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV) >= |
133 | AR5416_EEP_MINOR_VER_19) { | |
991312d8 LR |
134 | if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER) |
135 | INIT_INI_ARRAY(&ah->iniModesTxGain, | |
a364517b | 136 | ar9280Modes_high_power_tx_gain_9280_2); |
991312d8 LR |
137 | else |
138 | INIT_INI_ARRAY(&ah->iniModesTxGain, | |
a364517b | 139 | ar9280Modes_original_tx_gain_9280_2); |
991312d8 LR |
140 | } else { |
141 | INIT_INI_ARRAY(&ah->iniModesTxGain, | |
a364517b | 142 | ar9280Modes_original_tx_gain_9280_2); |
991312d8 LR |
143 | } |
144 | } | |
145 | ||
aa0e5786 FF |
146 | static void ar9271_hw_init_txgain_ini(struct ath_hw *ah, u32 txgain_type) |
147 | { | |
148 | if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER) | |
149 | INIT_INI_ARRAY(&ah->iniModesTxGain, | |
a364517b | 150 | ar9271Modes_high_power_tx_gain_9271); |
aa0e5786 FF |
151 | else |
152 | INIT_INI_ARRAY(&ah->iniModesTxGain, | |
a364517b | 153 | ar9271Modes_normal_power_tx_gain_9271); |
aa0e5786 FF |
154 | } |
155 | ||
991312d8 LR |
156 | static void ar9002_hw_init_mode_gain_regs(struct ath_hw *ah) |
157 | { | |
aa0e5786 FF |
158 | u32 txgain_type = ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE); |
159 | ||
991312d8 LR |
160 | if (AR_SREV_9287_11_OR_LATER(ah)) |
161 | INIT_INI_ARRAY(&ah->iniModesRxGain, | |
a364517b | 162 | ar9287Modes_rx_gain_9287_1_1); |
991312d8 LR |
163 | else if (AR_SREV_9280_20(ah)) |
164 | ar9280_20_hw_init_rxgain_ini(ah); | |
165 | ||
aa0e5786 FF |
166 | if (AR_SREV_9271(ah)) { |
167 | ar9271_hw_init_txgain_ini(ah, txgain_type); | |
168 | } else if (AR_SREV_9287_11_OR_LATER(ah)) { | |
991312d8 | 169 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
a364517b | 170 | ar9287Modes_tx_gain_9287_1_1); |
991312d8 | 171 | } else if (AR_SREV_9280_20(ah)) { |
aa0e5786 | 172 | ar9280_20_hw_init_txgain_ini(ah, txgain_type); |
991312d8 | 173 | } else if (AR_SREV_9285_12_OR_LATER(ah)) { |
991312d8 LR |
174 | /* txgain table */ |
175 | if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER) { | |
176 | if (AR_SREV_9285E_20(ah)) { | |
177 | INIT_INI_ARRAY(&ah->iniModesTxGain, | |
a364517b | 178 | ar9285Modes_XE2_0_high_power); |
991312d8 LR |
179 | } else { |
180 | INIT_INI_ARRAY(&ah->iniModesTxGain, | |
a364517b | 181 | ar9285Modes_high_power_tx_gain_9285_1_2); |
991312d8 LR |
182 | } |
183 | } else { | |
184 | if (AR_SREV_9285E_20(ah)) { | |
185 | INIT_INI_ARRAY(&ah->iniModesTxGain, | |
a364517b | 186 | ar9285Modes_XE2_0_normal_power); |
991312d8 LR |
187 | } else { |
188 | INIT_INI_ARRAY(&ah->iniModesTxGain, | |
a364517b | 189 | ar9285Modes_original_tx_gain_9285_1_2); |
991312d8 LR |
190 | } |
191 | } | |
192 | } | |
193 | } | |
194 | ||
b3950e6a LR |
195 | /* |
196 | * Helper for ASPM support. | |
197 | * | |
198 | * Disable PLL when in L0s as well as receiver clock when in L1. | |
199 | * This power saving option must be enabled through the SerDes. | |
200 | * | |
201 | * Programming the SerDes must go through the same 288 bit serial shift | |
202 | * register as the other analog registers. Hence the 9 writes. | |
203 | */ | |
204 | static void ar9002_hw_configpcipowersave(struct ath_hw *ah, | |
84c87dc8 | 205 | bool power_off) |
b3950e6a LR |
206 | { |
207 | u8 i; | |
208 | u32 val; | |
209 | ||
b3950e6a | 210 | /* Nothing to do on restore for 11N */ |
84c87dc8 | 211 | if (!power_off /* !restore */) { |
b3950e6a LR |
212 | if (AR_SREV_9280_20_OR_LATER(ah)) { |
213 | /* | |
214 | * AR9280 2.0 or later chips use SerDes values from the | |
215 | * initvals.h initialized depending on chipset during | |
216 | * __ath9k_hw_init() | |
217 | */ | |
218 | for (i = 0; i < ah->iniPcieSerdes.ia_rows; i++) { | |
219 | REG_WRITE(ah, INI_RA(&ah->iniPcieSerdes, i, 0), | |
220 | INI_RA(&ah->iniPcieSerdes, i, 1)); | |
221 | } | |
b3950e6a | 222 | } else { |
d5e347bf S |
223 | ENABLE_REGWRITE_BUFFER(ah); |
224 | ||
b3950e6a LR |
225 | REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00); |
226 | REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924); | |
227 | ||
228 | /* RX shut off when elecidle is asserted */ | |
229 | REG_WRITE(ah, AR_PCIE_SERDES, 0x28000039); | |
230 | REG_WRITE(ah, AR_PCIE_SERDES, 0x53160824); | |
231 | REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980579); | |
232 | ||
233 | /* | |
234 | * Ignore ah->ah_config.pcie_clock_req setting for | |
235 | * pre-AR9280 11n | |
236 | */ | |
237 | REG_WRITE(ah, AR_PCIE_SERDES, 0x001defff); | |
238 | ||
239 | REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40); | |
240 | REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554); | |
241 | REG_WRITE(ah, AR_PCIE_SERDES, 0x000e3007); | |
242 | ||
243 | /* Load the new settings */ | |
244 | REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000); | |
d5e347bf S |
245 | |
246 | REGWRITE_BUFFER_FLUSH(ah); | |
b3950e6a LR |
247 | } |
248 | ||
249 | udelay(1000); | |
15ae733b | 250 | } |
b3950e6a | 251 | |
15ae733b S |
252 | if (power_off) { |
253 | /* clear bit 19 to disable L1 */ | |
254 | REG_CLR_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA); | |
255 | ||
256 | val = REG_READ(ah, AR_WA); | |
b3950e6a | 257 | |
15ae733b S |
258 | /* |
259 | * Set PCIe workaround bits | |
260 | * In AR9280 and AR9285, bit 14 in WA register (disable L1) | |
261 | * should only be set when device enters D3 and be | |
262 | * cleared when device comes back to D0. | |
263 | */ | |
264 | if (ah->config.pcie_waen) { | |
265 | if (ah->config.pcie_waen & AR_WA_D3_L1_DISABLE) | |
266 | val |= AR_WA_D3_L1_DISABLE; | |
267 | } else { | |
d1ae25a0 SM |
268 | if (AR_SREV_9285(ah) || AR_SREV_9271(ah) || AR_SREV_9287(ah)) { |
269 | if (AR9285_WA_DEFAULT & AR_WA_D3_L1_DISABLE) | |
270 | val |= AR_WA_D3_L1_DISABLE; | |
271 | } else if (AR_SREV_9280(ah)) { | |
272 | if (AR9280_WA_DEFAULT & AR_WA_D3_L1_DISABLE) | |
273 | val |= AR_WA_D3_L1_DISABLE; | |
15ae733b S |
274 | } |
275 | } | |
276 | ||
277 | if (AR_SREV_9280(ah) || AR_SREV_9285(ah) || AR_SREV_9287(ah)) { | |
278 | /* | |
279 | * Disable bit 6 and 7 before entering D3 to | |
280 | * prevent system hang. | |
281 | */ | |
282 | val &= ~(AR_WA_BIT6 | AR_WA_BIT7); | |
283 | } | |
284 | ||
f119da30 VT |
285 | if (AR_SREV_9280(ah)) |
286 | val |= AR_WA_BIT22; | |
287 | ||
15ae733b S |
288 | if (AR_SREV_9285E_20(ah)) |
289 | val |= AR_WA_BIT23; | |
290 | ||
291 | REG_WRITE(ah, AR_WA, val); | |
292 | } else { | |
b3950e6a LR |
293 | if (ah->config.pcie_waen) { |
294 | val = ah->config.pcie_waen; | |
d1ae25a0 | 295 | val &= (~AR_WA_D3_L1_DISABLE); |
b3950e6a | 296 | } else { |
d1ae25a0 | 297 | if (AR_SREV_9285(ah) || AR_SREV_9271(ah) || AR_SREV_9287(ah)) { |
b3950e6a | 298 | val = AR9285_WA_DEFAULT; |
d1ae25a0 SM |
299 | val &= (~AR_WA_D3_L1_DISABLE); |
300 | } else if (AR_SREV_9280(ah)) { | |
b3950e6a | 301 | /* |
15ae733b S |
302 | * For AR9280 chips, bit 22 of 0x4004 |
303 | * needs to be set. | |
b3950e6a LR |
304 | */ |
305 | val = AR9280_WA_DEFAULT; | |
d1ae25a0 | 306 | val &= (~AR_WA_D3_L1_DISABLE); |
15ae733b | 307 | } else { |
b3950e6a | 308 | val = AR_WA_DEFAULT; |
15ae733b S |
309 | } |
310 | } | |
311 | ||
312 | /* WAR for ASPM system hang */ | |
5b64aa72 | 313 | if (AR_SREV_9285(ah) || AR_SREV_9287(ah)) |
15ae733b | 314 | val |= (AR_WA_BIT6 | AR_WA_BIT7); |
b3950e6a | 315 | |
15ae733b S |
316 | if (AR_SREV_9285E_20(ah)) |
317 | val |= AR_WA_BIT23; | |
318 | ||
b3950e6a | 319 | REG_WRITE(ah, AR_WA, val); |
b3950e6a | 320 | |
15ae733b S |
321 | /* set bit 19 to allow forcing of pcie core into L1 state */ |
322 | REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA); | |
b3950e6a LR |
323 | } |
324 | } | |
325 | ||
ebd5a14a LR |
326 | static int ar9002_hw_get_radiorev(struct ath_hw *ah) |
327 | { | |
328 | u32 val; | |
329 | int i; | |
330 | ||
7d0d0df0 | 331 | ENABLE_REGWRITE_BUFFER(ah); |
ebd5a14a | 332 | |
7d0d0df0 | 333 | REG_WRITE(ah, AR_PHY(0x36), 0x00007058); |
ebd5a14a LR |
334 | for (i = 0; i < 8; i++) |
335 | REG_WRITE(ah, AR_PHY(0x20), 0x00010000); | |
7d0d0df0 S |
336 | |
337 | REGWRITE_BUFFER_FLUSH(ah); | |
7d0d0df0 | 338 | |
ebd5a14a LR |
339 | val = (REG_READ(ah, AR_PHY(256)) >> 24) & 0xff; |
340 | val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4); | |
341 | ||
342 | return ath9k_hw_reverse_bits(val, 8); | |
343 | } | |
344 | ||
345 | int ar9002_hw_rf_claim(struct ath_hw *ah) | |
346 | { | |
347 | u32 val; | |
348 | ||
349 | REG_WRITE(ah, AR_PHY(0), 0x00000007); | |
350 | ||
351 | val = ar9002_hw_get_radiorev(ah); | |
352 | switch (val & AR_RADIO_SREV_MAJOR) { | |
353 | case 0: | |
354 | val = AR_RAD5133_SREV_MAJOR; | |
355 | break; | |
356 | case AR_RAD5133_SREV_MAJOR: | |
357 | case AR_RAD5122_SREV_MAJOR: | |
358 | case AR_RAD2133_SREV_MAJOR: | |
359 | case AR_RAD2122_SREV_MAJOR: | |
360 | break; | |
361 | default: | |
3800276a JP |
362 | ath_err(ath9k_hw_common(ah), |
363 | "Radio Chip Rev 0x%02X not supported\n", | |
364 | val & AR_RADIO_SREV_MAJOR); | |
ebd5a14a LR |
365 | return -EOPNOTSUPP; |
366 | } | |
367 | ||
368 | ah->hw_version.analog5GhzRev = val; | |
369 | ||
370 | return 0; | |
371 | } | |
372 | ||
e9141f71 S |
373 | void ar9002_hw_enable_async_fifo(struct ath_hw *ah) |
374 | { | |
375 | if (AR_SREV_9287_13_OR_LATER(ah)) { | |
376 | REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3, | |
377 | AR_MAC_PCU_ASYNC_FIFO_REG3_DATAPATH_SEL); | |
378 | REG_SET_BIT(ah, AR_PHY_MODE, AR_PHY_MODE_ASYNCFIFO); | |
379 | REG_CLR_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3, | |
380 | AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET); | |
381 | REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3, | |
382 | AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET); | |
383 | } | |
384 | } | |
385 | ||
4598702d SM |
386 | static void ar9002_hw_init_hang_checks(struct ath_hw *ah) |
387 | { | |
388 | if (AR_SREV_9100(ah) || AR_SREV_9160(ah)) { | |
389 | ah->config.hw_hang_checks |= HW_BB_RIFS_HANG; | |
390 | ah->config.hw_hang_checks |= HW_BB_DFS_HANG; | |
391 | } | |
392 | ||
393 | if (AR_SREV_9280(ah)) | |
394 | ah->config.hw_hang_checks |= HW_BB_RX_CLEAR_STUCK_HANG; | |
395 | ||
396 | if (AR_SREV_5416(ah) || AR_SREV_9100(ah) || AR_SREV_9160(ah)) | |
397 | ah->config.hw_hang_checks |= HW_MAC_HANG; | |
398 | } | |
399 | ||
b3950e6a | 400 | /* Sets up the AR5008/AR9001/AR9002 hardware familiy callbacks */ |
c1b976d2 | 401 | int ar9002_hw_attach_ops(struct ath_hw *ah) |
b3950e6a LR |
402 | { |
403 | struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); | |
404 | struct ath_hw_ops *ops = ath9k_hw_ops(ah); | |
c1b976d2 | 405 | int ret; |
b3950e6a | 406 | |
6aaacd86 FF |
407 | ret = ar9002_hw_init_mode_regs(ah); |
408 | if (ret) | |
409 | return ret; | |
410 | ||
991312d8 | 411 | priv_ops->init_mode_gain_regs = ar9002_hw_init_mode_gain_regs; |
4598702d | 412 | priv_ops->init_hang_checks = ar9002_hw_init_hang_checks; |
b3950e6a LR |
413 | |
414 | ops->config_pci_powersave = ar9002_hw_configpcipowersave; | |
415 | ||
c1b976d2 FF |
416 | ret = ar5008_hw_attach_phy_ops(ah); |
417 | if (ret) | |
418 | return ret; | |
419 | ||
7a37081e | 420 | if (AR_SREV_9280_20_OR_LATER(ah)) |
b3950e6a LR |
421 | ar9002_hw_attach_phy_ops(ah); |
422 | ||
423 | ar9002_hw_attach_calib_ops(ah); | |
424 | ar9002_hw_attach_mac_ops(ah); | |
c1b976d2 | 425 | return 0; |
b3950e6a | 426 | } |
c2ba3342 RM |
427 | |
428 | void ar9002_hw_load_ani_reg(struct ath_hw *ah, struct ath9k_channel *chan) | |
429 | { | |
430 | u32 modesIndex; | |
431 | int i; | |
432 | ||
8896934c FF |
433 | if (IS_CHAN_5GHZ(chan)) |
434 | modesIndex = IS_CHAN_HT40(chan) ? 2 : 1; | |
435 | else | |
436 | modesIndex = IS_CHAN_HT40(chan) ? 3 : 4; | |
c2ba3342 RM |
437 | |
438 | ENABLE_REGWRITE_BUFFER(ah); | |
439 | ||
440 | for (i = 0; i < ah->iniModes_9271_ANI_reg.ia_rows; i++) { | |
441 | u32 reg = INI_RA(&ah->iniModes_9271_ANI_reg, i, 0); | |
442 | u32 val = INI_RA(&ah->iniModes_9271_ANI_reg, i, modesIndex); | |
443 | u32 val_orig; | |
444 | ||
445 | if (reg == AR_PHY_CCK_DETECT) { | |
446 | val_orig = REG_READ(ah, reg); | |
447 | val &= AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK; | |
448 | val_orig &= ~AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK; | |
449 | ||
450 | REG_WRITE(ah, reg, val|val_orig); | |
451 | } else | |
452 | REG_WRITE(ah, reg, val); | |
453 | } | |
454 | ||
455 | REGWRITE_BUFFER_FLUSH(ah); | |
c2ba3342 | 456 | } |