1244943Sadrian/*
2244943Sadrian * Copyright (c) 2012 Qualcomm Atheros, All Rights Reserved.
3244943Sadrian *
4244943Sadrian * Permission to use, copy, modify, and/or distribute this software for any
5244943Sadrian * purpose with or without fee is hereby granted, provided that the above
6244943Sadrian * copyright notice and this permission notice appear in all copies.
7244943Sadrian *
8244943Sadrian * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9244943Sadrian * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10244943Sadrian * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11244943Sadrian * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12244943Sadrian * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13244943Sadrian * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14244943Sadrian * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15244943Sadrian *
16244943Sadrian * $FreeBSD$
17244943Sadrian */
18244943Sadrian#include "opt_ah.h"
19244943Sadrian
20244943Sadrian#include "ah.h"
21244943Sadrian#include "ah_internal.h"
22244943Sadrian#include "ah_devid.h"
23244943Sadrian#include "ah_desc.h"                    /* NB: for HAL_PHYERR* */
24244943Sadrian
25244943Sadrian#include "ar5416/ar5416.h"
26244943Sadrian#include "ar5416/ar5416reg.h"
27244943Sadrian#include "ar5416/ar5416phy.h"
28244943Sadrian
29244943Sadrian/*
30244943Sadrian * Default AR9280 spectral scan parameters
31244943Sadrian */
32244943Sadrian#define	AR5416_SPECTRAL_SCAN_ENA		0
33244943Sadrian#define	AR5416_SPECTRAL_SCAN_ACTIVE		0
34244943Sadrian#define	AR5416_SPECTRAL_SCAN_FFT_PERIOD		8
35244943Sadrian#define	AR5416_SPECTRAL_SCAN_PERIOD		1
36244943Sadrian#define	AR5416_SPECTRAL_SCAN_COUNT		16 //used to be 128
37244943Sadrian#define	AR5416_SPECTRAL_SCAN_SHORT_REPEAT	1
38244943Sadrian
39244943Sadrian/* constants */
40244943Sadrian#define	MAX_RADAR_RSSI_THRESH	0x3f
41244943Sadrian#define	MAX_RADAR_HEIGHT	0x3f
42244943Sadrian#define	ENABLE_ALL_PHYERR	0xffffffff
43244943Sadrian
44244943Sadrianstatic void ar5416DisableRadar(struct ath_hal *ah);
45244943Sadrianstatic void ar5416PrepSpectralScan(struct ath_hal *ah);
46244943Sadrian
47244943Sadrianstatic void
48244943Sadrianar5416DisableRadar(struct ath_hal *ah)
49244943Sadrian{
50244943Sadrian	uint32_t val;
51244943Sadrian
52244943Sadrian	// Enable radar FFT
53244943Sadrian	val = OS_REG_READ(ah, AR_PHY_RADAR_0);
54244943Sadrian	val |= AR_PHY_RADAR_0_FFT_ENA;
55244943Sadrian
56244943Sadrian	// set radar detect thresholds to max to effectively disable radar
57244943Sadrian	val &= ~AR_PHY_RADAR_0_RRSSI;
58244943Sadrian	val |= SM(MAX_RADAR_RSSI_THRESH, AR_PHY_RADAR_0_RRSSI);
59244943Sadrian
60244943Sadrian	val &= ~AR_PHY_RADAR_0_HEIGHT;
61244943Sadrian	val |= SM(MAX_RADAR_HEIGHT, AR_PHY_RADAR_0_HEIGHT);
62244943Sadrian
63244943Sadrian	val &= ~(AR_PHY_RADAR_0_ENA);
64244943Sadrian	OS_REG_WRITE(ah, AR_PHY_RADAR_0, val);
65244943Sadrian
66244943Sadrian	// disable extension radar detect
67244943Sadrian	val = OS_REG_READ(ah, AR_PHY_RADAR_EXT);
68244943Sadrian	OS_REG_WRITE(ah, AR_PHY_RADAR_EXT, val & ~AR_PHY_RADAR_EXT_ENA);
69244943Sadrian
70244943Sadrian	val = OS_REG_READ(ah, AR_RX_FILTER);
71244943Sadrian	val |= (1<<13);
72244943Sadrian	OS_REG_WRITE(ah, AR_RX_FILTER, val);
73244943Sadrian}
74244943Sadrian
75244943Sadrianstatic void
76244943Sadrianar5416PrepSpectralScan(struct ath_hal *ah)
77244943Sadrian{
78244943Sadrian
79244943Sadrian	ar5416DisableRadar(ah);
80244943Sadrian	OS_REG_WRITE(ah, AR_PHY_ERR, ENABLE_ALL_PHYERR);
81244943Sadrian}
82244943Sadrian
83244943Sadrianvoid
84244943Sadrianar5416ConfigureSpectralScan(struct ath_hal *ah, HAL_SPECTRAL_PARAM *ss)
85244943Sadrian{
86244943Sadrian	uint32_t val;
87244943Sadrian
88244943Sadrian	ar5416PrepSpectralScan(ah);
89244943Sadrian
90244943Sadrian	val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN);
91244943Sadrian
92244943Sadrian	if (ss->ss_fft_period != HAL_SPECTRAL_PARAM_NOVAL) {
93244943Sadrian		val &= ~AR_PHY_SPECTRAL_SCAN_FFT_PERIOD;
94244943Sadrian		val |= SM(ss->ss_fft_period, AR_PHY_SPECTRAL_SCAN_FFT_PERIOD);
95244943Sadrian	}
96244943Sadrian
97244943Sadrian	if (ss->ss_period != HAL_SPECTRAL_PARAM_NOVAL) {
98244943Sadrian		val &= ~AR_PHY_SPECTRAL_SCAN_PERIOD;
99244943Sadrian		val |= SM(ss->ss_period, AR_PHY_SPECTRAL_SCAN_PERIOD);
100244943Sadrian	}
101244943Sadrian
102244943Sadrian	if (ss->ss_period != HAL_SPECTRAL_PARAM_NOVAL) {
103244943Sadrian		val &= ~AR_PHY_SPECTRAL_SCAN_PERIOD;
104244943Sadrian		val |= SM(ss->ss_period, AR_PHY_SPECTRAL_SCAN_PERIOD);
105244943Sadrian	}
106244943Sadrian
107244943Sadrian	/* This section is different for Kiwi and Merlin */
108244943Sadrian	if (AR_SREV_MERLIN(ah) ) {
109244943Sadrian		if (ss->ss_count != HAL_SPECTRAL_PARAM_NOVAL) {
110244943Sadrian			val &= ~AR_PHY_SPECTRAL_SCAN_COUNT;
111244943Sadrian			val |= SM(ss->ss_count, AR_PHY_SPECTRAL_SCAN_COUNT);
112244943Sadrian		}
113244943Sadrian
114244943Sadrian		if (ss->ss_short_report == AH_TRUE) {
115244943Sadrian			val |= AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT;
116244950Sadrian		} else if (ss->ss_short_report != HAL_SPECTRAL_PARAM_NOVAL) {
117244943Sadrian			val &= ~AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT;
118244943Sadrian		}
119244943Sadrian	} else {
120244943Sadrian		if (ss->ss_count != HAL_SPECTRAL_PARAM_NOVAL) {
121244943Sadrian			/*
122244943Sadrian			 * In Merlin, for continous scan, scan_count = 128.
123244943Sadrian			 * In case of Kiwi, this value should be 0
124244943Sadrian			 */
125244943Sadrian			if (ss->ss_count == 128)
126244943Sadrian				ss->ss_count = 0;
127244943Sadrian			val &= ~AR_PHY_SPECTRAL_SCAN_COUNT_KIWI;
128244943Sadrian			val |= SM(ss->ss_count, AR_PHY_SPECTRAL_SCAN_COUNT_KIWI);
129244943Sadrian		}
130244943Sadrian
131244943Sadrian		if (ss->ss_short_report == AH_TRUE) {
132244943Sadrian			val |= AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_KIWI;
133244950Sadrian		} else if (ss->ss_short_report != HAL_SPECTRAL_PARAM_NOVAL) {
134244943Sadrian			val &= ~AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_KIWI;
135244943Sadrian		}
136244943Sadrian
137244943Sadrian		//Select the mask to be same as before
138244943Sadrian		val |= AR_PHY_SPECTRAL_SCAN_PHYERR_MASK_SELECT_KIWI;
139244943Sadrian	}
140244943Sadrian	// Enable spectral scan
141244943Sadrian	OS_REG_WRITE(ah, AR_PHY_SPECTRAL_SCAN, val | AR_PHY_SPECTRAL_SCAN_ENA);
142244943Sadrian
143244943Sadrian	ar5416GetSpectralParams(ah, ss);
144244943Sadrian}
145244943Sadrian
146244943Sadrian/*
147244943Sadrian * Get the spectral parameter values and return them in the pe
148244943Sadrian * structure
149244943Sadrian */
150244943Sadrianvoid
151244943Sadrianar5416GetSpectralParams(struct ath_hal *ah, HAL_SPECTRAL_PARAM *ss)
152244943Sadrian{
153244943Sadrian	uint32_t val;
154244943Sadrian
155244943Sadrian	val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN);
156244943Sadrian
157244943Sadrian	ss->ss_fft_period = MS(val, AR_PHY_SPECTRAL_SCAN_FFT_PERIOD);
158244943Sadrian	ss->ss_period = MS(val, AR_PHY_SPECTRAL_SCAN_PERIOD);
159244943Sadrian	if (AR_SREV_MERLIN(ah) ) {
160244943Sadrian		ss->ss_count = MS(val, AR_PHY_SPECTRAL_SCAN_COUNT);
161244943Sadrian		ss->ss_short_report = MS(val, AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT);
162244943Sadrian	} else {
163244943Sadrian		ss->ss_count = MS(val, AR_PHY_SPECTRAL_SCAN_COUNT_KIWI);
164244943Sadrian		ss->ss_short_report = MS(val, AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_KIWI);
165244943Sadrian	}
166244943Sadrian	val = OS_REG_READ(ah, AR_PHY_RADAR_1);
167244943Sadrian	ss->radar_bin_thresh_sel = MS(val, AR_PHY_RADAR_1_BIN_THRESH_SELECT);
168244943Sadrian}
169244943Sadrian
170244943SadrianHAL_BOOL
171244943Sadrianar5416IsSpectralActive(struct ath_hal *ah)
172244943Sadrian{
173244943Sadrian	uint32_t val;
174244943Sadrian
175244943Sadrian	val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN);
176244943Sadrian	return MS(val, AR_PHY_SPECTRAL_SCAN_ACTIVE);
177244943Sadrian}
178244943Sadrian
179244943SadrianHAL_BOOL
180244943Sadrianar5416IsSpectralEnabled(struct ath_hal *ah)
181244943Sadrian{
182244943Sadrian	uint32_t val;
183244943Sadrian
184244943Sadrian	val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN);
185244943Sadrian	return MS(val,AR_PHY_SPECTRAL_SCAN_ENA);
186244943Sadrian}
187244943Sadrian
188244943Sadrianvoid
189244943Sadrianar5416StartSpectralScan(struct ath_hal *ah)
190244943Sadrian{
191244943Sadrian	uint32_t val;
192244943Sadrian
193244943Sadrian	ar5416PrepSpectralScan(ah);
194244943Sadrian
195244943Sadrian	// Activate spectral scan
196244943Sadrian	val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN);
197244943Sadrian	val |= AR_PHY_SPECTRAL_SCAN_ENA;
198244943Sadrian	val |= AR_PHY_SPECTRAL_SCAN_ACTIVE;
199244943Sadrian	OS_REG_WRITE(ah, AR_PHY_SPECTRAL_SCAN, val);
200244943Sadrian	val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN);
201244943Sadrian	val = OS_REG_READ(ah, AR_PHY_ERR_MASK_REG);
202244943Sadrian	OS_REG_WRITE(ah, AR_PHY_ERR_MASK_REG, val | AR_PHY_ERR_RADAR);
203244943Sadrian}
204244943Sadrian
205244943Sadrianvoid
206244943Sadrianar5416StopSpectralScan(struct ath_hal *ah)
207244943Sadrian{
208244943Sadrian	uint32_t val;
209244943Sadrian	val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN);
210244943Sadrian
211244943Sadrian	// Deactivate spectral scan
212244943Sadrian	val &= ~AR_PHY_SPECTRAL_SCAN_ENA;
213244943Sadrian	val &= ~AR_PHY_SPECTRAL_SCAN_ACTIVE;
214244943Sadrian	OS_REG_WRITE(ah, AR_PHY_SPECTRAL_SCAN, val);
215244943Sadrian	val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN);
216244943Sadrian	val = OS_REG_READ(ah, AR_PHY_ERR_MASK_REG) & (~AR_PHY_ERR_RADAR);
217244943Sadrian	OS_REG_WRITE(ah, AR_PHY_ERR_MASK_REG, val);
218244943Sadrian}
219244943Sadrian
220244943Sadrianuint32_t
221244943Sadrianar5416GetSpectralConfig(struct ath_hal *ah)
222244943Sadrian{
223244943Sadrian	uint32_t val;
224244943Sadrian
225244943Sadrian	val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN);
226244943Sadrian	return val;
227244943Sadrian}
228244943Sadrian
229244943Sadrianvoid
230244943Sadrianar5416RestoreSpectralConfig(struct ath_hal *ah, uint32_t restoreval)
231244943Sadrian{
232244943Sadrian	uint32_t curval;
233244943Sadrian
234244943Sadrian	ar5416PrepSpectralScan(ah);
235244943Sadrian
236244943Sadrian	curval = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN);
237244943Sadrian
238244943Sadrian	if (restoreval != curval) {
239244943Sadrian		restoreval |= AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT;
240244943Sadrian		OS_REG_WRITE(ah, AR_PHY_SPECTRAL_SCAN, restoreval);
241244943Sadrian	}
242244943Sadrian	return;
243244943Sadrian}
244244943Sadrian
245