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.c132
1 files changed, 105 insertions, 27 deletions
diff --git a/drivers/net/wireless/ath/ath9k/btcoex.c b/drivers/net/wireless/ath/ath9k/btcoex.c
index fb4ac15f3b93..41ce0b139886 100644
--- a/drivers/net/wireless/ath/ath9k/btcoex.c
+++ b/drivers/net/wireless/ath/ath9k/btcoex.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2009 Atheros Communications Inc. 2 * Copyright (c) 2009-2011 Atheros Communications Inc.
3 * 3 *
4 * Permission to use, copy, modify, and/or distribute this software for any 4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above 5 * purpose with or without fee is hereby granted, provided that the above
@@ -35,29 +35,6 @@ struct ath_btcoex_config {
35 bool bt_hold_rx_clear; 35 bool bt_hold_rx_clear;
36}; 36};
37 37
38static const u16 ath_subsysid_tbl[] = {
39 AR9280_COEX2WIRE_SUBSYSID,
40 AT9285_COEX3WIRE_SA_SUBSYSID,
41 AT9285_COEX3WIRE_DA_SUBSYSID
42};
43
44/*
45 * Checks the subsystem id of the device to see if it
46 * supports btcoex
47 */
48bool ath9k_hw_btcoex_supported(struct ath_hw *ah)
49{
50 int i;
51
52 if (!ah->hw_version.subsysid)
53 return false;
54
55 for (i = 0; i < ARRAY_SIZE(ath_subsysid_tbl); i++)
56 if (ah->hw_version.subsysid == ath_subsysid_tbl[i])
57 return true;
58
59 return false;
60}
61 38
62void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum) 39void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum)
63{ 40{
@@ -74,6 +51,10 @@ void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum)
74 .bt_hold_rx_clear = true, 51 .bt_hold_rx_clear = true,
75 }; 52 };
76 u32 i; 53 u32 i;
54 bool rxclear_polarity = ath_bt_config.bt_rxclear_polarity;
55
56 if (AR_SREV_9300_20_OR_LATER(ah))
57 rxclear_polarity = !ath_bt_config.bt_rxclear_polarity;
77 58
78 btcoex_hw->bt_coex_mode = 59 btcoex_hw->bt_coex_mode =
79 (btcoex_hw->bt_coex_mode & AR_BT_QCU_THRESH) | 60 (btcoex_hw->bt_coex_mode & AR_BT_QCU_THRESH) |
@@ -82,7 +63,7 @@ void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum)
82 SM(ath_bt_config.bt_txframe_extend, AR_BT_TX_FRAME_EXTEND) | 63 SM(ath_bt_config.bt_txframe_extend, AR_BT_TX_FRAME_EXTEND) |
83 SM(ath_bt_config.bt_mode, AR_BT_MODE) | 64 SM(ath_bt_config.bt_mode, AR_BT_MODE) |
84 SM(ath_bt_config.bt_quiet_collision, AR_BT_QUIET) | 65 SM(ath_bt_config.bt_quiet_collision, AR_BT_QUIET) |
85 SM(ath_bt_config.bt_rxclear_polarity, AR_BT_RX_CLEAR_POLARITY) | 66 SM(rxclear_polarity, AR_BT_RX_CLEAR_POLARITY) |
86 SM(ath_bt_config.bt_priority_time, AR_BT_PRIORITY_TIME) | 67 SM(ath_bt_config.bt_priority_time, AR_BT_PRIORITY_TIME) |
87 SM(ath_bt_config.bt_first_slot_time, AR_BT_FIRST_SLOT_TIME) | 68 SM(ath_bt_config.bt_first_slot_time, AR_BT_FIRST_SLOT_TIME) |
88 SM(qnum, AR_BT_QCU_THRESH); 69 SM(qnum, AR_BT_QCU_THRESH);
@@ -165,18 +146,39 @@ void ath9k_hw_btcoex_set_weight(struct ath_hw *ah,
165} 146}
166EXPORT_SYMBOL(ath9k_hw_btcoex_set_weight); 147EXPORT_SYMBOL(ath9k_hw_btcoex_set_weight);
167 148
149
168static void ath9k_hw_btcoex_enable_3wire(struct ath_hw *ah) 150static void ath9k_hw_btcoex_enable_3wire(struct ath_hw *ah)
169{ 151{
170 struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw; 152 struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
153 u32 val;
171 154
172 /* 155 /*
173 * Program coex mode and weight registers to 156 * Program coex mode and weight registers to
174 * enable coex 3-wire 157 * enable coex 3-wire
175 */ 158 */
176 REG_WRITE(ah, AR_BT_COEX_MODE, btcoex_hw->bt_coex_mode); 159 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); 160 REG_WRITE(ah, AR_BT_COEX_MODE2, btcoex_hw->bt_coex_mode2);
179 161
162
163 if (AR_SREV_9300_20_OR_LATER(ah)) {
164 REG_WRITE(ah, AR_BT_COEX_WL_WEIGHTS0, ah->bt_coex_wlan_weight[0]);
165 REG_WRITE(ah, AR_BT_COEX_WL_WEIGHTS1, ah->bt_coex_wlan_weight[1]);
166 REG_WRITE(ah, AR_BT_COEX_BT_WEIGHTS0, ah->bt_coex_bt_weight[0]);
167 REG_WRITE(ah, AR_BT_COEX_BT_WEIGHTS1, ah->bt_coex_bt_weight[1]);
168 REG_WRITE(ah, AR_BT_COEX_BT_WEIGHTS2, ah->bt_coex_bt_weight[2]);
169 REG_WRITE(ah, AR_BT_COEX_BT_WEIGHTS3, ah->bt_coex_bt_weight[3]);
170
171 } else
172 REG_WRITE(ah, AR_BT_COEX_WEIGHT, btcoex_hw->bt_coex_weights);
173
174
175
176 if (AR_SREV_9271(ah)) {
177 val = REG_READ(ah, 0x50040);
178 val &= 0xFFFFFEFF;
179 REG_WRITE(ah, 0x50040, val);
180 }
181
180 REG_RMW_FIELD(ah, AR_QUIET1, AR_QUIET1_QUIET_ACK_CTS_ENABLE, 1); 182 REG_RMW_FIELD(ah, AR_QUIET1, AR_QUIET1_QUIET_ACK_CTS_ENABLE, 1);
181 REG_RMW_FIELD(ah, AR_PCU_MISC, AR_PCU_BT_ANT_PREVENT_RX, 0); 183 REG_RMW_FIELD(ah, AR_PCU_MISC, AR_PCU_BT_ANT_PREVENT_RX, 0);
182 184
@@ -218,10 +220,86 @@ void ath9k_hw_btcoex_disable(struct ath_hw *ah)
218 220
219 if (btcoex_hw->scheme == ATH_BTCOEX_CFG_3WIRE) { 221 if (btcoex_hw->scheme == ATH_BTCOEX_CFG_3WIRE) {
220 REG_WRITE(ah, AR_BT_COEX_MODE, AR_BT_QUIET | AR_BT_MODE); 222 REG_WRITE(ah, AR_BT_COEX_MODE, AR_BT_QUIET | AR_BT_MODE);
221 REG_WRITE(ah, AR_BT_COEX_WEIGHT, 0);
222 REG_WRITE(ah, AR_BT_COEX_MODE2, 0); 223 REG_WRITE(ah, AR_BT_COEX_MODE2, 0);
224
225 if (AR_SREV_9300_20_OR_LATER(ah)) {
226 REG_WRITE(ah, AR_BT_COEX_WL_WEIGHTS0, 0);
227 REG_WRITE(ah, AR_BT_COEX_WL_WEIGHTS1, 0);
228 REG_WRITE(ah, AR_BT_COEX_BT_WEIGHTS0, 0);
229 REG_WRITE(ah, AR_BT_COEX_BT_WEIGHTS1, 0);
230 REG_WRITE(ah, AR_BT_COEX_BT_WEIGHTS2, 0);
231 REG_WRITE(ah, AR_BT_COEX_BT_WEIGHTS3, 0);
232 } else
233 REG_WRITE(ah, AR_BT_COEX_WEIGHT, 0);
234
223 } 235 }
224 236
225 ah->btcoex_hw.enabled = false; 237 ah->btcoex_hw.enabled = false;
226} 238}
227EXPORT_SYMBOL(ath9k_hw_btcoex_disable); 239EXPORT_SYMBOL(ath9k_hw_btcoex_disable);
240
241static void ar9003_btcoex_bt_stomp(struct ath_hw *ah,
242 enum ath_stomp_type stomp_type)
243{
244 ah->bt_coex_bt_weight[0] = AR9300_BT_WGHT;
245 ah->bt_coex_bt_weight[1] = AR9300_BT_WGHT;
246 ah->bt_coex_bt_weight[2] = AR9300_BT_WGHT;
247 ah->bt_coex_bt_weight[3] = AR9300_BT_WGHT;
248
249
250 switch (stomp_type) {
251 case ATH_BTCOEX_STOMP_ALL:
252 ah->bt_coex_wlan_weight[0] = AR9300_STOMP_ALL_WLAN_WGHT0;
253 ah->bt_coex_wlan_weight[1] = AR9300_STOMP_ALL_WLAN_WGHT1;
254 break;
255 case ATH_BTCOEX_STOMP_LOW:
256 ah->bt_coex_wlan_weight[0] = AR9300_STOMP_LOW_WLAN_WGHT0;
257 ah->bt_coex_wlan_weight[1] = AR9300_STOMP_LOW_WLAN_WGHT1;
258 break;
259 case ATH_BTCOEX_STOMP_NONE:
260 ah->bt_coex_wlan_weight[0] = AR9300_STOMP_NONE_WLAN_WGHT0;
261 ah->bt_coex_wlan_weight[1] = AR9300_STOMP_NONE_WLAN_WGHT1;
262 break;
263
264 default:
265 ath_dbg(ath9k_hw_common(ah), ATH_DBG_BTCOEX,
266 "Invalid Stomptype\n");
267 break;
268 }
269
270 ath9k_hw_btcoex_enable(ah);
271}
272
273/*
274 * Configures appropriate weight based on stomp type.
275 */
276void ath9k_hw_btcoex_bt_stomp(struct ath_hw *ah,
277 enum ath_stomp_type stomp_type)
278{
279 if (AR_SREV_9300_20_OR_LATER(ah)) {
280 ar9003_btcoex_bt_stomp(ah, stomp_type);
281 return;
282 }
283
284 switch (stomp_type) {
285 case ATH_BTCOEX_STOMP_ALL:
286 ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT,
287 AR_STOMP_ALL_WLAN_WGHT);
288 break;
289 case ATH_BTCOEX_STOMP_LOW:
290 ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT,
291 AR_STOMP_LOW_WLAN_WGHT);
292 break;
293 case ATH_BTCOEX_STOMP_NONE:
294 ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT,
295 AR_STOMP_NONE_WLAN_WGHT);
296 break;
297 default:
298 ath_dbg(ath9k_hw_common(ah), ATH_DBG_BTCOEX,
299 "Invalid Stomptype\n");
300 break;
301 }
302
303 ath9k_hw_btcoex_enable(ah);
304}
305EXPORT_SYMBOL(ath9k_hw_btcoex_bt_stomp);