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  * $FreeBSD$
19  */
20 #include "opt_ah.h"
21 
22 #include "ah.h"
23 #include "ah_internal.h"
24 #include "ah_devid.h"
25 #include "ah_desc.h"                    /* NB: for HAL_PHYERR* */
26 
27 #include "ar5416/ar5416.h"
28 #include "ar5416/ar5416reg.h"
29 #include "ar5416/ar5416phy.h"
30 
31 /*
32  * Default AR9280 spectral scan parameters
33  */
34 #define	AR5416_SPECTRAL_SCAN_ENA		0
35 #define	AR5416_SPECTRAL_SCAN_ACTIVE		0
36 #define	AR5416_SPECTRAL_SCAN_FFT_PERIOD		8
37 #define	AR5416_SPECTRAL_SCAN_PERIOD		1
38 #define	AR5416_SPECTRAL_SCAN_COUNT		16 //used to be 128
39 #define	AR5416_SPECTRAL_SCAN_SHORT_REPEAT	1
40 
41 /* constants */
42 #define	MAX_RADAR_RSSI_THRESH	0x3f
43 #define	MAX_RADAR_HEIGHT	0x3f
44 #define	ENABLE_ALL_PHYERR	0xffffffff
45 
46 static void ar5416DisableRadar(struct ath_hal *ah);
47 static void ar5416PrepSpectralScan(struct ath_hal *ah);
48 
49 static void
50 ar5416DisableRadar(struct ath_hal *ah)
51 {
52 	uint32_t val;
53 
54 	// Enable radar FFT
55 	val = OS_REG_READ(ah, AR_PHY_RADAR_0);
56 	val |= AR_PHY_RADAR_0_FFT_ENA;
57 
58 	// set radar detect thresholds to max to effectively disable radar
59 	val &= ~AR_PHY_RADAR_0_RRSSI;
60 	val |= SM(MAX_RADAR_RSSI_THRESH, AR_PHY_RADAR_0_RRSSI);
61 
62 	val &= ~AR_PHY_RADAR_0_HEIGHT;
63 	val |= SM(MAX_RADAR_HEIGHT, AR_PHY_RADAR_0_HEIGHT);
64 
65 	val &= ~(AR_PHY_RADAR_0_ENA);
66 	OS_REG_WRITE(ah, AR_PHY_RADAR_0, val);
67 
68 	// disable extension radar detect
69 	val = OS_REG_READ(ah, AR_PHY_RADAR_EXT);
70 	OS_REG_WRITE(ah, AR_PHY_RADAR_EXT, val & ~AR_PHY_RADAR_EXT_ENA);
71 
72 	val = OS_REG_READ(ah, AR_RX_FILTER);
73 	val |= (1<<13);
74 	OS_REG_WRITE(ah, AR_RX_FILTER, val);
75 }
76 
77 static void
78 ar5416PrepSpectralScan(struct ath_hal *ah)
79 {
80 
81 	ar5416DisableRadar(ah);
82 	OS_REG_WRITE(ah, AR_PHY_ERR, ENABLE_ALL_PHYERR);
83 }
84 
85 void
86 ar5416ConfigureSpectralScan(struct ath_hal *ah, HAL_SPECTRAL_PARAM *ss)
87 {
88 	uint32_t val;
89 
90 	ar5416PrepSpectralScan(ah);
91 
92 	val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN);
93 
94 	if (ss->ss_fft_period != HAL_SPECTRAL_PARAM_NOVAL) {
95 		val &= ~AR_PHY_SPECTRAL_SCAN_FFT_PERIOD;
96 		val |= SM(ss->ss_fft_period, AR_PHY_SPECTRAL_SCAN_FFT_PERIOD);
97 	}
98 
99 	if (ss->ss_period != HAL_SPECTRAL_PARAM_NOVAL) {
100 		val &= ~AR_PHY_SPECTRAL_SCAN_PERIOD;
101 		val |= SM(ss->ss_period, AR_PHY_SPECTRAL_SCAN_PERIOD);
102 	}
103 
104 	if (ss->ss_period != HAL_SPECTRAL_PARAM_NOVAL) {
105 		val &= ~AR_PHY_SPECTRAL_SCAN_PERIOD;
106 		val |= SM(ss->ss_period, AR_PHY_SPECTRAL_SCAN_PERIOD);
107 	}
108 
109 	/* This section is different for Kiwi and Merlin */
110 	if (AR_SREV_MERLIN(ah) ) {
111 		if (ss->ss_count != HAL_SPECTRAL_PARAM_NOVAL) {
112 			val &= ~AR_PHY_SPECTRAL_SCAN_COUNT;
113 			val |= SM(ss->ss_count, AR_PHY_SPECTRAL_SCAN_COUNT);
114 		}
115 
116 		if (ss->ss_short_report == AH_TRUE) {
117 			val |= AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT;
118 		} else if (ss->ss_short_report != HAL_SPECTRAL_PARAM_NOVAL) {
119 			val &= ~AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT;
120 		}
121 	} else {
122 		if (ss->ss_count != HAL_SPECTRAL_PARAM_NOVAL) {
123 			/*
124 			 * In Merlin, for continuous scan, scan_count = 128.
125 			 * In case of Kiwi, this value should be 0
126 			 */
127 			if (ss->ss_count == 128)
128 				ss->ss_count = 0;
129 			val &= ~AR_PHY_SPECTRAL_SCAN_COUNT_KIWI;
130 			val |= SM(ss->ss_count, AR_PHY_SPECTRAL_SCAN_COUNT_KIWI);
131 		}
132 
133 		if (ss->ss_short_report == AH_TRUE) {
134 			val |= AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_KIWI;
135 		} else if (ss->ss_short_report != HAL_SPECTRAL_PARAM_NOVAL) {
136 			val &= ~AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_KIWI;
137 		}
138 
139 		//Select the mask to be same as before
140 		val |= AR_PHY_SPECTRAL_SCAN_PHYERR_MASK_SELECT_KIWI;
141 	}
142 	// Enable spectral scan
143 	OS_REG_WRITE(ah, AR_PHY_SPECTRAL_SCAN, val | AR_PHY_SPECTRAL_SCAN_ENA);
144 
145 	ar5416GetSpectralParams(ah, ss);
146 }
147 
148 /*
149  * Get the spectral parameter values and return them in the pe
150  * structure
151  */
152 void
153 ar5416GetSpectralParams(struct ath_hal *ah, HAL_SPECTRAL_PARAM *ss)
154 {
155 	uint32_t val;
156 
157 	val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN);
158 
159 	ss->ss_fft_period = MS(val, AR_PHY_SPECTRAL_SCAN_FFT_PERIOD);
160 	ss->ss_period = MS(val, AR_PHY_SPECTRAL_SCAN_PERIOD);
161 	if (AR_SREV_MERLIN(ah) ) {
162 		ss->ss_count = MS(val, AR_PHY_SPECTRAL_SCAN_COUNT);
163 		ss->ss_short_report = MS(val, AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT);
164 	} else {
165 		ss->ss_count = MS(val, AR_PHY_SPECTRAL_SCAN_COUNT_KIWI);
166 		ss->ss_short_report = MS(val, AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_KIWI);
167 	}
168 	val = OS_REG_READ(ah, AR_PHY_RADAR_1);
169 	ss->radar_bin_thresh_sel = MS(val, AR_PHY_RADAR_1_BIN_THRESH_SELECT);
170 }
171 
172 HAL_BOOL
173 ar5416IsSpectralActive(struct ath_hal *ah)
174 {
175 	uint32_t val;
176 
177 	val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN);
178 	return MS(val, AR_PHY_SPECTRAL_SCAN_ACTIVE);
179 }
180 
181 HAL_BOOL
182 ar5416IsSpectralEnabled(struct ath_hal *ah)
183 {
184 	uint32_t val;
185 
186 	val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN);
187 	return MS(val,AR_PHY_SPECTRAL_SCAN_ENA);
188 }
189 
190 void
191 ar5416StartSpectralScan(struct ath_hal *ah)
192 {
193 	uint32_t val;
194 
195 	ar5416PrepSpectralScan(ah);
196 
197 	// Activate spectral scan
198 	val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN);
199 	val |= AR_PHY_SPECTRAL_SCAN_ENA;
200 	val |= AR_PHY_SPECTRAL_SCAN_ACTIVE;
201 	OS_REG_WRITE(ah, AR_PHY_SPECTRAL_SCAN, val);
202 	val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN);
203 	val = OS_REG_READ(ah, AR_PHY_ERR_MASK_REG);
204 	OS_REG_WRITE(ah, AR_PHY_ERR_MASK_REG, val | AR_PHY_ERR_RADAR);
205 }
206 
207 void
208 ar5416StopSpectralScan(struct ath_hal *ah)
209 {
210 	uint32_t val;
211 	val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN);
212 
213 	// Deactivate spectral scan
214 	val &= ~AR_PHY_SPECTRAL_SCAN_ENA;
215 	val &= ~AR_PHY_SPECTRAL_SCAN_ACTIVE;
216 	OS_REG_WRITE(ah, AR_PHY_SPECTRAL_SCAN, val);
217 	val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN);
218 	val = OS_REG_READ(ah, AR_PHY_ERR_MASK_REG) & (~AR_PHY_ERR_RADAR);
219 	OS_REG_WRITE(ah, AR_PHY_ERR_MASK_REG, val);
220 }
221 
222 uint32_t
223 ar5416GetSpectralConfig(struct ath_hal *ah)
224 {
225 	uint32_t val;
226 
227 	val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN);
228 	return val;
229 }
230 
231 void
232 ar5416RestoreSpectralConfig(struct ath_hal *ah, uint32_t restoreval)
233 {
234 	uint32_t curval;
235 
236 	ar5416PrepSpectralScan(ah);
237 
238 	curval = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN);
239 
240 	if (restoreval != curval) {
241 		restoreval |= AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT;
242 		OS_REG_WRITE(ah, AR_PHY_SPECTRAL_SCAN, restoreval);
243 	}
244 	return;
245 }
246 
247