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
50void ar9300_disable_cck(struct ath_hal *ah);
51void ar9300_disable_radar(struct ath_hal *ah);
52void ar9300_disable_restart(struct ath_hal *ah);
53void ar9300_set_radar_dc_thresh(struct ath_hal *ah);
54void ar9300_disable_weak_signal(struct ath_hal *ah);
55void ar9300_disable_strong_signal(struct ath_hal *ah);
56void ar9300_prep_spectral_scan(struct ath_hal *ah);
57void ar9300_disable_dc_offset(struct ath_hal *ah);
58void ar9300_enable_cck_detect(struct ath_hal *ah);
59
60void
61ar9300_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
71void
72ar9300_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
99void 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
109void 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
120void
121ar9300_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
154void
155ar9300_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}
166void
167ar9300_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
178static 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
183void 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
188void 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
194void 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
217struct nf_cal {
218    int cal;
219    int pwr;
220};
221struct nf_cal_table_t {
222    int freq;
223    struct nf_cal chain[AH_MAX_CHAINS];
224};
225
226static 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
264static int
265ar9300_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
284static int
285ar9300_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
309void
310ar9300_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
408void
409ar9300_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
473HAL_BOOL
474ar9300_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
482HAL_BOOL
483ar9300_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
491void 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
527void 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
570u_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
588int16_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
608int16_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