]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/net/wireless/ath/ath9k/ar9003_phy.c
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux
[karo-tx-linux.git] / drivers / net / wireless / ath / ath9k / ar9003_phy.c
index fcafec0605f41e94679c889e092fcc56b6eb9748..e41d26939ab8799d66d71b30b0699799aad4eca1 100644 (file)
@@ -14,6 +14,7 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#include <linux/export.h>
 #include "hw.h"
 #include "ar9003_phy.h"
 
@@ -198,12 +199,14 @@ static void ar9003_hw_spur_mitigate_mrc_cck(struct ath_hw *ah,
                        synth_freq = chan->channel;
                }
        } else {
-               range = 10;
+               range = AR_SREV_9462(ah) ? 5 : 10;
                max_spur_cnts = 4;
                synth_freq = chan->channel;
        }
 
        for (i = 0; i < max_spur_cnts; i++) {
+               if (AR_SREV_9462(ah) && (i == 0 || i == 3))
+                       continue;
                negative = 0;
                if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah))
                        cur_bb_spur = FBIN2FREQ(spur_fbin_ptr[i],
@@ -370,7 +373,7 @@ static void ar9003_hw_spur_ofdm_work(struct ath_hw *ah,
                        else
                                spur_subchannel_sd = 0;
 
-                       spur_freq_sd = ((freq_offset + 10) << 9) / 11;
+                       spur_freq_sd = (freq_offset << 9) / 11;
 
                } else {
                        if (REG_READ_FIELD(ah, AR_PHY_GEN_CTRL,
@@ -379,7 +382,7 @@ static void ar9003_hw_spur_ofdm_work(struct ath_hw *ah,
                        else
                                spur_subchannel_sd = 1;
 
-                       spur_freq_sd = ((freq_offset - 10) << 9) / 11;
+                       spur_freq_sd = (freq_offset << 9) / 11;
 
                }
 
@@ -482,7 +485,7 @@ static void ar9003_hw_set_channel_regs(struct ath_hw *ah,
                (REG_READ(ah, AR_PHY_GEN_CTRL) & AR_PHY_GC_ENABLE_DAC_FIFO);
 
        /* Enable 11n HT, 20 MHz */
-       phymode = AR_PHY_GC_HT_EN | AR_PHY_GC_SINGLE_HT_LTF1 | AR_PHY_GC_WALSH |
+       phymode = AR_PHY_GC_HT_EN | AR_PHY_GC_SINGLE_HT_LTF1 |
                  AR_PHY_GC_SHORT_GI_40 | enableDacFifo;
 
        /* Configure baseband for dynamic 20/40 operation */
@@ -540,7 +543,7 @@ static void ar9003_hw_init_bb(struct ath_hw *ah,
        udelay(synthDelay + BASE_ACTIVATE_DELAY);
 }
 
-void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx)
+static void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx)
 {
        switch (rx) {
        case 0x5:
@@ -559,6 +562,9 @@ void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx)
 
        if ((ah->caps.hw_caps & ATH9K_HW_CAP_APM) && (tx == 0x7))
                REG_WRITE(ah, AR_SELFGEN_MASK, 0x3);
+       else if (AR_SREV_9462(ah))
+               /* xxx only when MCI support is enabled */
+               REG_WRITE(ah, AR_SELFGEN_MASK, 0x3);
        else
                REG_WRITE(ah, AR_SELFGEN_MASK, tx);
 
@@ -592,6 +598,9 @@ static void ar9003_hw_override_ini(struct ath_hw *ah)
        val = REG_READ(ah, AR_PCU_MISC_MODE2) & (~AR_ADHOC_MCAST_KEYID_ENABLE);
        REG_WRITE(ah, AR_PCU_MISC_MODE2,
                  val | AR_AGG_WEP_ENABLE_FIX | AR_AGG_WEP_ENABLE);
+
+       REG_SET_BIT(ah, AR_PHY_CCK_DETECT,
+                   AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV);
 }
 
 static void ar9003_hw_prog_ini(struct ath_hw *ah,
@@ -625,9 +634,7 @@ static void ar9003_hw_prog_ini(struct ath_hw *ah,
 static int ar9003_hw_process_ini(struct ath_hw *ah,
                                 struct ath9k_channel *chan)
 {
-       struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
        unsigned int regWrites = 0, i;
-       struct ieee80211_channel *channel = chan->chan;
        u32 modesIndex;
 
        switch (chan->chanmode) {
@@ -658,6 +665,10 @@ static int ar9003_hw_process_ini(struct ath_hw *ah,
                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))
+                       ar9003_hw_prog_ini(ah,
+                                          &ah->ini_radio_post_sys2ant,
+                                          modesIndex);
        }
 
        REG_WRITE_ARRAY(&ah->iniModesRxGain, 1, regWrites);
@@ -677,17 +688,27 @@ static int ar9003_hw_process_ini(struct ath_hw *ah,
        if (AR_SREV_9340(ah) && !ah->is_clk_25mhz)
                REG_WRITE_ARRAY(&ah->iniModesAdditional_40M, 1, regWrites);
 
+       if (AR_SREV_9462(ah))
+               ar9003_hw_prog_ini(ah, &ah->ini_BTCOEX_MAX_TXPWR, 1);
+
+       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);
 
-       /* Set TX power */
-       ah->eep_ops->set_txpower(ah, chan,
-                                ath9k_regd_get_ctl(regulatory, chan),
-                                channel->max_antenna_gain * 2,
-                                channel->max_power * 2,
-                                min((u32) MAX_RATE_POWER,
-                                (u32) regulatory->power_limit), false);
+       if (AR_SREV_9462(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;
 }
@@ -785,16 +806,6 @@ static void ar9003_hw_rfbus_done(struct ath_hw *ah)
        REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0);
 }
 
-static void ar9003_hw_set_diversity(struct ath_hw *ah, bool value)
-{
-       u32 v = REG_READ(ah, AR_PHY_CCK_DETECT);
-       if (value)
-               v |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
-       else
-               v &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
-       REG_WRITE(ah, AR_PHY_CCK_DETECT, v);
-}
-
 static bool ar9003_hw_ani_control(struct ath_hw *ah,
                                  enum ath9k_ani_cmd cmd, int param)
 {
@@ -1253,6 +1264,73 @@ static void ar9003_hw_antdiv_comb_conf_set(struct ath_hw *ah,
        REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval);
 }
 
+static int ar9003_hw_fast_chan_change(struct ath_hw *ah,
+                                     struct ath9k_channel *chan,
+                                     u8 *ini_reloaded)
+{
+       unsigned int regWrites = 0;
+       u32 modesIndex;
+
+       switch (chan->chanmode) {
+       case CHANNEL_A:
+       case CHANNEL_A_HT20:
+               modesIndex = 1;
+               break;
+       case CHANNEL_A_HT40PLUS:
+       case CHANNEL_A_HT40MINUS:
+               modesIndex = 2;
+               break;
+       case CHANNEL_G:
+       case CHANNEL_G_HT20:
+       case CHANNEL_B:
+               modesIndex = 4;
+               break;
+       case CHANNEL_G_HT40PLUS:
+       case CHANNEL_G_HT40MINUS:
+               modesIndex = 3;
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       if (modesIndex == ah->modes_index) {
+               *ini_reloaded = false;
+               goto set_rfmode;
+       }
+
+       ar9003_hw_prog_ini(ah, &ah->iniSOC[ATH_INI_POST], modesIndex);
+       ar9003_hw_prog_ini(ah, &ah->iniMac[ATH_INI_POST], modesIndex);
+       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))
+               ar9003_hw_prog_ini(ah,
+                               &ah->ini_radio_post_sys2ant,
+                               modesIndex);
+
+       REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites);
+
+       /*
+        * For 5GHz channels requiring Fast Clock, apply
+        * different modal values.
+        */
+       if (IS_CHAN_A_FAST_CLOCK(ah, chan))
+               REG_WRITE_ARRAY(&ah->iniModesAdditional, modesIndex, regWrites);
+
+       if (AR_SREV_9330(ah))
+               REG_WRITE_ARRAY(&ah->iniModesAdditional, 1, regWrites);
+
+       if (AR_SREV_9340(ah) && !ah->is_clk_25mhz)
+               REG_WRITE_ARRAY(&ah->iniModesAdditional_40M, 1, regWrites);
+
+       ah->modes_index = modesIndex;
+       *ini_reloaded = true;
+
+set_rfmode:
+       ar9003_hw_set_rfmode(ah, chan);
+       return 0;
+}
+
 void ar9003_hw_attach_phy_ops(struct ath_hw *ah)
 {
        struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
@@ -1277,11 +1355,11 @@ void ar9003_hw_attach_phy_ops(struct ath_hw *ah)
        priv_ops->set_delta_slope = ar9003_hw_set_delta_slope;
        priv_ops->rfbus_req = ar9003_hw_rfbus_req;
        priv_ops->rfbus_done = ar9003_hw_rfbus_done;
-       priv_ops->set_diversity = ar9003_hw_set_diversity;
        priv_ops->ani_control = ar9003_hw_ani_control;
        priv_ops->do_getnf = ar9003_hw_do_getnf;
        priv_ops->ani_cache_ini_regs = ar9003_hw_ani_cache_ini_regs;
        priv_ops->set_radar_params = ar9003_hw_set_radar_params;
+       priv_ops->fast_chan_change = ar9003_hw_fast_chan_change;
 
        ops->antdiv_comb_conf_get = ar9003_hw_antdiv_comb_conf_get;
        ops->antdiv_comb_conf_set = ar9003_hw_antdiv_comb_conf_set;