1 /*
2 * Copyright (c) 2013 Qualcomm Atheros, 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 WITH
9 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10 * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
11 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
13 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14 * PERFORMANCE OF THIS SOFTWARE.
15 */
16 #include "opt_ah.h"
17
18 #ifdef AH_SUPPORT_AR9300
19
20 #include "ah.h"
21 #include "ah_desc.h"
22 #include "ah_internal.h"
23
24 #include "ar9300/ar9300phy.h"
25 #include "ar9300/ar9300.h"
26 #include "ar9300/ar9300reg.h"
27 #include "ar9300/ar9300desc.h"
28
29 #if ATH_SUPPORT_SPECTRAL
30
31 /*
32 * Default 9300 spectral scan parameters
33 */
34 #define AR9300_SPECTRAL_SCAN_ENA 0
35 #define AR9300_SPECTRAL_SCAN_ACTIVE 0
36 #define AR9300_SPECTRAL_SCAN_FFT_PERIOD 8
37 #define AR9300_SPECTRAL_SCAN_PERIOD 1
38 #define AR9300_SPECTRAL_SCAN_COUNT 16 /* used to be 128 */
39 #define AR9300_SPECTRAL_SCAN_SHORT_REPEAT 1
40
41 /* constants */
42 #define MAX_RADAR_DC_PWR_THRESH 127
43 #define MAX_RADAR_RSSI_THRESH 0x3f
44 #define MAX_RADAR_HEIGHT 0x3f
45 #define MAX_CCA_THRESH 127
46 #define ENABLE_ALL_PHYERR 0xffffffff
47
48 void ar9300_disable_cck(struct ath_hal *ah);
49 void ar9300_disable_radar(struct ath_hal *ah);
50 void ar9300_disable_restart(struct ath_hal *ah);
51 void ar9300_set_radar_dc_thresh(struct ath_hal *ah);
52 void ar9300_disable_weak_signal(struct ath_hal *ah);
53 void ar9300_disable_strong_signal(struct ath_hal *ah);
54 void ar9300_prep_spectral_scan(struct ath_hal *ah);
55 void ar9300_disable_dc_offset(struct ath_hal *ah);
56 void ar9300_enable_cck_detect(struct ath_hal *ah);
57
58 void
ar9300_disable_cck(struct ath_hal * ah)59 ar9300_disable_cck(struct ath_hal *ah)
60 {
61 u_int32_t val;
62
63 val = OS_REG_READ(ah, AR_PHY_MODE);
64 val &= ~(AR_PHY_MODE_DYN_CCK_DISABLE);
65
66 OS_REG_WRITE(ah, AR_PHY_MODE, val);
67 }
68
69 void
ar9300_disable_radar(struct ath_hal * ah)70 ar9300_disable_radar(struct ath_hal *ah)
71 {
72 u_int32_t val;
73
74 /* Enable radar FFT */
75 val = OS_REG_READ(ah, AR_PHY_RADAR_0);
76 val |= AR_PHY_RADAR_0_FFT_ENA;
77
78 /* set radar detect thresholds to max to effectively disable radar */
79 val &= ~AR_PHY_RADAR_0_RRSSI;
80 val |= SM(MAX_RADAR_RSSI_THRESH, AR_PHY_RADAR_0_RRSSI);
81
82 val &= ~AR_PHY_RADAR_0_HEIGHT;
83 val |= SM(MAX_RADAR_HEIGHT, AR_PHY_RADAR_0_HEIGHT);
84
85 val &= ~(AR_PHY_RADAR_0_ENA);
86 OS_REG_WRITE(ah, AR_PHY_RADAR_0, val);
87
88 /* disable extension radar detect */
89 val = OS_REG_READ(ah, AR_PHY_RADAR_EXT);
90 OS_REG_WRITE(ah, AR_PHY_RADAR_EXT, val & ~AR_PHY_RADAR_EXT_ENA);
91
92 val = OS_REG_READ(ah, AR_RX_FILTER);
93 val |= (1 << 13);
94 OS_REG_WRITE(ah, AR_RX_FILTER, val);
95 }
96
ar9300_disable_restart(struct ath_hal * ah)97 void ar9300_disable_restart(struct ath_hal *ah)
98 {
99 u_int32_t val;
100 val = OS_REG_READ(ah, AR_PHY_RESTART);
101 val &= ~AR_PHY_RESTART_ENA;
102 OS_REG_WRITE(ah, AR_PHY_RESTART, val);
103
104 val = OS_REG_READ(ah, AR_PHY_RESTART);
105 }
106
ar9300_set_radar_dc_thresh(struct ath_hal * ah)107 void ar9300_set_radar_dc_thresh(struct ath_hal *ah)
108 {
109 u_int32_t val;
110 val = OS_REG_READ(ah, AR_PHY_RADAR_EXT);
111 val &= ~AR_PHY_RADAR_DC_PWR_THRESH;
112 val |= SM(MAX_RADAR_DC_PWR_THRESH, AR_PHY_RADAR_DC_PWR_THRESH);
113 OS_REG_WRITE(ah, AR_PHY_RADAR_EXT, val);
114
115 val = OS_REG_READ(ah, AR_PHY_RADAR_EXT);
116 }
117
118 void
ar9300_disable_weak_signal(struct ath_hal * ah)119 ar9300_disable_weak_signal(struct ath_hal *ah)
120 {
121 /* set firpwr to max (signed) */
122 OS_REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, AR_PHY_FIND_SIG_FIRPWR, 0x7f);
123 OS_REG_CLR_BIT(ah, AR_PHY_FIND_SIG, AR_PHY_FIND_SIG_FIRPWR_SIGN_BIT);
124
125 /* set firstep to max */
126 OS_REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, AR_PHY_FIND_SIG_FIRSTEP, 0x3f);
127
128 /* set relpwr to max (signed) */
129 OS_REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, AR_PHY_FIND_SIG_RELPWR, 0x1f);
130 OS_REG_CLR_BIT(ah, AR_PHY_FIND_SIG, AR_PHY_FIND_SIG_RELPWR_SIGN_BIT);
131
132 /* set relstep to max (signed) */
133 OS_REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, AR_PHY_FIND_SIG_RELSTEP, 0x1f);
134 OS_REG_CLR_BIT(ah, AR_PHY_FIND_SIG, AR_PHY_FIND_SIG_RELSTEP_SIGN_BIT);
135
136 /* set firpwr_low to max (signed) */
137 OS_REG_RMW_FIELD(ah, AR_PHY_FIND_SIG_LOW, AR_PHY_FIND_SIG_LOW_FIRPWR, 0x7f);
138 OS_REG_CLR_BIT(
139 ah, AR_PHY_FIND_SIG_LOW, AR_PHY_FIND_SIG_LOW_FIRPWR_SIGN_BIT);
140
141 /* set firstep_low to max */
142 OS_REG_RMW_FIELD(
143 ah, AR_PHY_FIND_SIG_LOW, AR_PHY_FIND_SIG_LOW_FIRSTEP_LOW, 0x3f);
144
145 /* set relstep_low to max (signed) */
146 OS_REG_RMW_FIELD(
147 ah, AR_PHY_FIND_SIG_LOW, AR_PHY_FIND_SIG_LOW_RELSTEP, 0x1f);
148 OS_REG_CLR_BIT(
149 ah, AR_PHY_FIND_SIG_LOW, AR_PHY_FIND_SIG_LOW_RELSTEP_SIGN_BIT);
150 }
151
152 void
ar9300_disable_strong_signal(struct ath_hal * ah)153 ar9300_disable_strong_signal(struct ath_hal *ah)
154 {
155 u_int32_t val;
156
157 val = OS_REG_READ(ah, AR_PHY_TIMING5);
158 val |= AR_PHY_TIMING5_RSSI_THR1A_ENA;
159 OS_REG_WRITE(ah, AR_PHY_TIMING5, val);
160
161 OS_REG_RMW_FIELD(ah, AR_PHY_TIMING5, AR_PHY_TIMING5_RSSI_THR1A, 0x7f);
162
163 }
164 void
ar9300_set_cca_threshold(struct ath_hal * ah,u_int8_t thresh62)165 ar9300_set_cca_threshold(struct ath_hal *ah, u_int8_t thresh62)
166 {
167 OS_REG_RMW_FIELD(ah, AR_PHY_CCA_0, AR_PHY_CCA_THRESH62, thresh62);
168 OS_REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, AR_PHY_EXT_CCA0_THRESH62, thresh62);
169 /*
170 OS_REG_RMW_FIELD(ah,
171 AR_PHY_EXTCHN_PWRTHR1, AR_PHY_EXT_CCA0_THRESH62, thresh62);
172 */
173 OS_REG_RMW_FIELD(ah, AR_PHY_EXT_CCA, AR_PHY_EXT_CCA_THRESH62, thresh62);
174 }
175
ar9300_classify_strong_bins(struct ath_hal * ah)176 static void ar9300_classify_strong_bins(struct ath_hal *ah)
177 {
178 OS_REG_RMW_FIELD(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_CF_BIN_THRESH, 0x1);
179 }
180
ar9300_disable_dc_offset(struct ath_hal * ah)181 void ar9300_disable_dc_offset(struct ath_hal *ah)
182 {
183 OS_REG_RMW_FIELD(ah, AR_PHY_TIMING2, AR_PHY_TIMING2_DC_OFFSET, 0);
184 }
185
ar9300_enable_cck_detect(struct ath_hal * ah)186 void ar9300_enable_cck_detect(struct ath_hal *ah)
187 {
188 OS_REG_RMW_FIELD(ah, AR_PHY_MODE, AR_PHY_MODE_DISABLE_CCK, 0);
189 OS_REG_RMW_FIELD(ah, AR_PHY_MODE, AR_PHY_MODE_DYNAMIC, 1);
190 }
191
ar9300_prep_spectral_scan(struct ath_hal * ah)192 void ar9300_prep_spectral_scan(struct ath_hal *ah)
193 {
194 ar9300_disable_radar(ah);
195 ar9300_classify_strong_bins(ah);
196 ar9300_disable_dc_offset(ah);
197 if (AH_PRIVATE(ah)->ah_curchan &&
198 IS_5GHZ_FAST_CLOCK_EN(ah, AH_PRIVATE(ah)->ah_curchan))
199 { /* fast clock */
200 ar9300_enable_cck_detect(ah);
201 }
202 #ifdef DEMO_MODE
203 ar9300_disable_strong_signal(ah);
204 ar9300_disable_weak_signal(ah);
205 ar9300_set_radar_dc_thresh(ah);
206 ar9300_set_cca_threshold(ah, MAX_CCA_THRESH);
207 /*ar9300_disable_restart(ah);*/
208 #endif
209 OS_REG_WRITE(ah, AR_PHY_ERR, HAL_PHYERR_SPECTRAL);
210 }
211
212
213 //#define TEST_NOISE_PWR_WITHOUT_EEPROM 1
214 #ifdef TEST_NOISE_PWR_WITHOUT_EEPROM
215 struct nf_cal {
216 int cal;
217 int pwr;
218 };
219 struct nf_cal_table_t {
220 int freq;
221 struct nf_cal chain[AH_MAX_CHAINS];
222 };
223
224 static const struct nf_cal_table_t nf_cal_table[] =
225 {
226 /* ch 1 */ {2412, { {N2DBM(-101, 00), N2DBM( -94, 25)},
227 {N2DBM(-107, 75), N2DBM( -99, 75)},
228 } },
229 /* ch 6 */ {2437, { {N2DBM(-102, 25), N2DBM( -94, 25)},
230 {N2DBM(-106, 00), N2DBM( -97, 25)},
231 } },
232 /* ch 11 */ {2462, { {N2DBM(-101, 50), N2DBM( -95, 00)},
233 {N2DBM(-105, 50), N2DBM( -98, 00)},
234 } },
235 /* ch 36 */ {5180, { {N2DBM(-114, 25), N2DBM( -95, 00)},
236 {N2DBM(-114, 75), N2DBM( -94, 00)},
237 } },
238 /* ch 44 */ {5220, { {N2DBM(-113, 00), N2DBM( -95, 00)},
239 {N2DBM(-115, 00), N2DBM( -94, 50)},
240 } },
241 /* ch 64 */ {5320, { {N2DBM(-113, 00), N2DBM( -95, 00)}, // not cal'ed
242 {N2DBM(-115, 00), N2DBM( -94, 50)},
243 } },
244 /* ch 100*/ {5500, { {N2DBM(-111, 50), N2DBM( -93, 75)},
245 {N2DBM(-112, 00), N2DBM( -95, 25)},
246 } },
247 /* ch 120*/ {5600, { {N2DBM(-111, 50), N2DBM( -93, 75)},
248 {N2DBM(-112, 00), N2DBM( -95, 25)},
249 } },
250 /* ch 140*/ {5700, { {N2DBM(-111, 75), N2DBM( -95, 00)},
251 {N2DBM(-111, 75), N2DBM( -96, 00)},
252 } },
253 /* ch 157*/ {5785, { {N2DBM(-112, 50), N2DBM( -94, 75)},
254 {N2DBM(-111, 75), N2DBM( -95, 50)},
255 } },
256 /* ch 165*/ {5825, { {N2DBM(-111, 50), N2DBM( -95, 00)},
257 {N2DBM(-112, 00), N2DBM( -95, 00)},
258 } },
259 {0}
260 };
261
262 static int
ar9300_noise_floor_get(struct ath_hal * ah,int freq_mhz,int ch)263 ar9300_noise_floor_get(struct ath_hal *ah, int freq_mhz, int ch)
264 {
265 int i;
266 for (i = 0; nf_cal_table[i].freq != 0; i++) {
267 if (nf_cal_table[i + 0].freq == freq_mhz ||
268 nf_cal_table[i + 1].freq > freq_mhz ||
269 nf_cal_table[i + 1].freq == 0) {
270 return nf_cal_table[i].chain[ch].cal;
271 }
272 }
273
274 ath_hal_printf(ah,
275 "%s: **Warning: device %d.%d: "
276 "no nf cal offset found for freq %d chain %d\n",
277 __func__, (AH_PRIVATE(ah))->ah_macVersion,
278 (AH_PRIVATE(ah))->ah_macRev, freq_mhz, ch);
279 return 0;
280 }
281
282 static int
ar9300_noise_floor_power_get(struct ath_hal * ah,int freq_mhz,int ch)283 ar9300_noise_floor_power_get(struct ath_hal *ah, int freq_mhz, int ch)
284 {
285 int i;
286 for (i = 0; nf_cal_table[i].freq != 0; i++) {
287 if (nf_cal_table[i + 0].freq == freq_mhz ||
288 nf_cal_table[i + 1].freq > freq_mhz ||
289 nf_cal_table[i + 1].freq == 0) {
290 return nf_cal_table[i].chain[ch].pwr;
291 }
292 }
293
294 ath_hal_printf(ah,
295 "%s: **Warning: device %d.%d: "
296 "no nf pwr offset found for freq %d chain %d\n",
297 __func__, (AH_PRIVATE(ah))->ah_macVersion,
298 (AH_PRIVATE(ah))->ah_macRev, freq_mhz, ch);
299 return 0;
300 }
301 #else
302 #define ar9300_noise_floor_get(_ah,_f,_ich) ar9300_noise_floor_cal_or_power_get((_ah), (_f), (_ich), 1/*use_cal*/)
303 #define ar9300_noise_floor_power_get(_ah,_f,_ich) ar9300_noise_floor_cal_or_power_get((_ah), (_f), (_ich), 0/*use_cal*/)
304 #endif
305
306
307 void
ar9300_configure_spectral_scan(struct ath_hal * ah,HAL_SPECTRAL_PARAM * ss)308 ar9300_configure_spectral_scan(struct ath_hal *ah, HAL_SPECTRAL_PARAM *ss)
309 {
310 u_int32_t val, i;
311 struct ath_hal_9300 *ahp = AH9300(ah);
312 HAL_BOOL asleep = ahp->ah_chip_full_sleep;
313 int16_t nf_buf[NUM_NF_READINGS];
314
315 if ((AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) && asleep) {
316 ar9300_set_power_mode(ah, HAL_PM_AWAKE, AH_TRUE);
317 }
318
319 ar9300_prep_spectral_scan(ah);
320
321 if (ss->ss_spectral_pri) {
322 for (i = 0; i < NUM_NF_READINGS; i++) {
323 nf_buf[i] = NOISE_PWR_DBM_2_INT(ss->ss_nf_cal[i]);
324 }
325 ar9300_load_nf(ah, nf_buf);
326 #ifdef DEMO_MODE
327 ar9300_disable_strong_signal(ah);
328 ar9300_disable_weak_signal(ah);
329 ar9300_set_radar_dc_thresh(ah);
330 ar9300_set_cca_threshold(ah, MAX_CCA_THRESH);
331 /*ar9300_disable_restart(ah);*/
332 #endif
333 }
334
335 val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN);
336
337 if (ss->ss_fft_period != HAL_SPECTRAL_PARAM_NOVAL) {
338 val &= ~AR_PHY_SPECTRAL_SCAN_FFT_PERIOD;
339 val |= SM(ss->ss_fft_period, AR_PHY_SPECTRAL_SCAN_FFT_PERIOD);
340 }
341
342 if (ss->ss_period != HAL_SPECTRAL_PARAM_NOVAL) {
343 val &= ~AR_PHY_SPECTRAL_SCAN_PERIOD;
344 val |= SM(ss->ss_period, AR_PHY_SPECTRAL_SCAN_PERIOD);
345 }
346
347 if (ss->ss_count != HAL_SPECTRAL_PARAM_NOVAL) {
348 val &= ~AR_PHY_SPECTRAL_SCAN_COUNT;
349 /* Remnants of a Merlin bug, 128 translates to 0 for
350 * continuous scanning. Instead we do piecemeal captures
351 * of 64 samples for Osprey.
352 */
353 if (ss->ss_count == 128) {
354 val |= SM(0, AR_PHY_SPECTRAL_SCAN_COUNT);
355 } else {
356 val |= SM(ss->ss_count, AR_PHY_SPECTRAL_SCAN_COUNT);
357 }
358 }
359
360 if (ss->ss_period != HAL_SPECTRAL_PARAM_NOVAL) {
361 val &= ~AR_PHY_SPECTRAL_SCAN_PERIOD;
362 val |= SM(ss->ss_period, AR_PHY_SPECTRAL_SCAN_PERIOD);
363 }
364
365 if (ss->ss_short_report == AH_TRUE) {
366 val |= AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT;
367 } else {
368 val &= ~AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT;
369 }
370
371 /* if noise power cal, force high priority */
372 if (ss->ss_spectral_pri) {
373 val |= AR_PHY_SPECTRAL_SCAN_PRIORITY_HI;
374 } else {
375 val &= ~AR_PHY_SPECTRAL_SCAN_PRIORITY_HI;
376 }
377
378 /* enable spectral scan */
379 OS_REG_WRITE(ah, AR_PHY_SPECTRAL_SCAN, val | AR_PHY_SPECTRAL_SCAN_ENABLE);
380
381 if ((AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) && asleep) {
382 ar9300_set_power_mode(ah, HAL_PM_FULL_SLEEP, AH_TRUE);
383 }
384 }
385
386 /*
387 * Get the spectral parameter values and return them in the pe
388 * structure
389 */
390
391 void
ar9300_get_spectral_params(struct ath_hal * ah,HAL_SPECTRAL_PARAM * ss)392 ar9300_get_spectral_params(struct ath_hal *ah, HAL_SPECTRAL_PARAM *ss)
393 {
394 u_int32_t val;
395 HAL_CHANNEL_INTERNAL *chan = AH_PRIVATE(ah)->ah_curchan;
396 int i, ichain, rx_chain_status;
397 struct ath_hal_9300 *ahp = AH9300(ah);
398 HAL_BOOL asleep = ahp->ah_chip_full_sleep;
399
400 if ((AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) && asleep) {
401 ar9300_set_power_mode(ah, HAL_PM_AWAKE, AH_TRUE);
402 }
403
404 val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN);
405
406 ss->ss_fft_period = MS(val, AR_PHY_SPECTRAL_SCAN_FFT_PERIOD);
407 ss->ss_period = MS(val, AR_PHY_SPECTRAL_SCAN_PERIOD);
408 ss->ss_count = MS(val, AR_PHY_SPECTRAL_SCAN_COUNT);
409 ss->ss_short_report = (val & AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT) ? 1:0;
410 ss->ss_spectral_pri = ( val & AR_PHY_SPECTRAL_SCAN_PRIORITY_HI) ? 1:0;
411 OS_MEMZERO(ss->ss_nf_cal, sizeof(ss->ss_nf_cal));
412 OS_MEMZERO(ss->ss_nf_pwr, sizeof(ss->ss_nf_cal));
413 ss->ss_nf_temp_data = 0;
414
415 if (chan != NULL) {
416 rx_chain_status = OS_REG_READ(ah, AR_PHY_RX_CHAINMASK) & 0x7;
417 for (i = 0; i < NUM_NF_READINGS; i++) {
418 ichain = i % 3;
419 if (rx_chain_status & (1 << ichain)) {
420 ss->ss_nf_cal[i] =
421 ar9300_noise_floor_get(ah, chan->channel, ichain);
422 ss->ss_nf_pwr[i] =
423 ar9300_noise_floor_power_get(ah, chan->channel, ichain);
424 }
425 }
426 ss->ss_nf_temp_data = OS_REG_READ_FIELD(ah, AR_PHY_BB_THERM_ADC_4, AR_PHY_BB_THERM_ADC_4_LATEST_THERM);
427 } else {
428 HALDEBUG(AH_NULL, HAL_DEBUG_UNMASKABLE,
429 "%s: chan is NULL - no ss nf values\n", __func__);
430 }
431
432 if ((AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) && asleep) {
433 ar9300_set_power_mode(ah, HAL_PM_FULL_SLEEP, AH_TRUE);
434 }
435 }
436
437 HAL_BOOL
ar9300_is_spectral_active(struct ath_hal * ah)438 ar9300_is_spectral_active(struct ath_hal *ah)
439 {
440 u_int32_t val;
441
442 val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN);
443 return MS(val, AR_PHY_SPECTRAL_SCAN_ACTIVE);
444 }
445
446 HAL_BOOL
ar9300_is_spectral_enabled(struct ath_hal * ah)447 ar9300_is_spectral_enabled(struct ath_hal *ah)
448 {
449 u_int32_t val;
450
451 val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN);
452 return MS(val, AR_PHY_SPECTRAL_SCAN_ENABLE);
453 }
454
ar9300_start_spectral_scan(struct ath_hal * ah)455 void ar9300_start_spectral_scan(struct ath_hal *ah)
456 {
457 u_int32_t val;
458 struct ath_hal_9300 *ahp = AH9300(ah);
459 HAL_BOOL asleep = ahp->ah_chip_full_sleep;
460
461 if ((AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) && asleep) {
462 ar9300_set_power_mode(ah, HAL_PM_AWAKE, AH_TRUE);
463 }
464
465 ar9300_prep_spectral_scan(ah);
466
467 /* activate spectral scan */
468 val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN);
469 /* This is a hardware bug fix, the enable and active bits should
470 * not be set/reset in the same write operation to the register
471 */
472 if (!(val & AR_PHY_SPECTRAL_SCAN_ENABLE)) {
473 val |= AR_PHY_SPECTRAL_SCAN_ENABLE;
474 OS_REG_WRITE(ah, AR_PHY_SPECTRAL_SCAN, val);
475 val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN);
476 }
477 val |= AR_PHY_SPECTRAL_SCAN_ACTIVE;
478 OS_REG_WRITE(ah, AR_PHY_SPECTRAL_SCAN, val);
479
480 /* Reset the PHY_ERR_MASK */
481 val = OS_REG_READ(ah, AR_PHY_ERR_MASK_REG);
482 OS_REG_WRITE(ah, AR_PHY_ERR_MASK_REG, val | AR_PHY_ERR_RADAR);
483
484 if ((AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) && asleep) {
485 ar9300_set_power_mode(ah, HAL_PM_FULL_SLEEP, AH_TRUE);
486 }
487 }
488
ar9300_stop_spectral_scan(struct ath_hal * ah)489 void ar9300_stop_spectral_scan(struct ath_hal *ah)
490 {
491 u_int32_t val;
492 struct ath_hal_9300 *ahp = AH9300(ah);
493 HAL_BOOL asleep = ahp->ah_chip_full_sleep;
494
495 if ((AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) && asleep) {
496 ar9300_set_power_mode(ah, HAL_PM_AWAKE, AH_TRUE);
497 }
498 val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN);
499
500 /* deactivate spectral scan */
501 /* HW Bug fix -- Do not disable the spectral scan
502 * only turn off the active bit
503 */
504 //val &= ~AR_PHY_SPECTRAL_SCAN_ENABLE;
505 val &= ~AR_PHY_SPECTRAL_SCAN_ACTIVE;
506 OS_REG_WRITE(ah, AR_PHY_SPECTRAL_SCAN, val);
507 val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN);
508
509 OS_REG_RMW_FIELD(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_CF_BIN_THRESH,
510 ahp->ah_radar1);
511 OS_REG_RMW_FIELD(ah, AR_PHY_TIMING2, AR_PHY_TIMING2_DC_OFFSET,
512 ahp->ah_dc_offset);
513 OS_REG_WRITE(ah, AR_PHY_ERR, 0);
514
515 if (AH_PRIVATE(ah)->ah_curchan &&
516 IS_5GHZ_FAST_CLOCK_EN(ah, AH_PRIVATE(ah)->ah_curchan))
517 { /* fast clock */
518 OS_REG_RMW_FIELD(ah, AR_PHY_MODE, AR_PHY_MODE_DISABLE_CCK,
519 ahp->ah_disable_cck);
520 }
521
522 val = OS_REG_READ(ah, AR_PHY_ERR);
523
524 val = OS_REG_READ(ah, AR_PHY_ERR_MASK_REG) & (~AR_PHY_ERR_RADAR);
525 OS_REG_WRITE(ah, AR_PHY_ERR_MASK_REG, val);
526
527 if ((AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) && asleep) {
528 ar9300_set_power_mode(ah, HAL_PM_FULL_SLEEP, AH_TRUE);
529 }
530 }
531
ar9300_get_spectral_config(struct ath_hal * ah)532 u_int32_t ar9300_get_spectral_config(struct ath_hal *ah)
533 {
534 u_int32_t val;
535 struct ath_hal_9300 *ahp = AH9300(ah);
536 HAL_BOOL asleep = ahp->ah_chip_full_sleep;
537
538 if ((AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) && asleep) {
539 ar9300_set_power_mode(ah, HAL_PM_AWAKE, AH_TRUE);
540 }
541
542 val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN);
543
544 if ((AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) && asleep) {
545 ar9300_set_power_mode(ah, HAL_PM_FULL_SLEEP, AH_TRUE);
546 }
547 return val;
548 }
549
ar9300_get_ctl_chan_nf(struct ath_hal * ah)550 int16_t ar9300_get_ctl_chan_nf(struct ath_hal *ah)
551 {
552 int16_t nf;
553 struct ath_hal_private *ahpriv = AH_PRIVATE(ah);
554
555 if ( (OS_REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) == 0) {
556 /* Noise floor calibration value is ready */
557 nf = MS(OS_REG_READ(ah, AR_PHY_CCA_0), AR_PHY_MINCCA_PWR);
558 } else {
559 /* NF calibration is not done, return nominal value */
560 nf = ahpriv->nfp->nominal;
561 }
562 if (nf & 0x100) {
563 nf = (0 - ((nf ^ 0x1ff) + 1));
564 }
565 return nf;
566 }
567
ar9300_get_ext_chan_nf(struct ath_hal * ah)568 int16_t ar9300_get_ext_chan_nf(struct ath_hal *ah)
569 {
570 int16_t nf;
571 struct ath_hal_private *ahpriv = AH_PRIVATE(ah);
572
573 if ((OS_REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) == 0) {
574 /* Noise floor calibration value is ready */
575 nf = MS(OS_REG_READ(ah, AR_PHY_EXT_CCA), AR_PHY_EXT_MINCCA_PWR);
576 } else {
577 /* NF calibration is not done, return nominal value */
578 nf = ahpriv->nfp->nominal;
579 }
580 if (nf & 0x100) {
581 nf = (0 - ((nf ^ 0x1ff) + 1));
582 }
583 return nf;
584 }
585
586 #endif
587 #endif /* ATH_SUPPORT_SPECTRAL */
588
589