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
17
18#include "opt_ah.h"
19
20#include "ah.h"
21#include "ah_desc.h"
22#include "ah_internal.h"
23
24#include "ar9300/ar9300.h"
25#include "ar9300/ar9300phy.h"
26#include "ar9300/ar9300reg.h"
27
28/*
29 * Default 5413/9300 radar phy parameters
30 * Values adjusted to fix EV76432/EV76320
31 */
32#define AR9300_DFS_FIRPWR   -28
33#define AR9300_DFS_RRSSI    0
34#define AR9300_DFS_HEIGHT   10
35#define AR9300_DFS_PRSSI    6
36#define AR9300_DFS_INBAND   8
37#define AR9300_DFS_RELPWR   8
38#define AR9300_DFS_RELSTEP  12
39#define AR9300_DFS_MAXLEN   255
40
41/*
42 * This PRSSI value should be used during CAC.
43 */
44#define AR9300_DFS_PRSSI_CAC 10
45
46/*
47 *  make sure that value matches value in ar9300_osprey_2p2_mac_core[][2]
48 *  for register 0x1040 to 0x104c
49*/
50#define AR9300_DEFAULT_DIFS     0x002ffc0f
51#define AR9300_FCC_RADARS_FCC_OFFSET 4
52
53struct dfs_pulse ar9300_etsi_radars[] = {
54
55    /* for short pulses, RSSI threshold should be smaller than
56 * Kquick-drop. The chip has only one chance to drop the gain which
57 * will be reported as the estimated RSSI */
58
59    /* TYPE staggered pulse */
60    /* 0.8-2us, 2-3 bursts,300-400 PRF, 10 pulses each */
61    {30,  2,  300,  400, 2, 30,  3,  0,  5, 15, 0,   0, 1, 31},   /* Type 5*/
62    /* 0.8-2us, 2-3 bursts, 400-1200 PRF, 15 pulses each */
63    {30,  2,  400, 1200, 2, 30,  7,  0,  5, 15, 0,   0, 0, 32},   /* Type 6 */
64
65    /* constant PRF based */
66    /* 0.8-5us, 200  300 PRF, 10 pulses */
67    {10, 5,   200,  400, 0, 24,  5,  0,  8, 15, 0,   0, 2, 33},   /* Type 1 */
68    {10, 5,   400,  600, 0, 24,  5,  0,  8, 15, 0,   0, 2, 37},   /* Type 1 */
69    {10, 5,   600,  800, 0, 24,  5,  0,  8, 15, 0,   0, 2, 38},   /* Type 1 */
70    {10, 5,   800, 1000, 0, 24,  5,  0,  8, 15, 0,   0, 2, 39},   /* Type 1 */
71//  {10, 5,   200, 1000, 0, 24,  5,  0,  8, 15, 0,   0, 2, 33},
72
73    /* 0.8-15us, 200-1600 PRF, 15 pulses */
74    {15, 15,  200, 1600, 0, 24, 8,  0, 18, 24, 0,   0, 0, 34},    /* Type 2 */
75
76    /* 0.8-15us, 2300-4000 PRF, 25 pulses*/
77    {25, 15, 2300, 4000,  0, 24, 10, 0, 18, 24, 0,   0, 0, 35},   /* Type 3 */
78
79    /* 20-30us, 2000-4000 PRF, 20 pulses*/
80    {20, 30, 2000, 4000, 0, 24, 8, 19, 33, 24, 0,   0, 0, 36},    /* Type 4 */
81};
82
83
84/* The following are for FCC Bin 1-4 pulses */
85struct dfs_pulse ar9300_fcc_radars[] = {
86
87    /* following two filters are specific to Japan/MKK4 */
88//  {18,  1,  720,  720, 1,  6,  6,  0,  1, 18,  0, 3, 0, 17}, // 1389 +/- 6 us
89//  {18,  4,  250,  250, 1, 10,  5,  1,  6, 18,  0, 3, 0, 18}, // 4000 +/- 6 us
90//  {18,  5,  260,  260, 1, 10,  6,  1,  6, 18,  0, 3, 0, 19}, // 3846 +/- 7 us
91    {18,  1,  720,  720, 0,  6,  6,  0,  1, 18,  0, 3, 0, 17}, // 1389 +/- 6 us
92    {18,  4,  250,  250, 0, 10,  5,  1,  6, 18,  0, 3, 0, 18}, // 4000 +/- 6 us
93    {18,  5,  260,  260, 0, 10,  6,  1,  6, 18,  0, 3, 1, 19}, // 3846 +/- 7 us
94//  {18,  5,  260,  260, 1, 10,  6,  1,  6, 18,  0, 3, 1, 20}, // 3846 +/- 7 us
95
96   {18, 5, 260, 260, 1, 10, 6, 1, 6, 18, 0, 3, 1, 20}, // 3846 +/- 7 us
97
98
99    /* following filters are common to both FCC and JAPAN */
100
101    // FCC TYPE 1
102    // {18,  1,  325, 1930, 0,  6,  7,  0,  1, 18,  0, 3, 0, 0}, // 518 to 3066
103    {18,  1,  700, 700, 0,  6,  5,  0,  1, 18,  0, 3, 1, 8},
104    {18,  1,  350, 350, 0,  6,  5,  0,  1, 18,  0, 3, 0, 0},
105
106
107    // FCC TYPE 6
108    // {9,   1, 3003, 3003, 1,  7,  5,  0,  1, 18,  0, 0, 0, 1}, // 333 +/- 7 us
109    //{9,   1, 3003, 3003, 1,  7,  5,  0,  1, 18,  0, 0, 0, 1},
110    {9,   1, 3003, 3003, 0,  7,  5,  0,  1, 18,  0, 0, 1, 1},
111
112    // FCC TYPE 2
113    {23, 5, 4347, 6666, 0, 18, 11,  0,  7, 22,  0, 3, 0, 2},
114
115    // FCC TYPE 3
116    {18, 10, 2000, 5000, 0, 23,  8,  6, 13, 22,  0, 3, 0, 5},
117
118    // FCC TYPE 4
119    {16, 15, 2000, 5000, 0, 25,  7, 11, 23, 22,  0, 3, 0, 11},
120
121};
122
123struct dfs_bin5pulse ar9300_bin5pulses[] = {
124        {2, 28, 105, 12, 22, 5},
125};
126
127
128#if 0
129/*
130 * Find the internal HAL channel corresponding to the
131 * public HAL channel specified in c
132 */
133
134static HAL_CHANNEL_INTERNAL *
135getchannel(struct ath_hal *ah, const struct ieee80211_channel *c)
136{
137#define CHAN_FLAGS    (CHANNEL_ALL | CHANNEL_HALF | CHANNEL_QUARTER)
138    HAL_CHANNEL_INTERNAL *base, *cc;
139    int flags = c->channel_flags & CHAN_FLAGS;
140    int n, lim;
141
142    /*
143     * Check current channel to avoid the lookup.
144     */
145    cc = AH_PRIVATE(ah)->ah_curchan;
146    if (cc != AH_NULL && cc->channel == c->channel &&
147        (cc->channel_flags & CHAN_FLAGS) == flags) {
148        return cc;
149    }
150
151    /* binary search based on known sorting order */
152    base = AH_TABLES(ah)->ah_channels;
153    n = AH_PRIVATE(ah)->ah_nchan;
154    /* binary search based on known sorting order */
155    for (lim = n; lim != 0; lim >>= 1) {
156        int d;
157        cc = &base[lim >> 1];
158        d = c->channel - cc->channel;
159        if (d == 0) {
160            if ((cc->channel_flags & CHAN_FLAGS) == flags) {
161                return cc;
162            }
163            d = flags - (cc->channel_flags & CHAN_FLAGS);
164        }
165        HALDEBUG(ah, HAL_DEBUG_DFS, "%s: channel %u/0x%x d %d\n", __func__,
166                cc->channel, cc->channel_flags, d);
167        if (d > 0) {
168            base = cc + 1;
169            lim--;
170        }
171    }
172    HALDEBUG(ah, HAL_DEBUG_DFS, "%s: no match for %u/0x%x\n",
173            __func__, c->channel, c->channel_flags);
174    return AH_NULL;
175#undef CHAN_FLAGS
176}
177
178/*
179 * Check the internal channel list to see if the desired channel
180 * is ok to release from the NOL.  If not, then do nothing.  If so,
181 * mark the channel as clear and reset the internal tsf time
182 */
183void
184ar9300_check_dfs(struct ath_hal *ah, struct ieee80211_channel *chan)
185{
186    HAL_CHANNEL_INTERNAL *ichan = AH_NULL;
187
188    ichan = getchannel(ah, chan);
189    if (ichan == AH_NULL) {
190        return;
191    }
192    if (!(ichan->priv_flags & CHANNEL_INTERFERENCE)) {
193        return;
194    }
195
196    ichan->priv_flags &= ~CHANNEL_INTERFERENCE;
197    ichan->dfs_tsf = 0;
198}
199
200/*
201 * This function marks the channel as having found a dfs event
202 * It also marks the end time that the dfs event should be cleared
203 * If the channel is already marked, then tsf end time can only
204 * be increased
205 */
206void
207ar9300_dfs_found(struct ath_hal *ah, struct ieee80211_channel *chan, u_int64_t nol_time)
208{
209    HAL_CHANNEL_INTERNAL *ichan;
210
211    ichan = getchannel(ah, chan);
212    if (ichan == AH_NULL) {
213        return;
214    }
215    if (!(ichan->priv_flags & CHANNEL_INTERFERENCE)) {
216        ichan->dfs_tsf = ar9300_get_tsf64(ah);
217    }
218    ichan->dfs_tsf += nol_time;
219    ichan->priv_flags |= CHANNEL_INTERFERENCE;
220    chan->priv_flags |= CHANNEL_INTERFERENCE;
221}
222#endif
223
224/*
225 * Enable radar detection and set the radar parameters per the
226 * values in pe
227 */
228void
229ar9300_enable_dfs(struct ath_hal *ah, HAL_PHYERR_PARAM *pe)
230{
231    u_int32_t val;
232    struct ath_hal_private  *ahp = AH_PRIVATE(ah);
233    const struct ieee80211_channel *chan = ahp->ah_curchan;
234    struct ath_hal_9300 *ah9300 = AH9300(ah);
235    int reg_writes = 0;
236
237    val = OS_REG_READ(ah, AR_PHY_RADAR_0);
238    val |= AR_PHY_RADAR_0_FFT_ENA;
239
240
241    if (pe->pe_enabled != HAL_PHYERR_PARAM_NOVAL) {
242        val &= ~AR_PHY_RADAR_0_ENA;
243        val |= SM(pe->pe_enabled, AR_PHY_RADAR_0_ENA);
244    }
245
246    if (pe->pe_firpwr != HAL_PHYERR_PARAM_NOVAL) {
247        val &= ~AR_PHY_RADAR_0_FIRPWR;
248        val |= SM(pe->pe_firpwr, AR_PHY_RADAR_0_FIRPWR);
249    }
250    if (pe->pe_rrssi != HAL_PHYERR_PARAM_NOVAL) {
251        val &= ~AR_PHY_RADAR_0_RRSSI;
252        val |= SM(pe->pe_rrssi, AR_PHY_RADAR_0_RRSSI);
253    }
254    if (pe->pe_height != HAL_PHYERR_PARAM_NOVAL) {
255        val &= ~AR_PHY_RADAR_0_HEIGHT;
256        val |= SM(pe->pe_height, AR_PHY_RADAR_0_HEIGHT);
257    }
258    if (pe->pe_prssi != HAL_PHYERR_PARAM_NOVAL) {
259        val &= ~AR_PHY_RADAR_0_PRSSI;
260        if (AR_SREV_AR9580(ah) || AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) {
261#if 0
262            if (ah->ah_use_cac_prssi) {
263                val |= SM(AR9300_DFS_PRSSI_CAC, AR_PHY_RADAR_0_PRSSI);
264            } else {
265#endif
266                val |= SM(pe->pe_prssi, AR_PHY_RADAR_0_PRSSI);
267//            }
268        } else {
269            val |= SM(pe->pe_prssi, AR_PHY_RADAR_0_PRSSI);
270        }
271    }
272    if (pe->pe_inband != HAL_PHYERR_PARAM_NOVAL) {
273        val &= ~AR_PHY_RADAR_0_INBAND;
274        val |= SM(pe->pe_inband, AR_PHY_RADAR_0_INBAND);
275    }
276    OS_REG_WRITE(ah, AR_PHY_RADAR_0, val);
277
278    val = OS_REG_READ(ah, AR_PHY_RADAR_1);
279    val |= AR_PHY_RADAR_1_MAX_RRSSI | AR_PHY_RADAR_1_BLOCK_CHECK;
280    if (pe->pe_maxlen != HAL_PHYERR_PARAM_NOVAL) {
281        val &= ~AR_PHY_RADAR_1_MAXLEN;
282        val |= SM(pe->pe_maxlen, AR_PHY_RADAR_1_MAXLEN);
283    }
284    if (pe->pe_relstep != HAL_PHYERR_PARAM_NOVAL) {
285        val &= ~AR_PHY_RADAR_1_RELSTEP_THRESH;
286        val |= SM(pe->pe_relstep, AR_PHY_RADAR_1_RELSTEP_THRESH);
287    }
288    if (pe->pe_relpwr != HAL_PHYERR_PARAM_NOVAL) {
289        val &= ~AR_PHY_RADAR_1_RELPWR_THRESH;
290        val |= SM(pe->pe_relpwr, AR_PHY_RADAR_1_RELPWR_THRESH);
291    }
292    OS_REG_WRITE(ah, AR_PHY_RADAR_1, val);
293
294    if (ath_hal_getcapability(ah, HAL_CAP_EXT_CHAN_DFS, 0, 0) == HAL_OK) {
295        val = OS_REG_READ(ah, AR_PHY_RADAR_EXT);
296        if (IEEE80211_IS_CHAN_HT40(chan)) {
297            /* Enable extension channel radar detection */
298            OS_REG_WRITE(ah, AR_PHY_RADAR_EXT, val | AR_PHY_RADAR_EXT_ENA);
299        } else {
300            /* HT20 mode, disable extension channel radar detect */
301            OS_REG_WRITE(ah, AR_PHY_RADAR_EXT, val & ~AR_PHY_RADAR_EXT_ENA);
302        }
303    }
304    /*
305        apply DFS postamble array from INI
306        column 0 is register ID, column 1 is  HT20 value, colum2 is HT40 value
307    */
308
309    if (AR_SREV_AR9580(ah) || AR_SREV_WASP(ah) || AR_SREV_OSPREY_22(ah) || AR_SREV_SCORPION(ah)) {
310        REG_WRITE_ARRAY(&ah9300->ah_ini_dfs, IEEE80211_IS_CHAN_HT40(chan)? 2:1, reg_writes);
311    }
312#ifdef ATH_HAL_DFS_CHIRPING_FIX_APH128
313    ath_hal_printf(ah, "DFS change the timing value\n");
314    if (AR_SREV_AR9580(ah) && IEEE80211_IS_CHAN_HT40(chan)) {
315        OS_REG_WRITE(ah, AR_PHY_TIMING6, 0x3140c00a);
316    }
317#endif
318
319}
320
321/*
322 * Get the radar parameter values and return them in the pe
323 * structure
324 */
325void
326ar9300_get_dfs_thresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe)
327{
328    u_int32_t val, temp;
329
330    val = OS_REG_READ(ah, AR_PHY_RADAR_0);
331    temp = MS(val, AR_PHY_RADAR_0_FIRPWR);
332    temp |= ~(AR_PHY_RADAR_0_FIRPWR >> AR_PHY_RADAR_0_FIRPWR_S);
333    pe->pe_firpwr = temp;
334    pe->pe_rrssi = MS(val, AR_PHY_RADAR_0_RRSSI);
335    pe->pe_height = MS(val, AR_PHY_RADAR_0_HEIGHT);
336    pe->pe_prssi = MS(val, AR_PHY_RADAR_0_PRSSI);
337    pe->pe_inband = MS(val, AR_PHY_RADAR_0_INBAND);
338    pe->pe_enabled = !! MS(val, AR_PHY_RADAR_0_ENA);
339
340    val = OS_REG_READ(ah, AR_PHY_RADAR_1);
341
342    pe->pe_relpwr = MS(val, AR_PHY_RADAR_1_RELPWR_THRESH);
343    pe->pe_enrelpwr = !! (val & AR_PHY_RADAR_1_RELPWR_ENA);
344
345    pe->pe_relstep = MS(val, AR_PHY_RADAR_1_RELSTEP_THRESH);
346    pe->pe_en_relstep_check = !! (val & AR_PHY_RADAR_1_RELSTEP_CHECK);
347
348    pe->pe_maxlen = MS(val, AR_PHY_RADAR_1_MAXLEN);
349}
350
351#if 0
352HAL_BOOL
353ar9300_radar_wait(struct ath_hal *ah, struct ieee80211_channel *chan)
354{
355    struct ath_hal_private *ahp = AH_PRIVATE(ah);
356
357    if (!ahp->ah_curchan) {
358        return AH_TRUE;
359    }
360
361    /*
362     * Rely on the upper layers to determine that we have spent
363     * enough time waiting.
364     */
365    chan->channel = ahp->ah_curchan->channel;
366    chan->channel_flags = ahp->ah_curchan->channel_flags;
367    chan->max_reg_tx_power = ahp->ah_curchan->max_reg_tx_power;
368
369    ahp->ah_curchan->priv_flags |= CHANNEL_DFS_CLEAR;
370    chan->priv_flags  = ahp->ah_curchan->priv_flags;
371    return AH_FALSE;
372
373}
374#endif
375
376struct dfs_pulse *
377ar9300_get_dfs_radars(
378    struct ath_hal *ah,
379    u_int32_t dfsdomain,
380    int *numradars,
381    struct dfs_bin5pulse **bin5pulses,
382    int *numb5radars,
383    HAL_PHYERR_PARAM *pe)
384{
385    struct dfs_pulse *dfs_radars = AH_NULL;
386    switch (dfsdomain) {
387    case HAL_DFS_FCC_DOMAIN:
388        dfs_radars = &ar9300_fcc_radars[AR9300_FCC_RADARS_FCC_OFFSET];
389        *numradars =
390            ARRAY_LENGTH(ar9300_fcc_radars) - AR9300_FCC_RADARS_FCC_OFFSET;
391        *bin5pulses = &ar9300_bin5pulses[0];
392        *numb5radars = ARRAY_LENGTH(ar9300_bin5pulses);
393        HALDEBUG(ah, HAL_DEBUG_DFS, "%s: DFS_FCC_DOMAIN_9300\n", __func__);
394        break;
395    case HAL_DFS_ETSI_DOMAIN:
396        dfs_radars = &ar9300_etsi_radars[0];
397        *numradars = ARRAY_LENGTH(ar9300_etsi_radars);
398        *bin5pulses = &ar9300_bin5pulses[0];
399        *numb5radars = ARRAY_LENGTH(ar9300_bin5pulses);
400        HALDEBUG(ah, HAL_DEBUG_DFS, "%s: DFS_ETSI_DOMAIN_9300\n", __func__);
401        break;
402    case HAL_DFS_MKK4_DOMAIN:
403        dfs_radars = &ar9300_fcc_radars[0];
404        *numradars = ARRAY_LENGTH(ar9300_fcc_radars);
405        *bin5pulses = &ar9300_bin5pulses[0];
406        *numb5radars = ARRAY_LENGTH(ar9300_bin5pulses);
407        HALDEBUG(ah, HAL_DEBUG_DFS, "%s: DFS_MKK4_DOMAIN_9300\n", __func__);
408        break;
409    default:
410        HALDEBUG(ah, HAL_DEBUG_DFS, "%s: no domain\n", __func__);
411        return AH_NULL;
412    }
413    /* Set the default phy parameters per chip */
414    pe->pe_firpwr = AR9300_DFS_FIRPWR;
415    pe->pe_rrssi = AR9300_DFS_RRSSI;
416    pe->pe_height = AR9300_DFS_HEIGHT;
417    pe->pe_prssi = AR9300_DFS_PRSSI;
418    /*
419        we have an issue with PRSSI.
420        For normal operation we use AR9300_DFS_PRSSI, which is set to 6.
421        Please refer to EV91563, 94164.
422        However, this causes problem during CAC as no radar is detected
423        during that period with PRSSI=6. Only PRSSI= 10 seems to fix this.
424        We use this flag to keep track of change in PRSSI.
425    */
426
427//    ah->ah_use_cac_prssi = 0;
428
429    pe->pe_inband = AR9300_DFS_INBAND;
430    pe->pe_relpwr = AR9300_DFS_RELPWR;
431    pe->pe_relstep = AR9300_DFS_RELSTEP;
432    pe->pe_maxlen = AR9300_DFS_MAXLEN;
433    return dfs_radars;
434}
435
436HAL_BOOL
437ar9300_get_default_dfs_thresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe)
438{
439
440    pe->pe_firpwr = AR9300_DFS_FIRPWR;
441    pe->pe_rrssi = AR9300_DFS_RRSSI;
442    pe->pe_height = AR9300_DFS_HEIGHT;
443    pe->pe_prssi = AR9300_DFS_PRSSI;
444    /* see prssi comment above */
445
446    pe->pe_inband = AR9300_DFS_INBAND;
447    pe->pe_relpwr = AR9300_DFS_RELPWR;
448    pe->pe_relstep = AR9300_DFS_RELSTEP;
449    pe->pe_maxlen = AR9300_DFS_MAXLEN;
450    return (AH_TRUE);
451}
452
453void ar9300_adjust_difs(struct ath_hal *ah, u_int32_t val)
454{
455    if (val == 0) {
456        /*
457         * EV 116936:
458         * Restore the register values with that of the HAL structure.
459         * Do not assume and overwrite these values to whatever
460         * is in ar9300_osprey22.ini.
461         */
462        struct ath_hal_9300 *ahp = AH9300(ah);
463        HAL_TX_QUEUE_INFO *qi;
464        int q;
465
466        AH9300(ah)->ah_fccaifs = 0;
467        HALDEBUG(ah, HAL_DEBUG_DFS, "%s: restore DIFS \n", __func__);
468        for (q = 0; q < 4; q++) {
469            qi = &ahp->ah_txq[q];
470            OS_REG_WRITE(ah, AR_DLCL_IFS(q),
471                    SM(qi->tqi_cwmin, AR_D_LCL_IFS_CWMIN)
472                    | SM(qi->tqi_cwmax, AR_D_LCL_IFS_CWMAX)
473                    | SM(qi->tqi_aifs, AR_D_LCL_IFS_AIFS));
474        }
475    } else {
476        /*
477         * These are values from George Lai and are specific to
478         * FCC domain. They are yet to be determined for other domains.
479         */
480
481        AH9300(ah)->ah_fccaifs = 1;
482        HALDEBUG(ah, HAL_DEBUG_DFS, "%s: set DIFS to default\n", __func__);
483        /*printk("%s:  modify DIFS\n", __func__);*/
484
485        OS_REG_WRITE(ah, AR_DLCL_IFS(0), 0x05fffc0f);
486        OS_REG_WRITE(ah, AR_DLCL_IFS(1), 0x05f0fc0f);
487        OS_REG_WRITE(ah, AR_DLCL_IFS(2), 0x05f03c07);
488        OS_REG_WRITE(ah, AR_DLCL_IFS(3), 0x05f01c03);
489    }
490}
491
492u_int32_t ar9300_dfs_config_fft(struct ath_hal *ah, HAL_BOOL is_enable)
493{
494    u_int32_t val;
495
496    val = OS_REG_READ(ah, AR_PHY_RADAR_0);
497
498    if (is_enable) {
499        val |= AR_PHY_RADAR_0_FFT_ENA;
500    } else {
501        val &= ~AR_PHY_RADAR_0_FFT_ENA;
502    }
503
504    OS_REG_WRITE(ah, AR_PHY_RADAR_0, val);
505    val = OS_REG_READ(ah, AR_PHY_RADAR_0);
506    return val;
507}
508/*
509    function to adjust PRSSI value for CAC problem
510
511*/
512void
513ar9300_dfs_cac_war(struct ath_hal *ah, u_int32_t start)
514{
515    u_int32_t val;
516
517    if (AR_SREV_AR9580(ah) || AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) {
518        val = OS_REG_READ(ah, AR_PHY_RADAR_0);
519        if (start) {
520            val &= ~AR_PHY_RADAR_0_PRSSI;
521            val |= SM(AR9300_DFS_PRSSI_CAC, AR_PHY_RADAR_0_PRSSI);
522        } else {
523            val &= ~AR_PHY_RADAR_0_PRSSI;
524            val |= SM(AR9300_DFS_PRSSI, AR_PHY_RADAR_0_PRSSI);
525        }
526        OS_REG_WRITE(ah, AR_PHY_RADAR_0, val | AR_PHY_RADAR_0_ENA);
527//        ah->ah_use_cac_prssi = start;
528    }
529}
530
531#if 0
532struct ieee80211_channel *
533ar9300_get_extension_channel(struct ath_hal *ah)
534{
535    struct ath_hal_private  *ahp = AH_PRIVATE(ah);
536    struct ath_hal_private_tables  *aht = AH_TABLES(ah);
537    int i = 0;
538
539    HAL_CHANNEL_INTERNAL *ichan = AH_NULL;
540    CHAN_CENTERS centers;
541
542    ichan = ahp->ah_curchan;
543    ar9300_get_channel_centers(ah, ichan, &centers);
544    if (centers.ctl_center == centers.ext_center) {
545        return AH_NULL;
546    }
547    for (i = 0; i < ahp->ah_nchan; i++) {
548        ichan = &aht->ah_channels[i];
549        if (ichan->channel == centers.ext_center) {
550            return (struct ieee80211_channel*)ichan;
551        }
552    }
553    return AH_NULL;
554}
555#endif
556
557HAL_BOOL
558ar9300_is_fast_clock_enabled(struct ath_hal *ah)
559{
560    struct ath_hal_private *ahp = AH_PRIVATE(ah);
561
562    if (IS_5GHZ_FAST_CLOCK_EN(ah, ahp->ah_curchan)) {
563        return AH_TRUE;
564    }
565    return AH_FALSE;
566}
567
568/*
569 * This should be enabled and linked into the build once
570 * radar support is enabled.
571 */
572#if 0
573HAL_BOOL
574ar9300_handle_radar_bb_panic(struct ath_hal *ah)
575{
576    u_int32_t status;
577    u_int32_t val;
578#ifdef AH_DEBUG
579    struct ath_hal_9300 *ahp = AH9300(ah);
580#endif
581
582    status = AH_PRIVATE(ah)->ah_bb_panic_last_status;
583
584    if ( status == 0x04000539 ) {
585        /* recover from this BB panic without reset*/
586        /* set AR9300_DFS_FIRPWR to -1 */
587        val = OS_REG_READ(ah, AR_PHY_RADAR_0);
588        val &= (~AR_PHY_RADAR_0_FIRPWR);
589        val |= SM( 0x7f, AR_PHY_RADAR_0_FIRPWR);
590        OS_REG_WRITE(ah, AR_PHY_RADAR_0, val);
591        OS_DELAY(1);
592        /* set AR9300_DFS_FIRPWR to its default value */
593        val = OS_REG_READ(ah, AR_PHY_RADAR_0);
594        val &= ~AR_PHY_RADAR_0_FIRPWR;
595        val |= SM( AR9300_DFS_FIRPWR, AR_PHY_RADAR_0_FIRPWR);
596        OS_REG_WRITE(ah, AR_PHY_RADAR_0, val);
597        return AH_TRUE;
598    } else if (status == 0x0400000a) {
599        /* EV 92527 : reset required if we see this signature */
600        HALDEBUG(ah, HAL_DEBUG_DFS, "%s: BB Panic -- 0x0400000a\n", __func__);
601        return AH_FALSE;
602    } else if (status == 0x1300000a) {
603        /* EV92527: we do not need a reset if we see this signature */
604        HALDEBUG(ah, HAL_DEBUG_DFS, "%s: BB Panic -- 0x1300000a\n", __func__);
605        return AH_TRUE;
606    } else if ((AR_SREV_WASP(ah) || AR_SREV_HONEYBEE(ah)) && (status == 0x04000409)) {
607        return AH_TRUE;
608    } else {
609        if (ar9300_get_capability(ah, HAL_CAP_LDPCWAR, 0, AH_NULL) == HAL_OK &&
610            (status & 0xff00000f) == 0x04000009 &&
611            status != 0x04000409 &&
612            status != 0x04000b09 &&
613            status != 0x04000e09 &&
614            (status & 0x0000ff00))
615        {
616            /* disable RIFS Rx */
617#ifdef AH_DEBUG
618            HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "%s: BB status=0x%08x rifs=%d - disable\n",
619                     __func__, status, ahp->ah_rifs_enabled);
620            ar9300_set_rifs_delay(ah, AH_FALSE);
621        }
622        return AH_FALSE;
623    }
624}
625#endif
626#endif
627