]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - drivers/net/wireless/ath/ath9k/hw.c
ath9k_hw: disable TX IQ calibration for AR9003
[net-next-2.6.git] / drivers / net / wireless / ath / ath9k / hw.c
index 7b1ba6fa4becde8274698de25963bc2684bb2bee..40b6e8415946d12dc4c7d2ca1c647568fd10f2e7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2009 Atheros Communications Inc.
+ * Copyright (c) 2008-2010 Atheros Communications Inc.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
 #include <asm/unaligned.h>
 
 #include "hw.h"
+#include "hw-ops.h"
 #include "rc.h"
-#include "initvals.h"
+#include "ar9003_mac.h"
 
 #define ATH9K_CLOCK_RATE_CCK           22
 #define ATH9K_CLOCK_RATE_5GHZ_OFDM     40
 #define ATH9K_CLOCK_RATE_2GHZ_OFDM     44
 
 static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type);
-static void ath9k_hw_set_regs(struct ath_hw *ah, struct ath9k_channel *chan);
-static u32 ath9k_hw_ini_fixup(struct ath_hw *ah,
-                             struct ar5416_eeprom_def *pEepData,
-                             u32 reg, u32 value);
 
 MODULE_AUTHOR("Atheros Communications");
 MODULE_DESCRIPTION("Support for Atheros 802.11n wireless LAN cards.");
@@ -48,6 +45,39 @@ static void __exit ath9k_exit(void)
 }
 module_exit(ath9k_exit);
 
+/* Private hardware callbacks */
+
+static void ath9k_hw_init_cal_settings(struct ath_hw *ah)
+{
+       ath9k_hw_private_ops(ah)->init_cal_settings(ah);
+}
+
+static void ath9k_hw_init_mode_regs(struct ath_hw *ah)
+{
+       ath9k_hw_private_ops(ah)->init_mode_regs(ah);
+}
+
+static bool ath9k_hw_macversion_supported(struct ath_hw *ah)
+{
+       struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
+
+       return priv_ops->macversion_supported(ah->hw_version.macVersion);
+}
+
+static u32 ath9k_hw_compute_pll_control(struct ath_hw *ah,
+                                       struct ath9k_channel *chan)
+{
+       return ath9k_hw_private_ops(ah)->compute_pll_control(ah, chan);
+}
+
+static void ath9k_hw_init_mode_gain_regs(struct ath_hw *ah)
+{
+       if (!ath9k_hw_private_ops(ah)->init_mode_gain_regs)
+               return;
+
+       ath9k_hw_private_ops(ah)->init_mode_gain_regs(ah);
+}
+
 /********************/
 /* Helper Functions */
 /********************/
@@ -235,21 +265,6 @@ static void ath9k_hw_read_revisions(struct ath_hw *ah)
        }
 }
 
-static int ath9k_hw_get_radiorev(struct ath_hw *ah)
-{
-       u32 val;
-       int i;
-
-       REG_WRITE(ah, AR_PHY(0x36), 0x00007058);
-
-       for (i = 0; i < 8; i++)
-               REG_WRITE(ah, AR_PHY(0x20), 0x00010000);
-       val = (REG_READ(ah, AR_PHY(256)) >> 24) & 0xff;
-       val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4);
-
-       return ath9k_hw_reverse_bits(val, 8);
-}
-
 /************************************/
 /* HW Attach, Detach, Init Routines */
 /************************************/
@@ -259,6 +274,8 @@ static void ath9k_hw_disablepcie(struct ath_hw *ah)
        if (AR_SREV_9100(ah))
                return;
 
+       ENABLE_REGWRITE_BUFFER(ah);
+
        REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00);
        REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
        REG_WRITE(ah, AR_PCIE_SERDES, 0x28000029);
@@ -270,20 +287,30 @@ static void ath9k_hw_disablepcie(struct ath_hw *ah)
        REG_WRITE(ah, AR_PCIE_SERDES, 0x000e1007);
 
        REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
+
+       REGWRITE_BUFFER_FLUSH(ah);
+       DISABLE_REGWRITE_BUFFER(ah);
 }
 
+/* This should work for all families including legacy */
 static bool ath9k_hw_chip_test(struct ath_hw *ah)
 {
        struct ath_common *common = ath9k_hw_common(ah);
-       u32 regAddr[2] = { AR_STA_ID0, AR_PHY_BASE + (8 << 2) };
+       u32 regAddr[2] = { AR_STA_ID0 };
        u32 regHold[2];
        u32 patternData[4] = { 0x55555555,
                               0xaaaaaaaa,
                               0x66666666,
                               0x99999999 };
-       int i, j;
+       int i, j, loop_max;
+
+       if (!AR_SREV_9300_20_OR_LATER(ah)) {
+               loop_max = 2;
+               regAddr[1] = AR_PHY_BASE + (8 << 2);
+       } else
+               loop_max = 1;
 
-       for (i = 0; i < 2; i++) {
+       for (i = 0; i < loop_max; i++) {
                u32 addr = regAddr[i];
                u32 wrData, rdData;
 
@@ -338,7 +365,13 @@ static void ath9k_hw_init_config(struct ath_hw *ah)
        ah->config.ofdm_trig_high = 500;
        ah->config.cck_trig_high = 200;
        ah->config.cck_trig_low = 100;
-       ah->config.enable_ani = 1;
+
+       /*
+        * For now ANI is disabled for AR9003, it is still
+        * being tested.
+        */
+       if (!AR_SREV_9300_20_OR_LATER(ah))
+               ah->config.enable_ani = 1;
 
        for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
                ah->config.spurchans[i][0] = AR_NO_SPUR;
@@ -352,6 +385,12 @@ static void ath9k_hw_init_config(struct ath_hw *ah)
 
        ah->config.rx_intr_mitigation = true;
 
+       /*
+        * Tx IQ Calibration (ah->config.tx_iq_calibration) is only
+        * used by AR9003, but it is showing reliability issues.
+        * It will take a while to fix so this is currently disabled.
+        */
+
        /*
         * We need this for PCI devices only (Cardbus, PCI, miniPCI)
         * _and_ if on non-uniprocessor systems (Multiprocessor/HT).
@@ -371,7 +410,6 @@ static void ath9k_hw_init_config(struct ath_hw *ah)
        if (num_possible_cpus() > 1)
                ah->config.serialize_regmode = SER_REG_MODE_AUTO;
 }
-EXPORT_SYMBOL(ath9k_hw_init);
 
 static void ath9k_hw_init_defaults(struct ath_hw *ah)
 {
@@ -385,8 +423,6 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah)
        ah->hw_version.subvendorid = 0;
 
        ah->ah_flags = 0;
-       if (ah->hw_version.devid == AR5416_AR9100_DEVID)
-               ah->hw_version.macVersion = AR_SREV_VERSION_9100;
        if (!AR_SREV_9100(ah))
                ah->ah_flags = AH_USE_EEPROM;
 
@@ -399,44 +435,17 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah)
        ah->power_mode = ATH9K_PM_UNDEFINED;
 }
 
-static int ath9k_hw_rf_claim(struct ath_hw *ah)
-{
-       u32 val;
-
-       REG_WRITE(ah, AR_PHY(0), 0x00000007);
-
-       val = ath9k_hw_get_radiorev(ah);
-       switch (val & AR_RADIO_SREV_MAJOR) {
-       case 0:
-               val = AR_RAD5133_SREV_MAJOR;
-               break;
-       case AR_RAD5133_SREV_MAJOR:
-       case AR_RAD5122_SREV_MAJOR:
-       case AR_RAD2133_SREV_MAJOR:
-       case AR_RAD2122_SREV_MAJOR:
-               break;
-       default:
-               ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL,
-                         "Radio Chip Rev 0x%02X not supported\n",
-                         val & AR_RADIO_SREV_MAJOR);
-               return -EOPNOTSUPP;
-       }
-
-       ah->hw_version.analog5GhzRev = val;
-
-       return 0;
-}
-
 static int ath9k_hw_init_macaddr(struct ath_hw *ah)
 {
        struct ath_common *common = ath9k_hw_common(ah);
        u32 sum;
        int i;
        u16 eeval;
+       u32 EEP_MAC[] = { EEP_MAC_LSW, EEP_MAC_MID, EEP_MAC_MSW };
 
        sum = 0;
        for (i = 0; i < 3; i++) {
-               eeval = ah->eep_ops->get_eeprom(ah, AR_EEPROM_MAC(i));
+               eeval = ah->eep_ops->get_eeprom(ah, EEP_MAC[i]);
                sum += eeval;
                common->macaddr[2 * i] = eeval >> 8;
                common->macaddr[2 * i + 1] = eeval & 0xff;
@@ -447,64 +456,20 @@ static int ath9k_hw_init_macaddr(struct ath_hw *ah)
        return 0;
 }
 
-static void ath9k_hw_init_rxgain_ini(struct ath_hw *ah)
-{
-       u32 rxgain_type;
-
-       if (ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV) >= AR5416_EEP_MINOR_VER_17) {
-               rxgain_type = ah->eep_ops->get_eeprom(ah, EEP_RXGAIN_TYPE);
-
-               if (rxgain_type == AR5416_EEP_RXGAIN_13DB_BACKOFF)
-                       INIT_INI_ARRAY(&ah->iniModesRxGain,
-                       ar9280Modes_backoff_13db_rxgain_9280_2,
-                       ARRAY_SIZE(ar9280Modes_backoff_13db_rxgain_9280_2), 6);
-               else if (rxgain_type == AR5416_EEP_RXGAIN_23DB_BACKOFF)
-                       INIT_INI_ARRAY(&ah->iniModesRxGain,
-                       ar9280Modes_backoff_23db_rxgain_9280_2,
-                       ARRAY_SIZE(ar9280Modes_backoff_23db_rxgain_9280_2), 6);
-               else
-                       INIT_INI_ARRAY(&ah->iniModesRxGain,
-                       ar9280Modes_original_rxgain_9280_2,
-                       ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 6);
-       } else {
-               INIT_INI_ARRAY(&ah->iniModesRxGain,
-                       ar9280Modes_original_rxgain_9280_2,
-                       ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 6);
-       }
-}
-
-static void ath9k_hw_init_txgain_ini(struct ath_hw *ah)
-{
-       u32 txgain_type;
-
-       if (ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV) >= AR5416_EEP_MINOR_VER_19) {
-               txgain_type = ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE);
-
-               if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER)
-                       INIT_INI_ARRAY(&ah->iniModesTxGain,
-                       ar9280Modes_high_power_tx_gain_9280_2,
-                       ARRAY_SIZE(ar9280Modes_high_power_tx_gain_9280_2), 6);
-               else
-                       INIT_INI_ARRAY(&ah->iniModesTxGain,
-                       ar9280Modes_original_tx_gain_9280_2,
-                       ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 6);
-       } else {
-               INIT_INI_ARRAY(&ah->iniModesTxGain,
-               ar9280Modes_original_tx_gain_9280_2,
-               ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 6);
-       }
-}
-
 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)
-               return ecode;
+       if (!AR_SREV_9300_20_OR_LATER(ah)) {
+               ecode = ar9002_hw_rf_claim(ah);
+               if (ecode != 0)
+                       return ecode;
+       }
 
        ecode = ath9k_hw_eeprom_init(ah);
        if (ecode != 0)
@@ -515,14 +480,12 @@ static int ath9k_hw_post_init(struct ath_hw *ah)
                  ah->eep_ops->get_eeprom_ver(ah),
                  ah->eep_ops->get_eeprom_rev(ah));
 
-        if (!AR_SREV_9280_10_OR_LATER(ah)) {
-               ecode = ath9k_hw_rf_alloc_ext_banks(ah);
-               if (ecode) {
-                       ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL,
-                                 "Failed allocating banks for "
-                                 "external radio\n");
-                       return ecode;
-               }
+       ecode = ath9k_hw_rf_alloc_ext_banks(ah);
+       if (ecode) {
+               ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL,
+                         "Failed allocating banks for "
+                         "external radio\n");
+               return ecode;
        }
 
        if (!AR_SREV_9100(ah)) {
@@ -533,335 +496,22 @@ static int ath9k_hw_post_init(struct ath_hw *ah)
        return 0;
 }
 
-static bool ath9k_hw_devid_supported(u16 devid)
+static void ath9k_hw_attach_ops(struct ath_hw *ah)
 {
-       switch (devid) {
-       case AR5416_DEVID_PCI:
-       case AR5416_DEVID_PCIE:
-       case AR5416_AR9100_DEVID:
-       case AR9160_DEVID_PCI:
-       case AR9280_DEVID_PCI:
-       case AR9280_DEVID_PCIE:
-       case AR9285_DEVID_PCIE:
-       case AR5416_DEVID_AR9287_PCI:
-       case AR5416_DEVID_AR9287_PCIE:
-       case AR9271_USB:
-       case AR2427_DEVID_PCIE:
-               return true;
-       default:
-               break;
-       }
-       return false;
-}
-
-static bool ath9k_hw_macversion_supported(u32 macversion)
-{
-       switch (macversion) {
-       case AR_SREV_VERSION_5416_PCI:
-       case AR_SREV_VERSION_5416_PCIE:
-       case AR_SREV_VERSION_9160:
-       case AR_SREV_VERSION_9100:
-       case AR_SREV_VERSION_9280:
-       case AR_SREV_VERSION_9285:
-       case AR_SREV_VERSION_9287:
-       case AR_SREV_VERSION_9271:
-               return true;
-       default:
-               break;
-       }
-       return false;
-}
-
-static void ath9k_hw_init_cal_settings(struct ath_hw *ah)
-{
-       if (AR_SREV_9160_10_OR_LATER(ah)) {
-               if (AR_SREV_9280_10_OR_LATER(ah)) {
-                       ah->iq_caldata.calData = &iq_cal_single_sample;
-                       ah->adcgain_caldata.calData =
-                               &adc_gain_cal_single_sample;
-                       ah->adcdc_caldata.calData =
-                               &adc_dc_cal_single_sample;
-                       ah->adcdc_calinitdata.calData =
-                               &adc_init_dc_cal;
-               } else {
-                       ah->iq_caldata.calData = &iq_cal_multi_sample;
-                       ah->adcgain_caldata.calData =
-                               &adc_gain_cal_multi_sample;
-                       ah->adcdc_caldata.calData =
-                               &adc_dc_cal_multi_sample;
-                       ah->adcdc_calinitdata.calData =
-                               &adc_init_dc_cal;
-               }
-               ah->supp_cals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL;
-       }
-}
-
-static void ath9k_hw_init_mode_regs(struct ath_hw *ah)
-{
-       if (AR_SREV_9271(ah)) {
-               INIT_INI_ARRAY(&ah->iniModes, ar9271Modes_9271,
-                              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;
-       }
-
-       if (AR_SREV_9287_11_OR_LATER(ah)) {
-               INIT_INI_ARRAY(&ah->iniModes, ar9287Modes_9287_1_1,
-                               ARRAY_SIZE(ar9287Modes_9287_1_1), 6);
-               INIT_INI_ARRAY(&ah->iniCommon, ar9287Common_9287_1_1,
-                               ARRAY_SIZE(ar9287Common_9287_1_1), 2);
-               if (ah->config.pcie_clock_req)
-                       INIT_INI_ARRAY(&ah->iniPcieSerdes,
-                       ar9287PciePhy_clkreq_off_L1_9287_1_1,
-                       ARRAY_SIZE(ar9287PciePhy_clkreq_off_L1_9287_1_1), 2);
-               else
-                       INIT_INI_ARRAY(&ah->iniPcieSerdes,
-                       ar9287PciePhy_clkreq_always_on_L1_9287_1_1,
-                       ARRAY_SIZE(ar9287PciePhy_clkreq_always_on_L1_9287_1_1),
-                                       2);
-       } else if (AR_SREV_9287_10_OR_LATER(ah)) {
-               INIT_INI_ARRAY(&ah->iniModes, ar9287Modes_9287_1_0,
-                               ARRAY_SIZE(ar9287Modes_9287_1_0), 6);
-               INIT_INI_ARRAY(&ah->iniCommon, ar9287Common_9287_1_0,
-                               ARRAY_SIZE(ar9287Common_9287_1_0), 2);
-
-               if (ah->config.pcie_clock_req)
-                       INIT_INI_ARRAY(&ah->iniPcieSerdes,
-                       ar9287PciePhy_clkreq_off_L1_9287_1_0,
-                       ARRAY_SIZE(ar9287PciePhy_clkreq_off_L1_9287_1_0), 2);
-               else
-                       INIT_INI_ARRAY(&ah->iniPcieSerdes,
-                       ar9287PciePhy_clkreq_always_on_L1_9287_1_0,
-                       ARRAY_SIZE(ar9287PciePhy_clkreq_always_on_L1_9287_1_0),
-                                 2);
-       } else if (AR_SREV_9285_12_OR_LATER(ah)) {
-
-
-               INIT_INI_ARRAY(&ah->iniModes, ar9285Modes_9285_1_2,
-                              ARRAY_SIZE(ar9285Modes_9285_1_2), 6);
-               INIT_INI_ARRAY(&ah->iniCommon, ar9285Common_9285_1_2,
-                              ARRAY_SIZE(ar9285Common_9285_1_2), 2);
-
-               if (ah->config.pcie_clock_req) {
-                       INIT_INI_ARRAY(&ah->iniPcieSerdes,
-                       ar9285PciePhy_clkreq_off_L1_9285_1_2,
-                       ARRAY_SIZE(ar9285PciePhy_clkreq_off_L1_9285_1_2), 2);
-               } else {
-                       INIT_INI_ARRAY(&ah->iniPcieSerdes,
-                       ar9285PciePhy_clkreq_always_on_L1_9285_1_2,
-                       ARRAY_SIZE(ar9285PciePhy_clkreq_always_on_L1_9285_1_2),
-                                 2);
-               }
-       } else if (AR_SREV_9285_10_OR_LATER(ah)) {
-               INIT_INI_ARRAY(&ah->iniModes, ar9285Modes_9285,
-                              ARRAY_SIZE(ar9285Modes_9285), 6);
-               INIT_INI_ARRAY(&ah->iniCommon, ar9285Common_9285,
-                              ARRAY_SIZE(ar9285Common_9285), 2);
-
-               if (ah->config.pcie_clock_req) {
-                       INIT_INI_ARRAY(&ah->iniPcieSerdes,
-                       ar9285PciePhy_clkreq_off_L1_9285,
-                       ARRAY_SIZE(ar9285PciePhy_clkreq_off_L1_9285), 2);
-               } else {
-                       INIT_INI_ARRAY(&ah->iniPcieSerdes,
-                       ar9285PciePhy_clkreq_always_on_L1_9285,
-                       ARRAY_SIZE(ar9285PciePhy_clkreq_always_on_L1_9285), 2);
-               }
-       } else if (AR_SREV_9280_20_OR_LATER(ah)) {
-               INIT_INI_ARRAY(&ah->iniModes, ar9280Modes_9280_2,
-                              ARRAY_SIZE(ar9280Modes_9280_2), 6);
-               INIT_INI_ARRAY(&ah->iniCommon, ar9280Common_9280_2,
-                              ARRAY_SIZE(ar9280Common_9280_2), 2);
-
-               if (ah->config.pcie_clock_req) {
-                       INIT_INI_ARRAY(&ah->iniPcieSerdes,
-                              ar9280PciePhy_clkreq_off_L1_9280,
-                              ARRAY_SIZE(ar9280PciePhy_clkreq_off_L1_9280),2);
-               } else {
-                       INIT_INI_ARRAY(&ah->iniPcieSerdes,
-                              ar9280PciePhy_clkreq_always_on_L1_9280,
-                              ARRAY_SIZE(ar9280PciePhy_clkreq_always_on_L1_9280), 2);
-               }
-               INIT_INI_ARRAY(&ah->iniModesAdditional,
-                              ar9280Modes_fast_clock_9280_2,
-                              ARRAY_SIZE(ar9280Modes_fast_clock_9280_2), 3);
-       } else if (AR_SREV_9280_10_OR_LATER(ah)) {
-               INIT_INI_ARRAY(&ah->iniModes, ar9280Modes_9280,
-                              ARRAY_SIZE(ar9280Modes_9280), 6);
-               INIT_INI_ARRAY(&ah->iniCommon, ar9280Common_9280,
-                              ARRAY_SIZE(ar9280Common_9280), 2);
-       } else if (AR_SREV_9160_10_OR_LATER(ah)) {
-               INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9160,
-                              ARRAY_SIZE(ar5416Modes_9160), 6);
-               INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9160,
-                              ARRAY_SIZE(ar5416Common_9160), 2);
-               INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0_9160,
-                              ARRAY_SIZE(ar5416Bank0_9160), 2);
-               INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain_9160,
-                              ARRAY_SIZE(ar5416BB_RfGain_9160), 3);
-               INIT_INI_ARRAY(&ah->iniBank1, ar5416Bank1_9160,
-                              ARRAY_SIZE(ar5416Bank1_9160), 2);
-               INIT_INI_ARRAY(&ah->iniBank2, ar5416Bank2_9160,
-                              ARRAY_SIZE(ar5416Bank2_9160), 2);
-               INIT_INI_ARRAY(&ah->iniBank3, ar5416Bank3_9160,
-                              ARRAY_SIZE(ar5416Bank3_9160), 3);
-               INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6_9160,
-                              ARRAY_SIZE(ar5416Bank6_9160), 3);
-               INIT_INI_ARRAY(&ah->iniBank6TPC, ar5416Bank6TPC_9160,
-                              ARRAY_SIZE(ar5416Bank6TPC_9160), 3);
-               INIT_INI_ARRAY(&ah->iniBank7, ar5416Bank7_9160,
-                              ARRAY_SIZE(ar5416Bank7_9160), 2);
-               if (AR_SREV_9160_11(ah)) {
-                       INIT_INI_ARRAY(&ah->iniAddac,
-                                      ar5416Addac_91601_1,
-                                      ARRAY_SIZE(ar5416Addac_91601_1), 2);
-               } else {
-                       INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac_9160,
-                                      ARRAY_SIZE(ar5416Addac_9160), 2);
-               }
-       } else if (AR_SREV_9100_OR_LATER(ah)) {
-               INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9100,
-                              ARRAY_SIZE(ar5416Modes_9100), 6);
-               INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9100,
-                              ARRAY_SIZE(ar5416Common_9100), 2);
-               INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0_9100,
-                              ARRAY_SIZE(ar5416Bank0_9100), 2);
-               INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain_9100,
-                              ARRAY_SIZE(ar5416BB_RfGain_9100), 3);
-               INIT_INI_ARRAY(&ah->iniBank1, ar5416Bank1_9100,
-                              ARRAY_SIZE(ar5416Bank1_9100), 2);
-               INIT_INI_ARRAY(&ah->iniBank2, ar5416Bank2_9100,
-                              ARRAY_SIZE(ar5416Bank2_9100), 2);
-               INIT_INI_ARRAY(&ah->iniBank3, ar5416Bank3_9100,
-                              ARRAY_SIZE(ar5416Bank3_9100), 3);
-               INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6_9100,
-                              ARRAY_SIZE(ar5416Bank6_9100), 3);
-               INIT_INI_ARRAY(&ah->iniBank6TPC, ar5416Bank6TPC_9100,
-                              ARRAY_SIZE(ar5416Bank6TPC_9100), 3);
-               INIT_INI_ARRAY(&ah->iniBank7, ar5416Bank7_9100,
-                              ARRAY_SIZE(ar5416Bank7_9100), 2);
-               INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac_9100,
-                              ARRAY_SIZE(ar5416Addac_9100), 2);
-       } else {
-               INIT_INI_ARRAY(&ah->iniModes, ar5416Modes,
-                              ARRAY_SIZE(ar5416Modes), 6);
-               INIT_INI_ARRAY(&ah->iniCommon, ar5416Common,
-                              ARRAY_SIZE(ar5416Common), 2);
-               INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0,
-                              ARRAY_SIZE(ar5416Bank0), 2);
-               INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain,
-                              ARRAY_SIZE(ar5416BB_RfGain), 3);
-               INIT_INI_ARRAY(&ah->iniBank1, ar5416Bank1,
-                              ARRAY_SIZE(ar5416Bank1), 2);
-               INIT_INI_ARRAY(&ah->iniBank2, ar5416Bank2,
-                              ARRAY_SIZE(ar5416Bank2), 2);
-               INIT_INI_ARRAY(&ah->iniBank3, ar5416Bank3,
-                              ARRAY_SIZE(ar5416Bank3), 3);
-               INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6,
-                              ARRAY_SIZE(ar5416Bank6), 3);
-               INIT_INI_ARRAY(&ah->iniBank6TPC, ar5416Bank6TPC,
-                              ARRAY_SIZE(ar5416Bank6TPC), 3);
-               INIT_INI_ARRAY(&ah->iniBank7, ar5416Bank7,
-                              ARRAY_SIZE(ar5416Bank7), 2);
-               INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac,
-                              ARRAY_SIZE(ar5416Addac), 2);
-       }
-}
-
-static void ath9k_hw_init_mode_gain_regs(struct ath_hw *ah)
-{
-       if (AR_SREV_9287_11_OR_LATER(ah))
-               INIT_INI_ARRAY(&ah->iniModesRxGain,
-               ar9287Modes_rx_gain_9287_1_1,
-               ARRAY_SIZE(ar9287Modes_rx_gain_9287_1_1), 6);
-       else if (AR_SREV_9287_10(ah))
-               INIT_INI_ARRAY(&ah->iniModesRxGain,
-               ar9287Modes_rx_gain_9287_1_0,
-               ARRAY_SIZE(ar9287Modes_rx_gain_9287_1_0), 6);
-       else if (AR_SREV_9280_20(ah))
-               ath9k_hw_init_rxgain_ini(ah);
-
-       if (AR_SREV_9287_11_OR_LATER(ah)) {
-               INIT_INI_ARRAY(&ah->iniModesTxGain,
-               ar9287Modes_tx_gain_9287_1_1,
-               ARRAY_SIZE(ar9287Modes_tx_gain_9287_1_1), 6);
-       } else if (AR_SREV_9287_10(ah)) {
-               INIT_INI_ARRAY(&ah->iniModesTxGain,
-               ar9287Modes_tx_gain_9287_1_0,
-               ARRAY_SIZE(ar9287Modes_tx_gain_9287_1_0), 6);
-       } else if (AR_SREV_9280_20(ah)) {
-               ath9k_hw_init_txgain_ini(ah);
-       } else if (AR_SREV_9285_12_OR_LATER(ah)) {
-               u32 txgain_type = ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE);
-
-               /* txgain table */
-               if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER) {
-                       INIT_INI_ARRAY(&ah->iniModesTxGain,
-                       ar9285Modes_high_power_tx_gain_9285_1_2,
-                       ARRAY_SIZE(ar9285Modes_high_power_tx_gain_9285_1_2), 6);
-               } else {
-                       INIT_INI_ARRAY(&ah->iniModesTxGain,
-                       ar9285Modes_original_tx_gain_9285_1_2,
-                       ARRAY_SIZE(ar9285Modes_original_tx_gain_9285_1_2), 6);
-               }
-
-       }
-}
-
-static void ath9k_hw_init_eeprom_fix(struct ath_hw *ah)
-{
-       u32 i, j;
-
-       if (ah->hw_version.devid == AR9280_DEVID_PCI) {
-
-               /* EEPROM Fixup */
-               for (i = 0; i < ah->iniModes.ia_rows; i++) {
-                       u32 reg = INI_RA(&ah->iniModes, i, 0);
-
-                       for (j = 1; j < ah->iniModes.ia_columns; j++) {
-                               u32 val = INI_RA(&ah->iniModes, i, j);
-
-                               INI_RA(&ah->iniModes, i, j) =
-                                       ath9k_hw_ini_fixup(ah,
-                                                          &ah->eeprom.def,
-                                                          reg, val);
-                       }
-               }
-       }
+       if (AR_SREV_9300_20_OR_LATER(ah))
+               ar9003_hw_attach_ops(ah);
+       else
+               ar9002_hw_attach_ops(ah);
 }
 
-int ath9k_hw_init(struct ath_hw *ah)
+/* Called for all hardware families */
+static int __ath9k_hw_init(struct ath_hw *ah)
 {
        struct ath_common *common = ath9k_hw_common(ah);
        int r = 0;
 
-       if (!ath9k_hw_devid_supported(ah->hw_version.devid)) {
-               ath_print(common, ATH_DBG_FATAL,
-                         "Unsupported device ID: 0x%0x\n",
-                         ah->hw_version.devid);
-               return -EOPNOTSUPP;
-       }
-
-       ath9k_hw_init_defaults(ah);
-       ath9k_hw_init_config(ah);
+       if (ah->hw_version.devid == AR5416_AR9100_DEVID)
+               ah->hw_version.macVersion = AR_SREV_VERSION_9100;
 
        if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) {
                ath_print(common, ATH_DBG_FATAL,
@@ -869,6 +519,11 @@ int ath9k_hw_init(struct ath_hw *ah)
                return -EIO;
        }
 
+       ath9k_hw_init_defaults(ah);
+       ath9k_hw_init_config(ah);
+
+       ath9k_hw_attach_ops(ah);
+
        if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) {
                ath_print(common, ATH_DBG_FATAL, "Couldn't wakeup chip\n");
                return -EIO;
@@ -893,7 +548,7 @@ int ath9k_hw_init(struct ath_hw *ah)
        else
                ah->config.max_txtrig_level = MAX_TX_FIFO_THRESHOLD;
 
-       if (!ath9k_hw_macversion_supported(ah->hw_version.macVersion)) {
+       if (!ath9k_hw_macversion_supported(ah)) {
                ath_print(common, ATH_DBG_FATAL,
                          "Mac Chip Rev 0x%02x.%x is not supported by "
                          "this driver\n", ah->hw_version.macVersion,
@@ -901,28 +556,15 @@ int ath9k_hw_init(struct ath_hw *ah)
                return -EOPNOTSUPP;
        }
 
-       if (AR_SREV_9100(ah)) {
-               ah->iq_caldata.calData = &iq_cal_multi_sample;
-               ah->supp_cals = IQ_MISMATCH_CAL;
-               ah->is_pciexpress = false;
-       }
-
-       if (AR_SREV_9271(ah))
+       if (AR_SREV_9271(ah) || AR_SREV_9100(ah))
                ah->is_pciexpress = false;
 
        ah->hw_version.phyRev = REG_READ(ah, AR_PHY_CHIP_ID);
-
        ath9k_hw_init_cal_settings(ah);
 
        ah->ani_function = ATH9K_ANI_ALL;
-       if (AR_SREV_9280_10_OR_LATER(ah)) {
+       if (AR_SREV_9280_10_OR_LATER(ah) && !AR_SREV_9300_20_OR_LATER(ah))
                ah->ani_function &= ~ATH9K_ANI_NOISE_IMMUNITY_LEVEL;
-               ah->ath9k_hw_rf_set_freq = &ath9k_hw_ar9280_set_channel;
-               ah->ath9k_hw_spur_mitigate_freq = &ath9k_hw_9280_spur_mitigate;
-       } else {
-               ah->ath9k_hw_rf_set_freq = &ath9k_hw_set_channel;
-               ah->ath9k_hw_spur_mitigate_freq = &ath9k_hw_spur_mitigate;
-       }
 
        ath9k_hw_init_mode_regs(ah);
 
@@ -931,15 +573,8 @@ int ath9k_hw_init(struct ath_hw *ah)
        else
                ath9k_hw_disablepcie(ah);
 
-       /* Support for Japan ch.14 (2484) spread */
-       if (AR_SREV_9287_11_OR_LATER(ah)) {
-               INIT_INI_ARRAY(&ah->iniCckfirNormal,
-                      ar9287Common_normal_cck_fir_coeff_92871_1,
-                      ARRAY_SIZE(ar9287Common_normal_cck_fir_coeff_92871_1), 2);
-               INIT_INI_ARRAY(&ah->iniCckfirJapan2484,
-                      ar9287Common_japan_2484_cck_fir_coeff_92871_1,
-                      ARRAY_SIZE(ar9287Common_japan_2484_cck_fir_coeff_92871_1), 2);
-       }
+       if (!AR_SREV_9300_20_OR_LATER(ah))
+               ar9002_hw_cck_chan14_spread(ah);
 
        r = ath9k_hw_post_init(ah);
        if (r)
@@ -950,8 +585,6 @@ int ath9k_hw_init(struct ath_hw *ah)
        if (r)
                return r;
 
-       ath9k_hw_init_eeprom_fix(ah);
-
        r = ath9k_hw_init_macaddr(ah);
        if (r) {
                ath_print(common, ATH_DBG_FATAL,
@@ -964,6 +597,9 @@ int ath9k_hw_init(struct ath_hw *ah)
        else
                ah->tx_trig_level = (AR_FTRIG_512B >> AR_FTRIG_S);
 
+       if (AR_SREV_9300_20_OR_LATER(ah))
+               ar9003_hw_set_nf_limits(ah);
+
        ath9k_init_nfcal_hist_buffer(ah);
 
        common->state = ATH_HW_INITIALIZED;
@@ -971,24 +607,50 @@ int ath9k_hw_init(struct ath_hw *ah)
        return 0;
 }
 
-static void ath9k_hw_init_bb(struct ath_hw *ah,
-                            struct ath9k_channel *chan)
+int ath9k_hw_init(struct ath_hw *ah)
 {
-       u32 synthDelay;
+       int ret;
+       struct ath_common *common = ath9k_hw_common(ah);
 
-       synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;
-       if (IS_CHAN_B(chan))
-               synthDelay = (4 * synthDelay) / 22;
-       else
-               synthDelay /= 10;
+       /* These are all the AR5008/AR9001/AR9002 hardware family of chipsets */
+       switch (ah->hw_version.devid) {
+       case AR5416_DEVID_PCI:
+       case AR5416_DEVID_PCIE:
+       case AR5416_AR9100_DEVID:
+       case AR9160_DEVID_PCI:
+       case AR9280_DEVID_PCI:
+       case AR9280_DEVID_PCIE:
+       case AR9285_DEVID_PCIE:
+       case AR9287_DEVID_PCI:
+       case AR9287_DEVID_PCIE:
+       case AR2427_DEVID_PCIE:
+       case AR9300_DEVID_PCIE:
+               break;
+       default:
+               if (common->bus_ops->ath_bus_type == ATH_USB)
+                       break;
+               ath_print(common, ATH_DBG_FATAL,
+                         "Hardware device ID 0x%04x not supported\n",
+                         ah->hw_version.devid);
+               return -EOPNOTSUPP;
+       }
 
-       REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
+       ret = __ath9k_hw_init(ah);
+       if (ret) {
+               ath_print(common, ATH_DBG_FATAL,
+                         "Unable to initialize hardware; "
+                         "initialization status: %d\n", ret);
+               return ret;
+       }
 
-       udelay(synthDelay + BASE_ACTIVATE_DELAY);
+       return 0;
 }
+EXPORT_SYMBOL(ath9k_hw_init);
 
 static void ath9k_hw_init_qos(struct ath_hw *ah)
 {
+       ENABLE_REGWRITE_BUFFER(ah);
+
        REG_WRITE(ah, AR_MIC_QOS_CONTROL, 0x100aa);
        REG_WRITE(ah, AR_MIC_QOS_SELECT, 0x3210);
 
@@ -1002,105 +664,22 @@ static void ath9k_hw_init_qos(struct ath_hw *ah)
        REG_WRITE(ah, AR_TXOP_4_7, 0xFFFFFFFF);
        REG_WRITE(ah, AR_TXOP_8_11, 0xFFFFFFFF);
        REG_WRITE(ah, AR_TXOP_12_15, 0xFFFFFFFF);
-}
-
-static void ath9k_hw_change_target_baud(struct ath_hw *ah, u32 freq, u32 baud)
-{
-       u32 lcr;
-       u32 baud_divider = freq * 1000 * 1000 / 16 / baud;
 
-       lcr = REG_READ(ah , 0x5100c);
-       lcr |= 0x80;
-
-       REG_WRITE(ah, 0x5100c, lcr);
-       REG_WRITE(ah, 0x51004, (baud_divider >> 8));
-       REG_WRITE(ah, 0x51000, (baud_divider & 0xff));
-
-       lcr &= ~0x80;
-       REG_WRITE(ah, 0x5100c, lcr);
+       REGWRITE_BUFFER_FLUSH(ah);
+       DISABLE_REGWRITE_BUFFER(ah);
 }
 
 static void ath9k_hw_init_pll(struct ath_hw *ah,
                              struct ath9k_channel *chan)
 {
-       u32 pll;
-
-       if (AR_SREV_9100(ah)) {
-               if (chan && IS_CHAN_5GHZ(chan))
-                       pll = 0x1450;
-               else
-                       pll = 0x1458;
-       } else {
-               if (AR_SREV_9280_10_OR_LATER(ah)) {
-                       pll = SM(0x5, AR_RTC_9160_PLL_REFDIV);
-
-                       if (chan && IS_CHAN_HALF_RATE(chan))
-                               pll |= SM(0x1, AR_RTC_9160_PLL_CLKSEL);
-                       else if (chan && IS_CHAN_QUARTER_RATE(chan))
-                               pll |= SM(0x2, AR_RTC_9160_PLL_CLKSEL);
-
-                       if (chan && IS_CHAN_5GHZ(chan)) {
-                               pll |= SM(0x28, AR_RTC_9160_PLL_DIV);
-
+       u32 pll = ath9k_hw_compute_pll_control(ah, chan);
 
-                               if (AR_SREV_9280_20(ah)) {
-                                       if (((chan->channel % 20) == 0)
-                                           || ((chan->channel % 10) == 0))
-                                               pll = 0x2850;
-                                       else
-                                               pll = 0x142c;
-                               }
-                       } else {
-                               pll |= SM(0x2c, AR_RTC_9160_PLL_DIV);
-                       }
-
-               } else if (AR_SREV_9160_10_OR_LATER(ah)) {
-
-                       pll = SM(0x5, AR_RTC_9160_PLL_REFDIV);
-
-                       if (chan && IS_CHAN_HALF_RATE(chan))
-                               pll |= SM(0x1, AR_RTC_9160_PLL_CLKSEL);
-                       else if (chan && IS_CHAN_QUARTER_RATE(chan))
-                               pll |= SM(0x2, AR_RTC_9160_PLL_CLKSEL);
-
-                       if (chan && IS_CHAN_5GHZ(chan))
-                               pll |= SM(0x50, AR_RTC_9160_PLL_DIV);
-                       else
-                               pll |= SM(0x58, AR_RTC_9160_PLL_DIV);
-               } else {
-                       pll = AR_RTC_PLL_REFDIV_5 | AR_RTC_PLL_DIV2;
-
-                       if (chan && IS_CHAN_HALF_RATE(chan))
-                               pll |= SM(0x1, AR_RTC_PLL_CLKSEL);
-                       else if (chan && IS_CHAN_QUARTER_RATE(chan))
-                               pll |= SM(0x2, AR_RTC_PLL_CLKSEL);
-
-                       if (chan && IS_CHAN_5GHZ(chan))
-                               pll |= SM(0xa, AR_RTC_PLL_DIV);
-                       else
-                               pll |= SM(0xb, AR_RTC_PLL_DIV);
-               }
-       }
        REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll);
 
        /* Switch the core clock for ar9271 to 117Mhz */
        if (AR_SREV_9271(ah)) {
-               if ((pll == 0x142c) || (pll == 0x2850) ) {
-                       udelay(500);
-                       /* set CLKOBS to output AHB clock */
-                       REG_WRITE(ah, 0x7020, 0xe);
-                       /*
-                        * 0x304: 117Mhz, ahb_ratio: 1x1
-                        * 0x306: 40Mhz, ahb_ratio: 1x1
-                        */
-                       REG_WRITE(ah, 0x50040, 0x304);
-                       /*
-                        * makes adjustments for the baud dividor to keep the
-                        * targetted baud rate based on the used core clock.
-                        */
-                       ath9k_hw_change_target_baud(ah, AR9271_CORE_CLOCK,
-                                                   AR9271_TARGET_BAUD_RATE);
-               }
+               udelay(500);
+               REG_WRITE(ah, 0x50040, 0x304);
        }
 
        udelay(RTC_PLL_SETTLE_DELAY);
@@ -1108,63 +687,40 @@ static void ath9k_hw_init_pll(struct ath_hw *ah,
        REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_FORCE_DERIVED_CLK);
 }
 
-static void ath9k_hw_init_chain_masks(struct ath_hw *ah)
-{
-       int rx_chainmask, tx_chainmask;
-
-       rx_chainmask = ah->rxchainmask;
-       tx_chainmask = ah->txchainmask;
-
-       switch (rx_chainmask) {
-       case 0x5:
-               REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP,
-                           AR_PHY_SWAP_ALT_CHAIN);
-       case 0x3:
-               if (ah->hw_version.macVersion == AR_SREV_REVISION_5416_10) {
-                       REG_WRITE(ah, AR_PHY_RX_CHAINMASK, 0x7);
-                       REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, 0x7);
-                       break;
-               }
-       case 0x1:
-       case 0x2:
-       case 0x7:
-               REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx_chainmask);
-               REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx_chainmask);
-               break;
-       default:
-               break;
-       }
-
-       REG_WRITE(ah, AR_SELFGEN_MASK, tx_chainmask);
-       if (tx_chainmask == 0x5) {
-               REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP,
-                           AR_PHY_SWAP_ALT_CHAIN);
-       }
-       if (AR_SREV_9100(ah))
-               REG_WRITE(ah, AR_PHY_ANALOG_SWAP,
-                         REG_READ(ah, AR_PHY_ANALOG_SWAP) | 0x00000001);
-}
-
 static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah,
                                          enum nl80211_iftype opmode)
 {
-       ah->mask_reg = AR_IMR_TXERR |
+       u32 imr_reg = AR_IMR_TXERR |
                AR_IMR_TXURN |
                AR_IMR_RXERR |
                AR_IMR_RXORN |
                AR_IMR_BCNMISC;
 
-       if (ah->config.rx_intr_mitigation)
-               ah->mask_reg |= AR_IMR_RXINTM | AR_IMR_RXMINTR;
-       else
-               ah->mask_reg |= AR_IMR_RXOK;
+       if (AR_SREV_9300_20_OR_LATER(ah)) {
+               imr_reg |= AR_IMR_RXOK_HP;
+               if (ah->config.rx_intr_mitigation)
+                       imr_reg |= AR_IMR_RXINTM | AR_IMR_RXMINTR;
+               else
+                       imr_reg |= AR_IMR_RXOK_LP;
+
+       } else {
+               if (ah->config.rx_intr_mitigation)
+                       imr_reg |= AR_IMR_RXINTM | AR_IMR_RXMINTR;
+               else
+                       imr_reg |= AR_IMR_RXOK;
+       }
 
-       ah->mask_reg |= AR_IMR_TXOK;
+       if (ah->config.tx_intr_mitigation)
+               imr_reg |= AR_IMR_TXINTM | AR_IMR_TXMINTR;
+       else
+               imr_reg |= AR_IMR_TXOK;
 
        if (opmode == NL80211_IFTYPE_AP)
-               ah->mask_reg |= AR_IMR_MIB;
+               imr_reg |= AR_IMR_MIB;
 
-       REG_WRITE(ah, AR_IMR, ah->mask_reg);
+       ENABLE_REGWRITE_BUFFER(ah);
+
+       REG_WRITE(ah, AR_IMR, imr_reg);
        ah->imrs2_reg |= AR_IMR_S2_GTT;
        REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg);
 
@@ -1173,6 +729,16 @@ static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah,
                REG_WRITE(ah, AR_INTR_SYNC_ENABLE, AR_INTR_SYNC_DEFAULT);
                REG_WRITE(ah, AR_INTR_SYNC_MASK, 0);
        }
+
+       REGWRITE_BUFFER_FLUSH(ah);
+       DISABLE_REGWRITE_BUFFER(ah);
+
+       if (AR_SREV_9300_20_OR_LATER(ah)) {
+               REG_WRITE(ah, AR_INTR_PRIO_ASYNC_ENABLE, 0);
+               REG_WRITE(ah, AR_INTR_PRIO_ASYNC_MASK, 0);
+               REG_WRITE(ah, AR_INTR_PRIO_SYNC_ENABLE, 0);
+               REG_WRITE(ah, AR_INTR_PRIO_SYNC_MASK, 0);
+       }
 }
 
 static void ath9k_hw_setslottime(struct ath_hw *ah, u32 us)
@@ -1255,19 +821,13 @@ void ath9k_hw_deinit(struct ath_hw *ah)
 {
        struct ath_common *common = ath9k_hw_common(ah);
 
-       if (common->state <= ATH_HW_INITIALIZED)
+       if (common->state < ATH_HW_INITIALIZED)
                goto free_hw;
 
-       if (!AR_SREV_9100(ah))
-               ath9k_hw_ani_disable(ah);
-
        ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP);
 
 free_hw:
-       if (!AR_SREV_9280_10_OR_LATER(ah))
-               ath9k_hw_rf_free_ext_banks(ah);
-       kfree(ah);
-       ah = NULL;
+       ath9k_hw_rf_free_ext_banks(ah);
 }
 EXPORT_SYMBOL(ath9k_hw_deinit);
 
@@ -1275,118 +835,7 @@ EXPORT_SYMBOL(ath9k_hw_deinit);
 /* INI */
 /*******/
 
-static void ath9k_hw_override_ini(struct ath_hw *ah,
-                                 struct ath9k_channel *chan)
-{
-       u32 val;
-
-       /*
-        * Set the RX_ABORT and RX_DIS and clear if off only after
-        * RXE is set for MAC. This prevents frames with corrupted
-        * descriptor status.
-        */
-       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);
-
-               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);
-
-               REG_WRITE(ah, AR_PCU_MISC_MODE2, val);
-       }
-
-       if (!AR_SREV_5416_20_OR_LATER(ah) ||
-           AR_SREV_9280_10_OR_LATER(ah))
-               return;
-       /*
-        * Disable BB clock gating
-        * 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,
-                             struct ar5416_eeprom_def *pEepData,
-                             u32 reg, u32 value)
-{
-       struct base_eep_header *pBase = &(pEepData->baseEepHeader);
-       struct ath_common *common = ath9k_hw_common(ah);
-
-       switch (ah->hw_version.devid) {
-       case AR9280_DEVID_PCI:
-               if (reg == 0x7894) {
-                       ath_print(common, ATH_DBG_EEPROM,
-                               "ini VAL: %x  EEPROM: %x\n", value,
-                               (pBase->version & 0xff));
-
-                       if ((pBase->version & 0xff) > 0x0a) {
-                               ath_print(common, ATH_DBG_EEPROM,
-                                         "PWDCLKIND: %d\n",
-                                         pBase->pwdclkind);
-                               value &= ~AR_AN_TOP2_PWDCLKIND;
-                               value |= AR_AN_TOP2_PWDCLKIND &
-                                       (pBase->pwdclkind << AR_AN_TOP2_PWDCLKIND_S);
-                       } else {
-                               ath_print(common, ATH_DBG_EEPROM,
-                                         "PWDCLKIND Earlier Rev\n");
-                       }
-
-                       ath_print(common, ATH_DBG_EEPROM,
-                                 "final ini VAL: %x\n", value);
-               }
-               break;
-       }
-
-       return value;
-}
-
-static u32 ath9k_hw_ini_fixup(struct ath_hw *ah,
-                             struct ar5416_eeprom_def *pEepData,
-                             u32 reg, u32 value)
-{
-       if (ah->eep_map == EEP_MAP_4KBITS)
-               return value;
-       else
-               return ath9k_hw_def_ini_fixup(ah, pEepData, reg, value);
-}
-
-static void ath9k_olc_init(struct ath_hw *ah)
-{
-       u32 i;
-
-       if (OLC_FOR_AR9287_10_LATER) {
-               REG_SET_BIT(ah, AR_PHY_TX_PWRCTRL9,
-                               AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL);
-               ath9k_hw_analog_shift_rmw(ah, AR9287_AN_TXPC0,
-                               AR9287_AN_TXPC0_TXPCMODE,
-                               AR9287_AN_TXPC0_TXPCMODE_S,
-                               AR9287_AN_TXPC0_TXPCMODE_TEMPSENSE);
-               udelay(100);
-       } else {
-               for (i = 0; i < AR9280_TX_GAIN_TABLE_SIZE; i++)
-                       ah->originalGain[i] =
-                               MS(REG_READ(ah, AR_PHY_TX_GAIN_TBL1 + i * 4),
-                                               AR_PHY_TX_GAIN);
-               ah->PDADCdelta = 0;
-       }
-}
-
-static u32 ath9k_regd_get_ctl(struct ath_regulatory *reg,
-                             struct ath9k_channel *chan)
+u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, struct ath9k_channel *chan)
 {
        u32 ctl = ath_regd_get_band_ctl(reg, chan->chan->band);
 
@@ -1400,190 +849,24 @@ static u32 ath9k_regd_get_ctl(struct ath_regulatory *reg,
        return ctl;
 }
 
-static int ath9k_hw_process_ini(struct ath_hw *ah,
-                               struct ath9k_channel *chan)
-{
-       struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
-       int i, regWrites = 0;
-       struct ieee80211_channel *channel = chan->chan;
-       u32 modesIndex, freqIndex;
-
-       switch (chan->chanmode) {
-       case CHANNEL_A:
-       case CHANNEL_A_HT20:
-               modesIndex = 1;
-               freqIndex = 1;
-               break;
-       case CHANNEL_A_HT40PLUS:
-       case CHANNEL_A_HT40MINUS:
-               modesIndex = 2;
-               freqIndex = 1;
-               break;
-       case CHANNEL_G:
-       case CHANNEL_G_HT20:
-       case CHANNEL_B:
-               modesIndex = 4;
-               freqIndex = 2;
-               break;
-       case CHANNEL_G_HT40PLUS:
-       case CHANNEL_G_HT40MINUS:
-               modesIndex = 3;
-               freqIndex = 2;
-               break;
-
-       default:
-               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);
-
-       if (AR_SREV_5416_22_OR_LATER(ah)) {
-               REG_WRITE_ARRAY(&ah->iniAddac, 1, regWrites);
-       } else {
-               struct ar5416IniArray temp;
-               u32 addacSize =
-                       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;
-               temp.ia_columns = ah->iniAddac.ia_columns;
-               temp.ia_rows = ah->iniAddac.ia_rows;
-               REG_WRITE_ARRAY(&temp, 1, regWrites);
-       }
-
-       REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC);
-
-       for (i = 0; i < ah->iniModes.ia_rows; i++) {
-               u32 reg = INI_RA(&ah->iniModes, i, 0);
-               u32 val = INI_RA(&ah->iniModes, i, modesIndex);
-
-               REG_WRITE(ah, reg, val);
-
-               if (reg >= 0x7800 && reg < 0x78a0
-                   && ah->config.analog_shiftreg) {
-                       udelay(100);
-               }
-
-               DO_DELAY(regWrites);
-       }
-
-       if (AR_SREV_9280(ah) || AR_SREV_9287_10_OR_LATER(ah))
-               REG_WRITE_ARRAY(&ah->iniModesRxGain, modesIndex, regWrites);
-
-       if (AR_SREV_9280(ah) || AR_SREV_9285_12_OR_LATER(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);
-
-               REG_WRITE(ah, reg, val);
-
-               if (reg >= 0x7800 && reg < 0x78a0
-                   && ah->config.analog_shiftreg) {
-                       udelay(100);
-               }
-
-               DO_DELAY(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);
-       }
-
-       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,
-                               regWrites);
-       }
-
-       ath9k_hw_override_ini(ah, chan);
-       ath9k_hw_set_regs(ah, chan);
-       ath9k_hw_init_chain_masks(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,
-                                channel->max_power * 2,
-                                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");
-               return -EIO;
-       }
-
-       return 0;
-}
-
 /****************************************/
 /* Reset and Channel Switching Routines */
 /****************************************/
 
-static void ath9k_hw_set_rfmode(struct ath_hw *ah, struct ath9k_channel *chan)
-{
-       u32 rfMode = 0;
-
-       if (chan == NULL)
-               return;
-
-       rfMode |= (IS_CHAN_B(chan) || IS_CHAN_G(chan))
-               ? AR_PHY_MODE_DYNAMIC : AR_PHY_MODE_OFDM;
-
-       if (!AR_SREV_9280_10_OR_LATER(ah))
-               rfMode |= (IS_CHAN_5GHZ(chan)) ?
-                       AR_PHY_MODE_RF5GHZ : AR_PHY_MODE_RF2GHZ;
-
-       if (AR_SREV_9280_20(ah) && IS_CHAN_A_5MHZ_SPACED(chan))
-               rfMode |= (AR_PHY_MODE_DYNAMIC | AR_PHY_MODE_DYN_CCK_DISABLE);
-
-       REG_WRITE(ah, AR_PHY_MODE, rfMode);
-}
-
-static void ath9k_hw_mark_phy_inactive(struct ath_hw *ah)
-{
-       REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS);
-}
-
 static inline void ath9k_hw_set_dma(struct ath_hw *ah)
 {
+       struct ath_common *common = ath9k_hw_common(ah);
        u32 regval;
 
+       ENABLE_REGWRITE_BUFFER(ah);
+
        /*
         * set AHB_MODE not to do cacheline prefetches
        */
-       regval = REG_READ(ah, AR_AHB_MODE);
-       REG_WRITE(ah, AR_AHB_MODE, regval | AR_AHB_PREFETCH_RD_EN);
+       if (!AR_SREV_9300_20_OR_LATER(ah)) {
+               regval = REG_READ(ah, AR_AHB_MODE);
+               REG_WRITE(ah, AR_AHB_MODE, regval | AR_AHB_PREFETCH_RD_EN);
+       }
 
        /*
         * let mac dma reads be in 128 byte chunks
@@ -1591,12 +874,18 @@ static inline void ath9k_hw_set_dma(struct ath_hw *ah)
        regval = REG_READ(ah, AR_TXCFG) & ~AR_TXCFG_DMASZ_MASK;
        REG_WRITE(ah, AR_TXCFG, regval | AR_TXCFG_DMASZ_128B);
 
+       REGWRITE_BUFFER_FLUSH(ah);
+       DISABLE_REGWRITE_BUFFER(ah);
+
        /*
         * Restore TX Trigger Level to its pre-reset value.
         * The initial value depends on whether aggregation is enabled, and is
         * adjusted whenever underruns are detected.
         */
-       REG_RMW_FIELD(ah, AR_TXCFG, AR_FTRIG, ah->tx_trig_level);
+       if (!AR_SREV_9300_20_OR_LATER(ah))
+               REG_RMW_FIELD(ah, AR_TXCFG, AR_FTRIG, ah->tx_trig_level);
+
+       ENABLE_REGWRITE_BUFFER(ah);
 
        /*
         * let mac dma writes be in 128 byte chunks
@@ -1609,6 +898,14 @@ static inline void ath9k_hw_set_dma(struct ath_hw *ah)
         */
        REG_WRITE(ah, AR_RXFIFO_CFG, 0x200);
 
+       if (AR_SREV_9300_20_OR_LATER(ah)) {
+               REG_RMW_FIELD(ah, AR_RXBP_THRESH, AR_RXBP_THRESH_HP, 0x1);
+               REG_RMW_FIELD(ah, AR_RXBP_THRESH, AR_RXBP_THRESH_LP, 0x1);
+
+               ath9k_hw_set_rx_bufsize(ah, common->rx_bufsize -
+                       ah->caps.rx_status_len);
+       }
+
        /*
         * reduce the number of usable entries in PCU TXBUF to avoid
         * wrap around issues.
@@ -1624,6 +921,12 @@ static inline void ath9k_hw_set_dma(struct ath_hw *ah)
                REG_WRITE(ah, AR_PCU_TXBUF_CTRL,
                          AR_PCU_TXBUF_CTRL_USABLE_SIZE);
        }
+
+       REGWRITE_BUFFER_FLUSH(ah);
+       DISABLE_REGWRITE_BUFFER(ah);
+
+       if (AR_SREV_9300_20_OR_LATER(ah))
+               ath9k_hw_reset_txstatus_ring(ah);
 }
 
 static void ath9k_hw_set_operating_mode(struct ath_hw *ah, int opmode)
@@ -1651,10 +954,8 @@ static void ath9k_hw_set_operating_mode(struct ath_hw *ah, int opmode)
        }
 }
 
-static inline void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah,
-                                                u32 coef_scaled,
-                                                u32 *coef_mantissa,
-                                                u32 *coef_exponent)
+void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, u32 coef_scaled,
+                                  u32 *coef_mantissa, u32 *coef_exponent)
 {
        u32 coef_exp, coef_man;
 
@@ -1670,40 +971,6 @@ static inline void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah,
        *coef_exponent = coef_exp - 16;
 }
 
-static void ath9k_hw_set_delta_slope(struct ath_hw *ah,
-                                    struct ath9k_channel *chan)
-{
-       u32 coef_scaled, ds_coef_exp, ds_coef_man;
-       u32 clockMhzScaled = 0x64000000;
-       struct chan_centers centers;
-
-       if (IS_CHAN_HALF_RATE(chan))
-               clockMhzScaled = clockMhzScaled >> 1;
-       else if (IS_CHAN_QUARTER_RATE(chan))
-               clockMhzScaled = clockMhzScaled >> 2;
-
-       ath9k_hw_get_channel_centers(ah, chan, &centers);
-       coef_scaled = clockMhzScaled / centers.synth_center;
-
-       ath9k_hw_get_delta_slope_vals(ah, coef_scaled, &ds_coef_man,
-                                     &ds_coef_exp);
-
-       REG_RMW_FIELD(ah, AR_PHY_TIMING3,
-                     AR_PHY_TIMING3_DSC_MAN, ds_coef_man);
-       REG_RMW_FIELD(ah, AR_PHY_TIMING3,
-                     AR_PHY_TIMING3_DSC_EXP, ds_coef_exp);
-
-       coef_scaled = (9 * coef_scaled) / 10;
-
-       ath9k_hw_get_delta_slope_vals(ah, coef_scaled, &ds_coef_man,
-                                     &ds_coef_exp);
-
-       REG_RMW_FIELD(ah, AR_PHY_HALFGI,
-                     AR_PHY_HALFGI_DSC_MAN, ds_coef_man);
-       REG_RMW_FIELD(ah, AR_PHY_HALFGI,
-                     AR_PHY_HALFGI_DSC_EXP, ds_coef_exp);
-}
-
 static bool ath9k_hw_set_reset(struct ath_hw *ah, int type)
 {
        u32 rst_flags;
@@ -1717,6 +984,8 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type)
                (void)REG_READ(ah, AR_RTC_DERIVED_CLK);
        }
 
+       ENABLE_REGWRITE_BUFFER(ah);
+
        REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN |
                  AR_RTC_FORCE_WAKE_ON_INT);
 
@@ -1728,11 +997,16 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type)
                if (tmpReg &
                    (AR_INTR_SYNC_LOCAL_TIMEOUT |
                     AR_INTR_SYNC_RADM_CPL_TIMEOUT)) {
+                       u32 val;
                        REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0);
-                       REG_WRITE(ah, AR_RC, AR_RC_AHB | AR_RC_HOSTIF);
-               } else {
+
+                       val = AR_RC_HOSTIF;
+                       if (!AR_SREV_9300_20_OR_LATER(ah))
+                               val |= AR_RC_AHB;
+                       REG_WRITE(ah, AR_RC, val);
+
+               } else if (!AR_SREV_9300_20_OR_LATER(ah))
                        REG_WRITE(ah, AR_RC, AR_RC_AHB);
-               }
 
                rst_flags = AR_RTC_RC_MAC_WARM;
                if (type == ATH9K_RESET_COLD)
@@ -1740,6 +1014,10 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type)
        }
 
        REG_WRITE(ah, AR_RTC_RC, rst_flags);
+
+       REGWRITE_BUFFER_FLUSH(ah);
+       DISABLE_REGWRITE_BUFFER(ah);
+
        udelay(50);
 
        REG_WRITE(ah, AR_RTC_RC, 0);
@@ -1760,16 +1038,23 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type)
 
 static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah)
 {
+       ENABLE_REGWRITE_BUFFER(ah);
+
        REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN |
                  AR_RTC_FORCE_WAKE_ON_INT);
 
-       if (!AR_SREV_9100(ah))
+       if (!AR_SREV_9100(ah) && !AR_SREV_9300_20_OR_LATER(ah))
                REG_WRITE(ah, AR_RC, AR_RC_AHB);
 
        REG_WRITE(ah, AR_RTC_RESET, 0);
-       udelay(2);
 
-       if (!AR_SREV_9100(ah))
+       REGWRITE_BUFFER_FLUSH(ah);
+       DISABLE_REGWRITE_BUFFER(ah);
+
+       if (!AR_SREV_9300_20_OR_LATER(ah))
+               udelay(2);
+
+       if (!AR_SREV_9100(ah) && !AR_SREV_9300_20_OR_LATER(ah))
                REG_WRITE(ah, AR_RC, 0);
 
        REG_WRITE(ah, AR_RTC_RESET, 1);
@@ -1805,34 +1090,6 @@ static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type)
        }
 }
 
-static void ath9k_hw_set_regs(struct ath_hw *ah, struct ath9k_channel *chan)
-{
-       u32 phymode;
-       u32 enableDacFifo = 0;
-
-       if (AR_SREV_9285_10_OR_LATER(ah))
-               enableDacFifo = (REG_READ(ah, AR_PHY_TURBO) &
-                                        AR_PHY_FC_ENABLE_DAC_FIFO);
-
-       phymode = AR_PHY_FC_HT_EN | AR_PHY_FC_SHORT_GI_40
-               | AR_PHY_FC_SINGLE_HT_LTF1 | AR_PHY_FC_WALSH | enableDacFifo;
-
-       if (IS_CHAN_HT40(chan)) {
-               phymode |= AR_PHY_FC_DYN2040_EN;
-
-               if ((chan->chanmode == CHANNEL_A_HT40PLUS) ||
-                   (chan->chanmode == CHANNEL_G_HT40PLUS))
-                       phymode |= AR_PHY_FC_DYN2040_PRI_CH;
-
-       }
-       REG_WRITE(ah, AR_PHY_TURBO, phymode);
-
-       ath9k_hw_set11nmac2040(ah);
-
-       REG_WRITE(ah, AR_GTXTO, 25 << AR_GTXTO_TIMEOUT_LIMIT_S);
-       REG_WRITE(ah, AR_CST, 0xF << AR_CST_TIMEOUT_LIMIT_S);
-}
-
 static bool ath9k_hw_chip_reset(struct ath_hw *ah,
                                struct ath9k_channel *chan)
 {
@@ -1858,7 +1115,7 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah,
        struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
        struct ath_common *common = ath9k_hw_common(ah);
        struct ieee80211_channel *channel = chan->chan;
-       u32 synthDelay, qnum;
+       u32 qnum;
        int r;
 
        for (qnum = 0; qnum < AR_NUM_QCU; qnum++) {
@@ -1870,17 +1127,15 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah,
                }
        }
 
-       REG_WRITE(ah, AR_PHY_RFBUS_REQ, AR_PHY_RFBUS_REQ_EN);
-       if (!ath9k_hw_wait(ah, AR_PHY_RFBUS_GRANT, AR_PHY_RFBUS_GRANT_EN,
-                          AR_PHY_RFBUS_GRANT_EN, AH_WAIT_TIMEOUT)) {
+       if (!ath9k_hw_rfbus_req(ah)) {
                ath_print(common, ATH_DBG_FATAL,
                          "Could not kill baseband RX\n");
                return false;
        }
 
-       ath9k_hw_set_regs(ah, chan);
+       ath9k_hw_set_channel_regs(ah, chan);
 
-       r = ah->ath9k_hw_rf_set_freq(ah, chan);
+       r = ath9k_hw_rf_set_freq(ah, chan);
        if (r) {
                ath_print(common, ATH_DBG_FATAL,
                          "Failed to set channel\n");
@@ -1894,20 +1149,12 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah,
                             min((u32) MAX_RATE_POWER,
                             (u32) regulatory->power_limit));
 
-       synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;
-       if (IS_CHAN_B(chan))
-               synthDelay = (4 * synthDelay) / 22;
-       else
-               synthDelay /= 10;
-
-       udelay(synthDelay + BASE_ACTIVATE_DELAY);
-
-       REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0);
+       ath9k_hw_rfbus_done(ah);
 
        if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan))
                ath9k_hw_set_delta_slope(ah, chan);
 
-       ah->ath9k_hw_spur_mitigate_freq(ah, chan);
+       ath9k_hw_spur_mitigate_freq(ah, chan);
 
        if (!chan->oneTimeCalsDone)
                chan->oneTimeCalsDone = true;
@@ -1915,17 +1162,33 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah,
        return true;
 }
 
-static void ath9k_enable_rfkill(struct ath_hw *ah)
+bool ath9k_hw_check_alive(struct ath_hw *ah)
 {
-       REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL,
-                   AR_GPIO_INPUT_EN_VAL_RFSILENT_BB);
+       int count = 50;
+       u32 reg;
+
+       if (AR_SREV_9285_10_OR_LATER(ah))
+               return true;
+
+       do {
+               reg = REG_READ(ah, AR_OBS_BUS_1);
+
+               if ((reg & 0x7E7FFFEF) == 0x00702400)
+                       continue;
 
-       REG_CLR_BIT(ah, AR_GPIO_INPUT_MUX2,
-                   AR_GPIO_INPUT_MUX2_RFSILENT);
+               switch (reg & 0x7E000B00) {
+               case 0x1E000000:
+               case 0x52000B00:
+               case 0x18000B00:
+                       continue;
+               default:
+                       return true;
+               }
+       } while (count-- > 0);
 
-       ath9k_hw_cfg_gpio_input(ah, ah->rfkill_gpio);
-       REG_SET_BIT(ah, AR_PHY_TEST, RFSILENT_BB);
+       return false;
 }
+EXPORT_SYMBOL(ath9k_hw_check_alive);
 
 int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
                    bool bChannelChange)
@@ -1936,11 +1199,18 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
        u32 saveDefAntenna;
        u32 macStaId1;
        u64 tsf = 0;
-       int i, rx_chainmask, r;
+       int i, r;
 
        ah->txchainmask = common->tx_chainmask;
        ah->rxchainmask = common->rx_chainmask;
 
+       if (!ah->chip_fullsleep) {
+               ath9k_hw_abortpcurecv(ah);
+               if (!ath9k_hw_stopdmarecv(ah))
+                       ath_print(common, ATH_DBG_XMIT,
+                               "Failed to stop receive dma\n");
+       }
+
        if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
                return -EIO;
 
@@ -1979,6 +1249,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
 
        ath9k_hw_mark_phy_inactive(ah);
 
+       /* Only required on the first reset */
        if (AR_SREV_9271(ah) && ah->htc_reset_init) {
                REG_WRITE(ah,
                          AR9271_RESET_POWER_DOWN_CONTROL,
@@ -1991,6 +1262,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
                return -EINVAL;
        }
 
+       /* Only required on the first reset */
        if (AR_SREV_9271(ah) && ah->htc_reset_init) {
                ah->htc_reset_init = false;
                REG_WRITE(ah,
@@ -2006,16 +1278,6 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
        if (AR_SREV_9280_10_OR_LATER(ah))
                REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE);
 
-       if (AR_SREV_9287_12_OR_LATER(ah)) {
-               /* Enable ASYNC FIFO */
-               REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3,
-                               AR_MAC_PCU_ASYNC_FIFO_REG3_DATAPATH_SEL);
-               REG_SET_BIT(ah, AR_PHY_MODE, AR_PHY_MODE_ASYNCFIFO);
-               REG_CLR_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3,
-                               AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET);
-               REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3,
-                               AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET);
-       }
        r = ath9k_hw_process_ini(ah, chan);
        if (r)
                return r;
@@ -2040,9 +1302,13 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
        if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan))
                ath9k_hw_set_delta_slope(ah, chan);
 
-       ah->ath9k_hw_spur_mitigate_freq(ah, chan);
+       ath9k_hw_spur_mitigate_freq(ah, chan);
        ah->eep_ops->set_board_values(ah, chan);
 
+       ath9k_hw_set_operating_mode(ah, ah->opmode);
+
+       ENABLE_REGWRITE_BUFFER(ah);
+
        REG_WRITE(ah, AR_STA_ID0, get_unaligned_le32(common->macaddr));
        REG_WRITE(ah, AR_STA_ID1, get_unaligned_le16(common->macaddr + 4)
                  | macStaId1
@@ -2050,25 +1316,27 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
                  | (ah->config.
                     ack_6mb ? AR_STA_ID1_ACKCTS_6MB : 0)
                  | ah->sta_id1_defaults);
-       ath9k_hw_set_operating_mode(ah, ah->opmode);
-
        ath_hw_setbssidmask(common);
-
        REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna);
-
        ath9k_hw_write_associd(ah);
-
        REG_WRITE(ah, AR_ISR, ~0);
-
        REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR);
 
-       r = ah->ath9k_hw_rf_set_freq(ah, chan);
+       REGWRITE_BUFFER_FLUSH(ah);
+       DISABLE_REGWRITE_BUFFER(ah);
+
+       r = ath9k_hw_rf_set_freq(ah, chan);
        if (r)
                return r;
 
+       ENABLE_REGWRITE_BUFFER(ah);
+
        for (i = 0; i < AR_NUM_DCU; i++)
                REG_WRITE(ah, AR_DQCUMASK(i), 1 << i);
 
+       REGWRITE_BUFFER_FLUSH(ah);
+       DISABLE_REGWRITE_BUFFER(ah);
+
        ah->intr_txqs = 0;
        for (i = 0; i < ah->caps.total_queues; i++)
                ath9k_hw_resettxqueue(ah, i);
@@ -2081,25 +1349,9 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
 
        ath9k_hw_init_global_settings(ah);
 
-       if (AR_SREV_9287_12_OR_LATER(ah)) {
-               REG_WRITE(ah, AR_D_GBL_IFS_SIFS,
-                         AR_D_GBL_IFS_SIFS_ASYNC_FIFO_DUR);
-               REG_WRITE(ah, AR_D_GBL_IFS_SLOT,
-                         AR_D_GBL_IFS_SLOT_ASYNC_FIFO_DUR);
-               REG_WRITE(ah, AR_D_GBL_IFS_EIFS,
-                         AR_D_GBL_IFS_EIFS_ASYNC_FIFO_DUR);
-
-               REG_WRITE(ah, AR_TIME_OUT, AR_TIME_OUT_ACK_CTS_ASYNC_FIFO_DUR);
-               REG_WRITE(ah, AR_USEC, AR_USEC_ASYNC_FIFO_DUR);
-
-               REG_SET_BIT(ah, AR_MAC_PCU_LOGIC_ANALYZER,
-                           AR_MAC_PCU_LOGIC_ANALYZER_DISBUG20768);
-               REG_RMW_FIELD(ah, AR_AHB_MODE, AR_AHB_CUSTOM_BURST_EN,
-                             AR_AHB_CUSTOM_BURST_ASYNC_FIFO_VAL);
-       }
-       if (AR_SREV_9287_12_OR_LATER(ah)) {
-               REG_SET_BIT(ah, AR_PCU_MISC_MODE2,
-                               AR_PCU_MISC_MODE2_ENABLE_AGGWEP);
+       if (!AR_SREV_9300_20_OR_LATER(ah)) {
+               ar9002_hw_enable_async_fifo(ah);
+               ar9002_hw_enable_wep_aggregation(ah);
        }
 
        REG_WRITE(ah, AR_STA_ID1,
@@ -2114,19 +1366,24 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
                REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_FIRST, 2000);
        }
 
+       if (ah->config.tx_intr_mitigation) {
+               REG_RMW_FIELD(ah, AR_TIMT, AR_TIMT_LAST, 300);
+               REG_RMW_FIELD(ah, AR_TIMT, AR_TIMT_FIRST, 750);
+       }
+
        ath9k_hw_init_bb(ah, chan);
 
        if (!ath9k_hw_init_cal(ah, chan))
                return -EIO;
 
-       rx_chainmask = ah->rxchainmask;
-       if ((rx_chainmask == 0x5) || (rx_chainmask == 0x3)) {
-               REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx_chainmask);
-               REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx_chainmask);
-       }
+       ENABLE_REGWRITE_BUFFER(ah);
 
+       ath9k_hw_restore_chainmask(ah);
        REG_WRITE(ah, AR_CFG_LED, saveLedState | AR_CFG_SCLK_32KHZ);
 
+       REGWRITE_BUFFER_FLUSH(ah);
+       DISABLE_REGWRITE_BUFFER(ah);
+
        /*
         * For big endian systems turn on swapping for descriptors
         */
@@ -2156,6 +1413,11 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
        if (ah->btcoex_hw.enabled)
                ath9k_hw_btcoex_enable(ah);
 
+       if (AR_SREV_9300_20_OR_LATER(ah)) {
+               ath9k_hw_loadnf(ah, curchan);
+               ath9k_hw_start_nfcal(ah);
+       }
+
        return 0;
 }
 EXPORT_SYMBOL(ath9k_hw_reset);
@@ -2442,21 +1704,35 @@ EXPORT_SYMBOL(ath9k_hw_keyisvalid);
 /* Power Management (Chipset) */
 /******************************/
 
+/*
+ * Notify Power Mgt is disabled in self-generated frames.
+ * If requested, force chip to sleep.
+ */
 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) {
+               /*
+                * 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_9100(ah))
+               if (!AR_SREV_9100(ah) && !AR_SREV_9300_20_OR_LATER(ah))
                        REG_WRITE(ah, AR_RC, AR_RC_AHB | AR_RC_HOSTIF);
 
-               if(!AR_SREV_5416(ah))
+               /* Shutdown chip. Active low */
+               if (!AR_SREV_5416(ah) && !AR_SREV_9271(ah))
                        REG_CLR_BIT(ah, (AR_RTC_RESET),
                                    AR_RTC_RESET_EN);
        }
 }
 
+/*
+ * Notify Power Management is enabled in self-generating
+ * frames. If request, set power mode of chip to
+ * auto/normal.  Duration in units of 128us (1/8 TU).
+ */
 static void ath9k_set_power_network_sleep(struct ath_hw *ah, int setChip)
 {
        REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
@@ -2464,9 +1740,14 @@ static void ath9k_set_power_network_sleep(struct ath_hw *ah, int setChip)
                struct ath9k_hw_capabilities *pCap = &ah->caps;
 
                if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
+                       /* Set WakeOnInterrupt bit; clear ForceWake bit */
                        REG_WRITE(ah, AR_RTC_FORCE_WAKE,
                                  AR_RTC_FORCE_WAKE_ON_INT);
                } else {
+                       /*
+                        * 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);
                }
@@ -2485,7 +1766,8 @@ static bool ath9k_hw_set_power_awake(struct ath_hw *ah, int setChip)
                                           ATH9K_RESET_POWER_ON) != true) {
                                return false;
                        }
-                       ath9k_hw_init_pll(ah, NULL);
+                       if (!AR_SREV_9300_20_OR_LATER(ah))
+                               ath9k_hw_init_pll(ah, NULL);
                }
                if (AR_SREV_9100(ah))
                        REG_SET_BIT(ah, AR_RTC_RESET,
@@ -2555,421 +1837,6 @@ bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode)
 }
 EXPORT_SYMBOL(ath9k_hw_setpower);
 
-/*
- * Helper for ASPM support.
- *
- * Disable PLL when in L0s as well as receiver clock when in L1.
- * This power saving option must be enabled through the SerDes.
- *
- * Programming the SerDes must go through the same 288 bit serial shift
- * register as the other analog registers.  Hence the 9 writes.
- */
-void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore, int power_off)
-{
-       u8 i;
-       u32 val;
-
-       if (ah->is_pciexpress != true)
-               return;
-
-       /* Do not touch SerDes registers */
-       if (ah->config.pcie_powersave_enable == 2)
-               return;
-
-       /* Nothing to do on restore for 11N */
-       if (!restore) {
-               if (AR_SREV_9280_20_OR_LATER(ah)) {
-                       /*
-                        * AR9280 2.0 or later chips use SerDes values from the
-                        * initvals.h initialized depending on chipset during
-                        * ath9k_hw_init()
-                        */
-                       for (i = 0; i < ah->iniPcieSerdes.ia_rows; i++) {
-                               REG_WRITE(ah, INI_RA(&ah->iniPcieSerdes, i, 0),
-                                         INI_RA(&ah->iniPcieSerdes, i, 1));
-                       }
-               } else if (AR_SREV_9280(ah) &&
-                          (ah->hw_version.macRev == AR_SREV_REVISION_9280_10)) {
-                       REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fd00);
-                       REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
-
-                       /* RX shut off when elecidle is asserted */
-                       REG_WRITE(ah, AR_PCIE_SERDES, 0xa8000019);
-                       REG_WRITE(ah, AR_PCIE_SERDES, 0x13160820);
-                       REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980560);
-
-                       /* Shut off CLKREQ active in L1 */
-                       if (ah->config.pcie_clock_req)
-                               REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffc);
-                       else
-                               REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffd);
-
-                       REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);
-                       REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);
-                       REG_WRITE(ah, AR_PCIE_SERDES, 0x00043007);
-
-                       /* Load the new settings */
-                       REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
-
-               } else {
-                       REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00);
-                       REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
-
-                       /* RX shut off when elecidle is asserted */
-                       REG_WRITE(ah, AR_PCIE_SERDES, 0x28000039);
-                       REG_WRITE(ah, AR_PCIE_SERDES, 0x53160824);
-                       REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980579);
-
-                       /*
-                        * Ignore ah->ah_config.pcie_clock_req setting for
-                        * pre-AR9280 11n
-                        */
-                       REG_WRITE(ah, AR_PCIE_SERDES, 0x001defff);
-
-                       REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);
-                       REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);
-                       REG_WRITE(ah, AR_PCIE_SERDES, 0x000e3007);
-
-                       /* Load the new settings */
-                       REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
-               }
-
-               udelay(1000);
-
-               /* set bit 19 to allow forcing of pcie core into L1 state */
-               REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
-
-               /* Several PCIe massages to ensure proper behaviour */
-               if (ah->config.pcie_waen) {
-                       val = ah->config.pcie_waen;
-                       if (!power_off)
-                               val &= (~AR_WA_D3_L1_DISABLE);
-               } else {
-                       if (AR_SREV_9285(ah) || AR_SREV_9271(ah) ||
-                           AR_SREV_9287(ah)) {
-                               val = AR9285_WA_DEFAULT;
-                               if (!power_off)
-                                       val &= (~AR_WA_D3_L1_DISABLE);
-                       } else if (AR_SREV_9280(ah)) {
-                               /*
-                                * On AR9280 chips bit 22 of 0x4004 needs to be
-                                * set otherwise card may disappear.
-                                */
-                               val = AR9280_WA_DEFAULT;
-                               if (!power_off)
-                                       val &= (~AR_WA_D3_L1_DISABLE);
-                       } else
-                               val = AR_WA_DEFAULT;
-               }
-
-               REG_WRITE(ah, AR_WA, val);
-       }
-
-       if (power_off) {
-               /*
-                * Set PCIe workaround bits
-                * bit 14 in WA register (disable L1) should only
-                * be set when device enters D3 and be cleared
-                * when device comes back to D0.
-                */
-               if (ah->config.pcie_waen) {
-                       if (ah->config.pcie_waen & AR_WA_D3_L1_DISABLE)
-                               REG_SET_BIT(ah, AR_WA, AR_WA_D3_L1_DISABLE);
-               } else {
-                       if (((AR_SREV_9285(ah) || AR_SREV_9271(ah) ||
-                             AR_SREV_9287(ah)) &&
-                            (AR9285_WA_DEFAULT & AR_WA_D3_L1_DISABLE)) ||
-                           (AR_SREV_9280(ah) &&
-                            (AR9280_WA_DEFAULT & AR_WA_D3_L1_DISABLE))) {
-                               REG_SET_BIT(ah, AR_WA, AR_WA_D3_L1_DISABLE);
-                       }
-               }
-       }
-}
-EXPORT_SYMBOL(ath9k_hw_configpcipowersave);
-
-/**********************/
-/* Interrupt Handling */
-/**********************/
-
-bool ath9k_hw_intrpend(struct ath_hw *ah)
-{
-       u32 host_isr;
-
-       if (AR_SREV_9100(ah))
-               return true;
-
-       host_isr = REG_READ(ah, AR_INTR_ASYNC_CAUSE);
-       if ((host_isr & AR_INTR_MAC_IRQ) && (host_isr != AR_INTR_SPURIOUS))
-               return true;
-
-       host_isr = REG_READ(ah, AR_INTR_SYNC_CAUSE);
-       if ((host_isr & AR_INTR_SYNC_DEFAULT)
-           && (host_isr != AR_INTR_SPURIOUS))
-               return true;
-
-       return false;
-}
-EXPORT_SYMBOL(ath9k_hw_intrpend);
-
-bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked)
-{
-       u32 isr = 0;
-       u32 mask2 = 0;
-       struct ath9k_hw_capabilities *pCap = &ah->caps;
-       u32 sync_cause = 0;
-       bool fatal_int = false;
-       struct ath_common *common = ath9k_hw_common(ah);
-
-       if (!AR_SREV_9100(ah)) {
-               if (REG_READ(ah, AR_INTR_ASYNC_CAUSE) & AR_INTR_MAC_IRQ) {
-                       if ((REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M)
-                           == AR_RTC_STATUS_ON) {
-                               isr = REG_READ(ah, AR_ISR);
-                       }
-               }
-
-               sync_cause = REG_READ(ah, AR_INTR_SYNC_CAUSE) &
-                       AR_INTR_SYNC_DEFAULT;
-
-               *masked = 0;
-
-               if (!isr && !sync_cause)
-                       return false;
-       } else {
-               *masked = 0;
-               isr = REG_READ(ah, AR_ISR);
-       }
-
-       if (isr) {
-               if (isr & AR_ISR_BCNMISC) {
-                       u32 isr2;
-                       isr2 = REG_READ(ah, AR_ISR_S2);
-                       if (isr2 & AR_ISR_S2_TIM)
-                               mask2 |= ATH9K_INT_TIM;
-                       if (isr2 & AR_ISR_S2_DTIM)
-                               mask2 |= ATH9K_INT_DTIM;
-                       if (isr2 & AR_ISR_S2_DTIMSYNC)
-                               mask2 |= ATH9K_INT_DTIMSYNC;
-                       if (isr2 & (AR_ISR_S2_CABEND))
-                               mask2 |= ATH9K_INT_CABEND;
-                       if (isr2 & AR_ISR_S2_GTT)
-                               mask2 |= ATH9K_INT_GTT;
-                       if (isr2 & AR_ISR_S2_CST)
-                               mask2 |= ATH9K_INT_CST;
-                       if (isr2 & AR_ISR_S2_TSFOOR)
-                               mask2 |= ATH9K_INT_TSFOOR;
-               }
-
-               isr = REG_READ(ah, AR_ISR_RAC);
-               if (isr == 0xffffffff) {
-                       *masked = 0;
-                       return false;
-               }
-
-               *masked = isr & ATH9K_INT_COMMON;
-
-               if (ah->config.rx_intr_mitigation) {
-                       if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM))
-                               *masked |= ATH9K_INT_RX;
-               }
-
-               if (isr & (AR_ISR_RXOK | AR_ISR_RXERR))
-                       *masked |= ATH9K_INT_RX;
-               if (isr &
-                   (AR_ISR_TXOK | AR_ISR_TXDESC | AR_ISR_TXERR |
-                    AR_ISR_TXEOL)) {
-                       u32 s0_s, s1_s;
-
-                       *masked |= ATH9K_INT_TX;
-
-                       s0_s = REG_READ(ah, AR_ISR_S0_S);
-                       ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXOK);
-                       ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXDESC);
-
-                       s1_s = REG_READ(ah, AR_ISR_S1_S);
-                       ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXERR);
-                       ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXEOL);
-               }
-
-               if (isr & AR_ISR_RXORN) {
-                       ath_print(common, ATH_DBG_INTERRUPT,
-                                 "receive FIFO overrun interrupt\n");
-               }
-
-               if (!AR_SREV_9100(ah)) {
-                       if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
-                               u32 isr5 = REG_READ(ah, AR_ISR_S5_S);
-                               if (isr5 & AR_ISR_S5_TIM_TIMER)
-                                       *masked |= ATH9K_INT_TIM_TIMER;
-                       }
-               }
-
-               *masked |= mask2;
-       }
-
-       if (AR_SREV_9100(ah))
-               return true;
-
-       if (isr & AR_ISR_GENTMR) {
-               u32 s5_s;
-
-               s5_s = REG_READ(ah, AR_ISR_S5_S);
-               if (isr & AR_ISR_GENTMR) {
-                       ah->intr_gen_timer_trigger =
-                               MS(s5_s, AR_ISR_S5_GENTIMER_TRIG);
-
-                       ah->intr_gen_timer_thresh =
-                               MS(s5_s, AR_ISR_S5_GENTIMER_THRESH);
-
-                       if (ah->intr_gen_timer_trigger)
-                               *masked |= ATH9K_INT_GENTIMER;
-
-               }
-       }
-
-       if (sync_cause) {
-               fatal_int =
-                       (sync_cause &
-                        (AR_INTR_SYNC_HOST1_FATAL | AR_INTR_SYNC_HOST1_PERR))
-                       ? true : false;
-
-               if (fatal_int) {
-                       if (sync_cause & AR_INTR_SYNC_HOST1_FATAL) {
-                               ath_print(common, ATH_DBG_ANY,
-                                         "received PCI FATAL interrupt\n");
-                       }
-                       if (sync_cause & AR_INTR_SYNC_HOST1_PERR) {
-                               ath_print(common, ATH_DBG_ANY,
-                                         "received PCI PERR interrupt\n");
-                       }
-                       *masked |= ATH9K_INT_FATAL;
-               }
-               if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) {
-                       ath_print(common, ATH_DBG_INTERRUPT,
-                                 "AR_INTR_SYNC_RADM_CPL_TIMEOUT\n");
-                       REG_WRITE(ah, AR_RC, AR_RC_HOSTIF);
-                       REG_WRITE(ah, AR_RC, 0);
-                       *masked |= ATH9K_INT_FATAL;
-               }
-               if (sync_cause & AR_INTR_SYNC_LOCAL_TIMEOUT) {
-                       ath_print(common, ATH_DBG_INTERRUPT,
-                                 "AR_INTR_SYNC_LOCAL_TIMEOUT\n");
-               }
-
-               REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause);
-               (void) REG_READ(ah, AR_INTR_SYNC_CAUSE_CLR);
-       }
-
-       return true;
-}
-EXPORT_SYMBOL(ath9k_hw_getisr);
-
-enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints)
-{
-       u32 omask = ah->mask_reg;
-       u32 mask, mask2;
-       struct ath9k_hw_capabilities *pCap = &ah->caps;
-       struct ath_common *common = ath9k_hw_common(ah);
-
-       ath_print(common, ATH_DBG_INTERRUPT, "0x%x => 0x%x\n", omask, ints);
-
-       if (omask & ATH9K_INT_GLOBAL) {
-               ath_print(common, ATH_DBG_INTERRUPT, "disable IER\n");
-               REG_WRITE(ah, AR_IER, AR_IER_DISABLE);
-               (void) REG_READ(ah, AR_IER);
-               if (!AR_SREV_9100(ah)) {
-                       REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, 0);
-                       (void) REG_READ(ah, AR_INTR_ASYNC_ENABLE);
-
-                       REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0);
-                       (void) REG_READ(ah, AR_INTR_SYNC_ENABLE);
-               }
-       }
-
-       mask = ints & ATH9K_INT_COMMON;
-       mask2 = 0;
-
-       if (ints & ATH9K_INT_TX) {
-               if (ah->txok_interrupt_mask)
-                       mask |= AR_IMR_TXOK;
-               if (ah->txdesc_interrupt_mask)
-                       mask |= AR_IMR_TXDESC;
-               if (ah->txerr_interrupt_mask)
-                       mask |= AR_IMR_TXERR;
-               if (ah->txeol_interrupt_mask)
-                       mask |= AR_IMR_TXEOL;
-       }
-       if (ints & ATH9K_INT_RX) {
-               mask |= AR_IMR_RXERR;
-               if (ah->config.rx_intr_mitigation)
-                       mask |= AR_IMR_RXMINTR | AR_IMR_RXINTM;
-               else
-                       mask |= AR_IMR_RXOK | AR_IMR_RXDESC;
-               if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
-                       mask |= AR_IMR_GENTMR;
-       }
-
-       if (ints & (ATH9K_INT_BMISC)) {
-               mask |= AR_IMR_BCNMISC;
-               if (ints & ATH9K_INT_TIM)
-                       mask2 |= AR_IMR_S2_TIM;
-               if (ints & ATH9K_INT_DTIM)
-                       mask2 |= AR_IMR_S2_DTIM;
-               if (ints & ATH9K_INT_DTIMSYNC)
-                       mask2 |= AR_IMR_S2_DTIMSYNC;
-               if (ints & ATH9K_INT_CABEND)
-                       mask2 |= AR_IMR_S2_CABEND;
-               if (ints & ATH9K_INT_TSFOOR)
-                       mask2 |= AR_IMR_S2_TSFOOR;
-       }
-
-       if (ints & (ATH9K_INT_GTT | ATH9K_INT_CST)) {
-               mask |= AR_IMR_BCNMISC;
-               if (ints & ATH9K_INT_GTT)
-                       mask2 |= AR_IMR_S2_GTT;
-               if (ints & ATH9K_INT_CST)
-                       mask2 |= AR_IMR_S2_CST;
-       }
-
-       ath_print(common, ATH_DBG_INTERRUPT, "new IMR 0x%x\n", mask);
-       REG_WRITE(ah, AR_IMR, mask);
-       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)) {
-               if (ints & ATH9K_INT_TIM_TIMER)
-                       REG_SET_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER);
-               else
-                       REG_CLR_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER);
-       }
-
-       if (ints & ATH9K_INT_GLOBAL) {
-               ath_print(common, ATH_DBG_INTERRUPT, "enable IER\n");
-               REG_WRITE(ah, AR_IER, AR_IER_ENABLE);
-               if (!AR_SREV_9100(ah)) {
-                       REG_WRITE(ah, AR_INTR_ASYNC_ENABLE,
-                                 AR_INTR_MAC_IRQ);
-                       REG_WRITE(ah, AR_INTR_ASYNC_MASK, AR_INTR_MAC_IRQ);
-
-
-                       REG_WRITE(ah, AR_INTR_SYNC_ENABLE,
-                                 AR_INTR_SYNC_DEFAULT);
-                       REG_WRITE(ah, AR_INTR_SYNC_MASK,
-                                 AR_INTR_SYNC_DEFAULT);
-               }
-               ath_print(common, ATH_DBG_INTERRUPT, "AR_IMR 0x%x IER 0x%x\n",
-                         REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER));
-       }
-
-       return omask;
-}
-EXPORT_SYMBOL(ath9k_hw_set_interrupts);
-
 /*******************/
 /* Beacon Handling */
 /*******************/
@@ -2980,6 +1847,8 @@ void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period)
 
        ah->beacon_interval = beacon_period;
 
+       ENABLE_REGWRITE_BUFFER(ah);
+
        switch (ah->opmode) {
        case NL80211_IFTYPE_STATION:
        case NL80211_IFTYPE_MONITOR:
@@ -3023,6 +1892,9 @@ void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period)
        REG_WRITE(ah, AR_SWBA_PERIOD, TU_TO_USEC(beacon_period));
        REG_WRITE(ah, AR_NDP_PERIOD, TU_TO_USEC(beacon_period));
 
+       REGWRITE_BUFFER_FLUSH(ah);
+       DISABLE_REGWRITE_BUFFER(ah);
+
        beacon_period &= ~ATH9K_BEACON_ENA;
        if (beacon_period & ATH9K_BEACON_RESET_TSF) {
                ath9k_hw_reset_tsf(ah);
@@ -3039,6 +1911,8 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah,
        struct ath9k_hw_capabilities *pCap = &ah->caps;
        struct ath_common *common = ath9k_hw_common(ah);
 
+       ENABLE_REGWRITE_BUFFER(ah);
+
        REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(bs->bs_nexttbtt));
 
        REG_WRITE(ah, AR_BEACON_PERIOD,
@@ -3046,6 +1920,9 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah,
        REG_WRITE(ah, AR_DMA_BEACON_PERIOD,
                  TU_TO_USEC(bs->bs_intval & ATH9K_BEACON_PERIOD));
 
+       REGWRITE_BUFFER_FLUSH(ah);
+       DISABLE_REGWRITE_BUFFER(ah);
+
        REG_RMW_FIELD(ah, AR_RSSI_THR,
                      AR_RSSI_THR_BM_THR, bs->bs_bmissthreshold);
 
@@ -3068,6 +1945,8 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah,
        ath_print(common, ATH_DBG_BEACON, "beacon period %d\n", beaconintval);
        ath_print(common, ATH_DBG_BEACON, "DTIM period %d\n", dtimperiod);
 
+       ENABLE_REGWRITE_BUFFER(ah);
+
        REG_WRITE(ah, AR_NEXT_DTIM,
                  TU_TO_USEC(bs->bs_nextdtim - SLEEP_SLOP));
        REG_WRITE(ah, AR_NEXT_TIM, TU_TO_USEC(nextTbtt - SLEEP_SLOP));
@@ -3087,6 +1966,9 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah,
        REG_WRITE(ah, AR_TIM_PERIOD, TU_TO_USEC(beaconintval));
        REG_WRITE(ah, AR_DTIM_PERIOD, TU_TO_USEC(dtimperiod));
 
+       REGWRITE_BUFFER_FLUSH(ah);
+       DISABLE_REGWRITE_BUFFER(ah);
+
        REG_SET_BIT(ah, AR_TIMER_MODE,
                    AR_TBTT_TIMER_EN | AR_TIM_TIMER_EN |
                    AR_DTIM_TIMER_EN);
@@ -3258,8 +2140,10 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
                pCap->hw_caps |= ATH9K_HW_CAP_RFSILENT;
        }
 #endif
-
-       pCap->hw_caps &= ~ATH9K_HW_CAP_AUTOSLEEP;
+       if (AR_SREV_9271(ah))
+               pCap->hw_caps |= ATH9K_HW_CAP_AUTOSLEEP;
+       else
+               pCap->hw_caps &= ~ATH9K_HW_CAP_AUTOSLEEP;
 
        if (AR_SREV_9280(ah) || AR_SREV_9285(ah))
                pCap->hw_caps &= ~ATH9K_HW_CAP_4KB_SPLITTRANS;
@@ -3303,6 +2187,20 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
                btcoex_hw->scheme = ATH_BTCOEX_CFG_NONE;
        }
 
+       if (AR_SREV_9300_20_OR_LATER(ah)) {
+               pCap->hw_caps |= ATH9K_HW_CAP_EDMA | ATH9K_HW_CAP_LDPC;
+               pCap->rx_hp_qdepth = ATH9K_HW_RX_HP_QDEPTH;
+               pCap->rx_lp_qdepth = ATH9K_HW_RX_LP_QDEPTH;
+               pCap->rx_status_len = sizeof(struct ar9003_rxs);
+               pCap->tx_desc_len = sizeof(struct ar9003_txc);
+               pCap->txs_len = sizeof(struct ar9003_txs);
+       } else {
+               pCap->tx_desc_len = sizeof(struct ath_desc);
+       }
+
+       if (AR_SREV_9300_20_OR_LATER(ah))
+               pCap->hw_caps |= ATH9K_HW_CAP_RAC_SUPPORTED;
+
        return 0;
 }
 
@@ -3335,10 +2233,6 @@ bool ath9k_hw_getcapability(struct ath_hw *ah, enum ath9k_capability_type type,
        case ATH9K_CAP_TKIP_SPLIT:
                return (ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA) ?
                        false : true;
-       case ATH9K_CAP_DIVERSITY:
-               return (REG_READ(ah, AR_PHY_CCK_DETECT) &
-                       AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV) ?
-                       true : false;
        case ATH9K_CAP_MCAST_KEYSRCH:
                switch (capability) {
                case 0:
@@ -3381,8 +2275,6 @@ EXPORT_SYMBOL(ath9k_hw_getcapability);
 bool ath9k_hw_setcapability(struct ath_hw *ah, enum ath9k_capability_type type,
                            u32 capability, u32 setting, int *status)
 {
-       u32 v;
-
        switch (type) {
        case ATH9K_CAP_TKIP_MIC:
                if (setting)
@@ -3392,14 +2284,6 @@ bool ath9k_hw_setcapability(struct ath_hw *ah, enum ath9k_capability_type type,
                        ah->sta_id1_defaults &=
                                ~AR_STA_ID1_CRPT_MIC_ENABLE;
                return true;
-       case ATH9K_CAP_DIVERSITY:
-               v = REG_READ(ah, AR_PHY_CCK_DETECT);
-               if (setting)
-                       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);
-               return true;
        case ATH9K_CAP_MCAST_KEYSRCH:
                if (setting)
                        ah->sta_id1_defaults |= AR_STA_ID1_MCAST_KSRCH;
@@ -3467,7 +2351,9 @@ u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio)
        if (gpio >= ah->caps.num_gpio_pins)
                return 0xffffffff;
 
-       if (AR_SREV_9271(ah))
+       if (AR_SREV_9300_20_OR_LATER(ah))
+               return MS_REG_READ(AR9300, gpio) != 0;
+       else 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;
@@ -3540,6 +2426,8 @@ void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits)
 {
        u32 phybits;
 
+       ENABLE_REGWRITE_BUFFER(ah);
+
        REG_WRITE(ah, AR_RX_FILTER, bits);
 
        phybits = 0;
@@ -3555,6 +2443,9 @@ void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits)
        else
                REG_WRITE(ah, AR_RXCFG,
                          REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_ZLFDMA);
+
+       REGWRITE_BUFFER_FLUSH(ah);
+       DISABLE_REGWRITE_BUFFER(ah);
 }
 EXPORT_SYMBOL(ath9k_hw_setrxfilter);
 
@@ -3627,14 +2518,25 @@ void ath9k_hw_write_associd(struct ath_hw *ah)
 }
 EXPORT_SYMBOL(ath9k_hw_write_associd);
 
+#define ATH9K_MAX_TSF_READ 10
+
 u64 ath9k_hw_gettsf64(struct ath_hw *ah)
 {
-       u64 tsf;
+       u32 tsf_lower, tsf_upper1, tsf_upper2;
+       int i;
+
+       tsf_upper1 = REG_READ(ah, AR_TSF_U32);
+       for (i = 0; i < ATH9K_MAX_TSF_READ; i++) {
+               tsf_lower = REG_READ(ah, AR_TSF_L32);
+               tsf_upper2 = REG_READ(ah, AR_TSF_U32);
+               if (tsf_upper2 == tsf_upper1)
+                       break;
+               tsf_upper1 = tsf_upper2;
+       }
 
-       tsf = REG_READ(ah, AR_TSF_U32);
-       tsf = (tsf << 32) | REG_READ(ah, AR_TSF_L32);
+       WARN_ON( i == ATH9K_MAX_TSF_READ );
 
-       return tsf;
+       return (((u64)tsf_upper1 << 32) | tsf_lower);
 }
 EXPORT_SYMBOL(ath9k_hw_gettsf64);
 
@@ -3885,6 +2787,16 @@ void ath_gen_timer_isr(struct ath_hw *ah)
 }
 EXPORT_SYMBOL(ath_gen_timer_isr);
 
+/********/
+/* HTC  */
+/********/
+
+void ath9k_hw_htc_resetinit(struct ath_hw *ah)
+{
+       ah->htc_reset_init = true;
+}
+EXPORT_SYMBOL(ath9k_hw_htc_resetinit);
+
 static struct {
        u32 version;
        const char * name;
@@ -3899,6 +2811,7 @@ static struct {
        { AR_SREV_VERSION_9285,         "9285" },
        { AR_SREV_VERSION_9287,         "9287" },
        { AR_SREV_VERSION_9271,         "9271" },
+       { AR_SREV_VERSION_9300,         "9300" },
 };
 
 /* For devices with external radios */