xref: /freebsd/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_spectral.c (revision 8d20be1e22095c27faf8fe8b2f0d089739cc742e)
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
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
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 
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 
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
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
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
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 
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 
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 
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 
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
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
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
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
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
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
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 
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 
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 
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 
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 
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