2 * Copyright (c) 2008-2009 Atheros Communications Inc.
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.
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.
18 * DOC: Programming Atheros 802.11n analog front end radios
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.
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.
29 * The following single-chips exist with a respective embedded radio:
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
36 * AR9220 - 11n dual-band 2x2 MIMO for PCI
37 * AR9223 - 11n single-band 2x2 MIMO for PCI
39 * AR9287 - 11n single-band 1x1 MIMO for USB
45 * ath9k_hw_write_regs - ??
47 * @ah: atheros hardware structure
51 * Used for both the chipsets with an external AR2133/AR5133 radios and
52 * single-chip devices.
54 void ath9k_hw_write_regs(struct ath_hw
*ah
, u32 freqIndex
, int regWrites
)
56 REG_WRITE_ARRAY(&ah
->iniBB_RfGain
, freqIndex
, regWrites
);
60 * ath9k_hw_ar9280_set_channel - set channel on single-chip device
61 * @ah: atheros hardware structure
64 * This is the function to change channel on single-chip devices, that is
65 * all devices after ar9280.
67 * This function takes the channel value in MHz and sets
68 * hardware channel value. Assumes writes have been enabled to analog bus.
73 * Channel Frequency = (3/4) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^17)
77 * Channel Frequency = (3/2) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^10)
78 * (freq_ref = 40MHz/(24>>amodeRefSel))
80 int ath9k_hw_ar9280_set_channel(struct ath_hw
*ah
, struct ath9k_channel
*chan
)
82 u16 bMode
, fracMode
, aModeRefSel
= 0;
83 u32 freq
, ndiv
, channelSel
= 0, channelFrac
= 0, reg32
= 0;
84 struct chan_centers centers
;
87 ath9k_hw_get_channel_centers(ah
, chan
, ¢ers
);
88 freq
= centers
.synth_center
;
90 reg32
= REG_READ(ah
, AR_PHY_SYNTH_CONTROL
);
93 if (freq
< 4800) { /* 2 GHz, fractional mode */
100 channelSel
= (freq
* 0x10000) / 15;
102 if (AR_SREV_9287_11_OR_LATER(ah
)) {
104 /* Enable channel spreading for channel 14 */
105 REG_WRITE_ARRAY(&ah
->iniCckfirJapan2484
,
108 REG_WRITE_ARRAY(&ah
->iniCckfirNormal
,
112 txctl
= REG_READ(ah
, AR_PHY_CCK_TX_CTRL
);
114 /* Enable channel spreading for channel 14 */
115 REG_WRITE(ah
, AR_PHY_CCK_TX_CTRL
,
116 txctl
| AR_PHY_CCK_TX_CTRL_JAPAN
);
118 REG_WRITE(ah
, AR_PHY_CCK_TX_CTRL
,
119 txctl
&~ AR_PHY_CCK_TX_CTRL_JAPAN
);
126 switch(ah
->eep_ops
->get_eeprom(ah
, EEP_FRAC_N_5G
)) {
128 if ((freq
% 20) == 0) {
130 } else if ((freq
% 10) == 0) {
139 * Enable 2G (fractional) mode for channels
140 * which are 5MHz spaced.
144 channelSel
= (freq
* 0x8000) / 15;
146 /* RefDivA setting */
147 REG_RMW_FIELD(ah
, AR_AN_SYNTH9
,
148 AR_AN_SYNTH9_REFDIVA
, refDivA
);
153 ndiv
= (freq
* (refDivA
>> aModeRefSel
)) / 60;
154 channelSel
= ndiv
& 0x1ff;
155 channelFrac
= (ndiv
& 0xfffffe00) * 2;
156 channelSel
= (channelSel
<< 17) | channelFrac
;
162 (fracMode
<< 28) | (aModeRefSel
<< 26) | (channelSel
);
164 REG_WRITE(ah
, AR_PHY_SYNTH_CONTROL
, reg32
);
167 ah
->curchan_rad_index
= -1;
173 * ath9k_hw_9280_spur_mitigate - convert baseband spur frequency
174 * @ah: atheros hardware structure
177 * For single-chip solutions. Converts to baseband spur frequency given the
178 * input channel frequency and compute register settings below.
180 void ath9k_hw_9280_spur_mitigate(struct ath_hw
*ah
, struct ath9k_channel
*chan
)
182 int bb_spur
= AR_NO_SPUR
;
185 int bb_spur_off
, spur_subchannel_sd
;
187 int spur_delta_phase
;
189 int upper
, lower
, cur_vit_mask
;
192 int pilot_mask_reg
[4] = { AR_PHY_TIMING7
, AR_PHY_TIMING8
,
193 AR_PHY_PILOT_MASK_01_30
, AR_PHY_PILOT_MASK_31_60
195 int chan_mask_reg
[4] = { AR_PHY_TIMING9
, AR_PHY_TIMING10
,
196 AR_PHY_CHANNEL_MASK_01_30
, AR_PHY_CHANNEL_MASK_31_60
198 int inc
[4] = { 0, 100, 0, 0 };
199 struct chan_centers centers
;
206 bool is2GHz
= IS_CHAN_2GHZ(chan
);
208 memset(&mask_m
, 0, sizeof(int8_t) * 123);
209 memset(&mask_p
, 0, sizeof(int8_t) * 123);
211 ath9k_hw_get_channel_centers(ah
, chan
, ¢ers
);
212 freq
= centers
.synth_center
;
214 ah
->config
.spurmode
= SPUR_ENABLE_EEPROM
;
215 for (i
= 0; i
< AR_EEPROM_MODAL_SPURS
; i
++) {
216 cur_bb_spur
= ah
->eep_ops
->get_spur_channel(ah
, i
, is2GHz
);
219 cur_bb_spur
= (cur_bb_spur
/ 10) + AR_BASE_FREQ_2GHZ
;
221 cur_bb_spur
= (cur_bb_spur
/ 10) + AR_BASE_FREQ_5GHZ
;
223 if (AR_NO_SPUR
== cur_bb_spur
)
225 cur_bb_spur
= cur_bb_spur
- freq
;
227 if (IS_CHAN_HT40(chan
)) {
228 if ((cur_bb_spur
> -AR_SPUR_FEEQ_BOUND_HT40
) &&
229 (cur_bb_spur
< AR_SPUR_FEEQ_BOUND_HT40
)) {
230 bb_spur
= cur_bb_spur
;
233 } else if ((cur_bb_spur
> -AR_SPUR_FEEQ_BOUND_HT20
) &&
234 (cur_bb_spur
< AR_SPUR_FEEQ_BOUND_HT20
)) {
235 bb_spur
= cur_bb_spur
;
240 if (AR_NO_SPUR
== bb_spur
) {
241 REG_CLR_BIT(ah
, AR_PHY_FORCE_CLKEN_CCK
,
242 AR_PHY_FORCE_CLKEN_CCK_MRC_MUX
);
245 REG_CLR_BIT(ah
, AR_PHY_FORCE_CLKEN_CCK
,
246 AR_PHY_FORCE_CLKEN_CCK_MRC_MUX
);
251 tmp
= REG_READ(ah
, AR_PHY_TIMING_CTRL4(0));
253 newVal
= tmp
| (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI
|
254 AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER
|
255 AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK
|
256 AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK
);
257 REG_WRITE(ah
, AR_PHY_TIMING_CTRL4(0), newVal
);
259 newVal
= (AR_PHY_SPUR_REG_MASK_RATE_CNTL
|
260 AR_PHY_SPUR_REG_ENABLE_MASK_PPM
|
261 AR_PHY_SPUR_REG_MASK_RATE_SELECT
|
262 AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI
|
263 SM(SPUR_RSSI_THRESH
, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH
));
264 REG_WRITE(ah
, AR_PHY_SPUR_REG
, newVal
);
266 if (IS_CHAN_HT40(chan
)) {
268 spur_subchannel_sd
= 1;
269 bb_spur_off
= bb_spur
+ 10;
271 spur_subchannel_sd
= 0;
272 bb_spur_off
= bb_spur
- 10;
275 spur_subchannel_sd
= 0;
276 bb_spur_off
= bb_spur
;
279 if (IS_CHAN_HT40(chan
))
281 ((bb_spur
* 262144) /
282 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE
;
285 ((bb_spur
* 524288) /
286 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE
;
288 denominator
= IS_CHAN_2GHZ(chan
) ? 44 : 40;
289 spur_freq_sd
= ((bb_spur_off
* 2048) / denominator
) & 0x3ff;
291 newVal
= (AR_PHY_TIMING11_USE_SPUR_IN_AGC
|
292 SM(spur_freq_sd
, AR_PHY_TIMING11_SPUR_FREQ_SD
) |
293 SM(spur_delta_phase
, AR_PHY_TIMING11_SPUR_DELTA_PHASE
));
294 REG_WRITE(ah
, AR_PHY_TIMING11
, newVal
);
296 newVal
= spur_subchannel_sd
<< AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S
;
297 REG_WRITE(ah
, AR_PHY_SFCORR_EXT
, newVal
);
303 for (i
= 0; i
< 4; i
++) {
307 for (bp
= 0; bp
< 30; bp
++) {
308 if ((cur_bin
> lower
) && (cur_bin
< upper
)) {
309 pilot_mask
= pilot_mask
| 0x1 << bp
;
310 chan_mask
= chan_mask
| 0x1 << bp
;
315 REG_WRITE(ah
, pilot_mask_reg
[i
], pilot_mask
);
316 REG_WRITE(ah
, chan_mask_reg
[i
], chan_mask
);
323 for (i
= 0; i
< 123; i
++) {
324 if ((cur_vit_mask
> lower
) && (cur_vit_mask
< upper
)) {
326 /* workaround for gcc bug #37014 */
327 volatile int tmp_v
= abs(cur_vit_mask
- bin
);
333 if (cur_vit_mask
< 0)
334 mask_m
[abs(cur_vit_mask
/ 100)] = mask_amt
;
336 mask_p
[cur_vit_mask
/ 100] = mask_amt
;
341 tmp_mask
= (mask_m
[46] << 30) | (mask_m
[47] << 28)
342 | (mask_m
[48] << 26) | (mask_m
[49] << 24)
343 | (mask_m
[50] << 22) | (mask_m
[51] << 20)
344 | (mask_m
[52] << 18) | (mask_m
[53] << 16)
345 | (mask_m
[54] << 14) | (mask_m
[55] << 12)
346 | (mask_m
[56] << 10) | (mask_m
[57] << 8)
347 | (mask_m
[58] << 6) | (mask_m
[59] << 4)
348 | (mask_m
[60] << 2) | (mask_m
[61] << 0);
349 REG_WRITE(ah
, AR_PHY_BIN_MASK_1
, tmp_mask
);
350 REG_WRITE(ah
, AR_PHY_VIT_MASK2_M_46_61
, tmp_mask
);
352 tmp_mask
= (mask_m
[31] << 28)
353 | (mask_m
[32] << 26) | (mask_m
[33] << 24)
354 | (mask_m
[34] << 22) | (mask_m
[35] << 20)
355 | (mask_m
[36] << 18) | (mask_m
[37] << 16)
356 | (mask_m
[48] << 14) | (mask_m
[39] << 12)
357 | (mask_m
[40] << 10) | (mask_m
[41] << 8)
358 | (mask_m
[42] << 6) | (mask_m
[43] << 4)
359 | (mask_m
[44] << 2) | (mask_m
[45] << 0);
360 REG_WRITE(ah
, AR_PHY_BIN_MASK_2
, tmp_mask
);
361 REG_WRITE(ah
, AR_PHY_MASK2_M_31_45
, tmp_mask
);
363 tmp_mask
= (mask_m
[16] << 30) | (mask_m
[16] << 28)
364 | (mask_m
[18] << 26) | (mask_m
[18] << 24)
365 | (mask_m
[20] << 22) | (mask_m
[20] << 20)
366 | (mask_m
[22] << 18) | (mask_m
[22] << 16)
367 | (mask_m
[24] << 14) | (mask_m
[24] << 12)
368 | (mask_m
[25] << 10) | (mask_m
[26] << 8)
369 | (mask_m
[27] << 6) | (mask_m
[28] << 4)
370 | (mask_m
[29] << 2) | (mask_m
[30] << 0);
371 REG_WRITE(ah
, AR_PHY_BIN_MASK_3
, tmp_mask
);
372 REG_WRITE(ah
, AR_PHY_MASK2_M_16_30
, tmp_mask
);
374 tmp_mask
= (mask_m
[0] << 30) | (mask_m
[1] << 28)
375 | (mask_m
[2] << 26) | (mask_m
[3] << 24)
376 | (mask_m
[4] << 22) | (mask_m
[5] << 20)
377 | (mask_m
[6] << 18) | (mask_m
[7] << 16)
378 | (mask_m
[8] << 14) | (mask_m
[9] << 12)
379 | (mask_m
[10] << 10) | (mask_m
[11] << 8)
380 | (mask_m
[12] << 6) | (mask_m
[13] << 4)
381 | (mask_m
[14] << 2) | (mask_m
[15] << 0);
382 REG_WRITE(ah
, AR_PHY_MASK_CTL
, tmp_mask
);
383 REG_WRITE(ah
, AR_PHY_MASK2_M_00_15
, tmp_mask
);
385 tmp_mask
= (mask_p
[15] << 28)
386 | (mask_p
[14] << 26) | (mask_p
[13] << 24)
387 | (mask_p
[12] << 22) | (mask_p
[11] << 20)
388 | (mask_p
[10] << 18) | (mask_p
[9] << 16)
389 | (mask_p
[8] << 14) | (mask_p
[7] << 12)
390 | (mask_p
[6] << 10) | (mask_p
[5] << 8)
391 | (mask_p
[4] << 6) | (mask_p
[3] << 4)
392 | (mask_p
[2] << 2) | (mask_p
[1] << 0);
393 REG_WRITE(ah
, AR_PHY_BIN_MASK2_1
, tmp_mask
);
394 REG_WRITE(ah
, AR_PHY_MASK2_P_15_01
, tmp_mask
);
396 tmp_mask
= (mask_p
[30] << 28)
397 | (mask_p
[29] << 26) | (mask_p
[28] << 24)
398 | (mask_p
[27] << 22) | (mask_p
[26] << 20)
399 | (mask_p
[25] << 18) | (mask_p
[24] << 16)
400 | (mask_p
[23] << 14) | (mask_p
[22] << 12)
401 | (mask_p
[21] << 10) | (mask_p
[20] << 8)
402 | (mask_p
[19] << 6) | (mask_p
[18] << 4)
403 | (mask_p
[17] << 2) | (mask_p
[16] << 0);
404 REG_WRITE(ah
, AR_PHY_BIN_MASK2_2
, tmp_mask
);
405 REG_WRITE(ah
, AR_PHY_MASK2_P_30_16
, tmp_mask
);
407 tmp_mask
= (mask_p
[45] << 28)
408 | (mask_p
[44] << 26) | (mask_p
[43] << 24)
409 | (mask_p
[42] << 22) | (mask_p
[41] << 20)
410 | (mask_p
[40] << 18) | (mask_p
[39] << 16)
411 | (mask_p
[38] << 14) | (mask_p
[37] << 12)
412 | (mask_p
[36] << 10) | (mask_p
[35] << 8)
413 | (mask_p
[34] << 6) | (mask_p
[33] << 4)
414 | (mask_p
[32] << 2) | (mask_p
[31] << 0);
415 REG_WRITE(ah
, AR_PHY_BIN_MASK2_3
, tmp_mask
);
416 REG_WRITE(ah
, AR_PHY_MASK2_P_45_31
, tmp_mask
);
418 tmp_mask
= (mask_p
[61] << 30) | (mask_p
[60] << 28)
419 | (mask_p
[59] << 26) | (mask_p
[58] << 24)
420 | (mask_p
[57] << 22) | (mask_p
[56] << 20)
421 | (mask_p
[55] << 18) | (mask_p
[54] << 16)
422 | (mask_p
[53] << 14) | (mask_p
[52] << 12)
423 | (mask_p
[51] << 10) | (mask_p
[50] << 8)
424 | (mask_p
[49] << 6) | (mask_p
[48] << 4)
425 | (mask_p
[47] << 2) | (mask_p
[46] << 0);
426 REG_WRITE(ah
, AR_PHY_BIN_MASK2_4
, tmp_mask
);
427 REG_WRITE(ah
, AR_PHY_MASK2_P_61_45
, tmp_mask
);
430 /* All code below is for non single-chip solutions */
433 * ath9k_phy_modify_rx_buffer() - perform analog swizzling of parameters
440 * Performs analog "swizzling" of parameters into their location.
441 * Used on external AR2133/AR5133 radios.
443 static void ath9k_phy_modify_rx_buffer(u32
*rfBuf
, u32 reg32
,
444 u32 numBits
, u32 firstBit
,
447 u32 tmp32
, mask
, arrayEntry
, lastBit
;
448 int32_t bitPosition
, bitsLeft
;
450 tmp32
= ath9k_hw_reverse_bits(reg32
, numBits
);
451 arrayEntry
= (firstBit
- 1) / 8;
452 bitPosition
= (firstBit
- 1) % 8;
454 while (bitsLeft
> 0) {
455 lastBit
= (bitPosition
+ bitsLeft
> 8) ?
456 8 : bitPosition
+ bitsLeft
;
457 mask
= (((1 << lastBit
) - 1) ^ ((1 << bitPosition
) - 1)) <<
459 rfBuf
[arrayEntry
] &= ~mask
;
460 rfBuf
[arrayEntry
] |= ((tmp32
<< bitPosition
) <<
461 (column
* 8)) & mask
;
462 bitsLeft
-= 8 - bitPosition
;
463 tmp32
= tmp32
>> (8 - bitPosition
);
470 * Fix on 2.4 GHz band for orientation sensitivity issue by increasing
476 * if synth_freq < 2412
478 * else if 2412 <= synth_freq <= 2422
480 * else // synth_freq > 2422
482 * else if forceBias > 0
483 * bias = forceBias & 7
485 * no change, use value from ini file
487 * no change, invalid band
490 * 2422 also uses value of 2
494 * Less than 2412 uses value of 0, 2412 and above uses value of 2
496 static void ath9k_hw_force_bias(struct ath_hw
*ah
, u16 synth_freq
)
498 struct ath_common
*common
= ath9k_hw_common(ah
);
503 if (!AR_SREV_5416(ah
) || synth_freq
>= 3000) {
507 BUG_ON(AR_SREV_9280_10_OR_LATER(ah
));
509 if (synth_freq
< 2412)
511 else if (synth_freq
< 2422)
516 /* pre-reverse this field */
517 tmp_reg
= ath9k_hw_reverse_bits(new_bias
, 3);
519 ath_print(common
, ATH_DBG_CONFIG
,
520 "Force rf_pwd_icsyndiv to %1d on %4d\n",
521 new_bias
, synth_freq
);
523 /* swizzle rf_pwd_icsyndiv */
524 ath9k_phy_modify_rx_buffer(ah
->analogBank6Data
, tmp_reg
, 3, 181, 3);
526 /* write Bank 6 with new params */
527 REG_WRITE_RF_ARRAY(&ah
->iniBank6
, ah
->analogBank6Data
, reg_writes
);
531 * ath9k_hw_set_channel - tune to a channel on the external AR2133/AR5133 radios
532 * @ah: atheros hardware stucture
535 * For the external AR2133/AR5133 radios, takes the MHz channel value and set
536 * the channel value. Assumes writes enabled to analog bus and bank6 register
537 * cache in ah->analogBank6Data.
539 int ath9k_hw_set_channel(struct ath_hw
*ah
, struct ath9k_channel
*chan
)
541 struct ath_common
*common
= ath9k_hw_common(ah
);
547 struct chan_centers centers
;
549 ath9k_hw_get_channel_centers(ah
, chan
, ¢ers
);
550 freq
= centers
.synth_center
;
555 if (((freq
- 2192) % 5) == 0) {
556 channelSel
= ((freq
- 672) * 2 - 3040) / 10;
558 } else if (((freq
- 2224) % 5) == 0) {
559 channelSel
= ((freq
- 704) * 2 - 3040) / 10;
562 ath_print(common
, ATH_DBG_FATAL
,
563 "Invalid channel %u MHz\n", freq
);
567 channelSel
= (channelSel
<< 2) & 0xff;
568 channelSel
= ath9k_hw_reverse_bits(channelSel
, 8);
570 txctl
= REG_READ(ah
, AR_PHY_CCK_TX_CTRL
);
573 REG_WRITE(ah
, AR_PHY_CCK_TX_CTRL
,
574 txctl
| AR_PHY_CCK_TX_CTRL_JAPAN
);
576 REG_WRITE(ah
, AR_PHY_CCK_TX_CTRL
,
577 txctl
& ~AR_PHY_CCK_TX_CTRL_JAPAN
);
580 } else if ((freq
% 20) == 0 && freq
>= 5120) {
582 ath9k_hw_reverse_bits(((freq
- 4800) / 20 << 2), 8);
583 aModeRefSel
= ath9k_hw_reverse_bits(1, 2);
584 } else if ((freq
% 10) == 0) {
586 ath9k_hw_reverse_bits(((freq
- 4800) / 10 << 1), 8);
587 if (AR_SREV_9100(ah
) || AR_SREV_9160_10_OR_LATER(ah
))
588 aModeRefSel
= ath9k_hw_reverse_bits(2, 2);
590 aModeRefSel
= ath9k_hw_reverse_bits(1, 2);
591 } else if ((freq
% 5) == 0) {
592 channelSel
= ath9k_hw_reverse_bits((freq
- 4800) / 5, 8);
593 aModeRefSel
= ath9k_hw_reverse_bits(1, 2);
595 ath_print(common
, ATH_DBG_FATAL
,
596 "Invalid channel %u MHz\n", freq
);
600 ath9k_hw_force_bias(ah
, freq
);
603 (channelSel
<< 8) | (aModeRefSel
<< 2) | (bModeSynth
<< 1) |
606 REG_WRITE(ah
, AR_PHY(0x37), reg32
);
609 ah
->curchan_rad_index
= -1;
615 * ath9k_hw_spur_mitigate - convert baseband spur frequency for external radios
616 * @ah: atheros hardware structure
619 * For non single-chip solutions. Converts to baseband spur frequency given the
620 * input channel frequency and compute register settings below.
622 void ath9k_hw_spur_mitigate(struct ath_hw
*ah
, struct ath9k_channel
*chan
)
624 int bb_spur
= AR_NO_SPUR
;
627 int spur_delta_phase
;
629 int upper
, lower
, cur_vit_mask
;
632 int pilot_mask_reg
[4] = { AR_PHY_TIMING7
, AR_PHY_TIMING8
,
633 AR_PHY_PILOT_MASK_01_30
, AR_PHY_PILOT_MASK_31_60
635 int chan_mask_reg
[4] = { AR_PHY_TIMING9
, AR_PHY_TIMING10
,
636 AR_PHY_CHANNEL_MASK_01_30
, AR_PHY_CHANNEL_MASK_31_60
638 int inc
[4] = { 0, 100, 0, 0 };
645 bool is2GHz
= IS_CHAN_2GHZ(chan
);
647 memset(&mask_m
, 0, sizeof(int8_t) * 123);
648 memset(&mask_p
, 0, sizeof(int8_t) * 123);
650 for (i
= 0; i
< AR_EEPROM_MODAL_SPURS
; i
++) {
651 cur_bb_spur
= ah
->eep_ops
->get_spur_channel(ah
, i
, is2GHz
);
652 if (AR_NO_SPUR
== cur_bb_spur
)
654 cur_bb_spur
= cur_bb_spur
- (chan
->channel
* 10);
655 if ((cur_bb_spur
> -95) && (cur_bb_spur
< 95)) {
656 bb_spur
= cur_bb_spur
;
661 if (AR_NO_SPUR
== bb_spur
)
666 tmp
= REG_READ(ah
, AR_PHY_TIMING_CTRL4(0));
667 new = tmp
| (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI
|
668 AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER
|
669 AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK
|
670 AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK
);
672 REG_WRITE(ah
, AR_PHY_TIMING_CTRL4(0), new);
674 new = (AR_PHY_SPUR_REG_MASK_RATE_CNTL
|
675 AR_PHY_SPUR_REG_ENABLE_MASK_PPM
|
676 AR_PHY_SPUR_REG_MASK_RATE_SELECT
|
677 AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI
|
678 SM(SPUR_RSSI_THRESH
, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH
));
679 REG_WRITE(ah
, AR_PHY_SPUR_REG
, new);
681 spur_delta_phase
= ((bb_spur
* 524288) / 100) &
682 AR_PHY_TIMING11_SPUR_DELTA_PHASE
;
684 denominator
= IS_CHAN_2GHZ(chan
) ? 440 : 400;
685 spur_freq_sd
= ((bb_spur
* 2048) / denominator
) & 0x3ff;
687 new = (AR_PHY_TIMING11_USE_SPUR_IN_AGC
|
688 SM(spur_freq_sd
, AR_PHY_TIMING11_SPUR_FREQ_SD
) |
689 SM(spur_delta_phase
, AR_PHY_TIMING11_SPUR_DELTA_PHASE
));
690 REG_WRITE(ah
, AR_PHY_TIMING11
, new);
696 for (i
= 0; i
< 4; i
++) {
700 for (bp
= 0; bp
< 30; bp
++) {
701 if ((cur_bin
> lower
) && (cur_bin
< upper
)) {
702 pilot_mask
= pilot_mask
| 0x1 << bp
;
703 chan_mask
= chan_mask
| 0x1 << bp
;
708 REG_WRITE(ah
, pilot_mask_reg
[i
], pilot_mask
);
709 REG_WRITE(ah
, chan_mask_reg
[i
], chan_mask
);
716 for (i
= 0; i
< 123; i
++) {
717 if ((cur_vit_mask
> lower
) && (cur_vit_mask
< upper
)) {
719 /* workaround for gcc bug #37014 */
720 volatile int tmp_v
= abs(cur_vit_mask
- bin
);
726 if (cur_vit_mask
< 0)
727 mask_m
[abs(cur_vit_mask
/ 100)] = mask_amt
;
729 mask_p
[cur_vit_mask
/ 100] = mask_amt
;
734 tmp_mask
= (mask_m
[46] << 30) | (mask_m
[47] << 28)
735 | (mask_m
[48] << 26) | (mask_m
[49] << 24)
736 | (mask_m
[50] << 22) | (mask_m
[51] << 20)
737 | (mask_m
[52] << 18) | (mask_m
[53] << 16)
738 | (mask_m
[54] << 14) | (mask_m
[55] << 12)
739 | (mask_m
[56] << 10) | (mask_m
[57] << 8)
740 | (mask_m
[58] << 6) | (mask_m
[59] << 4)
741 | (mask_m
[60] << 2) | (mask_m
[61] << 0);
742 REG_WRITE(ah
, AR_PHY_BIN_MASK_1
, tmp_mask
);
743 REG_WRITE(ah
, AR_PHY_VIT_MASK2_M_46_61
, tmp_mask
);
745 tmp_mask
= (mask_m
[31] << 28)
746 | (mask_m
[32] << 26) | (mask_m
[33] << 24)
747 | (mask_m
[34] << 22) | (mask_m
[35] << 20)
748 | (mask_m
[36] << 18) | (mask_m
[37] << 16)
749 | (mask_m
[48] << 14) | (mask_m
[39] << 12)
750 | (mask_m
[40] << 10) | (mask_m
[41] << 8)
751 | (mask_m
[42] << 6) | (mask_m
[43] << 4)
752 | (mask_m
[44] << 2) | (mask_m
[45] << 0);
753 REG_WRITE(ah
, AR_PHY_BIN_MASK_2
, tmp_mask
);
754 REG_WRITE(ah
, AR_PHY_MASK2_M_31_45
, tmp_mask
);
756 tmp_mask
= (mask_m
[16] << 30) | (mask_m
[16] << 28)
757 | (mask_m
[18] << 26) | (mask_m
[18] << 24)
758 | (mask_m
[20] << 22) | (mask_m
[20] << 20)
759 | (mask_m
[22] << 18) | (mask_m
[22] << 16)
760 | (mask_m
[24] << 14) | (mask_m
[24] << 12)
761 | (mask_m
[25] << 10) | (mask_m
[26] << 8)
762 | (mask_m
[27] << 6) | (mask_m
[28] << 4)
763 | (mask_m
[29] << 2) | (mask_m
[30] << 0);
764 REG_WRITE(ah
, AR_PHY_BIN_MASK_3
, tmp_mask
);
765 REG_WRITE(ah
, AR_PHY_MASK2_M_16_30
, tmp_mask
);
767 tmp_mask
= (mask_m
[0] << 30) | (mask_m
[1] << 28)
768 | (mask_m
[2] << 26) | (mask_m
[3] << 24)
769 | (mask_m
[4] << 22) | (mask_m
[5] << 20)
770 | (mask_m
[6] << 18) | (mask_m
[7] << 16)
771 | (mask_m
[8] << 14) | (mask_m
[9] << 12)
772 | (mask_m
[10] << 10) | (mask_m
[11] << 8)
773 | (mask_m
[12] << 6) | (mask_m
[13] << 4)
774 | (mask_m
[14] << 2) | (mask_m
[15] << 0);
775 REG_WRITE(ah
, AR_PHY_MASK_CTL
, tmp_mask
);
776 REG_WRITE(ah
, AR_PHY_MASK2_M_00_15
, tmp_mask
);
778 tmp_mask
= (mask_p
[15] << 28)
779 | (mask_p
[14] << 26) | (mask_p
[13] << 24)
780 | (mask_p
[12] << 22) | (mask_p
[11] << 20)
781 | (mask_p
[10] << 18) | (mask_p
[9] << 16)
782 | (mask_p
[8] << 14) | (mask_p
[7] << 12)
783 | (mask_p
[6] << 10) | (mask_p
[5] << 8)
784 | (mask_p
[4] << 6) | (mask_p
[3] << 4)
785 | (mask_p
[2] << 2) | (mask_p
[1] << 0);
786 REG_WRITE(ah
, AR_PHY_BIN_MASK2_1
, tmp_mask
);
787 REG_WRITE(ah
, AR_PHY_MASK2_P_15_01
, tmp_mask
);
789 tmp_mask
= (mask_p
[30] << 28)
790 | (mask_p
[29] << 26) | (mask_p
[28] << 24)
791 | (mask_p
[27] << 22) | (mask_p
[26] << 20)
792 | (mask_p
[25] << 18) | (mask_p
[24] << 16)
793 | (mask_p
[23] << 14) | (mask_p
[22] << 12)
794 | (mask_p
[21] << 10) | (mask_p
[20] << 8)
795 | (mask_p
[19] << 6) | (mask_p
[18] << 4)
796 | (mask_p
[17] << 2) | (mask_p
[16] << 0);
797 REG_WRITE(ah
, AR_PHY_BIN_MASK2_2
, tmp_mask
);
798 REG_WRITE(ah
, AR_PHY_MASK2_P_30_16
, tmp_mask
);
800 tmp_mask
= (mask_p
[45] << 28)
801 | (mask_p
[44] << 26) | (mask_p
[43] << 24)
802 | (mask_p
[42] << 22) | (mask_p
[41] << 20)
803 | (mask_p
[40] << 18) | (mask_p
[39] << 16)
804 | (mask_p
[38] << 14) | (mask_p
[37] << 12)
805 | (mask_p
[36] << 10) | (mask_p
[35] << 8)
806 | (mask_p
[34] << 6) | (mask_p
[33] << 4)
807 | (mask_p
[32] << 2) | (mask_p
[31] << 0);
808 REG_WRITE(ah
, AR_PHY_BIN_MASK2_3
, tmp_mask
);
809 REG_WRITE(ah
, AR_PHY_MASK2_P_45_31
, tmp_mask
);
811 tmp_mask
= (mask_p
[61] << 30) | (mask_p
[60] << 28)
812 | (mask_p
[59] << 26) | (mask_p
[58] << 24)
813 | (mask_p
[57] << 22) | (mask_p
[56] << 20)
814 | (mask_p
[55] << 18) | (mask_p
[54] << 16)
815 | (mask_p
[53] << 14) | (mask_p
[52] << 12)
816 | (mask_p
[51] << 10) | (mask_p
[50] << 8)
817 | (mask_p
[49] << 6) | (mask_p
[48] << 4)
818 | (mask_p
[47] << 2) | (mask_p
[46] << 0);
819 REG_WRITE(ah
, AR_PHY_BIN_MASK2_4
, tmp_mask
);
820 REG_WRITE(ah
, AR_PHY_MASK2_P_61_45
, tmp_mask
);
824 * ath9k_hw_rf_alloc_ext_banks - allocates banks for external radio programming
825 * @ah: atheros hardware structure
827 * Only required for older devices with external AR2133/AR5133 radios.
829 int ath9k_hw_rf_alloc_ext_banks(struct ath_hw
*ah
)
831 #define ATH_ALLOC_BANK(bank, size) do { \
832 bank = kzalloc((sizeof(u32) * size), GFP_KERNEL); \
834 ath_print(common, ATH_DBG_FATAL, \
835 "Cannot allocate RF banks\n"); \
840 struct ath_common
*common
= ath9k_hw_common(ah
);
842 BUG_ON(AR_SREV_9280_10_OR_LATER(ah
));
844 ATH_ALLOC_BANK(ah
->analogBank0Data
, ah
->iniBank0
.ia_rows
);
845 ATH_ALLOC_BANK(ah
->analogBank1Data
, ah
->iniBank1
.ia_rows
);
846 ATH_ALLOC_BANK(ah
->analogBank2Data
, ah
->iniBank2
.ia_rows
);
847 ATH_ALLOC_BANK(ah
->analogBank3Data
, ah
->iniBank3
.ia_rows
);
848 ATH_ALLOC_BANK(ah
->analogBank6Data
, ah
->iniBank6
.ia_rows
);
849 ATH_ALLOC_BANK(ah
->analogBank6TPCData
, ah
->iniBank6TPC
.ia_rows
);
850 ATH_ALLOC_BANK(ah
->analogBank7Data
, ah
->iniBank7
.ia_rows
);
851 ATH_ALLOC_BANK(ah
->addac5416_21
,
852 ah
->iniAddac
.ia_rows
* ah
->iniAddac
.ia_columns
);
853 ATH_ALLOC_BANK(ah
->bank6Temp
, ah
->iniBank6
.ia_rows
);
856 #undef ATH_ALLOC_BANK
861 * ath9k_hw_rf_free_ext_banks - Free memory for analog bank scratch buffers
862 * @ah: atheros hardware struture
863 * For the external AR2133/AR5133 radios banks.
866 ath9k_hw_rf_free_ext_banks(struct ath_hw
*ah
)
868 #define ATH_FREE_BANK(bank) do { \
873 BUG_ON(AR_SREV_9280_10_OR_LATER(ah
));
875 ATH_FREE_BANK(ah
->analogBank0Data
);
876 ATH_FREE_BANK(ah
->analogBank1Data
);
877 ATH_FREE_BANK(ah
->analogBank2Data
);
878 ATH_FREE_BANK(ah
->analogBank3Data
);
879 ATH_FREE_BANK(ah
->analogBank6Data
);
880 ATH_FREE_BANK(ah
->analogBank6TPCData
);
881 ATH_FREE_BANK(ah
->analogBank7Data
);
882 ATH_FREE_BANK(ah
->addac5416_21
);
883 ATH_FREE_BANK(ah
->bank6Temp
);
889 * ath9k_hw_set_rf_regs - programs rf registers based on EEPROM
890 * @ah: atheros hardware structure
894 * Used for the external AR2133/AR5133 radios.
896 * Reads the EEPROM header info from the device structure and programs
897 * all rf registers. This routine requires access to the analog
898 * rf device. This is not required for single-chip devices.
900 bool ath9k_hw_set_rf_regs(struct ath_hw
*ah
, struct ath9k_channel
*chan
,
904 u32 ob5GHz
= 0, db5GHz
= 0;
905 u32 ob2GHz
= 0, db2GHz
= 0;
909 * Software does not need to program bank data
910 * for single chip devices, that is AR9280 or anything
913 if (AR_SREV_9280_10_OR_LATER(ah
))
916 /* Setup rf parameters */
917 eepMinorRev
= ah
->eep_ops
->get_eeprom(ah
, EEP_MINOR_REV
);
919 /* Setup Bank 0 Write */
920 RF_BANK_SETUP(ah
->analogBank0Data
, &ah
->iniBank0
, 1);
922 /* Setup Bank 1 Write */
923 RF_BANK_SETUP(ah
->analogBank1Data
, &ah
->iniBank1
, 1);
925 /* Setup Bank 2 Write */
926 RF_BANK_SETUP(ah
->analogBank2Data
, &ah
->iniBank2
, 1);
928 /* Setup Bank 6 Write */
929 RF_BANK_SETUP(ah
->analogBank3Data
, &ah
->iniBank3
,
933 for (i
= 0; i
< ah
->iniBank6TPC
.ia_rows
; i
++) {
934 ah
->analogBank6Data
[i
] =
935 INI_RA(&ah
->iniBank6TPC
, i
, modesIndex
);
939 /* Only the 5 or 2 GHz OB/DB need to be set for a mode */
940 if (eepMinorRev
>= 2) {
941 if (IS_CHAN_2GHZ(chan
)) {
942 ob2GHz
= ah
->eep_ops
->get_eeprom(ah
, EEP_OB_2
);
943 db2GHz
= ah
->eep_ops
->get_eeprom(ah
, EEP_DB_2
);
944 ath9k_phy_modify_rx_buffer(ah
->analogBank6Data
,
946 ath9k_phy_modify_rx_buffer(ah
->analogBank6Data
,
949 ob5GHz
= ah
->eep_ops
->get_eeprom(ah
, EEP_OB_5
);
950 db5GHz
= ah
->eep_ops
->get_eeprom(ah
, EEP_DB_5
);
951 ath9k_phy_modify_rx_buffer(ah
->analogBank6Data
,
953 ath9k_phy_modify_rx_buffer(ah
->analogBank6Data
,
958 /* Setup Bank 7 Setup */
959 RF_BANK_SETUP(ah
->analogBank7Data
, &ah
->iniBank7
, 1);
961 /* Write Analog registers */
962 REG_WRITE_RF_ARRAY(&ah
->iniBank0
, ah
->analogBank0Data
,
964 REG_WRITE_RF_ARRAY(&ah
->iniBank1
, ah
->analogBank1Data
,
966 REG_WRITE_RF_ARRAY(&ah
->iniBank2
, ah
->analogBank2Data
,
968 REG_WRITE_RF_ARRAY(&ah
->iniBank3
, ah
->analogBank3Data
,
970 REG_WRITE_RF_ARRAY(&ah
->iniBank6TPC
, ah
->analogBank6Data
,
972 REG_WRITE_RF_ARRAY(&ah
->iniBank7
, ah
->analogBank7Data
,