Signed-off-by: Luis R. Rodriguez <[email protected]>
---
 drivers/net/wireless/ath/ath9k/Makefile     |    1 +
 drivers/net/wireless/ath/ath9k/ani.c        |  341 +-------------------------
 drivers/net/wireless/ath/ath9k/ani.h        |   20 ++
 drivers/net/wireless/ath/ath9k/ar9002_ani.c |  356 +++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath9k/ar9002_hw.c  |    2 +
 drivers/net/wireless/ath/ath9k/hw-ops.h     |   69 +++++
 drivers/net/wireless/ath/ath9k/hw.h         |   35 +++
 7 files changed, 484 insertions(+), 340 deletions(-)
 create mode 100644 drivers/net/wireless/ath/ath9k/ar9002_ani.c

diff --git a/drivers/net/wireless/ath/ath9k/Makefile 
b/drivers/net/wireless/ath/ath9k/Makefile
index affbf84..681fc4f 100644
--- a/drivers/net/wireless/ath/ath9k/Makefile
+++ b/drivers/net/wireless/ath/ath9k/Makefile
@@ -18,6 +18,7 @@ ath9k_hw-y:=  hw.o \
                ar9002_calib.o \
                ar9002_calib_settings.o \
                ar9002_btcoex.o \
+               ar9002_ani.o \
                eeprom.o \
                eeprom_def.o \
                eeprom_4k.o \
diff --git a/drivers/net/wireless/ath/ath9k/ani.c 
b/drivers/net/wireless/ath/ath9k/ani.c
index 024f8f6..bba9c0b 100644
--- a/drivers/net/wireless/ath/ath9k/ani.c
+++ b/drivers/net/wireless/ath/ath9k/ani.c
@@ -22,6 +22,7 @@
  */
 
 #include "hw.h"
+#include "hw-ops.h"
 
 static int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah,
                                        struct ath9k_channel *chan)
@@ -44,232 +45,6 @@ static int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah,
        return 0;
 }
 
-static bool ath9k_hw_ani_control(struct ath_hw *ah,
-                                enum ath9k_ani_cmd cmd, int param)
-{
-       struct ar5416AniState *aniState = ah->curani;
-       struct ath_common *common = ath9k_hw_common(ah);
-
-       switch (cmd & ah->ani_function) {
-       case ATH9K_ANI_NOISE_IMMUNITY_LEVEL:{
-               u32 level = param;
-
-               if (level >= ARRAY_SIZE(ah->totalSizeDesired)) {
-                       ath_print(common, ATH_DBG_ANI,
-                                 "level out of range (%u > %u)\n",
-                                 level,
-                                 (unsigned)ARRAY_SIZE(ah->totalSizeDesired));
-                       return false;
-               }
-
-               REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
-                             AR_PHY_DESIRED_SZ_TOT_DES,
-                             ah->totalSizeDesired[level]);
-               REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1,
-                             AR_PHY_AGC_CTL1_COARSE_LOW,
-                             ah->coarse_low[level]);
-               REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1,
-                             AR_PHY_AGC_CTL1_COARSE_HIGH,
-                             ah->coarse_high[level]);
-               REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
-                             AR_PHY_FIND_SIG_FIRPWR,
-                             ah->firpwr[level]);
-
-               if (level > aniState->noiseImmunityLevel)
-                       ah->stats.ast_ani_niup++;
-               else if (level < aniState->noiseImmunityLevel)
-                       ah->stats.ast_ani_nidown++;
-               aniState->noiseImmunityLevel = level;
-               break;
-       }
-       case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{
-               const int m1ThreshLow[] = { 127, 50 };
-               const int m2ThreshLow[] = { 127, 40 };
-               const int m1Thresh[] = { 127, 0x4d };
-               const int m2Thresh[] = { 127, 0x40 };
-               const int m2CountThr[] = { 31, 16 };
-               const int m2CountThrLow[] = { 63, 48 };
-               u32 on = param ? 1 : 0;
-
-               REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
-                             AR_PHY_SFCORR_LOW_M1_THRESH_LOW,
-                             m1ThreshLow[on]);
-               REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
-                             AR_PHY_SFCORR_LOW_M2_THRESH_LOW,
-                             m2ThreshLow[on]);
-               REG_RMW_FIELD(ah, AR_PHY_SFCORR,
-                             AR_PHY_SFCORR_M1_THRESH,
-                             m1Thresh[on]);
-               REG_RMW_FIELD(ah, AR_PHY_SFCORR,
-                             AR_PHY_SFCORR_M2_THRESH,
-                             m2Thresh[on]);
-               REG_RMW_FIELD(ah, AR_PHY_SFCORR,
-                             AR_PHY_SFCORR_M2COUNT_THR,
-                             m2CountThr[on]);
-               REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
-                             AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW,
-                             m2CountThrLow[on]);
-
-               REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
-                             AR_PHY_SFCORR_EXT_M1_THRESH_LOW,
-                             m1ThreshLow[on]);
-               REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
-                             AR_PHY_SFCORR_EXT_M2_THRESH_LOW,
-                             m2ThreshLow[on]);
-               REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
-                             AR_PHY_SFCORR_EXT_M1_THRESH,
-                             m1Thresh[on]);
-               REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
-                             AR_PHY_SFCORR_EXT_M2_THRESH,
-                             m2Thresh[on]);
-
-               if (on)
-                       REG_SET_BIT(ah, AR_PHY_SFCORR_LOW,
-                                   AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
-               else
-                       REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW,
-                                   AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
-
-               if (!on != aniState->ofdmWeakSigDetectOff) {
-                       if (on)
-                               ah->stats.ast_ani_ofdmon++;
-                       else
-                               ah->stats.ast_ani_ofdmoff++;
-                       aniState->ofdmWeakSigDetectOff = !on;
-               }
-               break;
-       }
-       case ATH9K_ANI_CCK_WEAK_SIGNAL_THR:{
-               const int weakSigThrCck[] = { 8, 6 };
-               u32 high = param ? 1 : 0;
-
-               REG_RMW_FIELD(ah, AR_PHY_CCK_DETECT,
-                             AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK,
-                             weakSigThrCck[high]);
-               if (high != aniState->cckWeakSigThreshold) {
-                       if (high)
-                               ah->stats.ast_ani_cckhigh++;
-                       else
-                               ah->stats.ast_ani_ccklow++;
-                       aniState->cckWeakSigThreshold = high;
-               }
-               break;
-       }
-       case ATH9K_ANI_FIRSTEP_LEVEL:{
-               const int firstep[] = { 0, 4, 8 };
-               u32 level = param;
-
-               if (level >= ARRAY_SIZE(firstep)) {
-                       ath_print(common, ATH_DBG_ANI,
-                                 "level out of range (%u > %u)\n",
-                                 level,
-                                 (unsigned) ARRAY_SIZE(firstep));
-                       return false;
-               }
-               REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
-                             AR_PHY_FIND_SIG_FIRSTEP,
-                             firstep[level]);
-               if (level > aniState->firstepLevel)
-                       ah->stats.ast_ani_stepup++;
-               else if (level < aniState->firstepLevel)
-                       ah->stats.ast_ani_stepdown++;
-               aniState->firstepLevel = level;
-               break;
-       }
-       case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{
-               const int cycpwrThr1[] =
-                       { 2, 4, 6, 8, 10, 12, 14, 16 };
-               u32 level = param;
-
-               if (level >= ARRAY_SIZE(cycpwrThr1)) {
-                       ath_print(common, ATH_DBG_ANI,
-                                 "level out of range (%u > %u)\n",
-                                 level,
-                                 (unsigned) ARRAY_SIZE(cycpwrThr1));
-                       return false;
-               }
-               REG_RMW_FIELD(ah, AR_PHY_TIMING5,
-                             AR_PHY_TIMING5_CYCPWR_THR1,
-                             cycpwrThr1[level]);
-               if (level > aniState->spurImmunityLevel)
-                       ah->stats.ast_ani_spurup++;
-               else if (level < aniState->spurImmunityLevel)
-                       ah->stats.ast_ani_spurdown++;
-               aniState->spurImmunityLevel = level;
-               break;
-       }
-       case ATH9K_ANI_PRESENT:
-               break;
-       default:
-               ath_print(common, ATH_DBG_ANI,
-                         "invalid cmd %u\n", cmd);
-               return false;
-       }
-
-       ath_print(common, ATH_DBG_ANI, "ANI parameters:\n");
-       ath_print(common, ATH_DBG_ANI,
-                 "noiseImmunityLevel=%d, spurImmunityLevel=%d, "
-                 "ofdmWeakSigDetectOff=%d\n",
-                 aniState->noiseImmunityLevel,
-                 aniState->spurImmunityLevel,
-                 !aniState->ofdmWeakSigDetectOff);
-       ath_print(common, ATH_DBG_ANI,
-                 "cckWeakSigThreshold=%d, "
-                 "firstepLevel=%d, listenTime=%d\n",
-                 aniState->cckWeakSigThreshold,
-                 aniState->firstepLevel,
-                 aniState->listenTime);
-       ath_print(common, ATH_DBG_ANI,
-               "cycleCount=%d, ofdmPhyErrCount=%d, cckPhyErrCount=%d\n\n",
-               aniState->cycleCount,
-               aniState->ofdmPhyErrCount,
-               aniState->cckPhyErrCount);
-
-       return true;
-}
-
-static void ath9k_hw_update_mibstats(struct ath_hw *ah,
-                                    struct ath9k_mib_stats *stats)
-{
-       stats->ackrcv_bad += REG_READ(ah, AR_ACK_FAIL);
-       stats->rts_bad += REG_READ(ah, AR_RTS_FAIL);
-       stats->fcs_bad += REG_READ(ah, AR_FCS_FAIL);
-       stats->rts_good += REG_READ(ah, AR_RTS_OK);
-       stats->beacons += REG_READ(ah, AR_BEACON_CNT);
-}
-
-/*
- * These masks are used by the hardware to know which
- * type of phy errors to include on their error counts.
- * We use one counter for OFDM phy timing errors and the
- * other for CCK phy timing errors only.
- */
-static void ath9k_hw_update_phy_err_masks(struct ath_hw *ah)
-{
-       REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
-       REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
-}
-
-static void ath9k_hw_update_phy_err1_count(struct ath_hw *ah,
-                                          u32 err_count,
-                                          bool reset_mask)
-{
-       REG_WRITE(ah, AR_PHY_ERR_1, err_count);
-
-       if (reset_mask)
-               REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
-}
-
-static void ath9k_hw_update_phy_err2_count(struct ath_hw *ah,
-                                          u32 err_count,
-                                          bool reset_mask)
-{
-       REG_WRITE(ah, AR_PHY_ERR_2, err_count);
-
-       if (reset_mask)
-               REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
-}
-
 /**
  * ath9k_hw_update_phy_err_count - update phy error counts
  *
@@ -323,26 +98,6 @@ static void ath9k_hw_update_phy_err_count(struct ath_hw *ah,
        ath9k_hw_update_phy_err2_count(ah, phy_err_count2, reset_masks);
 }
 
-static void ath9k_hw_get_phy_err_count(struct ath_hw *ah,
-                                      u32 *phy_err_count1,
-                                      u32 *phy_err_count2)
-{
-       *phy_err_count1 = REG_READ(ah, AR_PHY_ERR_1);
-       *phy_err_count2 = REG_READ(ah, AR_PHY_ERR_2);
-}
-
-static void ath9k_hw_get_mib_cycle_counters(struct ath_hw *ah,
-                                           u32 *rx_clear_count,
-                                           u32 *rx_frame_count,
-                                           u32 *tx_frame_count,
-                                           u32 *cycle_count)
-{
-       *rx_clear_count = REG_READ(ah, AR_RCCNT);
-       *rx_frame_count = REG_READ(ah, AR_RFCNT);
-       *tx_frame_count = REG_READ(ah, AR_TFCNT);
-       *cycle_count = REG_READ(ah, AR_CCCNT);
-}
-
 static void ath9k_ani_restart(struct ath_hw *ah)
 {
        struct ar5416AniState *aniState;
@@ -781,100 +536,6 @@ void ath9k_hw_ani_monitor(struct ath_hw *ah,
 }
 EXPORT_SYMBOL(ath9k_hw_ani_monitor);
 
-
-/**
- * ath9k_hw_clear_mib_counters - clears all MIB counters
- *
- * @ah: atheros hardware structure
- *
- * Used to clear all MIB counters for the OFDM and CCK filtered
- * frames and also the clock cycle counters and clock cycles we
- * have spent sleeping. Refer to ath9k_hw_update_phy_err_count()
- * for more documentation on the filtered frames, below we cover
- * the clock cycle counters and sleep cycle counters.
- *
- * 0x8250           32KHz Sleep MIB Count
- * (Int Addr: 0x94, Access, R/W, cold_reset, Clock: clk)
- *       SLPMIB1                 31:0    'h0     bit 31:0   SLPMIB_SLEEP_CNT
- *
- * 0x8254           32KHz Cycle MIB Count
- *        (Int Addr: 0x95, Access, R/W, cold_reset, Clock: clk)
- *        SLPMIB2                 31:0    'h0     bit 31:0   SLPMIB_CYCLE_CNT
- *
- * 0x8258           32KHz Mode MIB Control Status
- *        (Int Addr: 0x96, Access, R/W, cold_reset, Clock: clk)
- *        SLPMIB3                  1:0    'h0     bit 0      SLPMIB_CLR_CNT
- *                                        'h0    bit 1      SLPMIB_PEND
- *
- * The SLPMIB_SLEEP_CNT counts the number of 32KHz clock cycles that
- * the MAC has been asleep.  The SLPMIB_CYCLE_CNT is the counts the
- * absolute number of 32KHz clock cycles.  When the SLPMIB_CYCLE_CNT
- * bit 31 is 1, the sleep MIB interrupt will be asserted.  The
- * SLPMIB_SLEEP_CNT and SLPMIB_CYCLE_CNT are saturating counters when
- * the value of SLPMIB_CYCLE_CNT reaches 0xFFFF_FFFF both counters
- * will stop incrementing.  The SLPMIB_CLR_CNT will clear both the
- * SLPMIB_SLEEP_CNT and SLPMIB_CYCLE_CNT.  During the time that the
- * clearing of these register are pending the SLPMIB_CLR_PEND will
- * be asserted.  SLPMIB_SLEEP_CNT, SLPMIB_CYCLE_CNT, and
- * SLPMIB_CLR_CNT are writable for diagnostic purposes.  Before every
- * read/write, the SLPMIB_PEND bit should be polled to verify any
- * pending write has cleared.
- */
-static void ath9k_hw_clear_mib_counters(struct ath_hw *ah,
-                                       bool check_clock_cycles)
-{
-       REG_WRITE(ah, AR_FILT_OFDM, 0);
-       REG_WRITE(ah, AR_FILT_CCK, 0);
-
-       if (!check_clock_cycles)
-               return;
-
-       if (!(REG_READ(ah, AR_SLP_MIB_CTRL) & AR_SLP_MIB_PENDING))
-               REG_WRITE(ah, AR_SLP_MIB_CTRL, AR_SLP_MIB_CLEAR);
-}
-
-/**
- * ath9k_hw_mibc_cmd - commands for the MIB control register (MIBC)
- *
- * @ATH9K_HW_MIBC_INIT: initializes the register
- * @ATH9K_HW_MIBC_WARN_TEST: Warning test indicator
- * @ATH9K_HW_MIBC_FREEZE: freeze all counters, useful prior to collecting
- *     the MIB counters.
- * @ATH9K_HW_MIBC_CLEAR: clear all counters, can be used after collecting
- *     the MIB counters.
- * @ATH9K_HW_MIBC_STROBE: MIB counter strobe, can increment every
- *     counter by 1.
- */
-enum ath9k_hw_mibc_cmd {
-       ATH9K_HW_MIBC_INIT = 0,
-       ATH9K_HW_MIBC_WARN_TEST,
-       ATH9K_HW_MIBC_FREEZE,
-       ATH9K_HW_MIBC_CLEAR,
-       ATH9K_HW_MIBC_STROBE,
-};
-
-static void ath9k_hw_send_mibc_cmd(struct ath_hw *ah,
-                                  enum ath9k_hw_mibc_cmd cmd)
-{
-       switch (cmd) {
-       case ATH9K_HW_MIBC_INIT:
-               REG_WRITE(ah, AR_MIBC, 0);
-               break;
-       case ATH9K_HW_MIBC_WARN_TEST: /* unused */
-               REG_WRITE(ah, AR_MIBC, AR_MIBC_COW);
-               break;
-       case ATH9K_HW_MIBC_FREEZE:
-               REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC);
-               break;
-       case ATH9K_HW_MIBC_CLEAR:
-               REG_WRITE(ah, AR_MIBC, AR_MIBC_CMC);
-               break;
-       case ATH9K_HW_MIBC_STROBE: /* unused */
-               REG_WRITE(ah, AR_MIBC, AR_MIBC_MCS);
-               break;
-       }
-}
-
 void ath9k_enable_mib_counters(struct ath_hw *ah)
 {
        struct ath_common *common = ath9k_hw_common(ah);
diff --git a/drivers/net/wireless/ath/ath9k/ani.h 
b/drivers/net/wireless/ath/ath9k/ani.h
index 01c07e2..f9879e4 100644
--- a/drivers/net/wireless/ath/ath9k/ani.h
+++ b/drivers/net/wireless/ath/ath9k/ani.h
@@ -40,6 +40,26 @@
 #define HAL_SPUR_IMMUNE_MAX               7
 #define HAL_FIRST_STEP_MAX                2
 
+/**
+ * ath9k_hw_mibc_cmd - commands for the MIB control register (MIBC)
+ *
+ * @ATH9K_HW_MIBC_INIT: initializes the register
+ * @ATH9K_HW_MIBC_WARN_TEST: Warning test indicator
+ * @ATH9K_HW_MIBC_FREEZE: freeze all counters, useful prior to collecting
+ *     the MIB counters.
+ * @ATH9K_HW_MIBC_CLEAR: clear all counters, can be used after collecting
+ *     the MIB counters.
+ * @ATH9K_HW_MIBC_STROBE: MIB counter strobe, can increment every
+ *     counter by 1.
+ */
+enum ath9k_hw_mibc_cmd {
+       ATH9K_HW_MIBC_INIT = 0,
+       ATH9K_HW_MIBC_WARN_TEST,
+       ATH9K_HW_MIBC_FREEZE,
+       ATH9K_HW_MIBC_CLEAR,
+       ATH9K_HW_MIBC_STROBE,
+};
+
 enum ath9k_ani_cmd {
        ATH9K_ANI_PRESENT = 0x1,
        ATH9K_ANI_NOISE_IMMUNITY_LEVEL = 0x2,
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_ani.c 
b/drivers/net/wireless/ath/ath9k/ar9002_ani.c
new file mode 100644
index 0000000..39ede2d
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/ar9002_ani.c
@@ -0,0 +1,356 @@
+/*
+ * Copyright (c) 2008-2010 Atheros Communications Inc.
+ *
+ * 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.
+ */
+
+/*
+ * Adaptive Noise Immunity for the AR5008, AR9001 and AR9002 family
+ */
+
+#include "hw.h"
+
+static bool ar9002_hw_ani_control(struct ath_hw *ah,
+                                 enum ath9k_ani_cmd cmd,
+                                 int param)
+{
+       struct ar5416AniState *aniState = ah->curani;
+       struct ath_common *common = ath9k_hw_common(ah);
+
+       switch (cmd & ah->ani_function) {
+       case ATH9K_ANI_NOISE_IMMUNITY_LEVEL:{
+               u32 level = param;
+
+               if (level >= ARRAY_SIZE(ah->totalSizeDesired)) {
+                       ath_print(common, ATH_DBG_ANI,
+                                 "level out of range (%u > %u)\n",
+                                 level,
+                                 (unsigned)ARRAY_SIZE(ah->totalSizeDesired));
+                       return false;
+               }
+
+               REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
+                             AR_PHY_DESIRED_SZ_TOT_DES,
+                             ah->totalSizeDesired[level]);
+               REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1,
+                             AR_PHY_AGC_CTL1_COARSE_LOW,
+                             ah->coarse_low[level]);
+               REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1,
+                             AR_PHY_AGC_CTL1_COARSE_HIGH,
+                             ah->coarse_high[level]);
+               REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
+                             AR_PHY_FIND_SIG_FIRPWR,
+                             ah->firpwr[level]);
+
+               if (level > aniState->noiseImmunityLevel)
+                       ah->stats.ast_ani_niup++;
+               else if (level < aniState->noiseImmunityLevel)
+                       ah->stats.ast_ani_nidown++;
+               aniState->noiseImmunityLevel = level;
+               break;
+       }
+       case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{
+               const int m1ThreshLow[] = { 127, 50 };
+               const int m2ThreshLow[] = { 127, 40 };
+               const int m1Thresh[] = { 127, 0x4d };
+               const int m2Thresh[] = { 127, 0x40 };
+               const int m2CountThr[] = { 31, 16 };
+               const int m2CountThrLow[] = { 63, 48 };
+               u32 on = param ? 1 : 0;
+
+               REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
+                             AR_PHY_SFCORR_LOW_M1_THRESH_LOW,
+                             m1ThreshLow[on]);
+               REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
+                             AR_PHY_SFCORR_LOW_M2_THRESH_LOW,
+                             m2ThreshLow[on]);
+               REG_RMW_FIELD(ah, AR_PHY_SFCORR,
+                             AR_PHY_SFCORR_M1_THRESH,
+                             m1Thresh[on]);
+               REG_RMW_FIELD(ah, AR_PHY_SFCORR,
+                             AR_PHY_SFCORR_M2_THRESH,
+                             m2Thresh[on]);
+               REG_RMW_FIELD(ah, AR_PHY_SFCORR,
+                             AR_PHY_SFCORR_M2COUNT_THR,
+                             m2CountThr[on]);
+               REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
+                             AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW,
+                             m2CountThrLow[on]);
+
+               REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+                             AR_PHY_SFCORR_EXT_M1_THRESH_LOW,
+                             m1ThreshLow[on]);
+               REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+                             AR_PHY_SFCORR_EXT_M2_THRESH_LOW,
+                             m2ThreshLow[on]);
+               REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+                             AR_PHY_SFCORR_EXT_M1_THRESH,
+                             m1Thresh[on]);
+               REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+                             AR_PHY_SFCORR_EXT_M2_THRESH,
+                             m2Thresh[on]);
+
+               if (on)
+                       REG_SET_BIT(ah, AR_PHY_SFCORR_LOW,
+                                   AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
+               else
+                       REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW,
+                                   AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
+
+               if (!on != aniState->ofdmWeakSigDetectOff) {
+                       if (on)
+                               ah->stats.ast_ani_ofdmon++;
+                       else
+                               ah->stats.ast_ani_ofdmoff++;
+                       aniState->ofdmWeakSigDetectOff = !on;
+               }
+               break;
+       }
+       case ATH9K_ANI_CCK_WEAK_SIGNAL_THR:{
+               const int weakSigThrCck[] = { 8, 6 };
+               u32 high = param ? 1 : 0;
+
+               REG_RMW_FIELD(ah, AR_PHY_CCK_DETECT,
+                             AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK,
+                             weakSigThrCck[high]);
+               if (high != aniState->cckWeakSigThreshold) {
+                       if (high)
+                               ah->stats.ast_ani_cckhigh++;
+                       else
+                               ah->stats.ast_ani_ccklow++;
+                       aniState->cckWeakSigThreshold = high;
+               }
+               break;
+       }
+       case ATH9K_ANI_FIRSTEP_LEVEL:{
+               const int firstep[] = { 0, 4, 8 };
+               u32 level = param;
+
+               if (level >= ARRAY_SIZE(firstep)) {
+                       ath_print(common, ATH_DBG_ANI,
+                                 "level out of range (%u > %u)\n",
+                                 level,
+                                 (unsigned) ARRAY_SIZE(firstep));
+                       return false;
+               }
+               REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
+                             AR_PHY_FIND_SIG_FIRSTEP,
+                             firstep[level]);
+               if (level > aniState->firstepLevel)
+                       ah->stats.ast_ani_stepup++;
+               else if (level < aniState->firstepLevel)
+                       ah->stats.ast_ani_stepdown++;
+               aniState->firstepLevel = level;
+               break;
+       }
+       case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{
+               const int cycpwrThr1[] =
+                       { 2, 4, 6, 8, 10, 12, 14, 16 };
+               u32 level = param;
+
+               if (level >= ARRAY_SIZE(cycpwrThr1)) {
+                       ath_print(common, ATH_DBG_ANI,
+                                 "level out of range (%u > %u)\n",
+                                 level,
+                                 (unsigned) ARRAY_SIZE(cycpwrThr1));
+                       return false;
+               }
+               REG_RMW_FIELD(ah, AR_PHY_TIMING5,
+                             AR_PHY_TIMING5_CYCPWR_THR1,
+                             cycpwrThr1[level]);
+               if (level > aniState->spurImmunityLevel)
+                       ah->stats.ast_ani_spurup++;
+               else if (level < aniState->spurImmunityLevel)
+                       ah->stats.ast_ani_spurdown++;
+               aniState->spurImmunityLevel = level;
+               break;
+       }
+       case ATH9K_ANI_PRESENT:
+               break;
+       default:
+               ath_print(common, ATH_DBG_ANI,
+                         "invalid cmd %u\n", cmd);
+               return false;
+       }
+
+       ath_print(common, ATH_DBG_ANI, "ANI parameters:\n");
+       ath_print(common, ATH_DBG_ANI,
+                 "noiseImmunityLevel=%d, spurImmunityLevel=%d, "
+                 "ofdmWeakSigDetectOff=%d\n",
+                 aniState->noiseImmunityLevel,
+                 aniState->spurImmunityLevel,
+                 !aniState->ofdmWeakSigDetectOff);
+       ath_print(common, ATH_DBG_ANI,
+                 "cckWeakSigThreshold=%d, "
+                 "firstepLevel=%d, listenTime=%d\n",
+                 aniState->cckWeakSigThreshold,
+                 aniState->firstepLevel,
+                 aniState->listenTime);
+       ath_print(common, ATH_DBG_ANI,
+               "cycleCount=%d, ofdmPhyErrCount=%d, cckPhyErrCount=%d\n\n",
+               aniState->cycleCount,
+               aniState->ofdmPhyErrCount,
+               aniState->cckPhyErrCount);
+
+       return true;
+}
+
+static void ar9002_hw_update_mibstats(struct ath_hw *ah,
+                                     struct ath9k_mib_stats *stats)
+{
+       stats->ackrcv_bad += REG_READ(ah, AR_ACK_FAIL);
+       stats->rts_bad += REG_READ(ah, AR_RTS_FAIL);
+       stats->fcs_bad += REG_READ(ah, AR_FCS_FAIL);
+       stats->rts_good += REG_READ(ah, AR_RTS_OK);
+       stats->beacons += REG_READ(ah, AR_BEACON_CNT);
+}
+
+/*
+ * These masks are used by the hardware to know which
+ * type of phy errors to include on their error counts.
+ * We use one counter for OFDM phy timing errors and the
+ * other for CCK phy timing errors only.
+ */
+static void ar9002_hw_update_phy_err_masks(struct ath_hw *ah)
+{
+       REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
+       REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
+}
+
+static void ar9002_hw_update_phy_err1_count(struct ath_hw *ah,
+                                           u32 err_count,
+                                           bool reset_mask)
+{
+       REG_WRITE(ah, AR_PHY_ERR_1, err_count);
+
+       if (reset_mask)
+               REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
+}
+
+static void ar9002_hw_update_phy_err2_count(struct ath_hw *ah,
+                                           u32 err_count,
+                                           bool reset_mask)
+{
+       REG_WRITE(ah, AR_PHY_ERR_2, err_count);
+
+       if (reset_mask)
+               REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
+}
+
+static void ar9002_hw_get_phy_err_count(struct ath_hw *ah,
+                                       u32 *phy_err_count1,
+                                       u32 *phy_err_count2)
+{
+       *phy_err_count1 = REG_READ(ah, AR_PHY_ERR_1);
+       *phy_err_count2 = REG_READ(ah, AR_PHY_ERR_2);
+}
+
+static void ar9002_hw_get_mib_cycle_counters(struct ath_hw *ah,
+                                            u32 *rx_clear_count,
+                                            u32 *rx_frame_count,
+                                            u32 *tx_frame_count,
+                                            u32 *cycle_count)
+{
+       *rx_clear_count = REG_READ(ah, AR_RCCNT);
+       *rx_frame_count = REG_READ(ah, AR_RFCNT);
+       *tx_frame_count = REG_READ(ah, AR_TFCNT);
+       *cycle_count = REG_READ(ah, AR_CCCNT);
+}
+
+/**
+ * ar9002_hw_clear_mib_counters - clears all MIB counters
+ *
+ * @ah: atheros hardware structure
+ *
+ * Used to clear all MIB counters for the OFDM and CCK filtered
+ * frames and also the clock cycle counters and clock cycles we
+ * have spent sleeping. Refer to ath9k_hw_update_phy_err_count()
+ * for more documentation on the filtered frames, below we cover
+ * the clock cycle counters and sleep cycle counters.
+ *
+ * 0x8250           32KHz Sleep MIB Count
+ * (Int Addr: 0x94, Access, R/W, cold_reset, Clock: clk)
+ *       SLPMIB1                 31:0    'h0     bit 31:0   SLPMIB_SLEEP_CNT
+ *
+ * 0x8254           32KHz Cycle MIB Count
+ *        (Int Addr: 0x95, Access, R/W, cold_reset, Clock: clk)
+ *        SLPMIB2                 31:0    'h0     bit 31:0   SLPMIB_CYCLE_CNT
+ *
+ * 0x8258           32KHz Mode MIB Control Status
+ *        (Int Addr: 0x96, Access, R/W, cold_reset, Clock: clk)
+ *        SLPMIB3                  1:0    'h0     bit 0      SLPMIB_CLR_CNT
+ *                                        'h0    bit 1      SLPMIB_PEND
+ *
+ * The SLPMIB_SLEEP_CNT counts the number of 32KHz clock cycles that
+ * the MAC has been asleep.  The SLPMIB_CYCLE_CNT is the counts the
+ * absolute number of 32KHz clock cycles.  When the SLPMIB_CYCLE_CNT
+ * bit 31 is 1, the sleep MIB interrupt will be asserted.  The
+ * SLPMIB_SLEEP_CNT and SLPMIB_CYCLE_CNT are saturating counters when
+ * the value of SLPMIB_CYCLE_CNT reaches 0xFFFF_FFFF both counters
+ * will stop incrementing.  The SLPMIB_CLR_CNT will clear both the
+ * SLPMIB_SLEEP_CNT and SLPMIB_CYCLE_CNT.  During the time that the
+ * clearing of these register are pending the SLPMIB_CLR_PEND will
+ * be asserted.  SLPMIB_SLEEP_CNT, SLPMIB_CYCLE_CNT, and
+ * SLPMIB_CLR_CNT are writable for diagnostic purposes.  Before every
+ * read/write, the SLPMIB_PEND bit should be polled to verify any
+ * pending write has cleared.
+ */
+static void ar9002_hw_clear_mib_counters(struct ath_hw *ah,
+                                        bool check_clock_cycles)
+{
+       REG_WRITE(ah, AR_FILT_OFDM, 0);
+       REG_WRITE(ah, AR_FILT_CCK, 0);
+
+       if (!check_clock_cycles)
+               return;
+
+       if (!(REG_READ(ah, AR_SLP_MIB_CTRL) & AR_SLP_MIB_PENDING))
+               REG_WRITE(ah, AR_SLP_MIB_CTRL, AR_SLP_MIB_CLEAR);
+}
+
+static void ar9002_hw_send_mibc_cmd(struct ath_hw *ah,
+                                   enum ath9k_hw_mibc_cmd cmd)
+{
+       switch (cmd) {
+       case ATH9K_HW_MIBC_INIT:
+               REG_WRITE(ah, AR_MIBC, 0);
+               break;
+       case ATH9K_HW_MIBC_WARN_TEST: /* unused */
+               REG_WRITE(ah, AR_MIBC, AR_MIBC_COW);
+               break;
+       case ATH9K_HW_MIBC_FREEZE:
+               REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC);
+               break;
+       case ATH9K_HW_MIBC_CLEAR:
+               REG_WRITE(ah, AR_MIBC, AR_MIBC_CMC);
+               break;
+       case ATH9K_HW_MIBC_STROBE: /* unused */
+               REG_WRITE(ah, AR_MIBC, AR_MIBC_MCS);
+               break;
+       }
+}
+
+void ar9002_hw_attach_ani_ops(struct ath_hw *ah)
+{
+       struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
+
+       priv_ops->ani_control = &ar9002_hw_ani_control;
+       priv_ops->update_mibstats = &ar9002_hw_update_mibstats;
+       priv_ops->update_phy_err_masks = &ar9002_hw_update_phy_err_masks;
+       priv_ops->update_phy_err1_count = &ar9002_hw_update_phy_err1_count;
+       priv_ops->update_phy_err2_count = &ar9002_hw_update_phy_err2_count;
+       priv_ops->get_phy_err_count = &ar9002_hw_get_phy_err_count;
+       priv_ops->get_mib_cycle_counters = &ar9002_hw_get_mib_cycle_counters;
+       priv_ops->clear_mib_counters = &ar9002_hw_clear_mib_counters;
+       priv_ops->send_mibc_cmd = &ar9002_hw_send_mibc_cmd;
+}
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c 
b/drivers/net/wireless/ath/ath9k/ar9002_hw.c
index 8e5a07d..2356611 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c
@@ -20,6 +20,7 @@
 #include "ar9002_initvals.h"
 
 extern void ar9002_hw_attach_btcoex_ops(struct ath_hw *ah);
+extern void ar9002_hw_attach_ani_ops(struct ath_hw *ah);
 
 static void ar9002_hw_disablepcie(struct ath_hw *ah)
 {
@@ -815,5 +816,6 @@ void ar9002_hw_attach_ops(struct ath_hw *ah)
 
        ar9002_hw_attach_calib_ops(ah);
        ar9002_hw_attach_btcoex_ops(ah);
+       ar9002_hw_attach_ani_ops(ah);
 }
 EXPORT_SYMBOL(ar9002_hw_attach_ops);
diff --git a/drivers/net/wireless/ath/ath9k/hw-ops.h 
b/drivers/net/wireless/ath/ath9k/hw-ops.h
index 3e4f49f..006e260 100644
--- a/drivers/net/wireless/ath/ath9k/hw-ops.h
+++ b/drivers/net/wireless/ath/ath9k/hw-ops.h
@@ -163,4 +163,73 @@ static inline void ath9k_hw_btcoex_disable(struct ath_hw 
*ah)
        ath9k_hw_ops(ah)->btcoex_disable(ah);
 }
 
+/* ANI ops */
+
+static inline bool ath9k_hw_ani_control(struct ath_hw *ah,
+                                       enum ath9k_ani_cmd cmd,
+                                       int param)
+{
+       return ath9k_hw_private_ops(ah)->ani_control(ah, cmd, param);
+}
+
+static inline void ath9k_hw_update_mibstats(struct ath_hw *ah,
+                                           struct ath9k_mib_stats *stats)
+{
+       ath9k_hw_private_ops(ah)->update_mibstats(ah, stats);
+}
+
+static inline void ath9k_hw_update_phy_err_masks(struct ath_hw *ah)
+{
+       ath9k_hw_private_ops(ah)->update_phy_err_masks(ah);
+}
+
+static inline void ath9k_hw_update_phy_err1_count(struct ath_hw *ah,
+                                                 u32 err_count,
+                                                 bool reset_mask)
+{
+       ath9k_hw_private_ops(ah)->update_phy_err1_count(ah, err_count,
+                                                       reset_mask);
+}
+
+static inline void ath9k_hw_update_phy_err2_count(struct ath_hw *ah,
+                                                 u32 err_count,
+                                                 bool reset_mask)
+{
+       ath9k_hw_private_ops(ah)->update_phy_err2_count(ah, err_count,
+                                                       reset_mask);
+}
+
+static inline void ath9k_hw_get_phy_err_count(struct ath_hw *ah,
+                                             u32 *phy_err_count1,
+                                             u32 *phy_err_count2)
+{
+       ath9k_hw_private_ops(ah)->get_phy_err_count(ah, phy_err_count1,
+                                                   phy_err_count2);
+}
+
+static inline void ath9k_hw_get_mib_cycle_counters(struct ath_hw *ah,
+                                                  u32 *rx_clear_count,
+                                                  u32 *rx_frame_count,
+                                                  u32 *tx_frame_count,
+                                                  u32 *cycle_count)
+{
+       ath9k_hw_private_ops(ah)->get_mib_cycle_counters(ah,
+                                                        rx_clear_count,
+                                                        rx_frame_count,
+                                                        tx_frame_count,
+                                                        cycle_count);
+}
+
+static inline void ath9k_hw_clear_mib_counters(struct ath_hw *ah,
+                                              bool check_clock_cycles)
+{
+       ath9k_hw_private_ops(ah)->clear_mib_counters(ah, check_clock_cycles);
+}
+
+static inline void ath9k_hw_send_mibc_cmd(struct ath_hw *ah,
+                                         enum ath9k_hw_mibc_cmd cmd)
+{
+       ath9k_hw_private_ops(ah)->send_mibc_cmd(ah, cmd);
+}
+
 #endif /* ATH9K_HW_OPS_H */
diff --git a/drivers/net/wireless/ath/ath9k/hw.h 
b/drivers/net/wireless/ath/ath9k/hw.h
index ed137a8..259761d 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -469,6 +469,16 @@ struct ath_gen_timer_table {
  * @btcoex_supported: whether or not bluetooth coexistence is supported
  * @btcoex_enable_2wire:
  * @btcoex_enable_3wire:
+ *
+ * @ani_control:
+ * @update_mibstats:
+ * @update_phy_err_masks:
+ * @update_phy_err1_count:
+ * @update_phy_err2_count:
+ * @get_phy_err_count:
+ * @get_mib_cycle_counters:
+ * @clear_mib_counters:
+ * @send_mibc_cmd:
  */
 struct ath_hw_private_ops {
        /* General hardware ops */
@@ -499,6 +509,31 @@ struct ath_hw_private_ops {
        bool (*btcoex_supported)(struct ath_hw *ah);
        void (*btcoex_enable_2wire)(struct ath_hw *ah);
        void (*btcoex_enable_3wire)(struct ath_hw *ah);
+
+       /* ANI */
+       bool (*ani_control)(struct ath_hw *ah,
+                           enum ath9k_ani_cmd cmd, int param);
+       void (*update_mibstats)(struct ath_hw *ah,
+                               struct ath9k_mib_stats *stats);
+       void (*update_phy_err_masks)(struct ath_hw *ah);
+       void (*update_phy_err1_count)(struct ath_hw *ah,
+                                     u32 err_count,
+                                     bool reset_mask);
+       void (*update_phy_err2_count)(struct ath_hw *ah,
+                                     u32 err_count,
+                                     bool reset_mask);
+       void (*get_phy_err_count)(struct ath_hw *ah,
+                                 u32 *phy_err_count1,
+                                 u32 *phy_err_count2);
+       void (*get_mib_cycle_counters)(struct ath_hw *ah,
+                                      u32 *rx_clear_count,
+                                      u32 *rx_frame_count,
+                                      u32 *tx_frame_count,
+                                      u32 *cycle_count);
+       void (*clear_mib_counters)(struct ath_hw *ah,
+                                  bool check_clock_cycles);
+       void (*send_mibc_cmd)(struct ath_hw *ah,
+                             enum ath9k_hw_mibc_cmd cmd);
 };
 
 /**
-- 
1.6.3.3

_______________________________________________
ath9k-devel mailing list
[email protected]
https://lists.ath9k.org/mailman/listinfo/ath9k-devel

Reply via email to