summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoradrian <adrian@FreeBSD.org>2013-01-02 00:38:01 +0000
committeradrian <adrian@FreeBSD.org>2013-01-02 00:38:01 +0000
commitb28c06734db45223dfddd8500027aa7907df9abc (patch)
tree8681a231a819c3333d0365aa228ec4d00208fbef
parent96cc82a0b4332cd3ae9addbf0b169378e0d21466 (diff)
downloadFreeBSD-src-b28c06734db45223dfddd8500027aa7907df9abc.zip
FreeBSD-src-b28c06734db45223dfddd8500027aa7907df9abc.tar.gz
Bring over the basic spectral scan framework code from Qualcomm Atheros.
This includes the HAL routines to setup, enable/activate/disable spectral scan and configure the relevant registers. This still requires driver interaction to enable spectral scan reporting. Specifically: * call ah_spectralConfigure() to configure and enable spectral scan; * .. there's currently no way to disable spectral scan... that will have to follow. * call ah_spectralStart() to force start a spectral report; * call ah_spectralStop() to force stop an active spectral report. The spectral scan results appear as PHY errors (type 0x5 on the AR9280, same as radar) but with the spectral scan bit set (0x10 in the last byte of the frame) identifying it as a spectral report rather than a radar FFT report. Caveats: * It's likely quite difficult to run spectral _and_ radar at the same time. Enabling spectral scan disables the radar thresholds but leaves radar enabled. Thus, the driver (for now) needs to ensure that only one or the other is enabled. * .. it needs testing on HT40 mode. Tested: * AR9280 in STA mode, HT/20 only TODO: * Test on AR9285, AR9287; * Test in both HT20 and HT40 modes; * .. all the driver glue. Obtained from: Qualcomm Atheros
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar5416.h10
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar5416_attach.c9
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar5416_spectral.c244
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar5416phy.h21
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar5416reg.h1
-rw-r--r--sys/dev/ath/ath_hal/ar9002/ar9280_attach.c1
-rw-r--r--sys/dev/ath/ath_hal/ar9002/ar9285_attach.c1
-rw-r--r--sys/dev/ath/ath_hal/ar9002/ar9287_attach.c1
8 files changed, 286 insertions, 2 deletions
diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416.h b/sys/dev/ath/ath_hal/ar5416/ar5416.h
index 90397aa..d570588 100644
--- a/sys/dev/ath/ath_hal/ar5416/ar5416.h
+++ b/sys/dev/ath/ath_hal/ar5416/ar5416.h
@@ -265,6 +265,16 @@ extern HAL_BOOL ar5416ProcessRadarEvent(struct ath_hal *ah,
HAL_DFS_EVENT *event);
extern HAL_BOOL ar5416IsFastClockEnabled(struct ath_hal *ah);
+/* ar9280_spectral.c */
+extern void ar5416ConfigureSpectralScan(struct ath_hal *ah, HAL_SPECTRAL_PARAM *ss);
+extern void ar5416GetSpectralParams(struct ath_hal *ah, HAL_SPECTRAL_PARAM *ss);
+extern HAL_BOOL ar5416IsSpectralActive(struct ath_hal *ah);
+extern HAL_BOOL ar5416IsSpectralEnabled(struct ath_hal *ah);
+extern void ar5416StartSpectralScan(struct ath_hal *ah);
+extern void ar5416StopSpectralScan(struct ath_hal *ah);
+extern uint32_t ar5416GetSpectralConfig(struct ath_hal *ah);
+extern void ar5416RestoreSpectralConfig(struct ath_hal *ah, uint32_t restoreval);
+
extern HAL_BOOL ar5416SetPowerMode(struct ath_hal *ah, HAL_POWER_MODE mode,
int setChip);
extern HAL_POWER_MODE ar5416GetPowerMode(struct ath_hal *ah);
diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c b/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c
index 2a76b4b..d165540 100644
--- a/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c
+++ b/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c
@@ -161,6 +161,14 @@ ar5416InitState(struct ath_hal_5416 *ahp5416, uint16_t devid, HAL_SOFTC sc,
ah->ah_procRadarEvent = ar5416ProcessRadarEvent;
ah->ah_isFastClockEnabled = ar5416IsFastClockEnabled;
+ /* Spectral Scan Functions */
+ ah->ah_spectralConfigure = ar5416ConfigureSpectralScan;
+ ah->ah_spectralGetConfig = ar5416GetSpectralParams;
+ ah->ah_spectralStart = ar5416StartSpectralScan;
+ ah->ah_spectralStop = ar5416StopSpectralScan;
+ ah->ah_spectralIsEnabled = ar5416IsSpectralEnabled;
+ ah->ah_spectralIsActive = ar5416IsSpectralActive;
+
/* Power Management Functions */
ah->ah_setPowerMode = ar5416SetPowerMode;
@@ -918,6 +926,7 @@ ar5416FillCapabilityInfo(struct ath_hal *ah)
pCap->halMcastKeySrchSupport = AH_TRUE; /* Works on AR5416 and later */
pCap->halTsfAddSupport = AH_TRUE;
pCap->hal4AddrAggrSupport = AH_FALSE; /* Broken in Owl */
+ pCap->halSpectralScanSupport = AH_FALSE; /* AR9280 and later */
if (ath_hal_eepromGet(ah, AR_EEP_MAXQCU, &val) == HAL_OK)
pCap->halTotalQueues = val;
diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_spectral.c b/sys/dev/ath/ath_hal/ar5416/ar5416_spectral.c
new file mode 100644
index 0000000..3a4a57d
--- /dev/null
+++ b/sys/dev/ath/ath_hal/ar5416/ar5416_spectral.c
@@ -0,0 +1,244 @@
+/*
+ * Copyright (c) 2012 Qualcomm Atheros, All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $FreeBSD$
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+#include "ah_devid.h"
+#include "ah_desc.h" /* NB: for HAL_PHYERR* */
+
+#include "ar5416/ar5416.h"
+#include "ar5416/ar5416reg.h"
+#include "ar5416/ar5416phy.h"
+
+/*
+ * Default AR9280 spectral scan parameters
+ */
+#define AR5416_SPECTRAL_SCAN_ENA 0
+#define AR5416_SPECTRAL_SCAN_ACTIVE 0
+#define AR5416_SPECTRAL_SCAN_FFT_PERIOD 8
+#define AR5416_SPECTRAL_SCAN_PERIOD 1
+#define AR5416_SPECTRAL_SCAN_COUNT 16 //used to be 128
+#define AR5416_SPECTRAL_SCAN_SHORT_REPEAT 1
+
+/* constants */
+#define MAX_RADAR_RSSI_THRESH 0x3f
+#define MAX_RADAR_HEIGHT 0x3f
+#define ENABLE_ALL_PHYERR 0xffffffff
+
+static void ar5416DisableRadar(struct ath_hal *ah);
+static void ar5416PrepSpectralScan(struct ath_hal *ah);
+
+static void
+ar5416DisableRadar(struct ath_hal *ah)
+{
+ uint32_t val;
+
+ // Enable radar FFT
+ val = OS_REG_READ(ah, AR_PHY_RADAR_0);
+ val |= AR_PHY_RADAR_0_FFT_ENA;
+
+ // set radar detect thresholds to max to effectively disable radar
+ val &= ~AR_PHY_RADAR_0_RRSSI;
+ val |= SM(MAX_RADAR_RSSI_THRESH, AR_PHY_RADAR_0_RRSSI);
+
+ val &= ~AR_PHY_RADAR_0_HEIGHT;
+ val |= SM(MAX_RADAR_HEIGHT, AR_PHY_RADAR_0_HEIGHT);
+
+ val &= ~(AR_PHY_RADAR_0_ENA);
+ OS_REG_WRITE(ah, AR_PHY_RADAR_0, val);
+
+ // disable extension radar detect
+ val = OS_REG_READ(ah, AR_PHY_RADAR_EXT);
+ OS_REG_WRITE(ah, AR_PHY_RADAR_EXT, val & ~AR_PHY_RADAR_EXT_ENA);
+
+ val = OS_REG_READ(ah, AR_RX_FILTER);
+ val |= (1<<13);
+ OS_REG_WRITE(ah, AR_RX_FILTER, val);
+}
+
+static void
+ar5416PrepSpectralScan(struct ath_hal *ah)
+{
+
+ ar5416DisableRadar(ah);
+ OS_REG_WRITE(ah, AR_PHY_ERR, ENABLE_ALL_PHYERR);
+}
+
+void
+ar5416ConfigureSpectralScan(struct ath_hal *ah, HAL_SPECTRAL_PARAM *ss)
+{
+ uint32_t val;
+
+ ar5416PrepSpectralScan(ah);
+
+ val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN);
+
+ if (ss->ss_fft_period != HAL_SPECTRAL_PARAM_NOVAL) {
+ val &= ~AR_PHY_SPECTRAL_SCAN_FFT_PERIOD;
+ val |= SM(ss->ss_fft_period, AR_PHY_SPECTRAL_SCAN_FFT_PERIOD);
+ }
+
+ if (ss->ss_period != HAL_SPECTRAL_PARAM_NOVAL) {
+ val &= ~AR_PHY_SPECTRAL_SCAN_PERIOD;
+ val |= SM(ss->ss_period, AR_PHY_SPECTRAL_SCAN_PERIOD);
+ }
+
+ if (ss->ss_period != HAL_SPECTRAL_PARAM_NOVAL) {
+ val &= ~AR_PHY_SPECTRAL_SCAN_PERIOD;
+ val |= SM(ss->ss_period, AR_PHY_SPECTRAL_SCAN_PERIOD);
+ }
+
+ /* This section is different for Kiwi and Merlin */
+ if (AR_SREV_MERLIN(ah) ) {
+ if (ss->ss_count != HAL_SPECTRAL_PARAM_NOVAL) {
+ val &= ~AR_PHY_SPECTRAL_SCAN_COUNT;
+ val |= SM(ss->ss_count, AR_PHY_SPECTRAL_SCAN_COUNT);
+ }
+
+ if (ss->ss_short_report == AH_TRUE) {
+ val |= AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT;
+ } else {
+ val &= ~AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT;
+ }
+ } else {
+ if (ss->ss_count != HAL_SPECTRAL_PARAM_NOVAL) {
+ /*
+ * In Merlin, for continous scan, scan_count = 128.
+ * In case of Kiwi, this value should be 0
+ */
+ if (ss->ss_count == 128)
+ ss->ss_count = 0;
+ val &= ~AR_PHY_SPECTRAL_SCAN_COUNT_KIWI;
+ val |= SM(ss->ss_count, AR_PHY_SPECTRAL_SCAN_COUNT_KIWI);
+ }
+
+ if (ss->ss_short_report == AH_TRUE) {
+ val |= AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_KIWI;
+ } else {
+ val &= ~AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_KIWI;
+ }
+
+ //Select the mask to be same as before
+ val |= AR_PHY_SPECTRAL_SCAN_PHYERR_MASK_SELECT_KIWI;
+ }
+ // Enable spectral scan
+ OS_REG_WRITE(ah, AR_PHY_SPECTRAL_SCAN, val | AR_PHY_SPECTRAL_SCAN_ENA);
+
+ ar5416GetSpectralParams(ah, ss);
+}
+
+/*
+ * Get the spectral parameter values and return them in the pe
+ * structure
+ */
+void
+ar5416GetSpectralParams(struct ath_hal *ah, HAL_SPECTRAL_PARAM *ss)
+{
+ uint32_t val;
+
+ val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN);
+
+ ss->ss_fft_period = MS(val, AR_PHY_SPECTRAL_SCAN_FFT_PERIOD);
+ ss->ss_period = MS(val, AR_PHY_SPECTRAL_SCAN_PERIOD);
+ if (AR_SREV_MERLIN(ah) ) {
+ ss->ss_count = MS(val, AR_PHY_SPECTRAL_SCAN_COUNT);
+ ss->ss_short_report = MS(val, AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT);
+ } else {
+ ss->ss_count = MS(val, AR_PHY_SPECTRAL_SCAN_COUNT_KIWI);
+ ss->ss_short_report = MS(val, AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_KIWI);
+ }
+ val = OS_REG_READ(ah, AR_PHY_RADAR_1);
+ ss->radar_bin_thresh_sel = MS(val, AR_PHY_RADAR_1_BIN_THRESH_SELECT);
+}
+
+HAL_BOOL
+ar5416IsSpectralActive(struct ath_hal *ah)
+{
+ uint32_t val;
+
+ val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN);
+ return MS(val, AR_PHY_SPECTRAL_SCAN_ACTIVE);
+}
+
+HAL_BOOL
+ar5416IsSpectralEnabled(struct ath_hal *ah)
+{
+ uint32_t val;
+
+ val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN);
+ return MS(val,AR_PHY_SPECTRAL_SCAN_ENA);
+}
+
+void
+ar5416StartSpectralScan(struct ath_hal *ah)
+{
+ uint32_t val;
+
+ ar5416PrepSpectralScan(ah);
+
+ // Activate spectral scan
+ val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN);
+ val |= AR_PHY_SPECTRAL_SCAN_ENA;
+ val |= AR_PHY_SPECTRAL_SCAN_ACTIVE;
+ OS_REG_WRITE(ah, AR_PHY_SPECTRAL_SCAN, val);
+ val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN);
+ val = OS_REG_READ(ah, AR_PHY_ERR_MASK_REG);
+ OS_REG_WRITE(ah, AR_PHY_ERR_MASK_REG, val | AR_PHY_ERR_RADAR);
+}
+
+void
+ar5416StopSpectralScan(struct ath_hal *ah)
+{
+ uint32_t val;
+ val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN);
+
+ // Deactivate spectral scan
+ val &= ~AR_PHY_SPECTRAL_SCAN_ENA;
+ val &= ~AR_PHY_SPECTRAL_SCAN_ACTIVE;
+ OS_REG_WRITE(ah, AR_PHY_SPECTRAL_SCAN, val);
+ val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN);
+ val = OS_REG_READ(ah, AR_PHY_ERR_MASK_REG) & (~AR_PHY_ERR_RADAR);
+ OS_REG_WRITE(ah, AR_PHY_ERR_MASK_REG, val);
+}
+
+uint32_t
+ar5416GetSpectralConfig(struct ath_hal *ah)
+{
+ uint32_t val;
+
+ val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN);
+ return val;
+}
+
+void
+ar5416RestoreSpectralConfig(struct ath_hal *ah, uint32_t restoreval)
+{
+ uint32_t curval;
+
+ ar5416PrepSpectralScan(ah);
+
+ curval = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN);
+
+ if (restoreval != curval) {
+ restoreval |= AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT;
+ OS_REG_WRITE(ah, AR_PHY_SPECTRAL_SCAN, restoreval);
+ }
+ return;
+}
+
diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416phy.h b/sys/dev/ath/ath_hal/ar5416/ar5416phy.h
index a8171ed..4884dac 100644
--- a/sys/dev/ath/ath_hal/ar5416/ar5416phy.h
+++ b/sys/dev/ath/ath_hal/ar5416/ar5416phy.h
@@ -66,10 +66,27 @@
#define AR_PHY_SPECTRAL_SCAN_FFT_PERIOD_S 4
#define AR_PHY_SPECTRAL_SCAN_PERIOD 0x0000FF00
#define AR_PHY_SPECTRAL_SCAN_PERIOD_S 8
+
+/* Scan count and Short repeat flags are different for Kiwi and Merlin */
#define AR_PHY_SPECTRAL_SCAN_COUNT 0x00FF0000
#define AR_PHY_SPECTRAL_SCAN_COUNT_S 16
+#define AR_PHY_SPECTRAL_SCAN_COUNT_KIWI 0x0FFF0000
+#define AR_PHY_SPECTRAL_SCAN_COUNT_KIWI_S 16
+
#define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT 0x01000000
#define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_S 24
+#define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_KIWI 0x10000000
+#define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_KIWI_S 28
+
+/*
+ * Kiwi only, bit 30 is used to set the error type, if set it is 0x5 (HAL_PHYERR_RADAR)
+ * Else it is 38 (new error type)
+ */
+#define AR_PHY_SPECTRAL_SCAN_PHYERR_MASK_SELECT_KIWI 0x40000000 /* Spectral Error select bit mask */
+#define AR_PHY_SPECTRAL_SCAN_PHYERR_MASK_SELECT_KIWI_S 30 /* Spectral Error select bit 30 */
+
+#define AR_PHY_SPECTRAL_SCAN_PRIORITY_SELECT_KIWI 0x20000000 /* Spectral Error select bit mask */
+#define AR_PHY_SPECTRAL_SCAN_PRIORITY_SELECT_SELECT_KIWI_S 29 /* Spectral Error select bit 30 */
/* For AR_PHY_RADAR0 */
#define AR_PHY_RADAR_0_FFT_ENA 0x80000000
@@ -78,8 +95,8 @@
#define AR_PHY_RADAR_EXT_ENA 0x00004000
#define AR_PHY_RADAR_1 0x9958
-#define AR_PHY_RADAR_1_BIN_THRESH_SEL 0x07000000
-#define AR_PHY_RADAR_1_BIN_THRESH_SEL_S 24
+#define AR_PHY_RADAR_1_BIN_THRESH_SELECT 0x07000000
+#define AR_PHY_RADAR_1_BIN_THRESH_SELECT_S 24
#define AR_PHY_RADAR_1_RELPWR_ENA 0x00800000
#define AR_PHY_RADAR_1_USE_FIR128 0x00400000
#define AR_PHY_RADAR_1_RELPWR_THRESH 0x003F0000
diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416reg.h b/sys/dev/ath/ath_hal/ar5416/ar5416reg.h
index 483d29d..13b7da6 100644
--- a/sys/dev/ath/ath_hal/ar5416/ar5416reg.h
+++ b/sys/dev/ath/ath_hal/ar5416/ar5416reg.h
@@ -179,6 +179,7 @@
#define AR_2040_MODE 0x8318
#define AR_EXTRCCNT 0x8328 /* extension channel rx clear count */
#define AR_SELFGEN_MASK 0x832c /* rx and cal chain masks */
+#define AR_PHY_ERR_MASK_REG 0x8338
#define AR_PCU_TXBUF_CTRL 0x8340
#define AR_PCU_MISC_MODE2 0x8344
diff --git a/sys/dev/ath/ath_hal/ar9002/ar9280_attach.c b/sys/dev/ath/ath_hal/ar9002/ar9280_attach.c
index 5d79418..2a67fe5 100644
--- a/sys/dev/ath/ath_hal/ar9002/ar9280_attach.c
+++ b/sys/dev/ath/ath_hal/ar9002/ar9280_attach.c
@@ -900,6 +900,7 @@ ar9280FillCapabilityInfo(struct ath_hal *ah)
pCap->halHasRxSelfLinkedTail = AH_FALSE;
pCap->halMbssidAggrSupport = AH_TRUE;
pCap->hal4AddrAggrSupport = AH_TRUE;
+ pCap->halSpectralScanSupport = AH_TRUE;
if (AR_SREV_MERLIN_20(ah)) {
pCap->halPSPollBroken = AH_FALSE;
diff --git a/sys/dev/ath/ath_hal/ar9002/ar9285_attach.c b/sys/dev/ath/ath_hal/ar9002/ar9285_attach.c
index 863fcd9..5f6a2a9 100644
--- a/sys/dev/ath/ath_hal/ar9002/ar9285_attach.c
+++ b/sys/dev/ath/ath_hal/ar9002/ar9285_attach.c
@@ -524,6 +524,7 @@ ar9285FillCapabilityInfo(struct ath_hal *ah)
pCap->halHasRxSelfLinkedTail = AH_FALSE;
pCap->halMbssidAggrSupport = AH_TRUE;
pCap->hal4AddrAggrSupport = AH_TRUE;
+ pCap->halSpectralScanSupport = AH_TRUE;
if (AR_SREV_KITE_12_OR_LATER(ah))
pCap->halPSPollBroken = AH_FALSE;
diff --git a/sys/dev/ath/ath_hal/ar9002/ar9287_attach.c b/sys/dev/ath/ath_hal/ar9002/ar9287_attach.c
index b6b8c2c..010e2c3 100644
--- a/sys/dev/ath/ath_hal/ar9002/ar9287_attach.c
+++ b/sys/dev/ath/ath_hal/ar9002/ar9287_attach.c
@@ -453,6 +453,7 @@ ar9287FillCapabilityInfo(struct ath_hal *ah)
/* Disable this so Block-ACK works correctly */
pCap->halHasRxSelfLinkedTail = AH_FALSE;
pCap->halPSPollBroken = AH_FALSE;
+ pCap->halSpectralScanSupport = AH_TRUE;
/* Hardware supports (at least) single-stream STBC TX/RX */
pCap->halRxStbcSupport = 1;
OpenPOWER on IntegriCloud