blob: bde162f128aba6c70100c1dbd8d1c979061e0411 [file] [log] [blame]
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001/*
2 * Copyright (c) 2008 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 <linux/io.h>
18#include <asm/unaligned.h>
19
20#include "core.h"
21#include "hw.h"
22#include "reg.h"
23#include "phy.h"
24#include "initvals.h"
25
26static void ath9k_hw_iqcal_collect(struct ath_hal *ah);
27static void ath9k_hw_iqcalibrate(struct ath_hal *ah, u8 numChains);
28static void ath9k_hw_adc_gaincal_collect(struct ath_hal *ah);
29static void ath9k_hw_adc_gaincal_calibrate(struct ath_hal *ah,
30 u8 numChains);
31static void ath9k_hw_adc_dccal_collect(struct ath_hal *ah);
32static void ath9k_hw_adc_dccal_calibrate(struct ath_hal *ah,
33 u8 numChains);
34
35static const u8 CLOCK_RATE[] = { 40, 80, 22, 44, 88, 40 };
36static const int16_t NOISE_FLOOR[] = { -96, -93, -98, -96, -93, -96 };
37
38static const struct hal_percal_data iq_cal_multi_sample = {
39 IQ_MISMATCH_CAL,
40 MAX_CAL_SAMPLES,
41 PER_MIN_LOG_COUNT,
42 ath9k_hw_iqcal_collect,
43 ath9k_hw_iqcalibrate
44};
45static const struct hal_percal_data iq_cal_single_sample = {
46 IQ_MISMATCH_CAL,
47 MIN_CAL_SAMPLES,
48 PER_MAX_LOG_COUNT,
49 ath9k_hw_iqcal_collect,
50 ath9k_hw_iqcalibrate
51};
52static const struct hal_percal_data adc_gain_cal_multi_sample = {
53 ADC_GAIN_CAL,
54 MAX_CAL_SAMPLES,
55 PER_MIN_LOG_COUNT,
56 ath9k_hw_adc_gaincal_collect,
57 ath9k_hw_adc_gaincal_calibrate
58};
59static const struct hal_percal_data adc_gain_cal_single_sample = {
60 ADC_GAIN_CAL,
61 MIN_CAL_SAMPLES,
62 PER_MAX_LOG_COUNT,
63 ath9k_hw_adc_gaincal_collect,
64 ath9k_hw_adc_gaincal_calibrate
65};
66static const struct hal_percal_data adc_dc_cal_multi_sample = {
67 ADC_DC_CAL,
68 MAX_CAL_SAMPLES,
69 PER_MIN_LOG_COUNT,
70 ath9k_hw_adc_dccal_collect,
71 ath9k_hw_adc_dccal_calibrate
72};
73static const struct hal_percal_data adc_dc_cal_single_sample = {
74 ADC_DC_CAL,
75 MIN_CAL_SAMPLES,
76 PER_MAX_LOG_COUNT,
77 ath9k_hw_adc_dccal_collect,
78 ath9k_hw_adc_dccal_calibrate
79};
80static const struct hal_percal_data adc_init_dc_cal = {
81 ADC_DC_INIT_CAL,
82 MIN_CAL_SAMPLES,
83 INIT_LOG_COUNT,
84 ath9k_hw_adc_dccal_collect,
85 ath9k_hw_adc_dccal_calibrate
86};
87
88static const struct ath_hal ar5416hal = {
89 AR5416_MAGIC,
90 0,
91 0,
92 NULL,
93 NULL,
94 CTRY_DEFAULT,
95 0,
96 0,
97 0,
98 0,
99 0,
100 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
101 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
102 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
103 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
104 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
105 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
106 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
107 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
108 },
109};
110
111static struct ath9k_rate_table ar5416_11a_table = {
112 8,
113 {0},
114 {
115 {true, PHY_OFDM, 6000, 0x0b, 0x00, (0x80 | 12), 0},
116 {true, PHY_OFDM, 9000, 0x0f, 0x00, 18, 0},
117 {true, PHY_OFDM, 12000, 0x0a, 0x00, (0x80 | 24), 2},
118 {true, PHY_OFDM, 18000, 0x0e, 0x00, 36, 2},
119 {true, PHY_OFDM, 24000, 0x09, 0x00, (0x80 | 48), 4},
120 {true, PHY_OFDM, 36000, 0x0d, 0x00, 72, 4},
121 {true, PHY_OFDM, 48000, 0x08, 0x00, 96, 4},
122 {true, PHY_OFDM, 54000, 0x0c, 0x00, 108, 4}
123 },
124};
125
126static struct ath9k_rate_table ar5416_11b_table = {
127 4,
128 {0},
129 {
130 {true, PHY_CCK, 1000, 0x1b, 0x00, (0x80 | 2), 0},
131 {true, PHY_CCK, 2000, 0x1a, 0x04, (0x80 | 4), 1},
132 {true, PHY_CCK, 5500, 0x19, 0x04, (0x80 | 11), 1},
133 {true, PHY_CCK, 11000, 0x18, 0x04, (0x80 | 22), 1}
134 },
135};
136
137static struct ath9k_rate_table ar5416_11g_table = {
138 12,
139 {0},
140 {
141 {true, PHY_CCK, 1000, 0x1b, 0x00, (0x80 | 2), 0},
142 {true, PHY_CCK, 2000, 0x1a, 0x04, (0x80 | 4), 1},
143 {true, PHY_CCK, 5500, 0x19, 0x04, (0x80 | 11), 2},
144 {true, PHY_CCK, 11000, 0x18, 0x04, (0x80 | 22), 3},
145
146 {false, PHY_OFDM, 6000, 0x0b, 0x00, 12, 4},
147 {false, PHY_OFDM, 9000, 0x0f, 0x00, 18, 4},
148 {true, PHY_OFDM, 12000, 0x0a, 0x00, 24, 6},
149 {true, PHY_OFDM, 18000, 0x0e, 0x00, 36, 6},
150 {true, PHY_OFDM, 24000, 0x09, 0x00, 48, 8},
151 {true, PHY_OFDM, 36000, 0x0d, 0x00, 72, 8},
152 {true, PHY_OFDM, 48000, 0x08, 0x00, 96, 8},
153 {true, PHY_OFDM, 54000, 0x0c, 0x00, 108, 8}
154 },
155};
156
157static struct ath9k_rate_table ar5416_11ng_table = {
158 28,
159 {0},
160 {
161 {true, PHY_CCK, 1000, 0x1b, 0x00, (0x80 | 2), 0},
162 {true, PHY_CCK, 2000, 0x1a, 0x04, (0x80 | 4), 1},
163 {true, PHY_CCK, 5500, 0x19, 0x04, (0x80 | 11), 2},
164 {true, PHY_CCK, 11000, 0x18, 0x04, (0x80 | 22), 3},
165
166 {false, PHY_OFDM, 6000, 0x0b, 0x00, 12, 4},
167 {false, PHY_OFDM, 9000, 0x0f, 0x00, 18, 4},
168 {true, PHY_OFDM, 12000, 0x0a, 0x00, 24, 6},
169 {true, PHY_OFDM, 18000, 0x0e, 0x00, 36, 6},
170 {true, PHY_OFDM, 24000, 0x09, 0x00, 48, 8},
171 {true, PHY_OFDM, 36000, 0x0d, 0x00, 72, 8},
172 {true, PHY_OFDM, 48000, 0x08, 0x00, 96, 8},
173 {true, PHY_OFDM, 54000, 0x0c, 0x00, 108, 8},
174 {true, PHY_HT, 6500, 0x80, 0x00, 0, 4},
175 {true, PHY_HT, 13000, 0x81, 0x00, 1, 6},
176 {true, PHY_HT, 19500, 0x82, 0x00, 2, 6},
177 {true, PHY_HT, 26000, 0x83, 0x00, 3, 8},
178 {true, PHY_HT, 39000, 0x84, 0x00, 4, 8},
179 {true, PHY_HT, 52000, 0x85, 0x00, 5, 8},
180 {true, PHY_HT, 58500, 0x86, 0x00, 6, 8},
181 {true, PHY_HT, 65000, 0x87, 0x00, 7, 8},
182 {true, PHY_HT, 13000, 0x88, 0x00, 8, 4},
183 {true, PHY_HT, 26000, 0x89, 0x00, 9, 6},
184 {true, PHY_HT, 39000, 0x8a, 0x00, 10, 6},
185 {true, PHY_HT, 52000, 0x8b, 0x00, 11, 8},
186 {true, PHY_HT, 78000, 0x8c, 0x00, 12, 8},
187 {true, PHY_HT, 104000, 0x8d, 0x00, 13, 8},
188 {true, PHY_HT, 117000, 0x8e, 0x00, 14, 8},
189 {true, PHY_HT, 130000, 0x8f, 0x00, 15, 8},
190 },
191};
192
193static struct ath9k_rate_table ar5416_11na_table = {
194 24,
195 {0},
196 {
197 {true, PHY_OFDM, 6000, 0x0b, 0x00, (0x80 | 12), 0},
198 {true, PHY_OFDM, 9000, 0x0f, 0x00, 18, 0},
199 {true, PHY_OFDM, 12000, 0x0a, 0x00, (0x80 | 24), 2},
200 {true, PHY_OFDM, 18000, 0x0e, 0x00, 36, 2},
201 {true, PHY_OFDM, 24000, 0x09, 0x00, (0x80 | 48), 4},
202 {true, PHY_OFDM, 36000, 0x0d, 0x00, 72, 4},
203 {true, PHY_OFDM, 48000, 0x08, 0x00, 96, 4},
204 {true, PHY_OFDM, 54000, 0x0c, 0x00, 108, 4},
205 {true, PHY_HT, 6500, 0x80, 0x00, 0, 0},
206 {true, PHY_HT, 13000, 0x81, 0x00, 1, 2},
207 {true, PHY_HT, 19500, 0x82, 0x00, 2, 2},
208 {true, PHY_HT, 26000, 0x83, 0x00, 3, 4},
209 {true, PHY_HT, 39000, 0x84, 0x00, 4, 4},
210 {true, PHY_HT, 52000, 0x85, 0x00, 5, 4},
211 {true, PHY_HT, 58500, 0x86, 0x00, 6, 4},
212 {true, PHY_HT, 65000, 0x87, 0x00, 7, 4},
213 {true, PHY_HT, 13000, 0x88, 0x00, 8, 0},
214 {true, PHY_HT, 26000, 0x89, 0x00, 9, 2},
215 {true, PHY_HT, 39000, 0x8a, 0x00, 10, 2},
216 {true, PHY_HT, 52000, 0x8b, 0x00, 11, 4},
217 {true, PHY_HT, 78000, 0x8c, 0x00, 12, 4},
218 {true, PHY_HT, 104000, 0x8d, 0x00, 13, 4},
219 {true, PHY_HT, 117000, 0x8e, 0x00, 14, 4},
220 {true, PHY_HT, 130000, 0x8f, 0x00, 15, 4},
221 },
222};
223
224static enum wireless_mode ath9k_hw_chan2wmode(struct ath_hal *ah,
225 const struct ath9k_channel *chan)
226{
227 if (IS_CHAN_CCK(chan))
Sujith86b89ee2008-08-07 10:54:57 +0530228 return ATH9K_MODE_11A;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700229 if (IS_CHAN_G(chan))
Sujith86b89ee2008-08-07 10:54:57 +0530230 return ATH9K_MODE_11G;
231 return ATH9K_MODE_11A;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700232}
233
234static bool ath9k_hw_wait(struct ath_hal *ah,
235 u32 reg,
236 u32 mask,
237 u32 val)
238{
239 int i;
240
241 for (i = 0; i < (AH_TIMEOUT / AH_TIME_QUANTUM); i++) {
242 if ((REG_READ(ah, reg) & mask) == val)
243 return true;
244
245 udelay(AH_TIME_QUANTUM);
246 }
247 DPRINTF(ah->ah_sc, ATH_DBG_PHY_IO,
248 "%s: timeout on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n",
249 __func__, reg, REG_READ(ah, reg), mask, val);
250 return false;
251}
252
253static bool ath9k_hw_eeprom_read(struct ath_hal *ah, u32 off,
254 u16 *data)
255{
256 (void) REG_READ(ah, AR5416_EEPROM_OFFSET + (off << AR5416_EEPROM_S));
257
258 if (!ath9k_hw_wait(ah,
259 AR_EEPROM_STATUS_DATA,
260 AR_EEPROM_STATUS_DATA_BUSY |
261 AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0)) {
262 return false;
263 }
264
265 *data = MS(REG_READ(ah, AR_EEPROM_STATUS_DATA),
266 AR_EEPROM_STATUS_DATA_VAL);
267
268 return true;
269}
270
271static int ath9k_hw_flash_map(struct ath_hal *ah)
272{
273 struct ath_hal_5416 *ahp = AH5416(ah);
274
275 ahp->ah_cal_mem = ioremap(AR5416_EEPROM_START_ADDR, AR5416_EEPROM_MAX);
276
277 if (!ahp->ah_cal_mem) {
278 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
279 "%s: cannot remap eeprom region \n", __func__);
280 return -EIO;
281 }
282
283 return 0;
284}
285
286static bool ath9k_hw_flash_read(struct ath_hal *ah, u32 off,
287 u16 *data)
288{
289 struct ath_hal_5416 *ahp = AH5416(ah);
290
291 *data = ioread16(ahp->ah_cal_mem + off);
292 return true;
293}
294
295static void ath9k_hw_read_revisions(struct ath_hal *ah)
296{
297 u32 val;
298
299 val = REG_READ(ah, AR_SREV) & AR_SREV_ID;
300
301 if (val == 0xFF) {
302 val = REG_READ(ah, AR_SREV);
303
304 ah->ah_macVersion =
305 (val & AR_SREV_VERSION2) >> AR_SREV_TYPE2_S;
306
307 ah->ah_macRev = MS(val, AR_SREV_REVISION2);
308 ah->ah_isPciExpress =
309 (val & AR_SREV_TYPE2_HOST_MODE) ? 0 : 1;
310
311 } else {
312 if (!AR_SREV_9100(ah))
313 ah->ah_macVersion = MS(val, AR_SREV_VERSION);
314
315 ah->ah_macRev = val & AR_SREV_REVISION;
316
317 if (ah->ah_macVersion == AR_SREV_VERSION_5416_PCIE)
318 ah->ah_isPciExpress = true;
319 }
320}
321
322u32 ath9k_hw_reverse_bits(u32 val, u32 n)
323{
324 u32 retval;
325 int i;
326
327 for (i = 0, retval = 0; i < n; i++) {
328 retval = (retval << 1) | (val & 1);
329 val >>= 1;
330 }
331 return retval;
332}
333
334static void ath9k_hw_set_defaults(struct ath_hal *ah)
335{
336 int i;
337
Sujith60b67f52008-08-07 10:52:38 +0530338 ah->ah_config.dma_beacon_response_time = 2;
339 ah->ah_config.sw_beacon_response_time = 10;
340 ah->ah_config.additional_swba_backoff = 0;
341 ah->ah_config.ack_6mb = 0x0;
342 ah->ah_config.cwm_ignore_extcca = 0;
343 ah->ah_config.pcie_powersave_enable = 0;
344 ah->ah_config.pcie_l1skp_enable = 0;
345 ah->ah_config.pcie_clock_req = 0;
346 ah->ah_config.pcie_power_reset = 0x100;
347 ah->ah_config.pcie_restore = 0;
348 ah->ah_config.pcie_waen = 0;
349 ah->ah_config.analog_shiftreg = 1;
350 ah->ah_config.ht_enable = 1;
351 ah->ah_config.ofdm_trig_low = 200;
352 ah->ah_config.ofdm_trig_high = 500;
353 ah->ah_config.cck_trig_high = 200;
354 ah->ah_config.cck_trig_low = 100;
355 ah->ah_config.enable_ani = 0;
356 ah->ah_config.noise_immunity_level = 4;
357 ah->ah_config.ofdm_weaksignal_det = 1;
358 ah->ah_config.cck_weaksignal_thr = 0;
359 ah->ah_config.spur_immunity_level = 2;
360 ah->ah_config.firstep_level = 0;
361 ah->ah_config.rssi_thr_high = 40;
362 ah->ah_config.rssi_thr_low = 7;
363 ah->ah_config.diversity_control = 0;
364 ah->ah_config.antenna_switch_swap = 0;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700365
366 for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
Sujith60b67f52008-08-07 10:52:38 +0530367 ah->ah_config.spurchans[i][0] = AR_NO_SPUR;
368 ah->ah_config.spurchans[i][1] = AR_NO_SPUR;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700369 }
370
Sujith60b67f52008-08-07 10:52:38 +0530371 ah->ah_config.intr_mitigation = 0;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700372}
373
374static inline void ath9k_hw_override_ini(struct ath_hal *ah,
375 struct ath9k_channel *chan)
376{
377 if (!AR_SREV_5416_V20_OR_LATER(ah)
378 || AR_SREV_9280_10_OR_LATER(ah))
379 return;
380
381 REG_WRITE(ah, 0x9800 + (651 << 2), 0x11);
382}
383
384static inline void ath9k_hw_init_bb(struct ath_hal *ah,
385 struct ath9k_channel *chan)
386{
387 u32 synthDelay;
388
389 synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;
390 if (IS_CHAN_CCK(chan))
391 synthDelay = (4 * synthDelay) / 22;
392 else
393 synthDelay /= 10;
394
395 REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
396
397 udelay(synthDelay + BASE_ACTIVATE_DELAY);
398}
399
400static inline void ath9k_hw_init_interrupt_masks(struct ath_hal *ah,
401 enum ath9k_opmode opmode)
402{
403 struct ath_hal_5416 *ahp = AH5416(ah);
404
405 ahp->ah_maskReg = AR_IMR_TXERR |
406 AR_IMR_TXURN |
407 AR_IMR_RXERR |
408 AR_IMR_RXORN |
409 AR_IMR_BCNMISC;
410
411 if (ahp->ah_intrMitigation)
412 ahp->ah_maskReg |= AR_IMR_RXINTM | AR_IMR_RXMINTR;
413 else
414 ahp->ah_maskReg |= AR_IMR_RXOK;
415
416 ahp->ah_maskReg |= AR_IMR_TXOK;
417
418 if (opmode == ATH9K_M_HOSTAP)
419 ahp->ah_maskReg |= AR_IMR_MIB;
420
421 REG_WRITE(ah, AR_IMR, ahp->ah_maskReg);
422 REG_WRITE(ah, AR_IMR_S2, REG_READ(ah, AR_IMR_S2) | AR_IMR_S2_GTT);
423
424 if (!AR_SREV_9100(ah)) {
425 REG_WRITE(ah, AR_INTR_SYNC_CAUSE, 0xFFFFFFFF);
426 REG_WRITE(ah, AR_INTR_SYNC_ENABLE, AR_INTR_SYNC_DEFAULT);
427 REG_WRITE(ah, AR_INTR_SYNC_MASK, 0);
428 }
429}
430
431static inline void ath9k_hw_init_qos(struct ath_hal *ah)
432{
433 REG_WRITE(ah, AR_MIC_QOS_CONTROL, 0x100aa);
434 REG_WRITE(ah, AR_MIC_QOS_SELECT, 0x3210);
435
436 REG_WRITE(ah, AR_QOS_NO_ACK,
437 SM(2, AR_QOS_NO_ACK_TWO_BIT) |
438 SM(5, AR_QOS_NO_ACK_BIT_OFF) |
439 SM(0, AR_QOS_NO_ACK_BYTE_OFF));
440
441 REG_WRITE(ah, AR_TXOP_X, AR_TXOP_X_VAL);
442 REG_WRITE(ah, AR_TXOP_0_3, 0xFFFFFFFF);
443 REG_WRITE(ah, AR_TXOP_4_7, 0xFFFFFFFF);
444 REG_WRITE(ah, AR_TXOP_8_11, 0xFFFFFFFF);
445 REG_WRITE(ah, AR_TXOP_12_15, 0xFFFFFFFF);
446}
447
448static void ath9k_hw_analog_shift_rmw(struct ath_hal *ah,
449 u32 reg,
450 u32 mask,
451 u32 shift,
452 u32 val)
453{
454 u32 regVal;
455
456 regVal = REG_READ(ah, reg) & ~mask;
457 regVal |= (val << shift) & mask;
458
459 REG_WRITE(ah, reg, regVal);
460
Sujith60b67f52008-08-07 10:52:38 +0530461 if (ah->ah_config.analog_shiftreg)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700462 udelay(100);
463
464 return;
465}
466
467static u8 ath9k_hw_get_num_ant_config(struct ath_hal_5416 *ahp,
Sujith06df8be2008-08-07 10:53:39 +0530468 enum ieee80211_band freq_band)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700469{
470 struct ar5416_eeprom *eep = &ahp->ah_eeprom;
471 struct modal_eep_header *pModal =
Sujith06df8be2008-08-07 10:53:39 +0530472 &(eep->modalHeader[IEEE80211_BAND_5GHZ == freq_band]);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -0700473 struct base_eep_header *pBase = &eep->baseEepHeader;
474 u8 num_ant_config;
475
476 num_ant_config = 1;
477
478 if (pBase->version >= 0x0E0D)
479 if (pModal->useAnt1)
480 num_ant_config += 1;
481
482 return num_ant_config;
483}
484
485static int
486ath9k_hw_get_eeprom_antenna_cfg(struct ath_hal_5416 *ahp,
487 struct ath9k_channel *chan,
488 u8 index,
489 u16 *config)
490{
491 struct ar5416_eeprom *eep = &ahp->ah_eeprom;
492 struct modal_eep_header *pModal =
493 &(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
494 struct base_eep_header *pBase = &eep->baseEepHeader;
495
496 switch (index) {
497 case 0:
498 *config = pModal->antCtrlCommon & 0xFFFF;
499 return 0;
500 case 1:
501 if (pBase->version >= 0x0E0D) {
502 if (pModal->useAnt1) {
503 *config =
504 ((pModal->antCtrlCommon & 0xFFFF0000) >> 16);
505 return 0;
506 }
507 }
508 break;
509 default:
510 break;
511 }
512
513 return -EINVAL;
514}
515
516static inline bool ath9k_hw_nvram_read(struct ath_hal *ah,
517 u32 off,
518 u16 *data)
519{
520 if (ath9k_hw_use_flash(ah))
521 return ath9k_hw_flash_read(ah, off, data);
522 else
523 return ath9k_hw_eeprom_read(ah, off, data);
524}
525
526static inline bool ath9k_hw_fill_eeprom(struct ath_hal *ah)
527{
528 struct ath_hal_5416 *ahp = AH5416(ah);
529 struct ar5416_eeprom *eep = &ahp->ah_eeprom;
530 u16 *eep_data;
531 int addr, ar5416_eep_start_loc = 0;
532
533 if (!ath9k_hw_use_flash(ah)) {
534 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
535 "%s: Reading from EEPROM, not flash\n", __func__);
536 ar5416_eep_start_loc = 256;
537 }
538 if (AR_SREV_9100(ah))
539 ar5416_eep_start_loc = 256;
540
541 eep_data = (u16 *) eep;
542 for (addr = 0;
543 addr < sizeof(struct ar5416_eeprom) / sizeof(u16);
544 addr++) {
545 if (!ath9k_hw_nvram_read(ah, addr + ar5416_eep_start_loc,
546 eep_data)) {
547 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
548 "%s: Unable to read eeprom region \n",
549 __func__);
550 return false;
551 }
552 eep_data++;
553 }
554 return true;
555}
556
557/* XXX: Clean me up, make me more legible */
558static bool
559ath9k_hw_eeprom_set_board_values(struct ath_hal *ah,
560 struct ath9k_channel *chan)
561{
562 struct modal_eep_header *pModal;
563 int i, regChainOffset;
564 struct ath_hal_5416 *ahp = AH5416(ah);
565 struct ar5416_eeprom *eep = &ahp->ah_eeprom;
566 u8 txRxAttenLocal;
567 u16 ant_config;
568
569 pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
570
571 txRxAttenLocal = IS_CHAN_2GHZ(chan) ? 23 : 44;
572
573 ath9k_hw_get_eeprom_antenna_cfg(ahp, chan, 1, &ant_config);
574 REG_WRITE(ah, AR_PHY_SWITCH_COM, ant_config);
575
576 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
577 if (AR_SREV_9280(ah)) {
578 if (i >= 2)
579 break;
580 }
581
582 if (AR_SREV_5416_V20_OR_LATER(ah) &&
583 (ahp->ah_rxchainmask == 5 || ahp->ah_txchainmask == 5)
584 && (i != 0))
585 regChainOffset = (i == 1) ? 0x2000 : 0x1000;
586 else
587 regChainOffset = i * 0x1000;
588
589 REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset,
590 pModal->antCtrlChain[i]);
591
592 REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset,
593 (REG_READ(ah,
594 AR_PHY_TIMING_CTRL4(0) +
595 regChainOffset) &
596 ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF |
597 AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) |
598 SM(pModal->iqCalICh[i],
599 AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) |
600 SM(pModal->iqCalQCh[i],
601 AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF));
602
603 if ((i == 0) || AR_SREV_5416_V20_OR_LATER(ah)) {
604 if ((eep->baseEepHeader.version &
605 AR5416_EEP_VER_MINOR_MASK) >=
606 AR5416_EEP_MINOR_VER_3) {
607 txRxAttenLocal = pModal->txRxAttenCh[i];
608 if (AR_SREV_9280_10_OR_LATER(ah)) {
609 REG_RMW_FIELD(ah,
610 AR_PHY_GAIN_2GHZ +
611 regChainOffset,
612 AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN,
613 pModal->
614 bswMargin[i]);
615 REG_RMW_FIELD(ah,
616 AR_PHY_GAIN_2GHZ +
617 regChainOffset,
618 AR_PHY_GAIN_2GHZ_XATTEN1_DB,
619 pModal->
620 bswAtten[i]);
621 REG_RMW_FIELD(ah,
622 AR_PHY_GAIN_2GHZ +
623 regChainOffset,
624 AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,
625 pModal->
626 xatten2Margin[i]);
627 REG_RMW_FIELD(ah,
628 AR_PHY_GAIN_2GHZ +
629 regChainOffset,
630 AR_PHY_GAIN_2GHZ_XATTEN2_DB,
631 pModal->
632 xatten2Db[i]);
633 } else {
634 REG_WRITE(ah,
635 AR_PHY_GAIN_2GHZ +
636 regChainOffset,
637 (REG_READ(ah,
638 AR_PHY_GAIN_2GHZ +
639 regChainOffset) &
640 ~AR_PHY_GAIN_2GHZ_BSW_MARGIN)
641 | SM(pModal->
642 bswMargin[i],
643 AR_PHY_GAIN_2GHZ_BSW_MARGIN));
644 REG_WRITE(ah,
645 AR_PHY_GAIN_2GHZ +
646 regChainOffset,
647 (REG_READ(ah,
648 AR_PHY_GAIN_2GHZ +
649 regChainOffset) &
650 ~AR_PHY_GAIN_2GHZ_BSW_ATTEN)
651 | SM(pModal->bswAtten[i],
652 AR_PHY_GAIN_2GHZ_BSW_ATTEN));
653 }
654 }
655 if (AR_SREV_9280_10_OR_LATER(ah)) {
656 REG_RMW_FIELD(ah,
657 AR_PHY_RXGAIN +
658 regChainOffset,
659 AR9280_PHY_RXGAIN_TXRX_ATTEN,
660 txRxAttenLocal);
661 REG_RMW_FIELD(ah,
662 AR_PHY_RXGAIN +
663 regChainOffset,
664 AR9280_PHY_RXGAIN_TXRX_MARGIN,
665 pModal->rxTxMarginCh[i]);
666 } else {
667 REG_WRITE(ah,
668 AR_PHY_RXGAIN + regChainOffset,
669 (REG_READ(ah,
670 AR_PHY_RXGAIN +
671 regChainOffset) &
672 ~AR_PHY_RXGAIN_TXRX_ATTEN) |
673 SM(txRxAttenLocal,
674 AR_PHY_RXGAIN_TXRX_ATTEN));
675 REG_WRITE(ah,
676 AR_PHY_GAIN_2GHZ +
677 regChainOffset,
678 (REG_READ(ah,
679 AR_PHY_GAIN_2GHZ +
680 regChainOffset) &
681 ~AR_PHY_GAIN_2GHZ_RXTX_MARGIN) |
682 SM(pModal->rxTxMarginCh[i],
683 AR_PHY_GAIN_2GHZ_RXTX_MARGIN));
684 }
685 }
686 }
687
688 if (AR_SREV_9280_10_OR_LATER(ah)) {
689 if (IS_CHAN_2GHZ(chan)) {
690 ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0,
691 AR_AN_RF2G1_CH0_OB,
692 AR_AN_RF2G1_CH0_OB_S,
693 pModal->ob);
694 ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0,
695 AR_AN_RF2G1_CH0_DB,
696 AR_AN_RF2G1_CH0_DB_S,
697 pModal->db);
698 ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH1,
699 AR_AN_RF2G1_CH1_OB,
700 AR_AN_RF2G1_CH1_OB_S,
701 pModal->ob_ch1);
702 ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH1,
703 AR_AN_RF2G1_CH1_DB,
704 AR_AN_RF2G1_CH1_DB_S,
705 pModal->db_ch1);
706 } else {
707 ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH0,
708 AR_AN_RF5G1_CH0_OB5,
709 AR_AN_RF5G1_CH0_OB5_S,
710 pModal->ob);
711 ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH0,
712 AR_AN_RF5G1_CH0_DB5,
713 AR_AN_RF5G1_CH0_DB5_S,
714 pModal->db);
715 ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH1,
716 AR_AN_RF5G1_CH1_OB5,
717 AR_AN_RF5G1_CH1_OB5_S,
718 pModal->ob_ch1);
719 ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH1,
720 AR_AN_RF5G1_CH1_DB5,
721 AR_AN_RF5G1_CH1_DB5_S,
722 pModal->db_ch1);
723 }
724 ath9k_hw_analog_shift_rmw(ah, AR_AN_TOP2,
725 AR_AN_TOP2_XPABIAS_LVL,
726 AR_AN_TOP2_XPABIAS_LVL_S,
727 pModal->xpaBiasLvl);
728 ath9k_hw_analog_shift_rmw(ah, AR_AN_TOP2,
729 AR_AN_TOP2_LOCALBIAS,
730 AR_AN_TOP2_LOCALBIAS_S,
731 pModal->local_bias);
732 DPRINTF(ah->ah_sc, ATH_DBG_ANY, "ForceXPAon: %d\n",
733 pModal->force_xpaon);
734 REG_RMW_FIELD(ah, AR_PHY_XPA_CFG, AR_PHY_FORCE_XPA_CFG,
735 pModal->force_xpaon);
736 }
737
738 REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH,
739 pModal->switchSettling);
740 REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC,
741 pModal->adcDesiredSize);
742
743 if (!AR_SREV_9280_10_OR_LATER(ah))
744 REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
745 AR_PHY_DESIRED_SZ_PGA,
746 pModal->pgaDesiredSize);
747
748 REG_WRITE(ah, AR_PHY_RF_CTL4,
749 SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF)
750 | SM(pModal->txEndToXpaOff,
751 AR_PHY_RF_CTL4_TX_END_XPAB_OFF)
752 | SM(pModal->txFrameToXpaOn,
753 AR_PHY_RF_CTL4_FRAME_XPAA_ON)
754 | SM(pModal->txFrameToXpaOn,
755 AR_PHY_RF_CTL4_FRAME_XPAB_ON));
756
757 REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON,
758 pModal->txEndToRxOn);
759 if (AR_SREV_9280_10_OR_LATER(ah)) {
760 REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62,
761 pModal->thresh62);
762 REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0,
763 AR_PHY_EXT_CCA0_THRESH62,
764 pModal->thresh62);
765 } else {
766 REG_RMW_FIELD(ah, AR_PHY_CCA, AR_PHY_CCA_THRESH62,
767 pModal->thresh62);
768 REG_RMW_FIELD(ah, AR_PHY_EXT_CCA,
769 AR_PHY_EXT_CCA_THRESH62,
770 pModal->thresh62);
771 }
772
773 if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
774 AR5416_EEP_MINOR_VER_2) {
775 REG_RMW_FIELD(ah, AR_PHY_RF_CTL2,
776 AR_PHY_TX_END_DATA_START,
777 pModal->txFrameToDataStart);
778 REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_PA_ON,
779 pModal->txFrameToPaOn);
780 }
781
782 if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
783 AR5416_EEP_MINOR_VER_3) {
784 if (IS_CHAN_HT40(chan))
785 REG_RMW_FIELD(ah, AR_PHY_SETTLING,
786 AR_PHY_SETTLING_SWITCH,
787 pModal->swSettleHt40);
788 }
789
790 return true;
791}
792
793static inline int ath9k_hw_check_eeprom(struct ath_hal *ah)
794{
795 u32 sum = 0, el;
796 u16 *eepdata;
797 int i;
798 struct ath_hal_5416 *ahp = AH5416(ah);
799 bool need_swap = false;
800 struct ar5416_eeprom *eep =
801 (struct ar5416_eeprom *) &ahp->ah_eeprom;
802
803 if (!ath9k_hw_use_flash(ah)) {
804 u16 magic, magic2;
805 int addr;
806
807 if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET,
808 &magic)) {
809 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
810 "%s: Reading Magic # failed\n", __func__);
811 return false;
812 }
813 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "%s: Read Magic = 0x%04X\n",
814 __func__, magic);
815
816 if (magic != AR5416_EEPROM_MAGIC) {
817 magic2 = swab16(magic);
818
819 if (magic2 == AR5416_EEPROM_MAGIC) {
820 need_swap = true;
821 eepdata = (u16 *) (&ahp->ah_eeprom);
822
823 for (addr = 0;
824 addr <
825 sizeof(struct ar5416_eeprom) /
826 sizeof(u16); addr++) {
827 u16 temp;
828
829 temp = swab16(*eepdata);
830 *eepdata = temp;
831 eepdata++;
832
833 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
834 "0x%04X ", *eepdata);
835 if (((addr + 1) % 6) == 0)
836 DPRINTF(ah->ah_sc,
837 ATH_DBG_EEPROM,
838 "\n");
839 }
840 } else {
841 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
842 "Invalid EEPROM Magic. "
843 "endianness missmatch.\n");
844 return -EINVAL;
845 }
846 }
847 }
848 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "need_swap = %s.\n",
849 need_swap ? "True" : "False");
850
851 if (need_swap)
852 el = swab16(ahp->ah_eeprom.baseEepHeader.length);
853 else
854 el = ahp->ah_eeprom.baseEepHeader.length;
855
856 if (el > sizeof(struct ar5416_eeprom))
857 el = sizeof(struct ar5416_eeprom) / sizeof(u16);
858 else
859 el = el / sizeof(u16);
860
861 eepdata = (u16 *) (&ahp->ah_eeprom);
862
863 for (i = 0; i < el; i++)
864 sum ^= *eepdata++;
865
866 if (need_swap) {
867 u32 integer, j;
868 u16 word;
869
870 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
871 "EEPROM Endianness is not native.. Changing \n");
872
873 word = swab16(eep->baseEepHeader.length);
874 eep->baseEepHeader.length = word;
875
876 word = swab16(eep->baseEepHeader.checksum);
877 eep->baseEepHeader.checksum = word;
878
879 word = swab16(eep->baseEepHeader.version);
880 eep->baseEepHeader.version = word;
881
882 word = swab16(eep->baseEepHeader.regDmn[0]);
883 eep->baseEepHeader.regDmn[0] = word;
884
885 word = swab16(eep->baseEepHeader.regDmn[1]);
886 eep->baseEepHeader.regDmn[1] = word;
887
888 word = swab16(eep->baseEepHeader.rfSilent);
889 eep->baseEepHeader.rfSilent = word;
890
891 word = swab16(eep->baseEepHeader.blueToothOptions);
892 eep->baseEepHeader.blueToothOptions = word;
893
894 word = swab16(eep->baseEepHeader.deviceCap);
895 eep->baseEepHeader.deviceCap = word;
896
897 for (j = 0; j < ARRAY_SIZE(eep->modalHeader); j++) {
898 struct modal_eep_header *pModal =
899 &eep->modalHeader[j];
900 integer = swab32(pModal->antCtrlCommon);
901 pModal->antCtrlCommon = integer;
902
903 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
904 integer = swab32(pModal->antCtrlChain[i]);
905 pModal->antCtrlChain[i] = integer;
906 }
907
908 for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) {
909 word = swab16(pModal->spurChans[i].spurChan);
910 pModal->spurChans[i].spurChan = word;
911 }
912 }
913 }
914
915 if (sum != 0xffff || ar5416_get_eep_ver(ahp) != AR5416_EEP_VER ||
916 ar5416_get_eep_rev(ahp) < AR5416_EEP_NO_BACK_VER) {
917 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
918 "Bad EEPROM checksum 0x%x or revision 0x%04x\n",
919 sum, ar5416_get_eep_ver(ahp));
920 return -EINVAL;
921 }
922
923 return 0;
924}
925
926static bool ath9k_hw_chip_test(struct ath_hal *ah)
927{
928 u32 regAddr[2] = { AR_STA_ID0, AR_PHY_BASE + (8 << 2) };
929 u32 regHold[2];
930 u32 patternData[4] = { 0x55555555,
931 0xaaaaaaaa,
932 0x66666666,
933 0x99999999 };
934 int i, j;
935
936 for (i = 0; i < 2; i++) {
937 u32 addr = regAddr[i];
938 u32 wrData, rdData;
939
940 regHold[i] = REG_READ(ah, addr);
941 for (j = 0; j < 0x100; j++) {
942 wrData = (j << 16) | j;
943 REG_WRITE(ah, addr, wrData);
944 rdData = REG_READ(ah, addr);
945 if (rdData != wrData) {
946 DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
947 "%s: address test failed "
948 "addr: 0x%08x - wr:0x%08x != rd:0x%08x\n",
949 __func__, addr, wrData, rdData);
950 return false;
951 }
952 }
953 for (j = 0; j < 4; j++) {
954 wrData = patternData[j];
955 REG_WRITE(ah, addr, wrData);
956 rdData = REG_READ(ah, addr);
957 if (wrData != rdData) {
958 DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
959 "%s: address test failed "
960 "addr: 0x%08x - wr:0x%08x != rd:0x%08x\n",
961 __func__, addr, wrData, rdData);
962 return false;
963 }
964 }
965 REG_WRITE(ah, regAddr[i], regHold[i]);
966 }
967 udelay(100);
968 return true;
969}
970
971u32 ath9k_hw_getrxfilter(struct ath_hal *ah)
972{
973 u32 bits = REG_READ(ah, AR_RX_FILTER);
974 u32 phybits = REG_READ(ah, AR_PHY_ERR);
975
976 if (phybits & AR_PHY_ERR_RADAR)
977 bits |= ATH9K_RX_FILTER_PHYRADAR;
978 if (phybits & (AR_PHY_ERR_OFDM_TIMING | AR_PHY_ERR_CCK_TIMING))
979 bits |= ATH9K_RX_FILTER_PHYERR;
980 return bits;
981}
982
983void ath9k_hw_setrxfilter(struct ath_hal *ah, u32 bits)
984{
985 u32 phybits;
986
987 REG_WRITE(ah, AR_RX_FILTER, (bits & 0xffff) | AR_RX_COMPR_BAR);
988 phybits = 0;
989 if (bits & ATH9K_RX_FILTER_PHYRADAR)
990 phybits |= AR_PHY_ERR_RADAR;
991 if (bits & ATH9K_RX_FILTER_PHYERR)
992 phybits |= AR_PHY_ERR_OFDM_TIMING | AR_PHY_ERR_CCK_TIMING;
993 REG_WRITE(ah, AR_PHY_ERR, phybits);
994
995 if (phybits)
996 REG_WRITE(ah, AR_RXCFG,
997 REG_READ(ah, AR_RXCFG) | AR_RXCFG_ZLFDMA);
998 else
999 REG_WRITE(ah, AR_RXCFG,
1000 REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_ZLFDMA);
1001}
1002
1003bool ath9k_hw_setcapability(struct ath_hal *ah,
Sujith60b67f52008-08-07 10:52:38 +05301004 enum ath9k_capability_type type,
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001005 u32 capability,
1006 u32 setting,
1007 int *status)
1008{
1009 struct ath_hal_5416 *ahp = AH5416(ah);
1010 u32 v;
1011
1012 switch (type) {
Sujith60b67f52008-08-07 10:52:38 +05301013 case ATH9K_CAP_TKIP_MIC:
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001014 if (setting)
1015 ahp->ah_staId1Defaults |=
1016 AR_STA_ID1_CRPT_MIC_ENABLE;
1017 else
1018 ahp->ah_staId1Defaults &=
1019 ~AR_STA_ID1_CRPT_MIC_ENABLE;
1020 return true;
Sujith60b67f52008-08-07 10:52:38 +05301021 case ATH9K_CAP_DIVERSITY:
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001022 v = REG_READ(ah, AR_PHY_CCK_DETECT);
1023 if (setting)
1024 v |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
1025 else
1026 v &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
1027 REG_WRITE(ah, AR_PHY_CCK_DETECT, v);
1028 return true;
Sujith60b67f52008-08-07 10:52:38 +05301029 case ATH9K_CAP_MCAST_KEYSRCH:
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001030 if (setting)
1031 ahp->ah_staId1Defaults |= AR_STA_ID1_MCAST_KSRCH;
1032 else
1033 ahp->ah_staId1Defaults &= ~AR_STA_ID1_MCAST_KSRCH;
1034 return true;
Sujith60b67f52008-08-07 10:52:38 +05301035 case ATH9K_CAP_TSF_ADJUST:
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001036 if (setting)
1037 ahp->ah_miscMode |= AR_PCU_TX_ADD_TSF;
1038 else
1039 ahp->ah_miscMode &= ~AR_PCU_TX_ADD_TSF;
1040 return true;
1041 default:
1042 return false;
1043 }
1044}
1045
1046void ath9k_hw_dmaRegDump(struct ath_hal *ah)
1047{
1048 u32 val[ATH9K_NUM_DMA_DEBUG_REGS];
1049 int qcuOffset = 0, dcuOffset = 0;
1050 u32 *qcuBase = &val[0], *dcuBase = &val[4];
1051 int i;
1052
1053 REG_WRITE(ah, AR_MACMISC,
1054 ((AR_MACMISC_DMA_OBS_LINE_8 << AR_MACMISC_DMA_OBS_S) |
1055 (AR_MACMISC_MISC_OBS_BUS_1 <<
1056 AR_MACMISC_MISC_OBS_BUS_MSB_S)));
1057
1058 DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, "Raw DMA Debug values:\n");
1059 for (i = 0; i < ATH9K_NUM_DMA_DEBUG_REGS; i++) {
1060 if (i % 4 == 0)
1061 DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, "\n");
1062
1063 val[i] = REG_READ(ah, AR_DMADBG_0 + (i * sizeof(u32)));
1064 DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, "%d: %08x ", i, val[i]);
1065 }
1066
1067 DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, "\n\n");
1068 DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
1069 "Num QCU: chain_st fsp_ok fsp_st DCU: chain_st\n");
1070
1071 for (i = 0; i < ATH9K_NUM_QUEUES;
1072 i++, qcuOffset += 4, dcuOffset += 5) {
1073 if (i == 8) {
1074 qcuOffset = 0;
1075 qcuBase++;
1076 }
1077
1078 if (i == 6) {
1079 dcuOffset = 0;
1080 dcuBase++;
1081 }
1082
1083 DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
1084 "%2d %2x %1x %2x %2x\n",
1085 i, (*qcuBase & (0x7 << qcuOffset)) >> qcuOffset,
1086 (*qcuBase & (0x8 << qcuOffset)) >> (qcuOffset +
1087 3),
1088 val[2] & (0x7 << (i * 3)) >> (i * 3),
1089 (*dcuBase & (0x1f << dcuOffset)) >> dcuOffset);
1090 }
1091
1092 DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, "\n");
1093 DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
1094 "qcu_stitch state: %2x qcu_fetch state: %2x\n",
1095 (val[3] & 0x003c0000) >> 18, (val[3] & 0x03c00000) >> 22);
1096 DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
1097 "qcu_complete state: %2x dcu_complete state: %2x\n",
1098 (val[3] & 0x1c000000) >> 26, (val[6] & 0x3));
1099 DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
1100 "dcu_arb state: %2x dcu_fp state: %2x\n",
1101 (val[5] & 0x06000000) >> 25, (val[5] & 0x38000000) >> 27);
1102 DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
1103 "chan_idle_dur: %3d chan_idle_dur_valid: %1d\n",
1104 (val[6] & 0x000003fc) >> 2, (val[6] & 0x00000400) >> 10);
1105 DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
1106 "txfifo_valid_0: %1d txfifo_valid_1: %1d\n",
1107 (val[6] & 0x00000800) >> 11, (val[6] & 0x00001000) >> 12);
1108 DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
1109 "txfifo_dcu_num_0: %2d txfifo_dcu_num_1: %2d\n",
1110 (val[6] & 0x0001e000) >> 13, (val[6] & 0x001e0000) >> 17);
1111
1112 DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, "pcu observe 0x%x \n",
1113 REG_READ(ah, AR_OBS_BUS_1));
1114 DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
1115 "AR_CR 0x%x \n", REG_READ(ah, AR_CR));
1116}
1117
1118u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hal *ah,
1119 u32 *rxc_pcnt,
1120 u32 *rxf_pcnt,
1121 u32 *txf_pcnt)
1122{
1123 static u32 cycles, rx_clear, rx_frame, tx_frame;
1124 u32 good = 1;
1125
1126 u32 rc = REG_READ(ah, AR_RCCNT);
1127 u32 rf = REG_READ(ah, AR_RFCNT);
1128 u32 tf = REG_READ(ah, AR_TFCNT);
1129 u32 cc = REG_READ(ah, AR_CCCNT);
1130
1131 if (cycles == 0 || cycles > cc) {
1132 DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
1133 "%s: cycle counter wrap. ExtBusy = 0\n",
1134 __func__);
1135 good = 0;
1136 } else {
1137 u32 cc_d = cc - cycles;
1138 u32 rc_d = rc - rx_clear;
1139 u32 rf_d = rf - rx_frame;
1140 u32 tf_d = tf - tx_frame;
1141
1142 if (cc_d != 0) {
1143 *rxc_pcnt = rc_d * 100 / cc_d;
1144 *rxf_pcnt = rf_d * 100 / cc_d;
1145 *txf_pcnt = tf_d * 100 / cc_d;
1146 } else {
1147 good = 0;
1148 }
1149 }
1150
1151 cycles = cc;
1152 rx_frame = rf;
1153 rx_clear = rc;
1154 tx_frame = tf;
1155
1156 return good;
1157}
1158
1159void ath9k_hw_set11nmac2040(struct ath_hal *ah, enum ath9k_ht_macmode mode)
1160{
1161 u32 macmode;
1162
1163 if (mode == ATH9K_HT_MACMODE_2040 &&
Sujith60b67f52008-08-07 10:52:38 +05301164 !ah->ah_config.cwm_ignore_extcca)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001165 macmode = AR_2040_JOINED_RX_CLEAR;
1166 else
1167 macmode = 0;
1168
1169 REG_WRITE(ah, AR_2040_MODE, macmode);
1170}
1171
1172static void ath9k_hw_mark_phy_inactive(struct ath_hal *ah)
1173{
1174 REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS);
1175}
1176
1177
1178static struct ath_hal_5416 *ath9k_hw_newstate(u16 devid,
1179 struct ath_softc *sc,
1180 void __iomem *mem,
1181 int *status)
1182{
1183 static const u8 defbssidmask[ETH_ALEN] =
1184 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
1185 struct ath_hal_5416 *ahp;
1186 struct ath_hal *ah;
1187
1188 ahp = kzalloc(sizeof(struct ath_hal_5416), GFP_KERNEL);
1189 if (ahp == NULL) {
1190 DPRINTF(sc, ATH_DBG_FATAL,
1191 "%s: cannot allocate memory for state block\n",
1192 __func__);
1193 *status = -ENOMEM;
1194 return NULL;
1195 }
1196
1197 ah = &ahp->ah;
1198
1199 memcpy(&ahp->ah, &ar5416hal, sizeof(struct ath_hal));
1200
1201 ah->ah_sc = sc;
1202 ah->ah_sh = mem;
1203
1204 ah->ah_devid = devid;
1205 ah->ah_subvendorid = 0;
1206
1207 ah->ah_flags = 0;
1208 if ((devid == AR5416_AR9100_DEVID))
1209 ah->ah_macVersion = AR_SREV_VERSION_9100;
1210 if (!AR_SREV_9100(ah))
1211 ah->ah_flags = AH_USE_EEPROM;
1212
1213 ah->ah_powerLimit = MAX_RATE_POWER;
1214 ah->ah_tpScale = ATH9K_TP_SCALE_MAX;
1215
1216 ahp->ah_atimWindow = 0;
Sujith60b67f52008-08-07 10:52:38 +05301217 ahp->ah_diversityControl = ah->ah_config.diversity_control;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001218 ahp->ah_antennaSwitchSwap =
Sujith60b67f52008-08-07 10:52:38 +05301219 ah->ah_config.antenna_switch_swap;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001220
1221 ahp->ah_staId1Defaults = AR_STA_ID1_CRPT_MIC_ENABLE;
1222 ahp->ah_beaconInterval = 100;
1223 ahp->ah_enable32kHzClock = DONT_USE_32KHZ;
1224 ahp->ah_slottime = (u32) -1;
1225 ahp->ah_acktimeout = (u32) -1;
1226 ahp->ah_ctstimeout = (u32) -1;
1227 ahp->ah_globaltxtimeout = (u32) -1;
1228 memcpy(&ahp->ah_bssidmask, defbssidmask, ETH_ALEN);
1229
1230 ahp->ah_gBeaconRate = 0;
1231
1232 return ahp;
1233}
1234
1235static int ath9k_hw_eeprom_attach(struct ath_hal *ah)
1236{
1237 int status;
1238
1239 if (ath9k_hw_use_flash(ah))
1240 ath9k_hw_flash_map(ah);
1241
1242 if (!ath9k_hw_fill_eeprom(ah))
1243 return -EIO;
1244
1245 status = ath9k_hw_check_eeprom(ah);
1246
1247 return status;
1248}
1249
1250u32 ath9k_hw_get_eeprom(struct ath_hal_5416 *ahp,
1251 enum eeprom_param param)
1252{
1253 struct ar5416_eeprom *eep = &ahp->ah_eeprom;
1254 struct modal_eep_header *pModal = eep->modalHeader;
1255 struct base_eep_header *pBase = &eep->baseEepHeader;
1256
1257 switch (param) {
1258 case EEP_NFTHRESH_5:
1259 return -pModal[0].noiseFloorThreshCh[0];
1260 case EEP_NFTHRESH_2:
1261 return -pModal[1].noiseFloorThreshCh[0];
1262 case AR_EEPROM_MAC(0):
1263 return pBase->macAddr[0] << 8 | pBase->macAddr[1];
1264 case AR_EEPROM_MAC(1):
1265 return pBase->macAddr[2] << 8 | pBase->macAddr[3];
1266 case AR_EEPROM_MAC(2):
1267 return pBase->macAddr[4] << 8 | pBase->macAddr[5];
1268 case EEP_REG_0:
1269 return pBase->regDmn[0];
1270 case EEP_REG_1:
1271 return pBase->regDmn[1];
1272 case EEP_OP_CAP:
1273 return pBase->deviceCap;
1274 case EEP_OP_MODE:
1275 return pBase->opCapFlags;
1276 case EEP_RF_SILENT:
1277 return pBase->rfSilent;
1278 case EEP_OB_5:
1279 return pModal[0].ob;
1280 case EEP_DB_5:
1281 return pModal[0].db;
1282 case EEP_OB_2:
1283 return pModal[1].ob;
1284 case EEP_DB_2:
1285 return pModal[1].db;
1286 case EEP_MINOR_REV:
1287 return pBase->version & AR5416_EEP_VER_MINOR_MASK;
1288 case EEP_TX_MASK:
1289 return pBase->txMask;
1290 case EEP_RX_MASK:
1291 return pBase->rxMask;
1292 default:
1293 return 0;
1294 }
1295}
1296
1297static inline int ath9k_hw_get_radiorev(struct ath_hal *ah)
1298{
1299 u32 val;
1300 int i;
1301
1302 REG_WRITE(ah, AR_PHY(0x36), 0x00007058);
1303 for (i = 0; i < 8; i++)
1304 REG_WRITE(ah, AR_PHY(0x20), 0x00010000);
1305 val = (REG_READ(ah, AR_PHY(256)) >> 24) & 0xff;
1306 val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4);
1307 return ath9k_hw_reverse_bits(val, 8);
1308}
1309
1310static inline int ath9k_hw_init_macaddr(struct ath_hal *ah)
1311{
1312 u32 sum;
1313 int i;
1314 u16 eeval;
1315 struct ath_hal_5416 *ahp = AH5416(ah);
1316 DECLARE_MAC_BUF(mac);
1317
1318 sum = 0;
1319 for (i = 0; i < 3; i++) {
1320 eeval = ath9k_hw_get_eeprom(ahp, AR_EEPROM_MAC(i));
1321 sum += eeval;
1322 ahp->ah_macaddr[2 * i] = eeval >> 8;
1323 ahp->ah_macaddr[2 * i + 1] = eeval & 0xff;
1324 }
1325 if (sum == 0 || sum == 0xffff * 3) {
1326 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
1327 "%s: mac address read failed: %s\n", __func__,
1328 print_mac(mac, ahp->ah_macaddr));
1329 return -EADDRNOTAVAIL;
1330 }
1331
1332 return 0;
1333}
1334
1335static inline int16_t ath9k_hw_interpolate(u16 target,
1336 u16 srcLeft,
1337 u16 srcRight,
1338 int16_t targetLeft,
1339 int16_t targetRight)
1340{
1341 int16_t rv;
1342
1343 if (srcRight == srcLeft) {
1344 rv = targetLeft;
1345 } else {
1346 rv = (int16_t) (((target - srcLeft) * targetRight +
1347 (srcRight - target) * targetLeft) /
1348 (srcRight - srcLeft));
1349 }
1350 return rv;
1351}
1352
1353static inline u16 ath9k_hw_fbin2freq(u8 fbin,
1354 bool is2GHz)
1355{
1356
1357 if (fbin == AR5416_BCHAN_UNUSED)
1358 return fbin;
1359
1360 return (u16) ((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin));
1361}
1362
1363static u16 ath9k_hw_eeprom_get_spur_chan(struct ath_hal *ah,
1364 u16 i,
1365 bool is2GHz)
1366{
1367 struct ath_hal_5416 *ahp = AH5416(ah);
1368 struct ar5416_eeprom *eep =
1369 (struct ar5416_eeprom *) &ahp->ah_eeprom;
1370 u16 spur_val = AR_NO_SPUR;
1371
1372 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
1373 "Getting spur idx %d is2Ghz. %d val %x\n",
Sujith60b67f52008-08-07 10:52:38 +05301374 i, is2GHz, ah->ah_config.spurchans[i][is2GHz]);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001375
Sujith60b67f52008-08-07 10:52:38 +05301376 switch (ah->ah_config.spurmode) {
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001377 case SPUR_DISABLE:
1378 break;
1379 case SPUR_ENABLE_IOCTL:
Sujith60b67f52008-08-07 10:52:38 +05301380 spur_val = ah->ah_config.spurchans[i][is2GHz];
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07001381 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
1382 "Getting spur val from new loc. %d\n", spur_val);
1383 break;
1384 case SPUR_ENABLE_EEPROM:
1385 spur_val = eep->modalHeader[is2GHz].spurChans[i].spurChan;
1386 break;
1387
1388 }
1389 return spur_val;
1390}
1391
1392static inline int ath9k_hw_rfattach(struct ath_hal *ah)
1393{
1394 bool rfStatus = false;
1395 int ecode = 0;
1396
1397 rfStatus = ath9k_hw_init_rf(ah, &ecode);
1398 if (!rfStatus) {
1399 DPRINTF(ah->ah_sc, ATH_DBG_RESET,
1400 "%s: RF setup failed, status %u\n", __func__,
1401 ecode);
1402 return ecode;
1403 }
1404
1405 return 0;
1406}
1407
1408static int ath9k_hw_rf_claim(struct ath_hal *ah)
1409{
1410 u32 val;
1411
1412 REG_WRITE(ah, AR_PHY(0), 0x00000007);
1413
1414 val = ath9k_hw_get_radiorev(ah);
1415 switch (val & AR_RADIO_SREV_MAJOR) {
1416 case 0:
1417 val = AR_RAD5133_SREV_MAJOR;
1418 break;
1419 case AR_RAD5133_SREV_MAJOR:
1420 case AR_RAD5122_SREV_MAJOR:
1421 case AR_RAD2133_SREV_MAJOR:
1422 case AR_RAD2122_SREV_MAJOR:
1423 break;
1424 default:
1425 DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
1426 "%s: 5G Radio Chip Rev 0x%02X is not "
1427 "supported by this driver\n",
1428 __func__, ah->ah_analog5GhzRev);
1429 return -EOPNOTSUPP;
1430 }
1431
1432 ah->ah_analog5GhzRev = val;
1433
1434 return 0;
1435}
1436
1437static inline void ath9k_hw_init_pll(struct ath_hal *ah,
1438 struct ath9k_channel *chan)
1439{
1440 u32 pll;
1441
1442 if (AR_SREV_9100(ah)) {
1443 if (chan && IS_CHAN_5GHZ(chan))
1444 pll = 0x1450;
1445 else
1446 pll = 0x1458;
1447 } else {
1448 if (AR_SREV_9280_10_OR_LATER(ah)) {
1449 pll = SM(0x5, AR_RTC_9160_PLL_REFDIV);
1450
1451 if (chan && IS_CHAN_HALF_RATE(chan))
1452 pll |= SM(0x1, AR_RTC_9160_PLL_CLKSEL);
1453 else if (chan && IS_CHAN_QUARTER_RATE(chan))
1454 pll |= SM(0x2, AR_RTC_9160_PLL_CLKSEL);
1455
1456 if (chan && IS_CHAN_5GHZ(chan)) {
1457 pll |= SM(0x28, AR_RTC_9160_PLL_DIV);
1458
1459
1460 if (AR_SREV_9280_20(ah)) {
1461 if (((chan->channel % 20) == 0)
1462 || ((chan->channel % 10) == 0))
1463 pll = 0x2850;
1464 else
1465 pll = 0x142c;
1466 }
1467 } else {
1468 pll |= SM(0x2c, AR_RTC_9160_PLL_DIV);
1469 }
1470
1471 } else if (AR_SREV_9160_10_OR_LATER(ah)) {
1472
1473 pll = SM(0x5, AR_RTC_9160_PLL_REFDIV);
1474
1475 if (chan && IS_CHAN_HALF_RATE(chan))
1476 pll |= SM(0x1, AR_RTC_9160_PLL_CLKSEL);
1477 else if (chan && IS_CHAN_QUARTER_RATE(chan))
1478 pll |= SM(0x2, AR_RTC_9160_PLL_CLKSEL);
1479
1480 if (chan && IS_CHAN_5GHZ(chan))
1481 pll |= SM(0x50, AR_RTC_9160_PLL_DIV);
1482 else
1483 pll |= SM(0x58, AR_RTC_9160_PLL_DIV);
1484 } else {
1485 pll = AR_RTC_PLL_REFDIV_5 | AR_RTC_PLL_DIV2;
1486
1487 if (chan && IS_CHAN_HALF_RATE(chan))
1488 pll |= SM(0x1, AR_RTC_PLL_CLKSEL);
1489 else if (chan && IS_CHAN_QUARTER_RATE(chan))
1490 pll |= SM(0x2, AR_RTC_PLL_CLKSEL);
1491
1492 if (chan && IS_CHAN_5GHZ(chan))
1493 pll |= SM(0xa, AR_RTC_PLL_DIV);
1494 else
1495 pll |= SM(0xb, AR_RTC_PLL_DIV);
1496 }
1497 }
1498 REG_WRITE(ah, (u16) (AR_RTC_PLL_CONTROL), pll);
1499
1500 udelay(RTC_PLL_SETTLE_DELAY);
1501
1502 REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_FORCE_DERIVED_CLK);
1503}
1504
1505static void ath9k_hw_set_regs(struct ath_hal *ah, struct ath9k_channel *chan,
1506 enum ath9k_ht_macmode macmode)
1507{
1508 u32 phymode;
1509 struct ath_hal_5416 *ahp = AH5416(ah);
1510
1511 phymode = AR_PHY_FC_HT_EN | AR_PHY_FC_SHORT_GI_40
1512 | AR_PHY_FC_SINGLE_HT_LTF1 | AR_PHY_FC_WALSH;
1513
1514 if (IS_CHAN_HT40(chan)) {
1515 phymode |= AR_PHY_FC_DYN2040_EN;
1516
1517 if ((chan->chanmode == CHANNEL_A_HT40PLUS) ||
1518 (chan->chanmode == CHANNEL_G_HT40PLUS))
1519 phymode |= AR_PHY_FC_DYN2040_PRI_CH;
1520
1521 if (ahp->ah_extprotspacing == ATH9K_HT_EXTPROTSPACING_25)
1522 phymode |= AR_PHY_FC_DYN2040_EXT_CH;
1523 }
1524 REG_WRITE(ah, AR_PHY_TURBO, phymode);
1525
1526 ath9k_hw_set11nmac2040(ah, macmode);
1527
1528 REG_WRITE(ah, AR_GTXTO, 25 << AR_GTXTO_TIMEOUT_LIMIT_S);
1529 REG_WRITE(ah, AR_CST, 0xF << AR_CST_TIMEOUT_LIMIT_S);
1530}
1531
1532static void ath9k_hw_set_operating_mode(struct ath_hal *ah, int opmode)
1533{
1534 u32 val;
1535
1536 val = REG_READ(ah, AR_STA_ID1);
1537 val &= ~(AR_STA_ID1_STA_AP | AR_STA_ID1_ADHOC);
1538 switch (opmode) {
1539 case ATH9K_M_HOSTAP:
1540 REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_STA_AP
1541 | AR_STA_ID1_KSRCH_MODE);
1542 REG_CLR_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION);
1543 break;
1544 case ATH9K_M_IBSS:
1545 REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_ADHOC
1546 | AR_STA_ID1_KSRCH_MODE);
1547 REG_SET_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION);
1548 break;
1549 case ATH9K_M_STA:
1550 case ATH9K_M_MONITOR:
1551 REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_KSRCH_MODE);
1552 break;
1553 }
1554}
1555
1556static inline void
1557ath9k_hw_set_rfmode(struct ath_hal *ah, struct ath9k_channel *chan)
1558{
1559 u32 rfMode = 0;
1560
1561 if (chan == NULL)
1562 return;
1563
1564 rfMode |= (IS_CHAN_B(chan) || IS_CHAN_G(chan))
1565 ? AR_PHY_MODE_DYNAMIC : AR_PHY_MODE_OFDM;
1566
1567 if (!AR_SREV_9280_10_OR_LATER(ah))
1568 rfMode |= (IS_CHAN_5GHZ(chan)) ? AR_PHY_MODE_RF5GHZ :
1569 AR_PHY_MODE_RF2GHZ;
1570
1571 if (AR_SREV_9280_20(ah) && IS_CHAN_A_5MHZ_SPACED(chan))
1572 rfMode |= (AR_PHY_MODE_DYNAMIC | AR_PHY_MODE_DYN_CCK_DISABLE);
1573
1574 REG_WRITE(ah, AR_PHY_MODE, rfMode);
1575}
1576
1577static bool ath9k_hw_set_reset(struct ath_hal *ah, int type)
1578{
1579 u32 rst_flags;
1580 u32 tmpReg;
1581
1582 REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN |
1583 AR_RTC_FORCE_WAKE_ON_INT);
1584
1585 if (AR_SREV_9100(ah)) {
1586 rst_flags = AR_RTC_RC_MAC_WARM | AR_RTC_RC_MAC_COLD |
1587 AR_RTC_RC_COLD_RESET | AR_RTC_RC_WARM_RESET;
1588 } else {
1589 tmpReg = REG_READ(ah, AR_INTR_SYNC_CAUSE);
1590 if (tmpReg &
1591 (AR_INTR_SYNC_LOCAL_TIMEOUT |
1592 AR_INTR_SYNC_RADM_CPL_TIMEOUT)) {
1593 REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0);
1594 REG_WRITE(ah, AR_RC, AR_RC_AHB | AR_RC_HOSTIF);
1595 } else {
1596 REG_WRITE(ah, AR_RC, AR_RC_AHB);
1597 }
1598
1599 rst_flags = AR_RTC_RC_MAC_WARM;
1600 if (type == ATH9K_RESET_COLD)
1601 rst_flags |= AR_RTC_RC_MAC_COLD;
1602 }
1603
1604 REG_WRITE(ah, (u16) (AR_RTC_RC), rst_flags);
1605 udelay(50);
1606
1607 REG_WRITE(ah, (u16) (AR_RTC_RC), 0);
1608 if (!ath9k_hw_wait(ah, (u16) (AR_RTC_RC), AR_RTC_RC_M, 0)) {
1609 DPRINTF(ah->ah_sc, ATH_DBG_RESET,
1610 "%s: RTC stuck in MAC reset\n",
1611 __func__);
1612 return false;
1613 }
1614
1615 if (!AR_SREV_9100(ah))
1616 REG_WRITE(ah, AR_RC, 0);
1617
1618 ath9k_hw_init_pll(ah, NULL);
1619
1620 if (AR_SREV_9100(ah))
1621 udelay(50);
1622
1623 return true;
1624}
1625
1626static inline bool ath9k_hw_set_reset_power_on(struct ath_hal *ah)
1627{
1628 REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN |
1629 AR_RTC_FORCE_WAKE_ON_INT);
1630
1631 REG_WRITE(ah, (u16) (AR_RTC_RESET), 0);
1632 REG_WRITE(ah, (u16) (AR_RTC_RESET), 1);
1633
1634 if (!ath9k_hw_wait(ah,
1635 AR_RTC_STATUS,
1636 AR_RTC_STATUS_M,
1637 AR_RTC_STATUS_ON)) {
1638 DPRINTF(ah->ah_sc, ATH_DBG_RESET, "%s: RTC not waking up\n",
1639 __func__);
1640 return false;
1641 }
1642
1643 ath9k_hw_read_revisions(ah);
1644
1645 return ath9k_hw_set_reset(ah, ATH9K_RESET_WARM);
1646}
1647
1648static bool ath9k_hw_set_reset_reg(struct ath_hal *ah,
1649 u32 type)
1650{
1651 REG_WRITE(ah, AR_RTC_FORCE_WAKE,
1652 AR_RTC_FORCE_WAKE_EN | AR_RTC_FORCE_WAKE_ON_INT);
1653
1654 switch (type) {
1655 case ATH9K_RESET_POWER_ON:
1656 return ath9k_hw_set_reset_power_on(ah);
1657 break;
1658 case ATH9K_RESET_WARM:
1659 case ATH9K_RESET_COLD:
1660 return ath9k_hw_set_reset(ah, type);
1661 break;
1662 default:
1663 return false;
1664 }
1665}
1666
1667static inline
1668struct ath9k_channel *ath9k_hw_check_chan(struct ath_hal *ah,
1669 struct ath9k_channel *chan)
1670{
1671 if (!(IS_CHAN_2GHZ(chan) ^ IS_CHAN_5GHZ(chan))) {
1672 DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
1673 "%s: invalid channel %u/0x%x; not marked as "
1674 "2GHz or 5GHz\n", __func__, chan->channel,
1675 chan->channelFlags);
1676 return NULL;
1677 }
1678
1679 if (!IS_CHAN_OFDM(chan) &&
1680 !IS_CHAN_CCK(chan) &&
1681 !IS_CHAN_HT20(chan) &&
1682 !IS_CHAN_HT40(chan)) {
1683 DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
1684 "%s: invalid channel %u/0x%x; not marked as "
1685 "OFDM or CCK or HT20 or HT40PLUS or HT40MINUS\n",
1686 __func__, chan->channel, chan->channelFlags);
1687 return NULL;
1688 }
1689
1690 return ath9k_regd_check_channel(ah, chan);
1691}
1692
1693static inline bool
1694ath9k_hw_get_lower_upper_index(u8 target,
1695 u8 *pList,
1696 u16 listSize,
1697 u16 *indexL,
1698 u16 *indexR)
1699{
1700 u16 i;
1701
1702 if (target <= pList[0]) {
1703 *indexL = *indexR = 0;
1704 return true;
1705 }
1706 if (target >= pList[listSize - 1]) {
1707 *indexL = *indexR = (u16) (listSize - 1);
1708 return true;
1709 }
1710
1711 for (i = 0; i < listSize - 1; i++) {
1712 if (pList[i] == target) {
1713 *indexL = *indexR = i;
1714 return true;
1715 }
1716 if (target < pList[i + 1]) {
1717 *indexL = i;
1718 *indexR = (u16) (i + 1);
1719 return false;
1720 }
1721 }
1722 return false;
1723}
1724
1725static int16_t ath9k_hw_get_nf_hist_mid(int16_t *nfCalBuffer)
1726{
1727 int16_t nfval;
1728 int16_t sort[ATH9K_NF_CAL_HIST_MAX];
1729 int i, j;
1730
1731 for (i = 0; i < ATH9K_NF_CAL_HIST_MAX; i++)
1732 sort[i] = nfCalBuffer[i];
1733
1734 for (i = 0; i < ATH9K_NF_CAL_HIST_MAX - 1; i++) {
1735 for (j = 1; j < ATH9K_NF_CAL_HIST_MAX - i; j++) {
1736 if (sort[j] > sort[j - 1]) {
1737 nfval = sort[j];
1738 sort[j] = sort[j - 1];
1739 sort[j - 1] = nfval;
1740 }
1741 }
1742 }
1743 nfval = sort[(ATH9K_NF_CAL_HIST_MAX - 1) >> 1];
1744
1745 return nfval;
1746}
1747
1748static void ath9k_hw_update_nfcal_hist_buffer(struct ath9k_nfcal_hist *h,
1749 int16_t *nfarray)
1750{
1751 int i;
1752
1753 for (i = 0; i < NUM_NF_READINGS; i++) {
1754 h[i].nfCalBuffer[h[i].currIndex] = nfarray[i];
1755
1756 if (++h[i].currIndex >= ATH9K_NF_CAL_HIST_MAX)
1757 h[i].currIndex = 0;
1758
1759 if (h[i].invalidNFcount > 0) {
1760 if (nfarray[i] < AR_PHY_CCA_MIN_BAD_VALUE
1761 || nfarray[i] > AR_PHY_CCA_MAX_HIGH_VALUE) {
1762 h[i].invalidNFcount = ATH9K_NF_CAL_HIST_MAX;
1763 } else {
1764 h[i].invalidNFcount--;
1765 h[i].privNF = nfarray[i];
1766 }
1767 } else {
1768 h[i].privNF =
1769 ath9k_hw_get_nf_hist_mid(h[i].nfCalBuffer);
1770 }
1771 }
1772 return;
1773}
1774
1775static void ar5416GetNoiseFloor(struct ath_hal *ah,
1776 int16_t nfarray[NUM_NF_READINGS])
1777{
1778 int16_t nf;
1779
1780 if (AR_SREV_9280_10_OR_LATER(ah))
1781 nf = MS(REG_READ(ah, AR_PHY_CCA), AR9280_PHY_MINCCA_PWR);
1782 else
1783 nf = MS(REG_READ(ah, AR_PHY_CCA), AR_PHY_MINCCA_PWR);
1784
1785 if (nf & 0x100)
1786 nf = 0 - ((nf ^ 0x1ff) + 1);
1787 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
1788 "NF calibrated [ctl] [chain 0] is %d\n", nf);
1789 nfarray[0] = nf;
1790
1791 if (AR_SREV_9280_10_OR_LATER(ah))
1792 nf = MS(REG_READ(ah, AR_PHY_CH1_CCA),
1793 AR9280_PHY_CH1_MINCCA_PWR);
1794 else
1795 nf = MS(REG_READ(ah, AR_PHY_CH1_CCA),
1796 AR_PHY_CH1_MINCCA_PWR);
1797
1798 if (nf & 0x100)
1799 nf = 0 - ((nf ^ 0x1ff) + 1);
1800 DPRINTF(ah->ah_sc, ATH_DBG_NF_CAL,
1801 "NF calibrated [ctl] [chain 1] is %d\n", nf);
1802 nfarray[1] = nf;
1803
1804 if (!AR_SREV_9280(ah)) {
1805 nf = MS(REG_READ(ah, AR_PHY_CH2_CCA),
1806 AR_PHY_CH2_MINCCA_PWR);
1807 if (nf & 0x100)
1808 nf = 0 - ((nf ^ 0x1ff) + 1);
1809 DPRINTF(ah->ah_sc, ATH_DBG_NF_CAL,
1810 "NF calibrated [ctl] [chain 2] is %d\n", nf);
1811 nfarray[2] = nf;
1812 }
1813
1814 if (AR_SREV_9280_10_OR_LATER(ah))
1815 nf = MS(REG_READ(ah, AR_PHY_EXT_CCA),
1816 AR9280_PHY_EXT_MINCCA_PWR);
1817 else
1818 nf = MS(REG_READ(ah, AR_PHY_EXT_CCA),
1819 AR_PHY_EXT_MINCCA_PWR);
1820
1821 if (nf & 0x100)
1822 nf = 0 - ((nf ^ 0x1ff) + 1);
1823 DPRINTF(ah->ah_sc, ATH_DBG_NF_CAL,
1824 "NF calibrated [ext] [chain 0] is %d\n", nf);
1825 nfarray[3] = nf;
1826
1827 if (AR_SREV_9280_10_OR_LATER(ah))
1828 nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA),
1829 AR9280_PHY_CH1_EXT_MINCCA_PWR);
1830 else
1831 nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA),
1832 AR_PHY_CH1_EXT_MINCCA_PWR);
1833
1834 if (nf & 0x100)
1835 nf = 0 - ((nf ^ 0x1ff) + 1);
1836 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
1837 "NF calibrated [ext] [chain 1] is %d\n", nf);
1838 nfarray[4] = nf;
1839
1840 if (!AR_SREV_9280(ah)) {
1841 nf = MS(REG_READ(ah, AR_PHY_CH2_EXT_CCA),
1842 AR_PHY_CH2_EXT_MINCCA_PWR);
1843 if (nf & 0x100)
1844 nf = 0 - ((nf ^ 0x1ff) + 1);
1845 DPRINTF(ah->ah_sc, ATH_DBG_NF_CAL,
1846 "NF calibrated [ext] [chain 2] is %d\n", nf);
1847 nfarray[5] = nf;
1848 }
1849}
1850
1851static bool
1852getNoiseFloorThresh(struct ath_hal *ah,
1853 const struct ath9k_channel *chan,
1854 int16_t *nft)
1855{
1856 struct ath_hal_5416 *ahp = AH5416(ah);
1857
1858 switch (chan->chanmode) {
1859 case CHANNEL_A:
1860 case CHANNEL_A_HT20:
1861 case CHANNEL_A_HT40PLUS:
1862 case CHANNEL_A_HT40MINUS:
1863 *nft = (int16_t) ath9k_hw_get_eeprom(ahp, EEP_NFTHRESH_5);
1864 break;
1865 case CHANNEL_B:
1866 case CHANNEL_G:
1867 case CHANNEL_G_HT20:
1868 case CHANNEL_G_HT40PLUS:
1869 case CHANNEL_G_HT40MINUS:
1870 *nft = (int16_t) ath9k_hw_get_eeprom(ahp, EEP_NFTHRESH_2);
1871 break;
1872 default:
1873 DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
1874 "%s: invalid channel flags 0x%x\n", __func__,
1875 chan->channelFlags);
1876 return false;
1877 }
1878 return true;
1879}
1880
1881static void ath9k_hw_start_nfcal(struct ath_hal *ah)
1882{
1883 REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
1884 AR_PHY_AGC_CONTROL_ENABLE_NF);
1885 REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
1886 AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
1887 REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
1888}
1889
1890static void
1891ath9k_hw_loadnf(struct ath_hal *ah, struct ath9k_channel *chan)
1892{
1893 struct ath9k_nfcal_hist *h;
1894 int i, j;
1895 int32_t val;
1896 const u32 ar5416_cca_regs[6] = {
1897 AR_PHY_CCA,
1898 AR_PHY_CH1_CCA,
1899 AR_PHY_CH2_CCA,
1900 AR_PHY_EXT_CCA,
1901 AR_PHY_CH1_EXT_CCA,
1902 AR_PHY_CH2_EXT_CCA
1903 };
1904 u8 chainmask;
1905
1906 if (AR_SREV_9280(ah))
1907 chainmask = 0x1B;
1908 else
1909 chainmask = 0x3F;
1910
1911#ifdef ATH_NF_PER_CHAN
1912 h = chan->nfCalHist;
1913#else
1914 h = ah->nfCalHist;
1915#endif
1916
1917 for (i = 0; i < NUM_NF_READINGS; i++) {
1918 if (chainmask & (1 << i)) {
1919 val = REG_READ(ah, ar5416_cca_regs[i]);
1920 val &= 0xFFFFFE00;
1921 val |= (((u32) (h[i].privNF) << 1) & 0x1ff);
1922 REG_WRITE(ah, ar5416_cca_regs[i], val);
1923 }
1924 }
1925
1926 REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
1927 AR_PHY_AGC_CONTROL_ENABLE_NF);
1928 REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
1929 AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
1930 REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
1931
1932 for (j = 0; j < 1000; j++) {
1933 if ((REG_READ(ah, AR_PHY_AGC_CONTROL) &
1934 AR_PHY_AGC_CONTROL_NF) == 0)
1935 break;
1936 udelay(10);
1937 }
1938
1939 for (i = 0; i < NUM_NF_READINGS; i++) {
1940 if (chainmask & (1 << i)) {
1941 val = REG_READ(ah, ar5416_cca_regs[i]);
1942 val &= 0xFFFFFE00;
1943 val |= (((u32) (-50) << 1) & 0x1ff);
1944 REG_WRITE(ah, ar5416_cca_regs[i], val);
1945 }
1946 }
1947}
1948
1949static int16_t ath9k_hw_getnf(struct ath_hal *ah,
1950 struct ath9k_channel *chan)
1951{
1952 int16_t nf, nfThresh;
1953 int16_t nfarray[NUM_NF_READINGS] = { 0 };
1954 struct ath9k_nfcal_hist *h;
1955 u8 chainmask;
1956
1957 if (AR_SREV_9280(ah))
1958 chainmask = 0x1B;
1959 else
1960 chainmask = 0x3F;
1961
1962 chan->channelFlags &= (~CHANNEL_CW_INT);
1963 if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) {
1964 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
1965 "%s: NF did not complete in calibration window\n",
1966 __func__);
1967 nf = 0;
1968 chan->rawNoiseFloor = nf;
1969 return chan->rawNoiseFloor;
1970 } else {
1971 ar5416GetNoiseFloor(ah, nfarray);
1972 nf = nfarray[0];
1973 if (getNoiseFloorThresh(ah, chan, &nfThresh)
1974 && nf > nfThresh) {
1975 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
1976 "%s: noise floor failed detected; "
1977 "detected %d, threshold %d\n", __func__,
1978 nf, nfThresh);
1979 chan->channelFlags |= CHANNEL_CW_INT;
1980 }
1981 }
1982
1983#ifdef ATH_NF_PER_CHAN
1984 h = chan->nfCalHist;
1985#else
1986 h = ah->nfCalHist;
1987#endif
1988
1989 ath9k_hw_update_nfcal_hist_buffer(h, nfarray);
1990 chan->rawNoiseFloor = h[0].privNF;
1991
1992 return chan->rawNoiseFloor;
1993}
1994
1995static void ath9k_hw_update_mibstats(struct ath_hal *ah,
1996 struct ath9k_mib_stats *stats)
1997{
1998 stats->ackrcv_bad += REG_READ(ah, AR_ACK_FAIL);
1999 stats->rts_bad += REG_READ(ah, AR_RTS_FAIL);
2000 stats->fcs_bad += REG_READ(ah, AR_FCS_FAIL);
2001 stats->rts_good += REG_READ(ah, AR_RTS_OK);
2002 stats->beacons += REG_READ(ah, AR_BEACON_CNT);
2003}
2004
2005static void ath9k_enable_mib_counters(struct ath_hal *ah)
2006{
2007 struct ath_hal_5416 *ahp = AH5416(ah);
2008
2009 DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Enable mib counters\n");
2010
2011 ath9k_hw_update_mibstats(ah, &ahp->ah_mibStats);
2012
2013 REG_WRITE(ah, AR_FILT_OFDM, 0);
2014 REG_WRITE(ah, AR_FILT_CCK, 0);
2015 REG_WRITE(ah, AR_MIBC,
2016 ~(AR_MIBC_COW | AR_MIBC_FMC | AR_MIBC_CMC | AR_MIBC_MCS)
2017 & 0x0f);
2018 REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
2019 REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
2020}
2021
2022static void ath9k_hw_disable_mib_counters(struct ath_hal *ah)
2023{
2024 struct ath_hal_5416 *ahp = AH5416(ah);
2025
2026 DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Disabling MIB counters\n");
2027
2028 REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC | AR_MIBC_CMC);
2029
2030 ath9k_hw_update_mibstats(ah, &ahp->ah_mibStats);
2031
2032 REG_WRITE(ah, AR_FILT_OFDM, 0);
2033 REG_WRITE(ah, AR_FILT_CCK, 0);
2034}
2035
2036static int ath9k_hw_get_ani_channel_idx(struct ath_hal *ah,
2037 struct ath9k_channel *chan)
2038{
2039 struct ath_hal_5416 *ahp = AH5416(ah);
2040 int i;
2041
2042 for (i = 0; i < ARRAY_SIZE(ahp->ah_ani); i++) {
2043 if (ahp->ah_ani[i].c.channel == chan->channel)
2044 return i;
2045 if (ahp->ah_ani[i].c.channel == 0) {
2046 ahp->ah_ani[i].c.channel = chan->channel;
2047 ahp->ah_ani[i].c.channelFlags = chan->channelFlags;
2048 return i;
2049 }
2050 }
2051
2052 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
2053 "No more channel states left. Using channel 0\n");
2054 return 0;
2055}
2056
2057static void ath9k_hw_ani_attach(struct ath_hal *ah)
2058{
2059 struct ath_hal_5416 *ahp = AH5416(ah);
2060 int i;
2061
2062 ahp->ah_hasHwPhyCounters = 1;
2063
2064 memset(ahp->ah_ani, 0, sizeof(ahp->ah_ani));
2065 for (i = 0; i < ARRAY_SIZE(ahp->ah_ani); i++) {
2066 ahp->ah_ani[i].ofdmTrigHigh = ATH9K_ANI_OFDM_TRIG_HIGH;
2067 ahp->ah_ani[i].ofdmTrigLow = ATH9K_ANI_OFDM_TRIG_LOW;
2068 ahp->ah_ani[i].cckTrigHigh = ATH9K_ANI_CCK_TRIG_HIGH;
2069 ahp->ah_ani[i].cckTrigLow = ATH9K_ANI_CCK_TRIG_LOW;
2070 ahp->ah_ani[i].rssiThrHigh = ATH9K_ANI_RSSI_THR_HIGH;
2071 ahp->ah_ani[i].rssiThrLow = ATH9K_ANI_RSSI_THR_LOW;
2072 ahp->ah_ani[i].ofdmWeakSigDetectOff =
2073 !ATH9K_ANI_USE_OFDM_WEAK_SIG;
2074 ahp->ah_ani[i].cckWeakSigThreshold =
2075 ATH9K_ANI_CCK_WEAK_SIG_THR;
2076 ahp->ah_ani[i].spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL;
2077 ahp->ah_ani[i].firstepLevel = ATH9K_ANI_FIRSTEP_LVL;
2078 if (ahp->ah_hasHwPhyCounters) {
2079 ahp->ah_ani[i].ofdmPhyErrBase =
2080 AR_PHY_COUNTMAX - ATH9K_ANI_OFDM_TRIG_HIGH;
2081 ahp->ah_ani[i].cckPhyErrBase =
2082 AR_PHY_COUNTMAX - ATH9K_ANI_CCK_TRIG_HIGH;
2083 }
2084 }
2085 if (ahp->ah_hasHwPhyCounters) {
2086 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
2087 "Setting OfdmErrBase = 0x%08x\n",
2088 ahp->ah_ani[0].ofdmPhyErrBase);
2089 DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Setting cckErrBase = 0x%08x\n",
2090 ahp->ah_ani[0].cckPhyErrBase);
2091
2092 REG_WRITE(ah, AR_PHY_ERR_1, ahp->ah_ani[0].ofdmPhyErrBase);
2093 REG_WRITE(ah, AR_PHY_ERR_2, ahp->ah_ani[0].cckPhyErrBase);
2094 ath9k_enable_mib_counters(ah);
2095 }
2096 ahp->ah_aniPeriod = ATH9K_ANI_PERIOD;
Sujith60b67f52008-08-07 10:52:38 +05302097 if (ah->ah_config.enable_ani)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002098 ahp->ah_procPhyErr |= HAL_PROCESS_ANI;
2099}
2100
2101static inline void ath9k_hw_ani_setup(struct ath_hal *ah)
2102{
2103 struct ath_hal_5416 *ahp = AH5416(ah);
2104 int i;
2105
2106 const int totalSizeDesired[] = { -55, -55, -55, -55, -62 };
2107 const int coarseHigh[] = { -14, -14, -14, -14, -12 };
2108 const int coarseLow[] = { -64, -64, -64, -64, -70 };
2109 const int firpwr[] = { -78, -78, -78, -78, -80 };
2110
2111 for (i = 0; i < 5; i++) {
2112 ahp->ah_totalSizeDesired[i] = totalSizeDesired[i];
2113 ahp->ah_coarseHigh[i] = coarseHigh[i];
2114 ahp->ah_coarseLow[i] = coarseLow[i];
2115 ahp->ah_firpwr[i] = firpwr[i];
2116 }
2117}
2118
2119static void ath9k_hw_ani_detach(struct ath_hal *ah)
2120{
2121 struct ath_hal_5416 *ahp = AH5416(ah);
2122
2123 DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Detaching Ani\n");
2124 if (ahp->ah_hasHwPhyCounters) {
2125 ath9k_hw_disable_mib_counters(ah);
2126 REG_WRITE(ah, AR_PHY_ERR_1, 0);
2127 REG_WRITE(ah, AR_PHY_ERR_2, 0);
2128 }
2129}
2130
2131
2132static bool ath9k_hw_ani_control(struct ath_hal *ah,
2133 enum ath9k_ani_cmd cmd, int param)
2134{
2135 struct ath_hal_5416 *ahp = AH5416(ah);
2136 struct ar5416AniState *aniState = ahp->ah_curani;
2137
2138 switch (cmd & ahp->ah_ani_function) {
2139 case ATH9K_ANI_NOISE_IMMUNITY_LEVEL:{
2140 u32 level = param;
2141
2142 if (level >= ARRAY_SIZE(ahp->ah_totalSizeDesired)) {
2143 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
2144 "%s: level out of range (%u > %u)\n",
2145 __func__, level,
2146 (unsigned) ARRAY_SIZE(ahp->
2147 ah_totalSizeDesired));
2148 return false;
2149 }
2150
2151 REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
2152 AR_PHY_DESIRED_SZ_TOT_DES,
2153 ahp->ah_totalSizeDesired[level]);
2154 REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1,
2155 AR_PHY_AGC_CTL1_COARSE_LOW,
2156 ahp->ah_coarseLow[level]);
2157 REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1,
2158 AR_PHY_AGC_CTL1_COARSE_HIGH,
2159 ahp->ah_coarseHigh[level]);
2160 REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
2161 AR_PHY_FIND_SIG_FIRPWR,
2162 ahp->ah_firpwr[level]);
2163
2164 if (level > aniState->noiseImmunityLevel)
2165 ahp->ah_stats.ast_ani_niup++;
2166 else if (level < aniState->noiseImmunityLevel)
2167 ahp->ah_stats.ast_ani_nidown++;
2168 aniState->noiseImmunityLevel = level;
2169 break;
2170 }
2171 case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{
2172 const int m1ThreshLow[] = { 127, 50 };
2173 const int m2ThreshLow[] = { 127, 40 };
2174 const int m1Thresh[] = { 127, 0x4d };
2175 const int m2Thresh[] = { 127, 0x40 };
2176 const int m2CountThr[] = { 31, 16 };
2177 const int m2CountThrLow[] = { 63, 48 };
2178 u32 on = param ? 1 : 0;
2179
2180 REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
2181 AR_PHY_SFCORR_LOW_M1_THRESH_LOW,
2182 m1ThreshLow[on]);
2183 REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
2184 AR_PHY_SFCORR_LOW_M2_THRESH_LOW,
2185 m2ThreshLow[on]);
2186 REG_RMW_FIELD(ah, AR_PHY_SFCORR,
2187 AR_PHY_SFCORR_M1_THRESH,
2188 m1Thresh[on]);
2189 REG_RMW_FIELD(ah, AR_PHY_SFCORR,
2190 AR_PHY_SFCORR_M2_THRESH,
2191 m2Thresh[on]);
2192 REG_RMW_FIELD(ah, AR_PHY_SFCORR,
2193 AR_PHY_SFCORR_M2COUNT_THR,
2194 m2CountThr[on]);
2195 REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
2196 AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW,
2197 m2CountThrLow[on]);
2198
2199 REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
2200 AR_PHY_SFCORR_EXT_M1_THRESH_LOW,
2201 m1ThreshLow[on]);
2202 REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
2203 AR_PHY_SFCORR_EXT_M2_THRESH_LOW,
2204 m2ThreshLow[on]);
2205 REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
2206 AR_PHY_SFCORR_EXT_M1_THRESH,
2207 m1Thresh[on]);
2208 REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
2209 AR_PHY_SFCORR_EXT_M2_THRESH,
2210 m2Thresh[on]);
2211
2212 if (on)
2213 REG_SET_BIT(ah, AR_PHY_SFCORR_LOW,
2214 AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
2215 else
2216 REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW,
2217 AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
2218
2219 if (!on != aniState->ofdmWeakSigDetectOff) {
2220 if (on)
2221 ahp->ah_stats.ast_ani_ofdmon++;
2222 else
2223 ahp->ah_stats.ast_ani_ofdmoff++;
2224 aniState->ofdmWeakSigDetectOff = !on;
2225 }
2226 break;
2227 }
2228 case ATH9K_ANI_CCK_WEAK_SIGNAL_THR:{
2229 const int weakSigThrCck[] = { 8, 6 };
2230 u32 high = param ? 1 : 0;
2231
2232 REG_RMW_FIELD(ah, AR_PHY_CCK_DETECT,
2233 AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK,
2234 weakSigThrCck[high]);
2235 if (high != aniState->cckWeakSigThreshold) {
2236 if (high)
2237 ahp->ah_stats.ast_ani_cckhigh++;
2238 else
2239 ahp->ah_stats.ast_ani_ccklow++;
2240 aniState->cckWeakSigThreshold = high;
2241 }
2242 break;
2243 }
2244 case ATH9K_ANI_FIRSTEP_LEVEL:{
2245 const int firstep[] = { 0, 4, 8 };
2246 u32 level = param;
2247
2248 if (level >= ARRAY_SIZE(firstep)) {
2249 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
2250 "%s: level out of range (%u > %u)\n",
2251 __func__, level,
2252 (unsigned) ARRAY_SIZE(firstep));
2253 return false;
2254 }
2255 REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
2256 AR_PHY_FIND_SIG_FIRSTEP,
2257 firstep[level]);
2258 if (level > aniState->firstepLevel)
2259 ahp->ah_stats.ast_ani_stepup++;
2260 else if (level < aniState->firstepLevel)
2261 ahp->ah_stats.ast_ani_stepdown++;
2262 aniState->firstepLevel = level;
2263 break;
2264 }
2265 case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{
2266 const int cycpwrThr1[] =
2267 { 2, 4, 6, 8, 10, 12, 14, 16 };
2268 u32 level = param;
2269
2270 if (level >= ARRAY_SIZE(cycpwrThr1)) {
2271 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
2272 "%s: level out of range (%u > %u)\n",
2273 __func__, level,
2274 (unsigned)
2275 ARRAY_SIZE(cycpwrThr1));
2276 return false;
2277 }
2278 REG_RMW_FIELD(ah, AR_PHY_TIMING5,
2279 AR_PHY_TIMING5_CYCPWR_THR1,
2280 cycpwrThr1[level]);
2281 if (level > aniState->spurImmunityLevel)
2282 ahp->ah_stats.ast_ani_spurup++;
2283 else if (level < aniState->spurImmunityLevel)
2284 ahp->ah_stats.ast_ani_spurdown++;
2285 aniState->spurImmunityLevel = level;
2286 break;
2287 }
2288 case ATH9K_ANI_PRESENT:
2289 break;
2290 default:
2291 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
2292 "%s: invalid cmd %u\n", __func__, cmd);
2293 return false;
2294 }
2295
2296 DPRINTF(ah->ah_sc, ATH_DBG_ANI, "%s: ANI parameters:\n", __func__);
2297 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
2298 "noiseImmunityLevel=%d, spurImmunityLevel=%d, "
2299 "ofdmWeakSigDetectOff=%d\n",
2300 aniState->noiseImmunityLevel, aniState->spurImmunityLevel,
2301 !aniState->ofdmWeakSigDetectOff);
2302 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
2303 "cckWeakSigThreshold=%d, "
2304 "firstepLevel=%d, listenTime=%d\n",
2305 aniState->cckWeakSigThreshold, aniState->firstepLevel,
2306 aniState->listenTime);
2307 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
2308 "cycleCount=%d, ofdmPhyErrCount=%d, cckPhyErrCount=%d\n\n",
2309 aniState->cycleCount, aniState->ofdmPhyErrCount,
2310 aniState->cckPhyErrCount);
2311 return true;
2312}
2313
2314static void ath9k_ani_restart(struct ath_hal *ah)
2315{
2316 struct ath_hal_5416 *ahp = AH5416(ah);
2317 struct ar5416AniState *aniState;
2318
2319 if (!DO_ANI(ah))
2320 return;
2321
2322 aniState = ahp->ah_curani;
2323
2324 aniState->listenTime = 0;
2325 if (ahp->ah_hasHwPhyCounters) {
2326 if (aniState->ofdmTrigHigh > AR_PHY_COUNTMAX) {
2327 aniState->ofdmPhyErrBase = 0;
2328 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
2329 "OFDM Trigger is too high for hw counters\n");
2330 } else {
2331 aniState->ofdmPhyErrBase =
2332 AR_PHY_COUNTMAX - aniState->ofdmTrigHigh;
2333 }
2334 if (aniState->cckTrigHigh > AR_PHY_COUNTMAX) {
2335 aniState->cckPhyErrBase = 0;
2336 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
2337 "CCK Trigger is too high for hw counters\n");
2338 } else {
2339 aniState->cckPhyErrBase =
2340 AR_PHY_COUNTMAX - aniState->cckTrigHigh;
2341 }
2342 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
2343 "%s: Writing ofdmbase=%u cckbase=%u\n",
2344 __func__, aniState->ofdmPhyErrBase,
2345 aniState->cckPhyErrBase);
2346 REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase);
2347 REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase);
2348 REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
2349 REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
2350
2351 ath9k_hw_update_mibstats(ah, &ahp->ah_mibStats);
2352 }
2353 aniState->ofdmPhyErrCount = 0;
2354 aniState->cckPhyErrCount = 0;
2355}
2356
2357static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hal *ah)
2358{
2359 struct ath_hal_5416 *ahp = AH5416(ah);
2360 struct ath9k_channel *chan = ah->ah_curchan;
2361 struct ar5416AniState *aniState;
2362 enum wireless_mode mode;
2363 int32_t rssi;
2364
2365 if (!DO_ANI(ah))
2366 return;
2367
2368 aniState = ahp->ah_curani;
2369
2370 if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) {
2371 if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
2372 aniState->noiseImmunityLevel + 1)) {
2373 return;
2374 }
2375 }
2376
2377 if (aniState->spurImmunityLevel < HAL_SPUR_IMMUNE_MAX) {
2378 if (ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
2379 aniState->spurImmunityLevel + 1)) {
2380 return;
2381 }
2382 }
2383
2384 if (ah->ah_opmode == ATH9K_M_HOSTAP) {
2385 if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
2386 ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
2387 aniState->firstepLevel + 1);
2388 }
2389 return;
2390 }
2391 rssi = BEACON_RSSI(ahp);
2392 if (rssi > aniState->rssiThrHigh) {
2393 if (!aniState->ofdmWeakSigDetectOff) {
2394 if (ath9k_hw_ani_control(ah,
2395 ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
2396 false)) {
2397 ath9k_hw_ani_control(ah,
2398 ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
2399 0);
2400 return;
2401 }
2402 }
2403 if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
2404 ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
2405 aniState->firstepLevel + 1);
2406 return;
2407 }
2408 } else if (rssi > aniState->rssiThrLow) {
2409 if (aniState->ofdmWeakSigDetectOff)
2410 ath9k_hw_ani_control(ah,
2411 ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
2412 true);
2413 if (aniState->firstepLevel < HAL_FIRST_STEP_MAX)
2414 ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
2415 aniState->firstepLevel + 1);
2416 return;
2417 } else {
2418 mode = ath9k_hw_chan2wmode(ah, chan);
Sujith86b89ee2008-08-07 10:54:57 +05302419 if (mode == ATH9K_MODE_11G || mode == ATH9K_MODE_11B) {
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002420 if (!aniState->ofdmWeakSigDetectOff)
2421 ath9k_hw_ani_control(ah,
2422 ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
2423 false);
2424 if (aniState->firstepLevel > 0)
2425 ath9k_hw_ani_control(ah,
2426 ATH9K_ANI_FIRSTEP_LEVEL,
2427 0);
2428 return;
2429 }
2430 }
2431}
2432
2433static void ath9k_hw_ani_cck_err_trigger(struct ath_hal *ah)
2434{
2435 struct ath_hal_5416 *ahp = AH5416(ah);
2436 struct ath9k_channel *chan = ah->ah_curchan;
2437 struct ar5416AniState *aniState;
2438 enum wireless_mode mode;
2439 int32_t rssi;
2440
2441 if (!DO_ANI(ah))
2442 return;
2443
2444 aniState = ahp->ah_curani;
2445 if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) {
2446 if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
2447 aniState->noiseImmunityLevel + 1)) {
2448 return;
2449 }
2450 }
2451 if (ah->ah_opmode == ATH9K_M_HOSTAP) {
2452 if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
2453 ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
2454 aniState->firstepLevel + 1);
2455 }
2456 return;
2457 }
2458 rssi = BEACON_RSSI(ahp);
2459 if (rssi > aniState->rssiThrLow) {
2460 if (aniState->firstepLevel < HAL_FIRST_STEP_MAX)
2461 ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
2462 aniState->firstepLevel + 1);
2463 } else {
2464 mode = ath9k_hw_chan2wmode(ah, chan);
Sujith86b89ee2008-08-07 10:54:57 +05302465 if (mode == ATH9K_MODE_11G || mode == ATH9K_MODE_11B) {
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002466 if (aniState->firstepLevel > 0)
2467 ath9k_hw_ani_control(ah,
2468 ATH9K_ANI_FIRSTEP_LEVEL,
2469 0);
2470 }
2471 }
2472}
2473
2474static void ath9k_ani_reset(struct ath_hal *ah)
2475{
2476 struct ath_hal_5416 *ahp = AH5416(ah);
2477 struct ar5416AniState *aniState;
2478 struct ath9k_channel *chan = ah->ah_curchan;
2479 int index;
2480
2481 if (!DO_ANI(ah))
2482 return;
2483
2484 index = ath9k_hw_get_ani_channel_idx(ah, chan);
2485 aniState = &ahp->ah_ani[index];
2486 ahp->ah_curani = aniState;
2487
2488 if (DO_ANI(ah) && ah->ah_opmode != ATH9K_M_STA
2489 && ah->ah_opmode != ATH9K_M_IBSS) {
2490 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
2491 "%s: Reset ANI state opmode %u\n", __func__,
2492 ah->ah_opmode);
2493 ahp->ah_stats.ast_ani_reset++;
2494 ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, 0);
2495 ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL, 0);
2496 ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, 0);
2497 ath9k_hw_ani_control(ah,
2498 ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
2499 !ATH9K_ANI_USE_OFDM_WEAK_SIG);
2500 ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR,
2501 ATH9K_ANI_CCK_WEAK_SIG_THR);
2502 ath9k_hw_setrxfilter(ah,
2503 ath9k_hw_getrxfilter(ah) |
2504 ATH9K_RX_FILTER_PHYERR);
2505 if (ah->ah_opmode == ATH9K_M_HOSTAP) {
2506 ahp->ah_curani->ofdmTrigHigh =
Sujith60b67f52008-08-07 10:52:38 +05302507 ah->ah_config.ofdm_trig_high;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002508 ahp->ah_curani->ofdmTrigLow =
Sujith60b67f52008-08-07 10:52:38 +05302509 ah->ah_config.ofdm_trig_low;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002510 ahp->ah_curani->cckTrigHigh =
Sujith60b67f52008-08-07 10:52:38 +05302511 ah->ah_config.cck_trig_high;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002512 ahp->ah_curani->cckTrigLow =
Sujith60b67f52008-08-07 10:52:38 +05302513 ah->ah_config.cck_trig_low;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002514 }
2515 ath9k_ani_restart(ah);
2516 return;
2517 }
2518
2519 if (aniState->noiseImmunityLevel != 0)
2520 ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
2521 aniState->noiseImmunityLevel);
2522 if (aniState->spurImmunityLevel != 0)
2523 ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
2524 aniState->spurImmunityLevel);
2525 if (aniState->ofdmWeakSigDetectOff)
2526 ath9k_hw_ani_control(ah,
2527 ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
2528 !aniState->ofdmWeakSigDetectOff);
2529 if (aniState->cckWeakSigThreshold)
2530 ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR,
2531 aniState->cckWeakSigThreshold);
2532 if (aniState->firstepLevel != 0)
2533 ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
2534 aniState->firstepLevel);
2535 if (ahp->ah_hasHwPhyCounters) {
2536 ath9k_hw_setrxfilter(ah,
2537 ath9k_hw_getrxfilter(ah) &
2538 ~ATH9K_RX_FILTER_PHYERR);
2539 ath9k_ani_restart(ah);
2540 REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
2541 REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
2542
2543 } else {
2544 ath9k_ani_restart(ah);
2545 ath9k_hw_setrxfilter(ah,
2546 ath9k_hw_getrxfilter(ah) |
2547 ATH9K_RX_FILTER_PHYERR);
2548 }
2549}
2550
2551void ath9k_hw_procmibevent(struct ath_hal *ah,
2552 const struct ath9k_node_stats *stats)
2553{
2554 struct ath_hal_5416 *ahp = AH5416(ah);
2555 u32 phyCnt1, phyCnt2;
2556
2557 DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Processing Mib Intr\n");
2558
2559 REG_WRITE(ah, AR_FILT_OFDM, 0);
2560 REG_WRITE(ah, AR_FILT_CCK, 0);
2561 if (!(REG_READ(ah, AR_SLP_MIB_CTRL) & AR_SLP_MIB_PENDING))
2562 REG_WRITE(ah, AR_SLP_MIB_CTRL, AR_SLP_MIB_CLEAR);
2563
2564 ath9k_hw_update_mibstats(ah, &ahp->ah_mibStats);
2565 ahp->ah_stats.ast_nodestats = *stats;
2566
2567 if (!DO_ANI(ah))
2568 return;
2569
2570 phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
2571 phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
2572 if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) ||
2573 ((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK)) {
2574 struct ar5416AniState *aniState = ahp->ah_curani;
2575 u32 ofdmPhyErrCnt, cckPhyErrCnt;
2576
2577 ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase;
2578 ahp->ah_stats.ast_ani_ofdmerrs +=
2579 ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
2580 aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
2581
2582 cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase;
2583 ahp->ah_stats.ast_ani_cckerrs +=
2584 cckPhyErrCnt - aniState->cckPhyErrCount;
2585 aniState->cckPhyErrCount = cckPhyErrCnt;
2586
2587 if (aniState->ofdmPhyErrCount > aniState->ofdmTrigHigh)
2588 ath9k_hw_ani_ofdm_err_trigger(ah);
2589 if (aniState->cckPhyErrCount > aniState->cckTrigHigh)
2590 ath9k_hw_ani_cck_err_trigger(ah);
2591
2592 ath9k_ani_restart(ah);
2593 }
2594}
2595
2596static void ath9k_hw_ani_lower_immunity(struct ath_hal *ah)
2597{
2598 struct ath_hal_5416 *ahp = AH5416(ah);
2599 struct ar5416AniState *aniState;
2600 int32_t rssi;
2601
2602 aniState = ahp->ah_curani;
2603
2604 if (ah->ah_opmode == ATH9K_M_HOSTAP) {
2605 if (aniState->firstepLevel > 0) {
2606 if (ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
2607 aniState->firstepLevel - 1)) {
2608 return;
2609 }
2610 }
2611 } else {
2612 rssi = BEACON_RSSI(ahp);
2613 if (rssi > aniState->rssiThrHigh) {
2614 /* XXX: Handle me */
2615 } else if (rssi > aniState->rssiThrLow) {
2616 if (aniState->ofdmWeakSigDetectOff) {
2617 if (ath9k_hw_ani_control(ah,
2618 ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
2619 true) ==
2620 true) {
2621 return;
2622 }
2623 }
2624 if (aniState->firstepLevel > 0) {
2625 if (ath9k_hw_ani_control
2626 (ah, ATH9K_ANI_FIRSTEP_LEVEL,
2627 aniState->firstepLevel - 1) ==
2628 true) {
2629 return;
2630 }
2631 }
2632 } else {
2633 if (aniState->firstepLevel > 0) {
2634 if (ath9k_hw_ani_control
2635 (ah, ATH9K_ANI_FIRSTEP_LEVEL,
2636 aniState->firstepLevel - 1) ==
2637 true) {
2638 return;
2639 }
2640 }
2641 }
2642 }
2643
2644 if (aniState->spurImmunityLevel > 0) {
2645 if (ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
2646 aniState->spurImmunityLevel - 1)) {
2647 return;
2648 }
2649 }
2650
2651 if (aniState->noiseImmunityLevel > 0) {
2652 ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
2653 aniState->noiseImmunityLevel - 1);
2654 return;
2655 }
2656}
2657
2658static int32_t ath9k_hw_ani_get_listen_time(struct ath_hal *ah)
2659{
2660 struct ath_hal_5416 *ahp = AH5416(ah);
2661 struct ar5416AniState *aniState;
2662 u32 txFrameCount, rxFrameCount, cycleCount;
2663 int32_t listenTime;
2664
2665 txFrameCount = REG_READ(ah, AR_TFCNT);
2666 rxFrameCount = REG_READ(ah, AR_RFCNT);
2667 cycleCount = REG_READ(ah, AR_CCCNT);
2668
2669 aniState = ahp->ah_curani;
2670 if (aniState->cycleCount == 0 || aniState->cycleCount > cycleCount) {
2671
2672 listenTime = 0;
2673 ahp->ah_stats.ast_ani_lzero++;
2674 } else {
2675 int32_t ccdelta = cycleCount - aniState->cycleCount;
2676 int32_t rfdelta = rxFrameCount - aniState->rxFrameCount;
2677 int32_t tfdelta = txFrameCount - aniState->txFrameCount;
2678 listenTime = (ccdelta - rfdelta - tfdelta) / 44000;
2679 }
2680 aniState->cycleCount = cycleCount;
2681 aniState->txFrameCount = txFrameCount;
2682 aniState->rxFrameCount = rxFrameCount;
2683
2684 return listenTime;
2685}
2686
2687void ath9k_hw_ani_monitor(struct ath_hal *ah,
2688 const struct ath9k_node_stats *stats,
2689 struct ath9k_channel *chan)
2690{
2691 struct ath_hal_5416 *ahp = AH5416(ah);
2692 struct ar5416AniState *aniState;
2693 int32_t listenTime;
2694
2695 aniState = ahp->ah_curani;
2696 ahp->ah_stats.ast_nodestats = *stats;
2697
2698 listenTime = ath9k_hw_ani_get_listen_time(ah);
2699 if (listenTime < 0) {
2700 ahp->ah_stats.ast_ani_lneg++;
2701 ath9k_ani_restart(ah);
2702 return;
2703 }
2704
2705 aniState->listenTime += listenTime;
2706
2707 if (ahp->ah_hasHwPhyCounters) {
2708 u32 phyCnt1, phyCnt2;
2709 u32 ofdmPhyErrCnt, cckPhyErrCnt;
2710
2711 ath9k_hw_update_mibstats(ah, &ahp->ah_mibStats);
2712
2713 phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
2714 phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
2715
2716 if (phyCnt1 < aniState->ofdmPhyErrBase ||
2717 phyCnt2 < aniState->cckPhyErrBase) {
2718 if (phyCnt1 < aniState->ofdmPhyErrBase) {
2719 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
2720 "%s: phyCnt1 0x%x, resetting "
2721 "counter value to 0x%x\n",
2722 __func__, phyCnt1,
2723 aniState->ofdmPhyErrBase);
2724 REG_WRITE(ah, AR_PHY_ERR_1,
2725 aniState->ofdmPhyErrBase);
2726 REG_WRITE(ah, AR_PHY_ERR_MASK_1,
2727 AR_PHY_ERR_OFDM_TIMING);
2728 }
2729 if (phyCnt2 < aniState->cckPhyErrBase) {
2730 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
2731 "%s: phyCnt2 0x%x, resetting "
2732 "counter value to 0x%x\n",
2733 __func__, phyCnt2,
2734 aniState->cckPhyErrBase);
2735 REG_WRITE(ah, AR_PHY_ERR_2,
2736 aniState->cckPhyErrBase);
2737 REG_WRITE(ah, AR_PHY_ERR_MASK_2,
2738 AR_PHY_ERR_CCK_TIMING);
2739 }
2740 return;
2741 }
2742
2743 ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase;
2744 ahp->ah_stats.ast_ani_ofdmerrs +=
2745 ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
2746 aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
2747
2748 cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase;
2749 ahp->ah_stats.ast_ani_cckerrs +=
2750 cckPhyErrCnt - aniState->cckPhyErrCount;
2751 aniState->cckPhyErrCount = cckPhyErrCnt;
2752 }
2753
2754 if (!DO_ANI(ah))
2755 return;
2756
2757 if (aniState->listenTime > 5 * ahp->ah_aniPeriod) {
2758 if (aniState->ofdmPhyErrCount <= aniState->listenTime *
2759 aniState->ofdmTrigLow / 1000 &&
2760 aniState->cckPhyErrCount <= aniState->listenTime *
2761 aniState->cckTrigLow / 1000)
2762 ath9k_hw_ani_lower_immunity(ah);
2763 ath9k_ani_restart(ah);
2764 } else if (aniState->listenTime > ahp->ah_aniPeriod) {
2765 if (aniState->ofdmPhyErrCount > aniState->listenTime *
2766 aniState->ofdmTrigHigh / 1000) {
2767 ath9k_hw_ani_ofdm_err_trigger(ah);
2768 ath9k_ani_restart(ah);
2769 } else if (aniState->cckPhyErrCount >
2770 aniState->listenTime * aniState->cckTrigHigh /
2771 1000) {
2772 ath9k_hw_ani_cck_err_trigger(ah);
2773 ath9k_ani_restart(ah);
2774 }
2775 }
2776}
2777
2778#ifndef ATH_NF_PER_CHAN
2779static void ath9k_init_nfcal_hist_buffer(struct ath_hal *ah)
2780{
2781 int i, j;
2782
2783 for (i = 0; i < NUM_NF_READINGS; i++) {
2784 ah->nfCalHist[i].currIndex = 0;
2785 ah->nfCalHist[i].privNF = AR_PHY_CCA_MAX_GOOD_VALUE;
2786 ah->nfCalHist[i].invalidNFcount =
2787 AR_PHY_CCA_FILTERWINDOW_LENGTH;
2788 for (j = 0; j < ATH9K_NF_CAL_HIST_MAX; j++) {
2789 ah->nfCalHist[i].nfCalBuffer[j] =
2790 AR_PHY_CCA_MAX_GOOD_VALUE;
2791 }
2792 }
2793 return;
2794}
2795#endif
2796
2797static void ath9k_hw_gpio_cfg_output_mux(struct ath_hal *ah,
2798 u32 gpio, u32 type)
2799{
2800 int addr;
2801 u32 gpio_shift, tmp;
2802
2803 if (gpio > 11)
2804 addr = AR_GPIO_OUTPUT_MUX3;
2805 else if (gpio > 5)
2806 addr = AR_GPIO_OUTPUT_MUX2;
2807 else
2808 addr = AR_GPIO_OUTPUT_MUX1;
2809
2810 gpio_shift = (gpio % 6) * 5;
2811
2812 if (AR_SREV_9280_20_OR_LATER(ah)
2813 || (addr != AR_GPIO_OUTPUT_MUX1)) {
2814 REG_RMW(ah, addr, (type << gpio_shift),
2815 (0x1f << gpio_shift));
2816 } else {
2817 tmp = REG_READ(ah, addr);
2818 tmp = ((tmp & 0x1F0) << 1) | (tmp & ~0x1F0);
2819 tmp &= ~(0x1f << gpio_shift);
2820 tmp |= (type << gpio_shift);
2821 REG_WRITE(ah, addr, tmp);
2822 }
2823}
2824
2825static bool ath9k_hw_cfg_output(struct ath_hal *ah, u32 gpio,
2826 enum ath9k_gpio_output_mux_type
2827 halSignalType)
2828{
2829 u32 ah_signal_type;
2830 u32 gpio_shift;
2831
2832 static u32 MuxSignalConversionTable[] = {
2833
2834 AR_GPIO_OUTPUT_MUX_AS_OUTPUT,
2835
2836 AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED,
2837
2838 AR_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED,
2839
2840 AR_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED,
2841
2842 AR_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED,
2843 };
2844
2845 if ((halSignalType >= 0)
2846 && (halSignalType < ARRAY_SIZE(MuxSignalConversionTable)))
2847 ah_signal_type = MuxSignalConversionTable[halSignalType];
2848 else
2849 return false;
2850
2851 ath9k_hw_gpio_cfg_output_mux(ah, gpio, ah_signal_type);
2852
2853 gpio_shift = 2 * gpio;
2854
2855 REG_RMW(ah,
2856 AR_GPIO_OE_OUT,
2857 (AR_GPIO_OE_OUT_DRV_ALL << gpio_shift),
2858 (AR_GPIO_OE_OUT_DRV << gpio_shift));
2859
2860 return true;
2861}
2862
2863static bool ath9k_hw_set_gpio(struct ath_hal *ah, u32 gpio,
2864 u32 val)
2865{
2866 REG_RMW(ah, AR_GPIO_IN_OUT, ((val & 1) << gpio),
2867 AR_GPIO_BIT(gpio));
2868 return true;
2869}
2870
2871static u32 ath9k_hw_gpio_get(struct ath_hal *ah, u32 gpio)
2872{
Sujith60b67f52008-08-07 10:52:38 +05302873 if (gpio >= ah->ah_caps.num_gpio_pins)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002874 return 0xffffffff;
2875
2876 if (AR_SREV_9280_10_OR_LATER(ah)) {
2877 return (MS
2878 (REG_READ(ah, AR_GPIO_IN_OUT),
2879 AR928X_GPIO_IN_VAL) & AR_GPIO_BIT(gpio)) != 0;
2880 } else {
2881 return (MS(REG_READ(ah, AR_GPIO_IN_OUT), AR_GPIO_IN_VAL) &
2882 AR_GPIO_BIT(gpio)) != 0;
2883 }
2884}
2885
2886static inline int ath9k_hw_post_attach(struct ath_hal *ah)
2887{
2888 int ecode;
2889
2890 if (!ath9k_hw_chip_test(ah)) {
2891 DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
2892 "%s: hardware self-test failed\n", __func__);
2893 return -ENODEV;
2894 }
2895
2896 ecode = ath9k_hw_rf_claim(ah);
2897 if (ecode != 0)
2898 return ecode;
2899
2900 ecode = ath9k_hw_eeprom_attach(ah);
2901 if (ecode != 0)
2902 return ecode;
2903 ecode = ath9k_hw_rfattach(ah);
2904 if (ecode != 0)
2905 return ecode;
2906
2907 if (!AR_SREV_9100(ah)) {
2908 ath9k_hw_ani_setup(ah);
2909 ath9k_hw_ani_attach(ah);
2910 }
2911 return 0;
2912}
2913
2914static u32 ath9k_hw_ini_fixup(struct ath_hal *ah,
2915 struct ar5416_eeprom *pEepData,
2916 u32 reg, u32 value)
2917{
2918 struct base_eep_header *pBase = &(pEepData->baseEepHeader);
2919
2920 switch (ah->ah_devid) {
2921 case AR9280_DEVID_PCI:
2922 if (reg == 0x7894) {
2923 DPRINTF(ah->ah_sc, ATH_DBG_ANY,
2924 "ini VAL: %x EEPROM: %x\n", value,
2925 (pBase->version & 0xff));
2926
2927 if ((pBase->version & 0xff) > 0x0a) {
2928 DPRINTF(ah->ah_sc, ATH_DBG_ANY,
2929 "PWDCLKIND: %d\n",
2930 pBase->pwdclkind);
2931 value &= ~AR_AN_TOP2_PWDCLKIND;
2932 value |= AR_AN_TOP2_PWDCLKIND & (pBase->
2933 pwdclkind << AR_AN_TOP2_PWDCLKIND_S);
2934 } else {
2935 DPRINTF(ah->ah_sc, ATH_DBG_ANY,
2936 "PWDCLKIND Earlier Rev\n");
2937 }
2938
2939 DPRINTF(ah->ah_sc, ATH_DBG_ANY,
2940 "final ini VAL: %x\n", value);
2941 }
2942 break;
2943 }
2944 return value;
2945}
2946
2947static bool ath9k_hw_fill_cap_info(struct ath_hal *ah)
2948{
2949 struct ath_hal_5416 *ahp = AH5416(ah);
Sujith60b67f52008-08-07 10:52:38 +05302950 struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002951 u16 capField = 0, eeval;
2952
2953 eeval = ath9k_hw_get_eeprom(ahp, EEP_REG_0);
2954
2955 ah->ah_currentRD = eeval;
2956
2957 eeval = ath9k_hw_get_eeprom(ahp, EEP_REG_1);
2958 ah->ah_currentRDExt = eeval;
2959
2960 capField = ath9k_hw_get_eeprom(ahp, EEP_OP_CAP);
2961
2962 if (ah->ah_opmode != ATH9K_M_HOSTAP &&
2963 ah->ah_subvendorid == AR_SUBVENDOR_ID_NEW_A) {
2964 if (ah->ah_currentRD == 0x64 || ah->ah_currentRD == 0x65)
2965 ah->ah_currentRD += 5;
2966 else if (ah->ah_currentRD == 0x41)
2967 ah->ah_currentRD = 0x43;
2968 DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
2969 "%s: regdomain mapped to 0x%x\n", __func__,
2970 ah->ah_currentRD);
2971 }
2972
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002973 eeval = ath9k_hw_get_eeprom(ahp, EEP_OP_MODE);
Sujith86b89ee2008-08-07 10:54:57 +05302974 bitmap_zero(pCap->wireless_modes, ATH9K_MODE_MAX);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002975
2976 if (eeval & AR5416_OPFLAGS_11A) {
Sujith86b89ee2008-08-07 10:54:57 +05302977 set_bit(ATH9K_MODE_11A, pCap->wireless_modes);
2978 if (ah->ah_config.ht_enable) {
2979 if (!(eeval & AR5416_OPFLAGS_N_5G_HT20))
2980 set_bit(ATH9K_MODE_11NA_HT20,
2981 pCap->wireless_modes);
2982 if (!(eeval & AR5416_OPFLAGS_N_5G_HT40)) {
2983 set_bit(ATH9K_MODE_11NA_HT40PLUS,
2984 pCap->wireless_modes);
2985 set_bit(ATH9K_MODE_11NA_HT40MINUS,
2986 pCap->wireless_modes);
2987 }
2988 }
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002989 }
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07002990
Sujith86b89ee2008-08-07 10:54:57 +05302991 if (eeval & AR5416_OPFLAGS_11G) {
2992 set_bit(ATH9K_MODE_11B, pCap->wireless_modes);
2993 set_bit(ATH9K_MODE_11G, pCap->wireless_modes);
2994 if (ah->ah_config.ht_enable) {
2995 if (!(eeval & AR5416_OPFLAGS_N_2G_HT20))
2996 set_bit(ATH9K_MODE_11NG_HT20,
2997 pCap->wireless_modes);
2998 if (!(eeval & AR5416_OPFLAGS_N_2G_HT40)) {
2999 set_bit(ATH9K_MODE_11NG_HT40PLUS,
3000 pCap->wireless_modes);
3001 set_bit(ATH9K_MODE_11NG_HT40MINUS,
3002 pCap->wireless_modes);
3003 }
3004 }
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07003005 }
Sujith86b89ee2008-08-07 10:54:57 +05303006
Sujith60b67f52008-08-07 10:52:38 +05303007 pCap->tx_chainmask = ath9k_hw_get_eeprom(ahp, EEP_TX_MASK);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07003008 if ((ah->ah_isPciExpress)
3009 || (eeval & AR5416_OPFLAGS_11A)) {
Sujith60b67f52008-08-07 10:52:38 +05303010 pCap->rx_chainmask =
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07003011 ath9k_hw_get_eeprom(ahp, EEP_RX_MASK);
3012 } else {
Sujith60b67f52008-08-07 10:52:38 +05303013 pCap->rx_chainmask =
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07003014 (ath9k_hw_gpio_get(ah, 0)) ? 0x5 : 0x7;
3015 }
3016
3017 if (!(AR_SREV_9280(ah) && (ah->ah_macRev == 0)))
3018 ahp->ah_miscMode |= AR_PCU_MIC_NEW_LOC_ENA;
3019
Sujith60b67f52008-08-07 10:52:38 +05303020 pCap->low_2ghz_chan = 2312;
3021 pCap->high_2ghz_chan = 2732;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07003022
Sujith60b67f52008-08-07 10:52:38 +05303023 pCap->low_5ghz_chan = 4920;
3024 pCap->high_5ghz_chan = 6100;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07003025
Sujith60b67f52008-08-07 10:52:38 +05303026 pCap->hw_caps &= ~ATH9K_HW_CAP_CIPHER_CKIP;
3027 pCap->hw_caps |= ATH9K_HW_CAP_CIPHER_TKIP;
3028 pCap->hw_caps |= ATH9K_HW_CAP_CIPHER_AESCCM;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07003029
Sujith60b67f52008-08-07 10:52:38 +05303030 pCap->hw_caps &= ~ATH9K_HW_CAP_MIC_CKIP;
3031 pCap->hw_caps |= ATH9K_HW_CAP_MIC_TKIP;
3032 pCap->hw_caps |= ATH9K_HW_CAP_MIC_AESCCM;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07003033
Sujith60b67f52008-08-07 10:52:38 +05303034 pCap->hw_caps |= ATH9K_HW_CAP_CHAN_SPREAD;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07003035
Sujith60b67f52008-08-07 10:52:38 +05303036 if (ah->ah_config.ht_enable)
3037 pCap->hw_caps |= ATH9K_HW_CAP_HT;
3038 else
3039 pCap->hw_caps &= ~ATH9K_HW_CAP_HT;
3040
3041 pCap->hw_caps |= ATH9K_HW_CAP_GTT;
3042 pCap->hw_caps |= ATH9K_HW_CAP_VEOL;
3043 pCap->hw_caps |= ATH9K_HW_CAP_BSSIDMASK;
3044 pCap->hw_caps &= ~ATH9K_HW_CAP_MCAST_KEYSEARCH;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07003045
3046 if (capField & AR_EEPROM_EEPCAP_MAXQCU)
Sujith60b67f52008-08-07 10:52:38 +05303047 pCap->total_queues =
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07003048 MS(capField, AR_EEPROM_EEPCAP_MAXQCU);
3049 else
Sujith60b67f52008-08-07 10:52:38 +05303050 pCap->total_queues = ATH9K_NUM_TX_QUEUES;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07003051
3052 if (capField & AR_EEPROM_EEPCAP_KC_ENTRIES)
Sujith60b67f52008-08-07 10:52:38 +05303053 pCap->keycache_size =
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07003054 1 << MS(capField, AR_EEPROM_EEPCAP_KC_ENTRIES);
3055 else
Sujith60b67f52008-08-07 10:52:38 +05303056 pCap->keycache_size = AR_KEYTABLE_SIZE;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07003057
Sujith60b67f52008-08-07 10:52:38 +05303058 pCap->hw_caps |= ATH9K_HW_CAP_FASTCC;
3059 pCap->num_mr_retries = 4;
3060 pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07003061
3062 if (AR_SREV_9280_10_OR_LATER(ah))
Sujith60b67f52008-08-07 10:52:38 +05303063 pCap->num_gpio_pins = AR928X_NUM_GPIO;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07003064 else
Sujith60b67f52008-08-07 10:52:38 +05303065 pCap->num_gpio_pins = AR_NUM_GPIO;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07003066
3067 if (AR_SREV_9280_10_OR_LATER(ah)) {
Sujith60b67f52008-08-07 10:52:38 +05303068 pCap->hw_caps |= ATH9K_HW_CAP_WOW;
3069 pCap->hw_caps |= ATH9K_HW_CAP_WOW_MATCHPATTERN_EXACT;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07003070 } else {
Sujith60b67f52008-08-07 10:52:38 +05303071 pCap->hw_caps &= ~ATH9K_HW_CAP_WOW;
3072 pCap->hw_caps &= ~ATH9K_HW_CAP_WOW_MATCHPATTERN_EXACT;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07003073 }
3074
3075 if (AR_SREV_9160_10_OR_LATER(ah) || AR_SREV_9100(ah)) {
Sujith60b67f52008-08-07 10:52:38 +05303076 pCap->hw_caps |= ATH9K_HW_CAP_CST;
3077 pCap->rts_aggr_limit = ATH_AMPDU_LIMIT_MAX;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07003078 } else {
Sujith60b67f52008-08-07 10:52:38 +05303079 pCap->rts_aggr_limit = (8 * 1024);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07003080 }
3081
Sujith60b67f52008-08-07 10:52:38 +05303082 pCap->hw_caps |= ATH9K_HW_CAP_ENHANCEDPM;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07003083
3084 ah->ah_rfsilent = ath9k_hw_get_eeprom(ahp, EEP_RF_SILENT);
3085 if (ah->ah_rfsilent & EEP_RFSILENT_ENABLED) {
3086 ahp->ah_gpioSelect =
3087 MS(ah->ah_rfsilent, EEP_RFSILENT_GPIO_SEL);
3088 ahp->ah_polarity =
3089 MS(ah->ah_rfsilent, EEP_RFSILENT_POLARITY);
3090
Sujith60b67f52008-08-07 10:52:38 +05303091 ath9k_hw_setcapability(ah, ATH9K_CAP_RFSILENT, 1, true,
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07003092 NULL);
Sujith60b67f52008-08-07 10:52:38 +05303093 pCap->hw_caps |= ATH9K_HW_CAP_RFSILENT;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07003094 }
3095
3096 if ((ah->ah_macVersion == AR_SREV_VERSION_5416_PCI) ||
3097 (ah->ah_macVersion == AR_SREV_VERSION_5416_PCIE) ||
3098 (ah->ah_macVersion == AR_SREV_VERSION_9160) ||
3099 (ah->ah_macVersion == AR_SREV_VERSION_9100) ||
3100 (ah->ah_macVersion == AR_SREV_VERSION_9280))
Sujith60b67f52008-08-07 10:52:38 +05303101 pCap->hw_caps &= ~ATH9K_HW_CAP_AUTOSLEEP;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07003102 else
Sujith60b67f52008-08-07 10:52:38 +05303103 pCap->hw_caps |= ATH9K_HW_CAP_AUTOSLEEP;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07003104
3105 if (AR_SREV_9280(ah))
Sujith60b67f52008-08-07 10:52:38 +05303106 pCap->hw_caps &= ~ATH9K_HW_CAP_4KB_SPLITTRANS;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07003107 else
Sujith60b67f52008-08-07 10:52:38 +05303108 pCap->hw_caps |= ATH9K_HW_CAP_4KB_SPLITTRANS;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07003109
3110 if (ah->ah_currentRDExt & (1 << REG_EXT_JAPAN_MIDBAND)) {
Sujith60b67f52008-08-07 10:52:38 +05303111 pCap->reg_cap =
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07003112 AR_EEPROM_EEREGCAP_EN_KK_NEW_11A |
3113 AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN |
3114 AR_EEPROM_EEREGCAP_EN_KK_U2 |
3115 AR_EEPROM_EEREGCAP_EN_KK_MIDBAND;
3116 } else {
Sujith60b67f52008-08-07 10:52:38 +05303117 pCap->reg_cap =
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07003118 AR_EEPROM_EEREGCAP_EN_KK_NEW_11A |
3119 AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN;
3120 }
3121
Sujith60b67f52008-08-07 10:52:38 +05303122 pCap->reg_cap |= AR_EEPROM_EEREGCAP_EN_FCC_MIDBAND;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07003123
Sujith60b67f52008-08-07 10:52:38 +05303124 pCap->num_antcfg_5ghz =
Sujith06df8be2008-08-07 10:53:39 +05303125 ath9k_hw_get_num_ant_config(ahp, IEEE80211_BAND_5GHZ);
Sujith60b67f52008-08-07 10:52:38 +05303126 pCap->num_antcfg_2ghz =
Sujith06df8be2008-08-07 10:53:39 +05303127 ath9k_hw_get_num_ant_config(ahp, IEEE80211_BAND_2GHZ);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07003128
3129 return true;
3130}
3131
3132static void ar5416DisablePciePhy(struct ath_hal *ah)
3133{
3134 if (!AR_SREV_9100(ah))
3135 return;
3136
3137 REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00);
3138 REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
3139 REG_WRITE(ah, AR_PCIE_SERDES, 0x28000029);
3140 REG_WRITE(ah, AR_PCIE_SERDES, 0x57160824);
3141 REG_WRITE(ah, AR_PCIE_SERDES, 0x25980579);
3142 REG_WRITE(ah, AR_PCIE_SERDES, 0x00000000);
3143 REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);
3144 REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);
3145 REG_WRITE(ah, AR_PCIE_SERDES, 0x000e1007);
3146
3147 REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
3148}
3149
3150static void ath9k_set_power_sleep(struct ath_hal *ah, int setChip)
3151{
3152 REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
3153 if (setChip) {
3154 REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE,
3155 AR_RTC_FORCE_WAKE_EN);
3156 if (!AR_SREV_9100(ah))
3157 REG_WRITE(ah, AR_RC, AR_RC_AHB | AR_RC_HOSTIF);
3158
3159 REG_CLR_BIT(ah, (u16) (AR_RTC_RESET),
3160 AR_RTC_RESET_EN);
3161 }
3162}
3163
3164static void ath9k_set_power_network_sleep(struct ath_hal *ah, int setChip)
3165{
3166 REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
3167 if (setChip) {
Sujith60b67f52008-08-07 10:52:38 +05303168 struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07003169
Sujith60b67f52008-08-07 10:52:38 +05303170 if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07003171 REG_WRITE(ah, AR_RTC_FORCE_WAKE,
3172 AR_RTC_FORCE_WAKE_ON_INT);
3173 } else {
3174 REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE,
3175 AR_RTC_FORCE_WAKE_EN);
3176 }
3177 }
3178}
3179
3180static bool ath9k_hw_set_power_awake(struct ath_hal *ah,
3181 int setChip)
3182{
3183 u32 val;
3184 int i;
3185
3186 if (setChip) {
3187 if ((REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M) ==
3188 AR_RTC_STATUS_SHUTDOWN) {
3189 if (ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)
3190 != true) {
3191 return false;
3192 }
3193 }
3194 if (AR_SREV_9100(ah))
3195 REG_SET_BIT(ah, AR_RTC_RESET,
3196 AR_RTC_RESET_EN);
3197
3198 REG_SET_BIT(ah, AR_RTC_FORCE_WAKE,
3199 AR_RTC_FORCE_WAKE_EN);
3200 udelay(50);
3201
3202 for (i = POWER_UP_TIME / 50; i > 0; i--) {
3203 val = REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M;
3204 if (val == AR_RTC_STATUS_ON)
3205 break;
3206 udelay(50);
3207 REG_SET_BIT(ah, AR_RTC_FORCE_WAKE,
3208 AR_RTC_FORCE_WAKE_EN);
3209 }
3210 if (i == 0) {
3211 DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT,
3212 "%s: Failed to wakeup in %uus\n",
3213 __func__, POWER_UP_TIME / 20);
3214 return false;
3215 }
3216 }
3217
3218 REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
3219 return true;
3220}
3221
3222bool ath9k_hw_setpower(struct ath_hal *ah,
3223 enum ath9k_power_mode mode)
3224{
3225 struct ath_hal_5416 *ahp = AH5416(ah);
3226 static const char *modes[] = {
3227 "AWAKE",
3228 "FULL-SLEEP",
3229 "NETWORK SLEEP",
3230 "UNDEFINED"
3231 };
3232 int status = true, setChip = true;
3233
3234 DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT, "%s: %s -> %s (%s)\n", __func__,
3235 modes[ahp->ah_powerMode], modes[mode],
3236 setChip ? "set chip " : "");
3237
3238 switch (mode) {
3239 case ATH9K_PM_AWAKE:
3240 status = ath9k_hw_set_power_awake(ah, setChip);
3241 break;
3242 case ATH9K_PM_FULL_SLEEP:
3243 ath9k_set_power_sleep(ah, setChip);
3244 ahp->ah_chipFullSleep = true;
3245 break;
3246 case ATH9K_PM_NETWORK_SLEEP:
3247 ath9k_set_power_network_sleep(ah, setChip);
3248 break;
3249 default:
3250 DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT,
3251 "%s: unknown power mode %u\n", __func__, mode);
3252 return false;
3253 }
3254 ahp->ah_powerMode = mode;
3255 return status;
3256}
3257
3258static struct ath_hal *ath9k_hw_do_attach(u16 devid,
3259 struct ath_softc *sc,
3260 void __iomem *mem,
3261 int *status)
3262{
3263 struct ath_hal_5416 *ahp;
3264 struct ath_hal *ah;
3265 int ecode;
3266#ifndef CONFIG_SLOW_ANT_DIV
3267 u32 i;
3268 u32 j;
3269#endif
3270
3271 ahp = ath9k_hw_newstate(devid, sc, mem, status);
3272 if (ahp == NULL)
3273 return NULL;
3274
3275 ah = &ahp->ah;
3276
3277 ath9k_hw_set_defaults(ah);
3278
Sujith60b67f52008-08-07 10:52:38 +05303279 if (ah->ah_config.intr_mitigation != 0)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07003280 ahp->ah_intrMitigation = true;
3281
3282 if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) {
3283 DPRINTF(ah->ah_sc, ATH_DBG_RESET, "%s: couldn't reset chip\n",
3284 __func__);
3285 ecode = -EIO;
3286 goto bad;
3287 }
3288
3289 if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) {
3290 DPRINTF(ah->ah_sc, ATH_DBG_RESET, "%s: couldn't wakeup chip\n",
3291 __func__);
3292 ecode = -EIO;
3293 goto bad;
3294 }
3295
Sujith60b67f52008-08-07 10:52:38 +05303296 if (ah->ah_config.serialize_regmode == SER_REG_MODE_AUTO) {
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07003297 if (ah->ah_macVersion == AR_SREV_VERSION_5416_PCI) {
Sujith60b67f52008-08-07 10:52:38 +05303298 ah->ah_config.serialize_regmode =
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07003299 SER_REG_MODE_ON;
3300 } else {
Sujith60b67f52008-08-07 10:52:38 +05303301 ah->ah_config.serialize_regmode =
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07003302 SER_REG_MODE_OFF;
3303 }
3304 }
3305 DPRINTF(ah->ah_sc, ATH_DBG_RESET,
Sujith60b67f52008-08-07 10:52:38 +05303306 "%s: serialize_regmode is %d\n",
3307 __func__, ah->ah_config.serialize_regmode);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07003308
3309 if ((ah->ah_macVersion != AR_SREV_VERSION_5416_PCI) &&
3310 (ah->ah_macVersion != AR_SREV_VERSION_5416_PCIE) &&
3311 (ah->ah_macVersion != AR_SREV_VERSION_9160) &&
3312 (!AR_SREV_9100(ah)) && (!AR_SREV_9280(ah))) {
3313 DPRINTF(ah->ah_sc, ATH_DBG_RESET,
3314 "%s: Mac Chip Rev 0x%02x.%x is not supported by "
3315 "this driver\n", __func__,
3316 ah->ah_macVersion, ah->ah_macRev);
3317 ecode = -EOPNOTSUPP;
3318 goto bad;
3319 }
3320
3321 if (AR_SREV_9100(ah)) {
3322 ahp->ah_iqCalData.calData = &iq_cal_multi_sample;
3323 ahp->ah_suppCals = IQ_MISMATCH_CAL;
3324 ah->ah_isPciExpress = false;
3325 }
3326 ah->ah_phyRev = REG_READ(ah, AR_PHY_CHIP_ID);
3327
3328 if (AR_SREV_9160_10_OR_LATER(ah)) {
3329 if (AR_SREV_9280_10_OR_LATER(ah)) {
3330 ahp->ah_iqCalData.calData = &iq_cal_single_sample;
3331 ahp->ah_adcGainCalData.calData =
3332 &adc_gain_cal_single_sample;
3333 ahp->ah_adcDcCalData.calData =
3334 &adc_dc_cal_single_sample;
3335 ahp->ah_adcDcCalInitData.calData =
3336 &adc_init_dc_cal;
3337 } else {
3338 ahp->ah_iqCalData.calData = &iq_cal_multi_sample;
3339 ahp->ah_adcGainCalData.calData =
3340 &adc_gain_cal_multi_sample;
3341 ahp->ah_adcDcCalData.calData =
3342 &adc_dc_cal_multi_sample;
3343 ahp->ah_adcDcCalInitData.calData =
3344 &adc_init_dc_cal;
3345 }
3346 ahp->ah_suppCals =
3347 ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL;
3348 }
3349
3350 if (AR_SREV_9160(ah)) {
Sujith60b67f52008-08-07 10:52:38 +05303351 ah->ah_config.enable_ani = 1;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07003352 ahp->ah_ani_function = (ATH9K_ANI_SPUR_IMMUNITY_LEVEL |
3353 ATH9K_ANI_FIRSTEP_LEVEL);
3354 } else {
3355 ahp->ah_ani_function = ATH9K_ANI_ALL;
3356 if (AR_SREV_9280_10_OR_LATER(ah)) {
3357 ahp->ah_ani_function &=
3358 ~ATH9K_ANI_NOISE_IMMUNITY_LEVEL;
3359 }
3360 }
3361
3362 DPRINTF(ah->ah_sc, ATH_DBG_RESET,
3363 "%s: This Mac Chip Rev 0x%02x.%x is \n", __func__,
3364 ah->ah_macVersion, ah->ah_macRev);
3365
3366 if (AR_SREV_9280_20_OR_LATER(ah)) {
3367 INIT_INI_ARRAY(&ahp->ah_iniModes, ar9280Modes_9280_2,
3368 ARRAY_SIZE(ar9280Modes_9280_2), 6);
3369 INIT_INI_ARRAY(&ahp->ah_iniCommon, ar9280Common_9280_2,
3370 ARRAY_SIZE(ar9280Common_9280_2), 2);
3371
Sujith60b67f52008-08-07 10:52:38 +05303372 if (ah->ah_config.pcie_clock_req) {
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07003373 INIT_INI_ARRAY(&ahp->ah_iniPcieSerdes,
3374 ar9280PciePhy_clkreq_off_L1_9280,
3375 ARRAY_SIZE
3376 (ar9280PciePhy_clkreq_off_L1_9280),
3377 2);
3378 } else {
3379 INIT_INI_ARRAY(&ahp->ah_iniPcieSerdes,
3380 ar9280PciePhy_clkreq_always_on_L1_9280,
3381 ARRAY_SIZE
3382 (ar9280PciePhy_clkreq_always_on_L1_9280),
3383 2);
3384 }
3385 INIT_INI_ARRAY(&ahp->ah_iniModesAdditional,
3386 ar9280Modes_fast_clock_9280_2,
3387 ARRAY_SIZE(ar9280Modes_fast_clock_9280_2),
3388 3);
3389 } else if (AR_SREV_9280_10_OR_LATER(ah)) {
3390 INIT_INI_ARRAY(&ahp->ah_iniModes, ar9280Modes_9280,
3391 ARRAY_SIZE(ar9280Modes_9280), 6);
3392 INIT_INI_ARRAY(&ahp->ah_iniCommon, ar9280Common_9280,
3393 ARRAY_SIZE(ar9280Common_9280), 2);
3394 } else if (AR_SREV_9160_10_OR_LATER(ah)) {
3395 INIT_INI_ARRAY(&ahp->ah_iniModes, ar5416Modes_9160,
3396 ARRAY_SIZE(ar5416Modes_9160), 6);
3397 INIT_INI_ARRAY(&ahp->ah_iniCommon, ar5416Common_9160,
3398 ARRAY_SIZE(ar5416Common_9160), 2);
3399 INIT_INI_ARRAY(&ahp->ah_iniBank0, ar5416Bank0_9160,
3400 ARRAY_SIZE(ar5416Bank0_9160), 2);
3401 INIT_INI_ARRAY(&ahp->ah_iniBB_RfGain, ar5416BB_RfGain_9160,
3402 ARRAY_SIZE(ar5416BB_RfGain_9160), 3);
3403 INIT_INI_ARRAY(&ahp->ah_iniBank1, ar5416Bank1_9160,
3404 ARRAY_SIZE(ar5416Bank1_9160), 2);
3405 INIT_INI_ARRAY(&ahp->ah_iniBank2, ar5416Bank2_9160,
3406 ARRAY_SIZE(ar5416Bank2_9160), 2);
3407 INIT_INI_ARRAY(&ahp->ah_iniBank3, ar5416Bank3_9160,
3408 ARRAY_SIZE(ar5416Bank3_9160), 3);
3409 INIT_INI_ARRAY(&ahp->ah_iniBank6, ar5416Bank6_9160,
3410 ARRAY_SIZE(ar5416Bank6_9160), 3);
3411 INIT_INI_ARRAY(&ahp->ah_iniBank6TPC, ar5416Bank6TPC_9160,
3412 ARRAY_SIZE(ar5416Bank6TPC_9160), 3);
3413 INIT_INI_ARRAY(&ahp->ah_iniBank7, ar5416Bank7_9160,
3414 ARRAY_SIZE(ar5416Bank7_9160), 2);
3415 if (AR_SREV_9160_11(ah)) {
3416 INIT_INI_ARRAY(&ahp->ah_iniAddac,
3417 ar5416Addac_91601_1,
3418 ARRAY_SIZE(ar5416Addac_91601_1), 2);
3419 } else {
3420 INIT_INI_ARRAY(&ahp->ah_iniAddac, ar5416Addac_9160,
3421 ARRAY_SIZE(ar5416Addac_9160), 2);
3422 }
3423 } else if (AR_SREV_9100_OR_LATER(ah)) {
3424 INIT_INI_ARRAY(&ahp->ah_iniModes, ar5416Modes_9100,
3425 ARRAY_SIZE(ar5416Modes_9100), 6);
3426 INIT_INI_ARRAY(&ahp->ah_iniCommon, ar5416Common_9100,
3427 ARRAY_SIZE(ar5416Common_9100), 2);
3428 INIT_INI_ARRAY(&ahp->ah_iniBank0, ar5416Bank0_9100,
3429 ARRAY_SIZE(ar5416Bank0_9100), 2);
3430 INIT_INI_ARRAY(&ahp->ah_iniBB_RfGain, ar5416BB_RfGain_9100,
3431 ARRAY_SIZE(ar5416BB_RfGain_9100), 3);
3432 INIT_INI_ARRAY(&ahp->ah_iniBank1, ar5416Bank1_9100,
3433 ARRAY_SIZE(ar5416Bank1_9100), 2);
3434 INIT_INI_ARRAY(&ahp->ah_iniBank2, ar5416Bank2_9100,
3435 ARRAY_SIZE(ar5416Bank2_9100), 2);
3436 INIT_INI_ARRAY(&ahp->ah_iniBank3, ar5416Bank3_9100,
3437 ARRAY_SIZE(ar5416Bank3_9100), 3);
3438 INIT_INI_ARRAY(&ahp->ah_iniBank6, ar5416Bank6_9100,
3439 ARRAY_SIZE(ar5416Bank6_9100), 3);
3440 INIT_INI_ARRAY(&ahp->ah_iniBank6TPC, ar5416Bank6TPC_9100,
3441 ARRAY_SIZE(ar5416Bank6TPC_9100), 3);
3442 INIT_INI_ARRAY(&ahp->ah_iniBank7, ar5416Bank7_9100,
3443 ARRAY_SIZE(ar5416Bank7_9100), 2);
3444 INIT_INI_ARRAY(&ahp->ah_iniAddac, ar5416Addac_9100,
3445 ARRAY_SIZE(ar5416Addac_9100), 2);
3446 } else {
3447 INIT_INI_ARRAY(&ahp->ah_iniModes, ar5416Modes,
3448 ARRAY_SIZE(ar5416Modes), 6);
3449 INIT_INI_ARRAY(&ahp->ah_iniCommon, ar5416Common,
3450 ARRAY_SIZE(ar5416Common), 2);
3451 INIT_INI_ARRAY(&ahp->ah_iniBank0, ar5416Bank0,
3452 ARRAY_SIZE(ar5416Bank0), 2);
3453 INIT_INI_ARRAY(&ahp->ah_iniBB_RfGain, ar5416BB_RfGain,
3454 ARRAY_SIZE(ar5416BB_RfGain), 3);
3455 INIT_INI_ARRAY(&ahp->ah_iniBank1, ar5416Bank1,
3456 ARRAY_SIZE(ar5416Bank1), 2);
3457 INIT_INI_ARRAY(&ahp->ah_iniBank2, ar5416Bank2,
3458 ARRAY_SIZE(ar5416Bank2), 2);
3459 INIT_INI_ARRAY(&ahp->ah_iniBank3, ar5416Bank3,
3460 ARRAY_SIZE(ar5416Bank3), 3);
3461 INIT_INI_ARRAY(&ahp->ah_iniBank6, ar5416Bank6,
3462 ARRAY_SIZE(ar5416Bank6), 3);
3463 INIT_INI_ARRAY(&ahp->ah_iniBank6TPC, ar5416Bank6TPC,
3464 ARRAY_SIZE(ar5416Bank6TPC), 3);
3465 INIT_INI_ARRAY(&ahp->ah_iniBank7, ar5416Bank7,
3466 ARRAY_SIZE(ar5416Bank7), 2);
3467 INIT_INI_ARRAY(&ahp->ah_iniAddac, ar5416Addac,
3468 ARRAY_SIZE(ar5416Addac), 2);
3469 }
3470
3471 if (ah->ah_isPciExpress)
3472 ath9k_hw_configpcipowersave(ah, 0);
3473 else
3474 ar5416DisablePciePhy(ah);
3475
3476 ecode = ath9k_hw_post_attach(ah);
3477 if (ecode != 0)
3478 goto bad;
3479
3480#ifndef CONFIG_SLOW_ANT_DIV
3481 if (ah->ah_devid == AR9280_DEVID_PCI) {
3482 for (i = 0; i < ahp->ah_iniModes.ia_rows; i++) {
3483 u32 reg = INI_RA(&ahp->ah_iniModes, i, 0);
3484
3485 for (j = 1; j < ahp->ah_iniModes.ia_columns; j++) {
3486 u32 val = INI_RA(&ahp->ah_iniModes, i, j);
3487
3488 INI_RA(&ahp->ah_iniModes, i, j) =
3489 ath9k_hw_ini_fixup(ah, &ahp->ah_eeprom,
3490 reg, val);
3491 }
3492 }
3493 }
3494#endif
3495
3496 if (!ath9k_hw_fill_cap_info(ah)) {
3497 DPRINTF(ah->ah_sc, ATH_DBG_RESET,
3498 "%s:failed ath9k_hw_fill_cap_info\n", __func__);
3499 ecode = -EINVAL;
3500 goto bad;
3501 }
3502
3503 ecode = ath9k_hw_init_macaddr(ah);
3504 if (ecode != 0) {
3505 DPRINTF(ah->ah_sc, ATH_DBG_RESET,
3506 "%s: failed initializing mac address\n",
3507 __func__);
3508 goto bad;
3509 }
3510
3511 if (AR_SREV_9285(ah))
3512 ah->ah_txTrigLevel = (AR_FTRIG_256B >> AR_FTRIG_S);
3513 else
3514 ah->ah_txTrigLevel = (AR_FTRIG_512B >> AR_FTRIG_S);
3515
3516#ifndef ATH_NF_PER_CHAN
3517
3518 ath9k_init_nfcal_hist_buffer(ah);
3519#endif
3520
3521 return ah;
3522
3523bad:
3524 if (ahp)
3525 ath9k_hw_detach((struct ath_hal *) ahp);
3526 if (status)
3527 *status = ecode;
3528 return NULL;
3529}
3530
3531void ath9k_hw_detach(struct ath_hal *ah)
3532{
3533 if (!AR_SREV_9100(ah))
3534 ath9k_hw_ani_detach(ah);
3535 ath9k_hw_rfdetach(ah);
3536
3537 ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP);
3538 kfree(ah);
3539}
3540
3541bool ath9k_get_channel_edges(struct ath_hal *ah,
3542 u16 flags, u16 *low,
3543 u16 *high)
3544{
Sujith60b67f52008-08-07 10:52:38 +05303545 struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07003546
3547 if (flags & CHANNEL_5GHZ) {
Sujith60b67f52008-08-07 10:52:38 +05303548 *low = pCap->low_5ghz_chan;
3549 *high = pCap->high_5ghz_chan;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07003550 return true;
3551 }
3552 if ((flags & CHANNEL_2GHZ)) {
Sujith60b67f52008-08-07 10:52:38 +05303553 *low = pCap->low_2ghz_chan;
3554 *high = pCap->high_2ghz_chan;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07003555
3556 return true;
3557 }
3558 return false;
3559}
3560
3561static inline bool ath9k_hw_fill_vpd_table(u8 pwrMin,
3562 u8 pwrMax,
3563 u8 *pPwrList,
3564 u8 *pVpdList,
3565 u16
3566 numIntercepts,
3567 u8 *pRetVpdList)
3568{
3569 u16 i, k;
3570 u8 currPwr = pwrMin;
3571 u16 idxL = 0, idxR = 0;
3572
3573 for (i = 0; i <= (pwrMax - pwrMin) / 2; i++) {
3574 ath9k_hw_get_lower_upper_index(currPwr, pPwrList,
3575 numIntercepts, &(idxL),
3576 &(idxR));
3577 if (idxR < 1)
3578 idxR = 1;
3579 if (idxL == numIntercepts - 1)
3580 idxL = (u16) (numIntercepts - 2);
3581 if (pPwrList[idxL] == pPwrList[idxR])
3582 k = pVpdList[idxL];
3583 else
3584 k = (u16) (((currPwr -
3585 pPwrList[idxL]) *
3586 pVpdList[idxR] +
3587 (pPwrList[idxR] -
3588 currPwr) * pVpdList[idxL]) /
3589 (pPwrList[idxR] -
3590 pPwrList[idxL]));
3591 pRetVpdList[i] = (u8) k;
3592 currPwr += 2;
3593 }
3594
3595 return true;
3596}
3597
3598static inline void
3599ath9k_hw_get_gain_boundaries_pdadcs(struct ath_hal *ah,
3600 struct ath9k_channel *chan,
3601 struct cal_data_per_freq *pRawDataSet,
3602 u8 *bChans,
3603 u16 availPiers,
3604 u16 tPdGainOverlap,
3605 int16_t *pMinCalPower,
3606 u16 *pPdGainBoundaries,
3607 u8 *pPDADCValues,
3608 u16 numXpdGains)
3609{
3610 int i, j, k;
3611 int16_t ss;
3612 u16 idxL = 0, idxR = 0, numPiers;
3613 static u8 vpdTableL[AR5416_NUM_PD_GAINS]
3614 [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
3615 static u8 vpdTableR[AR5416_NUM_PD_GAINS]
3616 [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
3617 static u8 vpdTableI[AR5416_NUM_PD_GAINS]
3618 [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
3619
3620 u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR;
3621 u8 minPwrT4[AR5416_NUM_PD_GAINS];
3622 u8 maxPwrT4[AR5416_NUM_PD_GAINS];
3623 int16_t vpdStep;
3624 int16_t tmpVal;
3625 u16 sizeCurrVpdTable, maxIndex, tgtIndex;
3626 bool match;
3627 int16_t minDelta = 0;
3628 struct chan_centers centers;
3629
3630 ath9k_hw_get_channel_centers(ah, chan, &centers);
3631
3632 for (numPiers = 0; numPiers < availPiers; numPiers++) {
3633 if (bChans[numPiers] == AR5416_BCHAN_UNUSED)
3634 break;
3635 }
3636
3637 match = ath9k_hw_get_lower_upper_index((u8)
3638 FREQ2FBIN(centers.
3639 synth_center,
3640 IS_CHAN_2GHZ
3641 (chan)), bChans,
3642 numPiers, &idxL, &idxR);
3643
3644 if (match) {
3645 for (i = 0; i < numXpdGains; i++) {
3646 minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0];
3647 maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4];
3648 ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
3649 pRawDataSet[idxL].
3650 pwrPdg[i],
3651 pRawDataSet[idxL].
3652 vpdPdg[i],
3653 AR5416_PD_GAIN_ICEPTS,
3654 vpdTableI[i]);
3655 }
3656 } else {
3657 for (i = 0; i < numXpdGains; i++) {
3658 pVpdL = pRawDataSet[idxL].vpdPdg[i];
3659 pPwrL = pRawDataSet[idxL].pwrPdg[i];
3660 pVpdR = pRawDataSet[idxR].vpdPdg[i];
3661 pPwrR = pRawDataSet[idxR].pwrPdg[i];
3662
3663 minPwrT4[i] = max(pPwrL[0], pPwrR[0]);
3664
3665 maxPwrT4[i] =
3666 min(pPwrL[AR5416_PD_GAIN_ICEPTS - 1],
3667 pPwrR[AR5416_PD_GAIN_ICEPTS - 1]);
3668
3669
3670 ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
3671 pPwrL, pVpdL,
3672 AR5416_PD_GAIN_ICEPTS,
3673 vpdTableL[i]);
3674 ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
3675 pPwrR, pVpdR,
3676 AR5416_PD_GAIN_ICEPTS,
3677 vpdTableR[i]);
3678
3679 for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) {
3680 vpdTableI[i][j] =
3681 (u8) (ath9k_hw_interpolate
3682 ((u16)
3683 FREQ2FBIN(centers.
3684 synth_center,
3685 IS_CHAN_2GHZ
3686 (chan)),
3687 bChans[idxL],
3688 bChans[idxR], vpdTableL[i]
3689 [j], vpdTableR[i]
3690 [j]));
3691 }
3692 }
3693 }
3694
3695 *pMinCalPower = (int16_t) (minPwrT4[0] / 2);
3696
3697 k = 0;
3698 for (i = 0; i < numXpdGains; i++) {
3699 if (i == (numXpdGains - 1))
3700 pPdGainBoundaries[i] =
3701 (u16) (maxPwrT4[i] / 2);
3702 else
3703 pPdGainBoundaries[i] =
3704 (u16) ((maxPwrT4[i] +
3705 minPwrT4[i + 1]) / 4);
3706
3707 pPdGainBoundaries[i] =
3708 min((u16) AR5416_MAX_RATE_POWER,
3709 pPdGainBoundaries[i]);
3710
3711 if ((i == 0) && !AR_SREV_5416_V20_OR_LATER(ah)) {
3712 minDelta = pPdGainBoundaries[0] - 23;
3713 pPdGainBoundaries[0] = 23;
3714 } else {
3715 minDelta = 0;
3716 }
3717
3718 if (i == 0) {
3719 if (AR_SREV_9280_10_OR_LATER(ah))
3720 ss = (int16_t) (0 - (minPwrT4[i] / 2));
3721 else
3722 ss = 0;
3723 } else {
3724 ss = (int16_t) ((pPdGainBoundaries[i - 1] -
3725 (minPwrT4[i] / 2)) -
3726 tPdGainOverlap + 1 + minDelta);
3727 }
3728 vpdStep = (int16_t) (vpdTableI[i][1] - vpdTableI[i][0]);
3729 vpdStep = (int16_t) ((vpdStep < 1) ? 1 : vpdStep);
3730
3731 while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
3732 tmpVal = (int16_t) (vpdTableI[i][0] + ss * vpdStep);
3733 pPDADCValues[k++] =
3734 (u8) ((tmpVal < 0) ? 0 : tmpVal);
3735 ss++;
3736 }
3737
3738 sizeCurrVpdTable =
3739 (u8) ((maxPwrT4[i] - minPwrT4[i]) / 2 + 1);
3740 tgtIndex = (u8) (pPdGainBoundaries[i] + tPdGainOverlap -
3741 (minPwrT4[i] / 2));
3742 maxIndex = (tgtIndex <
3743 sizeCurrVpdTable) ? tgtIndex : sizeCurrVpdTable;
3744
3745 while ((ss < maxIndex)
3746 && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
3747 pPDADCValues[k++] = vpdTableI[i][ss++];
3748 }
3749
3750 vpdStep = (int16_t) (vpdTableI[i][sizeCurrVpdTable - 1] -
3751 vpdTableI[i][sizeCurrVpdTable - 2]);
3752 vpdStep = (int16_t) ((vpdStep < 1) ? 1 : vpdStep);
3753
3754 if (tgtIndex > maxIndex) {
3755 while ((ss <= tgtIndex)
3756 && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
3757 tmpVal = (int16_t) ((vpdTableI[i]
3758 [sizeCurrVpdTable -
3759 1] + (ss - maxIndex +
3760 1) * vpdStep));
3761 pPDADCValues[k++] = (u8) ((tmpVal >
3762 255) ? 255 : tmpVal);
3763 ss++;
3764 }
3765 }
3766 }
3767
3768 while (i < AR5416_PD_GAINS_IN_MASK) {
3769 pPdGainBoundaries[i] = pPdGainBoundaries[i - 1];
3770 i++;
3771 }
3772
3773 while (k < AR5416_NUM_PDADC_VALUES) {
3774 pPDADCValues[k] = pPDADCValues[k - 1];
3775 k++;
3776 }
3777 return;
3778}
3779
3780static inline bool
3781ath9k_hw_set_power_cal_table(struct ath_hal *ah,
3782 struct ar5416_eeprom *pEepData,
3783 struct ath9k_channel *chan,
3784 int16_t *pTxPowerIndexOffset)
3785{
3786 struct cal_data_per_freq *pRawDataset;
3787 u8 *pCalBChans = NULL;
3788 u16 pdGainOverlap_t2;
3789 static u8 pdadcValues[AR5416_NUM_PDADC_VALUES];
3790 u16 gainBoundaries[AR5416_PD_GAINS_IN_MASK];
3791 u16 numPiers, i, j;
3792 int16_t tMinCalPower;
3793 u16 numXpdGain, xpdMask;
3794 u16 xpdGainValues[AR5416_NUM_PD_GAINS] = { 0, 0, 0, 0 };
3795 u32 reg32, regOffset, regChainOffset;
3796 int16_t modalIdx;
3797 struct ath_hal_5416 *ahp = AH5416(ah);
3798
3799 modalIdx = IS_CHAN_2GHZ(chan) ? 1 : 0;
3800 xpdMask = pEepData->modalHeader[modalIdx].xpdGain;
3801
3802 if ((pEepData->baseEepHeader.
3803 version & AR5416_EEP_VER_MINOR_MASK) >=
3804 AR5416_EEP_MINOR_VER_2) {
3805 pdGainOverlap_t2 =
3806 pEepData->modalHeader[modalIdx].pdGainOverlap;
3807 } else {
3808 pdGainOverlap_t2 =
3809 (u16) (MS
3810 (REG_READ(ah, AR_PHY_TPCRG5),
3811 AR_PHY_TPCRG5_PD_GAIN_OVERLAP));
3812 }
3813
3814 if (IS_CHAN_2GHZ(chan)) {
3815 pCalBChans = pEepData->calFreqPier2G;
3816 numPiers = AR5416_NUM_2G_CAL_PIERS;
3817 } else {
3818 pCalBChans = pEepData->calFreqPier5G;
3819 numPiers = AR5416_NUM_5G_CAL_PIERS;
3820 }
3821
3822 numXpdGain = 0;
3823
3824 for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) {
3825 if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) {
3826 if (numXpdGain >= AR5416_NUM_PD_GAINS)
3827 break;
3828 xpdGainValues[numXpdGain] =
3829 (u16) (AR5416_PD_GAINS_IN_MASK - i);
3830 numXpdGain++;
3831 }
3832 }
3833
3834 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN,
3835 (numXpdGain - 1) & 0x3);
3836 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1,
3837 xpdGainValues[0]);
3838 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2,
3839 xpdGainValues[1]);
3840 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3,
3841 xpdGainValues[2]);
3842
3843 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
3844 if (AR_SREV_5416_V20_OR_LATER(ah) &&
3845 (ahp->ah_rxchainmask == 5 || ahp->ah_txchainmask == 5)
3846 && (i != 0)) {
3847 regChainOffset = (i == 1) ? 0x2000 : 0x1000;
3848 } else
3849 regChainOffset = i * 0x1000;
3850 if (pEepData->baseEepHeader.txMask & (1 << i)) {
3851 if (IS_CHAN_2GHZ(chan))
3852 pRawDataset = pEepData->calPierData2G[i];
3853 else
3854 pRawDataset = pEepData->calPierData5G[i];
3855
3856 ath9k_hw_get_gain_boundaries_pdadcs(ah, chan,
3857 pRawDataset,
3858 pCalBChans,
3859 numPiers,
3860 pdGainOverlap_t2,
3861 &tMinCalPower,
3862 gainBoundaries,
3863 pdadcValues,
3864 numXpdGain);
3865
3866 if ((i == 0) || AR_SREV_5416_V20_OR_LATER(ah)) {
3867
3868 REG_WRITE(ah,
3869 AR_PHY_TPCRG5 + regChainOffset,
3870 SM(pdGainOverlap_t2,
3871 AR_PHY_TPCRG5_PD_GAIN_OVERLAP)
3872 | SM(gainBoundaries[0],
3873 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1)
3874 | SM(gainBoundaries[1],
3875 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2)
3876 | SM(gainBoundaries[2],
3877 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3)
3878 | SM(gainBoundaries[3],
3879 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4));
3880 }
3881
3882 regOffset =
3883 AR_PHY_BASE + (672 << 2) + regChainOffset;
3884 for (j = 0; j < 32; j++) {
3885 reg32 =
3886 ((pdadcValues[4 * j + 0] & 0xFF) << 0)
3887 | ((pdadcValues[4 * j + 1] & 0xFF) <<
3888 8) | ((pdadcValues[4 * j + 2] &
3889 0xFF) << 16) |
3890 ((pdadcValues[4 * j + 3] & 0xFF) <<
3891 24);
3892 REG_WRITE(ah, regOffset, reg32);
3893
3894 DPRINTF(ah->ah_sc, ATH_DBG_PHY_IO,
3895 "PDADC (%d,%4x): %4.4x %8.8x\n",
3896 i, regChainOffset, regOffset,
3897 reg32);
3898 DPRINTF(ah->ah_sc, ATH_DBG_PHY_IO,
3899 "PDADC: Chain %d | PDADC %3d Value %3d | "
3900 "PDADC %3d Value %3d | PDADC %3d Value %3d | "
3901 "PDADC %3d Value %3d |\n",
3902 i, 4 * j, pdadcValues[4 * j],
3903 4 * j + 1, pdadcValues[4 * j + 1],
3904 4 * j + 2, pdadcValues[4 * j + 2],
3905 4 * j + 3,
3906 pdadcValues[4 * j + 3]);
3907
3908 regOffset += 4;
3909 }
3910 }
3911 }
3912 *pTxPowerIndexOffset = 0;
3913
3914 return true;
3915}
3916
3917void ath9k_hw_configpcipowersave(struct ath_hal *ah, int restore)
3918{
3919 struct ath_hal_5416 *ahp = AH5416(ah);
3920 u8 i;
3921
3922 if (ah->ah_isPciExpress != true)
3923 return;
3924
Sujith60b67f52008-08-07 10:52:38 +05303925 if (ah->ah_config.pcie_powersave_enable == 2)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07003926 return;
3927
3928 if (restore)
3929 return;
3930
3931 if (AR_SREV_9280_20_OR_LATER(ah)) {
3932 for (i = 0; i < ahp->ah_iniPcieSerdes.ia_rows; i++) {
3933 REG_WRITE(ah, INI_RA(&ahp->ah_iniPcieSerdes, i, 0),
3934 INI_RA(&ahp->ah_iniPcieSerdes, i, 1));
3935 }
3936 udelay(1000);
3937 } else if (AR_SREV_9280(ah)
3938 && (ah->ah_macRev == AR_SREV_REVISION_9280_10)) {
3939 REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fd00);
3940 REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
3941
3942 REG_WRITE(ah, AR_PCIE_SERDES, 0xa8000019);
3943 REG_WRITE(ah, AR_PCIE_SERDES, 0x13160820);
3944 REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980560);
3945
Sujith60b67f52008-08-07 10:52:38 +05303946 if (ah->ah_config.pcie_clock_req)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07003947 REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffc);
3948 else
3949 REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffd);
3950
3951 REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);
3952 REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);
3953 REG_WRITE(ah, AR_PCIE_SERDES, 0x00043007);
3954
3955 REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
3956
3957 udelay(1000);
3958 } else {
3959 REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00);
3960 REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
3961 REG_WRITE(ah, AR_PCIE_SERDES, 0x28000039);
3962 REG_WRITE(ah, AR_PCIE_SERDES, 0x53160824);
3963 REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980579);
3964 REG_WRITE(ah, AR_PCIE_SERDES, 0x001defff);
3965 REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);
3966 REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);
3967 REG_WRITE(ah, AR_PCIE_SERDES, 0x000e3007);
3968 REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
3969 }
3970
3971 REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
3972
Sujith60b67f52008-08-07 10:52:38 +05303973 if (ah->ah_config.pcie_waen) {
3974 REG_WRITE(ah, AR_WA, ah->ah_config.pcie_waen);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07003975 } else {
3976 if (AR_SREV_9280(ah))
3977 REG_WRITE(ah, AR_WA, 0x0040073f);
3978 else
3979 REG_WRITE(ah, AR_WA, 0x0000073f);
3980 }
3981}
3982
3983static inline void
3984ath9k_hw_get_legacy_target_powers(struct ath_hal *ah,
3985 struct ath9k_channel *chan,
3986 struct cal_target_power_leg *powInfo,
3987 u16 numChannels,
3988 struct cal_target_power_leg *pNewPower,
3989 u16 numRates,
3990 bool isExtTarget)
3991{
3992 u16 clo, chi;
3993 int i;
3994 int matchIndex = -1, lowIndex = -1;
3995 u16 freq;
3996 struct chan_centers centers;
3997
3998 ath9k_hw_get_channel_centers(ah, chan, &centers);
3999 freq = (isExtTarget) ? centers.ext_center : centers.ctl_center;
4000
4001 if (freq <= ath9k_hw_fbin2freq(powInfo[0].bChannel,
4002 IS_CHAN_2GHZ(chan))) {
4003 matchIndex = 0;
4004 } else {
4005 for (i = 0; (i < numChannels)
4006 && (powInfo[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
4007 if (freq ==
4008 ath9k_hw_fbin2freq(powInfo[i].bChannel,
4009 IS_CHAN_2GHZ(chan))) {
4010 matchIndex = i;
4011 break;
4012 } else if ((freq <
4013 ath9k_hw_fbin2freq(powInfo[i].bChannel,
4014 IS_CHAN_2GHZ(chan)))
4015 && (freq >
4016 ath9k_hw_fbin2freq(powInfo[i - 1].
4017 bChannel,
4018 IS_CHAN_2GHZ
4019 (chan)))) {
4020 lowIndex = i - 1;
4021 break;
4022 }
4023 }
4024 if ((matchIndex == -1) && (lowIndex == -1))
4025 matchIndex = i - 1;
4026 }
4027
4028 if (matchIndex != -1) {
4029 *pNewPower = powInfo[matchIndex];
4030 } else {
4031 clo = ath9k_hw_fbin2freq(powInfo[lowIndex].bChannel,
4032 IS_CHAN_2GHZ(chan));
4033 chi = ath9k_hw_fbin2freq(powInfo[lowIndex + 1].bChannel,
4034 IS_CHAN_2GHZ(chan));
4035
4036 for (i = 0; i < numRates; i++) {
4037 pNewPower->tPow2x[i] =
4038 (u8) ath9k_hw_interpolate(freq, clo, chi,
4039 powInfo
4040 [lowIndex].
4041 tPow2x[i],
4042 powInfo
4043 [lowIndex +
4044 1].tPow2x[i]);
4045 }
4046 }
4047}
4048
4049static inline void
4050ath9k_hw_get_target_powers(struct ath_hal *ah,
4051 struct ath9k_channel *chan,
4052 struct cal_target_power_ht *powInfo,
4053 u16 numChannels,
4054 struct cal_target_power_ht *pNewPower,
4055 u16 numRates,
4056 bool isHt40Target)
4057{
4058 u16 clo, chi;
4059 int i;
4060 int matchIndex = -1, lowIndex = -1;
4061 u16 freq;
4062 struct chan_centers centers;
4063
4064 ath9k_hw_get_channel_centers(ah, chan, &centers);
4065 freq = isHt40Target ? centers.synth_center : centers.ctl_center;
4066
4067 if (freq <=
4068 ath9k_hw_fbin2freq(powInfo[0].bChannel, IS_CHAN_2GHZ(chan))) {
4069 matchIndex = 0;
4070 } else {
4071 for (i = 0; (i < numChannels)
4072 && (powInfo[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
4073 if (freq ==
4074 ath9k_hw_fbin2freq(powInfo[i].bChannel,
4075 IS_CHAN_2GHZ(chan))) {
4076 matchIndex = i;
4077 break;
4078 } else
4079 if ((freq <
4080 ath9k_hw_fbin2freq(powInfo[i].bChannel,
4081 IS_CHAN_2GHZ(chan)))
4082 && (freq >
4083 ath9k_hw_fbin2freq(powInfo[i - 1].
4084 bChannel,
4085 IS_CHAN_2GHZ
4086 (chan)))) {
4087 lowIndex = i - 1;
4088 break;
4089 }
4090 }
4091 if ((matchIndex == -1) && (lowIndex == -1))
4092 matchIndex = i - 1;
4093 }
4094
4095 if (matchIndex != -1) {
4096 *pNewPower = powInfo[matchIndex];
4097 } else {
4098 clo = ath9k_hw_fbin2freq(powInfo[lowIndex].bChannel,
4099 IS_CHAN_2GHZ(chan));
4100 chi = ath9k_hw_fbin2freq(powInfo[lowIndex + 1].bChannel,
4101 IS_CHAN_2GHZ(chan));
4102
4103 for (i = 0; i < numRates; i++) {
4104 pNewPower->tPow2x[i] =
4105 (u8) ath9k_hw_interpolate(freq, clo, chi,
4106 powInfo
4107 [lowIndex].
4108 tPow2x[i],
4109 powInfo
4110 [lowIndex +
4111 1].tPow2x[i]);
4112 }
4113 }
4114}
4115
4116static inline u16
4117ath9k_hw_get_max_edge_power(u16 freq,
4118 struct cal_ctl_edges *pRdEdgesPower,
4119 bool is2GHz)
4120{
4121 u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
4122 int i;
4123
4124 for (i = 0; (i < AR5416_NUM_BAND_EDGES)
4125 && (pRdEdgesPower[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
4126 if (freq == ath9k_hw_fbin2freq(pRdEdgesPower[i].bChannel,
4127 is2GHz)) {
4128 twiceMaxEdgePower = pRdEdgesPower[i].tPower;
4129 break;
4130 } else if ((i > 0)
4131 && (freq <
4132 ath9k_hw_fbin2freq(pRdEdgesPower[i].
4133 bChannel, is2GHz))) {
4134 if (ath9k_hw_fbin2freq
4135 (pRdEdgesPower[i - 1].bChannel, is2GHz) < freq
4136 && pRdEdgesPower[i - 1].flag) {
4137 twiceMaxEdgePower =
4138 pRdEdgesPower[i - 1].tPower;
4139 }
4140 break;
4141 }
4142 }
4143 return twiceMaxEdgePower;
4144}
4145
4146static inline bool
4147ath9k_hw_set_power_per_rate_table(struct ath_hal *ah,
4148 struct ar5416_eeprom *pEepData,
4149 struct ath9k_channel *chan,
4150 int16_t *ratesArray,
4151 u16 cfgCtl,
4152 u8 AntennaReduction,
4153 u8 twiceMaxRegulatoryPower,
4154 u8 powerLimit)
4155{
4156 u8 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
4157 static const u16 tpScaleReductionTable[5] =
4158 { 0, 3, 6, 9, AR5416_MAX_RATE_POWER };
4159
4160 int i;
4161 int8_t twiceLargestAntenna;
4162 struct cal_ctl_data *rep;
4163 struct cal_target_power_leg targetPowerOfdm, targetPowerCck = {
4164 0, { 0, 0, 0, 0}
4165 };
4166 struct cal_target_power_leg targetPowerOfdmExt = {
4167 0, { 0, 0, 0, 0} }, targetPowerCckExt = {
4168 0, { 0, 0, 0, 0 }
4169 };
4170 struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = {
4171 0, {0, 0, 0, 0}
4172 };
4173 u8 scaledPower = 0, minCtlPower, maxRegAllowedPower;
4174 u16 ctlModesFor11a[] =
4175 { CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40 };
4176 u16 ctlModesFor11g[] =
4177 { CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT,
4178 CTL_2GHT40
4179 };
4180 u16 numCtlModes, *pCtlMode, ctlMode, freq;
4181 struct chan_centers centers;
4182 int tx_chainmask;
4183 u8 twiceMinEdgePower;
4184 struct ath_hal_5416 *ahp = AH5416(ah);
4185
4186 tx_chainmask = ahp->ah_txchainmask;
4187
4188 ath9k_hw_get_channel_centers(ah, chan, &centers);
4189
4190 twiceLargestAntenna = max(
4191 pEepData->modalHeader
4192 [IS_CHAN_2GHZ(chan)].antennaGainCh[0],
4193 pEepData->modalHeader
4194 [IS_CHAN_2GHZ(chan)].antennaGainCh[1]);
4195
4196 twiceLargestAntenna = max((u8) twiceLargestAntenna,
4197 pEepData->modalHeader
4198 [IS_CHAN_2GHZ(chan)].antennaGainCh[2]);
4199
4200 twiceLargestAntenna =
4201 (int8_t) min(AntennaReduction - twiceLargestAntenna, 0);
4202
4203 maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
4204
4205 if (ah->ah_tpScale != ATH9K_TP_SCALE_MAX) {
4206 maxRegAllowedPower -=
4207 (tpScaleReductionTable[(ah->ah_tpScale)] * 2);
4208 }
4209
4210 scaledPower = min(powerLimit, maxRegAllowedPower);
4211
4212 switch (ar5416_get_ntxchains(tx_chainmask)) {
4213 case 1:
4214 break;
4215 case 2:
4216 scaledPower -=
4217 pEepData->modalHeader[IS_CHAN_2GHZ(chan)].
4218 pwrDecreaseFor2Chain;
4219 break;
4220 case 3:
4221 scaledPower -=
4222 pEepData->modalHeader[IS_CHAN_2GHZ(chan)].
4223 pwrDecreaseFor3Chain;
4224 break;
4225 }
4226
4227 scaledPower = max(0, (int32_t) scaledPower);
4228
4229 if (IS_CHAN_2GHZ(chan)) {
4230 numCtlModes =
4231 ARRAY_SIZE(ctlModesFor11g) -
4232 SUB_NUM_CTL_MODES_AT_2G_40;
4233 pCtlMode = ctlModesFor11g;
4234
4235 ath9k_hw_get_legacy_target_powers(ah, chan,
4236 pEepData->
4237 calTargetPowerCck,
4238 AR5416_NUM_2G_CCK_TARGET_POWERS,
4239 &targetPowerCck, 4,
4240 false);
4241 ath9k_hw_get_legacy_target_powers(ah, chan,
4242 pEepData->
4243 calTargetPower2G,
4244 AR5416_NUM_2G_20_TARGET_POWERS,
4245 &targetPowerOfdm, 4,
4246 false);
4247 ath9k_hw_get_target_powers(ah, chan,
4248 pEepData->calTargetPower2GHT20,
4249 AR5416_NUM_2G_20_TARGET_POWERS,
4250 &targetPowerHt20, 8, false);
4251
4252 if (IS_CHAN_HT40(chan)) {
4253 numCtlModes = ARRAY_SIZE(ctlModesFor11g);
4254 ath9k_hw_get_target_powers(ah, chan,
4255 pEepData->
4256 calTargetPower2GHT40,
4257 AR5416_NUM_2G_40_TARGET_POWERS,
4258 &targetPowerHt40, 8,
4259 true);
4260 ath9k_hw_get_legacy_target_powers(ah, chan,
4261 pEepData->
4262 calTargetPowerCck,
4263 AR5416_NUM_2G_CCK_TARGET_POWERS,
4264 &targetPowerCckExt,
4265 4, true);
4266 ath9k_hw_get_legacy_target_powers(ah, chan,
4267 pEepData->
4268 calTargetPower2G,
4269 AR5416_NUM_2G_20_TARGET_POWERS,
4270 &targetPowerOfdmExt,
4271 4, true);
4272 }
4273 } else {
4274
4275 numCtlModes =
4276 ARRAY_SIZE(ctlModesFor11a) -
4277 SUB_NUM_CTL_MODES_AT_5G_40;
4278 pCtlMode = ctlModesFor11a;
4279
4280 ath9k_hw_get_legacy_target_powers(ah, chan,
4281 pEepData->
4282 calTargetPower5G,
4283 AR5416_NUM_5G_20_TARGET_POWERS,
4284 &targetPowerOfdm, 4,
4285 false);
4286 ath9k_hw_get_target_powers(ah, chan,
4287 pEepData->calTargetPower5GHT20,
4288 AR5416_NUM_5G_20_TARGET_POWERS,
4289 &targetPowerHt20, 8, false);
4290
4291 if (IS_CHAN_HT40(chan)) {
4292 numCtlModes = ARRAY_SIZE(ctlModesFor11a);
4293 ath9k_hw_get_target_powers(ah, chan,
4294 pEepData->
4295 calTargetPower5GHT40,
4296 AR5416_NUM_5G_40_TARGET_POWERS,
4297 &targetPowerHt40, 8,
4298 true);
4299 ath9k_hw_get_legacy_target_powers(ah, chan,
4300 pEepData->
4301 calTargetPower5G,
4302 AR5416_NUM_5G_20_TARGET_POWERS,
4303 &targetPowerOfdmExt,
4304 4, true);
4305 }
4306 }
4307
4308 for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) {
4309 bool isHt40CtlMode =
4310 (pCtlMode[ctlMode] == CTL_5GHT40)
4311 || (pCtlMode[ctlMode] == CTL_2GHT40);
4312 if (isHt40CtlMode)
4313 freq = centers.synth_center;
4314 else if (pCtlMode[ctlMode] & EXT_ADDITIVE)
4315 freq = centers.ext_center;
4316 else
4317 freq = centers.ctl_center;
4318
4319 if (ar5416_get_eep_ver(ahp) == 14
4320 && ar5416_get_eep_rev(ahp) <= 2)
4321 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
4322
4323 DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT,
4324 "LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d, "
4325 "EXT_ADDITIVE %d\n",
4326 ctlMode, numCtlModes, isHt40CtlMode,
4327 (pCtlMode[ctlMode] & EXT_ADDITIVE));
4328
4329 for (i = 0; (i < AR5416_NUM_CTLS) && pEepData->ctlIndex[i];
4330 i++) {
4331 DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT,
4332 " LOOP-Ctlidx %d: cfgCtl 0x%2.2x "
4333 "pCtlMode 0x%2.2x ctlIndex 0x%2.2x "
4334 "chan %d\n",
4335 i, cfgCtl, pCtlMode[ctlMode],
4336 pEepData->ctlIndex[i], chan->channel);
4337
4338 if ((((cfgCtl & ~CTL_MODE_M) |
4339 (pCtlMode[ctlMode] & CTL_MODE_M)) ==
4340 pEepData->ctlIndex[i])
4341 ||
4342 (((cfgCtl & ~CTL_MODE_M) |
4343 (pCtlMode[ctlMode] & CTL_MODE_M)) ==
4344 ((pEepData->
4345 ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL))) {
4346 rep = &(pEepData->ctlData[i]);
4347
4348 twiceMinEdgePower =
4349 ath9k_hw_get_max_edge_power(freq,
4350 rep->
4351 ctlEdges
4352 [ar5416_get_ntxchains
4353 (tx_chainmask)
4354 - 1],
4355 IS_CHAN_2GHZ
4356 (chan));
4357
4358 DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT,
4359 " MATCH-EE_IDX %d: ch %d is2 %d "
4360 "2xMinEdge %d chainmask %d chains %d\n",
4361 i, freq, IS_CHAN_2GHZ(chan),
4362 twiceMinEdgePower, tx_chainmask,
4363 ar5416_get_ntxchains
4364 (tx_chainmask));
4365 if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) {
4366 twiceMaxEdgePower =
4367 min(twiceMaxEdgePower,
4368 twiceMinEdgePower);
4369 } else {
4370 twiceMaxEdgePower =
4371 twiceMinEdgePower;
4372 break;
4373 }
4374 }
4375 }
4376
4377 minCtlPower = min(twiceMaxEdgePower, scaledPower);
4378
4379 DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT,
4380 " SEL-Min ctlMode %d pCtlMode %d "
4381 "2xMaxEdge %d sP %d minCtlPwr %d\n",
4382 ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower,
4383 scaledPower, minCtlPower);
4384
4385 switch (pCtlMode[ctlMode]) {
4386 case CTL_11B:
4387 for (i = 0; i < ARRAY_SIZE(targetPowerCck.tPow2x);
4388 i++) {
4389 targetPowerCck.tPow2x[i] =
4390 min(targetPowerCck.tPow2x[i],
4391 minCtlPower);
4392 }
4393 break;
4394 case CTL_11A:
4395 case CTL_11G:
4396 for (i = 0; i < ARRAY_SIZE(targetPowerOfdm.tPow2x);
4397 i++) {
4398 targetPowerOfdm.tPow2x[i] =
4399 min(targetPowerOfdm.tPow2x[i],
4400 minCtlPower);
4401 }
4402 break;
4403 case CTL_5GHT20:
4404 case CTL_2GHT20:
4405 for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x);
4406 i++) {
4407 targetPowerHt20.tPow2x[i] =
4408 min(targetPowerHt20.tPow2x[i],
4409 minCtlPower);
4410 }
4411 break;
4412 case CTL_11B_EXT:
4413 targetPowerCckExt.tPow2x[0] =
4414 min(targetPowerCckExt.tPow2x[0], minCtlPower);
4415 break;
4416 case CTL_11A_EXT:
4417 case CTL_11G_EXT:
4418 targetPowerOfdmExt.tPow2x[0] =
4419 min(targetPowerOfdmExt.tPow2x[0], minCtlPower);
4420 break;
4421 case CTL_5GHT40:
4422 case CTL_2GHT40:
4423 for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x);
4424 i++) {
4425 targetPowerHt40.tPow2x[i] =
4426 min(targetPowerHt40.tPow2x[i],
4427 minCtlPower);
4428 }
4429 break;
4430 default:
4431 break;
4432 }
4433 }
4434
4435 ratesArray[rate6mb] = ratesArray[rate9mb] = ratesArray[rate12mb] =
4436 ratesArray[rate18mb] = ratesArray[rate24mb] =
4437 targetPowerOfdm.tPow2x[0];
4438 ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1];
4439 ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2];
4440 ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3];
4441 ratesArray[rateXr] = targetPowerOfdm.tPow2x[0];
4442
4443 for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++)
4444 ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i];
4445
4446 if (IS_CHAN_2GHZ(chan)) {
4447 ratesArray[rate1l] = targetPowerCck.tPow2x[0];
4448 ratesArray[rate2s] = ratesArray[rate2l] =
4449 targetPowerCck.tPow2x[1];
4450 ratesArray[rate5_5s] = ratesArray[rate5_5l] =
4451 targetPowerCck.tPow2x[2];
4452 ;
4453 ratesArray[rate11s] = ratesArray[rate11l] =
4454 targetPowerCck.tPow2x[3];
4455 ;
4456 }
4457 if (IS_CHAN_HT40(chan)) {
4458 for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {
4459 ratesArray[rateHt40_0 + i] =
4460 targetPowerHt40.tPow2x[i];
4461 }
4462 ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0];
4463 ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0];
4464 ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0];
4465 if (IS_CHAN_2GHZ(chan)) {
4466 ratesArray[rateExtCck] =
4467 targetPowerCckExt.tPow2x[0];
4468 }
4469 }
4470 return true;
4471}
4472
4473static int
4474ath9k_hw_set_txpower(struct ath_hal *ah,
4475 struct ar5416_eeprom *pEepData,
4476 struct ath9k_channel *chan,
4477 u16 cfgCtl,
4478 u8 twiceAntennaReduction,
4479 u8 twiceMaxRegulatoryPower,
4480 u8 powerLimit)
4481{
4482 struct modal_eep_header *pModal =
4483 &(pEepData->modalHeader[IS_CHAN_2GHZ(chan)]);
4484 int16_t ratesArray[Ar5416RateSize];
4485 int16_t txPowerIndexOffset = 0;
4486 u8 ht40PowerIncForPdadc = 2;
4487 int i;
4488
4489 memset(ratesArray, 0, sizeof(ratesArray));
4490
4491 if ((pEepData->baseEepHeader.
4492 version & AR5416_EEP_VER_MINOR_MASK) >=
4493 AR5416_EEP_MINOR_VER_2) {
4494 ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
4495 }
4496
4497 if (!ath9k_hw_set_power_per_rate_table(ah, pEepData, chan,
4498 &ratesArray[0], cfgCtl,
4499 twiceAntennaReduction,
4500 twiceMaxRegulatoryPower,
4501 powerLimit)) {
4502 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
4503 "ath9k_hw_set_txpower: unable to set "
4504 "tx power per rate table\n");
4505 return -EIO;
4506 }
4507
4508 if (!ath9k_hw_set_power_cal_table
4509 (ah, pEepData, chan, &txPowerIndexOffset)) {
4510 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
4511 "ath9k_hw_set_txpower: unable to set power table\n");
4512 return -EIO;
4513 }
4514
4515 for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
4516 ratesArray[i] =
4517 (int16_t) (txPowerIndexOffset + ratesArray[i]);
4518 if (ratesArray[i] > AR5416_MAX_RATE_POWER)
4519 ratesArray[i] = AR5416_MAX_RATE_POWER;
4520 }
4521
4522 if (AR_SREV_9280_10_OR_LATER(ah)) {
4523 for (i = 0; i < Ar5416RateSize; i++)
4524 ratesArray[i] -= AR5416_PWR_TABLE_OFFSET * 2;
4525 }
4526
4527 REG_WRITE(ah, AR_PHY_POWER_TX_RATE1,
4528 ATH9K_POW_SM(ratesArray[rate18mb], 24)
4529 | ATH9K_POW_SM(ratesArray[rate12mb], 16)
4530 | ATH9K_POW_SM(ratesArray[rate9mb], 8)
4531 | ATH9K_POW_SM(ratesArray[rate6mb], 0)
4532 );
4533 REG_WRITE(ah, AR_PHY_POWER_TX_RATE2,
4534 ATH9K_POW_SM(ratesArray[rate54mb], 24)
4535 | ATH9K_POW_SM(ratesArray[rate48mb], 16)
4536 | ATH9K_POW_SM(ratesArray[rate36mb], 8)
4537 | ATH9K_POW_SM(ratesArray[rate24mb], 0)
4538 );
4539
4540 if (IS_CHAN_2GHZ(chan)) {
4541 REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
4542 ATH9K_POW_SM(ratesArray[rate2s], 24)
4543 | ATH9K_POW_SM(ratesArray[rate2l], 16)
4544 | ATH9K_POW_SM(ratesArray[rateXr], 8)
4545 | ATH9K_POW_SM(ratesArray[rate1l], 0)
4546 );
4547 REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
4548 ATH9K_POW_SM(ratesArray[rate11s], 24)
4549 | ATH9K_POW_SM(ratesArray[rate11l], 16)
4550 | ATH9K_POW_SM(ratesArray[rate5_5s], 8)
4551 | ATH9K_POW_SM(ratesArray[rate5_5l], 0)
4552 );
4553 }
4554
4555 REG_WRITE(ah, AR_PHY_POWER_TX_RATE5,
4556 ATH9K_POW_SM(ratesArray[rateHt20_3], 24)
4557 | ATH9K_POW_SM(ratesArray[rateHt20_2], 16)
4558 | ATH9K_POW_SM(ratesArray[rateHt20_1], 8)
4559 | ATH9K_POW_SM(ratesArray[rateHt20_0], 0)
4560 );
4561 REG_WRITE(ah, AR_PHY_POWER_TX_RATE6,
4562 ATH9K_POW_SM(ratesArray[rateHt20_7], 24)
4563 | ATH9K_POW_SM(ratesArray[rateHt20_6], 16)
4564 | ATH9K_POW_SM(ratesArray[rateHt20_5], 8)
4565 | ATH9K_POW_SM(ratesArray[rateHt20_4], 0)
4566 );
4567
4568 if (IS_CHAN_HT40(chan)) {
4569 REG_WRITE(ah, AR_PHY_POWER_TX_RATE7,
4570 ATH9K_POW_SM(ratesArray[rateHt40_3] +
4571 ht40PowerIncForPdadc, 24)
4572 | ATH9K_POW_SM(ratesArray[rateHt40_2] +
4573 ht40PowerIncForPdadc, 16)
4574 | ATH9K_POW_SM(ratesArray[rateHt40_1] +
4575 ht40PowerIncForPdadc, 8)
4576 | ATH9K_POW_SM(ratesArray[rateHt40_0] +
4577 ht40PowerIncForPdadc, 0)
4578 );
4579 REG_WRITE(ah, AR_PHY_POWER_TX_RATE8,
4580 ATH9K_POW_SM(ratesArray[rateHt40_7] +
4581 ht40PowerIncForPdadc, 24)
4582 | ATH9K_POW_SM(ratesArray[rateHt40_6] +
4583 ht40PowerIncForPdadc, 16)
4584 | ATH9K_POW_SM(ratesArray[rateHt40_5] +
4585 ht40PowerIncForPdadc, 8)
4586 | ATH9K_POW_SM(ratesArray[rateHt40_4] +
4587 ht40PowerIncForPdadc, 0)
4588 );
4589
4590 REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
4591 ATH9K_POW_SM(ratesArray[rateExtOfdm], 24)
4592 | ATH9K_POW_SM(ratesArray[rateExtCck], 16)
4593 | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
4594 | ATH9K_POW_SM(ratesArray[rateDupCck], 0)
4595 );
4596 }
4597
4598 REG_WRITE(ah, AR_PHY_POWER_TX_SUB,
4599 ATH9K_POW_SM(pModal->pwrDecreaseFor3Chain, 6)
4600 | ATH9K_POW_SM(pModal->pwrDecreaseFor2Chain, 0)
4601 );
4602
4603 i = rate6mb;
4604 if (IS_CHAN_HT40(chan))
4605 i = rateHt40_0;
4606 else if (IS_CHAN_HT20(chan))
4607 i = rateHt20_0;
4608
4609 if (AR_SREV_9280_10_OR_LATER(ah))
4610 ah->ah_maxPowerLevel =
4611 ratesArray[i] + AR5416_PWR_TABLE_OFFSET * 2;
4612 else
4613 ah->ah_maxPowerLevel = ratesArray[i];
4614
4615 return 0;
4616}
4617
4618static inline void ath9k_hw_get_delta_slope_vals(struct ath_hal *ah,
4619 u32 coef_scaled,
4620 u32 *coef_mantissa,
4621 u32 *coef_exponent)
4622{
4623 u32 coef_exp, coef_man;
4624
4625 for (coef_exp = 31; coef_exp > 0; coef_exp--)
4626 if ((coef_scaled >> coef_exp) & 0x1)
4627 break;
4628
4629 coef_exp = 14 - (coef_exp - COEF_SCALE_S);
4630
4631 coef_man = coef_scaled + (1 << (COEF_SCALE_S - coef_exp - 1));
4632
4633 *coef_mantissa = coef_man >> (COEF_SCALE_S - coef_exp);
4634 *coef_exponent = coef_exp - 16;
4635}
4636
4637static void
4638ath9k_hw_set_delta_slope(struct ath_hal *ah,
4639 struct ath9k_channel *chan)
4640{
4641 u32 coef_scaled, ds_coef_exp, ds_coef_man;
4642 u32 clockMhzScaled = 0x64000000;
4643 struct chan_centers centers;
4644
4645 if (IS_CHAN_HALF_RATE(chan))
4646 clockMhzScaled = clockMhzScaled >> 1;
4647 else if (IS_CHAN_QUARTER_RATE(chan))
4648 clockMhzScaled = clockMhzScaled >> 2;
4649
4650 ath9k_hw_get_channel_centers(ah, chan, &centers);
4651 coef_scaled = clockMhzScaled / centers.synth_center;
4652
4653 ath9k_hw_get_delta_slope_vals(ah, coef_scaled, &ds_coef_man,
4654 &ds_coef_exp);
4655
4656 REG_RMW_FIELD(ah, AR_PHY_TIMING3,
4657 AR_PHY_TIMING3_DSC_MAN, ds_coef_man);
4658 REG_RMW_FIELD(ah, AR_PHY_TIMING3,
4659 AR_PHY_TIMING3_DSC_EXP, ds_coef_exp);
4660
4661 coef_scaled = (9 * coef_scaled) / 10;
4662
4663 ath9k_hw_get_delta_slope_vals(ah, coef_scaled, &ds_coef_man,
4664 &ds_coef_exp);
4665
4666 REG_RMW_FIELD(ah, AR_PHY_HALFGI,
4667 AR_PHY_HALFGI_DSC_MAN, ds_coef_man);
4668 REG_RMW_FIELD(ah, AR_PHY_HALFGI,
4669 AR_PHY_HALFGI_DSC_EXP, ds_coef_exp);
4670}
4671
4672static void ath9k_hw_9280_spur_mitigate(struct ath_hal *ah,
4673 struct ath9k_channel *chan)
4674{
4675 int bb_spur = AR_NO_SPUR;
4676 int freq;
4677 int bin, cur_bin;
4678 int bb_spur_off, spur_subchannel_sd;
4679 int spur_freq_sd;
4680 int spur_delta_phase;
4681 int denominator;
4682 int upper, lower, cur_vit_mask;
4683 int tmp, newVal;
4684 int i;
4685 int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8,
4686 AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60
4687 };
4688 int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10,
4689 AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60
4690 };
4691 int inc[4] = { 0, 100, 0, 0 };
4692 struct chan_centers centers;
4693
4694 int8_t mask_m[123];
4695 int8_t mask_p[123];
4696 int8_t mask_amt;
4697 int tmp_mask;
4698 int cur_bb_spur;
4699 bool is2GHz = IS_CHAN_2GHZ(chan);
4700
4701 memset(&mask_m, 0, sizeof(int8_t) * 123);
4702 memset(&mask_p, 0, sizeof(int8_t) * 123);
4703
4704 ath9k_hw_get_channel_centers(ah, chan, &centers);
4705 freq = centers.synth_center;
4706
Sujith60b67f52008-08-07 10:52:38 +05304707 ah->ah_config.spurmode = SPUR_ENABLE_EEPROM;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07004708 for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
4709 cur_bb_spur = ath9k_hw_eeprom_get_spur_chan(ah, i, is2GHz);
4710
4711 if (is2GHz)
4712 cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_2GHZ;
4713 else
4714 cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_5GHZ;
4715
4716 if (AR_NO_SPUR == cur_bb_spur)
4717 break;
4718 cur_bb_spur = cur_bb_spur - freq;
4719
4720 if (IS_CHAN_HT40(chan)) {
4721 if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT40) &&
4722 (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT40)) {
4723 bb_spur = cur_bb_spur;
4724 break;
4725 }
4726 } else if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT20) &&
4727 (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT20)) {
4728 bb_spur = cur_bb_spur;
4729 break;
4730 }
4731 }
4732
4733 if (AR_NO_SPUR == bb_spur) {
4734 REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK,
4735 AR_PHY_FORCE_CLKEN_CCK_MRC_MUX);
4736 return;
4737 } else {
4738 REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK,
4739 AR_PHY_FORCE_CLKEN_CCK_MRC_MUX);
4740 }
4741
4742 bin = bb_spur * 320;
4743
4744 tmp = REG_READ(ah, AR_PHY_TIMING_CTRL4(0));
4745
4746 newVal = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI |
4747 AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER |
4748 AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK |
4749 AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK);
4750 REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0), newVal);
4751
4752 newVal = (AR_PHY_SPUR_REG_MASK_RATE_CNTL |
4753 AR_PHY_SPUR_REG_ENABLE_MASK_PPM |
4754 AR_PHY_SPUR_REG_MASK_RATE_SELECT |
4755 AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI |
4756 SM(SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH));
4757 REG_WRITE(ah, AR_PHY_SPUR_REG, newVal);
4758
4759 if (IS_CHAN_HT40(chan)) {
4760 if (bb_spur < 0) {
4761 spur_subchannel_sd = 1;
4762 bb_spur_off = bb_spur + 10;
4763 } else {
4764 spur_subchannel_sd = 0;
4765 bb_spur_off = bb_spur - 10;
4766 }
4767 } else {
4768 spur_subchannel_sd = 0;
4769 bb_spur_off = bb_spur;
4770 }
4771
4772 if (IS_CHAN_HT40(chan))
4773 spur_delta_phase =
4774 ((bb_spur * 262144) /
4775 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE;
4776 else
4777 spur_delta_phase =
4778 ((bb_spur * 524288) /
4779 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE;
4780
4781 denominator = IS_CHAN_2GHZ(chan) ? 44 : 40;
4782 spur_freq_sd = ((bb_spur_off * 2048) / denominator) & 0x3ff;
4783
4784 newVal = (AR_PHY_TIMING11_USE_SPUR_IN_AGC |
4785 SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) |
4786 SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE));
4787 REG_WRITE(ah, AR_PHY_TIMING11, newVal);
4788
4789 newVal = spur_subchannel_sd << AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S;
4790 REG_WRITE(ah, AR_PHY_SFCORR_EXT, newVal);
4791
4792 cur_bin = -6000;
4793 upper = bin + 100;
4794 lower = bin - 100;
4795
4796 for (i = 0; i < 4; i++) {
4797 int pilot_mask = 0;
4798 int chan_mask = 0;
4799 int bp = 0;
4800 for (bp = 0; bp < 30; bp++) {
4801 if ((cur_bin > lower) && (cur_bin < upper)) {
4802 pilot_mask = pilot_mask | 0x1 << bp;
4803 chan_mask = chan_mask | 0x1 << bp;
4804 }
4805 cur_bin += 100;
4806 }
4807 cur_bin += inc[i];
4808 REG_WRITE(ah, pilot_mask_reg[i], pilot_mask);
4809 REG_WRITE(ah, chan_mask_reg[i], chan_mask);
4810 }
4811
4812 cur_vit_mask = 6100;
4813 upper = bin + 120;
4814 lower = bin - 120;
4815
4816 for (i = 0; i < 123; i++) {
4817 if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) {
Adrian Bunkb08cbcd2008-08-05 22:06:51 +03004818
4819 /* workaround for gcc bug #37014 */
4820 volatile int tmp = abs(cur_vit_mask - bin);
4821
4822 if (tmp < 75)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07004823 mask_amt = 1;
4824 else
4825 mask_amt = 0;
4826 if (cur_vit_mask < 0)
4827 mask_m[abs(cur_vit_mask / 100)] = mask_amt;
4828 else
4829 mask_p[cur_vit_mask / 100] = mask_amt;
4830 }
4831 cur_vit_mask -= 100;
4832 }
4833
4834 tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28)
4835 | (mask_m[48] << 26) | (mask_m[49] << 24)
4836 | (mask_m[50] << 22) | (mask_m[51] << 20)
4837 | (mask_m[52] << 18) | (mask_m[53] << 16)
4838 | (mask_m[54] << 14) | (mask_m[55] << 12)
4839 | (mask_m[56] << 10) | (mask_m[57] << 8)
4840 | (mask_m[58] << 6) | (mask_m[59] << 4)
4841 | (mask_m[60] << 2) | (mask_m[61] << 0);
4842 REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask);
4843 REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask);
4844
4845 tmp_mask = (mask_m[31] << 28)
4846 | (mask_m[32] << 26) | (mask_m[33] << 24)
4847 | (mask_m[34] << 22) | (mask_m[35] << 20)
4848 | (mask_m[36] << 18) | (mask_m[37] << 16)
4849 | (mask_m[48] << 14) | (mask_m[39] << 12)
4850 | (mask_m[40] << 10) | (mask_m[41] << 8)
4851 | (mask_m[42] << 6) | (mask_m[43] << 4)
4852 | (mask_m[44] << 2) | (mask_m[45] << 0);
4853 REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask);
4854 REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask);
4855
4856 tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28)
4857 | (mask_m[18] << 26) | (mask_m[18] << 24)
4858 | (mask_m[20] << 22) | (mask_m[20] << 20)
4859 | (mask_m[22] << 18) | (mask_m[22] << 16)
4860 | (mask_m[24] << 14) | (mask_m[24] << 12)
4861 | (mask_m[25] << 10) | (mask_m[26] << 8)
4862 | (mask_m[27] << 6) | (mask_m[28] << 4)
4863 | (mask_m[29] << 2) | (mask_m[30] << 0);
4864 REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask);
4865 REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask);
4866
4867 tmp_mask = (mask_m[0] << 30) | (mask_m[1] << 28)
4868 | (mask_m[2] << 26) | (mask_m[3] << 24)
4869 | (mask_m[4] << 22) | (mask_m[5] << 20)
4870 | (mask_m[6] << 18) | (mask_m[7] << 16)
4871 | (mask_m[8] << 14) | (mask_m[9] << 12)
4872 | (mask_m[10] << 10) | (mask_m[11] << 8)
4873 | (mask_m[12] << 6) | (mask_m[13] << 4)
4874 | (mask_m[14] << 2) | (mask_m[15] << 0);
4875 REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask);
4876 REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask);
4877
4878 tmp_mask = (mask_p[15] << 28)
4879 | (mask_p[14] << 26) | (mask_p[13] << 24)
4880 | (mask_p[12] << 22) | (mask_p[11] << 20)
4881 | (mask_p[10] << 18) | (mask_p[9] << 16)
4882 | (mask_p[8] << 14) | (mask_p[7] << 12)
4883 | (mask_p[6] << 10) | (mask_p[5] << 8)
4884 | (mask_p[4] << 6) | (mask_p[3] << 4)
4885 | (mask_p[2] << 2) | (mask_p[1] << 0);
4886 REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask);
4887 REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask);
4888
4889 tmp_mask = (mask_p[30] << 28)
4890 | (mask_p[29] << 26) | (mask_p[28] << 24)
4891 | (mask_p[27] << 22) | (mask_p[26] << 20)
4892 | (mask_p[25] << 18) | (mask_p[24] << 16)
4893 | (mask_p[23] << 14) | (mask_p[22] << 12)
4894 | (mask_p[21] << 10) | (mask_p[20] << 8)
4895 | (mask_p[19] << 6) | (mask_p[18] << 4)
4896 | (mask_p[17] << 2) | (mask_p[16] << 0);
4897 REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask);
4898 REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask);
4899
4900 tmp_mask = (mask_p[45] << 28)
4901 | (mask_p[44] << 26) | (mask_p[43] << 24)
4902 | (mask_p[42] << 22) | (mask_p[41] << 20)
4903 | (mask_p[40] << 18) | (mask_p[39] << 16)
4904 | (mask_p[38] << 14) | (mask_p[37] << 12)
4905 | (mask_p[36] << 10) | (mask_p[35] << 8)
4906 | (mask_p[34] << 6) | (mask_p[33] << 4)
4907 | (mask_p[32] << 2) | (mask_p[31] << 0);
4908 REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask);
4909 REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask);
4910
4911 tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28)
4912 | (mask_p[59] << 26) | (mask_p[58] << 24)
4913 | (mask_p[57] << 22) | (mask_p[56] << 20)
4914 | (mask_p[55] << 18) | (mask_p[54] << 16)
4915 | (mask_p[53] << 14) | (mask_p[52] << 12)
4916 | (mask_p[51] << 10) | (mask_p[50] << 8)
4917 | (mask_p[49] << 6) | (mask_p[48] << 4)
4918 | (mask_p[47] << 2) | (mask_p[46] << 0);
4919 REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask);
4920 REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask);
4921}
4922
4923static void ath9k_hw_spur_mitigate(struct ath_hal *ah,
4924 struct ath9k_channel *chan)
4925{
4926 int bb_spur = AR_NO_SPUR;
4927 int bin, cur_bin;
4928 int spur_freq_sd;
4929 int spur_delta_phase;
4930 int denominator;
4931 int upper, lower, cur_vit_mask;
4932 int tmp, new;
4933 int i;
4934 int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8,
4935 AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60
4936 };
4937 int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10,
4938 AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60
4939 };
4940 int inc[4] = { 0, 100, 0, 0 };
4941
4942 int8_t mask_m[123];
4943 int8_t mask_p[123];
4944 int8_t mask_amt;
4945 int tmp_mask;
4946 int cur_bb_spur;
4947 bool is2GHz = IS_CHAN_2GHZ(chan);
4948
4949 memset(&mask_m, 0, sizeof(int8_t) * 123);
4950 memset(&mask_p, 0, sizeof(int8_t) * 123);
4951
4952 for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
4953 cur_bb_spur = ath9k_hw_eeprom_get_spur_chan(ah, i, is2GHz);
4954 if (AR_NO_SPUR == cur_bb_spur)
4955 break;
4956 cur_bb_spur = cur_bb_spur - (chan->channel * 10);
4957 if ((cur_bb_spur > -95) && (cur_bb_spur < 95)) {
4958 bb_spur = cur_bb_spur;
4959 break;
4960 }
4961 }
4962
4963 if (AR_NO_SPUR == bb_spur)
4964 return;
4965
4966 bin = bb_spur * 32;
4967
4968 tmp = REG_READ(ah, AR_PHY_TIMING_CTRL4(0));
4969 new = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI |
4970 AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER |
4971 AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK |
4972 AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK);
4973
4974 REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0), new);
4975
4976 new = (AR_PHY_SPUR_REG_MASK_RATE_CNTL |
4977 AR_PHY_SPUR_REG_ENABLE_MASK_PPM |
4978 AR_PHY_SPUR_REG_MASK_RATE_SELECT |
4979 AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI |
4980 SM(SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH));
4981 REG_WRITE(ah, AR_PHY_SPUR_REG, new);
4982
4983 spur_delta_phase = ((bb_spur * 524288) / 100) &
4984 AR_PHY_TIMING11_SPUR_DELTA_PHASE;
4985
4986 denominator = IS_CHAN_2GHZ(chan) ? 440 : 400;
4987 spur_freq_sd = ((bb_spur * 2048) / denominator) & 0x3ff;
4988
4989 new = (AR_PHY_TIMING11_USE_SPUR_IN_AGC |
4990 SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) |
4991 SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE));
4992 REG_WRITE(ah, AR_PHY_TIMING11, new);
4993
4994 cur_bin = -6000;
4995 upper = bin + 100;
4996 lower = bin - 100;
4997
4998 for (i = 0; i < 4; i++) {
4999 int pilot_mask = 0;
5000 int chan_mask = 0;
5001 int bp = 0;
5002 for (bp = 0; bp < 30; bp++) {
5003 if ((cur_bin > lower) && (cur_bin < upper)) {
5004 pilot_mask = pilot_mask | 0x1 << bp;
5005 chan_mask = chan_mask | 0x1 << bp;
5006 }
5007 cur_bin += 100;
5008 }
5009 cur_bin += inc[i];
5010 REG_WRITE(ah, pilot_mask_reg[i], pilot_mask);
5011 REG_WRITE(ah, chan_mask_reg[i], chan_mask);
5012 }
5013
5014 cur_vit_mask = 6100;
5015 upper = bin + 120;
5016 lower = bin - 120;
5017
5018 for (i = 0; i < 123; i++) {
5019 if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) {
5020 if ((abs(cur_vit_mask - bin)) < 75)
5021 mask_amt = 1;
5022 else
5023 mask_amt = 0;
5024 if (cur_vit_mask < 0)
5025 mask_m[abs(cur_vit_mask / 100)] = mask_amt;
5026 else
5027 mask_p[cur_vit_mask / 100] = mask_amt;
5028 }
5029 cur_vit_mask -= 100;
5030 }
5031
5032 tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28)
5033 | (mask_m[48] << 26) | (mask_m[49] << 24)
5034 | (mask_m[50] << 22) | (mask_m[51] << 20)
5035 | (mask_m[52] << 18) | (mask_m[53] << 16)
5036 | (mask_m[54] << 14) | (mask_m[55] << 12)
5037 | (mask_m[56] << 10) | (mask_m[57] << 8)
5038 | (mask_m[58] << 6) | (mask_m[59] << 4)
5039 | (mask_m[60] << 2) | (mask_m[61] << 0);
5040 REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask);
5041 REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask);
5042
5043 tmp_mask = (mask_m[31] << 28)
5044 | (mask_m[32] << 26) | (mask_m[33] << 24)
5045 | (mask_m[34] << 22) | (mask_m[35] << 20)
5046 | (mask_m[36] << 18) | (mask_m[37] << 16)
5047 | (mask_m[48] << 14) | (mask_m[39] << 12)
5048 | (mask_m[40] << 10) | (mask_m[41] << 8)
5049 | (mask_m[42] << 6) | (mask_m[43] << 4)
5050 | (mask_m[44] << 2) | (mask_m[45] << 0);
5051 REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask);
5052 REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask);
5053
5054 tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28)
5055 | (mask_m[18] << 26) | (mask_m[18] << 24)
5056 | (mask_m[20] << 22) | (mask_m[20] << 20)
5057 | (mask_m[22] << 18) | (mask_m[22] << 16)
5058 | (mask_m[24] << 14) | (mask_m[24] << 12)
5059 | (mask_m[25] << 10) | (mask_m[26] << 8)
5060 | (mask_m[27] << 6) | (mask_m[28] << 4)
5061 | (mask_m[29] << 2) | (mask_m[30] << 0);
5062 REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask);
5063 REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask);
5064
5065 tmp_mask = (mask_m[0] << 30) | (mask_m[1] << 28)
5066 | (mask_m[2] << 26) | (mask_m[3] << 24)
5067 | (mask_m[4] << 22) | (mask_m[5] << 20)
5068 | (mask_m[6] << 18) | (mask_m[7] << 16)
5069 | (mask_m[8] << 14) | (mask_m[9] << 12)
5070 | (mask_m[10] << 10) | (mask_m[11] << 8)
5071 | (mask_m[12] << 6) | (mask_m[13] << 4)
5072 | (mask_m[14] << 2) | (mask_m[15] << 0);
5073 REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask);
5074 REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask);
5075
5076 tmp_mask = (mask_p[15] << 28)
5077 | (mask_p[14] << 26) | (mask_p[13] << 24)
5078 | (mask_p[12] << 22) | (mask_p[11] << 20)
5079 | (mask_p[10] << 18) | (mask_p[9] << 16)
5080 | (mask_p[8] << 14) | (mask_p[7] << 12)
5081 | (mask_p[6] << 10) | (mask_p[5] << 8)
5082 | (mask_p[4] << 6) | (mask_p[3] << 4)
5083 | (mask_p[2] << 2) | (mask_p[1] << 0);
5084 REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask);
5085 REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask);
5086
5087 tmp_mask = (mask_p[30] << 28)
5088 | (mask_p[29] << 26) | (mask_p[28] << 24)
5089 | (mask_p[27] << 22) | (mask_p[26] << 20)
5090 | (mask_p[25] << 18) | (mask_p[24] << 16)
5091 | (mask_p[23] << 14) | (mask_p[22] << 12)
5092 | (mask_p[21] << 10) | (mask_p[20] << 8)
5093 | (mask_p[19] << 6) | (mask_p[18] << 4)
5094 | (mask_p[17] << 2) | (mask_p[16] << 0);
5095 REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask);
5096 REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask);
5097
5098 tmp_mask = (mask_p[45] << 28)
5099 | (mask_p[44] << 26) | (mask_p[43] << 24)
5100 | (mask_p[42] << 22) | (mask_p[41] << 20)
5101 | (mask_p[40] << 18) | (mask_p[39] << 16)
5102 | (mask_p[38] << 14) | (mask_p[37] << 12)
5103 | (mask_p[36] << 10) | (mask_p[35] << 8)
5104 | (mask_p[34] << 6) | (mask_p[33] << 4)
5105 | (mask_p[32] << 2) | (mask_p[31] << 0);
5106 REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask);
5107 REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask);
5108
5109 tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28)
5110 | (mask_p[59] << 26) | (mask_p[58] << 24)
5111 | (mask_p[57] << 22) | (mask_p[56] << 20)
5112 | (mask_p[55] << 18) | (mask_p[54] << 16)
5113 | (mask_p[53] << 14) | (mask_p[52] << 12)
5114 | (mask_p[51] << 10) | (mask_p[50] << 8)
5115 | (mask_p[49] << 6) | (mask_p[48] << 4)
5116 | (mask_p[47] << 2) | (mask_p[46] << 0);
5117 REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask);
5118 REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask);
5119}
5120
5121static inline void ath9k_hw_init_chain_masks(struct ath_hal *ah)
5122{
5123 struct ath_hal_5416 *ahp = AH5416(ah);
5124 int rx_chainmask, tx_chainmask;
5125
5126 rx_chainmask = ahp->ah_rxchainmask;
5127 tx_chainmask = ahp->ah_txchainmask;
5128
5129 switch (rx_chainmask) {
5130 case 0x5:
5131 REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP,
5132 AR_PHY_SWAP_ALT_CHAIN);
5133 case 0x3:
5134 if (((ah)->ah_macVersion <= AR_SREV_VERSION_9160)) {
5135 REG_WRITE(ah, AR_PHY_RX_CHAINMASK, 0x7);
5136 REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, 0x7);
5137 break;
5138 }
5139 case 0x1:
5140 case 0x2:
5141 if (!AR_SREV_9280(ah))
5142 break;
5143 case 0x7:
5144 REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx_chainmask);
5145 REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx_chainmask);
5146 break;
5147 default:
5148 break;
5149 }
5150
5151 REG_WRITE(ah, AR_SELFGEN_MASK, tx_chainmask);
5152 if (tx_chainmask == 0x5) {
5153 REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP,
5154 AR_PHY_SWAP_ALT_CHAIN);
5155 }
5156 if (AR_SREV_9100(ah))
5157 REG_WRITE(ah, AR_PHY_ANALOG_SWAP,
5158 REG_READ(ah, AR_PHY_ANALOG_SWAP) | 0x00000001);
5159}
5160
5161static void ath9k_hw_set_addac(struct ath_hal *ah,
5162 struct ath9k_channel *chan)
5163{
5164 struct modal_eep_header *pModal;
5165 struct ath_hal_5416 *ahp = AH5416(ah);
5166 struct ar5416_eeprom *eep = &ahp->ah_eeprom;
5167 u8 biaslevel;
5168
5169 if (ah->ah_macVersion != AR_SREV_VERSION_9160)
5170 return;
5171
5172 if (ar5416_get_eep_rev(ahp) < AR5416_EEP_MINOR_VER_7)
5173 return;
5174
5175 pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
5176
5177 if (pModal->xpaBiasLvl != 0xff) {
5178 biaslevel = pModal->xpaBiasLvl;
5179 } else {
5180
5181 u16 resetFreqBin, freqBin, freqCount = 0;
5182 struct chan_centers centers;
5183
5184 ath9k_hw_get_channel_centers(ah, chan, &centers);
5185
5186 resetFreqBin =
5187 FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan));
5188 freqBin = pModal->xpaBiasLvlFreq[0] & 0xff;
5189 biaslevel = (u8) (pModal->xpaBiasLvlFreq[0] >> 14);
5190
5191 freqCount++;
5192
5193 while (freqCount < 3) {
5194 if (pModal->xpaBiasLvlFreq[freqCount] == 0x0)
5195 break;
5196
5197 freqBin = pModal->xpaBiasLvlFreq[freqCount] & 0xff;
5198 if (resetFreqBin >= freqBin) {
5199 biaslevel =
5200 (u8) (pModal->
5201 xpaBiasLvlFreq[freqCount]
5202 >> 14);
5203 } else {
5204 break;
5205 }
5206 freqCount++;
5207 }
5208 }
5209
5210 if (IS_CHAN_2GHZ(chan)) {
5211 INI_RA(&ahp->ah_iniAddac, 7, 1) =
5212 (INI_RA(&ahp->ah_iniAddac, 7, 1) & (~0x18)) | biaslevel
5213 << 3;
5214 } else {
5215 INI_RA(&ahp->ah_iniAddac, 6, 1) =
5216 (INI_RA(&ahp->ah_iniAddac, 6, 1) & (~0xc0)) | biaslevel
5217 << 6;
5218 }
5219}
5220
5221static u32 ath9k_hw_mac_usec(struct ath_hal *ah, u32 clks)
5222{
5223 if (ah->ah_curchan != NULL)
5224 return clks /
5225 CLOCK_RATE[ath9k_hw_chan2wmode(ah, ah->ah_curchan)];
5226 else
Sujith86b89ee2008-08-07 10:54:57 +05305227 return clks / CLOCK_RATE[ATH9K_MODE_11B];
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07005228}
5229
5230static u32 ath9k_hw_mac_to_usec(struct ath_hal *ah, u32 clks)
5231{
5232 struct ath9k_channel *chan = ah->ah_curchan;
5233
5234 if (chan && IS_CHAN_HT40(chan))
5235 return ath9k_hw_mac_usec(ah, clks) / 2;
5236 else
5237 return ath9k_hw_mac_usec(ah, clks);
5238}
5239
5240static u32 ath9k_hw_mac_clks(struct ath_hal *ah, u32 usecs)
5241{
5242 if (ah->ah_curchan != NULL)
5243 return usecs * CLOCK_RATE[ath9k_hw_chan2wmode(ah,
5244 ah->ah_curchan)];
5245 else
Sujith86b89ee2008-08-07 10:54:57 +05305246 return usecs * CLOCK_RATE[ATH9K_MODE_11B];
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07005247}
5248
5249static u32 ath9k_hw_mac_to_clks(struct ath_hal *ah, u32 usecs)
5250{
5251 struct ath9k_channel *chan = ah->ah_curchan;
5252
5253 if (chan && IS_CHAN_HT40(chan))
5254 return ath9k_hw_mac_clks(ah, usecs) * 2;
5255 else
5256 return ath9k_hw_mac_clks(ah, usecs);
5257}
5258
5259static bool ath9k_hw_set_ack_timeout(struct ath_hal *ah, u32 us)
5260{
5261 struct ath_hal_5416 *ahp = AH5416(ah);
5262
5263 if (us > ath9k_hw_mac_to_usec(ah, MS(0xffffffff, AR_TIME_OUT_ACK))) {
5264 DPRINTF(ah->ah_sc, ATH_DBG_RESET, "%s: bad ack timeout %u\n",
5265 __func__, us);
5266 ahp->ah_acktimeout = (u32) -1;
5267 return false;
5268 } else {
5269 REG_RMW_FIELD(ah, AR_TIME_OUT,
5270 AR_TIME_OUT_ACK, ath9k_hw_mac_to_clks(ah, us));
5271 ahp->ah_acktimeout = us;
5272 return true;
5273 }
5274}
5275
5276static bool ath9k_hw_set_cts_timeout(struct ath_hal *ah, u32 us)
5277{
5278 struct ath_hal_5416 *ahp = AH5416(ah);
5279
5280 if (us > ath9k_hw_mac_to_usec(ah, MS(0xffffffff, AR_TIME_OUT_CTS))) {
5281 DPRINTF(ah->ah_sc, ATH_DBG_RESET, "%s: bad cts timeout %u\n",
5282 __func__, us);
5283 ahp->ah_ctstimeout = (u32) -1;
5284 return false;
5285 } else {
5286 REG_RMW_FIELD(ah, AR_TIME_OUT,
5287 AR_TIME_OUT_CTS, ath9k_hw_mac_to_clks(ah, us));
5288 ahp->ah_ctstimeout = us;
5289 return true;
5290 }
5291}
5292static bool ath9k_hw_set_global_txtimeout(struct ath_hal *ah,
5293 u32 tu)
5294{
5295 struct ath_hal_5416 *ahp = AH5416(ah);
5296
5297 if (tu > 0xFFFF) {
5298 DPRINTF(ah->ah_sc, ATH_DBG_XMIT,
5299 "%s: bad global tx timeout %u\n", __func__, tu);
5300 ahp->ah_globaltxtimeout = (u32) -1;
5301 return false;
5302 } else {
5303 REG_RMW_FIELD(ah, AR_GTXTO, AR_GTXTO_TIMEOUT_LIMIT, tu);
5304 ahp->ah_globaltxtimeout = tu;
5305 return true;
5306 }
5307}
5308
5309bool ath9k_hw_setslottime(struct ath_hal *ah, u32 us)
5310{
5311 struct ath_hal_5416 *ahp = AH5416(ah);
5312
5313 if (us < ATH9K_SLOT_TIME_9 || us > ath9k_hw_mac_to_usec(ah, 0xffff)) {
5314 DPRINTF(ah->ah_sc, ATH_DBG_RESET, "%s: bad slot time %u\n",
5315 __func__, us);
5316 ahp->ah_slottime = (u32) -1;
5317 return false;
5318 } else {
5319 REG_WRITE(ah, AR_D_GBL_IFS_SLOT, ath9k_hw_mac_to_clks(ah, us));
5320 ahp->ah_slottime = us;
5321 return true;
5322 }
5323}
5324
5325static inline void ath9k_hw_init_user_settings(struct ath_hal *ah)
5326{
5327 struct ath_hal_5416 *ahp = AH5416(ah);
5328
5329 DPRINTF(ah->ah_sc, ATH_DBG_RESET, "--AP %s ahp->ah_miscMode 0x%x\n",
5330 __func__, ahp->ah_miscMode);
5331 if (ahp->ah_miscMode != 0)
5332 REG_WRITE(ah, AR_PCU_MISC,
5333 REG_READ(ah, AR_PCU_MISC) | ahp->ah_miscMode);
5334 if (ahp->ah_slottime != (u32) -1)
5335 ath9k_hw_setslottime(ah, ahp->ah_slottime);
5336 if (ahp->ah_acktimeout != (u32) -1)
5337 ath9k_hw_set_ack_timeout(ah, ahp->ah_acktimeout);
5338 if (ahp->ah_ctstimeout != (u32) -1)
5339 ath9k_hw_set_cts_timeout(ah, ahp->ah_ctstimeout);
5340 if (ahp->ah_globaltxtimeout != (u32) -1)
5341 ath9k_hw_set_global_txtimeout(ah, ahp->ah_globaltxtimeout);
5342}
5343
5344static inline int
5345ath9k_hw_process_ini(struct ath_hal *ah,
5346 struct ath9k_channel *chan,
5347 enum ath9k_ht_macmode macmode)
5348{
5349 int i, regWrites = 0;
5350 struct ath_hal_5416 *ahp = AH5416(ah);
5351 u32 modesIndex, freqIndex;
5352 int status;
5353
5354 switch (chan->chanmode) {
5355 case CHANNEL_A:
5356 case CHANNEL_A_HT20:
5357 modesIndex = 1;
5358 freqIndex = 1;
5359 break;
5360 case CHANNEL_A_HT40PLUS:
5361 case CHANNEL_A_HT40MINUS:
5362 modesIndex = 2;
5363 freqIndex = 1;
5364 break;
5365 case CHANNEL_G:
5366 case CHANNEL_G_HT20:
5367 case CHANNEL_B:
5368 modesIndex = 4;
5369 freqIndex = 2;
5370 break;
5371 case CHANNEL_G_HT40PLUS:
5372 case CHANNEL_G_HT40MINUS:
5373 modesIndex = 3;
5374 freqIndex = 2;
5375 break;
5376
5377 default:
5378 return -EINVAL;
5379 }
5380
5381 REG_WRITE(ah, AR_PHY(0), 0x00000007);
5382
5383 REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_EXTERNAL_RADIO);
5384
5385 ath9k_hw_set_addac(ah, chan);
5386
5387 if (AR_SREV_5416_V22_OR_LATER(ah)) {
5388 REG_WRITE_ARRAY(&ahp->ah_iniAddac, 1, regWrites);
5389 } else {
5390 struct ar5416IniArray temp;
5391 u32 addacSize =
5392 sizeof(u32) * ahp->ah_iniAddac.ia_rows *
5393 ahp->ah_iniAddac.ia_columns;
5394
5395 memcpy(ahp->ah_addac5416_21,
5396 ahp->ah_iniAddac.ia_array, addacSize);
5397
5398 (ahp->ah_addac5416_21)[31 *
5399 ahp->ah_iniAddac.ia_columns + 1] = 0;
5400
5401 temp.ia_array = ahp->ah_addac5416_21;
5402 temp.ia_columns = ahp->ah_iniAddac.ia_columns;
5403 temp.ia_rows = ahp->ah_iniAddac.ia_rows;
5404 REG_WRITE_ARRAY(&temp, 1, regWrites);
5405 }
5406 REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC);
5407
5408 for (i = 0; i < ahp->ah_iniModes.ia_rows; i++) {
5409 u32 reg = INI_RA(&ahp->ah_iniModes, i, 0);
5410 u32 val = INI_RA(&ahp->ah_iniModes, i, modesIndex);
5411
5412#ifdef CONFIG_SLOW_ANT_DIV
5413 if (ah->ah_devid == AR9280_DEVID_PCI)
5414 val = ath9k_hw_ini_fixup(ah, &ahp->ah_eeprom, reg,
5415 val);
5416#endif
5417
5418 REG_WRITE(ah, reg, val);
5419
5420 if (reg >= 0x7800 && reg < 0x78a0
Sujith60b67f52008-08-07 10:52:38 +05305421 && ah->ah_config.analog_shiftreg) {
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07005422 udelay(100);
5423 }
5424
5425 DO_DELAY(regWrites);
5426 }
5427
5428 for (i = 0; i < ahp->ah_iniCommon.ia_rows; i++) {
5429 u32 reg = INI_RA(&ahp->ah_iniCommon, i, 0);
5430 u32 val = INI_RA(&ahp->ah_iniCommon, i, 1);
5431
5432 REG_WRITE(ah, reg, val);
5433
5434 if (reg >= 0x7800 && reg < 0x78a0
Sujith60b67f52008-08-07 10:52:38 +05305435 && ah->ah_config.analog_shiftreg) {
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07005436 udelay(100);
5437 }
5438
5439 DO_DELAY(regWrites);
5440 }
5441
5442 ath9k_hw_write_regs(ah, modesIndex, freqIndex, regWrites);
5443
5444 if (AR_SREV_9280_20(ah) && IS_CHAN_A_5MHZ_SPACED(chan)) {
5445 REG_WRITE_ARRAY(&ahp->ah_iniModesAdditional, modesIndex,
5446 regWrites);
5447 }
5448
5449 ath9k_hw_override_ini(ah, chan);
5450 ath9k_hw_set_regs(ah, chan, macmode);
5451 ath9k_hw_init_chain_masks(ah);
5452
5453 status = ath9k_hw_set_txpower(ah, &ahp->ah_eeprom, chan,
5454 ath9k_regd_get_ctl(ah, chan),
5455 ath9k_regd_get_antenna_allowed(ah,
5456 chan),
5457 chan->maxRegTxPower * 2,
5458 min((u32) MAX_RATE_POWER,
5459 (u32) ah->ah_powerLimit));
5460 if (status != 0) {
5461 DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT,
5462 "%s: error init'ing transmit power\n", __func__);
5463 return -EIO;
5464 }
5465
5466 if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) {
5467 DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
5468 "%s: ar5416SetRfRegs failed\n", __func__);
5469 return -EIO;
5470 }
5471
5472 return 0;
5473}
5474
5475static inline void ath9k_hw_setup_calibration(struct ath_hal *ah,
5476 struct hal_cal_list *currCal)
5477{
5478 REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(0),
5479 AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX,
5480 currCal->calData->calCountMax);
5481
5482 switch (currCal->calData->calType) {
5483 case IQ_MISMATCH_CAL:
5484 REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ);
5485 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
5486 "%s: starting IQ Mismatch Calibration\n",
5487 __func__);
5488 break;
5489 case ADC_GAIN_CAL:
5490 REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_GAIN);
5491 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
5492 "%s: starting ADC Gain Calibration\n", __func__);
5493 break;
5494 case ADC_DC_CAL:
5495 REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_PER);
5496 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
5497 "%s: starting ADC DC Calibration\n", __func__);
5498 break;
5499 case ADC_DC_INIT_CAL:
5500 REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_INIT);
5501 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
5502 "%s: starting Init ADC DC Calibration\n",
5503 __func__);
5504 break;
5505 }
5506
5507 REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0),
5508 AR_PHY_TIMING_CTRL4_DO_CAL);
5509}
5510
5511static inline void ath9k_hw_reset_calibration(struct ath_hal *ah,
5512 struct hal_cal_list *currCal)
5513{
5514 struct ath_hal_5416 *ahp = AH5416(ah);
5515 int i;
5516
5517 ath9k_hw_setup_calibration(ah, currCal);
5518
5519 currCal->calState = CAL_RUNNING;
5520
5521 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
5522 ahp->ah_Meas0.sign[i] = 0;
5523 ahp->ah_Meas1.sign[i] = 0;
5524 ahp->ah_Meas2.sign[i] = 0;
5525 ahp->ah_Meas3.sign[i] = 0;
5526 }
5527
5528 ahp->ah_CalSamples = 0;
5529}
5530
5531static inline void
5532ath9k_hw_per_calibration(struct ath_hal *ah,
5533 struct ath9k_channel *ichan,
5534 u8 rxchainmask,
5535 struct hal_cal_list *currCal,
5536 bool *isCalDone)
5537{
5538 struct ath_hal_5416 *ahp = AH5416(ah);
5539
5540 *isCalDone = false;
5541
5542 if (currCal->calState == CAL_RUNNING) {
5543 if (!(REG_READ(ah,
5544 AR_PHY_TIMING_CTRL4(0)) &
5545 AR_PHY_TIMING_CTRL4_DO_CAL)) {
5546
5547 currCal->calData->calCollect(ah);
5548
5549 ahp->ah_CalSamples++;
5550
5551 if (ahp->ah_CalSamples >=
5552 currCal->calData->calNumSamples) {
5553 int i, numChains = 0;
5554 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
5555 if (rxchainmask & (1 << i))
5556 numChains++;
5557 }
5558
5559 currCal->calData->calPostProc(ah,
5560 numChains);
5561
5562 ichan->CalValid |=
5563 currCal->calData->calType;
5564 currCal->calState = CAL_DONE;
5565 *isCalDone = true;
5566 } else {
5567 ath9k_hw_setup_calibration(ah, currCal);
5568 }
5569 }
5570 } else if (!(ichan->CalValid & currCal->calData->calType)) {
5571 ath9k_hw_reset_calibration(ah, currCal);
5572 }
5573}
5574
5575static inline bool ath9k_hw_run_init_cals(struct ath_hal *ah,
5576 int init_cal_count)
5577{
5578 struct ath_hal_5416 *ahp = AH5416(ah);
5579 struct ath9k_channel ichan;
5580 bool isCalDone;
5581 struct hal_cal_list *currCal = ahp->ah_cal_list_curr;
5582 const struct hal_percal_data *calData = currCal->calData;
5583 int i;
5584
5585 if (currCal == NULL)
5586 return false;
5587
5588 ichan.CalValid = 0;
5589
5590 for (i = 0; i < init_cal_count; i++) {
5591 ath9k_hw_reset_calibration(ah, currCal);
5592
5593 if (!ath9k_hw_wait(ah, AR_PHY_TIMING_CTRL4(0),
5594 AR_PHY_TIMING_CTRL4_DO_CAL, 0)) {
5595 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
5596 "%s: Cal %d failed to complete in 100ms.\n",
5597 __func__, calData->calType);
5598
5599 ahp->ah_cal_list = ahp->ah_cal_list_last =
5600 ahp->ah_cal_list_curr = NULL;
5601 return false;
5602 }
5603
5604 ath9k_hw_per_calibration(ah, &ichan, ahp->ah_rxchainmask,
5605 currCal, &isCalDone);
5606 if (!isCalDone) {
5607 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
5608 "%s: Not able to run Init Cal %d.\n",
5609 __func__, calData->calType);
5610 }
5611 if (currCal->calNext) {
5612 currCal = currCal->calNext;
5613 calData = currCal->calData;
5614 }
5615 }
5616
5617 ahp->ah_cal_list = ahp->ah_cal_list_last = ahp->ah_cal_list_curr = NULL;
5618 return true;
5619}
5620
5621static inline bool
5622ath9k_hw_channel_change(struct ath_hal *ah,
5623 struct ath9k_channel *chan,
5624 enum ath9k_ht_macmode macmode)
5625{
5626 u32 synthDelay, qnum;
5627 struct ath_hal_5416 *ahp = AH5416(ah);
5628
5629 for (qnum = 0; qnum < AR_NUM_QCU; qnum++) {
5630 if (ath9k_hw_numtxpending(ah, qnum)) {
5631 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
5632 "%s: Transmit frames pending on queue %d\n",
5633 __func__, qnum);
5634 return false;
5635 }
5636 }
5637
5638 REG_WRITE(ah, AR_PHY_RFBUS_REQ, AR_PHY_RFBUS_REQ_EN);
5639 if (!ath9k_hw_wait(ah, AR_PHY_RFBUS_GRANT, AR_PHY_RFBUS_GRANT_EN,
5640 AR_PHY_RFBUS_GRANT_EN)) {
5641 DPRINTF(ah->ah_sc, ATH_DBG_PHY_IO,
5642 "%s: Could not kill baseband RX\n", __func__);
5643 return false;
5644 }
5645
5646 ath9k_hw_set_regs(ah, chan, macmode);
5647
5648 if (AR_SREV_9280_10_OR_LATER(ah)) {
5649 if (!(ath9k_hw_ar9280_set_channel(ah, chan))) {
5650 DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
5651 "%s: failed to set channel\n", __func__);
5652 return false;
5653 }
5654 } else {
5655 if (!(ath9k_hw_set_channel(ah, chan))) {
5656 DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
5657 "%s: failed to set channel\n", __func__);
5658 return false;
5659 }
5660 }
5661
5662 if (ath9k_hw_set_txpower(ah, &ahp->ah_eeprom, chan,
5663 ath9k_regd_get_ctl(ah, chan),
5664 ath9k_regd_get_antenna_allowed(ah, chan),
5665 chan->maxRegTxPower * 2,
5666 min((u32) MAX_RATE_POWER,
5667 (u32) ah->ah_powerLimit)) != 0) {
5668 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
5669 "%s: error init'ing transmit power\n", __func__);
5670 return false;
5671 }
5672
5673 synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;
5674 if (IS_CHAN_CCK(chan))
5675 synthDelay = (4 * synthDelay) / 22;
5676 else
5677 synthDelay /= 10;
5678
5679 udelay(synthDelay + BASE_ACTIVATE_DELAY);
5680
5681 REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0);
5682
5683 if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan))
5684 ath9k_hw_set_delta_slope(ah, chan);
5685
5686 if (AR_SREV_9280_10_OR_LATER(ah))
5687 ath9k_hw_9280_spur_mitigate(ah, chan);
5688 else
5689 ath9k_hw_spur_mitigate(ah, chan);
5690
5691 if (!chan->oneTimeCalsDone)
5692 chan->oneTimeCalsDone = true;
5693
5694 return true;
5695}
5696
5697static bool ath9k_hw_chip_reset(struct ath_hal *ah,
5698 struct ath9k_channel *chan)
5699{
5700 struct ath_hal_5416 *ahp = AH5416(ah);
5701
5702 if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM))
5703 return false;
5704
5705 if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
5706 return false;
5707
5708 ahp->ah_chipFullSleep = false;
5709
5710 ath9k_hw_init_pll(ah, chan);
5711
5712 ath9k_hw_set_rfmode(ah, chan);
5713
5714 return true;
5715}
5716
5717static inline void ath9k_hw_set_dma(struct ath_hal *ah)
5718{
5719 u32 regval;
5720
5721 regval = REG_READ(ah, AR_AHB_MODE);
5722 REG_WRITE(ah, AR_AHB_MODE, regval | AR_AHB_PREFETCH_RD_EN);
5723
5724 regval = REG_READ(ah, AR_TXCFG) & ~AR_TXCFG_DMASZ_MASK;
5725 REG_WRITE(ah, AR_TXCFG, regval | AR_TXCFG_DMASZ_128B);
5726
5727 REG_RMW_FIELD(ah, AR_TXCFG, AR_FTRIG, ah->ah_txTrigLevel);
5728
5729 regval = REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_DMASZ_MASK;
5730 REG_WRITE(ah, AR_RXCFG, regval | AR_RXCFG_DMASZ_128B);
5731
5732 REG_WRITE(ah, AR_RXFIFO_CFG, 0x200);
5733
5734 if (AR_SREV_9285(ah)) {
5735 REG_WRITE(ah, AR_PCU_TXBUF_CTRL,
5736 AR_9285_PCU_TXBUF_CTRL_USABLE_SIZE);
5737 } else {
5738 REG_WRITE(ah, AR_PCU_TXBUF_CTRL,
5739 AR_PCU_TXBUF_CTRL_USABLE_SIZE);
5740 }
5741}
5742
5743bool ath9k_hw_stopdmarecv(struct ath_hal *ah)
5744{
5745 REG_WRITE(ah, AR_CR, AR_CR_RXD);
5746 if (!ath9k_hw_wait(ah, AR_CR, AR_CR_RXE, 0)) {
5747 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
5748 "%s: dma failed to stop in 10ms\n"
5749 "AR_CR=0x%08x\nAR_DIAG_SW=0x%08x\n",
5750 __func__,
5751 REG_READ(ah, AR_CR), REG_READ(ah, AR_DIAG_SW));
5752 return false;
5753 } else {
5754 return true;
5755 }
5756}
5757
5758void ath9k_hw_startpcureceive(struct ath_hal *ah)
5759{
5760 REG_CLR_BIT(ah, AR_DIAG_SW,
5761 (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
5762
5763 ath9k_enable_mib_counters(ah);
5764
5765 ath9k_ani_reset(ah);
5766}
5767
5768void ath9k_hw_stoppcurecv(struct ath_hal *ah)
5769{
5770 REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS);
5771
5772 ath9k_hw_disable_mib_counters(ah);
5773}
5774
5775static bool ath9k_hw_iscal_supported(struct ath_hal *ah,
5776 struct ath9k_channel *chan,
5777 enum hal_cal_types calType)
5778{
5779 struct ath_hal_5416 *ahp = AH5416(ah);
5780 bool retval = false;
5781
5782 switch (calType & ahp->ah_suppCals) {
5783 case IQ_MISMATCH_CAL:
5784 if (!IS_CHAN_B(chan))
5785 retval = true;
5786 break;
5787 case ADC_GAIN_CAL:
5788 case ADC_DC_CAL:
5789 if (!IS_CHAN_B(chan)
5790 && !(IS_CHAN_2GHZ(chan) && IS_CHAN_HT20(chan)))
5791 retval = true;
5792 break;
5793 }
5794
5795 return retval;
5796}
5797
5798static inline bool ath9k_hw_init_cal(struct ath_hal *ah,
5799 struct ath9k_channel *chan)
5800{
5801 struct ath_hal_5416 *ahp = AH5416(ah);
5802 struct ath9k_channel *ichan =
5803 ath9k_regd_check_channel(ah, chan);
5804
5805 REG_WRITE(ah, AR_PHY_AGC_CONTROL,
5806 REG_READ(ah, AR_PHY_AGC_CONTROL) |
5807 AR_PHY_AGC_CONTROL_CAL);
5808
5809 if (!ath9k_hw_wait
5810 (ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0)) {
5811 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
5812 "%s: offset calibration failed to complete in 1ms; "
5813 "noisy environment?\n", __func__);
5814 return false;
5815 }
5816
5817 REG_WRITE(ah, AR_PHY_AGC_CONTROL,
5818 REG_READ(ah, AR_PHY_AGC_CONTROL) |
5819 AR_PHY_AGC_CONTROL_NF);
5820
5821 ahp->ah_cal_list = ahp->ah_cal_list_last = ahp->ah_cal_list_curr =
5822 NULL;
5823
5824 if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) {
5825 if (ath9k_hw_iscal_supported(ah, chan, ADC_GAIN_CAL)) {
5826 INIT_CAL(&ahp->ah_adcGainCalData);
5827 INSERT_CAL(ahp, &ahp->ah_adcGainCalData);
5828 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
5829 "%s: enabling ADC Gain Calibration.\n",
5830 __func__);
5831 }
5832 if (ath9k_hw_iscal_supported(ah, chan, ADC_DC_CAL)) {
5833 INIT_CAL(&ahp->ah_adcDcCalData);
5834 INSERT_CAL(ahp, &ahp->ah_adcDcCalData);
5835 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
5836 "%s: enabling ADC DC Calibration.\n",
5837 __func__);
5838 }
5839 if (ath9k_hw_iscal_supported(ah, chan, IQ_MISMATCH_CAL)) {
5840 INIT_CAL(&ahp->ah_iqCalData);
5841 INSERT_CAL(ahp, &ahp->ah_iqCalData);
5842 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
5843 "%s: enabling IQ Calibration.\n",
5844 __func__);
5845 }
5846
5847 ahp->ah_cal_list_curr = ahp->ah_cal_list;
5848
5849 if (ahp->ah_cal_list_curr)
5850 ath9k_hw_reset_calibration(ah,
5851 ahp->ah_cal_list_curr);
5852 }
5853
5854 ichan->CalValid = 0;
5855
5856 return true;
5857}
5858
5859
5860bool ath9k_hw_reset(struct ath_hal *ah, enum ath9k_opmode opmode,
5861 struct ath9k_channel *chan,
5862 enum ath9k_ht_macmode macmode,
5863 u8 txchainmask, u8 rxchainmask,
5864 enum ath9k_ht_extprotspacing extprotspacing,
5865 bool bChannelChange,
5866 int *status)
5867{
5868#define FAIL(_code) do { ecode = _code; goto bad; } while (0)
5869 u32 saveLedState;
5870 struct ath_hal_5416 *ahp = AH5416(ah);
5871 struct ath9k_channel *curchan = ah->ah_curchan;
5872 u32 saveDefAntenna;
5873 u32 macStaId1;
5874 int ecode;
5875 int i, rx_chainmask;
5876
5877 ahp->ah_extprotspacing = extprotspacing;
5878 ahp->ah_txchainmask = txchainmask;
5879 ahp->ah_rxchainmask = rxchainmask;
5880
5881 if (AR_SREV_9280(ah)) {
5882 ahp->ah_txchainmask &= 0x3;
5883 ahp->ah_rxchainmask &= 0x3;
5884 }
5885
5886 if (ath9k_hw_check_chan(ah, chan) == NULL) {
5887 DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
5888 "%s: invalid channel %u/0x%x; no mapping\n",
5889 __func__, chan->channel, chan->channelFlags);
5890 FAIL(-EINVAL);
5891 }
5892
5893 if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
5894 return false;
5895
5896 if (curchan)
5897 ath9k_hw_getnf(ah, curchan);
5898
5899 if (bChannelChange &&
5900 (ahp->ah_chipFullSleep != true) &&
5901 (ah->ah_curchan != NULL) &&
5902 (chan->channel != ah->ah_curchan->channel) &&
5903 ((chan->channelFlags & CHANNEL_ALL) ==
5904 (ah->ah_curchan->channelFlags & CHANNEL_ALL)) &&
5905 (!AR_SREV_9280(ah) || (!IS_CHAN_A_5MHZ_SPACED(chan) &&
5906 !IS_CHAN_A_5MHZ_SPACED(ah->
5907 ah_curchan)))) {
5908
5909 if (ath9k_hw_channel_change(ah, chan, macmode)) {
5910 ath9k_hw_loadnf(ah, ah->ah_curchan);
5911 ath9k_hw_start_nfcal(ah);
5912 return true;
5913 }
5914 }
5915
5916 saveDefAntenna = REG_READ(ah, AR_DEF_ANTENNA);
5917 if (saveDefAntenna == 0)
5918 saveDefAntenna = 1;
5919
5920 macStaId1 = REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_BASE_RATE_11B;
5921
5922 saveLedState = REG_READ(ah, AR_CFG_LED) &
5923 (AR_CFG_LED_ASSOC_CTL | AR_CFG_LED_MODE_SEL |
5924 AR_CFG_LED_BLINK_THRESH_SEL | AR_CFG_LED_BLINK_SLOW);
5925
5926 ath9k_hw_mark_phy_inactive(ah);
5927
5928 if (!ath9k_hw_chip_reset(ah, chan)) {
5929 DPRINTF(ah->ah_sc, ATH_DBG_RESET, "%s: chip reset failed\n",
5930 __func__);
5931 FAIL(-EIO);
5932 }
5933
5934 if (AR_SREV_9280(ah)) {
5935 REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL,
5936 AR_GPIO_JTAG_DISABLE);
5937
Sujith86b89ee2008-08-07 10:54:57 +05305938 if (test_bit(ATH9K_MODE_11A, ah->ah_caps.wireless_modes)) {
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07005939 if (IS_CHAN_5GHZ(chan))
5940 ath9k_hw_set_gpio(ah, 9, 0);
5941 else
5942 ath9k_hw_set_gpio(ah, 9, 1);
5943 }
5944 ath9k_hw_cfg_output(ah, 9, ATH9K_GPIO_OUTPUT_MUX_AS_OUTPUT);
5945 }
5946
5947 ecode = ath9k_hw_process_ini(ah, chan, macmode);
5948 if (ecode != 0)
5949 goto bad;
5950
5951 if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan))
5952 ath9k_hw_set_delta_slope(ah, chan);
5953
5954 if (AR_SREV_9280_10_OR_LATER(ah))
5955 ath9k_hw_9280_spur_mitigate(ah, chan);
5956 else
5957 ath9k_hw_spur_mitigate(ah, chan);
5958
5959 if (!ath9k_hw_eeprom_set_board_values(ah, chan)) {
5960 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
5961 "%s: error setting board options\n", __func__);
5962 FAIL(-EIO);
5963 }
5964
5965 ath9k_hw_decrease_chain_power(ah, chan);
5966
5967 REG_WRITE(ah, AR_STA_ID0, get_unaligned_le32(ahp->ah_macaddr));
5968 REG_WRITE(ah, AR_STA_ID1, get_unaligned_le16(ahp->ah_macaddr + 4)
5969 | macStaId1
5970 | AR_STA_ID1_RTS_USE_DEF
5971 | (ah->ah_config.
Sujith60b67f52008-08-07 10:52:38 +05305972 ack_6mb ? AR_STA_ID1_ACKCTS_6MB : 0)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07005973 | ahp->ah_staId1Defaults);
5974 ath9k_hw_set_operating_mode(ah, opmode);
5975
5976 REG_WRITE(ah, AR_BSSMSKL, get_unaligned_le32(ahp->ah_bssidmask));
5977 REG_WRITE(ah, AR_BSSMSKU, get_unaligned_le16(ahp->ah_bssidmask + 4));
5978
5979 REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna);
5980
5981 REG_WRITE(ah, AR_BSS_ID0, get_unaligned_le32(ahp->ah_bssid));
5982 REG_WRITE(ah, AR_BSS_ID1, get_unaligned_le16(ahp->ah_bssid + 4) |
5983 ((ahp->ah_assocId & 0x3fff) << AR_BSS_ID1_AID_S));
5984
5985 REG_WRITE(ah, AR_ISR, ~0);
5986
5987 REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR);
5988
5989 if (AR_SREV_9280_10_OR_LATER(ah)) {
5990 if (!(ath9k_hw_ar9280_set_channel(ah, chan)))
5991 FAIL(-EIO);
5992 } else {
5993 if (!(ath9k_hw_set_channel(ah, chan)))
5994 FAIL(-EIO);
5995 }
5996
5997 for (i = 0; i < AR_NUM_DCU; i++)
5998 REG_WRITE(ah, AR_DQCUMASK(i), 1 << i);
5999
6000 ahp->ah_intrTxqs = 0;
Sujith60b67f52008-08-07 10:52:38 +05306001 for (i = 0; i < ah->ah_caps.total_queues; i++)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07006002 ath9k_hw_resettxqueue(ah, i);
6003
6004 ath9k_hw_init_interrupt_masks(ah, opmode);
6005 ath9k_hw_init_qos(ah);
6006
6007 ath9k_hw_init_user_settings(ah);
6008
6009 ah->ah_opmode = opmode;
6010
6011 REG_WRITE(ah, AR_STA_ID1,
6012 REG_READ(ah, AR_STA_ID1) | AR_STA_ID1_PRESERVE_SEQNUM);
6013
6014 ath9k_hw_set_dma(ah);
6015
6016 REG_WRITE(ah, AR_OBS, 8);
6017
6018 if (ahp->ah_intrMitigation) {
6019
6020 REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, 500);
6021 REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_FIRST, 2000);
6022 }
6023
6024 ath9k_hw_init_bb(ah, chan);
6025
6026 if (!ath9k_hw_init_cal(ah, chan))
6027 FAIL(-ENODEV);
6028
6029 rx_chainmask = ahp->ah_rxchainmask;
6030 if ((rx_chainmask == 0x5) || (rx_chainmask == 0x3)) {
6031 REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx_chainmask);
6032 REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx_chainmask);
6033 }
6034
6035 REG_WRITE(ah, AR_CFG_LED, saveLedState | AR_CFG_SCLK_32KHZ);
6036
6037 if (AR_SREV_9100(ah)) {
6038 u32 mask;
6039 mask = REG_READ(ah, AR_CFG);
6040 if (mask & (AR_CFG_SWRB | AR_CFG_SWTB | AR_CFG_SWRG)) {
6041 DPRINTF(ah->ah_sc, ATH_DBG_RESET,
6042 "%s CFG Byte Swap Set 0x%x\n", __func__,
6043 mask);
6044 } else {
6045 mask =
6046 INIT_CONFIG_STATUS | AR_CFG_SWRB | AR_CFG_SWTB;
6047 REG_WRITE(ah, AR_CFG, mask);
6048 DPRINTF(ah->ah_sc, ATH_DBG_RESET,
6049 "%s Setting CFG 0x%x\n", __func__,
6050 REG_READ(ah, AR_CFG));
6051 }
6052 } else {
6053#ifdef __BIG_ENDIAN
6054 REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD);
6055#endif
6056 }
6057
6058 return true;
6059bad:
6060 if (status)
6061 *status = ecode;
6062 return false;
6063#undef FAIL
6064}
6065
6066bool ath9k_hw_phy_disable(struct ath_hal *ah)
6067{
6068 return ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM);
6069}
6070
6071bool ath9k_hw_disable(struct ath_hal *ah)
6072{
6073 if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
6074 return false;
6075
6076 return ath9k_hw_set_reset_reg(ah, ATH9K_RESET_COLD);
6077}
6078
6079bool
6080ath9k_hw_calibrate(struct ath_hal *ah, struct ath9k_channel *chan,
6081 u8 rxchainmask, bool longcal,
6082 bool *isCalDone)
6083{
6084 struct ath_hal_5416 *ahp = AH5416(ah);
6085 struct hal_cal_list *currCal = ahp->ah_cal_list_curr;
6086 struct ath9k_channel *ichan =
6087 ath9k_regd_check_channel(ah, chan);
6088
6089 *isCalDone = true;
6090
6091 if (ichan == NULL) {
6092 DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
6093 "%s: invalid channel %u/0x%x; no mapping\n",
6094 __func__, chan->channel, chan->channelFlags);
6095 return false;
6096 }
6097
6098 if (currCal &&
6099 (currCal->calState == CAL_RUNNING ||
6100 currCal->calState == CAL_WAITING)) {
6101 ath9k_hw_per_calibration(ah, ichan, rxchainmask, currCal,
6102 isCalDone);
6103 if (*isCalDone) {
6104 ahp->ah_cal_list_curr = currCal = currCal->calNext;
6105
6106 if (currCal->calState == CAL_WAITING) {
6107 *isCalDone = false;
6108 ath9k_hw_reset_calibration(ah, currCal);
6109 }
6110 }
6111 }
6112
6113 if (longcal) {
6114 ath9k_hw_getnf(ah, ichan);
6115 ath9k_hw_loadnf(ah, ah->ah_curchan);
6116 ath9k_hw_start_nfcal(ah);
6117
6118 if ((ichan->channelFlags & CHANNEL_CW_INT) != 0) {
6119
6120 chan->channelFlags |= CHANNEL_CW_INT;
6121 ichan->channelFlags &= ~CHANNEL_CW_INT;
6122 }
6123 }
6124
6125 return true;
6126}
6127
6128static void ath9k_hw_iqcal_collect(struct ath_hal *ah)
6129{
6130 struct ath_hal_5416 *ahp = AH5416(ah);
6131 int i;
6132
6133 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
6134 ahp->ah_totalPowerMeasI[i] +=
6135 REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
6136 ahp->ah_totalPowerMeasQ[i] +=
6137 REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
6138 ahp->ah_totalIqCorrMeas[i] +=
6139 (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
6140 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
6141 "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
6142 ahp->ah_CalSamples, i, ahp->ah_totalPowerMeasI[i],
6143 ahp->ah_totalPowerMeasQ[i],
6144 ahp->ah_totalIqCorrMeas[i]);
6145 }
6146}
6147
6148static void ath9k_hw_adc_gaincal_collect(struct ath_hal *ah)
6149{
6150 struct ath_hal_5416 *ahp = AH5416(ah);
6151 int i;
6152
6153 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
6154 ahp->ah_totalAdcIOddPhase[i] +=
6155 REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
6156 ahp->ah_totalAdcIEvenPhase[i] +=
6157 REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
6158 ahp->ah_totalAdcQOddPhase[i] +=
6159 REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
6160 ahp->ah_totalAdcQEvenPhase[i] +=
6161 REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
6162
6163 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
6164 "%d: Chn %d oddi=0x%08x; eveni=0x%08x; "
6165 "oddq=0x%08x; evenq=0x%08x;\n",
6166 ahp->ah_CalSamples, i,
6167 ahp->ah_totalAdcIOddPhase[i],
6168 ahp->ah_totalAdcIEvenPhase[i],
6169 ahp->ah_totalAdcQOddPhase[i],
6170 ahp->ah_totalAdcQEvenPhase[i]);
6171 }
6172}
6173
6174static void ath9k_hw_adc_dccal_collect(struct ath_hal *ah)
6175{
6176 struct ath_hal_5416 *ahp = AH5416(ah);
6177 int i;
6178
6179 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
6180 ahp->ah_totalAdcDcOffsetIOddPhase[i] +=
6181 (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
6182 ahp->ah_totalAdcDcOffsetIEvenPhase[i] +=
6183 (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
6184 ahp->ah_totalAdcDcOffsetQOddPhase[i] +=
6185 (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
6186 ahp->ah_totalAdcDcOffsetQEvenPhase[i] +=
6187 (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
6188
6189 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
6190 "%d: Chn %d oddi=0x%08x; eveni=0x%08x; "
6191 "oddq=0x%08x; evenq=0x%08x;\n",
6192 ahp->ah_CalSamples, i,
6193 ahp->ah_totalAdcDcOffsetIOddPhase[i],
6194 ahp->ah_totalAdcDcOffsetIEvenPhase[i],
6195 ahp->ah_totalAdcDcOffsetQOddPhase[i],
6196 ahp->ah_totalAdcDcOffsetQEvenPhase[i]);
6197 }
6198}
6199
6200static void ath9k_hw_iqcalibrate(struct ath_hal *ah, u8 numChains)
6201{
6202 struct ath_hal_5416 *ahp = AH5416(ah);
6203 u32 powerMeasQ, powerMeasI, iqCorrMeas;
6204 u32 qCoffDenom, iCoffDenom;
6205 int32_t qCoff, iCoff;
6206 int iqCorrNeg, i;
6207
6208 for (i = 0; i < numChains; i++) {
6209 powerMeasI = ahp->ah_totalPowerMeasI[i];
6210 powerMeasQ = ahp->ah_totalPowerMeasQ[i];
6211 iqCorrMeas = ahp->ah_totalIqCorrMeas[i];
6212
6213 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
6214 "Starting IQ Cal and Correction for Chain %d\n",
6215 i);
6216
6217 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
6218 "Orignal: Chn %diq_corr_meas = 0x%08x\n",
6219 i, ahp->ah_totalIqCorrMeas[i]);
6220
6221 iqCorrNeg = 0;
6222
6223
6224 if (iqCorrMeas > 0x80000000) {
6225 iqCorrMeas = (0xffffffff - iqCorrMeas) + 1;
6226 iqCorrNeg = 1;
6227 }
6228
6229 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
6230 "Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI);
6231 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
6232 "Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ);
6233 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "iqCorrNeg is 0x%08x\n",
6234 iqCorrNeg);
6235
6236 iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128;
6237 qCoffDenom = powerMeasQ / 64;
6238
6239 if (powerMeasQ != 0) {
6240
6241 iCoff = iqCorrMeas / iCoffDenom;
6242 qCoff = powerMeasI / qCoffDenom - 64;
6243 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
6244 "Chn %d iCoff = 0x%08x\n", i, iCoff);
6245 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
6246 "Chn %d qCoff = 0x%08x\n", i, qCoff);
6247
6248
6249 iCoff = iCoff & 0x3f;
6250 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
6251 "New: Chn %d iCoff = 0x%08x\n", i, iCoff);
6252 if (iqCorrNeg == 0x0)
6253 iCoff = 0x40 - iCoff;
6254
6255 if (qCoff > 15)
6256 qCoff = 15;
6257 else if (qCoff <= -16)
6258 qCoff = 16;
6259
6260 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
6261 "Chn %d : iCoff = 0x%x qCoff = 0x%x\n",
6262 i, iCoff, qCoff);
6263
6264 REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i),
6265 AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF,
6266 iCoff);
6267 REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i),
6268 AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF,
6269 qCoff);
6270 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
6271 "IQ Cal and Correction done for Chain %d\n",
6272 i);
6273 }
6274 }
6275
6276 REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0),
6277 AR_PHY_TIMING_CTRL4_IQCORR_ENABLE);
6278}
6279
6280static void
6281ath9k_hw_adc_gaincal_calibrate(struct ath_hal *ah, u8 numChains)
6282{
6283 struct ath_hal_5416 *ahp = AH5416(ah);
6284 u32 iOddMeasOffset, iEvenMeasOffset, qOddMeasOffset,
6285 qEvenMeasOffset;
6286 u32 qGainMismatch, iGainMismatch, val, i;
6287
6288 for (i = 0; i < numChains; i++) {
6289 iOddMeasOffset = ahp->ah_totalAdcIOddPhase[i];
6290 iEvenMeasOffset = ahp->ah_totalAdcIEvenPhase[i];
6291 qOddMeasOffset = ahp->ah_totalAdcQOddPhase[i];
6292 qEvenMeasOffset = ahp->ah_totalAdcQEvenPhase[i];
6293
6294 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
6295 "Starting ADC Gain Cal for Chain %d\n", i);
6296
6297 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
6298 "Chn %d pwr_meas_odd_i = 0x%08x\n", i,
6299 iOddMeasOffset);
6300 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
6301 "Chn %d pwr_meas_even_i = 0x%08x\n", i,
6302 iEvenMeasOffset);
6303 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
6304 "Chn %d pwr_meas_odd_q = 0x%08x\n", i,
6305 qOddMeasOffset);
6306 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
6307 "Chn %d pwr_meas_even_q = 0x%08x\n", i,
6308 qEvenMeasOffset);
6309
6310 if (iOddMeasOffset != 0 && qEvenMeasOffset != 0) {
6311 iGainMismatch =
6312 ((iEvenMeasOffset * 32) /
6313 iOddMeasOffset) & 0x3f;
6314 qGainMismatch =
6315 ((qOddMeasOffset * 32) /
6316 qEvenMeasOffset) & 0x3f;
6317
6318 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
6319 "Chn %d gain_mismatch_i = 0x%08x\n", i,
6320 iGainMismatch);
6321 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
6322 "Chn %d gain_mismatch_q = 0x%08x\n", i,
6323 qGainMismatch);
6324
6325 val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
6326 val &= 0xfffff000;
6327 val |= (qGainMismatch) | (iGainMismatch << 6);
6328 REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
6329
6330 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
6331 "ADC Gain Cal done for Chain %d\n", i);
6332 }
6333 }
6334
6335 REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
6336 REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
6337 AR_PHY_NEW_ADC_GAIN_CORR_ENABLE);
6338}
6339
6340static void
6341ath9k_hw_adc_dccal_calibrate(struct ath_hal *ah, u8 numChains)
6342{
6343 struct ath_hal_5416 *ahp = AH5416(ah);
6344 u32 iOddMeasOffset, iEvenMeasOffset, val, i;
6345 int32_t qOddMeasOffset, qEvenMeasOffset, qDcMismatch, iDcMismatch;
6346 const struct hal_percal_data *calData =
6347 ahp->ah_cal_list_curr->calData;
6348 u32 numSamples =
6349 (1 << (calData->calCountMax + 5)) * calData->calNumSamples;
6350
6351 for (i = 0; i < numChains; i++) {
6352 iOddMeasOffset = ahp->ah_totalAdcDcOffsetIOddPhase[i];
6353 iEvenMeasOffset = ahp->ah_totalAdcDcOffsetIEvenPhase[i];
6354 qOddMeasOffset = ahp->ah_totalAdcDcOffsetQOddPhase[i];
6355 qEvenMeasOffset = ahp->ah_totalAdcDcOffsetQEvenPhase[i];
6356
6357 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
6358 "Starting ADC DC Offset Cal for Chain %d\n", i);
6359
6360 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
6361 "Chn %d pwr_meas_odd_i = %d\n", i,
6362 iOddMeasOffset);
6363 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
6364 "Chn %d pwr_meas_even_i = %d\n", i,
6365 iEvenMeasOffset);
6366 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
6367 "Chn %d pwr_meas_odd_q = %d\n", i,
6368 qOddMeasOffset);
6369 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
6370 "Chn %d pwr_meas_even_q = %d\n", i,
6371 qEvenMeasOffset);
6372
6373 iDcMismatch = (((iEvenMeasOffset - iOddMeasOffset) * 2) /
6374 numSamples) & 0x1ff;
6375 qDcMismatch = (((qOddMeasOffset - qEvenMeasOffset) * 2) /
6376 numSamples) & 0x1ff;
6377
6378 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
6379 "Chn %d dc_offset_mismatch_i = 0x%08x\n", i,
6380 iDcMismatch);
6381 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
6382 "Chn %d dc_offset_mismatch_q = 0x%08x\n", i,
6383 qDcMismatch);
6384
6385 val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
6386 val &= 0xc0000fff;
6387 val |= (qDcMismatch << 12) | (iDcMismatch << 21);
6388 REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
6389
6390 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
6391 "ADC DC Offset Cal done for Chain %d\n", i);
6392 }
6393
6394 REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
6395 REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
6396 AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE);
6397}
6398
6399bool ath9k_hw_set_txpowerlimit(struct ath_hal *ah, u32 limit)
6400{
6401 struct ath_hal_5416 *ahp = AH5416(ah);
6402 struct ath9k_channel *chan = ah->ah_curchan;
6403
6404 ah->ah_powerLimit = min(limit, (u32) MAX_RATE_POWER);
6405
6406 if (ath9k_hw_set_txpower(ah, &ahp->ah_eeprom, chan,
6407 ath9k_regd_get_ctl(ah, chan),
6408 ath9k_regd_get_antenna_allowed(ah,
6409 chan),
6410 chan->maxRegTxPower * 2,
6411 min((u32) MAX_RATE_POWER,
6412 (u32) ah->ah_powerLimit)) != 0)
6413 return false;
6414
6415 return true;
6416}
6417
6418void
6419ath9k_hw_get_channel_centers(struct ath_hal *ah,
6420 struct ath9k_channel *chan,
6421 struct chan_centers *centers)
6422{
6423 int8_t extoff;
6424 struct ath_hal_5416 *ahp = AH5416(ah);
6425
6426 if (!IS_CHAN_HT40(chan)) {
6427 centers->ctl_center = centers->ext_center =
6428 centers->synth_center = chan->channel;
6429 return;
6430 }
6431
6432 if ((chan->chanmode == CHANNEL_A_HT40PLUS) ||
6433 (chan->chanmode == CHANNEL_G_HT40PLUS)) {
6434 centers->synth_center =
6435 chan->channel + HT40_CHANNEL_CENTER_SHIFT;
6436 extoff = 1;
6437 } else {
6438 centers->synth_center =
6439 chan->channel - HT40_CHANNEL_CENTER_SHIFT;
6440 extoff = -1;
6441 }
6442
6443 centers->ctl_center = centers->synth_center - (extoff *
6444 HT40_CHANNEL_CENTER_SHIFT);
6445 centers->ext_center = centers->synth_center + (extoff *
6446 ((ahp->
6447 ah_extprotspacing
6448 ==
6449 ATH9K_HT_EXTPROTSPACING_20)
6450 ?
6451 HT40_CHANNEL_CENTER_SHIFT
6452 : 15));
6453
6454}
6455
6456void
6457ath9k_hw_reset_calvalid(struct ath_hal *ah, struct ath9k_channel *chan,
6458 bool *isCalDone)
6459{
6460 struct ath_hal_5416 *ahp = AH5416(ah);
6461 struct ath9k_channel *ichan =
6462 ath9k_regd_check_channel(ah, chan);
6463 struct hal_cal_list *currCal = ahp->ah_cal_list_curr;
6464
6465 *isCalDone = true;
6466
6467 if (!AR_SREV_9100(ah) && !AR_SREV_9160_10_OR_LATER(ah))
6468 return;
6469
6470 if (currCal == NULL)
6471 return;
6472
6473 if (ichan == NULL) {
6474 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
6475 "%s: invalid channel %u/0x%x; no mapping\n",
6476 __func__, chan->channel, chan->channelFlags);
6477 return;
6478 }
6479
6480
6481 if (currCal->calState != CAL_DONE) {
6482 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
6483 "%s: Calibration state incorrect, %d\n",
6484 __func__, currCal->calState);
6485 return;
6486 }
6487
6488
6489 if (!ath9k_hw_iscal_supported(ah, chan, currCal->calData->calType))
6490 return;
6491
6492 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
6493 "%s: Resetting Cal %d state for channel %u/0x%x\n",
6494 __func__, currCal->calData->calType, chan->channel,
6495 chan->channelFlags);
6496
6497 ichan->CalValid &= ~currCal->calData->calType;
6498 currCal->calState = CAL_WAITING;
6499
6500 *isCalDone = false;
6501}
6502
6503void ath9k_hw_getmac(struct ath_hal *ah, u8 *mac)
6504{
6505 struct ath_hal_5416 *ahp = AH5416(ah);
6506
6507 memcpy(mac, ahp->ah_macaddr, ETH_ALEN);
6508}
6509
6510bool ath9k_hw_setmac(struct ath_hal *ah, const u8 *mac)
6511{
6512 struct ath_hal_5416 *ahp = AH5416(ah);
6513
6514 memcpy(ahp->ah_macaddr, mac, ETH_ALEN);
6515 return true;
6516}
6517
6518void ath9k_hw_getbssidmask(struct ath_hal *ah, u8 *mask)
6519{
6520 struct ath_hal_5416 *ahp = AH5416(ah);
6521
6522 memcpy(mask, ahp->ah_bssidmask, ETH_ALEN);
6523}
6524
6525bool
6526ath9k_hw_setbssidmask(struct ath_hal *ah, const u8 *mask)
6527{
6528 struct ath_hal_5416 *ahp = AH5416(ah);
6529
6530 memcpy(ahp->ah_bssidmask, mask, ETH_ALEN);
6531
6532 REG_WRITE(ah, AR_BSSMSKL, get_unaligned_le32(ahp->ah_bssidmask));
6533 REG_WRITE(ah, AR_BSSMSKU, get_unaligned_le16(ahp->ah_bssidmask + 4));
6534
6535 return true;
6536}
6537
6538#ifdef CONFIG_ATH9K_RFKILL
6539static void ath9k_enable_rfkill(struct ath_hal *ah)
6540{
6541 struct ath_hal_5416 *ahp = AH5416(ah);
6542
6543 REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL,
6544 AR_GPIO_INPUT_EN_VAL_RFSILENT_BB);
6545
6546 REG_CLR_BIT(ah, AR_GPIO_INPUT_MUX2,
6547 AR_GPIO_INPUT_MUX2_RFSILENT);
6548
6549 ath9k_hw_cfg_gpio_input(ah, ahp->ah_gpioSelect);
6550 REG_SET_BIT(ah, AR_PHY_TEST, RFSILENT_BB);
6551
6552 if (ahp->ah_gpioBit == ath9k_hw_gpio_get(ah, ahp->ah_gpioSelect)) {
6553
6554 ath9k_hw_set_gpio_intr(ah, ahp->ah_gpioSelect,
6555 !ahp->ah_gpioBit);
6556 } else {
6557 ath9k_hw_set_gpio_intr(ah, ahp->ah_gpioSelect,
6558 ahp->ah_gpioBit);
6559 }
6560}
6561#endif
6562
6563void
6564ath9k_hw_write_associd(struct ath_hal *ah, const u8 *bssid,
6565 u16 assocId)
6566{
6567 struct ath_hal_5416 *ahp = AH5416(ah);
6568
6569 memcpy(ahp->ah_bssid, bssid, ETH_ALEN);
6570 ahp->ah_assocId = assocId;
6571
6572 REG_WRITE(ah, AR_BSS_ID0, get_unaligned_le32(ahp->ah_bssid));
6573 REG_WRITE(ah, AR_BSS_ID1, get_unaligned_le16(ahp->ah_bssid + 4) |
6574 ((assocId & 0x3fff) << AR_BSS_ID1_AID_S));
6575}
6576
6577u64 ath9k_hw_gettsf64(struct ath_hal *ah)
6578{
6579 u64 tsf;
6580
6581 tsf = REG_READ(ah, AR_TSF_U32);
6582 tsf = (tsf << 32) | REG_READ(ah, AR_TSF_L32);
6583 return tsf;
6584}
6585
6586void ath9k_hw_reset_tsf(struct ath_hal *ah)
6587{
6588 int count;
6589
6590 count = 0;
6591 while (REG_READ(ah, AR_SLP32_MODE) & AR_SLP32_TSF_WRITE_STATUS) {
6592 count++;
6593 if (count > 10) {
6594 DPRINTF(ah->ah_sc, ATH_DBG_RESET,
6595 "%s: AR_SLP32_TSF_WRITE_STATUS limit exceeded\n",
6596 __func__);
6597 break;
6598 }
6599 udelay(10);
6600 }
6601 REG_WRITE(ah, AR_RESET_TSF, AR_RESET_TSF_ONCE);
6602}
6603
6604u32 ath9k_hw_getdefantenna(struct ath_hal *ah)
6605{
6606 return REG_READ(ah, AR_DEF_ANTENNA) & 0x7;
6607}
6608
6609void ath9k_hw_setantenna(struct ath_hal *ah, u32 antenna)
6610{
6611 REG_WRITE(ah, AR_DEF_ANTENNA, (antenna & 0x7));
6612}
6613
6614bool
6615ath9k_hw_setantennaswitch(struct ath_hal *ah,
6616 enum ath9k_ant_setting settings,
6617 struct ath9k_channel *chan,
6618 u8 *tx_chainmask,
6619 u8 *rx_chainmask,
6620 u8 *antenna_cfgd)
6621{
6622 struct ath_hal_5416 *ahp = AH5416(ah);
6623 static u8 tx_chainmask_cfg, rx_chainmask_cfg;
6624
6625 if (AR_SREV_9280(ah)) {
6626 if (!tx_chainmask_cfg) {
6627
6628 tx_chainmask_cfg = *tx_chainmask;
6629 rx_chainmask_cfg = *rx_chainmask;
6630 }
6631
6632 switch (settings) {
6633 case ATH9K_ANT_FIXED_A:
6634 *tx_chainmask = ATH9K_ANTENNA0_CHAINMASK;
6635 *rx_chainmask = ATH9K_ANTENNA0_CHAINMASK;
6636 *antenna_cfgd = true;
6637 break;
6638 case ATH9K_ANT_FIXED_B:
Sujith60b67f52008-08-07 10:52:38 +05306639 if (ah->ah_caps.tx_chainmask >
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07006640 ATH9K_ANTENNA1_CHAINMASK) {
6641 *tx_chainmask = ATH9K_ANTENNA1_CHAINMASK;
6642 }
6643 *rx_chainmask = ATH9K_ANTENNA1_CHAINMASK;
6644 *antenna_cfgd = true;
6645 break;
6646 case ATH9K_ANT_VARIABLE:
6647 *tx_chainmask = tx_chainmask_cfg;
6648 *rx_chainmask = rx_chainmask_cfg;
6649 *antenna_cfgd = true;
6650 break;
6651 default:
6652 break;
6653 }
6654 } else {
6655 ahp->ah_diversityControl = settings;
6656 }
6657
6658 return true;
6659}
6660
6661void ath9k_hw_setopmode(struct ath_hal *ah)
6662{
6663 ath9k_hw_set_operating_mode(ah, ah->ah_opmode);
6664}
6665
6666bool
Sujith60b67f52008-08-07 10:52:38 +05306667ath9k_hw_getcapability(struct ath_hal *ah, enum ath9k_capability_type type,
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07006668 u32 capability, u32 *result)
6669{
6670 struct ath_hal_5416 *ahp = AH5416(ah);
Sujith60b67f52008-08-07 10:52:38 +05306671 const struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07006672
6673 switch (type) {
Sujith60b67f52008-08-07 10:52:38 +05306674 case ATH9K_CAP_CIPHER:
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07006675 switch (capability) {
6676 case ATH9K_CIPHER_AES_CCM:
6677 case ATH9K_CIPHER_AES_OCB:
6678 case ATH9K_CIPHER_TKIP:
6679 case ATH9K_CIPHER_WEP:
6680 case ATH9K_CIPHER_MIC:
6681 case ATH9K_CIPHER_CLR:
6682 return true;
6683 default:
6684 return false;
6685 }
Sujith60b67f52008-08-07 10:52:38 +05306686 case ATH9K_CAP_TKIP_MIC:
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07006687 switch (capability) {
6688 case 0:
6689 return true;
6690 case 1:
6691 return (ahp->ah_staId1Defaults &
6692 AR_STA_ID1_CRPT_MIC_ENABLE) ? true :
6693 false;
6694 }
Sujith60b67f52008-08-07 10:52:38 +05306695 case ATH9K_CAP_TKIP_SPLIT:
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07006696 return (ahp->ah_miscMode & AR_PCU_MIC_NEW_LOC_ENA) ?
6697 false : true;
Sujith60b67f52008-08-07 10:52:38 +05306698 case ATH9K_CAP_WME_TKIPMIC:
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07006699 return 0;
Sujith60b67f52008-08-07 10:52:38 +05306700 case ATH9K_CAP_PHYCOUNTERS:
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07006701 return ahp->ah_hasHwPhyCounters ? 0 : -ENXIO;
Sujith60b67f52008-08-07 10:52:38 +05306702 case ATH9K_CAP_DIVERSITY:
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07006703 return (REG_READ(ah, AR_PHY_CCK_DETECT) &
6704 AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV) ?
6705 true : false;
Sujith60b67f52008-08-07 10:52:38 +05306706 case ATH9K_CAP_PHYDIAG:
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07006707 return true;
Sujith60b67f52008-08-07 10:52:38 +05306708 case ATH9K_CAP_MCAST_KEYSRCH:
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07006709 switch (capability) {
6710 case 0:
6711 return true;
6712 case 1:
6713 if (REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_ADHOC) {
6714 return false;
6715 } else {
6716 return (ahp->ah_staId1Defaults &
6717 AR_STA_ID1_MCAST_KSRCH) ? true :
6718 false;
6719 }
6720 }
6721 return false;
Sujith60b67f52008-08-07 10:52:38 +05306722 case ATH9K_CAP_TSF_ADJUST:
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07006723 return (ahp->ah_miscMode & AR_PCU_TX_ADD_TSF) ?
6724 true : false;
Sujith60b67f52008-08-07 10:52:38 +05306725 case ATH9K_CAP_RFSILENT:
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07006726 if (capability == 3)
6727 return false;
Sujith60b67f52008-08-07 10:52:38 +05306728 case ATH9K_CAP_ANT_CFG_2GHZ:
6729 *result = pCap->num_antcfg_2ghz;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07006730 return true;
Sujith60b67f52008-08-07 10:52:38 +05306731 case ATH9K_CAP_ANT_CFG_5GHZ:
6732 *result = pCap->num_antcfg_5ghz;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07006733 return true;
Sujith60b67f52008-08-07 10:52:38 +05306734 case ATH9K_CAP_TXPOW:
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07006735 switch (capability) {
6736 case 0:
6737 return 0;
6738 case 1:
6739 *result = ah->ah_powerLimit;
6740 return 0;
6741 case 2:
6742 *result = ah->ah_maxPowerLevel;
6743 return 0;
6744 case 3:
6745 *result = ah->ah_tpScale;
6746 return 0;
6747 }
6748 return false;
6749 default:
6750 return false;
6751 }
6752}
6753
6754int
6755ath9k_hw_select_antconfig(struct ath_hal *ah, u32 cfg)
6756{
6757 struct ath_hal_5416 *ahp = AH5416(ah);
6758 struct ath9k_channel *chan = ah->ah_curchan;
Sujith60b67f52008-08-07 10:52:38 +05306759 const struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07006760 u16 ant_config;
6761 u32 halNumAntConfig;
6762
6763 halNumAntConfig =
Sujith60b67f52008-08-07 10:52:38 +05306764 IS_CHAN_2GHZ(chan) ? pCap->num_antcfg_2ghz : pCap->
6765 num_antcfg_5ghz;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07006766
6767 if (cfg < halNumAntConfig) {
6768 if (!ath9k_hw_get_eeprom_antenna_cfg(ahp, chan,
6769 cfg, &ant_config)) {
6770 REG_WRITE(ah, AR_PHY_SWITCH_COM, ant_config);
6771 return 0;
6772 }
6773 }
6774
6775 return -EINVAL;
6776}
6777
6778bool ath9k_hw_intrpend(struct ath_hal *ah)
6779{
6780 u32 host_isr;
6781
6782 if (AR_SREV_9100(ah))
6783 return true;
6784
6785 host_isr = REG_READ(ah, AR_INTR_ASYNC_CAUSE);
6786 if ((host_isr & AR_INTR_MAC_IRQ) && (host_isr != AR_INTR_SPURIOUS))
6787 return true;
6788
6789 host_isr = REG_READ(ah, AR_INTR_SYNC_CAUSE);
6790 if ((host_isr & AR_INTR_SYNC_DEFAULT)
6791 && (host_isr != AR_INTR_SPURIOUS))
6792 return true;
6793
6794 return false;
6795}
6796
6797bool ath9k_hw_getisr(struct ath_hal *ah, enum ath9k_int *masked)
6798{
6799 u32 isr = 0;
6800 u32 mask2 = 0;
Sujith60b67f52008-08-07 10:52:38 +05306801 struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07006802 u32 sync_cause = 0;
6803 bool fatal_int = false;
6804
6805 if (!AR_SREV_9100(ah)) {
6806 if (REG_READ(ah, AR_INTR_ASYNC_CAUSE) & AR_INTR_MAC_IRQ) {
6807 if ((REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M)
6808 == AR_RTC_STATUS_ON) {
6809 isr = REG_READ(ah, AR_ISR);
6810 }
6811 }
6812
6813 sync_cause =
6814 REG_READ(ah,
6815 AR_INTR_SYNC_CAUSE) & AR_INTR_SYNC_DEFAULT;
6816
6817 *masked = 0;
6818
6819 if (!isr && !sync_cause)
6820 return false;
6821 } else {
6822 *masked = 0;
6823 isr = REG_READ(ah, AR_ISR);
6824 }
6825
6826 if (isr) {
6827 struct ath_hal_5416 *ahp = AH5416(ah);
6828
6829 if (isr & AR_ISR_BCNMISC) {
6830 u32 isr2;
6831 isr2 = REG_READ(ah, AR_ISR_S2);
6832 if (isr2 & AR_ISR_S2_TIM)
6833 mask2 |= ATH9K_INT_TIM;
6834 if (isr2 & AR_ISR_S2_DTIM)
6835 mask2 |= ATH9K_INT_DTIM;
6836 if (isr2 & AR_ISR_S2_DTIMSYNC)
6837 mask2 |= ATH9K_INT_DTIMSYNC;
6838 if (isr2 & (AR_ISR_S2_CABEND))
6839 mask2 |= ATH9K_INT_CABEND;
6840 if (isr2 & AR_ISR_S2_GTT)
6841 mask2 |= ATH9K_INT_GTT;
6842 if (isr2 & AR_ISR_S2_CST)
6843 mask2 |= ATH9K_INT_CST;
6844 }
6845
6846 isr = REG_READ(ah, AR_ISR_RAC);
6847 if (isr == 0xffffffff) {
6848 *masked = 0;
6849 return false;
6850 }
6851
6852 *masked = isr & ATH9K_INT_COMMON;
6853
6854 if (ahp->ah_intrMitigation) {
6855
6856 if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM))
6857 *masked |= ATH9K_INT_RX;
6858 }
6859
6860 if (isr & (AR_ISR_RXOK | AR_ISR_RXERR))
6861 *masked |= ATH9K_INT_RX;
6862 if (isr &
6863 (AR_ISR_TXOK | AR_ISR_TXDESC | AR_ISR_TXERR |
6864 AR_ISR_TXEOL)) {
6865 u32 s0_s, s1_s;
6866
6867 *masked |= ATH9K_INT_TX;
6868
6869 s0_s = REG_READ(ah, AR_ISR_S0_S);
6870 ahp->ah_intrTxqs |= MS(s0_s, AR_ISR_S0_QCU_TXOK);
6871 ahp->ah_intrTxqs |= MS(s0_s, AR_ISR_S0_QCU_TXDESC);
6872
6873 s1_s = REG_READ(ah, AR_ISR_S1_S);
6874 ahp->ah_intrTxqs |= MS(s1_s, AR_ISR_S1_QCU_TXERR);
6875 ahp->ah_intrTxqs |= MS(s1_s, AR_ISR_S1_QCU_TXEOL);
6876 }
6877
6878 if (isr & AR_ISR_RXORN) {
6879 DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT,
6880 "%s: receive FIFO overrun interrupt\n",
6881 __func__);
6882 }
6883
6884 if (!AR_SREV_9100(ah)) {
Sujith60b67f52008-08-07 10:52:38 +05306885 if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07006886 u32 isr5 = REG_READ(ah, AR_ISR_S5_S);
6887 if (isr5 & AR_ISR_S5_TIM_TIMER)
6888 *masked |= ATH9K_INT_TIM_TIMER;
6889 }
6890 }
6891
6892 *masked |= mask2;
6893 }
6894 if (AR_SREV_9100(ah))
6895 return true;
6896 if (sync_cause) {
6897 fatal_int =
6898 (sync_cause &
6899 (AR_INTR_SYNC_HOST1_FATAL | AR_INTR_SYNC_HOST1_PERR))
6900 ? true : false;
6901
6902 if (fatal_int) {
6903 if (sync_cause & AR_INTR_SYNC_HOST1_FATAL) {
6904 DPRINTF(ah->ah_sc, ATH_DBG_ANY,
6905 "%s: received PCI FATAL interrupt\n",
6906 __func__);
6907 }
6908 if (sync_cause & AR_INTR_SYNC_HOST1_PERR) {
6909 DPRINTF(ah->ah_sc, ATH_DBG_ANY,
6910 "%s: received PCI PERR interrupt\n",
6911 __func__);
6912 }
6913 }
6914 if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) {
6915 DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT,
6916 "%s: AR_INTR_SYNC_RADM_CPL_TIMEOUT\n",
6917 __func__);
6918 REG_WRITE(ah, AR_RC, AR_RC_HOSTIF);
6919 REG_WRITE(ah, AR_RC, 0);
6920 *masked |= ATH9K_INT_FATAL;
6921 }
6922 if (sync_cause & AR_INTR_SYNC_LOCAL_TIMEOUT) {
6923 DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT,
6924 "%s: AR_INTR_SYNC_LOCAL_TIMEOUT\n",
6925 __func__);
6926 }
6927
6928 REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause);
6929 (void) REG_READ(ah, AR_INTR_SYNC_CAUSE_CLR);
6930 }
6931 return true;
6932}
6933
6934enum ath9k_int ath9k_hw_intrget(struct ath_hal *ah)
6935{
6936 return AH5416(ah)->ah_maskReg;
6937}
6938
6939enum ath9k_int ath9k_hw_set_interrupts(struct ath_hal *ah, enum ath9k_int ints)
6940{
6941 struct ath_hal_5416 *ahp = AH5416(ah);
6942 u32 omask = ahp->ah_maskReg;
6943 u32 mask, mask2;
Sujith60b67f52008-08-07 10:52:38 +05306944 struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07006945
6946 DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "%s: 0x%x => 0x%x\n", __func__,
6947 omask, ints);
6948
6949 if (omask & ATH9K_INT_GLOBAL) {
6950 DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "%s: disable IER\n",
6951 __func__);
6952 REG_WRITE(ah, AR_IER, AR_IER_DISABLE);
6953 (void) REG_READ(ah, AR_IER);
6954 if (!AR_SREV_9100(ah)) {
6955 REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, 0);
6956 (void) REG_READ(ah, AR_INTR_ASYNC_ENABLE);
6957
6958 REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0);
6959 (void) REG_READ(ah, AR_INTR_SYNC_ENABLE);
6960 }
6961 }
6962
6963 mask = ints & ATH9K_INT_COMMON;
6964 mask2 = 0;
6965
6966 if (ints & ATH9K_INT_TX) {
6967 if (ahp->ah_txOkInterruptMask)
6968 mask |= AR_IMR_TXOK;
6969 if (ahp->ah_txDescInterruptMask)
6970 mask |= AR_IMR_TXDESC;
6971 if (ahp->ah_txErrInterruptMask)
6972 mask |= AR_IMR_TXERR;
6973 if (ahp->ah_txEolInterruptMask)
6974 mask |= AR_IMR_TXEOL;
6975 }
6976 if (ints & ATH9K_INT_RX) {
6977 mask |= AR_IMR_RXERR;
6978 if (ahp->ah_intrMitigation)
6979 mask |= AR_IMR_RXMINTR | AR_IMR_RXINTM;
6980 else
6981 mask |= AR_IMR_RXOK | AR_IMR_RXDESC;
Sujith60b67f52008-08-07 10:52:38 +05306982 if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07006983 mask |= AR_IMR_GENTMR;
6984 }
6985
6986 if (ints & (ATH9K_INT_BMISC)) {
6987 mask |= AR_IMR_BCNMISC;
6988 if (ints & ATH9K_INT_TIM)
6989 mask2 |= AR_IMR_S2_TIM;
6990 if (ints & ATH9K_INT_DTIM)
6991 mask2 |= AR_IMR_S2_DTIM;
6992 if (ints & ATH9K_INT_DTIMSYNC)
6993 mask2 |= AR_IMR_S2_DTIMSYNC;
6994 if (ints & ATH9K_INT_CABEND)
6995 mask2 |= (AR_IMR_S2_CABEND);
6996 }
6997
6998 if (ints & (ATH9K_INT_GTT | ATH9K_INT_CST)) {
6999 mask |= AR_IMR_BCNMISC;
7000 if (ints & ATH9K_INT_GTT)
7001 mask2 |= AR_IMR_S2_GTT;
7002 if (ints & ATH9K_INT_CST)
7003 mask2 |= AR_IMR_S2_CST;
7004 }
7005
7006 DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "%s: new IMR 0x%x\n", __func__,
7007 mask);
7008 REG_WRITE(ah, AR_IMR, mask);
7009 mask = REG_READ(ah, AR_IMR_S2) & ~(AR_IMR_S2_TIM |
7010 AR_IMR_S2_DTIM |
7011 AR_IMR_S2_DTIMSYNC |
7012 AR_IMR_S2_CABEND |
7013 AR_IMR_S2_CABTO |
7014 AR_IMR_S2_TSFOOR |
7015 AR_IMR_S2_GTT | AR_IMR_S2_CST);
7016 REG_WRITE(ah, AR_IMR_S2, mask | mask2);
7017 ahp->ah_maskReg = ints;
7018
Sujith60b67f52008-08-07 10:52:38 +05307019 if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07007020 if (ints & ATH9K_INT_TIM_TIMER)
7021 REG_SET_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER);
7022 else
7023 REG_CLR_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER);
7024 }
7025
7026 if (ints & ATH9K_INT_GLOBAL) {
7027 DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "%s: enable IER\n",
7028 __func__);
7029 REG_WRITE(ah, AR_IER, AR_IER_ENABLE);
7030 if (!AR_SREV_9100(ah)) {
7031 REG_WRITE(ah, AR_INTR_ASYNC_ENABLE,
7032 AR_INTR_MAC_IRQ);
7033 REG_WRITE(ah, AR_INTR_ASYNC_MASK, AR_INTR_MAC_IRQ);
7034
7035
7036 REG_WRITE(ah, AR_INTR_SYNC_ENABLE,
7037 AR_INTR_SYNC_DEFAULT);
7038 REG_WRITE(ah, AR_INTR_SYNC_MASK,
7039 AR_INTR_SYNC_DEFAULT);
7040 }
7041 DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "AR_IMR 0x%x IER 0x%x\n",
7042 REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER));
7043 }
7044
7045 return omask;
7046}
7047
7048void
7049ath9k_hw_beaconinit(struct ath_hal *ah,
7050 u32 next_beacon, u32 beacon_period)
7051{
7052 struct ath_hal_5416 *ahp = AH5416(ah);
7053 int flags = 0;
7054
7055 ahp->ah_beaconInterval = beacon_period;
7056
7057 switch (ah->ah_opmode) {
7058 case ATH9K_M_STA:
7059 case ATH9K_M_MONITOR:
7060 REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(next_beacon));
7061 REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT, 0xffff);
7062 REG_WRITE(ah, AR_NEXT_SWBA, 0x7ffff);
7063 flags |= AR_TBTT_TIMER_EN;
7064 break;
7065 case ATH9K_M_IBSS:
7066 REG_SET_BIT(ah, AR_TXCFG,
7067 AR_TXCFG_ADHOC_BEACON_ATIM_TX_POLICY);
7068 REG_WRITE(ah, AR_NEXT_NDP_TIMER,
7069 TU_TO_USEC(next_beacon +
7070 (ahp->ah_atimWindow ? ahp->
7071 ah_atimWindow : 1)));
7072 flags |= AR_NDP_TIMER_EN;
7073 case ATH9K_M_HOSTAP:
7074 REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(next_beacon));
7075 REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT,
7076 TU_TO_USEC(next_beacon -
7077 ah->ah_config.
Sujith60b67f52008-08-07 10:52:38 +05307078 dma_beacon_response_time));
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07007079 REG_WRITE(ah, AR_NEXT_SWBA,
7080 TU_TO_USEC(next_beacon -
7081 ah->ah_config.
Sujith60b67f52008-08-07 10:52:38 +05307082 sw_beacon_response_time));
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07007083 flags |=
7084 AR_TBTT_TIMER_EN | AR_DBA_TIMER_EN | AR_SWBA_TIMER_EN;
7085 break;
7086 }
7087
7088 REG_WRITE(ah, AR_BEACON_PERIOD, TU_TO_USEC(beacon_period));
7089 REG_WRITE(ah, AR_DMA_BEACON_PERIOD, TU_TO_USEC(beacon_period));
7090 REG_WRITE(ah, AR_SWBA_PERIOD, TU_TO_USEC(beacon_period));
7091 REG_WRITE(ah, AR_NDP_PERIOD, TU_TO_USEC(beacon_period));
7092
7093 beacon_period &= ~ATH9K_BEACON_ENA;
7094 if (beacon_period & ATH9K_BEACON_RESET_TSF) {
7095 beacon_period &= ~ATH9K_BEACON_RESET_TSF;
7096 ath9k_hw_reset_tsf(ah);
7097 }
7098
7099 REG_SET_BIT(ah, AR_TIMER_MODE, flags);
7100}
7101
7102void
7103ath9k_hw_set_sta_beacon_timers(struct ath_hal *ah,
7104 const struct ath9k_beacon_state *bs)
7105{
7106 u32 nextTbtt, beaconintval, dtimperiod, beacontimeout;
Sujith60b67f52008-08-07 10:52:38 +05307107 struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07007108
7109 REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(bs->bs_nexttbtt));
7110
7111 REG_WRITE(ah, AR_BEACON_PERIOD,
7112 TU_TO_USEC(bs->bs_intval & ATH9K_BEACON_PERIOD));
7113 REG_WRITE(ah, AR_DMA_BEACON_PERIOD,
7114 TU_TO_USEC(bs->bs_intval & ATH9K_BEACON_PERIOD));
7115
7116 REG_RMW_FIELD(ah, AR_RSSI_THR,
7117 AR_RSSI_THR_BM_THR, bs->bs_bmissthreshold);
7118
7119 beaconintval = bs->bs_intval & ATH9K_BEACON_PERIOD;
7120
7121 if (bs->bs_sleepduration > beaconintval)
7122 beaconintval = bs->bs_sleepduration;
7123
7124 dtimperiod = bs->bs_dtimperiod;
7125 if (bs->bs_sleepduration > dtimperiod)
7126 dtimperiod = bs->bs_sleepduration;
7127
7128 if (beaconintval == dtimperiod)
7129 nextTbtt = bs->bs_nextdtim;
7130 else
7131 nextTbtt = bs->bs_nexttbtt;
7132
7133 DPRINTF(ah->ah_sc, ATH_DBG_BEACON, "%s: next DTIM %d\n", __func__,
7134 bs->bs_nextdtim);
7135 DPRINTF(ah->ah_sc, ATH_DBG_BEACON, "%s: next beacon %d\n", __func__,
7136 nextTbtt);
7137 DPRINTF(ah->ah_sc, ATH_DBG_BEACON, "%s: beacon period %d\n", __func__,
7138 beaconintval);
7139 DPRINTF(ah->ah_sc, ATH_DBG_BEACON, "%s: DTIM period %d\n", __func__,
7140 dtimperiod);
7141
7142 REG_WRITE(ah, AR_NEXT_DTIM,
7143 TU_TO_USEC(bs->bs_nextdtim - SLEEP_SLOP));
7144 REG_WRITE(ah, AR_NEXT_TIM, TU_TO_USEC(nextTbtt - SLEEP_SLOP));
7145
7146 REG_WRITE(ah, AR_SLEEP1,
7147 SM((CAB_TIMEOUT_VAL << 3), AR_SLEEP1_CAB_TIMEOUT)
7148 | AR_SLEEP1_ASSUME_DTIM);
7149
Sujith60b67f52008-08-07 10:52:38 +05307150 if (pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07007151 beacontimeout = (BEACON_TIMEOUT_VAL << 3);
7152 else
7153 beacontimeout = MIN_BEACON_TIMEOUT_VAL;
7154
7155 REG_WRITE(ah, AR_SLEEP2,
7156 SM(beacontimeout, AR_SLEEP2_BEACON_TIMEOUT));
7157
7158 REG_WRITE(ah, AR_TIM_PERIOD, TU_TO_USEC(beaconintval));
7159 REG_WRITE(ah, AR_DTIM_PERIOD, TU_TO_USEC(dtimperiod));
7160
7161 REG_SET_BIT(ah, AR_TIMER_MODE,
7162 AR_TBTT_TIMER_EN | AR_TIM_TIMER_EN |
7163 AR_DTIM_TIMER_EN);
7164
7165}
7166
7167bool ath9k_hw_keyisvalid(struct ath_hal *ah, u16 entry)
7168{
Sujith60b67f52008-08-07 10:52:38 +05307169 if (entry < ah->ah_caps.keycache_size) {
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07007170 u32 val = REG_READ(ah, AR_KEYTABLE_MAC1(entry));
7171 if (val & AR_KEYTABLE_VALID)
7172 return true;
7173 }
7174 return false;
7175}
7176
7177bool ath9k_hw_keyreset(struct ath_hal *ah, u16 entry)
7178{
7179 u32 keyType;
7180
Sujith60b67f52008-08-07 10:52:38 +05307181 if (entry >= ah->ah_caps.keycache_size) {
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07007182 DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE,
7183 "%s: entry %u out of range\n", __func__, entry);
7184 return false;
7185 }
7186 keyType = REG_READ(ah, AR_KEYTABLE_TYPE(entry));
7187
7188 REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), 0);
7189 REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), 0);
7190 REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), 0);
7191 REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), 0);
7192 REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), 0);
7193 REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), AR_KEYTABLE_TYPE_CLR);
7194 REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), 0);
7195 REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), 0);
7196
7197 if (keyType == AR_KEYTABLE_TYPE_TKIP && ATH9K_IS_MIC_ENABLED(ah)) {
7198 u16 micentry = entry + 64;
7199
7200 REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), 0);
7201 REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0);
7202 REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), 0);
7203 REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0);
7204
7205 }
7206
7207 if (ah->ah_curchan == NULL)
7208 return true;
7209
7210 return true;
7211}
7212
7213bool
7214ath9k_hw_keysetmac(struct ath_hal *ah, u16 entry,
7215 const u8 *mac)
7216{
7217 u32 macHi, macLo;
7218
Sujith60b67f52008-08-07 10:52:38 +05307219 if (entry >= ah->ah_caps.keycache_size) {
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07007220 DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE,
7221 "%s: entry %u out of range\n", __func__, entry);
7222 return false;
7223 }
7224
7225 if (mac != NULL) {
7226 macHi = (mac[5] << 8) | mac[4];
7227 macLo = (mac[3] << 24) | (mac[2] << 16)
7228 | (mac[1] << 8) | mac[0];
7229 macLo >>= 1;
7230 macLo |= (macHi & 1) << 31;
7231 macHi >>= 1;
7232 } else {
7233 macLo = macHi = 0;
7234 }
7235 REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), macLo);
7236 REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), macHi | AR_KEYTABLE_VALID);
7237
7238 return true;
7239}
7240
7241bool
7242ath9k_hw_set_keycache_entry(struct ath_hal *ah, u16 entry,
7243 const struct ath9k_keyval *k,
7244 const u8 *mac, int xorKey)
7245{
Sujith60b67f52008-08-07 10:52:38 +05307246 const struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07007247 u32 key0, key1, key2, key3, key4;
7248 u32 keyType;
7249 u32 xorMask = xorKey ?
7250 (ATH9K_KEY_XOR << 24 | ATH9K_KEY_XOR << 16 | ATH9K_KEY_XOR << 8
7251 | ATH9K_KEY_XOR) : 0;
7252 struct ath_hal_5416 *ahp = AH5416(ah);
7253
Sujith60b67f52008-08-07 10:52:38 +05307254 if (entry >= pCap->keycache_size) {
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07007255 DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE,
7256 "%s: entry %u out of range\n", __func__, entry);
7257 return false;
7258 }
7259 switch (k->kv_type) {
7260 case ATH9K_CIPHER_AES_OCB:
7261 keyType = AR_KEYTABLE_TYPE_AES;
7262 break;
7263 case ATH9K_CIPHER_AES_CCM:
Sujith60b67f52008-08-07 10:52:38 +05307264 if (!(pCap->hw_caps & ATH9K_HW_CAP_CIPHER_AESCCM)) {
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07007265 DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE,
7266 "%s: AES-CCM not supported by "
7267 "mac rev 0x%x\n", __func__,
7268 ah->ah_macRev);
7269 return false;
7270 }
7271 keyType = AR_KEYTABLE_TYPE_CCM;
7272 break;
7273 case ATH9K_CIPHER_TKIP:
7274 keyType = AR_KEYTABLE_TYPE_TKIP;
7275 if (ATH9K_IS_MIC_ENABLED(ah)
Sujith60b67f52008-08-07 10:52:38 +05307276 && entry + 64 >= pCap->keycache_size) {
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07007277 DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE,
7278 "%s: entry %u inappropriate for TKIP\n",
7279 __func__, entry);
7280 return false;
7281 }
7282 break;
7283 case ATH9K_CIPHER_WEP:
7284 if (k->kv_len < 40 / NBBY) {
7285 DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE,
7286 "%s: WEP key length %u too small\n",
7287 __func__, k->kv_len);
7288 return false;
7289 }
7290 if (k->kv_len <= 40 / NBBY)
7291 keyType = AR_KEYTABLE_TYPE_40;
7292 else if (k->kv_len <= 104 / NBBY)
7293 keyType = AR_KEYTABLE_TYPE_104;
7294 else
7295 keyType = AR_KEYTABLE_TYPE_128;
7296 break;
7297 case ATH9K_CIPHER_CLR:
7298 keyType = AR_KEYTABLE_TYPE_CLR;
7299 break;
7300 default:
7301 DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE,
7302 "%s: cipher %u not supported\n", __func__,
7303 k->kv_type);
7304 return false;
7305 }
7306
7307 key0 = get_unaligned_le32(k->kv_val + 0) ^ xorMask;
7308 key1 = (get_unaligned_le16(k->kv_val + 4) ^ xorMask) & 0xffff;
7309 key2 = get_unaligned_le32(k->kv_val + 6) ^ xorMask;
7310 key3 = (get_unaligned_le16(k->kv_val + 10) ^ xorMask) & 0xffff;
7311 key4 = get_unaligned_le32(k->kv_val + 12) ^ xorMask;
7312 if (k->kv_len <= 104 / NBBY)
7313 key4 &= 0xff;
7314
7315 if (keyType == AR_KEYTABLE_TYPE_TKIP && ATH9K_IS_MIC_ENABLED(ah)) {
7316 u16 micentry = entry + 64;
7317
7318 REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), ~key0);
7319 REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), ~key1);
7320 REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2);
7321 REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3);
7322 REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4);
7323 REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType);
7324 (void) ath9k_hw_keysetmac(ah, entry, mac);
7325
7326 if (ahp->ah_miscMode & AR_PCU_MIC_NEW_LOC_ENA) {
7327 u32 mic0, mic1, mic2, mic3, mic4;
7328
7329 mic0 = get_unaligned_le32(k->kv_mic + 0);
7330 mic2 = get_unaligned_le32(k->kv_mic + 4);
7331 mic1 = get_unaligned_le16(k->kv_txmic + 2) & 0xffff;
7332 mic3 = get_unaligned_le16(k->kv_txmic + 0) & 0xffff;
7333 mic4 = get_unaligned_le32(k->kv_txmic + 4);
7334 REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0);
7335 REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), mic1);
7336 REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2);
7337 REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), mic3);
7338 REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), mic4);
7339 REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry),
7340 AR_KEYTABLE_TYPE_CLR);
7341
7342 } else {
7343 u32 mic0, mic2;
7344
7345 mic0 = get_unaligned_le32(k->kv_mic + 0);
7346 mic2 = get_unaligned_le32(k->kv_mic + 4);
7347 REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0);
7348 REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0);
7349 REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2);
7350 REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0);
7351 REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), 0);
7352 REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry),
7353 AR_KEYTABLE_TYPE_CLR);
7354 }
7355 REG_WRITE(ah, AR_KEYTABLE_MAC0(micentry), 0);
7356 REG_WRITE(ah, AR_KEYTABLE_MAC1(micentry), 0);
7357 REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0);
7358 REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1);
7359 } else {
7360 REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0);
7361 REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1);
7362 REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2);
7363 REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3);
7364 REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4);
7365 REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType);
7366
7367 (void) ath9k_hw_keysetmac(ah, entry, mac);
7368 }
7369
7370 if (ah->ah_curchan == NULL)
7371 return true;
7372
7373 return true;
7374}
7375
7376bool
7377ath9k_hw_updatetxtriglevel(struct ath_hal *ah, bool bIncTrigLevel)
7378{
7379 struct ath_hal_5416 *ahp = AH5416(ah);
7380 u32 txcfg, curLevel, newLevel;
7381 enum ath9k_int omask;
7382
7383 if (ah->ah_txTrigLevel >= MAX_TX_FIFO_THRESHOLD)
7384 return false;
7385
7386 omask = ath9k_hw_set_interrupts(ah,
7387 ahp->ah_maskReg & ~ATH9K_INT_GLOBAL);
7388
7389 txcfg = REG_READ(ah, AR_TXCFG);
7390 curLevel = MS(txcfg, AR_FTRIG);
7391 newLevel = curLevel;
7392 if (bIncTrigLevel) {
7393 if (curLevel < MAX_TX_FIFO_THRESHOLD)
7394 newLevel++;
7395 } else if (curLevel > MIN_TX_FIFO_THRESHOLD)
7396 newLevel--;
7397 if (newLevel != curLevel)
7398 REG_WRITE(ah, AR_TXCFG,
7399 (txcfg & ~AR_FTRIG) | SM(newLevel, AR_FTRIG));
7400
7401 ath9k_hw_set_interrupts(ah, omask);
7402
7403 ah->ah_txTrigLevel = newLevel;
7404
7405 return newLevel != curLevel;
7406}
7407
Sujithea9880f2008-08-07 10:53:10 +05307408bool ath9k_hw_set_txq_props(struct ath_hal *ah, int q,
7409 const struct ath9k_tx_queue_info *qinfo)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07007410{
7411 u32 cw;
Sujithea9880f2008-08-07 10:53:10 +05307412 struct ath_hal_5416 *ahp = AH5416(ah);
7413 struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
7414 struct ath9k_tx_queue_info *qi;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07007415
Sujithea9880f2008-08-07 10:53:10 +05307416 if (q >= pCap->total_queues) {
7417 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: invalid queue num %u\n",
7418 __func__, q);
7419 return false;
7420 }
7421
7422 qi = &ahp->ah_txq[q];
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07007423 if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
7424 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: inactive queue\n",
7425 __func__);
7426 return false;
7427 }
7428
7429 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: queue %p\n", __func__, qi);
7430
Sujithea9880f2008-08-07 10:53:10 +05307431 qi->tqi_ver = qinfo->tqi_ver;
7432 qi->tqi_subtype = qinfo->tqi_subtype;
7433 qi->tqi_qflags = qinfo->tqi_qflags;
7434 qi->tqi_priority = qinfo->tqi_priority;
7435 if (qinfo->tqi_aifs != ATH9K_TXQ_USEDEFAULT)
7436 qi->tqi_aifs = min(qinfo->tqi_aifs, 255U);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07007437 else
7438 qi->tqi_aifs = INIT_AIFS;
Sujithea9880f2008-08-07 10:53:10 +05307439 if (qinfo->tqi_cwmin != ATH9K_TXQ_USEDEFAULT) {
7440 cw = min(qinfo->tqi_cwmin, 1024U);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07007441 qi->tqi_cwmin = 1;
7442 while (qi->tqi_cwmin < cw)
7443 qi->tqi_cwmin = (qi->tqi_cwmin << 1) | 1;
7444 } else
Sujithea9880f2008-08-07 10:53:10 +05307445 qi->tqi_cwmin = qinfo->tqi_cwmin;
7446 if (qinfo->tqi_cwmax != ATH9K_TXQ_USEDEFAULT) {
7447 cw = min(qinfo->tqi_cwmax, 1024U);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07007448 qi->tqi_cwmax = 1;
7449 while (qi->tqi_cwmax < cw)
7450 qi->tqi_cwmax = (qi->tqi_cwmax << 1) | 1;
7451 } else
7452 qi->tqi_cwmax = INIT_CWMAX;
7453
Sujithea9880f2008-08-07 10:53:10 +05307454 if (qinfo->tqi_shretry != 0)
7455 qi->tqi_shretry = min((u32) qinfo->tqi_shretry, 15U);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07007456 else
7457 qi->tqi_shretry = INIT_SH_RETRY;
Sujithea9880f2008-08-07 10:53:10 +05307458 if (qinfo->tqi_lgretry != 0)
7459 qi->tqi_lgretry = min((u32) qinfo->tqi_lgretry, 15U);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07007460 else
7461 qi->tqi_lgretry = INIT_LG_RETRY;
Sujithea9880f2008-08-07 10:53:10 +05307462 qi->tqi_cbrPeriod = qinfo->tqi_cbrPeriod;
7463 qi->tqi_cbrOverflowLimit = qinfo->tqi_cbrOverflowLimit;
7464 qi->tqi_burstTime = qinfo->tqi_burstTime;
7465 qi->tqi_readyTime = qinfo->tqi_readyTime;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07007466
Sujithea9880f2008-08-07 10:53:10 +05307467 switch (qinfo->tqi_subtype) {
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07007468 case ATH9K_WME_UPSD:
7469 if (qi->tqi_type == ATH9K_TX_QUEUE_DATA)
7470 qi->tqi_intFlags = ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS;
7471 break;
7472 default:
7473 break;
7474 }
7475 return true;
7476}
7477
Sujithea9880f2008-08-07 10:53:10 +05307478bool ath9k_hw_get_txq_props(struct ath_hal *ah, int q,
7479 struct ath9k_tx_queue_info *qinfo)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07007480{
7481 struct ath_hal_5416 *ahp = AH5416(ah);
Sujith60b67f52008-08-07 10:52:38 +05307482 struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
Sujithea9880f2008-08-07 10:53:10 +05307483 struct ath9k_tx_queue_info *qi;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07007484
Sujith60b67f52008-08-07 10:52:38 +05307485 if (q >= pCap->total_queues) {
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07007486 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: invalid queue num %u\n",
7487 __func__, q);
7488 return false;
7489 }
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07007490
Sujithea9880f2008-08-07 10:53:10 +05307491 qi = &ahp->ah_txq[q];
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07007492 if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
7493 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: inactive queue\n",
7494 __func__);
7495 return false;
7496 }
7497
Sujithea9880f2008-08-07 10:53:10 +05307498 qinfo->tqi_qflags = qi->tqi_qflags;
7499 qinfo->tqi_ver = qi->tqi_ver;
7500 qinfo->tqi_subtype = qi->tqi_subtype;
7501 qinfo->tqi_qflags = qi->tqi_qflags;
7502 qinfo->tqi_priority = qi->tqi_priority;
7503 qinfo->tqi_aifs = qi->tqi_aifs;
7504 qinfo->tqi_cwmin = qi->tqi_cwmin;
7505 qinfo->tqi_cwmax = qi->tqi_cwmax;
7506 qinfo->tqi_shretry = qi->tqi_shretry;
7507 qinfo->tqi_lgretry = qi->tqi_lgretry;
7508 qinfo->tqi_cbrPeriod = qi->tqi_cbrPeriod;
7509 qinfo->tqi_cbrOverflowLimit = qi->tqi_cbrOverflowLimit;
7510 qinfo->tqi_burstTime = qi->tqi_burstTime;
7511 qinfo->tqi_readyTime = qi->tqi_readyTime;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07007512
7513 return true;
7514}
7515
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07007516int
7517ath9k_hw_setuptxqueue(struct ath_hal *ah, enum ath9k_tx_queue type,
Sujithea9880f2008-08-07 10:53:10 +05307518 const struct ath9k_tx_queue_info *qinfo)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07007519{
7520 struct ath_hal_5416 *ahp = AH5416(ah);
7521 struct ath9k_tx_queue_info *qi;
Sujith60b67f52008-08-07 10:52:38 +05307522 struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07007523 int q;
7524
7525 switch (type) {
7526 case ATH9K_TX_QUEUE_BEACON:
Sujith60b67f52008-08-07 10:52:38 +05307527 q = pCap->total_queues - 1;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07007528 break;
7529 case ATH9K_TX_QUEUE_CAB:
Sujith60b67f52008-08-07 10:52:38 +05307530 q = pCap->total_queues - 2;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07007531 break;
7532 case ATH9K_TX_QUEUE_PSPOLL:
7533 q = 1;
7534 break;
7535 case ATH9K_TX_QUEUE_UAPSD:
Sujith60b67f52008-08-07 10:52:38 +05307536 q = pCap->total_queues - 3;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07007537 break;
7538 case ATH9K_TX_QUEUE_DATA:
Sujith60b67f52008-08-07 10:52:38 +05307539 for (q = 0; q < pCap->total_queues; q++)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07007540 if (ahp->ah_txq[q].tqi_type ==
7541 ATH9K_TX_QUEUE_INACTIVE)
7542 break;
Sujith60b67f52008-08-07 10:52:38 +05307543 if (q == pCap->total_queues) {
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07007544 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
7545 "%s: no available tx queue\n", __func__);
7546 return -1;
7547 }
7548 break;
7549 default:
7550 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: bad tx queue type %u\n",
7551 __func__, type);
7552 return -1;
7553 }
7554
7555 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: queue %u\n", __func__, q);
7556
7557 qi = &ahp->ah_txq[q];
7558 if (qi->tqi_type != ATH9K_TX_QUEUE_INACTIVE) {
7559 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
7560 "%s: tx queue %u already active\n", __func__, q);
7561 return -1;
7562 }
7563 memset(qi, 0, sizeof(struct ath9k_tx_queue_info));
7564 qi->tqi_type = type;
Sujithea9880f2008-08-07 10:53:10 +05307565 if (qinfo == NULL) {
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07007566 qi->tqi_qflags =
7567 TXQ_FLAG_TXOKINT_ENABLE
7568 | TXQ_FLAG_TXERRINT_ENABLE
7569 | TXQ_FLAG_TXDESCINT_ENABLE | TXQ_FLAG_TXURNINT_ENABLE;
7570 qi->tqi_aifs = INIT_AIFS;
7571 qi->tqi_cwmin = ATH9K_TXQ_USEDEFAULT;
7572 qi->tqi_cwmax = INIT_CWMAX;
7573 qi->tqi_shretry = INIT_SH_RETRY;
7574 qi->tqi_lgretry = INIT_LG_RETRY;
7575 qi->tqi_physCompBuf = 0;
7576 } else {
Sujithea9880f2008-08-07 10:53:10 +05307577 qi->tqi_physCompBuf = qinfo->tqi_physCompBuf;
7578 (void) ath9k_hw_set_txq_props(ah, q, qinfo);
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07007579 }
7580
7581 return q;
7582}
7583
7584static void
7585ath9k_hw_set_txq_interrupts(struct ath_hal *ah,
7586 struct ath9k_tx_queue_info *qi)
7587{
7588 struct ath_hal_5416 *ahp = AH5416(ah);
7589
7590 DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT,
7591 "%s: tx ok 0x%x err 0x%x desc 0x%x eol 0x%x urn 0x%x\n",
7592 __func__, ahp->ah_txOkInterruptMask,
7593 ahp->ah_txErrInterruptMask, ahp->ah_txDescInterruptMask,
7594 ahp->ah_txEolInterruptMask, ahp->ah_txUrnInterruptMask);
7595
7596 REG_WRITE(ah, AR_IMR_S0,
7597 SM(ahp->ah_txOkInterruptMask, AR_IMR_S0_QCU_TXOK)
7598 | SM(ahp->ah_txDescInterruptMask, AR_IMR_S0_QCU_TXDESC));
7599 REG_WRITE(ah, AR_IMR_S1,
7600 SM(ahp->ah_txErrInterruptMask, AR_IMR_S1_QCU_TXERR)
7601 | SM(ahp->ah_txEolInterruptMask, AR_IMR_S1_QCU_TXEOL));
7602 REG_RMW_FIELD(ah, AR_IMR_S2,
7603 AR_IMR_S2_QCU_TXURN, ahp->ah_txUrnInterruptMask);
7604}
7605
7606bool ath9k_hw_releasetxqueue(struct ath_hal *ah, u32 q)
7607{
7608 struct ath_hal_5416 *ahp = AH5416(ah);
Sujith60b67f52008-08-07 10:52:38 +05307609 struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07007610 struct ath9k_tx_queue_info *qi;
7611
Sujith60b67f52008-08-07 10:52:38 +05307612 if (q >= pCap->total_queues) {
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07007613 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: invalid queue num %u\n",
7614 __func__, q);
7615 return false;
7616 }
7617 qi = &ahp->ah_txq[q];
7618 if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
7619 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: inactive queue %u\n",
7620 __func__, q);
7621 return false;
7622 }
7623
7624 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: release queue %u\n",
7625 __func__, q);
7626
7627 qi->tqi_type = ATH9K_TX_QUEUE_INACTIVE;
7628 ahp->ah_txOkInterruptMask &= ~(1 << q);
7629 ahp->ah_txErrInterruptMask &= ~(1 << q);
7630 ahp->ah_txDescInterruptMask &= ~(1 << q);
7631 ahp->ah_txEolInterruptMask &= ~(1 << q);
7632 ahp->ah_txUrnInterruptMask &= ~(1 << q);
7633 ath9k_hw_set_txq_interrupts(ah, qi);
7634
7635 return true;
7636}
7637
7638bool ath9k_hw_resettxqueue(struct ath_hal *ah, u32 q)
7639{
7640 struct ath_hal_5416 *ahp = AH5416(ah);
Sujith60b67f52008-08-07 10:52:38 +05307641 struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07007642 struct ath9k_channel *chan = ah->ah_curchan;
7643 struct ath9k_tx_queue_info *qi;
7644 u32 cwMin, chanCwMin, value;
7645
Sujith60b67f52008-08-07 10:52:38 +05307646 if (q >= pCap->total_queues) {
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07007647 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: invalid queue num %u\n",
7648 __func__, q);
7649 return false;
7650 }
7651 qi = &ahp->ah_txq[q];
7652 if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
7653 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: inactive queue %u\n",
7654 __func__, q);
7655 return true;
7656 }
7657
7658 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: reset queue %u\n", __func__, q);
7659
7660 if (qi->tqi_cwmin == ATH9K_TXQ_USEDEFAULT) {
7661 if (chan && IS_CHAN_B(chan))
7662 chanCwMin = INIT_CWMIN_11B;
7663 else
7664 chanCwMin = INIT_CWMIN;
7665
7666 for (cwMin = 1; cwMin < chanCwMin; cwMin = (cwMin << 1) | 1);
7667 } else
7668 cwMin = qi->tqi_cwmin;
7669
7670 REG_WRITE(ah, AR_DLCL_IFS(q), SM(cwMin, AR_D_LCL_IFS_CWMIN)
7671 | SM(qi->tqi_cwmax, AR_D_LCL_IFS_CWMAX)
7672 | SM(qi->tqi_aifs, AR_D_LCL_IFS_AIFS));
7673
7674 REG_WRITE(ah, AR_DRETRY_LIMIT(q),
7675 SM(INIT_SSH_RETRY, AR_D_RETRY_LIMIT_STA_SH)
7676 | SM(INIT_SLG_RETRY, AR_D_RETRY_LIMIT_STA_LG)
7677 | SM(qi->tqi_shretry, AR_D_RETRY_LIMIT_FR_SH)
7678 );
7679
7680 REG_WRITE(ah, AR_QMISC(q), AR_Q_MISC_DCU_EARLY_TERM_REQ);
7681 REG_WRITE(ah, AR_DMISC(q),
7682 AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN | 0x2);
7683
7684 if (qi->tqi_cbrPeriod) {
7685 REG_WRITE(ah, AR_QCBRCFG(q),
7686 SM(qi->tqi_cbrPeriod, AR_Q_CBRCFG_INTERVAL)
7687 | SM(qi->tqi_cbrOverflowLimit,
7688 AR_Q_CBRCFG_OVF_THRESH));
7689 REG_WRITE(ah, AR_QMISC(q),
7690 REG_READ(ah,
7691 AR_QMISC(q)) | AR_Q_MISC_FSP_CBR | (qi->
7692 tqi_cbrOverflowLimit
7693 ?
7694 AR_Q_MISC_CBR_EXP_CNTR_LIMIT_EN
7695 :
7696 0));
7697 }
7698 if (qi->tqi_readyTime && (qi->tqi_type != ATH9K_TX_QUEUE_CAB)) {
7699 REG_WRITE(ah, AR_QRDYTIMECFG(q),
7700 SM(qi->tqi_readyTime, AR_Q_RDYTIMECFG_DURATION) |
7701 AR_Q_RDYTIMECFG_EN);
7702 }
7703
7704 REG_WRITE(ah, AR_DCHNTIME(q),
7705 SM(qi->tqi_burstTime, AR_D_CHNTIME_DUR) |
7706 (qi->tqi_burstTime ? AR_D_CHNTIME_EN : 0));
7707
7708 if (qi->tqi_burstTime
7709 && (qi->tqi_qflags & TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE)) {
7710 REG_WRITE(ah, AR_QMISC(q),
7711 REG_READ(ah,
7712 AR_QMISC(q)) |
7713 AR_Q_MISC_RDYTIME_EXP_POLICY);
7714
7715 }
7716
7717 if (qi->tqi_qflags & TXQ_FLAG_BACKOFF_DISABLE) {
7718 REG_WRITE(ah, AR_DMISC(q),
7719 REG_READ(ah, AR_DMISC(q)) |
7720 AR_D_MISC_POST_FR_BKOFF_DIS);
7721 }
7722 if (qi->tqi_qflags & TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE) {
7723 REG_WRITE(ah, AR_DMISC(q),
7724 REG_READ(ah, AR_DMISC(q)) |
7725 AR_D_MISC_FRAG_BKOFF_EN);
7726 }
7727 switch (qi->tqi_type) {
7728 case ATH9K_TX_QUEUE_BEACON:
7729 REG_WRITE(ah, AR_QMISC(q), REG_READ(ah, AR_QMISC(q))
7730 | AR_Q_MISC_FSP_DBA_GATED
7731 | AR_Q_MISC_BEACON_USE
7732 | AR_Q_MISC_CBR_INCR_DIS1);
7733
7734 REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q))
7735 | (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL <<
7736 AR_D_MISC_ARB_LOCKOUT_CNTRL_S)
7737 | AR_D_MISC_BEACON_USE
7738 | AR_D_MISC_POST_FR_BKOFF_DIS);
7739 break;
7740 case ATH9K_TX_QUEUE_CAB:
7741 REG_WRITE(ah, AR_QMISC(q), REG_READ(ah, AR_QMISC(q))
7742 | AR_Q_MISC_FSP_DBA_GATED
7743 | AR_Q_MISC_CBR_INCR_DIS1
7744 | AR_Q_MISC_CBR_INCR_DIS0);
7745 value = (qi->tqi_readyTime
Sujith60b67f52008-08-07 10:52:38 +05307746 - (ah->ah_config.sw_beacon_response_time -
7747 ah->ah_config.dma_beacon_response_time)
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07007748 -
Sujith60b67f52008-08-07 10:52:38 +05307749 ah->ah_config.additional_swba_backoff) *
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07007750 1024;
7751 REG_WRITE(ah, AR_QRDYTIMECFG(q),
7752 value | AR_Q_RDYTIMECFG_EN);
7753 REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q))
7754 | (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL <<
7755 AR_D_MISC_ARB_LOCKOUT_CNTRL_S));
7756 break;
7757 case ATH9K_TX_QUEUE_PSPOLL:
7758 REG_WRITE(ah, AR_QMISC(q),
7759 REG_READ(ah,
7760 AR_QMISC(q)) | AR_Q_MISC_CBR_INCR_DIS1);
7761 break;
7762 case ATH9K_TX_QUEUE_UAPSD:
7763 REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q))
7764 | AR_D_MISC_POST_FR_BKOFF_DIS);
7765 break;
7766 default:
7767 break;
7768 }
7769
7770 if (qi->tqi_intFlags & ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS) {
7771 REG_WRITE(ah, AR_DMISC(q),
7772 REG_READ(ah, AR_DMISC(q)) |
7773 SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL,
7774 AR_D_MISC_ARB_LOCKOUT_CNTRL) |
7775 AR_D_MISC_POST_FR_BKOFF_DIS);
7776 }
7777
7778 if (qi->tqi_qflags & TXQ_FLAG_TXOKINT_ENABLE)
7779 ahp->ah_txOkInterruptMask |= 1 << q;
7780 else
7781 ahp->ah_txOkInterruptMask &= ~(1 << q);
7782 if (qi->tqi_qflags & TXQ_FLAG_TXERRINT_ENABLE)
7783 ahp->ah_txErrInterruptMask |= 1 << q;
7784 else
7785 ahp->ah_txErrInterruptMask &= ~(1 << q);
7786 if (qi->tqi_qflags & TXQ_FLAG_TXDESCINT_ENABLE)
7787 ahp->ah_txDescInterruptMask |= 1 << q;
7788 else
7789 ahp->ah_txDescInterruptMask &= ~(1 << q);
7790 if (qi->tqi_qflags & TXQ_FLAG_TXEOLINT_ENABLE)
7791 ahp->ah_txEolInterruptMask |= 1 << q;
7792 else
7793 ahp->ah_txEolInterruptMask &= ~(1 << q);
7794 if (qi->tqi_qflags & TXQ_FLAG_TXURNINT_ENABLE)
7795 ahp->ah_txUrnInterruptMask |= 1 << q;
7796 else
7797 ahp->ah_txUrnInterruptMask &= ~(1 << q);
7798 ath9k_hw_set_txq_interrupts(ah, qi);
7799
7800 return true;
7801}
7802
7803void ath9k_hw_gettxintrtxqs(struct ath_hal *ah, u32 *txqs)
7804{
7805 struct ath_hal_5416 *ahp = AH5416(ah);
7806 *txqs &= ahp->ah_intrTxqs;
7807 ahp->ah_intrTxqs &= ~(*txqs);
7808}
7809
7810bool
7811ath9k_hw_filltxdesc(struct ath_hal *ah, struct ath_desc *ds,
7812 u32 segLen, bool firstSeg,
7813 bool lastSeg, const struct ath_desc *ds0)
7814{
7815 struct ar5416_desc *ads = AR5416DESC(ds);
7816
7817 if (firstSeg) {
7818 ads->ds_ctl1 |= segLen | (lastSeg ? 0 : AR_TxMore);
7819 } else if (lastSeg) {
7820 ads->ds_ctl0 = 0;
7821 ads->ds_ctl1 = segLen;
7822 ads->ds_ctl2 = AR5416DESC_CONST(ds0)->ds_ctl2;
7823 ads->ds_ctl3 = AR5416DESC_CONST(ds0)->ds_ctl3;
7824 } else {
7825 ads->ds_ctl0 = 0;
7826 ads->ds_ctl1 = segLen | AR_TxMore;
7827 ads->ds_ctl2 = 0;
7828 ads->ds_ctl3 = 0;
7829 }
7830 ads->ds_txstatus0 = ads->ds_txstatus1 = 0;
7831 ads->ds_txstatus2 = ads->ds_txstatus3 = 0;
7832 ads->ds_txstatus4 = ads->ds_txstatus5 = 0;
7833 ads->ds_txstatus6 = ads->ds_txstatus7 = 0;
7834 ads->ds_txstatus8 = ads->ds_txstatus9 = 0;
7835 return true;
7836}
7837
7838void ath9k_hw_cleartxdesc(struct ath_hal *ah, struct ath_desc *ds)
7839{
7840 struct ar5416_desc *ads = AR5416DESC(ds);
7841
7842 ads->ds_txstatus0 = ads->ds_txstatus1 = 0;
7843 ads->ds_txstatus2 = ads->ds_txstatus3 = 0;
7844 ads->ds_txstatus4 = ads->ds_txstatus5 = 0;
7845 ads->ds_txstatus6 = ads->ds_txstatus7 = 0;
7846 ads->ds_txstatus8 = ads->ds_txstatus9 = 0;
7847}
7848
7849int
7850ath9k_hw_txprocdesc(struct ath_hal *ah, struct ath_desc *ds)
7851{
7852 struct ar5416_desc *ads = AR5416DESC(ds);
7853
7854 if ((ads->ds_txstatus9 & AR_TxDone) == 0)
7855 return -EINPROGRESS;
7856
7857 ds->ds_txstat.ts_seqnum = MS(ads->ds_txstatus9, AR_SeqNum);
7858 ds->ds_txstat.ts_tstamp = ads->AR_SendTimestamp;
7859 ds->ds_txstat.ts_status = 0;
7860 ds->ds_txstat.ts_flags = 0;
7861
7862 if (ads->ds_txstatus1 & AR_ExcessiveRetries)
7863 ds->ds_txstat.ts_status |= ATH9K_TXERR_XRETRY;
7864 if (ads->ds_txstatus1 & AR_Filtered)
7865 ds->ds_txstat.ts_status |= ATH9K_TXERR_FILT;
7866 if (ads->ds_txstatus1 & AR_FIFOUnderrun)
7867 ds->ds_txstat.ts_status |= ATH9K_TXERR_FIFO;
7868 if (ads->ds_txstatus9 & AR_TxOpExceeded)
7869 ds->ds_txstat.ts_status |= ATH9K_TXERR_XTXOP;
7870 if (ads->ds_txstatus1 & AR_TxTimerExpired)
7871 ds->ds_txstat.ts_status |= ATH9K_TXERR_TIMER_EXPIRED;
7872
7873 if (ads->ds_txstatus1 & AR_DescCfgErr)
7874 ds->ds_txstat.ts_flags |= ATH9K_TX_DESC_CFG_ERR;
7875 if (ads->ds_txstatus1 & AR_TxDataUnderrun) {
7876 ds->ds_txstat.ts_flags |= ATH9K_TX_DATA_UNDERRUN;
7877 ath9k_hw_updatetxtriglevel(ah, true);
7878 }
7879 if (ads->ds_txstatus1 & AR_TxDelimUnderrun) {
7880 ds->ds_txstat.ts_flags |= ATH9K_TX_DELIM_UNDERRUN;
7881 ath9k_hw_updatetxtriglevel(ah, true);
7882 }
7883 if (ads->ds_txstatus0 & AR_TxBaStatus) {
7884 ds->ds_txstat.ts_flags |= ATH9K_TX_BA;
7885 ds->ds_txstat.ba_low = ads->AR_BaBitmapLow;
7886 ds->ds_txstat.ba_high = ads->AR_BaBitmapHigh;
7887 }
7888
7889 ds->ds_txstat.ts_rateindex = MS(ads->ds_txstatus9, AR_FinalTxIdx);
7890 switch (ds->ds_txstat.ts_rateindex) {
7891 case 0:
7892 ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate0);
7893 break;
7894 case 1:
7895 ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate1);
7896 break;
7897 case 2:
7898 ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate2);
7899 break;
7900 case 3:
7901 ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate3);
7902 break;
7903 }
7904
7905 ds->ds_txstat.ts_rssi = MS(ads->ds_txstatus5, AR_TxRSSICombined);
7906 ds->ds_txstat.ts_rssi_ctl0 = MS(ads->ds_txstatus0, AR_TxRSSIAnt00);
7907 ds->ds_txstat.ts_rssi_ctl1 = MS(ads->ds_txstatus0, AR_TxRSSIAnt01);
7908 ds->ds_txstat.ts_rssi_ctl2 = MS(ads->ds_txstatus0, AR_TxRSSIAnt02);
7909 ds->ds_txstat.ts_rssi_ext0 = MS(ads->ds_txstatus5, AR_TxRSSIAnt10);
7910 ds->ds_txstat.ts_rssi_ext1 = MS(ads->ds_txstatus5, AR_TxRSSIAnt11);
7911 ds->ds_txstat.ts_rssi_ext2 = MS(ads->ds_txstatus5, AR_TxRSSIAnt12);
7912 ds->ds_txstat.evm0 = ads->AR_TxEVM0;
7913 ds->ds_txstat.evm1 = ads->AR_TxEVM1;
7914 ds->ds_txstat.evm2 = ads->AR_TxEVM2;
7915 ds->ds_txstat.ts_shortretry = MS(ads->ds_txstatus1, AR_RTSFailCnt);
7916 ds->ds_txstat.ts_longretry = MS(ads->ds_txstatus1, AR_DataFailCnt);
7917 ds->ds_txstat.ts_virtcol = MS(ads->ds_txstatus1, AR_VirtRetryCnt);
7918 ds->ds_txstat.ts_antenna = 1;
7919
7920 return 0;
7921}
7922
7923void
7924ath9k_hw_set11n_txdesc(struct ath_hal *ah, struct ath_desc *ds,
7925 u32 pktLen, enum ath9k_pkt_type type, u32 txPower,
7926 u32 keyIx, enum ath9k_key_type keyType, u32 flags)
7927{
7928 struct ar5416_desc *ads = AR5416DESC(ds);
7929 struct ath_hal_5416 *ahp = AH5416(ah);
7930
7931 txPower += ahp->ah_txPowerIndexOffset;
7932 if (txPower > 63)
7933 txPower = 63;
7934
7935 ads->ds_ctl0 = (pktLen & AR_FrameLen)
7936 | (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
7937 | SM(txPower, AR_XmitPower)
7938 | (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
7939 | (flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0)
7940 | (flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0)
7941 | (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0);
7942
7943 ads->ds_ctl1 =
7944 (keyIx != ATH9K_TXKEYIX_INVALID ? SM(keyIx, AR_DestIdx) : 0)
7945 | SM(type, AR_FrameType)
7946 | (flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0)
7947 | (flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0)
7948 | (flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0);
7949
7950 ads->ds_ctl6 = SM(keyType, AR_EncrType);
7951
7952 if (AR_SREV_9285(ah)) {
7953
7954 ads->ds_ctl8 = 0;
7955 ads->ds_ctl9 = 0;
7956 ads->ds_ctl10 = 0;
7957 ads->ds_ctl11 = 0;
7958 }
7959}
7960
7961void
7962ath9k_hw_set11n_ratescenario(struct ath_hal *ah, struct ath_desc *ds,
7963 struct ath_desc *lastds,
7964 u32 durUpdateEn, u32 rtsctsRate,
7965 u32 rtsctsDuration,
7966 struct ath9k_11n_rate_series series[],
7967 u32 nseries, u32 flags)
7968{
7969 struct ar5416_desc *ads = AR5416DESC(ds);
7970 struct ar5416_desc *last_ads = AR5416DESC(lastds);
7971 u32 ds_ctl0;
7972
7973 (void) nseries;
7974 (void) rtsctsDuration;
7975
7976 if (flags & (ATH9K_TXDESC_RTSENA | ATH9K_TXDESC_CTSENA)) {
7977 ds_ctl0 = ads->ds_ctl0;
7978
7979 if (flags & ATH9K_TXDESC_RTSENA) {
7980 ds_ctl0 &= ~AR_CTSEnable;
7981 ds_ctl0 |= AR_RTSEnable;
7982 } else {
7983 ds_ctl0 &= ~AR_RTSEnable;
7984 ds_ctl0 |= AR_CTSEnable;
7985 }
7986
7987 ads->ds_ctl0 = ds_ctl0;
7988 } else {
7989 ads->ds_ctl0 =
7990 (ads->ds_ctl0 & ~(AR_RTSEnable | AR_CTSEnable));
7991 }
7992
7993 ads->ds_ctl2 = set11nTries(series, 0)
7994 | set11nTries(series, 1)
7995 | set11nTries(series, 2)
7996 | set11nTries(series, 3)
7997 | (durUpdateEn ? AR_DurUpdateEna : 0)
7998 | SM(0, AR_BurstDur);
7999
8000 ads->ds_ctl3 = set11nRate(series, 0)
8001 | set11nRate(series, 1)
8002 | set11nRate(series, 2)
8003 | set11nRate(series, 3);
8004
8005 ads->ds_ctl4 = set11nPktDurRTSCTS(series, 0)
8006 | set11nPktDurRTSCTS(series, 1);
8007
8008 ads->ds_ctl5 = set11nPktDurRTSCTS(series, 2)
8009 | set11nPktDurRTSCTS(series, 3);
8010
8011 ads->ds_ctl7 = set11nRateFlags(series, 0)
8012 | set11nRateFlags(series, 1)
8013 | set11nRateFlags(series, 2)
8014 | set11nRateFlags(series, 3)
8015 | SM(rtsctsRate, AR_RTSCTSRate);
8016 last_ads->ds_ctl2 = ads->ds_ctl2;
8017 last_ads->ds_ctl3 = ads->ds_ctl3;
8018}
8019
8020void
8021ath9k_hw_set11n_aggr_first(struct ath_hal *ah, struct ath_desc *ds,
8022 u32 aggrLen)
8023{
8024 struct ar5416_desc *ads = AR5416DESC(ds);
8025
8026 ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr);
8027
8028 ads->ds_ctl6 &= ~AR_AggrLen;
8029 ads->ds_ctl6 |= SM(aggrLen, AR_AggrLen);
8030}
8031
8032void
8033ath9k_hw_set11n_aggr_middle(struct ath_hal *ah, struct ath_desc *ds,
8034 u32 numDelims)
8035{
8036 struct ar5416_desc *ads = AR5416DESC(ds);
8037 unsigned int ctl6;
8038
8039 ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr);
8040
8041 ctl6 = ads->ds_ctl6;
8042 ctl6 &= ~AR_PadDelim;
8043 ctl6 |= SM(numDelims, AR_PadDelim);
8044 ads->ds_ctl6 = ctl6;
8045}
8046
8047void ath9k_hw_set11n_aggr_last(struct ath_hal *ah, struct ath_desc *ds)
8048{
8049 struct ar5416_desc *ads = AR5416DESC(ds);
8050
8051 ads->ds_ctl1 |= AR_IsAggr;
8052 ads->ds_ctl1 &= ~AR_MoreAggr;
8053 ads->ds_ctl6 &= ~AR_PadDelim;
8054}
8055
8056void ath9k_hw_clr11n_aggr(struct ath_hal *ah, struct ath_desc *ds)
8057{
8058 struct ar5416_desc *ads = AR5416DESC(ds);
8059
8060 ads->ds_ctl1 &= (~AR_IsAggr & ~AR_MoreAggr);
8061}
8062
8063void
8064ath9k_hw_set11n_burstduration(struct ath_hal *ah, struct ath_desc *ds,
8065 u32 burstDuration)
8066{
8067 struct ar5416_desc *ads = AR5416DESC(ds);
8068
8069 ads->ds_ctl2 &= ~AR_BurstDur;
8070 ads->ds_ctl2 |= SM(burstDuration, AR_BurstDur);
8071}
8072
8073void
8074ath9k_hw_set11n_virtualmorefrag(struct ath_hal *ah, struct ath_desc *ds,
8075 u32 vmf)
8076{
8077 struct ar5416_desc *ads = AR5416DESC(ds);
8078
8079 if (vmf)
8080 ads->ds_ctl0 |= AR_VirtMoreFrag;
8081 else
8082 ads->ds_ctl0 &= ~AR_VirtMoreFrag;
8083}
8084
8085void ath9k_hw_putrxbuf(struct ath_hal *ah, u32 rxdp)
8086{
8087 REG_WRITE(ah, AR_RXDP, rxdp);
8088}
8089
8090void ath9k_hw_rxena(struct ath_hal *ah)
8091{
8092 REG_WRITE(ah, AR_CR, AR_CR_RXE);
8093}
8094
8095bool ath9k_hw_setrxabort(struct ath_hal *ah, bool set)
8096{
8097 if (set) {
8098
8099 REG_SET_BIT(ah, AR_DIAG_SW,
8100 (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
8101
8102 if (!ath9k_hw_wait
8103 (ah, AR_OBS_BUS_1, AR_OBS_BUS_1_RX_STATE, 0)) {
8104 u32 reg;
8105
8106 REG_CLR_BIT(ah, AR_DIAG_SW,
8107 (AR_DIAG_RX_DIS |
8108 AR_DIAG_RX_ABORT));
8109
8110 reg = REG_READ(ah, AR_OBS_BUS_1);
8111 DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
8112 "%s: rx failed to go idle in 10 ms RXSM=0x%x\n",
8113 __func__, reg);
8114
8115 return false;
8116 }
8117 } else {
8118 REG_CLR_BIT(ah, AR_DIAG_SW,
8119 (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
8120 }
8121
8122 return true;
8123}
8124
8125void
8126ath9k_hw_setmcastfilter(struct ath_hal *ah, u32 filter0,
8127 u32 filter1)
8128{
8129 REG_WRITE(ah, AR_MCAST_FIL0, filter0);
8130 REG_WRITE(ah, AR_MCAST_FIL1, filter1);
8131}
8132
8133bool
8134ath9k_hw_setuprxdesc(struct ath_hal *ah, struct ath_desc *ds,
8135 u32 size, u32 flags)
8136{
8137 struct ar5416_desc *ads = AR5416DESC(ds);
Sujith60b67f52008-08-07 10:52:38 +05308138 struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07008139
8140 ads->ds_ctl1 = size & AR_BufLen;
8141 if (flags & ATH9K_RXDESC_INTREQ)
8142 ads->ds_ctl1 |= AR_RxIntrReq;
8143
8144 ads->ds_rxstatus8 &= ~AR_RxDone;
Sujith60b67f52008-08-07 10:52:38 +05308145 if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07008146 memset(&(ads->u), 0, sizeof(ads->u));
8147 return true;
8148}
8149
8150int
8151ath9k_hw_rxprocdesc(struct ath_hal *ah, struct ath_desc *ds,
8152 u32 pa, struct ath_desc *nds, u64 tsf)
8153{
8154 struct ar5416_desc ads;
8155 struct ar5416_desc *adsp = AR5416DESC(ds);
8156
8157 if ((adsp->ds_rxstatus8 & AR_RxDone) == 0)
8158 return -EINPROGRESS;
8159
8160 ads.u.rx = adsp->u.rx;
8161
8162 ds->ds_rxstat.rs_status = 0;
8163 ds->ds_rxstat.rs_flags = 0;
8164
8165 ds->ds_rxstat.rs_datalen = ads.ds_rxstatus1 & AR_DataLen;
8166 ds->ds_rxstat.rs_tstamp = ads.AR_RcvTimestamp;
8167
8168 ds->ds_rxstat.rs_rssi = MS(ads.ds_rxstatus4, AR_RxRSSICombined);
8169 ds->ds_rxstat.rs_rssi_ctl0 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt00);
8170 ds->ds_rxstat.rs_rssi_ctl1 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt01);
8171 ds->ds_rxstat.rs_rssi_ctl2 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt02);
8172 ds->ds_rxstat.rs_rssi_ext0 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt10);
8173 ds->ds_rxstat.rs_rssi_ext1 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt11);
8174 ds->ds_rxstat.rs_rssi_ext2 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt12);
8175 if (ads.ds_rxstatus8 & AR_RxKeyIdxValid)
8176 ds->ds_rxstat.rs_keyix = MS(ads.ds_rxstatus8, AR_KeyIdx);
8177 else
8178 ds->ds_rxstat.rs_keyix = ATH9K_RXKEYIX_INVALID;
8179
8180 ds->ds_rxstat.rs_rate = RXSTATUS_RATE(ah, (&ads));
8181 ds->ds_rxstat.rs_more = (ads.ds_rxstatus1 & AR_RxMore) ? 1 : 0;
8182
8183 ds->ds_rxstat.rs_isaggr = (ads.ds_rxstatus8 & AR_RxAggr) ? 1 : 0;
8184 ds->ds_rxstat.rs_moreaggr =
8185 (ads.ds_rxstatus8 & AR_RxMoreAggr) ? 1 : 0;
8186 ds->ds_rxstat.rs_antenna = MS(ads.ds_rxstatus3, AR_RxAntenna);
8187 ds->ds_rxstat.rs_flags =
8188 (ads.ds_rxstatus3 & AR_GI) ? ATH9K_RX_GI : 0;
8189 ds->ds_rxstat.rs_flags |=
8190 (ads.ds_rxstatus3 & AR_2040) ? ATH9K_RX_2040 : 0;
8191
8192 if (ads.ds_rxstatus8 & AR_PreDelimCRCErr)
8193 ds->ds_rxstat.rs_flags |= ATH9K_RX_DELIM_CRC_PRE;
8194 if (ads.ds_rxstatus8 & AR_PostDelimCRCErr)
8195 ds->ds_rxstat.rs_flags |= ATH9K_RX_DELIM_CRC_POST;
8196 if (ads.ds_rxstatus8 & AR_DecryptBusyErr)
8197 ds->ds_rxstat.rs_flags |= ATH9K_RX_DECRYPT_BUSY;
8198
8199 if ((ads.ds_rxstatus8 & AR_RxFrameOK) == 0) {
8200
8201 if (ads.ds_rxstatus8 & AR_CRCErr)
8202 ds->ds_rxstat.rs_status |= ATH9K_RXERR_CRC;
8203 else if (ads.ds_rxstatus8 & AR_PHYErr) {
8204 u32 phyerr;
8205
8206 ds->ds_rxstat.rs_status |= ATH9K_RXERR_PHY;
8207 phyerr = MS(ads.ds_rxstatus8, AR_PHYErrCode);
8208 ds->ds_rxstat.rs_phyerr = phyerr;
8209 } else if (ads.ds_rxstatus8 & AR_DecryptCRCErr)
8210 ds->ds_rxstat.rs_status |= ATH9K_RXERR_DECRYPT;
8211 else if (ads.ds_rxstatus8 & AR_MichaelErr)
8212 ds->ds_rxstat.rs_status |= ATH9K_RXERR_MIC;
8213 }
8214
8215 return 0;
8216}
8217
8218static void ath9k_hw_setup_rate_table(struct ath_hal *ah,
8219 struct ath9k_rate_table *rt)
8220{
8221 int i;
8222
8223 if (rt->rateCodeToIndex[0] != 0)
8224 return;
8225 for (i = 0; i < 256; i++)
8226 rt->rateCodeToIndex[i] = (u8) -1;
8227 for (i = 0; i < rt->rateCount; i++) {
8228 u8 code = rt->info[i].rateCode;
8229 u8 cix = rt->info[i].controlRate;
8230
8231 rt->rateCodeToIndex[code] = i;
8232 rt->rateCodeToIndex[code | rt->info[i].shortPreamble] = i;
8233
8234 rt->info[i].lpAckDuration =
8235 ath9k_hw_computetxtime(ah, rt,
8236 WLAN_CTRL_FRAME_SIZE,
8237 cix,
8238 false);
8239 rt->info[i].spAckDuration =
8240 ath9k_hw_computetxtime(ah, rt,
8241 WLAN_CTRL_FRAME_SIZE,
8242 cix,
8243 true);
8244 }
8245}
8246
8247const struct ath9k_rate_table *ath9k_hw_getratetable(struct ath_hal *ah,
8248 u32 mode)
8249{
8250 struct ath9k_rate_table *rt;
8251 switch (mode) {
Sujith86b89ee2008-08-07 10:54:57 +05308252 case ATH9K_MODE_11A:
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07008253 rt = &ar5416_11a_table;
8254 break;
Sujith86b89ee2008-08-07 10:54:57 +05308255 case ATH9K_MODE_11B:
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07008256 rt = &ar5416_11b_table;
8257 break;
Sujith86b89ee2008-08-07 10:54:57 +05308258 case ATH9K_MODE_11G:
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07008259 rt = &ar5416_11g_table;
8260 break;
Sujith86b89ee2008-08-07 10:54:57 +05308261 case ATH9K_MODE_11NG_HT20:
8262 case ATH9K_MODE_11NG_HT40PLUS:
8263 case ATH9K_MODE_11NG_HT40MINUS:
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07008264 rt = &ar5416_11ng_table;
8265 break;
Sujith86b89ee2008-08-07 10:54:57 +05308266 case ATH9K_MODE_11NA_HT20:
8267 case ATH9K_MODE_11NA_HT40PLUS:
8268 case ATH9K_MODE_11NA_HT40MINUS:
Luis R. Rodriguezf078f202008-08-04 00:16:41 -07008269 rt = &ar5416_11na_table;
8270 break;
8271 default:
8272 DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, "%s: invalid mode 0x%x\n",
8273 __func__, mode);
8274 return NULL;
8275 }
8276 ath9k_hw_setup_rate_table(ah, rt);
8277 return rt;
8278}
8279
8280static const char *ath9k_hw_devname(u16 devid)
8281{
8282 switch (devid) {
8283 case AR5416_DEVID_PCI:
8284 case AR5416_DEVID_PCIE:
8285 return "Atheros 5416";
8286 case AR9160_DEVID_PCI:
8287 return "Atheros 9160";
8288 case AR9280_DEVID_PCI:
8289 case AR9280_DEVID_PCIE:
8290 return "Atheros 9280";
8291 }
8292 return NULL;
8293}
8294
8295const char *ath9k_hw_probe(u16 vendorid, u16 devid)
8296{
8297 return vendorid == ATHEROS_VENDOR_ID ?
8298 ath9k_hw_devname(devid) : NULL;
8299}
8300
8301struct ath_hal *ath9k_hw_attach(u16 devid,
8302 struct ath_softc *sc,
8303 void __iomem *mem,
8304 int *error)
8305{
8306 struct ath_hal *ah = NULL;
8307
8308 switch (devid) {
8309 case AR5416_DEVID_PCI:
8310 case AR5416_DEVID_PCIE:
8311 case AR9160_DEVID_PCI:
8312 case AR9280_DEVID_PCI:
8313 case AR9280_DEVID_PCIE:
8314 ah = ath9k_hw_do_attach(devid, sc, mem, error);
8315 break;
8316 default:
8317 DPRINTF(ah->ah_sc, ATH_DBG_ANY,
8318 "devid=0x%x not supported.\n", devid);
8319 ah = NULL;
8320 *error = -ENXIO;
8321 break;
8322 }
8323 if (ah != NULL) {
8324 ah->ah_devid = ah->ah_devid;
8325 ah->ah_subvendorid = ah->ah_subvendorid;
8326 ah->ah_macVersion = ah->ah_macVersion;
8327 ah->ah_macRev = ah->ah_macRev;
8328 ah->ah_phyRev = ah->ah_phyRev;
8329 ah->ah_analog5GhzRev = ah->ah_analog5GhzRev;
8330 ah->ah_analog2GhzRev = ah->ah_analog2GhzRev;
8331 }
8332 return ah;
8333}
8334
8335u16
8336ath9k_hw_computetxtime(struct ath_hal *ah,
8337 const struct ath9k_rate_table *rates,
8338 u32 frameLen, u16 rateix,
8339 bool shortPreamble)
8340{
8341 u32 bitsPerSymbol, numBits, numSymbols, phyTime, txTime;
8342 u32 kbps;
8343
8344 kbps = rates->info[rateix].rateKbps;
8345
8346 if (kbps == 0)
8347 return 0;
8348 switch (rates->info[rateix].phy) {
8349
8350 case PHY_CCK:
8351 phyTime = CCK_PREAMBLE_BITS + CCK_PLCP_BITS;
8352 if (shortPreamble && rates->info[rateix].shortPreamble)
8353 phyTime >>= 1;
8354 numBits = frameLen << 3;
8355 txTime = CCK_SIFS_TIME + phyTime
8356 + ((numBits * 1000) / kbps);
8357 break;
8358 case PHY_OFDM:
8359 if (ah->ah_curchan && IS_CHAN_QUARTER_RATE(ah->ah_curchan)) {
8360 bitsPerSymbol =
8361 (kbps * OFDM_SYMBOL_TIME_QUARTER) / 1000;
8362
8363 numBits = OFDM_PLCP_BITS + (frameLen << 3);
8364 numSymbols = DIV_ROUND_UP(numBits, bitsPerSymbol);
8365 txTime = OFDM_SIFS_TIME_QUARTER
8366 + OFDM_PREAMBLE_TIME_QUARTER
8367 + (numSymbols * OFDM_SYMBOL_TIME_QUARTER);
8368 } else if (ah->ah_curchan &&
8369 IS_CHAN_HALF_RATE(ah->ah_curchan)) {
8370 bitsPerSymbol =
8371 (kbps * OFDM_SYMBOL_TIME_HALF) / 1000;
8372
8373 numBits = OFDM_PLCP_BITS + (frameLen << 3);
8374 numSymbols = DIV_ROUND_UP(numBits, bitsPerSymbol);
8375 txTime = OFDM_SIFS_TIME_HALF +
8376 OFDM_PREAMBLE_TIME_HALF
8377 + (numSymbols * OFDM_SYMBOL_TIME_HALF);
8378 } else {
8379 bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME) / 1000;
8380
8381 numBits = OFDM_PLCP_BITS + (frameLen << 3);
8382 numSymbols = DIV_ROUND_UP(numBits, bitsPerSymbol);
8383 txTime = OFDM_SIFS_TIME + OFDM_PREAMBLE_TIME
8384 + (numSymbols * OFDM_SYMBOL_TIME);
8385 }
8386 break;
8387
8388 default:
8389 DPRINTF(ah->ah_sc, ATH_DBG_PHY_IO,
8390 "%s: unknown phy %u (rate ix %u)\n", __func__,
8391 rates->info[rateix].phy, rateix);
8392 txTime = 0;
8393 break;
8394 }
8395 return txTime;
8396}
8397
8398u32 ath9k_hw_mhz2ieee(struct ath_hal *ah, u32 freq, u32 flags)
8399{
8400 if (flags & CHANNEL_2GHZ) {
8401 if (freq == 2484)
8402 return 14;
8403 if (freq < 2484)
8404 return (freq - 2407) / 5;
8405 else
8406 return 15 + ((freq - 2512) / 20);
8407 } else if (flags & CHANNEL_5GHZ) {
8408 if (ath9k_regd_is_public_safety_sku(ah) &&
8409 IS_CHAN_IN_PUBLIC_SAFETY_BAND(freq)) {
8410 return ((freq * 10) +
8411 (((freq % 5) == 2) ? 5 : 0) - 49400) / 5;
8412 } else if ((flags & CHANNEL_A) && (freq <= 5000)) {
8413 return (freq - 4000) / 5;
8414 } else {
8415 return (freq - 5000) / 5;
8416 }
8417 } else {
8418 if (freq == 2484)
8419 return 14;
8420 if (freq < 2484)
8421 return (freq - 2407) / 5;
8422 if (freq < 5000) {
8423 if (ath9k_regd_is_public_safety_sku(ah)
8424 && IS_CHAN_IN_PUBLIC_SAFETY_BAND(freq)) {
8425 return ((freq * 10) +
8426 (((freq % 5) ==
8427 2) ? 5 : 0) - 49400) / 5;
8428 } else if (freq > 4900) {
8429 return (freq - 4000) / 5;
8430 } else {
8431 return 15 + ((freq - 2512) / 20);
8432 }
8433 }
8434 return (freq - 5000) / 5;
8435 }
8436}
8437
8438int16_t
8439ath9k_hw_getchan_noise(struct ath_hal *ah, struct ath9k_channel *chan)
8440{
8441 struct ath9k_channel *ichan;
8442
8443 ichan = ath9k_regd_check_channel(ah, chan);
8444 if (ichan == NULL) {
8445 DPRINTF(ah->ah_sc, ATH_DBG_NF_CAL,
8446 "%s: invalid channel %u/0x%x; no mapping\n",
8447 __func__, chan->channel, chan->channelFlags);
8448 return 0;
8449 }
8450 if (ichan->rawNoiseFloor == 0) {
8451 enum wireless_mode mode = ath9k_hw_chan2wmode(ah, chan);
8452 return NOISE_FLOOR[mode];
8453 } else
8454 return ichan->rawNoiseFloor;
8455}
8456
8457bool ath9k_hw_set_tsfadjust(struct ath_hal *ah, u32 setting)
8458{
8459 struct ath_hal_5416 *ahp = AH5416(ah);
8460
8461 if (setting)
8462 ahp->ah_miscMode |= AR_PCU_TX_ADD_TSF;
8463 else
8464 ahp->ah_miscMode &= ~AR_PCU_TX_ADD_TSF;
8465 return true;
8466}
8467
8468bool ath9k_hw_phycounters(struct ath_hal *ah)
8469{
8470 struct ath_hal_5416 *ahp = AH5416(ah);
8471
8472 return ahp->ah_hasHwPhyCounters ? true : false;
8473}
8474
8475u32 ath9k_hw_gettxbuf(struct ath_hal *ah, u32 q)
8476{
8477 return REG_READ(ah, AR_QTXDP(q));
8478}
8479
8480bool ath9k_hw_puttxbuf(struct ath_hal *ah, u32 q,
8481 u32 txdp)
8482{
8483 REG_WRITE(ah, AR_QTXDP(q), txdp);
8484
8485 return true;
8486}
8487
8488bool ath9k_hw_txstart(struct ath_hal *ah, u32 q)
8489{
8490 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: queue %u\n", __func__, q);
8491
8492 REG_WRITE(ah, AR_Q_TXE, 1 << q);
8493
8494 return true;
8495}
8496
8497u32 ath9k_hw_numtxpending(struct ath_hal *ah, u32 q)
8498{
8499 u32 npend;
8500
8501 npend = REG_READ(ah, AR_QSTS(q)) & AR_Q_STS_PEND_FR_CNT;
8502 if (npend == 0) {
8503
8504 if (REG_READ(ah, AR_Q_TXE) & (1 << q))
8505 npend = 1;
8506 }
8507 return npend;
8508}
8509
8510bool ath9k_hw_stoptxdma(struct ath_hal *ah, u32 q)
8511{
8512 u32 wait;
8513
8514 REG_WRITE(ah, AR_Q_TXD, 1 << q);
8515
8516 for (wait = 1000; wait != 0; wait--) {
8517 if (ath9k_hw_numtxpending(ah, q) == 0)
8518 break;
8519 udelay(100);
8520 }
8521
8522 if (ath9k_hw_numtxpending(ah, q)) {
8523 u32 tsfLow, j;
8524
8525 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
8526 "%s: Num of pending TX Frames %d on Q %d\n",
8527 __func__, ath9k_hw_numtxpending(ah, q), q);
8528
8529 for (j = 0; j < 2; j++) {
8530 tsfLow = REG_READ(ah, AR_TSF_L32);
8531 REG_WRITE(ah, AR_QUIET2,
8532 SM(10, AR_QUIET2_QUIET_DUR));
8533 REG_WRITE(ah, AR_QUIET_PERIOD, 100);
8534 REG_WRITE(ah, AR_NEXT_QUIET_TIMER, tsfLow >> 10);
8535 REG_SET_BIT(ah, AR_TIMER_MODE,
8536 AR_QUIET_TIMER_EN);
8537
8538 if ((REG_READ(ah, AR_TSF_L32) >> 10) ==
8539 (tsfLow >> 10)) {
8540 break;
8541 }
8542 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
8543 "%s: TSF have moved while trying to set "
8544 "quiet time TSF: 0x%08x\n",
8545 __func__, tsfLow);
8546 }
8547
8548 REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
8549
8550 udelay(200);
8551 REG_CLR_BIT(ah, AR_TIMER_MODE, AR_QUIET_TIMER_EN);
8552
8553 wait = 1000;
8554
8555 while (ath9k_hw_numtxpending(ah, q)) {
8556 if ((--wait) == 0) {
8557 DPRINTF(ah->ah_sc, ATH_DBG_XMIT,
8558 "%s: Failed to stop Tx DMA in 100 "
8559 "msec after killing last frame\n",
8560 __func__);
8561 break;
8562 }
8563 udelay(100);
8564 }
8565
8566 REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
8567 }
8568
8569 REG_WRITE(ah, AR_Q_TXD, 0);
8570 return wait != 0;
8571}