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