]>
Commit | Line | Data |
---|---|---|
f078f209 | 1 | /* |
cee075a2 | 2 | * Copyright (c) 2008-2009 Atheros Communications Inc. |
f078f209 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 | ||
131d1d03 LR |
17 | /** |
18 | * DOC: Programming Atheros 802.11n analog front end radios | |
19 | * | |
20 | * AR5416 MAC based PCI devices and AR518 MAC based PCI-Express | |
21 | * devices have either an external AR2133 analog front end radio for single | |
22 | * band 2.4 GHz communication or an AR5133 analog front end radio for dual | |
23 | * band 2.4 GHz / 5 GHz communication. | |
24 | * | |
25 | * All devices after the AR5416 and AR5418 family starting with the AR9280 | |
26 | * have their analog front radios, MAC/BB and host PCIe/USB interface embedded | |
27 | * into a single-chip and require less programming. | |
28 | * | |
29 | * The following single-chips exist with a respective embedded radio: | |
30 | * | |
31 | * AR9280 - 11n dual-band 2x2 MIMO for PCIe | |
32 | * AR9281 - 11n single-band 1x2 MIMO for PCIe | |
33 | * AR9285 - 11n single-band 1x1 for PCIe | |
34 | * AR9287 - 11n single-band 2x2 MIMO for PCIe | |
35 | * | |
36 | * AR9220 - 11n dual-band 2x2 MIMO for PCI | |
37 | * AR9223 - 11n single-band 2x2 MIMO for PCI | |
38 | * | |
39 | * AR9287 - 11n single-band 1x1 MIMO for USB | |
40 | */ | |
41 | ||
5a0e3ad6 TH |
42 | #include <linux/slab.h> |
43 | ||
cfe8cba9 | 44 | #include "hw.h" |
f078f209 | 45 | |
131d1d03 LR |
46 | /** |
47 | * ath9k_hw_write_regs - ?? | |
48 | * | |
49 | * @ah: atheros hardware structure | |
131d1d03 LR |
50 | * @freqIndex: |
51 | * @regWrites: | |
52 | * | |
53 | * Used for both the chipsets with an external AR2133/AR5133 radios and | |
54 | * single-chip devices. | |
55 | */ | |
896ff260 | 56 | void ath9k_hw_write_regs(struct ath_hw *ah, u32 freqIndex, int regWrites) |
f078f209 | 57 | { |
2660b81a | 58 | REG_WRITE_ARRAY(&ah->iniBB_RfGain, freqIndex, regWrites); |
f078f209 LR |
59 | } |
60 | ||
131d1d03 LR |
61 | /** |
62 | * ath9k_hw_ar9280_set_channel - set channel on single-chip device | |
63 | * @ah: atheros hardware structure | |
64 | * @chan: | |
65 | * | |
66 | * This is the function to change channel on single-chip devices, that is | |
67 | * all devices after ar9280. | |
68 | * | |
69 | * This function takes the channel value in MHz and sets | |
70 | * hardware channel value. Assumes writes have been enabled to analog bus. | |
71 | * | |
72 | * Actual Expression, | |
73 | * | |
74 | * For 2GHz channel, | |
75 | * Channel Frequency = (3/4) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^17) | |
76 | * (freq_ref = 40MHz) | |
77 | * | |
78 | * For 5GHz channel, | |
79 | * Channel Frequency = (3/2) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^10) | |
80 | * (freq_ref = 40MHz/(24>>amodeRefSel)) | |
81 | */ | |
0a3b7bac | 82 | int ath9k_hw_ar9280_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) |
f078f209 LR |
83 | { |
84 | u16 bMode, fracMode, aModeRefSel = 0; | |
85 | u32 freq, ndiv, channelSel = 0, channelFrac = 0, reg32 = 0; | |
86 | struct chan_centers centers; | |
87 | u32 refDivA = 24; | |
88 | ||
89 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); | |
90 | freq = centers.synth_center; | |
91 | ||
92 | reg32 = REG_READ(ah, AR_PHY_SYNTH_CONTROL); | |
93 | reg32 &= 0xc0000000; | |
94 | ||
131d1d03 | 95 | if (freq < 4800) { /* 2 GHz, fractional mode */ |
f078f209 | 96 | u32 txctl; |
193cd458 | 97 | int regWrites = 0; |
f078f209 LR |
98 | |
99 | bMode = 1; | |
100 | fracMode = 1; | |
101 | aModeRefSel = 0; | |
102 | channelSel = (freq * 0x10000) / 15; | |
103 | ||
193cd458 S |
104 | if (AR_SREV_9287_11_OR_LATER(ah)) { |
105 | if (freq == 2484) { | |
131d1d03 | 106 | /* Enable channel spreading for channel 14 */ |
193cd458 S |
107 | REG_WRITE_ARRAY(&ah->iniCckfirJapan2484, |
108 | 1, regWrites); | |
109 | } else { | |
110 | REG_WRITE_ARRAY(&ah->iniCckfirNormal, | |
111 | 1, regWrites); | |
112 | } | |
f078f209 | 113 | } else { |
193cd458 S |
114 | txctl = REG_READ(ah, AR_PHY_CCK_TX_CTRL); |
115 | if (freq == 2484) { | |
116 | /* Enable channel spreading for channel 14 */ | |
117 | REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, | |
118 | txctl | AR_PHY_CCK_TX_CTRL_JAPAN); | |
119 | } else { | |
120 | REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, | |
121 | txctl &~ AR_PHY_CCK_TX_CTRL_JAPAN); | |
122 | } | |
f078f209 LR |
123 | } |
124 | } else { | |
125 | bMode = 0; | |
126 | fracMode = 0; | |
127 | ||
06d0f066 S |
128 | switch(ah->eep_ops->get_eeprom(ah, EEP_FRAC_N_5G)) { |
129 | case 0: | |
130 | if ((freq % 20) == 0) { | |
131 | aModeRefSel = 3; | |
132 | } else if ((freq % 10) == 0) { | |
133 | aModeRefSel = 2; | |
134 | } | |
135 | if (aModeRefSel) | |
136 | break; | |
137 | case 1: | |
138 | default: | |
f078f209 | 139 | aModeRefSel = 0; |
131d1d03 LR |
140 | /* |
141 | * Enable 2G (fractional) mode for channels | |
142 | * which are 5MHz spaced. | |
143 | */ | |
f078f209 LR |
144 | fracMode = 1; |
145 | refDivA = 1; | |
146 | channelSel = (freq * 0x8000) / 15; | |
147 | ||
131d1d03 | 148 | /* RefDivA setting */ |
f078f209 LR |
149 | REG_RMW_FIELD(ah, AR_AN_SYNTH9, |
150 | AR_AN_SYNTH9_REFDIVA, refDivA); | |
06d0f066 | 151 | |
f078f209 | 152 | } |
06d0f066 | 153 | |
f078f209 LR |
154 | if (!fracMode) { |
155 | ndiv = (freq * (refDivA >> aModeRefSel)) / 60; | |
156 | channelSel = ndiv & 0x1ff; | |
157 | channelFrac = (ndiv & 0xfffffe00) * 2; | |
158 | channelSel = (channelSel << 17) | channelFrac; | |
159 | } | |
160 | } | |
161 | ||
162 | reg32 = reg32 | | |
163 | (bMode << 29) | | |
164 | (fracMode << 28) | (aModeRefSel << 26) | (channelSel); | |
165 | ||
166 | REG_WRITE(ah, AR_PHY_SYNTH_CONTROL, reg32); | |
167 | ||
2660b81a S |
168 | ah->curchan = chan; |
169 | ah->curchan_rad_index = -1; | |
0a3b7bac LR |
170 | |
171 | return 0; | |
f078f209 LR |
172 | } |
173 | ||
e16393bb LR |
174 | /** |
175 | * ath9k_hw_9280_spur_mitigate - convert baseband spur frequency | |
176 | * @ah: atheros hardware structure | |
177 | * @chan: | |
178 | * | |
179 | * For single-chip solutions. Converts to baseband spur frequency given the | |
180 | * input channel frequency and compute register settings below. | |
181 | */ | |
182 | void ath9k_hw_9280_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan) | |
183 | { | |
184 | int bb_spur = AR_NO_SPUR; | |
185 | int freq; | |
186 | int bin, cur_bin; | |
187 | int bb_spur_off, spur_subchannel_sd; | |
188 | int spur_freq_sd; | |
189 | int spur_delta_phase; | |
190 | int denominator; | |
191 | int upper, lower, cur_vit_mask; | |
192 | int tmp, newVal; | |
193 | int i; | |
194 | int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8, | |
195 | AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60 | |
196 | }; | |
197 | int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10, | |
198 | AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60 | |
199 | }; | |
200 | int inc[4] = { 0, 100, 0, 0 }; | |
201 | struct chan_centers centers; | |
202 | ||
203 | int8_t mask_m[123]; | |
204 | int8_t mask_p[123]; | |
205 | int8_t mask_amt; | |
206 | int tmp_mask; | |
207 | int cur_bb_spur; | |
208 | bool is2GHz = IS_CHAN_2GHZ(chan); | |
209 | ||
210 | memset(&mask_m, 0, sizeof(int8_t) * 123); | |
211 | memset(&mask_p, 0, sizeof(int8_t) * 123); | |
212 | ||
213 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); | |
214 | freq = centers.synth_center; | |
215 | ||
216 | ah->config.spurmode = SPUR_ENABLE_EEPROM; | |
217 | for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { | |
218 | cur_bb_spur = ah->eep_ops->get_spur_channel(ah, i, is2GHz); | |
219 | ||
220 | if (is2GHz) | |
221 | cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_2GHZ; | |
222 | else | |
223 | cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_5GHZ; | |
224 | ||
225 | if (AR_NO_SPUR == cur_bb_spur) | |
226 | break; | |
227 | cur_bb_spur = cur_bb_spur - freq; | |
228 | ||
229 | if (IS_CHAN_HT40(chan)) { | |
230 | if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT40) && | |
231 | (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT40)) { | |
232 | bb_spur = cur_bb_spur; | |
233 | break; | |
234 | } | |
235 | } else if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT20) && | |
236 | (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT20)) { | |
237 | bb_spur = cur_bb_spur; | |
238 | break; | |
239 | } | |
240 | } | |
241 | ||
242 | if (AR_NO_SPUR == bb_spur) { | |
243 | REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK, | |
244 | AR_PHY_FORCE_CLKEN_CCK_MRC_MUX); | |
245 | return; | |
246 | } else { | |
247 | REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK, | |
248 | AR_PHY_FORCE_CLKEN_CCK_MRC_MUX); | |
249 | } | |
250 | ||
251 | bin = bb_spur * 320; | |
252 | ||
253 | tmp = REG_READ(ah, AR_PHY_TIMING_CTRL4(0)); | |
254 | ||
255 | newVal = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI | | |
256 | AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER | | |
257 | AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK | | |
258 | AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK); | |
259 | REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0), newVal); | |
260 | ||
261 | newVal = (AR_PHY_SPUR_REG_MASK_RATE_CNTL | | |
262 | AR_PHY_SPUR_REG_ENABLE_MASK_PPM | | |
263 | AR_PHY_SPUR_REG_MASK_RATE_SELECT | | |
264 | AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI | | |
265 | SM(SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH)); | |
266 | REG_WRITE(ah, AR_PHY_SPUR_REG, newVal); | |
267 | ||
268 | if (IS_CHAN_HT40(chan)) { | |
269 | if (bb_spur < 0) { | |
270 | spur_subchannel_sd = 1; | |
271 | bb_spur_off = bb_spur + 10; | |
272 | } else { | |
273 | spur_subchannel_sd = 0; | |
274 | bb_spur_off = bb_spur - 10; | |
275 | } | |
276 | } else { | |
277 | spur_subchannel_sd = 0; | |
278 | bb_spur_off = bb_spur; | |
279 | } | |
280 | ||
281 | if (IS_CHAN_HT40(chan)) | |
282 | spur_delta_phase = | |
283 | ((bb_spur * 262144) / | |
284 | 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE; | |
285 | else | |
286 | spur_delta_phase = | |
287 | ((bb_spur * 524288) / | |
288 | 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE; | |
289 | ||
290 | denominator = IS_CHAN_2GHZ(chan) ? 44 : 40; | |
291 | spur_freq_sd = ((bb_spur_off * 2048) / denominator) & 0x3ff; | |
292 | ||
293 | newVal = (AR_PHY_TIMING11_USE_SPUR_IN_AGC | | |
294 | SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) | | |
295 | SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE)); | |
296 | REG_WRITE(ah, AR_PHY_TIMING11, newVal); | |
297 | ||
298 | newVal = spur_subchannel_sd << AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S; | |
299 | REG_WRITE(ah, AR_PHY_SFCORR_EXT, newVal); | |
300 | ||
301 | cur_bin = -6000; | |
302 | upper = bin + 100; | |
303 | lower = bin - 100; | |
304 | ||
305 | for (i = 0; i < 4; i++) { | |
306 | int pilot_mask = 0; | |
307 | int chan_mask = 0; | |
308 | int bp = 0; | |
309 | for (bp = 0; bp < 30; bp++) { | |
310 | if ((cur_bin > lower) && (cur_bin < upper)) { | |
311 | pilot_mask = pilot_mask | 0x1 << bp; | |
312 | chan_mask = chan_mask | 0x1 << bp; | |
313 | } | |
314 | cur_bin += 100; | |
315 | } | |
316 | cur_bin += inc[i]; | |
317 | REG_WRITE(ah, pilot_mask_reg[i], pilot_mask); | |
318 | REG_WRITE(ah, chan_mask_reg[i], chan_mask); | |
319 | } | |
320 | ||
321 | cur_vit_mask = 6100; | |
322 | upper = bin + 120; | |
323 | lower = bin - 120; | |
324 | ||
325 | for (i = 0; i < 123; i++) { | |
326 | if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) { | |
327 | ||
328 | /* workaround for gcc bug #37014 */ | |
329 | volatile int tmp_v = abs(cur_vit_mask - bin); | |
330 | ||
331 | if (tmp_v < 75) | |
332 | mask_amt = 1; | |
333 | else | |
334 | mask_amt = 0; | |
335 | if (cur_vit_mask < 0) | |
336 | mask_m[abs(cur_vit_mask / 100)] = mask_amt; | |
337 | else | |
338 | mask_p[cur_vit_mask / 100] = mask_amt; | |
339 | } | |
340 | cur_vit_mask -= 100; | |
341 | } | |
342 | ||
343 | tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28) | |
344 | | (mask_m[48] << 26) | (mask_m[49] << 24) | |
345 | | (mask_m[50] << 22) | (mask_m[51] << 20) | |
346 | | (mask_m[52] << 18) | (mask_m[53] << 16) | |
347 | | (mask_m[54] << 14) | (mask_m[55] << 12) | |
348 | | (mask_m[56] << 10) | (mask_m[57] << 8) | |
349 | | (mask_m[58] << 6) | (mask_m[59] << 4) | |
350 | | (mask_m[60] << 2) | (mask_m[61] << 0); | |
351 | REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask); | |
352 | REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask); | |
353 | ||
354 | tmp_mask = (mask_m[31] << 28) | |
355 | | (mask_m[32] << 26) | (mask_m[33] << 24) | |
356 | | (mask_m[34] << 22) | (mask_m[35] << 20) | |
357 | | (mask_m[36] << 18) | (mask_m[37] << 16) | |
358 | | (mask_m[48] << 14) | (mask_m[39] << 12) | |
359 | | (mask_m[40] << 10) | (mask_m[41] << 8) | |
360 | | (mask_m[42] << 6) | (mask_m[43] << 4) | |
361 | | (mask_m[44] << 2) | (mask_m[45] << 0); | |
362 | REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask); | |
363 | REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask); | |
364 | ||
365 | tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28) | |
366 | | (mask_m[18] << 26) | (mask_m[18] << 24) | |
367 | | (mask_m[20] << 22) | (mask_m[20] << 20) | |
368 | | (mask_m[22] << 18) | (mask_m[22] << 16) | |
369 | | (mask_m[24] << 14) | (mask_m[24] << 12) | |
370 | | (mask_m[25] << 10) | (mask_m[26] << 8) | |
371 | | (mask_m[27] << 6) | (mask_m[28] << 4) | |
372 | | (mask_m[29] << 2) | (mask_m[30] << 0); | |
373 | REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask); | |
374 | REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask); | |
375 | ||
376 | tmp_mask = (mask_m[0] << 30) | (mask_m[1] << 28) | |
377 | | (mask_m[2] << 26) | (mask_m[3] << 24) | |
378 | | (mask_m[4] << 22) | (mask_m[5] << 20) | |
379 | | (mask_m[6] << 18) | (mask_m[7] << 16) | |
380 | | (mask_m[8] << 14) | (mask_m[9] << 12) | |
381 | | (mask_m[10] << 10) | (mask_m[11] << 8) | |
382 | | (mask_m[12] << 6) | (mask_m[13] << 4) | |
383 | | (mask_m[14] << 2) | (mask_m[15] << 0); | |
384 | REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask); | |
385 | REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask); | |
386 | ||
387 | tmp_mask = (mask_p[15] << 28) | |
388 | | (mask_p[14] << 26) | (mask_p[13] << 24) | |
389 | | (mask_p[12] << 22) | (mask_p[11] << 20) | |
390 | | (mask_p[10] << 18) | (mask_p[9] << 16) | |
391 | | (mask_p[8] << 14) | (mask_p[7] << 12) | |
392 | | (mask_p[6] << 10) | (mask_p[5] << 8) | |
393 | | (mask_p[4] << 6) | (mask_p[3] << 4) | |
394 | | (mask_p[2] << 2) | (mask_p[1] << 0); | |
395 | REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask); | |
396 | REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask); | |
397 | ||
398 | tmp_mask = (mask_p[30] << 28) | |
399 | | (mask_p[29] << 26) | (mask_p[28] << 24) | |
400 | | (mask_p[27] << 22) | (mask_p[26] << 20) | |
401 | | (mask_p[25] << 18) | (mask_p[24] << 16) | |
402 | | (mask_p[23] << 14) | (mask_p[22] << 12) | |
403 | | (mask_p[21] << 10) | (mask_p[20] << 8) | |
404 | | (mask_p[19] << 6) | (mask_p[18] << 4) | |
405 | | (mask_p[17] << 2) | (mask_p[16] << 0); | |
406 | REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask); | |
407 | REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask); | |
408 | ||
409 | tmp_mask = (mask_p[45] << 28) | |
410 | | (mask_p[44] << 26) | (mask_p[43] << 24) | |
411 | | (mask_p[42] << 22) | (mask_p[41] << 20) | |
412 | | (mask_p[40] << 18) | (mask_p[39] << 16) | |
413 | | (mask_p[38] << 14) | (mask_p[37] << 12) | |
414 | | (mask_p[36] << 10) | (mask_p[35] << 8) | |
415 | | (mask_p[34] << 6) | (mask_p[33] << 4) | |
416 | | (mask_p[32] << 2) | (mask_p[31] << 0); | |
417 | REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask); | |
418 | REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask); | |
419 | ||
420 | tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28) | |
421 | | (mask_p[59] << 26) | (mask_p[58] << 24) | |
422 | | (mask_p[57] << 22) | (mask_p[56] << 20) | |
423 | | (mask_p[55] << 18) | (mask_p[54] << 16) | |
424 | | (mask_p[53] << 14) | (mask_p[52] << 12) | |
425 | | (mask_p[51] << 10) | (mask_p[50] << 8) | |
426 | | (mask_p[49] << 6) | (mask_p[48] << 4) | |
427 | | (mask_p[47] << 2) | (mask_p[46] << 0); | |
428 | REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask); | |
429 | REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask); | |
430 | } | |
431 | ||
432 | /* All code below is for non single-chip solutions */ | |
433 | ||
ddcd4c08 LR |
434 | /** |
435 | * ath9k_phy_modify_rx_buffer() - perform analog swizzling of parameters | |
436 | * @rfbuf: | |
437 | * @reg32: | |
438 | * @numBits: | |
439 | * @firstBit: | |
440 | * @column: | |
441 | * | |
442 | * Performs analog "swizzling" of parameters into their location. | |
443 | * Used on external AR2133/AR5133 radios. | |
444 | */ | |
445 | static void ath9k_phy_modify_rx_buffer(u32 *rfBuf, u32 reg32, | |
446 | u32 numBits, u32 firstBit, | |
447 | u32 column) | |
448 | { | |
449 | u32 tmp32, mask, arrayEntry, lastBit; | |
450 | int32_t bitPosition, bitsLeft; | |
451 | ||
452 | tmp32 = ath9k_hw_reverse_bits(reg32, numBits); | |
453 | arrayEntry = (firstBit - 1) / 8; | |
454 | bitPosition = (firstBit - 1) % 8; | |
455 | bitsLeft = numBits; | |
456 | while (bitsLeft > 0) { | |
457 | lastBit = (bitPosition + bitsLeft > 8) ? | |
458 | 8 : bitPosition + bitsLeft; | |
459 | mask = (((1 << lastBit) - 1) ^ ((1 << bitPosition) - 1)) << | |
460 | (column * 8); | |
461 | rfBuf[arrayEntry] &= ~mask; | |
462 | rfBuf[arrayEntry] |= ((tmp32 << bitPosition) << | |
463 | (column * 8)) & mask; | |
464 | bitsLeft -= 8 - bitPosition; | |
465 | tmp32 = tmp32 >> (8 - bitPosition); | |
466 | bitPosition = 0; | |
467 | arrayEntry++; | |
468 | } | |
469 | } | |
470 | ||
a7765828 LR |
471 | /* |
472 | * Fix on 2.4 GHz band for orientation sensitivity issue by increasing | |
473 | * rf_pwd_icsyndiv. | |
474 | * | |
475 | * Theoretical Rules: | |
476 | * if 2 GHz band | |
477 | * if forceBiasAuto | |
478 | * if synth_freq < 2412 | |
479 | * bias = 0 | |
480 | * else if 2412 <= synth_freq <= 2422 | |
481 | * bias = 1 | |
482 | * else // synth_freq > 2422 | |
483 | * bias = 2 | |
484 | * else if forceBias > 0 | |
485 | * bias = forceBias & 7 | |
486 | * else | |
487 | * no change, use value from ini file | |
488 | * else | |
489 | * no change, invalid band | |
490 | * | |
491 | * 1st Mod: | |
492 | * 2422 also uses value of 2 | |
493 | * <approved> | |
494 | * | |
495 | * 2nd Mod: | |
496 | * Less than 2412 uses value of 0, 2412 and above uses value of 2 | |
497 | */ | |
498 | static void ath9k_hw_force_bias(struct ath_hw *ah, u16 synth_freq) | |
499 | { | |
500 | struct ath_common *common = ath9k_hw_common(ah); | |
501 | u32 tmp_reg; | |
502 | int reg_writes = 0; | |
503 | u32 new_bias = 0; | |
504 | ||
505 | if (!AR_SREV_5416(ah) || synth_freq >= 3000) { | |
506 | return; | |
507 | } | |
508 | ||
509 | BUG_ON(AR_SREV_9280_10_OR_LATER(ah)); | |
510 | ||
511 | if (synth_freq < 2412) | |
512 | new_bias = 0; | |
513 | else if (synth_freq < 2422) | |
514 | new_bias = 1; | |
515 | else | |
516 | new_bias = 2; | |
517 | ||
518 | /* pre-reverse this field */ | |
519 | tmp_reg = ath9k_hw_reverse_bits(new_bias, 3); | |
520 | ||
521 | ath_print(common, ATH_DBG_CONFIG, | |
522 | "Force rf_pwd_icsyndiv to %1d on %4d\n", | |
523 | new_bias, synth_freq); | |
524 | ||
525 | /* swizzle rf_pwd_icsyndiv */ | |
526 | ath9k_phy_modify_rx_buffer(ah->analogBank6Data, tmp_reg, 3, 181, 3); | |
527 | ||
528 | /* write Bank 6 with new params */ | |
529 | REG_WRITE_RF_ARRAY(&ah->iniBank6, ah->analogBank6Data, reg_writes); | |
530 | } | |
531 | ||
e16393bb LR |
532 | /** |
533 | * ath9k_hw_set_channel - tune to a channel on the external AR2133/AR5133 radios | |
534 | * @ah: atheros hardware stucture | |
535 | * @chan: | |
536 | * | |
537 | * For the external AR2133/AR5133 radios, takes the MHz channel value and set | |
538 | * the channel value. Assumes writes enabled to analog bus and bank6 register | |
539 | * cache in ah->analogBank6Data. | |
540 | */ | |
541 | int ath9k_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) | |
542 | { | |
543 | struct ath_common *common = ath9k_hw_common(ah); | |
544 | u32 channelSel = 0; | |
545 | u32 bModeSynth = 0; | |
546 | u32 aModeRefSel = 0; | |
547 | u32 reg32 = 0; | |
548 | u16 freq; | |
549 | struct chan_centers centers; | |
550 | ||
551 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); | |
552 | freq = centers.synth_center; | |
553 | ||
554 | if (freq < 4800) { | |
555 | u32 txctl; | |
556 | ||
557 | if (((freq - 2192) % 5) == 0) { | |
558 | channelSel = ((freq - 672) * 2 - 3040) / 10; | |
559 | bModeSynth = 0; | |
560 | } else if (((freq - 2224) % 5) == 0) { | |
561 | channelSel = ((freq - 704) * 2 - 3040) / 10; | |
562 | bModeSynth = 1; | |
563 | } else { | |
564 | ath_print(common, ATH_DBG_FATAL, | |
565 | "Invalid channel %u MHz\n", freq); | |
566 | return -EINVAL; | |
567 | } | |
568 | ||
569 | channelSel = (channelSel << 2) & 0xff; | |
570 | channelSel = ath9k_hw_reverse_bits(channelSel, 8); | |
571 | ||
572 | txctl = REG_READ(ah, AR_PHY_CCK_TX_CTRL); | |
573 | if (freq == 2484) { | |
574 | ||
575 | REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, | |
576 | txctl | AR_PHY_CCK_TX_CTRL_JAPAN); | |
577 | } else { | |
578 | REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, | |
579 | txctl & ~AR_PHY_CCK_TX_CTRL_JAPAN); | |
580 | } | |
581 | ||
582 | } else if ((freq % 20) == 0 && freq >= 5120) { | |
583 | channelSel = | |
584 | ath9k_hw_reverse_bits(((freq - 4800) / 20 << 2), 8); | |
585 | aModeRefSel = ath9k_hw_reverse_bits(1, 2); | |
586 | } else if ((freq % 10) == 0) { | |
587 | channelSel = | |
588 | ath9k_hw_reverse_bits(((freq - 4800) / 10 << 1), 8); | |
589 | if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) | |
590 | aModeRefSel = ath9k_hw_reverse_bits(2, 2); | |
591 | else | |
592 | aModeRefSel = ath9k_hw_reverse_bits(1, 2); | |
593 | } else if ((freq % 5) == 0) { | |
594 | channelSel = ath9k_hw_reverse_bits((freq - 4800) / 5, 8); | |
595 | aModeRefSel = ath9k_hw_reverse_bits(1, 2); | |
596 | } else { | |
597 | ath_print(common, ATH_DBG_FATAL, | |
598 | "Invalid channel %u MHz\n", freq); | |
599 | return -EINVAL; | |
600 | } | |
601 | ||
a7765828 | 602 | ath9k_hw_force_bias(ah, freq); |
a7765828 | 603 | |
e16393bb LR |
604 | reg32 = |
605 | (channelSel << 8) | (aModeRefSel << 2) | (bModeSynth << 1) | | |
606 | (1 << 5) | 0x1; | |
607 | ||
608 | REG_WRITE(ah, AR_PHY(0x37), reg32); | |
609 | ||
610 | ah->curchan = chan; | |
611 | ah->curchan_rad_index = -1; | |
612 | ||
613 | return 0; | |
614 | } | |
615 | ||
616 | /** | |
617 | * ath9k_hw_spur_mitigate - convert baseband spur frequency for external radios | |
618 | * @ah: atheros hardware structure | |
619 | * @chan: | |
620 | * | |
621 | * For non single-chip solutions. Converts to baseband spur frequency given the | |
622 | * input channel frequency and compute register settings below. | |
623 | */ | |
624 | void ath9k_hw_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan) | |
625 | { | |
626 | int bb_spur = AR_NO_SPUR; | |
627 | int bin, cur_bin; | |
628 | int spur_freq_sd; | |
629 | int spur_delta_phase; | |
630 | int denominator; | |
631 | int upper, lower, cur_vit_mask; | |
632 | int tmp, new; | |
633 | int i; | |
634 | int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8, | |
635 | AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60 | |
636 | }; | |
637 | int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10, | |
638 | AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60 | |
639 | }; | |
640 | int inc[4] = { 0, 100, 0, 0 }; | |
641 | ||
642 | int8_t mask_m[123]; | |
643 | int8_t mask_p[123]; | |
644 | int8_t mask_amt; | |
645 | int tmp_mask; | |
646 | int cur_bb_spur; | |
647 | bool is2GHz = IS_CHAN_2GHZ(chan); | |
648 | ||
649 | memset(&mask_m, 0, sizeof(int8_t) * 123); | |
650 | memset(&mask_p, 0, sizeof(int8_t) * 123); | |
651 | ||
652 | for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { | |
653 | cur_bb_spur = ah->eep_ops->get_spur_channel(ah, i, is2GHz); | |
654 | if (AR_NO_SPUR == cur_bb_spur) | |
655 | break; | |
656 | cur_bb_spur = cur_bb_spur - (chan->channel * 10); | |
657 | if ((cur_bb_spur > -95) && (cur_bb_spur < 95)) { | |
658 | bb_spur = cur_bb_spur; | |
659 | break; | |
660 | } | |
661 | } | |
662 | ||
663 | if (AR_NO_SPUR == bb_spur) | |
664 | return; | |
665 | ||
666 | bin = bb_spur * 32; | |
667 | ||
668 | tmp = REG_READ(ah, AR_PHY_TIMING_CTRL4(0)); | |
669 | new = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI | | |
670 | AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER | | |
671 | AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK | | |
672 | AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK); | |
673 | ||
674 | REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0), new); | |
675 | ||
676 | new = (AR_PHY_SPUR_REG_MASK_RATE_CNTL | | |
677 | AR_PHY_SPUR_REG_ENABLE_MASK_PPM | | |
678 | AR_PHY_SPUR_REG_MASK_RATE_SELECT | | |
679 | AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI | | |
680 | SM(SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH)); | |
681 | REG_WRITE(ah, AR_PHY_SPUR_REG, new); | |
682 | ||
683 | spur_delta_phase = ((bb_spur * 524288) / 100) & | |
684 | AR_PHY_TIMING11_SPUR_DELTA_PHASE; | |
685 | ||
686 | denominator = IS_CHAN_2GHZ(chan) ? 440 : 400; | |
687 | spur_freq_sd = ((bb_spur * 2048) / denominator) & 0x3ff; | |
688 | ||
689 | new = (AR_PHY_TIMING11_USE_SPUR_IN_AGC | | |
690 | SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) | | |
691 | SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE)); | |
692 | REG_WRITE(ah, AR_PHY_TIMING11, new); | |
693 | ||
694 | cur_bin = -6000; | |
695 | upper = bin + 100; | |
696 | lower = bin - 100; | |
697 | ||
698 | for (i = 0; i < 4; i++) { | |
699 | int pilot_mask = 0; | |
700 | int chan_mask = 0; | |
701 | int bp = 0; | |
702 | for (bp = 0; bp < 30; bp++) { | |
703 | if ((cur_bin > lower) && (cur_bin < upper)) { | |
704 | pilot_mask = pilot_mask | 0x1 << bp; | |
705 | chan_mask = chan_mask | 0x1 << bp; | |
706 | } | |
707 | cur_bin += 100; | |
708 | } | |
709 | cur_bin += inc[i]; | |
710 | REG_WRITE(ah, pilot_mask_reg[i], pilot_mask); | |
711 | REG_WRITE(ah, chan_mask_reg[i], chan_mask); | |
712 | } | |
713 | ||
714 | cur_vit_mask = 6100; | |
715 | upper = bin + 120; | |
716 | lower = bin - 120; | |
717 | ||
718 | for (i = 0; i < 123; i++) { | |
719 | if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) { | |
720 | ||
721 | /* workaround for gcc bug #37014 */ | |
722 | volatile int tmp_v = abs(cur_vit_mask - bin); | |
723 | ||
724 | if (tmp_v < 75) | |
725 | mask_amt = 1; | |
726 | else | |
727 | mask_amt = 0; | |
728 | if (cur_vit_mask < 0) | |
729 | mask_m[abs(cur_vit_mask / 100)] = mask_amt; | |
730 | else | |
731 | mask_p[cur_vit_mask / 100] = mask_amt; | |
732 | } | |
733 | cur_vit_mask -= 100; | |
734 | } | |
735 | ||
736 | tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28) | |
737 | | (mask_m[48] << 26) | (mask_m[49] << 24) | |
738 | | (mask_m[50] << 22) | (mask_m[51] << 20) | |
739 | | (mask_m[52] << 18) | (mask_m[53] << 16) | |
740 | | (mask_m[54] << 14) | (mask_m[55] << 12) | |
741 | | (mask_m[56] << 10) | (mask_m[57] << 8) | |
742 | | (mask_m[58] << 6) | (mask_m[59] << 4) | |
743 | | (mask_m[60] << 2) | (mask_m[61] << 0); | |
744 | REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask); | |
745 | REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask); | |
746 | ||
747 | tmp_mask = (mask_m[31] << 28) | |
748 | | (mask_m[32] << 26) | (mask_m[33] << 24) | |
749 | | (mask_m[34] << 22) | (mask_m[35] << 20) | |
750 | | (mask_m[36] << 18) | (mask_m[37] << 16) | |
751 | | (mask_m[48] << 14) | (mask_m[39] << 12) | |
752 | | (mask_m[40] << 10) | (mask_m[41] << 8) | |
753 | | (mask_m[42] << 6) | (mask_m[43] << 4) | |
754 | | (mask_m[44] << 2) | (mask_m[45] << 0); | |
755 | REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask); | |
756 | REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask); | |
757 | ||
758 | tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28) | |
759 | | (mask_m[18] << 26) | (mask_m[18] << 24) | |
760 | | (mask_m[20] << 22) | (mask_m[20] << 20) | |
761 | | (mask_m[22] << 18) | (mask_m[22] << 16) | |
762 | | (mask_m[24] << 14) | (mask_m[24] << 12) | |
763 | | (mask_m[25] << 10) | (mask_m[26] << 8) | |
764 | | (mask_m[27] << 6) | (mask_m[28] << 4) | |
765 | | (mask_m[29] << 2) | (mask_m[30] << 0); | |
766 | REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask); | |
767 | REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask); | |
768 | ||
769 | tmp_mask = (mask_m[0] << 30) | (mask_m[1] << 28) | |
770 | | (mask_m[2] << 26) | (mask_m[3] << 24) | |
771 | | (mask_m[4] << 22) | (mask_m[5] << 20) | |
772 | | (mask_m[6] << 18) | (mask_m[7] << 16) | |
773 | | (mask_m[8] << 14) | (mask_m[9] << 12) | |
774 | | (mask_m[10] << 10) | (mask_m[11] << 8) | |
775 | | (mask_m[12] << 6) | (mask_m[13] << 4) | |
776 | | (mask_m[14] << 2) | (mask_m[15] << 0); | |
777 | REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask); | |
778 | REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask); | |
779 | ||
780 | tmp_mask = (mask_p[15] << 28) | |
781 | | (mask_p[14] << 26) | (mask_p[13] << 24) | |
782 | | (mask_p[12] << 22) | (mask_p[11] << 20) | |
783 | | (mask_p[10] << 18) | (mask_p[9] << 16) | |
784 | | (mask_p[8] << 14) | (mask_p[7] << 12) | |
785 | | (mask_p[6] << 10) | (mask_p[5] << 8) | |
786 | | (mask_p[4] << 6) | (mask_p[3] << 4) | |
787 | | (mask_p[2] << 2) | (mask_p[1] << 0); | |
788 | REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask); | |
789 | REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask); | |
790 | ||
791 | tmp_mask = (mask_p[30] << 28) | |
792 | | (mask_p[29] << 26) | (mask_p[28] << 24) | |
793 | | (mask_p[27] << 22) | (mask_p[26] << 20) | |
794 | | (mask_p[25] << 18) | (mask_p[24] << 16) | |
795 | | (mask_p[23] << 14) | (mask_p[22] << 12) | |
796 | | (mask_p[21] << 10) | (mask_p[20] << 8) | |
797 | | (mask_p[19] << 6) | (mask_p[18] << 4) | |
798 | | (mask_p[17] << 2) | (mask_p[16] << 0); | |
799 | REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask); | |
800 | REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask); | |
801 | ||
802 | tmp_mask = (mask_p[45] << 28) | |
803 | | (mask_p[44] << 26) | (mask_p[43] << 24) | |
804 | | (mask_p[42] << 22) | (mask_p[41] << 20) | |
805 | | (mask_p[40] << 18) | (mask_p[39] << 16) | |
806 | | (mask_p[38] << 14) | (mask_p[37] << 12) | |
807 | | (mask_p[36] << 10) | (mask_p[35] << 8) | |
808 | | (mask_p[34] << 6) | (mask_p[33] << 4) | |
809 | | (mask_p[32] << 2) | (mask_p[31] << 0); | |
810 | REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask); | |
811 | REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask); | |
812 | ||
813 | tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28) | |
814 | | (mask_p[59] << 26) | (mask_p[58] << 24) | |
815 | | (mask_p[57] << 22) | (mask_p[56] << 20) | |
816 | | (mask_p[55] << 18) | (mask_p[54] << 16) | |
817 | | (mask_p[53] << 14) | (mask_p[52] << 12) | |
818 | | (mask_p[51] << 10) | (mask_p[50] << 8) | |
819 | | (mask_p[49] << 6) | (mask_p[48] << 4) | |
820 | | (mask_p[47] << 2) | (mask_p[46] << 0); | |
821 | REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask); | |
822 | REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask); | |
823 | } | |
824 | ||
825 | /** | |
826 | * ath9k_hw_rf_alloc_ext_banks - allocates banks for external radio programming | |
827 | * @ah: atheros hardware structure | |
828 | * | |
829 | * Only required for older devices with external AR2133/AR5133 radios. | |
830 | */ | |
831 | int ath9k_hw_rf_alloc_ext_banks(struct ath_hw *ah) | |
832 | { | |
833 | #define ATH_ALLOC_BANK(bank, size) do { \ | |
834 | bank = kzalloc((sizeof(u32) * size), GFP_KERNEL); \ | |
835 | if (!bank) { \ | |
836 | ath_print(common, ATH_DBG_FATAL, \ | |
837 | "Cannot allocate RF banks\n"); \ | |
838 | return -ENOMEM; \ | |
839 | } \ | |
840 | } while (0); | |
841 | ||
842 | struct ath_common *common = ath9k_hw_common(ah); | |
843 | ||
844 | BUG_ON(AR_SREV_9280_10_OR_LATER(ah)); | |
845 | ||
846 | ATH_ALLOC_BANK(ah->analogBank0Data, ah->iniBank0.ia_rows); | |
847 | ATH_ALLOC_BANK(ah->analogBank1Data, ah->iniBank1.ia_rows); | |
848 | ATH_ALLOC_BANK(ah->analogBank2Data, ah->iniBank2.ia_rows); | |
849 | ATH_ALLOC_BANK(ah->analogBank3Data, ah->iniBank3.ia_rows); | |
850 | ATH_ALLOC_BANK(ah->analogBank6Data, ah->iniBank6.ia_rows); | |
851 | ATH_ALLOC_BANK(ah->analogBank6TPCData, ah->iniBank6TPC.ia_rows); | |
852 | ATH_ALLOC_BANK(ah->analogBank7Data, ah->iniBank7.ia_rows); | |
853 | ATH_ALLOC_BANK(ah->addac5416_21, | |
854 | ah->iniAddac.ia_rows * ah->iniAddac.ia_columns); | |
855 | ATH_ALLOC_BANK(ah->bank6Temp, ah->iniBank6.ia_rows); | |
856 | ||
857 | return 0; | |
858 | #undef ATH_ALLOC_BANK | |
859 | } | |
860 | ||
861 | ||
862 | /** | |
863 | * ath9k_hw_rf_free_ext_banks - Free memory for analog bank scratch buffers | |
864 | * @ah: atheros hardware struture | |
865 | * For the external AR2133/AR5133 radios banks. | |
866 | */ | |
867 | void | |
868 | ath9k_hw_rf_free_ext_banks(struct ath_hw *ah) | |
869 | { | |
870 | #define ATH_FREE_BANK(bank) do { \ | |
871 | kfree(bank); \ | |
872 | bank = NULL; \ | |
873 | } while (0); | |
874 | ||
875 | BUG_ON(AR_SREV_9280_10_OR_LATER(ah)); | |
876 | ||
877 | ATH_FREE_BANK(ah->analogBank0Data); | |
878 | ATH_FREE_BANK(ah->analogBank1Data); | |
879 | ATH_FREE_BANK(ah->analogBank2Data); | |
880 | ATH_FREE_BANK(ah->analogBank3Data); | |
881 | ATH_FREE_BANK(ah->analogBank6Data); | |
882 | ATH_FREE_BANK(ah->analogBank6TPCData); | |
883 | ATH_FREE_BANK(ah->analogBank7Data); | |
884 | ATH_FREE_BANK(ah->addac5416_21); | |
885 | ATH_FREE_BANK(ah->bank6Temp); | |
886 | ||
887 | #undef ATH_FREE_BANK | |
888 | } | |
889 | ||
131d1d03 LR |
890 | /* * |
891 | * ath9k_hw_set_rf_regs - programs rf registers based on EEPROM | |
892 | * @ah: atheros hardware structure | |
893 | * @chan: | |
894 | * @modesIndex: | |
895 | * | |
896 | * Used for the external AR2133/AR5133 radios. | |
897 | * | |
898 | * Reads the EEPROM header info from the device structure and programs | |
899 | * all rf registers. This routine requires access to the analog | |
900 | * rf device. This is not required for single-chip devices. | |
901 | */ | |
e16393bb LR |
902 | bool ath9k_hw_set_rf_regs(struct ath_hw *ah, struct ath9k_channel *chan, |
903 | u16 modesIndex) | |
f078f209 | 904 | { |
f078f209 LR |
905 | u32 eepMinorRev; |
906 | u32 ob5GHz = 0, db5GHz = 0; | |
907 | u32 ob2GHz = 0, db2GHz = 0; | |
908 | int regWrites = 0; | |
909 | ||
131d1d03 LR |
910 | /* |
911 | * Software does not need to program bank data | |
912 | * for single chip devices, that is AR9280 or anything | |
913 | * after that. | |
914 | */ | |
f078f209 LR |
915 | if (AR_SREV_9280_10_OR_LATER(ah)) |
916 | return true; | |
917 | ||
131d1d03 | 918 | /* Setup rf parameters */ |
f74df6fb | 919 | eepMinorRev = ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV); |
f078f209 | 920 | |
131d1d03 | 921 | /* Setup Bank 0 Write */ |
2660b81a | 922 | RF_BANK_SETUP(ah->analogBank0Data, &ah->iniBank0, 1); |
f078f209 | 923 | |
131d1d03 | 924 | /* Setup Bank 1 Write */ |
2660b81a | 925 | RF_BANK_SETUP(ah->analogBank1Data, &ah->iniBank1, 1); |
f078f209 | 926 | |
131d1d03 | 927 | /* Setup Bank 2 Write */ |
2660b81a | 928 | RF_BANK_SETUP(ah->analogBank2Data, &ah->iniBank2, 1); |
f078f209 | 929 | |
131d1d03 | 930 | /* Setup Bank 6 Write */ |
2660b81a | 931 | RF_BANK_SETUP(ah->analogBank3Data, &ah->iniBank3, |
f078f209 LR |
932 | modesIndex); |
933 | { | |
934 | int i; | |
2660b81a S |
935 | for (i = 0; i < ah->iniBank6TPC.ia_rows; i++) { |
936 | ah->analogBank6Data[i] = | |
937 | INI_RA(&ah->iniBank6TPC, i, modesIndex); | |
f078f209 LR |
938 | } |
939 | } | |
940 | ||
131d1d03 | 941 | /* Only the 5 or 2 GHz OB/DB need to be set for a mode */ |
f078f209 LR |
942 | if (eepMinorRev >= 2) { |
943 | if (IS_CHAN_2GHZ(chan)) { | |
f74df6fb S |
944 | ob2GHz = ah->eep_ops->get_eeprom(ah, EEP_OB_2); |
945 | db2GHz = ah->eep_ops->get_eeprom(ah, EEP_DB_2); | |
2660b81a | 946 | ath9k_phy_modify_rx_buffer(ah->analogBank6Data, |
f078f209 | 947 | ob2GHz, 3, 197, 0); |
2660b81a | 948 | ath9k_phy_modify_rx_buffer(ah->analogBank6Data, |
f078f209 LR |
949 | db2GHz, 3, 194, 0); |
950 | } else { | |
f74df6fb S |
951 | ob5GHz = ah->eep_ops->get_eeprom(ah, EEP_OB_5); |
952 | db5GHz = ah->eep_ops->get_eeprom(ah, EEP_DB_5); | |
2660b81a | 953 | ath9k_phy_modify_rx_buffer(ah->analogBank6Data, |
f078f209 | 954 | ob5GHz, 3, 203, 0); |
2660b81a | 955 | ath9k_phy_modify_rx_buffer(ah->analogBank6Data, |
f078f209 LR |
956 | db5GHz, 3, 200, 0); |
957 | } | |
958 | } | |
959 | ||
131d1d03 | 960 | /* Setup Bank 7 Setup */ |
2660b81a | 961 | RF_BANK_SETUP(ah->analogBank7Data, &ah->iniBank7, 1); |
f078f209 | 962 | |
131d1d03 | 963 | /* Write Analog registers */ |
2660b81a | 964 | REG_WRITE_RF_ARRAY(&ah->iniBank0, ah->analogBank0Data, |
f078f209 | 965 | regWrites); |
2660b81a | 966 | REG_WRITE_RF_ARRAY(&ah->iniBank1, ah->analogBank1Data, |
f078f209 | 967 | regWrites); |
2660b81a | 968 | REG_WRITE_RF_ARRAY(&ah->iniBank2, ah->analogBank2Data, |
f078f209 | 969 | regWrites); |
2660b81a | 970 | REG_WRITE_RF_ARRAY(&ah->iniBank3, ah->analogBank3Data, |
f078f209 | 971 | regWrites); |
2660b81a | 972 | REG_WRITE_RF_ARRAY(&ah->iniBank6TPC, ah->analogBank6Data, |
f078f209 | 973 | regWrites); |
2660b81a | 974 | REG_WRITE_RF_ARRAY(&ah->iniBank7, ah->analogBank7Data, |
f078f209 LR |
975 | regWrites); |
976 | ||
977 | return true; | |
978 | } |