ath9k: Enable Bluetooth Coexistence support
authorVasanthakumar Thiagarajan <vasanth@atheros.com>
Fri, 2 Jan 2009 10:05:46 +0000 (15:35 +0530)
committerJohn W. Linville <linville@tuxdriver.com>
Thu, 29 Jan 2009 20:59:46 +0000 (15:59 -0500)
Signed-off-by: Vasanthakumar Thiagarajan <vasanth@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/ath9k/ath9k.h
drivers/net/wireless/ath9k/hw.c
drivers/net/wireless/ath9k/main.c
drivers/net/wireless/ath9k/reg.h

index adcd34249a8bfc015aab7c2e80371a8feae3df52..f2ad62536bf8212c81a23176a8ef50bbfbcfee8a 100644 (file)
@@ -198,6 +198,7 @@ enum ath9k_hw_caps {
        ATH9K_HW_CAP_AUTOSLEEP                  = BIT(19),
        ATH9K_HW_CAP_4KB_SPLITTRANS             = BIT(20),
        ATH9K_HW_CAP_WOW_MATCHPATTERN_EXACT     = BIT(21),
+       ATH9K_HW_CAP_BT_COEX                    = BIT(22)
 };
 
 enum ath9k_capability_type {
@@ -752,6 +753,7 @@ struct ath9k_node_stats {
 #define AR_GPIO_OUTPUT_MUX_AS_OUTPUT             0
 #define AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED 1
 #define AR_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED     2
+#define AR_GPIO_OUTPUT_MUX_AS_TX_FRAME           3
 #define AR_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED    5
 #define AR_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED      6
 
@@ -801,6 +803,8 @@ struct ath_hal {
        u16 ah_rfsilent;
        u32 ah_rfkill_gpio;
        u32 ah_rfkill_polarity;
+       u32 ah_btactive_gpio;
+       u32 ah_wlanactive_gpio;
 
 #ifndef ATH_NF_PER_CHAN
        struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS];
@@ -1050,5 +1054,6 @@ void ath9k_hw_rxena(struct ath_hal *ah);
 void ath9k_hw_startpcureceive(struct ath_hal *ah);
 void ath9k_hw_stoppcurecv(struct ath_hal *ah);
 bool ath9k_hw_stopdmarecv(struct ath_hal *ah);
+void ath9k_hw_btcoex_enable(struct ath_hal *ah);
 
 #endif
index 19144caa79775951ee43101b1f067f8ec45b66e5..3c026e6b245380b26ec1eab0ef5f15cf322ba225 100644 (file)
@@ -3341,6 +3341,12 @@ bool ath9k_hw_fill_cap_info(struct ath_hal *ah)
        pCap->num_antcfg_2ghz =
                ath9k_hw_get_num_ant_config(ah, ATH9K_HAL_FREQ_BAND_2GHZ);
 
+       if (AR_SREV_9280_10_OR_LATER(ah)) {
+               pCap->hw_caps |= ATH9K_HW_CAP_BT_COEX;
+               ah->ah_btactive_gpio = 6;
+               ah->ah_wlanactive_gpio = 5;
+       }
+
        return true;
 }
 
@@ -3836,3 +3842,30 @@ void ath9k_hw_set11nmac2040(struct ath_hal *ah, enum ath9k_ht_macmode mode)
 
        REG_WRITE(ah, AR_2040_MODE, macmode);
 }
+
+/***************************/
+/*  Bluetooth Coexistence  */
+/***************************/
+
+void ath9k_hw_btcoex_enable(struct ath_hal *ah)
+{
+       /* connect bt_active to baseband */
+       REG_CLR_BIT(ah, AR_GPIO_INPUT_EN_VAL,
+                       (AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_DEF |
+                        AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_DEF));
+
+       REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL,
+                       AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB);
+
+       /* Set input mux for bt_active to gpio pin */
+       REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1,
+                       AR_GPIO_INPUT_MUX1_BT_ACTIVE,
+                       ah->ah_btactive_gpio);
+
+       /* Configure the desired gpio port for input */
+       ath9k_hw_cfg_gpio_input(ah, ah->ah_btactive_gpio);
+
+       /* Configure the desired GPIO port for TX_FRAME output */
+       ath9k_hw_cfg_output(ah, ah->ah_wlanactive_gpio,
+                           AR_GPIO_OUTPUT_MUX_AS_TX_FRAME);
+}
index 9c1fb96acc5bda744891291c7a5d58fd031f4fbf..8929b02aa22d1669c8ed17810b36cb3b5b77458c 100644 (file)
@@ -431,12 +431,14 @@ static void ath_ani_calibrate(unsigned long data)
 /*
  * Update tx/rx chainmask. For legacy association,
  * hard code chainmask to 1x1, for 11n association, use
- * the chainmask configuration.
+ * the chainmask configuration, for bt coexistence, use
+ * the chainmask configuration even in legacy mode.
  */
 static void ath_update_chainmask(struct ath_softc *sc, int is_ht)
 {
        sc->sc_flags |= SC_OP_CHAINMASK_UPDATE;
-       if (is_ht) {
+       if (is_ht ||
+           (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_BT_COEX)) {
                sc->sc_tx_chainmask = sc->sc_ah->ah_caps.tx_chainmask;
                sc->sc_rx_chainmask = sc->sc_ah->ah_caps.rx_chainmask;
        } else {
@@ -1519,6 +1521,9 @@ static int ath_init(u16 devid, struct ath_softc *sc)
                sc->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ;
        }
 
+       if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_BT_COEX)
+               ath9k_hw_btcoex_enable(sc->sc_ah);
+
        return 0;
 bad2:
        /* cleanup tx queues */
index 8cc9beff5ec15c7e487d0c170999ac03c04daec1..9a615224e4f74c139b2476465ed33cdb86ee6586 100644 (file)
@@ -897,14 +897,24 @@ enum {
 #define AR_GPIO_INTR_POL_VAL_S                   0
 
 #define AR_GPIO_INPUT_EN_VAL                     0x4054
+#define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_DEF     0x00000004
+#define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_S       2
+#define AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_DEF    0x00000008
+#define AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_S      3
+#define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_DEF       0x00000010
+#define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_S         4
 #define AR_GPIO_INPUT_EN_VAL_RFSILENT_DEF        0x00000080
 #define AR_GPIO_INPUT_EN_VAL_RFSILENT_DEF_S      7
+#define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB        0x00001000
+#define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB_S      12
 #define AR_GPIO_INPUT_EN_VAL_RFSILENT_BB         0x00008000
 #define AR_GPIO_INPUT_EN_VAL_RFSILENT_BB_S       15
 #define AR_GPIO_RTC_RESET_OVERRIDE_ENABLE        0x00010000
 #define AR_GPIO_JTAG_DISABLE                     0x00020000
 
 #define AR_GPIO_INPUT_MUX1                       0x4058
+#define AR_GPIO_INPUT_MUX1_BT_ACTIVE             0x000f0000
+#define AR_GPIO_INPUT_MUX1_BT_ACTIVE_S           16
 
 #define AR_GPIO_INPUT_MUX2                       0x405c
 #define AR_GPIO_INPUT_MUX2_CLK25                 0x0000000f