htc_drv_gpio.c revision 21cb987914cb5334af78378141efed77505ea987
1#include "htc.h" 2 3/******************/ 4/* BTCOEX */ 5/******************/ 6 7/* 8 * Detects if there is any priority bt traffic 9 */ 10static void ath_detect_bt_priority(struct ath9k_htc_priv *priv) 11{ 12 struct ath_btcoex *btcoex = &priv->btcoex; 13 struct ath_hw *ah = priv->ah; 14 15 if (ath9k_hw_gpio_get(ah, ah->btcoex_hw.btpriority_gpio)) 16 btcoex->bt_priority_cnt++; 17 18 if (time_after(jiffies, btcoex->bt_priority_time + 19 msecs_to_jiffies(ATH_BT_PRIORITY_TIME_THRESHOLD))) { 20 priv->op_flags &= ~(OP_BT_PRIORITY_DETECTED | OP_BT_SCAN); 21 /* Detect if colocated bt started scanning */ 22 if (btcoex->bt_priority_cnt >= ATH_BT_CNT_SCAN_THRESHOLD) { 23 ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX, 24 "BT scan detected"); 25 priv->op_flags |= (OP_BT_SCAN | 26 OP_BT_PRIORITY_DETECTED); 27 } else if (btcoex->bt_priority_cnt >= ATH_BT_CNT_THRESHOLD) { 28 ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX, 29 "BT priority traffic detected"); 30 priv->op_flags |= OP_BT_PRIORITY_DETECTED; 31 } 32 33 btcoex->bt_priority_cnt = 0; 34 btcoex->bt_priority_time = jiffies; 35 } 36} 37 38/* 39 * This is the master bt coex work which runs for every 40 * 45ms, bt traffic will be given priority during 55% of this 41 * period while wlan gets remaining 45% 42 */ 43static void ath_btcoex_period_work(struct work_struct *work) 44{ 45 struct ath9k_htc_priv *priv = container_of(work, struct ath9k_htc_priv, 46 coex_period_work.work); 47 struct ath_btcoex *btcoex = &priv->btcoex; 48 struct ath_common *common = ath9k_hw_common(priv->ah); 49 u32 timer_period; 50 bool is_btscan; 51 int ret; 52 u8 cmd_rsp, aggr; 53 54 ath_detect_bt_priority(priv); 55 56 is_btscan = !!(priv->op_flags & OP_BT_SCAN); 57 58 aggr = priv->op_flags & OP_BT_PRIORITY_DETECTED; 59 60 WMI_CMD_BUF(WMI_AGGR_LIMIT_CMD, &aggr); 61 62 ath9k_cmn_btcoex_bt_stomp(common, is_btscan ? ATH_BTCOEX_STOMP_ALL : 63 btcoex->bt_stomp_type); 64 65 timer_period = is_btscan ? btcoex->btscan_no_stomp : 66 btcoex->btcoex_no_stomp; 67 ieee80211_queue_delayed_work(priv->hw, &priv->duty_cycle_work, 68 msecs_to_jiffies(timer_period)); 69 ieee80211_queue_delayed_work(priv->hw, &priv->coex_period_work, 70 msecs_to_jiffies(btcoex->btcoex_period)); 71} 72 73/* 74 * Work to time slice between wlan and bt traffic and 75 * configure weight registers 76 */ 77static void ath_btcoex_duty_cycle_work(struct work_struct *work) 78{ 79 struct ath9k_htc_priv *priv = container_of(work, struct ath9k_htc_priv, 80 duty_cycle_work.work); 81 struct ath_hw *ah = priv->ah; 82 struct ath_btcoex *btcoex = &priv->btcoex; 83 struct ath_common *common = ath9k_hw_common(ah); 84 bool is_btscan = priv->op_flags & OP_BT_SCAN; 85 86 ath_print(common, ATH_DBG_BTCOEX, 87 "time slice work for bt and wlan\n"); 88 89 if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW || is_btscan) 90 ath9k_cmn_btcoex_bt_stomp(common, ATH_BTCOEX_STOMP_NONE); 91 else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL) 92 ath9k_cmn_btcoex_bt_stomp(common, ATH_BTCOEX_STOMP_LOW); 93} 94 95void ath_htc_init_btcoex_work(struct ath9k_htc_priv *priv) 96{ 97 struct ath_btcoex *btcoex = &priv->btcoex; 98 99 btcoex->btcoex_period = ATH_BTCOEX_DEF_BT_PERIOD; 100 btcoex->btcoex_no_stomp = (100 - ATH_BTCOEX_DEF_DUTY_CYCLE) * 101 btcoex->btcoex_period / 100; 102 btcoex->btscan_no_stomp = (100 - ATH_BTCOEX_BTSCAN_DUTY_CYCLE) * 103 btcoex->btcoex_period / 100; 104 INIT_DELAYED_WORK(&priv->coex_period_work, ath_btcoex_period_work); 105 INIT_DELAYED_WORK(&priv->duty_cycle_work, ath_btcoex_duty_cycle_work); 106} 107 108/* 109 * (Re)start btcoex work 110 */ 111 112void ath_htc_resume_btcoex_work(struct ath9k_htc_priv *priv) 113{ 114 struct ath_btcoex *btcoex = &priv->btcoex; 115 struct ath_hw *ah = priv->ah; 116 117 ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX, 118 "Starting btcoex work"); 119 120 btcoex->bt_priority_cnt = 0; 121 btcoex->bt_priority_time = jiffies; 122 priv->op_flags &= ~(OP_BT_PRIORITY_DETECTED | OP_BT_SCAN); 123 ieee80211_queue_delayed_work(priv->hw, &priv->coex_period_work, 0); 124} 125 126 127/* 128 * Cancel btcoex and bt duty cycle work. 129 */ 130void ath_htc_cancel_btcoex_work(struct ath9k_htc_priv *priv) 131{ 132 cancel_delayed_work_sync(&priv->coex_period_work); 133 cancel_delayed_work_sync(&priv->duty_cycle_work); 134} 135