ath9k: Add support for Adaptive Power Management
[pandora-kernel.git] / drivers / net / wireless / ath / ath9k / hw.c
index cc13ee1..b4396a9 100644 (file)
@@ -310,10 +310,9 @@ static bool ath9k_hw_chip_test(struct ath_hw *ah)
        struct ath_common *common = ath9k_hw_common(ah);
        u32 regAddr[2] = { AR_STA_ID0 };
        u32 regHold[2];
-       u32 patternData[4] = { 0x55555555,
-                              0xaaaaaaaa,
-                              0x66666666,
-                              0x99999999 };
+       static const u32 patternData[4] = {
+               0x55555555, 0xaaaaaaaa, 0x66666666, 0x99999999
+       };
        int i, j, loop_max;
 
        if (!AR_SREV_9300_20_OR_LATER(ah)) {
@@ -419,10 +418,6 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah)
        ah->hw_version.magic = AR5416_MAGIC;
        ah->hw_version.subvendorid = 0;
 
-       ah->ah_flags = 0;
-       if (!AR_SREV_9100(ah))
-               ah->ah_flags = AH_USE_EEPROM;
-
        ah->atim_window = 0;
        ah->sta_id1_defaults =
                AR_STA_ID1_CRPT_MIC_ENABLE |
@@ -440,7 +435,7 @@ static int ath9k_hw_init_macaddr(struct ath_hw *ah)
        u32 sum;
        int i;
        u16 eeval;
-       u32 EEP_MAC[] = { EEP_MAC_LSW, EEP_MAC_MID, EEP_MAC_MSW };
+       static const u32 EEP_MAC[] = { EEP_MAC_LSW, EEP_MAC_MID, EEP_MAC_MSW };
 
        sum = 0;
        for (i = 0; i < 3; i++) {
@@ -484,6 +479,7 @@ static int ath9k_hw_post_init(struct ath_hw *ah)
                ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL,
                          "Failed allocating banks for "
                          "external radio\n");
+               ath9k_hw_rf_free_ext_banks(ah);
                return ecode;
        }
 
@@ -952,9 +948,12 @@ static void ath9k_hw_set_operating_mode(struct ath_hw *ah, int opmode)
                REG_SET_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION);
                break;
        case NL80211_IFTYPE_STATION:
-       case NL80211_IFTYPE_MONITOR:
                REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_KSRCH_MODE);
                break;
+       default:
+               if (ah->is_monitoring)
+                       REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_KSRCH_MODE);
+               break;
        }
 }
 
@@ -1166,7 +1165,7 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah,
                             channel->max_antenna_gain * 2,
                             channel->max_power * 2,
                             min((u32) MAX_RATE_POWER,
-                            (u32) regulatory->power_limit));
+                            (u32) regulatory->power_limit), false);
 
        ath9k_hw_rfbus_done(ah);
 
@@ -1634,7 +1633,6 @@ void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period)
 
        switch (ah->opmode) {
        case NL80211_IFTYPE_STATION:
-       case NL80211_IFTYPE_MONITOR:
                REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(next_beacon));
                REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT, 0xffff);
                REG_WRITE(ah, AR_NEXT_SWBA, 0x7ffff);
@@ -1663,6 +1661,14 @@ void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period)
                        AR_TBTT_TIMER_EN | AR_DBA_TIMER_EN | AR_SWBA_TIMER_EN;
                break;
        default:
+               if (ah->is_monitoring) {
+                       REG_WRITE(ah, AR_NEXT_TBTT_TIMER,
+                                       TU_TO_USEC(next_beacon));
+                       REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT, 0xffff);
+                       REG_WRITE(ah, AR_NEXT_SWBA, 0x7ffff);
+                       flags |= AR_TBTT_TIMER_EN;
+                       break;
+               }
                ath_print(ath9k_hw_common(ah), ATH_DBG_BEACON,
                          "%s: unsupported opmode: %d\n",
                          __func__, ah->opmode);
@@ -1822,6 +1828,10 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
 
        ah->misc_mode |= AR_PCU_MIC_NEW_LOC_ENA;
 
+       /* enable key search for every frame in an aggregate */
+       if (AR_SREV_9300_20_OR_LATER(ah))
+               ah->misc_mode |= AR_PCU_ALWAYS_PERFORM_KEYSEARCH;
+
        pCap->low_2ghz_chan = 2312;
        pCap->high_2ghz_chan = 2732;
 
@@ -1915,8 +1925,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
        pCap->num_antcfg_2ghz =
                ah->eep_ops->get_num_ant_config(ah, ATH9K_HAL_FREQ_BAND_2GHZ);
 
-       if (AR_SREV_9280_20_OR_LATER(ah) &&
-           ath9k_hw_btcoex_supported(ah)) {
+       if (AR_SREV_9280_20_OR_LATER(ah) && common->btcoex_enabled) {
                btcoex_hw->btactive_gpio = ATH_BTACTIVE_GPIO;
                btcoex_hw->wlanactive_gpio = ATH_WLANACTIVE_GPIO;
 
@@ -1952,6 +1961,9 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
        if (AR_SREV_9300_20_OR_LATER(ah))
                pCap->hw_caps |= ATH9K_HW_CAP_RAC_SUPPORTED;
 
+       if (AR_SREV_9300_20_OR_LATER(ah))
+               ah->ent_mode = REG_READ(ah, AR_ENT_OTP);
+
        if (AR_SREV_9287_11_OR_LATER(ah) || AR_SREV_9271(ah))
                pCap->hw_caps |= ATH9K_HW_CAP_SGI_20;
 
@@ -1962,6 +1974,12 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
                        if ((ant_div_ctl1 & 0x1) && ((ant_div_ctl1 >> 3) & 0x1))
                                pCap->hw_caps |= ATH9K_HW_CAP_ANT_DIV_COMB;
                }
+       if (AR_SREV_9300_20_OR_LATER(ah)) {
+               if (ah->eep_ops->get_eeprom(ah, EEP_CHAIN_MASK_REDUCE))
+                       pCap->hw_caps |= ATH9K_HW_CAP_APM;
+       }
+
+
 
        return 0;
 }
@@ -2165,7 +2183,7 @@ bool ath9k_hw_disable(struct ath_hw *ah)
 }
 EXPORT_SYMBOL(ath9k_hw_disable);
 
-void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit)
+void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test)
 {
        struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
        struct ath9k_channel *chan = ah->curchan;
@@ -2178,7 +2196,7 @@ void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit)
                                 channel->max_antenna_gain * 2,
                                 channel->max_power * 2,
                                 min((u32) MAX_RATE_POWER,
-                                (u32) regulatory->power_limit));
+                                (u32) regulatory->power_limit), test);
 }
 EXPORT_SYMBOL(ath9k_hw_set_txpowerlimit);
 
@@ -2312,11 +2330,10 @@ static u32 rightmost_index(struct ath_gen_timer_table *timer_table, u32 *mask)
        return timer_table->gen_timer_index[b];
 }
 
-u32 ath9k_hw_gettsf32(struct ath_hw *ah)
+static u32 ath9k_hw_gettsf32(struct ath_hw *ah)
 {
        return REG_READ(ah, AR_TSF_L32);
 }
-EXPORT_SYMBOL(ath9k_hw_gettsf32);
 
 struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah,
                                          void (*trigger)(void *),