117d50d1dSVasanthakumar Thiagarajan /* 217d50d1dSVasanthakumar Thiagarajan * Copyright (c) 2009 Atheros Communications Inc. 317d50d1dSVasanthakumar Thiagarajan * 417d50d1dSVasanthakumar Thiagarajan * Permission to use, copy, modify, and/or distribute this software for any 517d50d1dSVasanthakumar Thiagarajan * purpose with or without fee is hereby granted, provided that the above 617d50d1dSVasanthakumar Thiagarajan * copyright notice and this permission notice appear in all copies. 717d50d1dSVasanthakumar Thiagarajan * 817d50d1dSVasanthakumar Thiagarajan * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 917d50d1dSVasanthakumar Thiagarajan * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1017d50d1dSVasanthakumar Thiagarajan * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 1117d50d1dSVasanthakumar Thiagarajan * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1217d50d1dSVasanthakumar Thiagarajan * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1317d50d1dSVasanthakumar Thiagarajan * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 1417d50d1dSVasanthakumar Thiagarajan * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1517d50d1dSVasanthakumar Thiagarajan */ 1617d50d1dSVasanthakumar Thiagarajan 1717d50d1dSVasanthakumar Thiagarajan #include "ath9k.h" 1817d50d1dSVasanthakumar Thiagarajan 19*1773912bSVasanthakumar Thiagarajan static const struct ath_btcoex_config ath_bt_config = { 0, true, true, 20*1773912bSVasanthakumar Thiagarajan ATH_BT_COEX_MODE_SLOTTED, true, true, 2, 5, true }; 21*1773912bSVasanthakumar Thiagarajan 22*1773912bSVasanthakumar Thiagarajan 23*1773912bSVasanthakumar Thiagarajan /* 24*1773912bSVasanthakumar Thiagarajan * Detects if there is any priority bt traffic 25*1773912bSVasanthakumar Thiagarajan */ 26*1773912bSVasanthakumar Thiagarajan static void ath_detect_bt_priority(struct ath_softc *sc) 27*1773912bSVasanthakumar Thiagarajan { 28*1773912bSVasanthakumar Thiagarajan struct ath_btcoex_info *btinfo = &sc->btcoex_info; 29*1773912bSVasanthakumar Thiagarajan 30*1773912bSVasanthakumar Thiagarajan if (ath9k_hw_gpio_get(sc->sc_ah, btinfo->btpriority_gpio)) 31*1773912bSVasanthakumar Thiagarajan btinfo->bt_priority_cnt++; 32*1773912bSVasanthakumar Thiagarajan 33*1773912bSVasanthakumar Thiagarajan if (time_after(jiffies, btinfo->bt_priority_time + 34*1773912bSVasanthakumar Thiagarajan msecs_to_jiffies(ATH_BT_PRIORITY_TIME_THRESHOLD))) { 35*1773912bSVasanthakumar Thiagarajan if (btinfo->bt_priority_cnt >= ATH_BT_CNT_THRESHOLD) { 36*1773912bSVasanthakumar Thiagarajan DPRINTF(sc, ATH_DBG_BTCOEX, 37*1773912bSVasanthakumar Thiagarajan "BT priority traffic detected"); 38*1773912bSVasanthakumar Thiagarajan sc->sc_flags |= SC_OP_BT_PRIORITY_DETECTED; 39*1773912bSVasanthakumar Thiagarajan } else { 40*1773912bSVasanthakumar Thiagarajan sc->sc_flags &= ~SC_OP_BT_PRIORITY_DETECTED; 41*1773912bSVasanthakumar Thiagarajan } 42*1773912bSVasanthakumar Thiagarajan 43*1773912bSVasanthakumar Thiagarajan btinfo->bt_priority_cnt = 0; 44*1773912bSVasanthakumar Thiagarajan btinfo->bt_priority_time = jiffies; 45*1773912bSVasanthakumar Thiagarajan } 46*1773912bSVasanthakumar Thiagarajan } 47*1773912bSVasanthakumar Thiagarajan 48*1773912bSVasanthakumar Thiagarajan /* 49*1773912bSVasanthakumar Thiagarajan * Configures appropriate weight based on stomp type. 50*1773912bSVasanthakumar Thiagarajan */ 51*1773912bSVasanthakumar Thiagarajan static void ath_btcoex_bt_stomp(struct ath_softc *sc, 52*1773912bSVasanthakumar Thiagarajan struct ath_btcoex_info *btinfo, 53*1773912bSVasanthakumar Thiagarajan int stomp_type) 54*1773912bSVasanthakumar Thiagarajan { 55*1773912bSVasanthakumar Thiagarajan 56*1773912bSVasanthakumar Thiagarajan switch (stomp_type) { 57*1773912bSVasanthakumar Thiagarajan case ATH_BTCOEX_STOMP_ALL: 58*1773912bSVasanthakumar Thiagarajan ath_btcoex_set_weight(btinfo, AR_BT_COEX_WGHT, 59*1773912bSVasanthakumar Thiagarajan AR_STOMP_ALL_WLAN_WGHT); 60*1773912bSVasanthakumar Thiagarajan break; 61*1773912bSVasanthakumar Thiagarajan case ATH_BTCOEX_STOMP_LOW: 62*1773912bSVasanthakumar Thiagarajan ath_btcoex_set_weight(btinfo, AR_BT_COEX_WGHT, 63*1773912bSVasanthakumar Thiagarajan AR_STOMP_LOW_WLAN_WGHT); 64*1773912bSVasanthakumar Thiagarajan break; 65*1773912bSVasanthakumar Thiagarajan case ATH_BTCOEX_STOMP_NONE: 66*1773912bSVasanthakumar Thiagarajan ath_btcoex_set_weight(btinfo, AR_BT_COEX_WGHT, 67*1773912bSVasanthakumar Thiagarajan AR_STOMP_NONE_WLAN_WGHT); 68*1773912bSVasanthakumar Thiagarajan break; 69*1773912bSVasanthakumar Thiagarajan default: 70*1773912bSVasanthakumar Thiagarajan DPRINTF(sc, ATH_DBG_BTCOEX, "Invalid Stomptype\n"); 71*1773912bSVasanthakumar Thiagarajan break; 72*1773912bSVasanthakumar Thiagarajan } 73*1773912bSVasanthakumar Thiagarajan 74*1773912bSVasanthakumar Thiagarajan ath9k_hw_btcoex_enable(sc->sc_ah); 75*1773912bSVasanthakumar Thiagarajan } 76*1773912bSVasanthakumar Thiagarajan 77*1773912bSVasanthakumar Thiagarajan /* 78*1773912bSVasanthakumar Thiagarajan * This is the master bt coex timer which runs for every 79*1773912bSVasanthakumar Thiagarajan * 45ms, bt traffic will be given priority during 55% of this 80*1773912bSVasanthakumar Thiagarajan * period while wlan gets remaining 45% 81*1773912bSVasanthakumar Thiagarajan */ 82*1773912bSVasanthakumar Thiagarajan 83*1773912bSVasanthakumar Thiagarajan static void ath_btcoex_period_timer(unsigned long data) 84*1773912bSVasanthakumar Thiagarajan { 85*1773912bSVasanthakumar Thiagarajan struct ath_softc *sc = (struct ath_softc *) data; 86*1773912bSVasanthakumar Thiagarajan struct ath_btcoex_info *btinfo = &sc->btcoex_info; 87*1773912bSVasanthakumar Thiagarajan unsigned long flags; 88*1773912bSVasanthakumar Thiagarajan 89*1773912bSVasanthakumar Thiagarajan ath_detect_bt_priority(sc); 90*1773912bSVasanthakumar Thiagarajan 91*1773912bSVasanthakumar Thiagarajan spin_lock_irqsave(&btinfo->btcoex_lock, flags); 92*1773912bSVasanthakumar Thiagarajan 93*1773912bSVasanthakumar Thiagarajan ath_btcoex_bt_stomp(sc, btinfo, btinfo->bt_stomp_type); 94*1773912bSVasanthakumar Thiagarajan 95*1773912bSVasanthakumar Thiagarajan spin_unlock_irqrestore(&btinfo->btcoex_lock, flags); 96*1773912bSVasanthakumar Thiagarajan 97*1773912bSVasanthakumar Thiagarajan if (btinfo->btcoex_period != btinfo->btcoex_no_stomp) { 98*1773912bSVasanthakumar Thiagarajan if (btinfo->hw_timer_enabled) 99*1773912bSVasanthakumar Thiagarajan ath_gen_timer_stop(sc->sc_ah, btinfo->no_stomp_timer); 100*1773912bSVasanthakumar Thiagarajan 101*1773912bSVasanthakumar Thiagarajan ath_gen_timer_start(sc->sc_ah, 102*1773912bSVasanthakumar Thiagarajan btinfo->no_stomp_timer, 103*1773912bSVasanthakumar Thiagarajan (ath9k_hw_gettsf32(sc->sc_ah) + 104*1773912bSVasanthakumar Thiagarajan btinfo->btcoex_no_stomp), 105*1773912bSVasanthakumar Thiagarajan btinfo->btcoex_no_stomp * 10); 106*1773912bSVasanthakumar Thiagarajan btinfo->hw_timer_enabled = true; 107*1773912bSVasanthakumar Thiagarajan } 108*1773912bSVasanthakumar Thiagarajan 109*1773912bSVasanthakumar Thiagarajan mod_timer(&btinfo->period_timer, jiffies + 110*1773912bSVasanthakumar Thiagarajan msecs_to_jiffies(ATH_BTCOEX_DEF_BT_PERIOD)); 111*1773912bSVasanthakumar Thiagarajan } 112*1773912bSVasanthakumar Thiagarajan 113*1773912bSVasanthakumar Thiagarajan /* 114*1773912bSVasanthakumar Thiagarajan * Generic tsf based hw timer which configures weight 115*1773912bSVasanthakumar Thiagarajan * registers to time slice between wlan and bt traffic 116*1773912bSVasanthakumar Thiagarajan */ 117*1773912bSVasanthakumar Thiagarajan 118*1773912bSVasanthakumar Thiagarajan static void ath_btcoex_no_stomp_timer(void *arg) 119*1773912bSVasanthakumar Thiagarajan { 120*1773912bSVasanthakumar Thiagarajan struct ath_softc *sc = (struct ath_softc *)arg; 121*1773912bSVasanthakumar Thiagarajan struct ath_btcoex_info *btinfo = &sc->btcoex_info; 122*1773912bSVasanthakumar Thiagarajan unsigned long flags; 123*1773912bSVasanthakumar Thiagarajan 124*1773912bSVasanthakumar Thiagarajan DPRINTF(sc, ATH_DBG_BTCOEX, "no stomp timer running \n"); 125*1773912bSVasanthakumar Thiagarajan 126*1773912bSVasanthakumar Thiagarajan spin_lock_irqsave(&btinfo->btcoex_lock, flags); 127*1773912bSVasanthakumar Thiagarajan 128*1773912bSVasanthakumar Thiagarajan if (btinfo->bt_stomp_type == ATH_BTCOEX_STOMP_LOW) 129*1773912bSVasanthakumar Thiagarajan ath_btcoex_bt_stomp(sc, btinfo, ATH_BTCOEX_STOMP_NONE); 130*1773912bSVasanthakumar Thiagarajan else if (btinfo->bt_stomp_type == ATH_BTCOEX_STOMP_ALL) 131*1773912bSVasanthakumar Thiagarajan ath_btcoex_bt_stomp(sc, btinfo, ATH_BTCOEX_STOMP_LOW); 132*1773912bSVasanthakumar Thiagarajan 133*1773912bSVasanthakumar Thiagarajan spin_unlock_irqrestore(&btinfo->btcoex_lock, flags); 134*1773912bSVasanthakumar Thiagarajan } 135*1773912bSVasanthakumar Thiagarajan 136*1773912bSVasanthakumar Thiagarajan static int ath_init_btcoex_info(struct ath_hw *hw, 137*1773912bSVasanthakumar Thiagarajan struct ath_btcoex_info *btcoex_info) 138*1773912bSVasanthakumar Thiagarajan { 139*1773912bSVasanthakumar Thiagarajan u32 i; 140*1773912bSVasanthakumar Thiagarajan int qnum; 141*1773912bSVasanthakumar Thiagarajan 142*1773912bSVasanthakumar Thiagarajan qnum = ath_tx_get_qnum(hw->ah_sc, ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_BE); 143*1773912bSVasanthakumar Thiagarajan 144*1773912bSVasanthakumar Thiagarajan btcoex_info->bt_coex_mode = 145*1773912bSVasanthakumar Thiagarajan (btcoex_info->bt_coex_mode & AR_BT_QCU_THRESH) | 146*1773912bSVasanthakumar Thiagarajan SM(ath_bt_config.bt_time_extend, AR_BT_TIME_EXTEND) | 147*1773912bSVasanthakumar Thiagarajan SM(ath_bt_config.bt_txstate_extend, AR_BT_TXSTATE_EXTEND) | 148*1773912bSVasanthakumar Thiagarajan SM(ath_bt_config.bt_txframe_extend, AR_BT_TX_FRAME_EXTEND) | 149*1773912bSVasanthakumar Thiagarajan SM(ath_bt_config.bt_mode, AR_BT_MODE) | 150*1773912bSVasanthakumar Thiagarajan SM(ath_bt_config.bt_quiet_collision, AR_BT_QUIET) | 151*1773912bSVasanthakumar Thiagarajan SM(ath_bt_config.bt_rxclear_polarity, AR_BT_RX_CLEAR_POLARITY) | 152*1773912bSVasanthakumar Thiagarajan SM(ath_bt_config.bt_priority_time, AR_BT_PRIORITY_TIME) | 153*1773912bSVasanthakumar Thiagarajan SM(ath_bt_config.bt_first_slot_time, AR_BT_FIRST_SLOT_TIME) | 154*1773912bSVasanthakumar Thiagarajan SM(qnum, AR_BT_QCU_THRESH); 155*1773912bSVasanthakumar Thiagarajan 156*1773912bSVasanthakumar Thiagarajan btcoex_info->bt_coex_mode2 = 157*1773912bSVasanthakumar Thiagarajan SM(ath_bt_config.bt_hold_rx_clear, AR_BT_HOLD_RX_CLEAR) | 158*1773912bSVasanthakumar Thiagarajan SM(ATH_BTCOEX_BMISS_THRESH, AR_BT_BCN_MISS_THRESH) | 159*1773912bSVasanthakumar Thiagarajan AR_BT_DISABLE_BT_ANT; 160*1773912bSVasanthakumar Thiagarajan 161*1773912bSVasanthakumar Thiagarajan btcoex_info->bt_stomp_type = ATH_BTCOEX_STOMP_LOW; 162*1773912bSVasanthakumar Thiagarajan 163*1773912bSVasanthakumar Thiagarajan btcoex_info->btcoex_period = ATH_BTCOEX_DEF_BT_PERIOD * 1000; 164*1773912bSVasanthakumar Thiagarajan 165*1773912bSVasanthakumar Thiagarajan btcoex_info->btcoex_no_stomp = (100 - ATH_BTCOEX_DEF_DUTY_CYCLE) * 166*1773912bSVasanthakumar Thiagarajan btcoex_info->btcoex_period / 100; 167*1773912bSVasanthakumar Thiagarajan 168*1773912bSVasanthakumar Thiagarajan for (i = 0; i < 32; i++) 169*1773912bSVasanthakumar Thiagarajan hw->hw_gen_timers.gen_timer_index[(debruijn32 << i) >> 27] = i; 170*1773912bSVasanthakumar Thiagarajan 171*1773912bSVasanthakumar Thiagarajan setup_timer(&btcoex_info->period_timer, ath_btcoex_period_timer, 172*1773912bSVasanthakumar Thiagarajan (unsigned long) hw->ah_sc); 173*1773912bSVasanthakumar Thiagarajan 174*1773912bSVasanthakumar Thiagarajan btcoex_info->no_stomp_timer = ath_gen_timer_alloc(hw, 175*1773912bSVasanthakumar Thiagarajan ath_btcoex_no_stomp_timer, 176*1773912bSVasanthakumar Thiagarajan ath_btcoex_no_stomp_timer, 177*1773912bSVasanthakumar Thiagarajan (void *)hw->ah_sc, AR_FIRST_NDP_TIMER); 178*1773912bSVasanthakumar Thiagarajan 179*1773912bSVasanthakumar Thiagarajan if (btcoex_info->no_stomp_timer == NULL) 180*1773912bSVasanthakumar Thiagarajan return -ENOMEM; 181*1773912bSVasanthakumar Thiagarajan 182*1773912bSVasanthakumar Thiagarajan spin_lock_init(&btcoex_info->btcoex_lock); 183*1773912bSVasanthakumar Thiagarajan 184*1773912bSVasanthakumar Thiagarajan return 0; 185*1773912bSVasanthakumar Thiagarajan } 186*1773912bSVasanthakumar Thiagarajan 187*1773912bSVasanthakumar Thiagarajan int ath9k_hw_btcoex_init(struct ath_hw *ah) 18817d50d1dSVasanthakumar Thiagarajan { 189f14462c6SVasanthakumar Thiagarajan struct ath_btcoex_info *btcoex_info = &ah->ah_sc->btcoex_info; 190*1773912bSVasanthakumar Thiagarajan int ret = 0; 191f14462c6SVasanthakumar Thiagarajan 192*1773912bSVasanthakumar Thiagarajan if (btcoex_info->btcoex_scheme == ATH_BTCOEX_CFG_2WIRE) { 19317d50d1dSVasanthakumar Thiagarajan /* connect bt_active to baseband */ 19417d50d1dSVasanthakumar Thiagarajan REG_CLR_BIT(ah, AR_GPIO_INPUT_EN_VAL, 19517d50d1dSVasanthakumar Thiagarajan (AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_DEF | 19617d50d1dSVasanthakumar Thiagarajan AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_DEF)); 19717d50d1dSVasanthakumar Thiagarajan 19817d50d1dSVasanthakumar Thiagarajan REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, 19917d50d1dSVasanthakumar Thiagarajan AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB); 20017d50d1dSVasanthakumar Thiagarajan 20117d50d1dSVasanthakumar Thiagarajan /* Set input mux for bt_active to gpio pin */ 20217d50d1dSVasanthakumar Thiagarajan REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1, 20317d50d1dSVasanthakumar Thiagarajan AR_GPIO_INPUT_MUX1_BT_ACTIVE, 204f14462c6SVasanthakumar Thiagarajan btcoex_info->btactive_gpio); 20517d50d1dSVasanthakumar Thiagarajan 20617d50d1dSVasanthakumar Thiagarajan /* Configure the desired gpio port for input */ 207f14462c6SVasanthakumar Thiagarajan ath9k_hw_cfg_gpio_input(ah, btcoex_info->btactive_gpio); 208*1773912bSVasanthakumar Thiagarajan } else { 209*1773912bSVasanthakumar Thiagarajan /* btcoex 3-wire */ 210*1773912bSVasanthakumar Thiagarajan REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, 211*1773912bSVasanthakumar Thiagarajan (AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_BB | 212*1773912bSVasanthakumar Thiagarajan AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB)); 213*1773912bSVasanthakumar Thiagarajan 214*1773912bSVasanthakumar Thiagarajan /* Set input mux for bt_prority_async and 215*1773912bSVasanthakumar Thiagarajan * bt_active_async to GPIO pins */ 216*1773912bSVasanthakumar Thiagarajan REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1, 217*1773912bSVasanthakumar Thiagarajan AR_GPIO_INPUT_MUX1_BT_ACTIVE, 218*1773912bSVasanthakumar Thiagarajan btcoex_info->btactive_gpio); 219*1773912bSVasanthakumar Thiagarajan 220*1773912bSVasanthakumar Thiagarajan REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1, 221*1773912bSVasanthakumar Thiagarajan AR_GPIO_INPUT_MUX1_BT_PRIORITY, 222*1773912bSVasanthakumar Thiagarajan btcoex_info->btpriority_gpio); 223*1773912bSVasanthakumar Thiagarajan 224*1773912bSVasanthakumar Thiagarajan /* Configure the desired GPIO ports for input */ 225*1773912bSVasanthakumar Thiagarajan 226*1773912bSVasanthakumar Thiagarajan ath9k_hw_cfg_gpio_input(ah, btcoex_info->btactive_gpio); 227*1773912bSVasanthakumar Thiagarajan ath9k_hw_cfg_gpio_input(ah, btcoex_info->btpriority_gpio); 228*1773912bSVasanthakumar Thiagarajan 229*1773912bSVasanthakumar Thiagarajan ret = ath_init_btcoex_info(ah, btcoex_info); 230*1773912bSVasanthakumar Thiagarajan } 231*1773912bSVasanthakumar Thiagarajan 232*1773912bSVasanthakumar Thiagarajan return ret; 23317d50d1dSVasanthakumar Thiagarajan } 23417d50d1dSVasanthakumar Thiagarajan 23517d50d1dSVasanthakumar Thiagarajan void ath9k_hw_btcoex_enable(struct ath_hw *ah) 23617d50d1dSVasanthakumar Thiagarajan { 237f14462c6SVasanthakumar Thiagarajan struct ath_btcoex_info *btcoex_info = &ah->ah_sc->btcoex_info; 238f14462c6SVasanthakumar Thiagarajan 239*1773912bSVasanthakumar Thiagarajan if (btcoex_info->btcoex_scheme == ATH_BTCOEX_CFG_2WIRE) { 24017d50d1dSVasanthakumar Thiagarajan /* Configure the desired GPIO port for TX_FRAME output */ 241f14462c6SVasanthakumar Thiagarajan ath9k_hw_cfg_output(ah, btcoex_info->wlanactive_gpio, 24217d50d1dSVasanthakumar Thiagarajan AR_GPIO_OUTPUT_MUX_AS_TX_FRAME); 243*1773912bSVasanthakumar Thiagarajan } else { 244*1773912bSVasanthakumar Thiagarajan /* 245*1773912bSVasanthakumar Thiagarajan * Program coex mode and weight registers to 246*1773912bSVasanthakumar Thiagarajan * enable coex 3-wire 247*1773912bSVasanthakumar Thiagarajan */ 248*1773912bSVasanthakumar Thiagarajan REG_WRITE(ah, AR_BT_COEX_MODE, btcoex_info->bt_coex_mode); 249*1773912bSVasanthakumar Thiagarajan REG_WRITE(ah, AR_BT_COEX_WEIGHT, btcoex_info->bt_coex_weights); 250*1773912bSVasanthakumar Thiagarajan REG_WRITE(ah, AR_BT_COEX_MODE2, btcoex_info->bt_coex_mode2); 251*1773912bSVasanthakumar Thiagarajan 252*1773912bSVasanthakumar Thiagarajan REG_RMW_FIELD(ah, AR_QUIET1, 253*1773912bSVasanthakumar Thiagarajan AR_QUIET1_QUIET_ACK_CTS_ENABLE, 1); 254*1773912bSVasanthakumar Thiagarajan REG_RMW_FIELD(ah, AR_PCU_MISC, 255*1773912bSVasanthakumar Thiagarajan AR_PCU_BT_ANT_PREVENT_RX, 0); 256*1773912bSVasanthakumar Thiagarajan 257*1773912bSVasanthakumar Thiagarajan ath9k_hw_cfg_output(ah, btcoex_info->wlanactive_gpio, 258*1773912bSVasanthakumar Thiagarajan AR_GPIO_OUTPUT_MUX_AS_RX_CLEAR_EXTERNAL); 259*1773912bSVasanthakumar Thiagarajan } 260*1773912bSVasanthakumar Thiagarajan 261*1773912bSVasanthakumar Thiagarajan REG_RMW(ah, AR_GPIO_PDPU, 262*1773912bSVasanthakumar Thiagarajan (0x2 << (btcoex_info->btactive_gpio * 2)), 263*1773912bSVasanthakumar Thiagarajan (0x3 << (btcoex_info->btactive_gpio * 2))); 26417d50d1dSVasanthakumar Thiagarajan 26517d50d1dSVasanthakumar Thiagarajan ah->ah_sc->sc_flags |= SC_OP_BTCOEX_ENABLED; 26617d50d1dSVasanthakumar Thiagarajan } 26717d50d1dSVasanthakumar Thiagarajan 26817d50d1dSVasanthakumar Thiagarajan void ath9k_hw_btcoex_disable(struct ath_hw *ah) 26917d50d1dSVasanthakumar Thiagarajan { 270f14462c6SVasanthakumar Thiagarajan struct ath_btcoex_info *btcoex_info = &ah->ah_sc->btcoex_info; 27117d50d1dSVasanthakumar Thiagarajan 272f14462c6SVasanthakumar Thiagarajan ath9k_hw_set_gpio(ah, btcoex_info->wlanactive_gpio, 0); 273f14462c6SVasanthakumar Thiagarajan 274f14462c6SVasanthakumar Thiagarajan ath9k_hw_cfg_output(ah, btcoex_info->wlanactive_gpio, 27517d50d1dSVasanthakumar Thiagarajan AR_GPIO_OUTPUT_MUX_AS_OUTPUT); 27617d50d1dSVasanthakumar Thiagarajan 277*1773912bSVasanthakumar Thiagarajan if (btcoex_info->btcoex_scheme == ATH_BTCOEX_CFG_3WIRE) { 278*1773912bSVasanthakumar Thiagarajan REG_WRITE(ah, AR_BT_COEX_MODE, AR_BT_QUIET | AR_BT_MODE); 279*1773912bSVasanthakumar Thiagarajan REG_WRITE(ah, AR_BT_COEX_WEIGHT, 0); 280*1773912bSVasanthakumar Thiagarajan REG_WRITE(ah, AR_BT_COEX_MODE2, 0); 281*1773912bSVasanthakumar Thiagarajan } 282*1773912bSVasanthakumar Thiagarajan 28317d50d1dSVasanthakumar Thiagarajan ah->ah_sc->sc_flags &= ~SC_OP_BTCOEX_ENABLED; 28417d50d1dSVasanthakumar Thiagarajan } 285*1773912bSVasanthakumar Thiagarajan 286*1773912bSVasanthakumar Thiagarajan /* 287*1773912bSVasanthakumar Thiagarajan * Pause btcoex timer and bt duty cycle timer 288*1773912bSVasanthakumar Thiagarajan */ 289*1773912bSVasanthakumar Thiagarajan void ath_btcoex_timer_pause(struct ath_softc *sc, 290*1773912bSVasanthakumar Thiagarajan struct ath_btcoex_info *btinfo) 291*1773912bSVasanthakumar Thiagarajan { 292*1773912bSVasanthakumar Thiagarajan 293*1773912bSVasanthakumar Thiagarajan del_timer_sync(&btinfo->period_timer); 294*1773912bSVasanthakumar Thiagarajan 295*1773912bSVasanthakumar Thiagarajan if (btinfo->hw_timer_enabled) 296*1773912bSVasanthakumar Thiagarajan ath_gen_timer_stop(sc->sc_ah, btinfo->no_stomp_timer); 297*1773912bSVasanthakumar Thiagarajan 298*1773912bSVasanthakumar Thiagarajan btinfo->hw_timer_enabled = false; 299*1773912bSVasanthakumar Thiagarajan } 300*1773912bSVasanthakumar Thiagarajan 301*1773912bSVasanthakumar Thiagarajan /* 302*1773912bSVasanthakumar Thiagarajan * (Re)start btcoex timers 303*1773912bSVasanthakumar Thiagarajan */ 304*1773912bSVasanthakumar Thiagarajan void ath_btcoex_timer_resume(struct ath_softc *sc, 305*1773912bSVasanthakumar Thiagarajan struct ath_btcoex_info *btinfo) 306*1773912bSVasanthakumar Thiagarajan { 307*1773912bSVasanthakumar Thiagarajan 308*1773912bSVasanthakumar Thiagarajan DPRINTF(sc, ATH_DBG_BTCOEX, "Starting btcoex timers"); 309*1773912bSVasanthakumar Thiagarajan 310*1773912bSVasanthakumar Thiagarajan /* make sure duty cycle timer is also stopped when resuming */ 311*1773912bSVasanthakumar Thiagarajan if (btinfo->hw_timer_enabled) 312*1773912bSVasanthakumar Thiagarajan ath_gen_timer_stop(sc->sc_ah, btinfo->no_stomp_timer); 313*1773912bSVasanthakumar Thiagarajan 314*1773912bSVasanthakumar Thiagarajan btinfo->bt_priority_cnt = 0; 315*1773912bSVasanthakumar Thiagarajan btinfo->bt_priority_time = jiffies; 316*1773912bSVasanthakumar Thiagarajan sc->sc_flags &= ~SC_OP_BT_PRIORITY_DETECTED; 317*1773912bSVasanthakumar Thiagarajan 318*1773912bSVasanthakumar Thiagarajan mod_timer(&btinfo->period_timer, jiffies); 319*1773912bSVasanthakumar Thiagarajan } 320