ath9k_hw: Fix full sleep setup for AR9271
[safe/jmp/linux-2.6] / drivers / net / wireless / ath / ath9k / hw.c
index 2311fe7..023c38b 100644 (file)
@@ -52,28 +52,6 @@ module_exit(ath9k_exit);
 /* Helper Functions */
 /********************/
 
-static u32 ath9k_hw_mac_usec(struct ath_hw *ah, u32 clks)
-{
-       struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
-
-       if (!ah->curchan) /* should really check for CCK instead */
-               return clks / ATH9K_CLOCK_RATE_CCK;
-       if (conf->channel->band == IEEE80211_BAND_2GHZ)
-               return clks / ATH9K_CLOCK_RATE_2GHZ_OFDM;
-
-       return clks / ATH9K_CLOCK_RATE_5GHZ_OFDM;
-}
-
-static u32 ath9k_hw_mac_to_usec(struct ath_hw *ah, u32 clks)
-{
-       struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
-
-       if (conf_is_ht40(conf))
-               return ath9k_hw_mac_usec(ah, clks) / 2;
-       else
-               return ath9k_hw_mac_usec(ah, clks);
-}
-
 static u32 ath9k_hw_mac_clks(struct ath_hw *ah, u32 usecs)
 {
        struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
@@ -356,7 +334,6 @@ static void ath9k_hw_init_config(struct ath_hw *ah)
        ah->config.pcie_clock_req = 0;
        ah->config.pcie_waen = 0;
        ah->config.analog_shiftreg = 1;
-       ah->config.ht_enable = 1;
        ah->config.ofdm_trig_low = 200;
        ah->config.ofdm_trig_high = 500;
        ah->config.cck_trig_high = 200;
@@ -368,6 +345,11 @@ static void ath9k_hw_init_config(struct ath_hw *ah)
                ah->config.spurchans[i][1] = AR_NO_SPUR;
        }
 
+       if (ah->hw_version.devid != AR2427_DEVID_PCIE)
+               ah->config.ht_enable = 1;
+       else
+               ah->config.ht_enable = 0;
+
        ah->config.rx_intr_mitigation = true;
 
        /*
@@ -413,8 +395,6 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah)
        ah->beacon_interval = 100;
        ah->enable_32kHz_clock = DONT_USE_32KHZ;
        ah->slottime = (u32) -1;
-       ah->acktimeout = (u32) -1;
-       ah->ctstimeout = (u32) -1;
        ah->globaltxtimeout = (u32) -1;
        ah->power_mode = ATH9K_PM_UNDEFINED;
 }
@@ -519,8 +499,10 @@ static int ath9k_hw_post_init(struct ath_hw *ah)
 {
        int ecode;
 
-       if (!ath9k_hw_chip_test(ah))
-               return -ENODEV;
+       if (!AR_SREV_9271(ah)) {
+               if (!ath9k_hw_chip_test(ah))
+                       return -ENODEV;
+       }
 
        ecode = ath9k_hw_rf_claim(ah);
        if (ecode != 0)
@@ -566,6 +548,7 @@ static bool ath9k_hw_devid_supported(u16 devid)
        case AR5416_DEVID_AR9287_PCI:
        case AR5416_DEVID_AR9287_PCIE:
        case AR9271_USB:
+       case AR2427_DEVID_PCIE:
                return true;
        default:
                break;
@@ -622,9 +605,23 @@ static void ath9k_hw_init_mode_regs(struct ath_hw *ah)
                               ARRAY_SIZE(ar9271Modes_9271), 6);
                INIT_INI_ARRAY(&ah->iniCommon, ar9271Common_9271,
                               ARRAY_SIZE(ar9271Common_9271), 2);
+               INIT_INI_ARRAY(&ah->iniCommon_normal_cck_fir_coeff_9271,
+                              ar9271Common_normal_cck_fir_coeff_9271,
+                              ARRAY_SIZE(ar9271Common_normal_cck_fir_coeff_9271), 2);
+               INIT_INI_ARRAY(&ah->iniCommon_japan_2484_cck_fir_coeff_9271,
+                              ar9271Common_japan_2484_cck_fir_coeff_9271,
+                              ARRAY_SIZE(ar9271Common_japan_2484_cck_fir_coeff_9271), 2);
                INIT_INI_ARRAY(&ah->iniModes_9271_1_0_only,
                               ar9271Modes_9271_1_0_only,
                               ARRAY_SIZE(ar9271Modes_9271_1_0_only), 6);
+               INIT_INI_ARRAY(&ah->iniModes_9271_ANI_reg, ar9271Modes_9271_ANI_reg,
+                              ARRAY_SIZE(ar9271Modes_9271_ANI_reg), 6);
+               INIT_INI_ARRAY(&ah->iniModes_high_power_tx_gain_9271,
+                              ar9271Modes_high_power_tx_gain_9271,
+                              ARRAY_SIZE(ar9271Modes_high_power_tx_gain_9271), 6);
+               INIT_INI_ARRAY(&ah->iniModes_normal_power_tx_gain_9271,
+                              ar9271Modes_normal_power_tx_gain_9271,
+                              ARRAY_SIZE(ar9271Modes_normal_power_tx_gain_9271), 6);
                return;
        }
 
@@ -831,12 +828,11 @@ static void ath9k_hw_init_mode_gain_regs(struct ath_hw *ah)
        }
 }
 
-static void ath9k_hw_init_11a_eeprom_fix(struct ath_hw *ah)
+static void ath9k_hw_init_eeprom_fix(struct ath_hw *ah)
 {
        u32 i, j;
 
-       if ((ah->hw_version.devid == AR9280_DEVID_PCI) &&
-           test_bit(ATH9K_MODE_11A, ah->caps.wireless_modes)) {
+       if (ah->hw_version.devid == AR9280_DEVID_PCI) {
 
                /* EEPROM Fixup */
                for (i = 0; i < ah->iniModes.ia_rows; i++) {
@@ -956,7 +952,7 @@ int ath9k_hw_init(struct ath_hw *ah)
        if (r)
                return r;
 
-       ath9k_hw_init_11a_eeprom_fix(ah);
+       ath9k_hw_init_eeprom_fix(ah);
 
        r = ath9k_hw_init_macaddr(ah);
        if (r) {
@@ -1171,7 +1167,8 @@ static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah,
                ah->mask_reg |= AR_IMR_MIB;
 
        REG_WRITE(ah, AR_IMR, ah->mask_reg);
-       REG_WRITE(ah, AR_IMR_S2, REG_READ(ah, AR_IMR_S2) | AR_IMR_S2_GTT);
+       ah->imrs2_reg |= AR_IMR_S2_GTT;
+       REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg);
 
        if (!AR_SREV_9100(ah)) {
                REG_WRITE(ah, AR_INTR_SYNC_CAUSE, 0xFFFFFFFF);
@@ -1180,34 +1177,25 @@ static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah,
        }
 }
 
-static bool ath9k_hw_set_ack_timeout(struct ath_hw *ah, u32 us)
+static void ath9k_hw_setslottime(struct ath_hw *ah, u32 us)
 {
-       if (us > ath9k_hw_mac_to_usec(ah, MS(0xffffffff, AR_TIME_OUT_ACK))) {
-               ath_print(ath9k_hw_common(ah), ATH_DBG_RESET,
-                         "bad ack timeout %u\n", us);
-               ah->acktimeout = (u32) -1;
-               return false;
-       } else {
-               REG_RMW_FIELD(ah, AR_TIME_OUT,
-                             AR_TIME_OUT_ACK, ath9k_hw_mac_to_clks(ah, us));
-               ah->acktimeout = us;
-               return true;
-       }
+       u32 val = ath9k_hw_mac_to_clks(ah, us);
+       val = min(val, (u32) 0xFFFF);
+       REG_WRITE(ah, AR_D_GBL_IFS_SLOT, val);
 }
 
-static bool ath9k_hw_set_cts_timeout(struct ath_hw *ah, u32 us)
+static void ath9k_hw_set_ack_timeout(struct ath_hw *ah, u32 us)
 {
-       if (us > ath9k_hw_mac_to_usec(ah, MS(0xffffffff, AR_TIME_OUT_CTS))) {
-               ath_print(ath9k_hw_common(ah), ATH_DBG_RESET,
-                         "bad cts timeout %u\n", us);
-               ah->ctstimeout = (u32) -1;
-               return false;
-       } else {
-               REG_RMW_FIELD(ah, AR_TIME_OUT,
-                             AR_TIME_OUT_CTS, ath9k_hw_mac_to_clks(ah, us));
-               ah->ctstimeout = us;
-               return true;
-       }
+       u32 val = ath9k_hw_mac_to_clks(ah, us);
+       val = min(val, (u32) MS(0xFFFFFFFF, AR_TIME_OUT_ACK));
+       REG_RMW_FIELD(ah, AR_TIME_OUT, AR_TIME_OUT_ACK, val);
+}
+
+static void ath9k_hw_set_cts_timeout(struct ath_hw *ah, u32 us)
+{
+       u32 val = ath9k_hw_mac_to_clks(ah, us);
+       val = min(val, (u32) MS(0xFFFFFFFF, AR_TIME_OUT_CTS));
+       REG_RMW_FIELD(ah, AR_TIME_OUT, AR_TIME_OUT_CTS, val);
 }
 
 static bool ath9k_hw_set_global_txtimeout(struct ath_hw *ah, u32 tu)
@@ -1224,23 +1212,46 @@ static bool ath9k_hw_set_global_txtimeout(struct ath_hw *ah, u32 tu)
        }
 }
 
-static void ath9k_hw_init_user_settings(struct ath_hw *ah)
+void ath9k_hw_init_global_settings(struct ath_hw *ah)
 {
+       struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
+       int acktimeout;
+       int slottime;
+       int sifstime;
+
        ath_print(ath9k_hw_common(ah), ATH_DBG_RESET, "ah->misc_mode 0x%x\n",
                  ah->misc_mode);
 
        if (ah->misc_mode != 0)
                REG_WRITE(ah, AR_PCU_MISC,
                          REG_READ(ah, AR_PCU_MISC) | ah->misc_mode);
-       if (ah->slottime != (u32) -1)
-               ath9k_hw_setslottime(ah, ah->slottime);
-       if (ah->acktimeout != (u32) -1)
-               ath9k_hw_set_ack_timeout(ah, ah->acktimeout);
-       if (ah->ctstimeout != (u32) -1)
-               ath9k_hw_set_cts_timeout(ah, ah->ctstimeout);
+
+       if (conf->channel && conf->channel->band == IEEE80211_BAND_5GHZ)
+               sifstime = 16;
+       else
+               sifstime = 10;
+
+       /* As defined by IEEE 802.11-2007 17.3.8.6 */
+       slottime = ah->slottime + 3 * ah->coverage_class;
+       acktimeout = slottime + sifstime;
+
+       /*
+        * Workaround for early ACK timeouts, add an offset to match the
+        * initval's 64us ack timeout value.
+        * This was initially only meant to work around an issue with delayed
+        * BA frames in some implementations, but it has been found to fix ACK
+        * timeout issues in other cases as well.
+        */
+       if (conf->channel && conf->channel->band == IEEE80211_BAND_2GHZ)
+               acktimeout += 64 - sifstime - ah->slottime;
+
+       ath9k_hw_setslottime(ah, slottime);
+       ath9k_hw_set_ack_timeout(ah, acktimeout);
+       ath9k_hw_set_cts_timeout(ah, acktimeout);
        if (ah->globaltxtimeout != (u32) -1)
                ath9k_hw_set_global_txtimeout(ah, ah->globaltxtimeout);
 }
+EXPORT_SYMBOL(ath9k_hw_init_global_settings);
 
 void ath9k_hw_deinit(struct ath_hw *ah)
 {
@@ -1271,26 +1282,6 @@ static void ath9k_hw_override_ini(struct ath_hw *ah,
 {
        u32 val;
 
-       if (AR_SREV_9271(ah)) {
-               /*
-                * Enable spectral scan to solution for issues with stuck
-                * beacons on AR9271 1.0. The beacon stuck issue is not seeon on
-                * AR9271 1.1
-                */
-               if (AR_SREV_9271_10(ah)) {
-                       val = REG_READ(ah, AR_PHY_SPECTRAL_SCAN) |
-                             AR_PHY_SPECTRAL_SCAN_ENABLE;
-                       REG_WRITE(ah, AR_PHY_SPECTRAL_SCAN, val);
-               }
-               else if (AR_SREV_9271_11(ah))
-                       /*
-                        * change AR_PHY_RF_CTL3 setting to fix MAC issue
-                        * present on AR9271 1.1
-                        */
-                       REG_WRITE(ah, AR_PHY_RF_CTL3, 0x3a020001);
-               return;
-       }
-
        /*
         * Set the RX_ABORT and RX_DIS and clear if off only after
         * RXE is set for MAC. This prevents frames with corrupted
@@ -1299,8 +1290,10 @@ static void ath9k_hw_override_ini(struct ath_hw *ah,
        REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
 
        if (AR_SREV_9280_10_OR_LATER(ah)) {
-               val = REG_READ(ah, AR_PCU_MISC_MODE2) &
-                              (~AR_PCU_MISC_MODE2_HWWAR1);
+               val = REG_READ(ah, AR_PCU_MISC_MODE2);
+
+               if (!AR_SREV_9271(ah))
+                       val &= ~AR_PCU_MISC_MODE2_HWWAR1;
 
                if (AR_SREV_9287_10_OR_LATER(ah))
                        val = val & (~AR_PCU_MISC_MODE2_HWWAR2);
@@ -1316,6 +1309,16 @@ static void ath9k_hw_override_ini(struct ath_hw *ah,
         * Necessary to avoid issues on AR5416 2.0
         */
        REG_WRITE(ah, 0x9800 + (651 << 2), 0x11);
+
+       /*
+        * Disable RIFS search on some chips to avoid baseband
+        * hang issues.
+        */
+       if (AR_SREV_9100(ah) || AR_SREV_9160(ah)) {
+               val = REG_READ(ah, AR_PHY_HEAVY_CLIP_FACTOR_RIFS);
+               val &= ~AR_PHY_RIFS_INIT_DELAY;
+               REG_WRITE(ah, AR_PHY_HEAVY_CLIP_FACTOR_RIFS, val);
+       }
 }
 
 static u32 ath9k_hw_def_ini_fixup(struct ath_hw *ah,
@@ -1434,7 +1437,10 @@ static int ath9k_hw_process_ini(struct ath_hw *ah,
                return -EINVAL;
        }
 
+       /* Set correct baseband to analog shift setting to access analog chips */
        REG_WRITE(ah, AR_PHY(0), 0x00000007);
+
+       /* Write ADDAC shifts */
        REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_EXTERNAL_RADIO);
        ah->eep_ops->set_addac(ah, chan);
 
@@ -1446,9 +1452,11 @@ static int ath9k_hw_process_ini(struct ath_hw *ah,
                        sizeof(u32) * ah->iniAddac.ia_rows *
                        ah->iniAddac.ia_columns;
 
+               /* For AR5416 2.0/2.1 */
                memcpy(ah->addac5416_21,
                       ah->iniAddac.ia_array, addacSize);
 
+               /* override CLKDRV value at [row, column] = [31, 1] */
                (ah->addac5416_21)[31 * ah->iniAddac.ia_columns + 1] = 0;
 
                temp.ia_array = ah->addac5416_21;
@@ -1480,6 +1488,11 @@ static int ath9k_hw_process_ini(struct ath_hw *ah,
            AR_SREV_9287_10_OR_LATER(ah))
                REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites);
 
+       if (AR_SREV_9271_10(ah))
+               REG_WRITE_ARRAY(&ah->iniModes_9271_1_0_only,
+                               modesIndex, regWrites);
+
+       /* Write common array parameters */
        for (i = 0; i < ah->iniCommon.ia_rows; i++) {
                u32 reg = INI_RA(&ah->iniCommon, i, 0);
                u32 val = INI_RA(&ah->iniCommon, i, 1);
@@ -1494,11 +1507,16 @@ static int ath9k_hw_process_ini(struct ath_hw *ah,
                DO_DELAY(regWrites);
        }
 
-       ath9k_hw_write_regs(ah, freqIndex, regWrites);
+       if (AR_SREV_9271(ah)) {
+               if (ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE) == 1)
+                       REG_WRITE_ARRAY(&ah->iniModes_high_power_tx_gain_9271,
+                                       modesIndex, regWrites);
+               else
+                       REG_WRITE_ARRAY(&ah->iniModes_normal_power_tx_gain_9271,
+                                       modesIndex, regWrites);
+       }
 
-       if (AR_SREV_9271_10(ah))
-               REG_WRITE_ARRAY(&ah->iniModes_9271_1_0_only,
-                               modesIndex, regWrites);
+       ath9k_hw_write_regs(ah, freqIndex, regWrites);
 
        if (AR_SREV_9280_20(ah) && IS_CHAN_A_5MHZ_SPACED(chan)) {
                REG_WRITE_ARRAY(&ah->iniModesAdditional, modesIndex,
@@ -1512,6 +1530,7 @@ static int ath9k_hw_process_ini(struct ath_hw *ah,
        if (OLC_FOR_AR9280_20_LATER)
                ath9k_olc_init(ah);
 
+       /* Set TX power */
        ah->eep_ops->set_txpower(ah, chan,
                                 ath9k_regd_get_ctl(regulatory, chan),
                                 channel->max_antenna_gain * 2,
@@ -1519,6 +1538,7 @@ static int ath9k_hw_process_ini(struct ath_hw *ah,
                                 min((u32) MAX_RATE_POWER,
                                 (u32) regulatory->power_limit));
 
+       /* Write analog registers */
        if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) {
                ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL,
                          "ar5416SetRfRegs failed\n");
@@ -2061,7 +2081,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
        if (ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
                ath9k_enable_rfkill(ah);
 
-       ath9k_hw_init_user_settings(ah);
+       ath9k_hw_init_global_settings(ah);
 
        if (AR_SREV_9287_12_OR_LATER(ah)) {
                REG_WRITE(ah, AR_D_GBL_IFS_SIFS,
@@ -2433,7 +2453,7 @@ static void ath9k_set_power_sleep(struct ath_hw *ah, int setChip)
                if (!AR_SREV_9100(ah))
                        REG_WRITE(ah, AR_RC, AR_RC_AHB | AR_RC_HOSTIF);
 
-               if(!AR_SREV_5416(ah))
+               if (!AR_SREV_5416(ah) && !AR_SREV_9271(ah))
                        REG_CLR_BIT(ah, (AR_RTC_RESET),
                                    AR_RTC_RESET_EN);
        }
@@ -2916,14 +2936,11 @@ enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints)
 
        ath_print(common, ATH_DBG_INTERRUPT, "new IMR 0x%x\n", mask);
        REG_WRITE(ah, AR_IMR, mask);
-       mask = REG_READ(ah, AR_IMR_S2) & ~(AR_IMR_S2_TIM |
-                                          AR_IMR_S2_DTIM |
-                                          AR_IMR_S2_DTIMSYNC |
-                                          AR_IMR_S2_CABEND |
-                                          AR_IMR_S2_CABTO |
-                                          AR_IMR_S2_TSFOOR |
-                                          AR_IMR_S2_GTT | AR_IMR_S2_CST);
-       REG_WRITE(ah, AR_IMR_S2, mask | mask2);
+       ah->imrs2_reg &= ~(AR_IMR_S2_TIM | AR_IMR_S2_DTIM | AR_IMR_S2_DTIMSYNC |
+                          AR_IMR_S2_CABEND | AR_IMR_S2_CABTO |
+                          AR_IMR_S2_TSFOOR | AR_IMR_S2_GTT | AR_IMR_S2_CST);
+       ah->imrs2_reg |= mask2;
+       REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg);
        ah->mask_reg = ints;
 
        if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
@@ -3214,7 +3231,9 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
        else
                pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD;
 
-       if (AR_SREV_9285_10_OR_LATER(ah))
+       if (AR_SREV_9271(ah))
+               pCap->num_gpio_pins = AR9271_NUM_GPIO;
+       else if (AR_SREV_9285_10_OR_LATER(ah))
                pCap->num_gpio_pins = AR9285_NUM_GPIO;
        else if (AR_SREV_9280_10_OR_LATER(ah))
                pCap->num_gpio_pins = AR928X_NUM_GPIO;
@@ -3450,7 +3469,9 @@ u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio)
        if (gpio >= ah->caps.num_gpio_pins)
                return 0xffffffff;
 
-       if (AR_SREV_9287_10_OR_LATER(ah))
+       if (AR_SREV_9271(ah))
+               return MS_REG_READ(AR9271, gpio) != 0;
+       else if (AR_SREV_9287_10_OR_LATER(ah))
                return MS_REG_READ(AR9287, gpio) != 0;
        else if (AR_SREV_9285_10_OR_LATER(ah))
                return MS_REG_READ(AR9285, gpio) != 0;
@@ -3479,6 +3500,9 @@ EXPORT_SYMBOL(ath9k_hw_cfg_output);
 
 void ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val)
 {
+       if (AR_SREV_9271(ah))
+               val = ~val;
+
        REG_RMW(ah, AR_GPIO_IN_OUT, ((val & 1) << gpio),
                AR_GPIO_BIT(gpio));
 }
@@ -3658,21 +3682,6 @@ u64 ath9k_hw_extend_tsf(struct ath_hw *ah, u32 rstamp)
 }
 EXPORT_SYMBOL(ath9k_hw_extend_tsf);
 
-bool ath9k_hw_setslottime(struct ath_hw *ah, u32 us)
-{
-       if (us < ATH9K_SLOT_TIME_9 || us > ath9k_hw_mac_to_usec(ah, 0xffff)) {
-               ath_print(ath9k_hw_common(ah), ATH_DBG_RESET,
-                         "bad slot time %u\n", us);
-               ah->slottime = (u32) -1;
-               return false;
-       } else {
-               REG_WRITE(ah, AR_D_GBL_IFS_SLOT, ath9k_hw_mac_to_clks(ah, us));
-               ah->slottime = us;
-               return true;
-       }
-}
-EXPORT_SYMBOL(ath9k_hw_setslottime);
-
 void ath9k_hw_set11nmac2040(struct ath_hw *ah)
 {
        struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;