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
48void ar9300_disable_cck(struct ath_hal *ah);
49void ar9300_disable_radar(struct ath_hal *ah);
50void ar9300_disable_restart(struct ath_hal *ah);
51void ar9300_set_radar_dc_thresh(struct ath_hal *ah);
52void ar9300_disable_weak_signal(struct ath_hal *ah);
53void ar9300_disable_strong_signal(struct ath_hal *ah);
54void ar9300_prep_spectral_scan(struct ath_hal *ah);
55void ar9300_disable_dc_offset(struct ath_hal *ah);
56void ar9300_enable_cck_detect(struct ath_hal *ah);
57
58void
59ar9300_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
69void
70ar9300_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
97void 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
107void 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
118void
119ar9300_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
152void
153ar9300_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}
164void
165ar9300_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
176static 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
181void 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
186void 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
192void 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
215struct nf_cal {
216    int cal;
217    int pwr;
218};
219struct nf_cal_table_t {
220    int freq;
221    struct nf_cal chain[AH_MAX_CHAINS];
222};
223
224static 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
262static int
263ar9300_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
282static int
283ar9300_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
307void
308ar9300_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
391void
392ar9300_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
437HAL_BOOL
438ar9300_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
446HAL_BOOL
447ar9300_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
455void 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
489void 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
532u_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
550int16_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
568int16_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