ar5416_spectral.c revision 244950
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: head/sys/dev/ath/ath_hal/ar5416/ar5416_spectral.c 244950 2013-01-02 03:56:20Z adrian $
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
44static void ar5416DisableRadar(struct ath_hal *ah);
45static void ar5416PrepSpectralScan(struct ath_hal *ah);
46
47static void
48ar5416DisableRadar(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
75static void
76ar5416PrepSpectralScan(struct ath_hal *ah)
77{
78
79	ar5416DisableRadar(ah);
80	OS_REG_WRITE(ah, AR_PHY_ERR, ENABLE_ALL_PHYERR);
81}
82
83void
84ar5416ConfigureSpectralScan(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 */
150void
151ar5416GetSpectralParams(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
170HAL_BOOL
171ar5416IsSpectralActive(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
179HAL_BOOL
180ar5416IsSpectralEnabled(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
188void
189ar5416StartSpectralScan(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
205void
206ar5416StopSpectralScan(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
220uint32_t
221ar5416GetSpectralConfig(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
229void
230ar5416RestoreSpectralConfig(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