ath9k_hw: clean up tx power handling
[pandora-kernel.git] / drivers / net / wireless / ath / ath9k / hw.c
index 2a5f908..949656d 100644 (file)
@@ -284,7 +284,12 @@ static void ath9k_hw_read_revisions(struct ath_hw *ah)
                ah->hw_version.macVersion =
                        (val & AR_SREV_VERSION2) >> AR_SREV_TYPE2_S;
                ah->hw_version.macRev = MS(val, AR_SREV_REVISION2);
-               ah->is_pciexpress = (val & AR_SREV_TYPE2_HOST_MODE) ? 0 : 1;
+
+               if (AR_SREV_9480(ah))
+                       ah->is_pciexpress = true;
+               else
+                       ah->is_pciexpress = (val &
+                                            AR_SREV_TYPE2_HOST_MODE) ? 0 : 1;
        } else {
                if (!AR_SREV_9100(ah))
                        ah->hw_version.macVersion = MS(val, AR_SREV_VERSION);
@@ -318,6 +323,14 @@ static void ath9k_hw_disablepcie(struct ath_hw *ah)
        REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
 }
 
+static void ath9k_hw_aspm_init(struct ath_hw *ah)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+
+       if (common->bus_ops->aspm_init)
+               common->bus_ops->aspm_init(common);
+}
+
 /* This should work for all families including legacy */
 static bool ath9k_hw_chip_test(struct ath_hw *ah)
 {
@@ -378,7 +391,6 @@ static void ath9k_hw_init_config(struct ath_hw *ah)
        ah->config.additional_swba_backoff = 0;
        ah->config.ack_6mb = 0x0;
        ah->config.cwm_ignore_extcca = 0;
-       ah->config.pcie_powersave_enable = 0;
        ah->config.pcie_clock_req = 0;
        ah->config.pcie_waen = 0;
        ah->config.analog_shiftreg = 1;
@@ -421,7 +433,6 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah)
 
        regulatory->country_code = CTRY_DEFAULT;
        regulatory->power_limit = MAX_RATE_POWER;
-       regulatory->tp_scale = ATH9K_TP_SCALE_MAX;
 
        ah->hw_version.magic = AR5416_MAGIC;
        ah->hw_version.subvendorid = 0;
@@ -433,7 +444,7 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah)
        if (AR_SREV_9100(ah))
                ah->sta_id1_defaults |= AR_STA_ID1_AR9100_BA_FIX;
        ah->enable_32kHz_clock = DONT_USE_32KHZ;
-       ah->slottime = 20;
+       ah->slottime = ATH9K_SLOT_TIME_9;
        ah->globaltxtimeout = (u32) -1;
        ah->power_mode = ATH9K_PM_UNDEFINED;
 }
@@ -573,6 +584,7 @@ static int __ath9k_hw_init(struct ath_hw *ah)
        case AR_SREV_VERSION_9330:
        case AR_SREV_VERSION_9485:
        case AR_SREV_VERSION_9340:
+       case AR_SREV_VERSION_9480:
                break;
        default:
                ath_err(common,
@@ -596,10 +608,7 @@ static int __ath9k_hw_init(struct ath_hw *ah)
 
        ath9k_hw_init_mode_regs(ah);
 
-
-       if (ah->is_pciexpress)
-               ath9k_hw_configpcipowersave(ah, 0, 0);
-       else
+       if (!ah->is_pciexpress)
                ath9k_hw_disablepcie(ah);
 
        if (!AR_SREV_9300_20_OR_LATER(ah))
@@ -614,6 +623,9 @@ static int __ath9k_hw_init(struct ath_hw *ah)
        if (r)
                return r;
 
+       if (ah->is_pciexpress)
+               ath9k_hw_aspm_init(ah);
+
        r = ath9k_hw_init_macaddr(ah);
        if (r) {
                ath_err(common, "Failed to initialize MAC address\n");
@@ -656,6 +668,8 @@ int ath9k_hw_init(struct ath_hw *ah)
        case AR9300_DEVID_AR9485_PCIE:
        case AR9300_DEVID_AR9330:
        case AR9300_DEVID_AR9340:
+       case AR9300_DEVID_AR9580:
+       case AR9300_DEVID_AR9480:
                break;
        default:
                if (common->bus_ops->ath_bus_type == ATH_USB)
@@ -952,7 +966,7 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah)
        struct ath_common *common = ath9k_hw_common(ah);
        struct ieee80211_conf *conf = &common->hw->conf;
        const struct ath9k_channel *chan = ah->curchan;
-       int acktimeout;
+       int acktimeout, ctstimeout;
        int slottime;
        int sifstime;
        int rx_lat = 0, tx_lat = 0, eifs = 0;
@@ -967,7 +981,10 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah)
        if (ah->misc_mode != 0)
                REG_SET_BIT(ah, AR_PCU_MISC, ah->misc_mode);
 
-       rx_lat = 37;
+       if (IS_CHAN_A_FAST_CLOCK(ah, chan))
+               rx_lat = 41;
+       else
+               rx_lat = 37;
        tx_lat = 54;
 
        if (IS_CHAN_HALF_RATE(chan)) {
@@ -981,7 +998,7 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah)
                sifstime = 32;
        } else if (IS_CHAN_QUARTER_RATE(chan)) {
                eifs = 340;
-               rx_lat *= 4;
+               rx_lat = (rx_lat * 4) - 1;
                tx_lat *= 4;
                if (IS_CHAN_A_FAST_CLOCK(ah, chan))
                    tx_lat += 22;
@@ -989,8 +1006,14 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah)
                slottime = 21;
                sifstime = 64;
        } else {
-               eifs = REG_READ(ah, AR_D_GBL_IFS_EIFS);
-               reg = REG_READ(ah, AR_USEC);
+               if (AR_SREV_9287(ah) && AR_SREV_9287_13_OR_LATER(ah)) {
+                       eifs = AR_D_GBL_IFS_EIFS_ASYNC_FIFO;
+                       reg = AR_USEC_ASYNC_FIFO;
+               } else {
+                       eifs = REG_READ(ah, AR_D_GBL_IFS_EIFS)/
+                               common->clockrate;
+                       reg = REG_READ(ah, AR_USEC);
+               }
                rx_lat = MS(reg, AR_USEC_RX_LAT);
                tx_lat = MS(reg, AR_USEC_TX_LAT);
 
@@ -1003,6 +1026,7 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah)
 
        /* As defined by IEEE 802.11-2007 17.3.8.6 */
        acktimeout = slottime + sifstime + 3 * ah->coverage_class;
+       ctstimeout = acktimeout;
 
        /*
         * Workaround for early ACK timeouts, add an offset to match the
@@ -1017,7 +1041,7 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah)
        ath9k_hw_set_sifs_time(ah, sifstime);
        ath9k_hw_setslottime(ah, slottime);
        ath9k_hw_set_ack_timeout(ah, acktimeout);
-       ath9k_hw_set_cts_timeout(ah, acktimeout);
+       ath9k_hw_set_cts_timeout(ah, ctstimeout);
        if (ah->globaltxtimeout != (u32) -1)
                ath9k_hw_set_global_txtimeout(ah, ah->globaltxtimeout);
 
@@ -1322,6 +1346,7 @@ static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah)
 
 static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type)
 {
+
        if (AR_SREV_9300_20_OR_LATER(ah)) {
                REG_WRITE(ah, AR_WA, ah->WARegVal);
                udelay(10);
@@ -1363,9 +1388,7 @@ static bool ath9k_hw_chip_reset(struct ath_hw *ah,
 static bool ath9k_hw_channel_change(struct ath_hw *ah,
                                    struct ath9k_channel *chan)
 {
-       struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
        struct ath_common *common = ath9k_hw_common(ah);
-       struct ieee80211_channel *channel = chan->chan;
        u32 qnum;
        int r;
 
@@ -1390,14 +1413,7 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah,
                return false;
        }
        ath9k_hw_set_clockrate(ah);
-
-       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);
-
+       ath9k_hw_apply_txpower(ah, chan);
        ath9k_hw_rfbus_done(ah);
 
        if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan))
@@ -1461,9 +1477,6 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
        u64 tsf = 0;
        int i, r;
 
-       ah->txchainmask = common->tx_chainmask;
-       ah->rxchainmask = common->rx_chainmask;
-
        if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
                return -EIO;
 
@@ -1479,15 +1492,18 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
                memset(caldata, 0, sizeof(*caldata));
                ath9k_init_nfcal_hist_buffer(ah, chan);
        }
+       ah->noise = ath9k_hw_getchan_noise(ah, chan);
+
+       if ((AR_SREV_9280(ah) && common->bus_ops->ath_bus_type == ATH_PCI) ||
+           (AR_SREV_9300_20_OR_LATER(ah) && IS_CHAN_5GHZ(chan)))
+               bChannelChange = false;
 
        if (bChannelChange &&
            (ah->chip_fullsleep != true) &&
            (ah->curchan != NULL) &&
            (chan->channel != ah->curchan->channel) &&
            ((chan->channelFlags & CHANNEL_ALL) ==
-            (ah->curchan->channelFlags & CHANNEL_ALL)) &&
-           (!AR_SREV_9280(ah) || AR_DEVID_7010(ah))) {
-
+            (ah->curchan->channelFlags & CHANNEL_ALL))) {
                if (ath9k_hw_channel_change(ah, chan)) {
                        ath9k_hw_loadnf(ah, ah->curchan);
                        ath9k_hw_start_nfcal(ah, true);
@@ -1727,25 +1743,41 @@ static void ath9k_set_power_sleep(struct ath_hw *ah, int setChip)
 {
        REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
        if (setChip) {
+               if (AR_SREV_9480(ah)) {
+                       REG_WRITE(ah, AR_TIMER_MODE,
+                                 REG_READ(ah, AR_TIMER_MODE) & 0xFFFFFF00);
+                       REG_WRITE(ah, AR_NDP2_TIMER_MODE, REG_READ(ah,
+                                 AR_NDP2_TIMER_MODE) & 0xFFFFFF00);
+                       REG_WRITE(ah, AR_SLP32_INC,
+                                 REG_READ(ah, AR_SLP32_INC) & 0xFFF00000);
+                       /* xxx Required for WLAN only case ? */
+                       REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_EN, 0);
+                       udelay(100);
+               }
+
                /*
                 * Clear the RTC force wake bit to allow the
                 * mac to go to sleep.
                 */
-               REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE,
-                           AR_RTC_FORCE_WAKE_EN);
+               REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN);
+
+               if (AR_SREV_9480(ah))
+                       udelay(100);
+
                if (!AR_SREV_9100(ah) && !AR_SREV_9300_20_OR_LATER(ah))
                        REG_WRITE(ah, AR_RC, AR_RC_AHB | AR_RC_HOSTIF);
 
                /* Shutdown chip. Active low */
-               if (!AR_SREV_5416(ah) && !AR_SREV_9271(ah))
-                       REG_CLR_BIT(ah, (AR_RTC_RESET),
-                                   AR_RTC_RESET_EN);
+               if (!AR_SREV_5416(ah) &&
+                               !AR_SREV_9271(ah) && !AR_SREV_9480_10(ah)) {
+                       REG_CLR_BIT(ah, AR_RTC_RESET, AR_RTC_RESET_EN);
+                       udelay(2);
+               }
        }
 
        /* Clear Bit 14 of AR_WA after putting chip into Full Sleep mode. */
-       if (AR_SREV_9300_20_OR_LATER(ah))
-               REG_WRITE(ah, AR_WA,
-                         ah->WARegVal & ~AR_WA_D3_L1_DISABLE);
+       if (!AR_SREV_9480(ah))
+               REG_WRITE(ah, AR_WA, ah->WARegVal & ~AR_WA_D3_L1_DISABLE);
 }
 
 /*
@@ -1755,6 +1787,8 @@ static void ath9k_set_power_sleep(struct ath_hw *ah, int setChip)
  */
 static void ath9k_set_power_network_sleep(struct ath_hw *ah, int setChip)
 {
+       u32 val;
+
        REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
        if (setChip) {
                struct ath9k_hw_capabilities *pCap = &ah->caps;
@@ -1764,12 +1798,30 @@ static void ath9k_set_power_network_sleep(struct ath_hw *ah, int setChip)
                        REG_WRITE(ah, AR_RTC_FORCE_WAKE,
                                  AR_RTC_FORCE_WAKE_ON_INT);
                } else {
+
+                       /* When chip goes into network sleep, it could be waken
+                        * up by MCI_INT interrupt caused by BT's HW messages
+                        * (LNA_xxx, CONT_xxx) which chould be in a very fast
+                        * rate (~100us). This will cause chip to leave and
+                        * re-enter network sleep mode frequently, which in
+                        * consequence will have WLAN MCI HW to generate lots of
+                        * SYS_WAKING and SYS_SLEEPING messages which will make
+                        * BT CPU to busy to process.
+                        */
+                       if (AR_SREV_9480(ah)) {
+                               val = REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_EN) &
+                                       ~AR_MCI_INTERRUPT_RX_HW_MSG_MASK;
+                               REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_EN, val);
+                       }
                        /*
                         * Clear the RTC force wake bit to allow the
                         * mac to go to sleep.
                         */
                        REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE,
                                    AR_RTC_FORCE_WAKE_EN);
+
+                       if (AR_SREV_9480(ah))
+                               udelay(30);
                }
        }
 
@@ -1997,12 +2049,22 @@ EXPORT_SYMBOL(ath9k_hw_set_sta_beacon_timers);
 /* HW Capabilities */
 /*******************/
 
+static u8 fixup_chainmask(u8 chip_chainmask, u8 eeprom_chainmask)
+{
+       eeprom_chainmask &= chip_chainmask;
+       if (eeprom_chainmask)
+               return eeprom_chainmask;
+       else
+               return chip_chainmask;
+}
+
 int ath9k_hw_fill_cap_info(struct ath_hw *ah)
 {
        struct ath9k_hw_capabilities *pCap = &ah->caps;
        struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
        struct ath_common *common = ath9k_hw_common(ah);
        struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
+       unsigned int chip_chainmask;
 
        u16 eeval;
        u8 ant_div_ctl1, tx_chainmask, rx_chainmask;
@@ -2039,6 +2101,15 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
        if (eeval & AR5416_OPFLAGS_11G)
                pCap->hw_caps |= ATH9K_HW_CAP_2GHZ;
 
+       if (AR_SREV_9485(ah) || AR_SREV_9285(ah) || AR_SREV_9330(ah))
+               chip_chainmask = 1;
+       else if (!AR_SREV_9280_20_OR_LATER(ah))
+               chip_chainmask = 7;
+       else if (!AR_SREV_9300_20_OR_LATER(ah) || AR_SREV_9340(ah))
+               chip_chainmask = 3;
+       else
+               chip_chainmask = 7;
+
        pCap->tx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_TX_MASK);
        /*
         * For AR9271 we will temporarilly uses the rx chainmax as read from
@@ -2055,6 +2126,11 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
                /* Use rx_chainmask from EEPROM. */
                pCap->rx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_RX_MASK);
 
+       pCap->tx_chainmask = fixup_chainmask(chip_chainmask, pCap->tx_chainmask);
+       pCap->rx_chainmask = fixup_chainmask(chip_chainmask, pCap->rx_chainmask);
+       ah->txchainmask = pCap->tx_chainmask;
+       ah->rxchainmask = pCap->rx_chainmask;
+
        ah->misc_mode |= AR_PCU_MIC_NEW_LOC_ENA;
 
        /* enable key search for every frame in an aggregate */
@@ -2072,6 +2148,10 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
                pCap->num_gpio_pins = AR9271_NUM_GPIO;
        else if (AR_DEVID_7010(ah))
                pCap->num_gpio_pins = AR7010_NUM_GPIO;
+       else if (AR_SREV_9300_20_OR_LATER(ah))
+               pCap->num_gpio_pins = AR9300_NUM_GPIO;
+       else if (AR_SREV_9287_11_OR_LATER(ah))
+               pCap->num_gpio_pins = AR9287_NUM_GPIO;
        else if (AR_SREV_9285_12_OR_LATER(ah))
                pCap->num_gpio_pins = AR9285_NUM_GPIO;
        else if (AR_SREV_9280_20_OR_LATER(ah))
@@ -2364,6 +2444,9 @@ void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits)
 
        ENABLE_REGWRITE_BUFFER(ah);
 
+       if (AR_SREV_9480(ah))
+               bits |= ATH9K_RX_FILTER_CONTROL_WRAPPER;
+
        REG_WRITE(ah, AR_RX_FILTER, bits);
 
        phybits = 0;
@@ -2405,20 +2488,56 @@ bool ath9k_hw_disable(struct ath_hw *ah)
 }
 EXPORT_SYMBOL(ath9k_hw_disable);
 
+static int get_antenna_gain(struct ath_hw *ah, struct ath9k_channel *chan)
+{
+       enum eeprom_param gain_param;
+
+       if (IS_CHAN_2GHZ(chan))
+               gain_param = EEP_ANTENNA_GAIN_2G;
+       else
+               gain_param = EEP_ANTENNA_GAIN_5G;
+
+       return ah->eep_ops->get_eeprom(ah, gain_param);
+}
+
+void ath9k_hw_apply_txpower(struct ath_hw *ah, struct ath9k_channel *chan)
+{
+       struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
+       struct ieee80211_channel *channel;
+       int chan_pwr, new_pwr, max_gain;
+       int ant_gain, ant_reduction = 0;
+
+       if (!chan)
+               return;
+
+       channel = chan->chan;
+       chan_pwr = min_t(int, channel->max_power * 2, MAX_RATE_POWER);
+       new_pwr = min_t(int, chan_pwr, reg->power_limit);
+       max_gain = chan_pwr - new_pwr + channel->max_antenna_gain * 2;
+
+       ant_gain = get_antenna_gain(ah, chan);
+       if (ant_gain > max_gain)
+               ant_reduction = ant_gain - max_gain;
+
+       ah->eep_ops->set_txpower(ah, chan,
+                                ath9k_regd_get_ctl(reg, chan),
+                                ant_reduction, new_pwr, false);
+}
+
 void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test)
 {
-       struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
+       struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
        struct ath9k_channel *chan = ah->curchan;
        struct ieee80211_channel *channel = chan->chan;
 
-       regulatory->power_limit = min(limit, (u32) MAX_RATE_POWER);
+       reg->power_limit = min_t(int, limit, MAX_RATE_POWER);
+       if (test)
+               channel->max_power = MAX_RATE_POWER / 2;
 
-       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), test);
+       ath9k_hw_apply_txpower(ah, chan);
+
+       if (test)
+               channel->max_power = DIV_ROUND_UP(reg->max_power_level, 2);
 }
 EXPORT_SYMBOL(ath9k_hw_set_txpowerlimit);
 
@@ -2617,6 +2736,20 @@ void ath9k_hw_gen_timer_start(struct ath_hw *ah,
        REG_SET_BIT(ah, gen_tmr_configuration[timer->index].mode_addr,
                    gen_tmr_configuration[timer->index].mode_mask);
 
+       if (AR_SREV_9480(ah)) {
+               /*
+                * Starting from AR9480, each generic timer can select which tsf
+                * to use. But we still follow the old rule, 0 - 7 use tsf and
+                * 8 - 15  use tsf2.
+                */
+               if ((timer->index < AR_GEN_TIMER_BANK_1_LEN))
+                       REG_CLR_BIT(ah, AR_MAC_PCU_GEN_TIMER_TSF_SEL,
+                                      (1 << timer->index));
+               else
+                       REG_SET_BIT(ah, AR_MAC_PCU_GEN_TIMER_TSF_SEL,
+                                      (1 << timer->index));
+       }
+
        /* Enable both trigger and thresh interrupt masks */
        REG_SET_BIT(ah, AR_IMR_S5,
                (SM(AR_GENTMR_BIT(timer->index), AR_IMR_S5_GENTIMER_THRESH) |
@@ -2720,7 +2853,9 @@ static struct {
        { AR_SREV_VERSION_9271,         "9271" },
        { AR_SREV_VERSION_9300,         "9300" },
        { AR_SREV_VERSION_9330,         "9330" },
+       { AR_SREV_VERSION_9340,         "9340" },
        { AR_SREV_VERSION_9485,         "9485" },
+       { AR_SREV_VERSION_9480,         "9480" },
 };
 
 /* For devices with external radios */