ath9k: Fix diversity combining for AR9285
[cascardo/linux.git] / drivers / net / wireless / ath / ath9k / ar9003_phy.c
index e1714d7..3ec33ce 100644 (file)
@@ -632,6 +632,22 @@ static void ar9003_hw_override_ini(struct ath_hw *ah)
 
        REG_SET_BIT(ah, AR_PHY_CCK_DETECT,
                    AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV);
+
+       if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) {
+               REG_WRITE(ah, AR_GLB_SWREG_DISCONT_MODE,
+                         AR_GLB_SWREG_DISCONT_EN_BT_WLAN);
+
+               if (REG_READ_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_0,
+                                  AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL))
+                       ah->enabled_cals |= TX_IQ_CAL;
+               else
+                       ah->enabled_cals &= ~TX_IQ_CAL;
+
+               if (REG_READ(ah, AR_PHY_CL_CAL_CTL) & AR_PHY_CL_CAL_ENABLE)
+                       ah->enabled_cals |= TX_CL_CAL;
+               else
+                       ah->enabled_cals &= ~TX_CL_CAL;
+       }
 }
 
 static void ar9003_hw_prog_ini(struct ath_hw *ah,
@@ -735,22 +751,53 @@ static int ar9003_hw_process_ini(struct ath_hw *ah,
                return -EINVAL;
        }
 
+       /*
+        * SOC, MAC, BB, RADIO initvals.
+        */
        for (i = 0; i < ATH_INI_NUM_SPLIT; i++) {
                ar9003_hw_prog_ini(ah, &ah->iniSOC[i], modesIndex);
                ar9003_hw_prog_ini(ah, &ah->iniMac[i], modesIndex);
                ar9003_hw_prog_ini(ah, &ah->iniBB[i], modesIndex);
                ar9003_hw_prog_ini(ah, &ah->iniRadio[i], modesIndex);
-               if (i == ATH_INI_POST && AR_SREV_9462_20(ah))
+               if (i == ATH_INI_POST && AR_SREV_9462_20_OR_LATER(ah))
                        ar9003_hw_prog_ini(ah,
                                           &ah->ini_radio_post_sys2ant,
                                           modesIndex);
        }
 
+       /*
+        * RXGAIN initvals.
+        */
        REG_WRITE_ARRAY(&ah->iniModesRxGain, 1, regWrites);
+
+       if (AR_SREV_9462_20_OR_LATER(ah)) {
+               /*
+                * CUS217 mix LNA mode.
+                */
+               if (ar9003_hw_get_rx_gain_idx(ah) == 2) {
+                       REG_WRITE_ARRAY(&ah->ini_modes_rxgain_bb_core,
+                                       1, regWrites);
+                       REG_WRITE_ARRAY(&ah->ini_modes_rxgain_bb_postamble,
+                                       modesIndex, regWrites);
+               }
+
+               /*
+                * 5G-XLNA
+                */
+               if ((ar9003_hw_get_rx_gain_idx(ah) == 2) ||
+                   (ar9003_hw_get_rx_gain_idx(ah) == 3)) {
+                       REG_WRITE_ARRAY(&ah->ini_modes_rxgain_5g_xlna,
+                                       modesIndex, regWrites);
+               }
+       }
+
        if (AR_SREV_9550(ah))
                REG_WRITE_ARRAY(&ah->ini_modes_rx_gain_bounds, modesIndex,
                                regWrites);
 
+       /*
+        * TXGAIN initvals.
+        */
        if (AR_SREV_9550(ah)) {
                int modes_txgain_index;
 
@@ -772,34 +819,23 @@ static int ar9003_hw_process_ini(struct ath_hw *ah,
                REG_WRITE_ARRAY(&ah->iniModesFastClock,
                                modesIndex, regWrites);
 
+       /*
+        * Clock frequency initvals.
+        */
        REG_WRITE_ARRAY(&ah->iniAdditional, 1, regWrites);
 
+       /*
+        * JAPAN regulatory.
+        */
        if (chan->channel == 2484)
                ar9003_hw_prog_ini(ah, &ah->iniCckfirJapan2484, 1);
 
-       if (AR_SREV_9462(ah) || AR_SREV_9565(ah))
-               REG_WRITE(ah, AR_GLB_SWREG_DISCONT_MODE,
-                         AR_GLB_SWREG_DISCONT_EN_BT_WLAN);
-
        ah->modes_index = modesIndex;
        ar9003_hw_override_ini(ah);
        ar9003_hw_set_channel_regs(ah, chan);
        ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
        ath9k_hw_apply_txpower(ah, chan, false);
 
-       if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) {
-               if (REG_READ_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_0,
-                                  AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL))
-                       ah->enabled_cals |= TX_IQ_CAL;
-               else
-                       ah->enabled_cals &= ~TX_IQ_CAL;
-
-               if (REG_READ(ah, AR_PHY_CL_CAL_CTL) & AR_PHY_CL_CAL_ENABLE)
-                       ah->enabled_cals |= TX_CL_CAL;
-               else
-                       ah->enabled_cals &= ~TX_CL_CAL;
-       }
-
        return 0;
 }
 
@@ -905,7 +941,12 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
 {
        struct ath_common *common = ath9k_hw_common(ah);
        struct ath9k_channel *chan = ah->curchan;
-       struct ar5416AniState *aniState = &chan->ani;
+       struct ar5416AniState *aniState = &ah->ani;
+       int m1ThreshLow, m2ThreshLow;
+       int m1Thresh, m2Thresh;
+       int m2CountThr, m2CountThrLow;
+       int m1ThreshLowExt, m2ThreshLowExt;
+       int m1ThreshExt, m2ThreshExt;
        s32 value, value2;
 
        switch (cmd & ah->ani_function) {
@@ -919,6 +960,61 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
                 */
                u32 on = param ? 1 : 0;
 
+               if (AR_SREV_9462(ah) || AR_SREV_9565(ah))
+                       goto skip_ws_det;
+
+               m1ThreshLow = on ?
+                       aniState->iniDef.m1ThreshLow : m1ThreshLow_off;
+               m2ThreshLow = on ?
+                       aniState->iniDef.m2ThreshLow : m2ThreshLow_off;
+               m1Thresh = on ?
+                       aniState->iniDef.m1Thresh : m1Thresh_off;
+               m2Thresh = on ?
+                       aniState->iniDef.m2Thresh : m2Thresh_off;
+               m2CountThr = on ?
+                       aniState->iniDef.m2CountThr : m2CountThr_off;
+               m2CountThrLow = on ?
+                       aniState->iniDef.m2CountThrLow : m2CountThrLow_off;
+               m1ThreshLowExt = on ?
+                       aniState->iniDef.m1ThreshLowExt : m1ThreshLowExt_off;
+               m2ThreshLowExt = on ?
+                       aniState->iniDef.m2ThreshLowExt : m2ThreshLowExt_off;
+               m1ThreshExt = on ?
+                       aniState->iniDef.m1ThreshExt : m1ThreshExt_off;
+               m2ThreshExt = on ?
+                       aniState->iniDef.m2ThreshExt : m2ThreshExt_off;
+
+               REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
+                             AR_PHY_SFCORR_LOW_M1_THRESH_LOW,
+                             m1ThreshLow);
+               REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
+                             AR_PHY_SFCORR_LOW_M2_THRESH_LOW,
+                             m2ThreshLow);
+               REG_RMW_FIELD(ah, AR_PHY_SFCORR,
+                             AR_PHY_SFCORR_M1_THRESH,
+                             m1Thresh);
+               REG_RMW_FIELD(ah, AR_PHY_SFCORR,
+                             AR_PHY_SFCORR_M2_THRESH,
+                             m2Thresh);
+               REG_RMW_FIELD(ah, AR_PHY_SFCORR,
+                             AR_PHY_SFCORR_M2COUNT_THR,
+                             m2CountThr);
+               REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
+                             AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW,
+                             m2CountThrLow);
+               REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+                             AR_PHY_SFCORR_EXT_M1_THRESH_LOW,
+                             m1ThreshLowExt);
+               REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+                             AR_PHY_SFCORR_EXT_M2_THRESH_LOW,
+                             m2ThreshLowExt);
+               REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+                             AR_PHY_SFCORR_EXT_M1_THRESH,
+                             m1ThreshExt);
+               REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+                             AR_PHY_SFCORR_EXT_M2_THRESH,
+                             m2ThreshExt);
+skip_ws_det:
                if (on)
                        REG_SET_BIT(ah, AR_PHY_SFCORR_LOW,
                                    AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
@@ -1173,7 +1269,7 @@ static void ar9003_hw_ani_cache_ini_regs(struct ath_hw *ah)
        struct ath9k_ani_default *iniDef;
        u32 val;
 
-       aniState = &ah->curchan->ani;
+       aniState = &ah->ani;
        iniDef = &aniState->iniDef;
 
        ath_dbg(common, ANI, "ver %d.%d opmode %u chan %d Mhz/0x%x\n",
@@ -1214,7 +1310,7 @@ static void ar9003_hw_ani_cache_ini_regs(struct ath_hw *ah)
        /* these levels just got reset to defaults by the INI */
        aniState->spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL;
        aniState->firstepLevel = ATH9K_ANI_FIRSTEP_LVL;
-       aniState->ofdmWeakSigDetect = ATH9K_ANI_USE_OFDM_WEAK_SIG;
+       aniState->ofdmWeakSigDetect = true;
        aniState->mrcCCK = true;
 }
 
@@ -1369,8 +1465,8 @@ static void ar9003_hw_antctrl_shared_chain_lnadiv(struct ath_hw *ah,
                        AR_PHY_ANT_DIV_ALT_LNACONF |
                        AR_PHY_ANT_DIV_MAIN_GAINTB |
                        AR_PHY_ANT_DIV_ALT_GAINTB);
-               regval |= (AR_PHY_ANT_DIV_LNA1 << AR_PHY_ANT_DIV_MAIN_LNACONF_S);
-               regval |= (AR_PHY_ANT_DIV_LNA2 << AR_PHY_ANT_DIV_ALT_LNACONF_S);
+               regval |= (ATH_ANT_DIV_COMB_LNA1 << AR_PHY_ANT_DIV_MAIN_LNACONF_S);
+               regval |= (ATH_ANT_DIV_COMB_LNA2 << AR_PHY_ANT_DIV_ALT_LNACONF_S);
                REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval);
        }
 }
@@ -1415,12 +1511,24 @@ static int ar9003_hw_fast_chan_change(struct ath_hw *ah,
        ar9003_hw_prog_ini(ah, &ah->iniBB[ATH_INI_POST], modesIndex);
        ar9003_hw_prog_ini(ah, &ah->iniRadio[ATH_INI_POST], modesIndex);
 
-       if (AR_SREV_9462_20(ah))
+       if (AR_SREV_9462_20_OR_LATER(ah))
                ar9003_hw_prog_ini(ah, &ah->ini_radio_post_sys2ant,
                                   modesIndex);
 
        REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites);
 
+       if (AR_SREV_9462_20_OR_LATER(ah)) {
+               /*
+                * CUS217 mix LNA mode.
+                */
+               if (ar9003_hw_get_rx_gain_idx(ah) == 2) {
+                       REG_WRITE_ARRAY(&ah->ini_modes_rxgain_bb_core,
+                                       1, regWrites);
+                       REG_WRITE_ARRAY(&ah->ini_modes_rxgain_bb_postamble,
+                                       modesIndex, regWrites);
+               }
+       }
+
        /*
         * For 5GHz channels requiring Fast Clock, apply
         * different modal values.
@@ -1431,7 +1539,11 @@ static int ar9003_hw_fast_chan_change(struct ath_hw *ah,
        if (AR_SREV_9565(ah))
                REG_WRITE_ARRAY(&ah->iniModesFastClock, 1, regWrites);
 
-       REG_WRITE_ARRAY(&ah->iniAdditional, 1, regWrites);
+       /*
+        * JAPAN regulatory.
+        */
+       if (chan->channel == 2484)
+               ar9003_hw_prog_ini(ah, &ah->iniCckfirJapan2484, 1);
 
        ah->modes_index = modesIndex;
        *ini_reloaded = true;