1 /*
2  * Copyright (c) 2012 Qualcomm Atheros, All Rights Reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  *
16  * $FreeBSD$
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
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
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
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 continous 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
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
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
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
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
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
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
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 
245