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: releng/12.0/sys/dev/ath/ath_hal/ar5416/ar5416_spectral.c 326695 2017-12-08 15:57:29Z pfg $
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
46static void ar5416DisableRadar(struct ath_hal *ah);
47static void ar5416PrepSpectralScan(struct ath_hal *ah);
48
49static void
50ar5416DisableRadar(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
77static void
78ar5416PrepSpectralScan(struct ath_hal *ah)
79{
80
81	ar5416DisableRadar(ah);
82	OS_REG_WRITE(ah, AR_PHY_ERR, ENABLE_ALL_PHYERR);
83}
84
85void
86ar5416ConfigureSpectralScan(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 */
152void
153ar5416GetSpectralParams(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
172HAL_BOOL
173ar5416IsSpectralActive(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
181HAL_BOOL
182ar5416IsSpectralEnabled(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
190void
191ar5416StartSpectralScan(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
207void
208ar5416StopSpectralScan(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
222uint32_t
223ar5416GetSpectralConfig(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
231void
232ar5416RestoreSpectralConfig(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