1250003Sadrian/*
2250003Sadrian * Copyright (c) 2013 Qualcomm Atheros, Inc.
3250003Sadrian *
4250003Sadrian * Permission to use, copy, modify, and/or distribute this software for any
5250003Sadrian * purpose with or without fee is hereby granted, provided that the above
6250003Sadrian * copyright notice and this permission notice appear in all copies.
7250003Sadrian *
8250003Sadrian * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
9250003Sadrian * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10250003Sadrian * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
11250003Sadrian * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12250003Sadrian * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
13250003Sadrian * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14250003Sadrian * PERFORMANCE OF THIS SOFTWARE.
15250003Sadrian */
16250003Sadrian
17250003Sadrian
18250003Sadrian#include "opt_ah.h"
19250003Sadrian
20250003Sadrian#include "ah.h"
21250003Sadrian#include "ah_desc.h"
22250003Sadrian#include "ah_internal.h"
23250003Sadrian
24250003Sadrian#include "ar9300/ar9300.h"
25250003Sadrian#include "ar9300/ar9300phy.h"
26250003Sadrian#include "ar9300/ar9300reg.h"
27250003Sadrian
28250003Sadrian/*
29250003Sadrian * Default 5413/9300 radar phy parameters
30250003Sadrian * Values adjusted to fix EV76432/EV76320
31250003Sadrian */
32250003Sadrian#define AR9300_DFS_FIRPWR   -28
33250003Sadrian#define AR9300_DFS_RRSSI    0
34250003Sadrian#define AR9300_DFS_HEIGHT   10
35250003Sadrian#define AR9300_DFS_PRSSI    6
36250003Sadrian#define AR9300_DFS_INBAND   8
37250003Sadrian#define AR9300_DFS_RELPWR   8
38250003Sadrian#define AR9300_DFS_RELSTEP  12
39250003Sadrian#define AR9300_DFS_MAXLEN   255
40250008Sadrian
41250008Sadrian/*
42250008Sadrian * This PRSSI value should be used during CAC.
43250008Sadrian */
44250003Sadrian#define AR9300_DFS_PRSSI_CAC 10
45250003Sadrian
46250003Sadrian/*
47250003Sadrian *  make sure that value matches value in ar9300_osprey_2p2_mac_core[][2]
48250003Sadrian *  for register 0x1040 to 0x104c
49250003Sadrian*/
50250003Sadrian#define AR9300_DEFAULT_DIFS     0x002ffc0f
51250003Sadrian#define AR9300_FCC_RADARS_FCC_OFFSET 4
52250003Sadrian
53250003Sadrianstruct dfs_pulse ar9300_etsi_radars[] = {
54250003Sadrian
55250003Sadrian    /* for short pulses, RSSI threshold should be smaller than
56250003Sadrian * Kquick-drop. The chip has only one chance to drop the gain which
57250003Sadrian * will be reported as the estimated RSSI */
58250003Sadrian
59250003Sadrian    /* TYPE staggered pulse */
60250003Sadrian    /* 0.8-2us, 2-3 bursts,300-400 PRF, 10 pulses each */
61250003Sadrian    {30,  2,  300,  400, 2, 30,  3,  0,  5, 15, 0,   0, 1, 31},   /* Type 5*/
62250003Sadrian    /* 0.8-2us, 2-3 bursts, 400-1200 PRF, 15 pulses each */
63250003Sadrian    {30,  2,  400, 1200, 2, 30,  7,  0,  5, 15, 0,   0, 0, 32},   /* Type 6 */
64250003Sadrian
65250003Sadrian    /* constant PRF based */
66250003Sadrian    /* 0.8-5us, 200  300 PRF, 10 pulses */
67250003Sadrian    {10, 5,   200,  400, 0, 24,  5,  0,  8, 15, 0,   0, 2, 33},   /* Type 1 */
68250003Sadrian    {10, 5,   400,  600, 0, 24,  5,  0,  8, 15, 0,   0, 2, 37},   /* Type 1 */
69250003Sadrian    {10, 5,   600,  800, 0, 24,  5,  0,  8, 15, 0,   0, 2, 38},   /* Type 1 */
70250003Sadrian    {10, 5,   800, 1000, 0, 24,  5,  0,  8, 15, 0,   0, 2, 39},   /* Type 1 */
71250003Sadrian//  {10, 5,   200, 1000, 0, 24,  5,  0,  8, 15, 0,   0, 2, 33},
72250003Sadrian
73250003Sadrian    /* 0.8-15us, 200-1600 PRF, 15 pulses */
74250003Sadrian    {15, 15,  200, 1600, 0, 24, 8,  0, 18, 24, 0,   0, 0, 34},    /* Type 2 */
75250003Sadrian
76250003Sadrian    /* 0.8-15us, 2300-4000 PRF, 25 pulses*/
77250003Sadrian    {25, 15, 2300, 4000,  0, 24, 10, 0, 18, 24, 0,   0, 0, 35},   /* Type 3 */
78250003Sadrian
79250003Sadrian    /* 20-30us, 2000-4000 PRF, 20 pulses*/
80250003Sadrian    {20, 30, 2000, 4000, 0, 24, 8, 19, 33, 24, 0,   0, 0, 36},    /* Type 4 */
81250003Sadrian};
82250003Sadrian
83250003Sadrian
84250003Sadrian/* The following are for FCC Bin 1-4 pulses */
85250003Sadrianstruct dfs_pulse ar9300_fcc_radars[] = {
86250003Sadrian
87250003Sadrian    /* following two filters are specific to Japan/MKK4 */
88250003Sadrian//  {18,  1,  720,  720, 1,  6,  6,  0,  1, 18,  0, 3, 0, 17}, // 1389 +/- 6 us
89250003Sadrian//  {18,  4,  250,  250, 1, 10,  5,  1,  6, 18,  0, 3, 0, 18}, // 4000 +/- 6 us
90250003Sadrian//  {18,  5,  260,  260, 1, 10,  6,  1,  6, 18,  0, 3, 0, 19}, // 3846 +/- 7 us
91250003Sadrian    {18,  1,  720,  720, 0,  6,  6,  0,  1, 18,  0, 3, 0, 17}, // 1389 +/- 6 us
92250003Sadrian    {18,  4,  250,  250, 0, 10,  5,  1,  6, 18,  0, 3, 0, 18}, // 4000 +/- 6 us
93250003Sadrian    {18,  5,  260,  260, 0, 10,  6,  1,  6, 18,  0, 3, 1, 19}, // 3846 +/- 7 us
94250003Sadrian//  {18,  5,  260,  260, 1, 10,  6,  1,  6, 18,  0, 3, 1, 20}, // 3846 +/- 7 us
95250003Sadrian
96250003Sadrian   {18, 5, 260, 260, 1, 10, 6, 1, 6, 18, 0, 3, 1, 20}, // 3846 +/- 7 us
97250003Sadrian
98250003Sadrian
99250003Sadrian    /* following filters are common to both FCC and JAPAN */
100250003Sadrian
101250003Sadrian    // FCC TYPE 1
102250003Sadrian    // {18,  1,  325, 1930, 0,  6,  7,  0,  1, 18,  0, 3, 0, 0}, // 518 to 3066
103250003Sadrian    {18,  1,  700, 700, 0,  6,  5,  0,  1, 18,  0, 3, 1, 8},
104250003Sadrian    {18,  1,  350, 350, 0,  6,  5,  0,  1, 18,  0, 3, 0, 0},
105250003Sadrian
106250003Sadrian
107250003Sadrian    // FCC TYPE 6
108250003Sadrian    // {9,   1, 3003, 3003, 1,  7,  5,  0,  1, 18,  0, 0, 0, 1}, // 333 +/- 7 us
109250003Sadrian    //{9,   1, 3003, 3003, 1,  7,  5,  0,  1, 18,  0, 0, 0, 1},
110250003Sadrian    {9,   1, 3003, 3003, 0,  7,  5,  0,  1, 18,  0, 0, 1, 1},
111250003Sadrian
112250003Sadrian    // FCC TYPE 2
113250003Sadrian    {23, 5, 4347, 6666, 0, 18, 11,  0,  7, 22,  0, 3, 0, 2},
114250003Sadrian
115250003Sadrian    // FCC TYPE 3
116250003Sadrian    {18, 10, 2000, 5000, 0, 23,  8,  6, 13, 22,  0, 3, 0, 5},
117250003Sadrian
118250003Sadrian    // FCC TYPE 4
119250003Sadrian    {16, 15, 2000, 5000, 0, 25,  7, 11, 23, 22,  0, 3, 0, 11},
120250003Sadrian
121250003Sadrian};
122250003Sadrian
123250003Sadrianstruct dfs_bin5pulse ar9300_bin5pulses[] = {
124250003Sadrian        {2, 28, 105, 12, 22, 5},
125250003Sadrian};
126250003Sadrian
127250003Sadrian
128250008Sadrian#if 0
129250003Sadrian/*
130250003Sadrian * Find the internal HAL channel corresponding to the
131250003Sadrian * public HAL channel specified in c
132250003Sadrian */
133250003Sadrian
134250003Sadrianstatic HAL_CHANNEL_INTERNAL *
135250008Sadriangetchannel(struct ath_hal *ah, const struct ieee80211_channel *c)
136250003Sadrian{
137250003Sadrian#define CHAN_FLAGS    (CHANNEL_ALL | CHANNEL_HALF | CHANNEL_QUARTER)
138250003Sadrian    HAL_CHANNEL_INTERNAL *base, *cc;
139250003Sadrian    int flags = c->channel_flags & CHAN_FLAGS;
140250003Sadrian    int n, lim;
141250003Sadrian
142250003Sadrian    /*
143250003Sadrian     * Check current channel to avoid the lookup.
144250003Sadrian     */
145250003Sadrian    cc = AH_PRIVATE(ah)->ah_curchan;
146250003Sadrian    if (cc != AH_NULL && cc->channel == c->channel &&
147250003Sadrian        (cc->channel_flags & CHAN_FLAGS) == flags) {
148250003Sadrian        return cc;
149250003Sadrian    }
150250003Sadrian
151250003Sadrian    /* binary search based on known sorting order */
152250003Sadrian    base = AH_TABLES(ah)->ah_channels;
153250003Sadrian    n = AH_PRIVATE(ah)->ah_nchan;
154250003Sadrian    /* binary search based on known sorting order */
155250003Sadrian    for (lim = n; lim != 0; lim >>= 1) {
156250003Sadrian        int d;
157250003Sadrian        cc = &base[lim >> 1];
158250003Sadrian        d = c->channel - cc->channel;
159250003Sadrian        if (d == 0) {
160250003Sadrian            if ((cc->channel_flags & CHAN_FLAGS) == flags) {
161250003Sadrian                return cc;
162250003Sadrian            }
163250003Sadrian            d = flags - (cc->channel_flags & CHAN_FLAGS);
164250003Sadrian        }
165250003Sadrian        HALDEBUG(ah, HAL_DEBUG_DFS, "%s: channel %u/0x%x d %d\n", __func__,
166250003Sadrian                cc->channel, cc->channel_flags, d);
167250003Sadrian        if (d > 0) {
168250003Sadrian            base = cc + 1;
169250003Sadrian            lim--;
170250003Sadrian        }
171250003Sadrian    }
172250003Sadrian    HALDEBUG(ah, HAL_DEBUG_DFS, "%s: no match for %u/0x%x\n",
173250003Sadrian            __func__, c->channel, c->channel_flags);
174250003Sadrian    return AH_NULL;
175250003Sadrian#undef CHAN_FLAGS
176250003Sadrian}
177250003Sadrian
178250003Sadrian/*
179250003Sadrian * Check the internal channel list to see if the desired channel
180250003Sadrian * is ok to release from the NOL.  If not, then do nothing.  If so,
181250003Sadrian * mark the channel as clear and reset the internal tsf time
182250003Sadrian */
183250003Sadrianvoid
184250008Sadrianar9300_check_dfs(struct ath_hal *ah, struct ieee80211_channel *chan)
185250003Sadrian{
186250003Sadrian    HAL_CHANNEL_INTERNAL *ichan = AH_NULL;
187250003Sadrian
188250003Sadrian    ichan = getchannel(ah, chan);
189250003Sadrian    if (ichan == AH_NULL) {
190250003Sadrian        return;
191250003Sadrian    }
192250003Sadrian    if (!(ichan->priv_flags & CHANNEL_INTERFERENCE)) {
193250003Sadrian        return;
194250003Sadrian    }
195250003Sadrian
196250003Sadrian    ichan->priv_flags &= ~CHANNEL_INTERFERENCE;
197250003Sadrian    ichan->dfs_tsf = 0;
198250003Sadrian}
199250003Sadrian
200250003Sadrian/*
201250003Sadrian * This function marks the channel as having found a dfs event
202250003Sadrian * It also marks the end time that the dfs event should be cleared
203250003Sadrian * If the channel is already marked, then tsf end time can only
204250003Sadrian * be increased
205250003Sadrian */
206250003Sadrianvoid
207250008Sadrianar9300_dfs_found(struct ath_hal *ah, struct ieee80211_channel *chan, u_int64_t nol_time)
208250003Sadrian{
209250003Sadrian    HAL_CHANNEL_INTERNAL *ichan;
210250003Sadrian
211250003Sadrian    ichan = getchannel(ah, chan);
212250003Sadrian    if (ichan == AH_NULL) {
213250003Sadrian        return;
214250003Sadrian    }
215250003Sadrian    if (!(ichan->priv_flags & CHANNEL_INTERFERENCE)) {
216250003Sadrian        ichan->dfs_tsf = ar9300_get_tsf64(ah);
217250003Sadrian    }
218250003Sadrian    ichan->dfs_tsf += nol_time;
219250003Sadrian    ichan->priv_flags |= CHANNEL_INTERFERENCE;
220250003Sadrian    chan->priv_flags |= CHANNEL_INTERFERENCE;
221250003Sadrian}
222250008Sadrian#endif
223250003Sadrian
224250003Sadrian/*
225250003Sadrian * Enable radar detection and set the radar parameters per the
226250003Sadrian * values in pe
227250003Sadrian */
228250003Sadrianvoid
229250003Sadrianar9300_enable_dfs(struct ath_hal *ah, HAL_PHYERR_PARAM *pe)
230250003Sadrian{
231250003Sadrian    u_int32_t val;
232250003Sadrian    struct ath_hal_private  *ahp = AH_PRIVATE(ah);
233250008Sadrian    const struct ieee80211_channel *chan = ahp->ah_curchan;
234250003Sadrian    struct ath_hal_9300 *ah9300 = AH9300(ah);
235250003Sadrian    int reg_writes = 0;
236250003Sadrian
237250003Sadrian    val = OS_REG_READ(ah, AR_PHY_RADAR_0);
238250003Sadrian    val |= AR_PHY_RADAR_0_FFT_ENA | AR_PHY_RADAR_0_ENA;
239250003Sadrian    if (pe->pe_firpwr != HAL_PHYERR_PARAM_NOVAL) {
240250003Sadrian        val &= ~AR_PHY_RADAR_0_FIRPWR;
241250003Sadrian        val |= SM(pe->pe_firpwr, AR_PHY_RADAR_0_FIRPWR);
242250003Sadrian    }
243250003Sadrian    if (pe->pe_rrssi != HAL_PHYERR_PARAM_NOVAL) {
244250003Sadrian        val &= ~AR_PHY_RADAR_0_RRSSI;
245250003Sadrian        val |= SM(pe->pe_rrssi, AR_PHY_RADAR_0_RRSSI);
246250003Sadrian    }
247250003Sadrian    if (pe->pe_height != HAL_PHYERR_PARAM_NOVAL) {
248250003Sadrian        val &= ~AR_PHY_RADAR_0_HEIGHT;
249250003Sadrian        val |= SM(pe->pe_height, AR_PHY_RADAR_0_HEIGHT);
250250003Sadrian    }
251250003Sadrian    if (pe->pe_prssi != HAL_PHYERR_PARAM_NOVAL) {
252250003Sadrian        val &= ~AR_PHY_RADAR_0_PRSSI;
253250003Sadrian        if (AR_SREV_AR9580(ah) || AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) {
254250008Sadrian#if 0
255250003Sadrian            if (ah->ah_use_cac_prssi) {
256250003Sadrian                val |= SM(AR9300_DFS_PRSSI_CAC, AR_PHY_RADAR_0_PRSSI);
257250003Sadrian            } else {
258250008Sadrian#endif
259250003Sadrian                val |= SM(pe->pe_prssi, AR_PHY_RADAR_0_PRSSI);
260250008Sadrian//            }
261250003Sadrian        } else {
262250003Sadrian            val |= SM(pe->pe_prssi, AR_PHY_RADAR_0_PRSSI);
263250003Sadrian        }
264250003Sadrian    }
265250003Sadrian    if (pe->pe_inband != HAL_PHYERR_PARAM_NOVAL) {
266250003Sadrian        val &= ~AR_PHY_RADAR_0_INBAND;
267250003Sadrian        val |= SM(pe->pe_inband, AR_PHY_RADAR_0_INBAND);
268250003Sadrian    }
269250003Sadrian    OS_REG_WRITE(ah, AR_PHY_RADAR_0, val);
270250003Sadrian
271250003Sadrian    val = OS_REG_READ(ah, AR_PHY_RADAR_1);
272250003Sadrian    val |= AR_PHY_RADAR_1_MAX_RRSSI | AR_PHY_RADAR_1_BLOCK_CHECK;
273250003Sadrian    if (pe->pe_maxlen != HAL_PHYERR_PARAM_NOVAL) {
274250003Sadrian        val &= ~AR_PHY_RADAR_1_MAXLEN;
275250003Sadrian        val |= SM(pe->pe_maxlen, AR_PHY_RADAR_1_MAXLEN);
276250003Sadrian    }
277250003Sadrian    if (pe->pe_relstep != HAL_PHYERR_PARAM_NOVAL) {
278250003Sadrian        val &= ~AR_PHY_RADAR_1_RELSTEP_THRESH;
279250003Sadrian        val |= SM(pe->pe_relstep, AR_PHY_RADAR_1_RELSTEP_THRESH);
280250003Sadrian    }
281250003Sadrian    if (pe->pe_relpwr != HAL_PHYERR_PARAM_NOVAL) {
282250003Sadrian        val &= ~AR_PHY_RADAR_1_RELPWR_THRESH;
283250003Sadrian        val |= SM(pe->pe_relpwr, AR_PHY_RADAR_1_RELPWR_THRESH);
284250003Sadrian    }
285250003Sadrian    OS_REG_WRITE(ah, AR_PHY_RADAR_1, val);
286250003Sadrian
287250003Sadrian    if (ath_hal_getcapability(ah, HAL_CAP_EXT_CHAN_DFS, 0, 0) == HAL_OK) {
288250003Sadrian        val = OS_REG_READ(ah, AR_PHY_RADAR_EXT);
289250008Sadrian        if (IEEE80211_IS_CHAN_HT40(chan)) {
290250003Sadrian            /* Enable extension channel radar detection */
291250003Sadrian            OS_REG_WRITE(ah, AR_PHY_RADAR_EXT, val | AR_PHY_RADAR_EXT_ENA);
292250003Sadrian        } else {
293250003Sadrian            /* HT20 mode, disable extension channel radar detect */
294250003Sadrian            OS_REG_WRITE(ah, AR_PHY_RADAR_EXT, val & ~AR_PHY_RADAR_EXT_ENA);
295250003Sadrian        }
296250003Sadrian    }
297250003Sadrian    /*
298250003Sadrian        apply DFS postamble array from INI
299250003Sadrian        column 0 is register ID, column 1 is  HT20 value, colum2 is HT40 value
300250003Sadrian    */
301250003Sadrian
302250003Sadrian    if (AR_SREV_AR9580(ah) || AR_SREV_WASP(ah) || AR_SREV_OSPREY_22(ah) || AR_SREV_SCORPION(ah)) {
303250008Sadrian        REG_WRITE_ARRAY(&ah9300->ah_ini_dfs, IEEE80211_IS_CHAN_HT40(chan)? 2:1, reg_writes);
304250003Sadrian    }
305250003Sadrian#ifdef ATH_HAL_DFS_CHIRPING_FIX_APH128
306250008Sadrian    ath_hal_printf(ah, "DFS change the timing value\n");
307250008Sadrian    if (AR_SREV_AR9580(ah) && IEEE80211_IS_CHAN_HT40(chan)) {
308250008Sadrian        OS_REG_WRITE(ah, AR_PHY_TIMING6, 0x3140c00a);
309250003Sadrian    }
310250003Sadrian#endif
311250003Sadrian
312250003Sadrian}
313250003Sadrian
314250003Sadrian/*
315250003Sadrian * Get the radar parameter values and return them in the pe
316250003Sadrian * structure
317250003Sadrian */
318250003Sadrianvoid
319250003Sadrianar9300_get_dfs_thresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe)
320250003Sadrian{
321250003Sadrian    u_int32_t val, temp;
322250003Sadrian
323250003Sadrian    val = OS_REG_READ(ah, AR_PHY_RADAR_0);
324250003Sadrian    temp = MS(val, AR_PHY_RADAR_0_FIRPWR);
325250003Sadrian    temp |= ~(AR_PHY_RADAR_0_FIRPWR >> AR_PHY_RADAR_0_FIRPWR_S);
326250003Sadrian    pe->pe_firpwr = temp;
327250003Sadrian    pe->pe_rrssi = MS(val, AR_PHY_RADAR_0_RRSSI);
328250003Sadrian    pe->pe_height = MS(val, AR_PHY_RADAR_0_HEIGHT);
329250003Sadrian    pe->pe_prssi = MS(val, AR_PHY_RADAR_0_PRSSI);
330250003Sadrian    pe->pe_inband = MS(val, AR_PHY_RADAR_0_INBAND);
331250003Sadrian
332250003Sadrian    val = OS_REG_READ(ah, AR_PHY_RADAR_1);
333250003Sadrian
334250003Sadrian    pe->pe_relpwr = MS(val, AR_PHY_RADAR_1_RELPWR_THRESH);
335250008Sadrian    pe->pe_enrelpwr = !! (val & AR_PHY_RADAR_1_RELPWR_ENA);
336250008Sadrian
337250003Sadrian    pe->pe_relstep = MS(val, AR_PHY_RADAR_1_RELSTEP_THRESH);
338250008Sadrian    pe->pe_en_relstep_check = !! (val & AR_PHY_RADAR_1_RELSTEP_CHECK);
339250008Sadrian
340250003Sadrian    pe->pe_maxlen = MS(val, AR_PHY_RADAR_1_MAXLEN);
341250003Sadrian}
342250003Sadrian
343250008Sadrian#if 0
344250003SadrianHAL_BOOL
345250008Sadrianar9300_radar_wait(struct ath_hal *ah, struct ieee80211_channel *chan)
346250003Sadrian{
347250003Sadrian    struct ath_hal_private *ahp = AH_PRIVATE(ah);
348250003Sadrian
349250003Sadrian    if (!ahp->ah_curchan) {
350250003Sadrian        return AH_TRUE;
351250003Sadrian    }
352250003Sadrian
353250003Sadrian    /*
354250003Sadrian     * Rely on the upper layers to determine that we have spent
355250003Sadrian     * enough time waiting.
356250003Sadrian     */
357250003Sadrian    chan->channel = ahp->ah_curchan->channel;
358250003Sadrian    chan->channel_flags = ahp->ah_curchan->channel_flags;
359250003Sadrian    chan->max_reg_tx_power = ahp->ah_curchan->max_reg_tx_power;
360250003Sadrian
361250003Sadrian    ahp->ah_curchan->priv_flags |= CHANNEL_DFS_CLEAR;
362250003Sadrian    chan->priv_flags  = ahp->ah_curchan->priv_flags;
363250003Sadrian    return AH_FALSE;
364250003Sadrian
365250003Sadrian}
366250008Sadrian#endif
367250003Sadrian
368250003Sadrianstruct dfs_pulse *
369250003Sadrianar9300_get_dfs_radars(
370250003Sadrian    struct ath_hal *ah,
371250003Sadrian    u_int32_t dfsdomain,
372250003Sadrian    int *numradars,
373250003Sadrian    struct dfs_bin5pulse **bin5pulses,
374250003Sadrian    int *numb5radars,
375250003Sadrian    HAL_PHYERR_PARAM *pe)
376250003Sadrian{
377250003Sadrian    struct dfs_pulse *dfs_radars = AH_NULL;
378250003Sadrian    switch (dfsdomain) {
379250008Sadrian    case HAL_DFS_FCC_DOMAIN:
380250003Sadrian        dfs_radars = &ar9300_fcc_radars[AR9300_FCC_RADARS_FCC_OFFSET];
381250003Sadrian        *numradars =
382250003Sadrian            ARRAY_LENGTH(ar9300_fcc_radars) - AR9300_FCC_RADARS_FCC_OFFSET;
383250003Sadrian        *bin5pulses = &ar9300_bin5pulses[0];
384250003Sadrian        *numb5radars = ARRAY_LENGTH(ar9300_bin5pulses);
385250003Sadrian        HALDEBUG(ah, HAL_DEBUG_DFS, "%s: DFS_FCC_DOMAIN_9300\n", __func__);
386250003Sadrian        break;
387250008Sadrian    case HAL_DFS_ETSI_DOMAIN:
388250003Sadrian        dfs_radars = &ar9300_etsi_radars[0];
389250003Sadrian        *numradars = ARRAY_LENGTH(ar9300_etsi_radars);
390250003Sadrian        *bin5pulses = &ar9300_bin5pulses[0];
391250003Sadrian        *numb5radars = ARRAY_LENGTH(ar9300_bin5pulses);
392250003Sadrian        HALDEBUG(ah, HAL_DEBUG_DFS, "%s: DFS_ETSI_DOMAIN_9300\n", __func__);
393250003Sadrian        break;
394250008Sadrian    case HAL_DFS_MKK4_DOMAIN:
395250003Sadrian        dfs_radars = &ar9300_fcc_radars[0];
396250003Sadrian        *numradars = ARRAY_LENGTH(ar9300_fcc_radars);
397250003Sadrian        *bin5pulses = &ar9300_bin5pulses[0];
398250003Sadrian        *numb5radars = ARRAY_LENGTH(ar9300_bin5pulses);
399250003Sadrian        HALDEBUG(ah, HAL_DEBUG_DFS, "%s: DFS_MKK4_DOMAIN_9300\n", __func__);
400250003Sadrian        break;
401250003Sadrian    default:
402250003Sadrian        HALDEBUG(ah, HAL_DEBUG_DFS, "%s: no domain\n", __func__);
403250003Sadrian        return AH_NULL;
404250003Sadrian    }
405250003Sadrian    /* Set the default phy parameters per chip */
406250003Sadrian    pe->pe_firpwr = AR9300_DFS_FIRPWR;
407250003Sadrian    pe->pe_rrssi = AR9300_DFS_RRSSI;
408250003Sadrian    pe->pe_height = AR9300_DFS_HEIGHT;
409250003Sadrian    pe->pe_prssi = AR9300_DFS_PRSSI;
410250003Sadrian    /*
411250003Sadrian        we have an issue with PRSSI.
412250003Sadrian        For normal operation we use AR9300_DFS_PRSSI, which is set to 6.
413250003Sadrian        Please refer to EV91563, 94164.
414250003Sadrian        However, this causes problem during CAC as no radar is detected
415250003Sadrian        during that period with PRSSI=6. Only PRSSI= 10 seems to fix this.
416250003Sadrian        We use this flag to keep track of change in PRSSI.
417250003Sadrian    */
418250003Sadrian
419250008Sadrian//    ah->ah_use_cac_prssi = 0;
420250003Sadrian
421250003Sadrian    pe->pe_inband = AR9300_DFS_INBAND;
422250003Sadrian    pe->pe_relpwr = AR9300_DFS_RELPWR;
423250003Sadrian    pe->pe_relstep = AR9300_DFS_RELSTEP;
424250003Sadrian    pe->pe_maxlen = AR9300_DFS_MAXLEN;
425250003Sadrian    return dfs_radars;
426250003Sadrian}
427250003Sadrian
428250003Sadrianvoid ar9300_adjust_difs(struct ath_hal *ah, u_int32_t val)
429250003Sadrian{
430250003Sadrian    if (val == 0) {
431250003Sadrian        /*
432250003Sadrian         * EV 116936:
433250003Sadrian         * Restore the register values with that of the HAL structure.
434250003Sadrian         * Do not assume and overwrite these values to whatever
435250003Sadrian         * is in ar9300_osprey22.ini.
436250003Sadrian         */
437250003Sadrian        struct ath_hal_9300 *ahp = AH9300(ah);
438250003Sadrian        HAL_TX_QUEUE_INFO *qi;
439250003Sadrian        int q;
440250003Sadrian
441250008Sadrian        AH9300(ah)->ah_fccaifs = 0;
442250003Sadrian        HALDEBUG(ah, HAL_DEBUG_DFS, "%s: restore DIFS \n", __func__);
443250003Sadrian        for (q = 0; q < 4; q++) {
444250003Sadrian            qi = &ahp->ah_txq[q];
445250003Sadrian            OS_REG_WRITE(ah, AR_DLCL_IFS(q),
446250003Sadrian                    SM(qi->tqi_cwmin, AR_D_LCL_IFS_CWMIN)
447250003Sadrian                    | SM(qi->tqi_cwmax, AR_D_LCL_IFS_CWMAX)
448250003Sadrian                    | SM(qi->tqi_aifs, AR_D_LCL_IFS_AIFS));
449250003Sadrian        }
450250003Sadrian    } else {
451250003Sadrian        /*
452250003Sadrian         * These are values from George Lai and are specific to
453250003Sadrian         * FCC domain. They are yet to be determined for other domains.
454250003Sadrian         */
455250003Sadrian
456250008Sadrian        AH9300(ah)->ah_fccaifs = 1;
457250003Sadrian        HALDEBUG(ah, HAL_DEBUG_DFS, "%s: set DIFS to default\n", __func__);
458250003Sadrian        /*printk("%s:  modify DIFS\n", __func__);*/
459250003Sadrian
460250003Sadrian        OS_REG_WRITE(ah, AR_DLCL_IFS(0), 0x05fffc0f);
461250003Sadrian        OS_REG_WRITE(ah, AR_DLCL_IFS(1), 0x05f0fc0f);
462250003Sadrian        OS_REG_WRITE(ah, AR_DLCL_IFS(2), 0x05f03c07);
463250003Sadrian        OS_REG_WRITE(ah, AR_DLCL_IFS(3), 0x05f01c03);
464250003Sadrian    }
465250003Sadrian}
466250003Sadrian
467250003Sadrianu_int32_t ar9300_dfs_config_fft(struct ath_hal *ah, HAL_BOOL is_enable)
468250003Sadrian{
469250003Sadrian    u_int32_t val;
470250003Sadrian
471250003Sadrian    val = OS_REG_READ(ah, AR_PHY_RADAR_0);
472250003Sadrian
473250003Sadrian    if (is_enable) {
474250003Sadrian        val |= AR_PHY_RADAR_0_FFT_ENA;
475250003Sadrian    } else {
476250003Sadrian        val &= ~AR_PHY_RADAR_0_FFT_ENA;
477250003Sadrian    }
478250003Sadrian
479250003Sadrian    OS_REG_WRITE(ah, AR_PHY_RADAR_0, val);
480250003Sadrian    val = OS_REG_READ(ah, AR_PHY_RADAR_0);
481250003Sadrian    return val;
482250003Sadrian}
483250003Sadrian/*
484250003Sadrian    function to adjust PRSSI value for CAC problem
485250003Sadrian
486250003Sadrian*/
487250003Sadrianvoid
488250003Sadrianar9300_dfs_cac_war(struct ath_hal *ah, u_int32_t start)
489250003Sadrian{
490250003Sadrian    u_int32_t val;
491250003Sadrian
492250003Sadrian    if (AR_SREV_AR9580(ah) || AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) {
493250003Sadrian        val = OS_REG_READ(ah, AR_PHY_RADAR_0);
494250003Sadrian        if (start) {
495250003Sadrian            val &= ~AR_PHY_RADAR_0_PRSSI;
496250003Sadrian            val |= SM(AR9300_DFS_PRSSI_CAC, AR_PHY_RADAR_0_PRSSI);
497250003Sadrian        } else {
498250003Sadrian            val &= ~AR_PHY_RADAR_0_PRSSI;
499250003Sadrian            val |= SM(AR9300_DFS_PRSSI, AR_PHY_RADAR_0_PRSSI);
500250003Sadrian        }
501250003Sadrian        OS_REG_WRITE(ah, AR_PHY_RADAR_0, val | AR_PHY_RADAR_0_ENA);
502250008Sadrian//        ah->ah_use_cac_prssi = start;
503250003Sadrian    }
504250003Sadrian}
505250003Sadrian
506250008Sadrian#if 0
507250008Sadrianstruct ieee80211_channel *
508250003Sadrianar9300_get_extension_channel(struct ath_hal *ah)
509250003Sadrian{
510250003Sadrian    struct ath_hal_private  *ahp = AH_PRIVATE(ah);
511250003Sadrian    struct ath_hal_private_tables  *aht = AH_TABLES(ah);
512250003Sadrian    int i = 0;
513250003Sadrian
514250003Sadrian    HAL_CHANNEL_INTERNAL *ichan = AH_NULL;
515250003Sadrian    CHAN_CENTERS centers;
516250003Sadrian
517250003Sadrian    ichan = ahp->ah_curchan;
518250003Sadrian    ar9300_get_channel_centers(ah, ichan, &centers);
519250003Sadrian    if (centers.ctl_center == centers.ext_center) {
520250003Sadrian        return AH_NULL;
521250003Sadrian    }
522250003Sadrian    for (i = 0; i < ahp->ah_nchan; i++) {
523250003Sadrian        ichan = &aht->ah_channels[i];
524250003Sadrian        if (ichan->channel == centers.ext_center) {
525250008Sadrian            return (struct ieee80211_channel*)ichan;
526250003Sadrian        }
527250003Sadrian    }
528250003Sadrian    return AH_NULL;
529250003Sadrian}
530250008Sadrian#endif
531250003Sadrian
532250003SadrianHAL_BOOL
533250003Sadrianar9300_is_fast_clock_enabled(struct ath_hal *ah)
534250003Sadrian{
535250003Sadrian    struct ath_hal_private *ahp = AH_PRIVATE(ah);
536250003Sadrian
537250003Sadrian    if (IS_5GHZ_FAST_CLOCK_EN(ah, ahp->ah_curchan)) {
538250003Sadrian        return AH_TRUE;
539250003Sadrian    }
540250003Sadrian    return AH_FALSE;
541250003Sadrian}
542250003Sadrian
543250008Sadrian/*
544250008Sadrian * This should be enabled and linked into the build once
545250008Sadrian * radar support is enabled.
546250008Sadrian */
547250008Sadrian#if 0
548250003SadrianHAL_BOOL
549250003Sadrianar9300_handle_radar_bb_panic(struct ath_hal *ah)
550250003Sadrian{
551250003Sadrian    u_int32_t status;
552250003Sadrian    u_int32_t val;
553250003Sadrian#ifdef AH_DEBUG
554250003Sadrian    struct ath_hal_9300 *ahp = AH9300(ah);
555250003Sadrian#endif
556250003Sadrian
557250003Sadrian    status = AH_PRIVATE(ah)->ah_bb_panic_last_status;
558250003Sadrian
559250003Sadrian    if ( status == 0x04000539 ) {
560250003Sadrian        /* recover from this BB panic without reset*/
561250003Sadrian        /* set AR9300_DFS_FIRPWR to -1 */
562250003Sadrian        val = OS_REG_READ(ah, AR_PHY_RADAR_0);
563250003Sadrian        val &= (~AR_PHY_RADAR_0_FIRPWR);
564250003Sadrian        val |= SM( 0x7f, AR_PHY_RADAR_0_FIRPWR);
565250003Sadrian        OS_REG_WRITE(ah, AR_PHY_RADAR_0, val);
566250003Sadrian        OS_DELAY(1);
567250003Sadrian        /* set AR9300_DFS_FIRPWR to its default value */
568250003Sadrian        val = OS_REG_READ(ah, AR_PHY_RADAR_0);
569250003Sadrian        val &= ~AR_PHY_RADAR_0_FIRPWR;
570250003Sadrian        val |= SM( AR9300_DFS_FIRPWR, AR_PHY_RADAR_0_FIRPWR);
571250003Sadrian        OS_REG_WRITE(ah, AR_PHY_RADAR_0, val);
572250003Sadrian        return AH_TRUE;
573250003Sadrian    } else if (status == 0x0400000a) {
574250003Sadrian        /* EV 92527 : reset required if we see this signature */
575250003Sadrian        HALDEBUG(ah, HAL_DEBUG_DFS, "%s: BB Panic -- 0x0400000a\n", __func__);
576250003Sadrian        return AH_FALSE;
577250003Sadrian    } else if (status == 0x1300000a) {
578250003Sadrian        /* EV92527: we do not need a reset if we see this signature */
579250003Sadrian        HALDEBUG(ah, HAL_DEBUG_DFS, "%s: BB Panic -- 0x1300000a\n", __func__);
580250003Sadrian        return AH_TRUE;
581291437Sadrian    } else if ((AR_SREV_WASP(ah) || AR_SREV_HONEYBEE(ah)) && (status == 0x04000409)) {
582250003Sadrian        return AH_TRUE;
583250003Sadrian    } else {
584250003Sadrian        if (ar9300_get_capability(ah, HAL_CAP_LDPCWAR, 0, AH_NULL) == HAL_OK &&
585250003Sadrian            (status & 0xff00000f) == 0x04000009 &&
586250003Sadrian            status != 0x04000409 &&
587250003Sadrian            status != 0x04000b09 &&
588250003Sadrian            status != 0x04000e09 &&
589250003Sadrian            (status & 0x0000ff00))
590250003Sadrian        {
591250003Sadrian            /* disable RIFS Rx */
592250003Sadrian#ifdef AH_DEBUG
593250003Sadrian            HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "%s: BB status=0x%08x rifs=%d - disable\n",
594250003Sadrian                     __func__, status, ahp->ah_rifs_enabled);
595250003Sadrian            ar9300_set_rifs_delay(ah, AH_FALSE);
596250003Sadrian        }
597250003Sadrian        return AH_FALSE;
598250003Sadrian    }
599250003Sadrian}
600250003Sadrian#endif
601250008Sadrian#endif
602