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