1 /*-
2 * SPDX-License-Identifier: ISC
3 *
4 * Copyright (c) 2012 Qualcomm Atheros, All Rights Reserved.
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 #include "opt_ah.h"
19
20 #include "ah.h"
21 #include "ah_internal.h"
22 #include "ah_devid.h"
23 #include "ah_desc.h" /* NB: for HAL_PHYERR* */
24
25 #include "ar5416/ar5416.h"
26 #include "ar5416/ar5416reg.h"
27 #include "ar5416/ar5416phy.h"
28
29 /*
30 * Default AR9280 spectral scan parameters
31 */
32 #define AR5416_SPECTRAL_SCAN_ENA 0
33 #define AR5416_SPECTRAL_SCAN_ACTIVE 0
34 #define AR5416_SPECTRAL_SCAN_FFT_PERIOD 8
35 #define AR5416_SPECTRAL_SCAN_PERIOD 1
36 #define AR5416_SPECTRAL_SCAN_COUNT 16 //used to be 128
37 #define AR5416_SPECTRAL_SCAN_SHORT_REPEAT 1
38
39 /* constants */
40 #define MAX_RADAR_RSSI_THRESH 0x3f
41 #define MAX_RADAR_HEIGHT 0x3f
42 #define ENABLE_ALL_PHYERR 0xffffffff
43
44 static void ar5416DisableRadar(struct ath_hal *ah);
45 static void ar5416PrepSpectralScan(struct ath_hal *ah);
46
47 static void
ar5416DisableRadar(struct ath_hal * ah)48 ar5416DisableRadar(struct ath_hal *ah)
49 {
50 uint32_t val;
51
52 // Enable radar FFT
53 val = OS_REG_READ(ah, AR_PHY_RADAR_0);
54 val |= AR_PHY_RADAR_0_FFT_ENA;
55
56 // set radar detect thresholds to max to effectively disable radar
57 val &= ~AR_PHY_RADAR_0_RRSSI;
58 val |= SM(MAX_RADAR_RSSI_THRESH, AR_PHY_RADAR_0_RRSSI);
59
60 val &= ~AR_PHY_RADAR_0_HEIGHT;
61 val |= SM(MAX_RADAR_HEIGHT, AR_PHY_RADAR_0_HEIGHT);
62
63 val &= ~(AR_PHY_RADAR_0_ENA);
64 OS_REG_WRITE(ah, AR_PHY_RADAR_0, val);
65
66 // disable extension radar detect
67 val = OS_REG_READ(ah, AR_PHY_RADAR_EXT);
68 OS_REG_WRITE(ah, AR_PHY_RADAR_EXT, val & ~AR_PHY_RADAR_EXT_ENA);
69
70 val = OS_REG_READ(ah, AR_RX_FILTER);
71 val |= (1<<13);
72 OS_REG_WRITE(ah, AR_RX_FILTER, val);
73 }
74
75 static void
ar5416PrepSpectralScan(struct ath_hal * ah)76 ar5416PrepSpectralScan(struct ath_hal *ah)
77 {
78
79 ar5416DisableRadar(ah);
80 OS_REG_WRITE(ah, AR_PHY_ERR, ENABLE_ALL_PHYERR);
81 }
82
83 void
ar5416ConfigureSpectralScan(struct ath_hal * ah,HAL_SPECTRAL_PARAM * ss)84 ar5416ConfigureSpectralScan(struct ath_hal *ah, HAL_SPECTRAL_PARAM *ss)
85 {
86 uint32_t val;
87
88 ar5416PrepSpectralScan(ah);
89
90 val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN);
91
92 if (ss->ss_fft_period != HAL_SPECTRAL_PARAM_NOVAL) {
93 val &= ~AR_PHY_SPECTRAL_SCAN_FFT_PERIOD;
94 val |= SM(ss->ss_fft_period, AR_PHY_SPECTRAL_SCAN_FFT_PERIOD);
95 }
96
97 if (ss->ss_period != HAL_SPECTRAL_PARAM_NOVAL) {
98 val &= ~AR_PHY_SPECTRAL_SCAN_PERIOD;
99 val |= SM(ss->ss_period, AR_PHY_SPECTRAL_SCAN_PERIOD);
100 }
101
102 if (ss->ss_period != HAL_SPECTRAL_PARAM_NOVAL) {
103 val &= ~AR_PHY_SPECTRAL_SCAN_PERIOD;
104 val |= SM(ss->ss_period, AR_PHY_SPECTRAL_SCAN_PERIOD);
105 }
106
107 /* This section is different for Kiwi and Merlin */
108 if (AR_SREV_MERLIN(ah) ) {
109 if (ss->ss_count != HAL_SPECTRAL_PARAM_NOVAL) {
110 val &= ~AR_PHY_SPECTRAL_SCAN_COUNT;
111 val |= SM(ss->ss_count, AR_PHY_SPECTRAL_SCAN_COUNT);
112 }
113
114 if (ss->ss_short_report == AH_TRUE) {
115 val |= AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT;
116 } else if (ss->ss_short_report != HAL_SPECTRAL_PARAM_NOVAL) {
117 val &= ~AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT;
118 }
119 } else {
120 if (ss->ss_count != HAL_SPECTRAL_PARAM_NOVAL) {
121 /*
122 * In Merlin, for continuous scan, scan_count = 128.
123 * In case of Kiwi, this value should be 0
124 */
125 if (ss->ss_count == 128)
126 ss->ss_count = 0;
127 val &= ~AR_PHY_SPECTRAL_SCAN_COUNT_KIWI;
128 val |= SM(ss->ss_count, AR_PHY_SPECTRAL_SCAN_COUNT_KIWI);
129 }
130
131 if (ss->ss_short_report == AH_TRUE) {
132 val |= AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_KIWI;
133 } else if (ss->ss_short_report != HAL_SPECTRAL_PARAM_NOVAL) {
134 val &= ~AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_KIWI;
135 }
136
137 //Select the mask to be same as before
138 val |= AR_PHY_SPECTRAL_SCAN_PHYERR_MASK_SELECT_KIWI;
139 }
140 // Enable spectral scan
141 OS_REG_WRITE(ah, AR_PHY_SPECTRAL_SCAN, val | AR_PHY_SPECTRAL_SCAN_ENA);
142
143 ar5416GetSpectralParams(ah, ss);
144 }
145
146 /*
147 * Get the spectral parameter values and return them in the pe
148 * structure
149 */
150 void
ar5416GetSpectralParams(struct ath_hal * ah,HAL_SPECTRAL_PARAM * ss)151 ar5416GetSpectralParams(struct ath_hal *ah, HAL_SPECTRAL_PARAM *ss)
152 {
153 uint32_t val;
154
155 val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN);
156
157 ss->ss_fft_period = MS(val, AR_PHY_SPECTRAL_SCAN_FFT_PERIOD);
158 ss->ss_period = MS(val, AR_PHY_SPECTRAL_SCAN_PERIOD);
159 if (AR_SREV_MERLIN(ah) ) {
160 ss->ss_count = MS(val, AR_PHY_SPECTRAL_SCAN_COUNT);
161 ss->ss_short_report = MS(val, AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT);
162 } else {
163 ss->ss_count = MS(val, AR_PHY_SPECTRAL_SCAN_COUNT_KIWI);
164 ss->ss_short_report = MS(val, AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_KIWI);
165 }
166 val = OS_REG_READ(ah, AR_PHY_RADAR_1);
167 ss->radar_bin_thresh_sel = MS(val, AR_PHY_RADAR_1_BIN_THRESH_SELECT);
168 }
169
170 HAL_BOOL
ar5416IsSpectralActive(struct ath_hal * ah)171 ar5416IsSpectralActive(struct ath_hal *ah)
172 {
173 uint32_t val;
174
175 val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN);
176 return MS(val, AR_PHY_SPECTRAL_SCAN_ACTIVE);
177 }
178
179 HAL_BOOL
ar5416IsSpectralEnabled(struct ath_hal * ah)180 ar5416IsSpectralEnabled(struct ath_hal *ah)
181 {
182 uint32_t val;
183
184 val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN);
185 return MS(val,AR_PHY_SPECTRAL_SCAN_ENA);
186 }
187
188 void
ar5416StartSpectralScan(struct ath_hal * ah)189 ar5416StartSpectralScan(struct ath_hal *ah)
190 {
191 uint32_t val;
192
193 ar5416PrepSpectralScan(ah);
194
195 // Activate spectral scan
196 val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN);
197 val |= AR_PHY_SPECTRAL_SCAN_ENA;
198 val |= AR_PHY_SPECTRAL_SCAN_ACTIVE;
199 OS_REG_WRITE(ah, AR_PHY_SPECTRAL_SCAN, val);
200 val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN);
201 val = OS_REG_READ(ah, AR_PHY_ERR_MASK_REG);
202 OS_REG_WRITE(ah, AR_PHY_ERR_MASK_REG, val | AR_PHY_ERR_RADAR);
203 }
204
205 void
ar5416StopSpectralScan(struct ath_hal * ah)206 ar5416StopSpectralScan(struct ath_hal *ah)
207 {
208 uint32_t val;
209 val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN);
210
211 // Deactivate spectral scan
212 val &= ~AR_PHY_SPECTRAL_SCAN_ENA;
213 val &= ~AR_PHY_SPECTRAL_SCAN_ACTIVE;
214 OS_REG_WRITE(ah, AR_PHY_SPECTRAL_SCAN, val);
215 val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN);
216 val = OS_REG_READ(ah, AR_PHY_ERR_MASK_REG) & (~AR_PHY_ERR_RADAR);
217 OS_REG_WRITE(ah, AR_PHY_ERR_MASK_REG, val);
218 }
219
220 uint32_t
ar5416GetSpectralConfig(struct ath_hal * ah)221 ar5416GetSpectralConfig(struct ath_hal *ah)
222 {
223 uint32_t val;
224
225 val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN);
226 return val;
227 }
228
229 void
ar5416RestoreSpectralConfig(struct ath_hal * ah,uint32_t restoreval)230 ar5416RestoreSpectralConfig(struct ath_hal *ah, uint32_t restoreval)
231 {
232 uint32_t curval;
233
234 ar5416PrepSpectralScan(ah);
235
236 curval = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN);
237
238 if (restoreval != curval) {
239 restoreval |= AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT;
240 OS_REG_WRITE(ah, AR_PHY_SPECTRAL_SCAN, restoreval);
241 }
242 return;
243 }
244