aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath9k/btcoex.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/btcoex.c')
-rw-r--r--drivers/net/wireless/ath/ath9k/btcoex.c383
1 files changed, 135 insertions, 248 deletions
diff --git a/drivers/net/wireless/ath/ath9k/btcoex.c b/drivers/net/wireless/ath/ath9k/btcoex.c
index 55f607b7699e..fb4ac15f3b93 100644
--- a/drivers/net/wireless/ath/ath9k/btcoex.c
+++ b/drivers/net/wireless/ath/ath9k/btcoex.c
@@ -14,10 +14,26 @@
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */ 15 */
16 16
17#include "ath9k.h" 17#include "hw.h"
18 18
19static const struct ath_btcoex_config ath_bt_config = { 0, true, true, 19enum ath_bt_mode {
20 ATH_BT_COEX_MODE_SLOTTED, true, true, 2, 5, true }; 20 ATH_BT_COEX_MODE_LEGACY, /* legacy rx_clear mode */
21 ATH_BT_COEX_MODE_UNSLOTTED, /* untimed/unslotted mode */
22 ATH_BT_COEX_MODE_SLOTTED, /* slotted mode */
23 ATH_BT_COEX_MODE_DISALBED, /* coexistence disabled */
24};
25
26struct ath_btcoex_config {
27 u8 bt_time_extend;
28 bool bt_txstate_extend;
29 bool bt_txframe_extend;
30 enum ath_bt_mode bt_mode; /* coexistence mode */
31 bool bt_quiet_collision;
32 bool bt_rxclear_polarity; /* invert rx_clear as WLAN_ACTIVE*/
33 u8 bt_priority_time;
34 u8 bt_first_slot_time;
35 bool bt_hold_rx_clear;
36};
21 37
22static const u16 ath_subsysid_tbl[] = { 38static const u16 ath_subsysid_tbl[] = {
23 AR9280_COEX2WIRE_SUBSYSID, 39 AR9280_COEX2WIRE_SUBSYSID,
@@ -29,141 +45,38 @@ static const u16 ath_subsysid_tbl[] = {
29 * Checks the subsystem id of the device to see if it 45 * Checks the subsystem id of the device to see if it
30 * supports btcoex 46 * supports btcoex
31 */ 47 */
32bool ath_btcoex_supported(u16 subsysid) 48bool ath9k_hw_btcoex_supported(struct ath_hw *ah)
33{ 49{
34 int i; 50 int i;
35 51
36 if (!subsysid) 52 if (!ah->hw_version.subsysid)
37 return false; 53 return false;
38 54
39 for (i = 0; i < ARRAY_SIZE(ath_subsysid_tbl); i++) 55 for (i = 0; i < ARRAY_SIZE(ath_subsysid_tbl); i++)
40 if (subsysid == ath_subsysid_tbl[i]) 56 if (ah->hw_version.subsysid == ath_subsysid_tbl[i])
41 return true; 57 return true;
42 58
43 return false; 59 return false;
44} 60}
45 61
46/* 62void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum)
47 * Detects if there is any priority bt traffic
48 */
49static void ath_detect_bt_priority(struct ath_softc *sc)
50{
51 struct ath_btcoex_info *btinfo = &sc->btcoex_info;
52
53 if (ath9k_hw_gpio_get(sc->sc_ah, btinfo->btpriority_gpio))
54 btinfo->bt_priority_cnt++;
55
56 if (time_after(jiffies, btinfo->bt_priority_time +
57 msecs_to_jiffies(ATH_BT_PRIORITY_TIME_THRESHOLD))) {
58 if (btinfo->bt_priority_cnt >= ATH_BT_CNT_THRESHOLD) {
59 DPRINTF(sc, ATH_DBG_BTCOEX,
60 "BT priority traffic detected");
61 sc->sc_flags |= SC_OP_BT_PRIORITY_DETECTED;
62 } else {
63 sc->sc_flags &= ~SC_OP_BT_PRIORITY_DETECTED;
64 }
65
66 btinfo->bt_priority_cnt = 0;
67 btinfo->bt_priority_time = jiffies;
68 }
69}
70
71/*
72 * Configures appropriate weight based on stomp type.
73 */
74static void ath_btcoex_bt_stomp(struct ath_softc *sc,
75 struct ath_btcoex_info *btinfo,
76 int stomp_type)
77{
78
79 switch (stomp_type) {
80 case ATH_BTCOEX_STOMP_ALL:
81 ath_btcoex_set_weight(btinfo, AR_BT_COEX_WGHT,
82 AR_STOMP_ALL_WLAN_WGHT);
83 break;
84 case ATH_BTCOEX_STOMP_LOW:
85 ath_btcoex_set_weight(btinfo, AR_BT_COEX_WGHT,
86 AR_STOMP_LOW_WLAN_WGHT);
87 break;
88 case ATH_BTCOEX_STOMP_NONE:
89 ath_btcoex_set_weight(btinfo, AR_BT_COEX_WGHT,
90 AR_STOMP_NONE_WLAN_WGHT);
91 break;
92 default:
93 DPRINTF(sc, ATH_DBG_BTCOEX, "Invalid Stomptype\n");
94 break;
95 }
96
97 ath9k_hw_btcoex_enable(sc->sc_ah);
98}
99
100/*
101 * This is the master bt coex timer which runs for every
102 * 45ms, bt traffic will be given priority during 55% of this
103 * period while wlan gets remaining 45%
104 */
105
106static void ath_btcoex_period_timer(unsigned long data)
107{
108 struct ath_softc *sc = (struct ath_softc *) data;
109 struct ath_btcoex_info *btinfo = &sc->btcoex_info;
110
111 ath_detect_bt_priority(sc);
112
113 spin_lock_bh(&btinfo->btcoex_lock);
114
115 ath_btcoex_bt_stomp(sc, btinfo, btinfo->bt_stomp_type);
116
117 spin_unlock_bh(&btinfo->btcoex_lock);
118
119 if (btinfo->btcoex_period != btinfo->btcoex_no_stomp) {
120 if (btinfo->hw_timer_enabled)
121 ath_gen_timer_stop(sc->sc_ah, btinfo->no_stomp_timer);
122
123 ath_gen_timer_start(sc->sc_ah,
124 btinfo->no_stomp_timer,
125 (ath9k_hw_gettsf32(sc->sc_ah) +
126 btinfo->btcoex_no_stomp),
127 btinfo->btcoex_no_stomp * 10);
128 btinfo->hw_timer_enabled = true;
129 }
130
131 mod_timer(&btinfo->period_timer, jiffies +
132 msecs_to_jiffies(ATH_BTCOEX_DEF_BT_PERIOD));
133}
134
135/*
136 * Generic tsf based hw timer which configures weight
137 * registers to time slice between wlan and bt traffic
138 */
139
140static void ath_btcoex_no_stomp_timer(void *arg)
141{
142 struct ath_softc *sc = (struct ath_softc *)arg;
143 struct ath_btcoex_info *btinfo = &sc->btcoex_info;
144
145 DPRINTF(sc, ATH_DBG_BTCOEX, "no stomp timer running \n");
146
147 spin_lock_bh(&btinfo->btcoex_lock);
148
149 if (btinfo->bt_stomp_type == ATH_BTCOEX_STOMP_LOW)
150 ath_btcoex_bt_stomp(sc, btinfo, ATH_BTCOEX_STOMP_NONE);
151 else if (btinfo->bt_stomp_type == ATH_BTCOEX_STOMP_ALL)
152 ath_btcoex_bt_stomp(sc, btinfo, ATH_BTCOEX_STOMP_LOW);
153
154 spin_unlock_bh(&btinfo->btcoex_lock);
155}
156
157static int ath_init_btcoex_info(struct ath_hw *hw,
158 struct ath_btcoex_info *btcoex_info)
159{ 63{
64 struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
65 const struct ath_btcoex_config ath_bt_config = {
66 .bt_time_extend = 0,
67 .bt_txstate_extend = true,
68 .bt_txframe_extend = true,
69 .bt_mode = ATH_BT_COEX_MODE_SLOTTED,
70 .bt_quiet_collision = true,
71 .bt_rxclear_polarity = true,
72 .bt_priority_time = 2,
73 .bt_first_slot_time = 5,
74 .bt_hold_rx_clear = true,
75 };
160 u32 i; 76 u32 i;
161 int qnum;
162 77
163 qnum = ath_tx_get_qnum(hw->ah_sc, ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_BE); 78 btcoex_hw->bt_coex_mode =
164 79 (btcoex_hw->bt_coex_mode & AR_BT_QCU_THRESH) |
165 btcoex_info->bt_coex_mode =
166 (btcoex_info->bt_coex_mode & AR_BT_QCU_THRESH) |
167 SM(ath_bt_config.bt_time_extend, AR_BT_TIME_EXTEND) | 80 SM(ath_bt_config.bt_time_extend, AR_BT_TIME_EXTEND) |
168 SM(ath_bt_config.bt_txstate_extend, AR_BT_TXSTATE_EXTEND) | 81 SM(ath_bt_config.bt_txstate_extend, AR_BT_TXSTATE_EXTEND) |
169 SM(ath_bt_config.bt_txframe_extend, AR_BT_TX_FRAME_EXTEND) | 82 SM(ath_bt_config.bt_txframe_extend, AR_BT_TX_FRAME_EXTEND) |
@@ -174,167 +87,141 @@ static int ath_init_btcoex_info(struct ath_hw *hw,
174 SM(ath_bt_config.bt_first_slot_time, AR_BT_FIRST_SLOT_TIME) | 87 SM(ath_bt_config.bt_first_slot_time, AR_BT_FIRST_SLOT_TIME) |
175 SM(qnum, AR_BT_QCU_THRESH); 88 SM(qnum, AR_BT_QCU_THRESH);
176 89
177 btcoex_info->bt_coex_mode2 = 90 btcoex_hw->bt_coex_mode2 =
178 SM(ath_bt_config.bt_hold_rx_clear, AR_BT_HOLD_RX_CLEAR) | 91 SM(ath_bt_config.bt_hold_rx_clear, AR_BT_HOLD_RX_CLEAR) |
179 SM(ATH_BTCOEX_BMISS_THRESH, AR_BT_BCN_MISS_THRESH) | 92 SM(ATH_BTCOEX_BMISS_THRESH, AR_BT_BCN_MISS_THRESH) |
180 AR_BT_DISABLE_BT_ANT; 93 AR_BT_DISABLE_BT_ANT;
181 94
182 btcoex_info->bt_stomp_type = ATH_BTCOEX_STOMP_LOW; 95 for (i = 0; i < 32; i++)
96 ah->hw_gen_timers.gen_timer_index[(debruijn32 << i) >> 27] = i;
97}
98EXPORT_SYMBOL(ath9k_hw_init_btcoex_hw);
183 99
184 btcoex_info->btcoex_period = ATH_BTCOEX_DEF_BT_PERIOD * 1000; 100void ath9k_hw_btcoex_init_2wire(struct ath_hw *ah)
101{
102 struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
185 103
186 btcoex_info->btcoex_no_stomp = (100 - ATH_BTCOEX_DEF_DUTY_CYCLE) * 104 /* connect bt_active to baseband */
187 btcoex_info->btcoex_period / 100; 105 REG_CLR_BIT(ah, AR_GPIO_INPUT_EN_VAL,
106 (AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_DEF |
107 AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_DEF));
188 108
189 for (i = 0; i < 32; i++) 109 REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL,
190 hw->hw_gen_timers.gen_timer_index[(debruijn32 << i) >> 27] = i; 110 AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB);
191 111
192 setup_timer(&btcoex_info->period_timer, ath_btcoex_period_timer, 112 /* Set input mux for bt_active to gpio pin */
193 (unsigned long) hw->ah_sc); 113 REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1,
114 AR_GPIO_INPUT_MUX1_BT_ACTIVE,
115 btcoex_hw->btactive_gpio);
194 116
195 btcoex_info->no_stomp_timer = ath_gen_timer_alloc(hw, 117 /* Configure the desired gpio port for input */
196 ath_btcoex_no_stomp_timer, 118 ath9k_hw_cfg_gpio_input(ah, btcoex_hw->btactive_gpio);
197 ath_btcoex_no_stomp_timer, 119}
198 (void *)hw->ah_sc, AR_FIRST_NDP_TIMER); 120EXPORT_SYMBOL(ath9k_hw_btcoex_init_2wire);
121
122void ath9k_hw_btcoex_init_3wire(struct ath_hw *ah)
123{
124 struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
199 125
200 if (btcoex_info->no_stomp_timer == NULL) 126 /* btcoex 3-wire */
201 return -ENOMEM; 127 REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL,
128 (AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_BB |
129 AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB));
202 130
203 spin_lock_init(&btcoex_info->btcoex_lock); 131 /* Set input mux for bt_prority_async and
132 * bt_active_async to GPIO pins */
133 REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1,
134 AR_GPIO_INPUT_MUX1_BT_ACTIVE,
135 btcoex_hw->btactive_gpio);
204 136
205 return 0; 137 REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1,
138 AR_GPIO_INPUT_MUX1_BT_PRIORITY,
139 btcoex_hw->btpriority_gpio);
140
141 /* Configure the desired GPIO ports for input */
142
143 ath9k_hw_cfg_gpio_input(ah, btcoex_hw->btactive_gpio);
144 ath9k_hw_cfg_gpio_input(ah, btcoex_hw->btpriority_gpio);
206} 145}
146EXPORT_SYMBOL(ath9k_hw_btcoex_init_3wire);
207 147
208int ath9k_hw_btcoex_init(struct ath_hw *ah) 148static void ath9k_hw_btcoex_enable_2wire(struct ath_hw *ah)
209{ 149{
210 struct ath_btcoex_info *btcoex_info = &ah->ah_sc->btcoex_info; 150 struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
211 int ret = 0;
212
213 if (btcoex_info->btcoex_scheme == ATH_BTCOEX_CFG_2WIRE) {
214 /* connect bt_active to baseband */
215 REG_CLR_BIT(ah, AR_GPIO_INPUT_EN_VAL,
216 (AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_DEF |
217 AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_DEF));
218
219 REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL,
220 AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB);
221
222 /* Set input mux for bt_active to gpio pin */
223 REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1,
224 AR_GPIO_INPUT_MUX1_BT_ACTIVE,
225 btcoex_info->btactive_gpio);
226
227 /* Configure the desired gpio port for input */
228 ath9k_hw_cfg_gpio_input(ah, btcoex_info->btactive_gpio);
229 } else {
230 /* btcoex 3-wire */
231 REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL,
232 (AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_BB |
233 AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB));
234
235 /* Set input mux for bt_prority_async and
236 * bt_active_async to GPIO pins */
237 REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1,
238 AR_GPIO_INPUT_MUX1_BT_ACTIVE,
239 btcoex_info->btactive_gpio);
240
241 REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1,
242 AR_GPIO_INPUT_MUX1_BT_PRIORITY,
243 btcoex_info->btpriority_gpio);
244
245 /* Configure the desired GPIO ports for input */
246
247 ath9k_hw_cfg_gpio_input(ah, btcoex_info->btactive_gpio);
248 ath9k_hw_cfg_gpio_input(ah, btcoex_info->btpriority_gpio);
249
250 ret = ath_init_btcoex_info(ah, btcoex_info);
251 }
252 151
253 return ret; 152 /* Configure the desired GPIO port for TX_FRAME output */
153 ath9k_hw_cfg_output(ah, btcoex_hw->wlanactive_gpio,
154 AR_GPIO_OUTPUT_MUX_AS_TX_FRAME);
254} 155}
255 156
256void ath9k_hw_btcoex_enable(struct ath_hw *ah) 157void ath9k_hw_btcoex_set_weight(struct ath_hw *ah,
158 u32 bt_weight,
159 u32 wlan_weight)
257{ 160{
258 struct ath_btcoex_info *btcoex_info = &ah->ah_sc->btcoex_info; 161 struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
259
260 if (btcoex_info->btcoex_scheme == ATH_BTCOEX_CFG_2WIRE) {
261 /* Configure the desired GPIO port for TX_FRAME output */
262 ath9k_hw_cfg_output(ah, btcoex_info->wlanactive_gpio,
263 AR_GPIO_OUTPUT_MUX_AS_TX_FRAME);
264 } else {
265 /*
266 * Program coex mode and weight registers to
267 * enable coex 3-wire
268 */
269 REG_WRITE(ah, AR_BT_COEX_MODE, btcoex_info->bt_coex_mode);
270 REG_WRITE(ah, AR_BT_COEX_WEIGHT, btcoex_info->bt_coex_weights);
271 REG_WRITE(ah, AR_BT_COEX_MODE2, btcoex_info->bt_coex_mode2);
272
273 REG_RMW_FIELD(ah, AR_QUIET1,
274 AR_QUIET1_QUIET_ACK_CTS_ENABLE, 1);
275 REG_RMW_FIELD(ah, AR_PCU_MISC,
276 AR_PCU_BT_ANT_PREVENT_RX, 0);
277
278 ath9k_hw_cfg_output(ah, btcoex_info->wlanactive_gpio,
279 AR_GPIO_OUTPUT_MUX_AS_RX_CLEAR_EXTERNAL);
280 }
281 162
282 REG_RMW(ah, AR_GPIO_PDPU, 163 btcoex_hw->bt_coex_weights = SM(bt_weight, AR_BTCOEX_BT_WGHT) |
283 (0x2 << (btcoex_info->btactive_gpio * 2)), 164 SM(wlan_weight, AR_BTCOEX_WL_WGHT);
284 (0x3 << (btcoex_info->btactive_gpio * 2)));
285
286 ah->ah_sc->sc_flags |= SC_OP_BTCOEX_ENABLED;
287} 165}
166EXPORT_SYMBOL(ath9k_hw_btcoex_set_weight);
288 167
289void ath9k_hw_btcoex_disable(struct ath_hw *ah) 168static void ath9k_hw_btcoex_enable_3wire(struct ath_hw *ah)
290{ 169{
291 struct ath_btcoex_info *btcoex_info = &ah->ah_sc->btcoex_info; 170 struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
292 171
293 ath9k_hw_set_gpio(ah, btcoex_info->wlanactive_gpio, 0); 172 /*
173 * Program coex mode and weight registers to
174 * enable coex 3-wire
175 */
176 REG_WRITE(ah, AR_BT_COEX_MODE, btcoex_hw->bt_coex_mode);
177 REG_WRITE(ah, AR_BT_COEX_WEIGHT, btcoex_hw->bt_coex_weights);
178 REG_WRITE(ah, AR_BT_COEX_MODE2, btcoex_hw->bt_coex_mode2);
294 179
295 ath9k_hw_cfg_output(ah, btcoex_info->wlanactive_gpio, 180 REG_RMW_FIELD(ah, AR_QUIET1, AR_QUIET1_QUIET_ACK_CTS_ENABLE, 1);
296 AR_GPIO_OUTPUT_MUX_AS_OUTPUT); 181 REG_RMW_FIELD(ah, AR_PCU_MISC, AR_PCU_BT_ANT_PREVENT_RX, 0);
297 182
298 if (btcoex_info->btcoex_scheme == ATH_BTCOEX_CFG_3WIRE) { 183 ath9k_hw_cfg_output(ah, btcoex_hw->wlanactive_gpio,
299 REG_WRITE(ah, AR_BT_COEX_MODE, AR_BT_QUIET | AR_BT_MODE); 184 AR_GPIO_OUTPUT_MUX_AS_RX_CLEAR_EXTERNAL);
300 REG_WRITE(ah, AR_BT_COEX_WEIGHT, 0);
301 REG_WRITE(ah, AR_BT_COEX_MODE2, 0);
302 }
303
304 ah->ah_sc->sc_flags &= ~SC_OP_BTCOEX_ENABLED;
305} 185}
306 186
307/* 187void ath9k_hw_btcoex_enable(struct ath_hw *ah)
308 * Pause btcoex timer and bt duty cycle timer
309 */
310void ath_btcoex_timer_pause(struct ath_softc *sc,
311 struct ath_btcoex_info *btinfo)
312{ 188{
189 struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
313 190
314 del_timer_sync(&btinfo->period_timer); 191 switch (btcoex_hw->scheme) {
192 case ATH_BTCOEX_CFG_NONE:
193 break;
194 case ATH_BTCOEX_CFG_2WIRE:
195 ath9k_hw_btcoex_enable_2wire(ah);
196 break;
197 case ATH_BTCOEX_CFG_3WIRE:
198 ath9k_hw_btcoex_enable_3wire(ah);
199 break;
200 }
315 201
316 if (btinfo->hw_timer_enabled) 202 REG_RMW(ah, AR_GPIO_PDPU,
317 ath_gen_timer_stop(sc->sc_ah, btinfo->no_stomp_timer); 203 (0x2 << (btcoex_hw->btactive_gpio * 2)),
204 (0x3 << (btcoex_hw->btactive_gpio * 2)));
318 205
319 btinfo->hw_timer_enabled = false; 206 ah->btcoex_hw.enabled = true;
320} 207}
208EXPORT_SYMBOL(ath9k_hw_btcoex_enable);
321 209
322/* 210void ath9k_hw_btcoex_disable(struct ath_hw *ah)
323 * (Re)start btcoex timers
324 */
325void ath_btcoex_timer_resume(struct ath_softc *sc,
326 struct ath_btcoex_info *btinfo)
327{ 211{
212 struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
328 213
329 DPRINTF(sc, ATH_DBG_BTCOEX, "Starting btcoex timers"); 214 ath9k_hw_set_gpio(ah, btcoex_hw->wlanactive_gpio, 0);
330 215
331 /* make sure duty cycle timer is also stopped when resuming */ 216 ath9k_hw_cfg_output(ah, btcoex_hw->wlanactive_gpio,
332 if (btinfo->hw_timer_enabled) 217 AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
333 ath_gen_timer_stop(sc->sc_ah, btinfo->no_stomp_timer);
334 218
335 btinfo->bt_priority_cnt = 0; 219 if (btcoex_hw->scheme == ATH_BTCOEX_CFG_3WIRE) {
336 btinfo->bt_priority_time = jiffies; 220 REG_WRITE(ah, AR_BT_COEX_MODE, AR_BT_QUIET | AR_BT_MODE);
337 sc->sc_flags &= ~SC_OP_BT_PRIORITY_DETECTED; 221 REG_WRITE(ah, AR_BT_COEX_WEIGHT, 0);
222 REG_WRITE(ah, AR_BT_COEX_MODE2, 0);
223 }
338 224
339 mod_timer(&btinfo->period_timer, jiffies); 225 ah->btcoex_hw.enabled = false;
340} 226}
227EXPORT_SYMBOL(ath9k_hw_btcoex_disable);