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, ¢ers);
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