1 /*
2 * Copyright (c) 2013 Qualcomm Atheros, Inc.
3 *
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
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
9 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10 * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
11 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
13 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14 * PERFORMANCE OF THIS SOFTWARE.
15 */
16
17
18 #include "opt_ah.h"
19
20 #include "ah.h"
21 #include "ah_internal.h"
22
23 #include "ar9300/ar9300.h"
24 #include "ar9300/ar9300reg.h"
25 #include "ar9300/ar9300phy.h"
26
27 #if ATH_SUPPORT_MCI
28
29 #define AH_MCI_REMOTE_RESET_INTERVAL_US 500
30 #define AH_MCI_DEBUG_PRINT_SCHED 0
31
ar9300_mci_print_msg(struct ath_hal * ah,HAL_BOOL send,u_int8_t hdr,int len,u_int32_t * pl)32 static void ar9300_mci_print_msg(struct ath_hal *ah, HAL_BOOL send,u_int8_t hdr,
33 int len, u_int32_t *pl)
34 {
35 #if 0
36 char s[128];
37 char *p = s;
38 int i;
39 u_int8_t *p_data = (u_int8_t *) pl;
40
41 if (send) {
42 p += snprintf(s, 60,
43 "(MCI) >>>>> Hdr: %02X, Len: %d, Payload:", hdr, len);
44 }
45 else {
46 p += snprintf(s, 60,
47 "(MCI) <<<<< Hdr: %02X, Len: %d, Payload:", hdr, len);
48 }
49 for ( i=0; i<len; i++)
50 {
51 p += snprintf(p, 60, " %02x", *(p_data + i));
52 }
53 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "%s\n", s);
54 /*
55 for ( i=0; i<(len + 3)/4; i++)
56 {
57 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) 0x%08x\n", *(pl + i));
58 }
59 */
60 #endif
61 }
62
63 static
ar9300_mci_osla_setup(struct ath_hal * ah,HAL_BOOL enable)64 void ar9300_mci_osla_setup(struct ath_hal *ah, HAL_BOOL enable)
65 {
66 // struct ath_hal_9300 *ahp = AH9300(ah);
67 u_int32_t thresh;
68
69 if (enable) {
70 OS_REG_RMW_FIELD(ah, AR_MCI_SCHD_TABLE_2, AR_MCI_SCHD_TABLE_2_HW_BASED, 1);
71 OS_REG_RMW_FIELD(ah, AR_MCI_SCHD_TABLE_2, AR_MCI_SCHD_TABLE_2_MEM_BASED, 1);
72
73 if (!(ah->ah_config.ath_hal_mci_config &
74 ATH_MCI_CONFIG_DISABLE_AGGR_THRESH))
75 {
76
77 if (AR_SREV_APHRODITE(ah))
78 OS_REG_RMW_FIELD(ah, AR_MCI_MISC, AR_MCI_MISC_HW_FIX_EN, 1);
79
80 thresh = MS(ah->ah_config.ath_hal_mci_config,
81 ATH_MCI_CONFIG_AGGR_THRESH);
82 OS_REG_RMW_FIELD(ah, AR_BTCOEX_CTRL,
83 AR_BTCOEX_CTRL_AGGR_THRESH, thresh);
84 OS_REG_RMW_FIELD(ah, AR_BTCOEX_CTRL,
85 AR_BTCOEX_CTRL_TIME_TO_NEXT_BT_THRESH_EN, 1);
86 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
87 "(MCI) SCHED aggr thresh: on, thresh=%d (%d.%d%%)\n",
88 thresh, (thresh + 1)*125/10, (thresh + 1)*125%10);
89
90 }
91 else {
92 OS_REG_RMW_FIELD(ah, AR_BTCOEX_CTRL,
93 AR_BTCOEX_CTRL_TIME_TO_NEXT_BT_THRESH_EN, 0);
94 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) SCHED aggr thresh: off\n");
95 }
96 OS_REG_RMW_FIELD(ah, AR_BTCOEX_CTRL,
97 AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN, 1);
98 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) SCHED one step look ahead: on\n");
99 }
100 else {
101 OS_REG_CLR_BIT(ah, AR_BTCOEX_CTRL,
102 AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN);
103 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) SCHED one step look ahead: off\n");
104 }
105 }
106
ar9300_mci_reset_req_wakeup(struct ath_hal * ah)107 static void ar9300_mci_reset_req_wakeup(struct ath_hal *ah)
108 {
109 /* to be tested in emulation */
110 if (AR_SREV_JUPITER_20_OR_LATER(ah) || AR_SREV_APHRODITE(ah)) {
111 OS_REG_RMW_FIELD(ah, AR_MCI_COMMAND2,
112 AR_MCI_COMMAND2_RESET_REQ_WAKEUP, 1);
113 OS_DELAY(1);
114 OS_REG_RMW_FIELD(ah, AR_MCI_COMMAND2,
115 AR_MCI_COMMAND2_RESET_REQ_WAKEUP, 0);
116 }
117 }
118
ar9300_mci_wait_for_interrupt(struct ath_hal * ah,u_int32_t address,u_int32_t bit_position,int32_t time_out)119 static int32_t ar9300_mci_wait_for_interrupt(struct ath_hal *ah,
120 u_int32_t address,
121 u_int32_t bit_position,
122 int32_t time_out)
123 {
124 int data; //, loop;
125
126 while (time_out) {
127 data = OS_REG_READ(ah, address);
128
129 if (data & bit_position) {
130 OS_REG_WRITE(ah, address, bit_position);
131 if (address == AR_MCI_INTERRUPT_RX_MSG_RAW) {
132 if (bit_position & AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE) {
133 ar9300_mci_reset_req_wakeup(ah);
134 }
135 if (bit_position & (AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING |
136 AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING))
137 {
138 OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RAW,
139 AR_MCI_INTERRUPT_REMOTE_SLEEP_UPDATE);
140 }
141 OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, AR_MCI_INTERRUPT_RX_MSG);
142 }
143 break;
144 }
145
146 OS_DELAY(10);
147 time_out -= 10;
148 if (time_out < 0) {
149 break;
150 }
151 }
152
153 if (time_out <= 0) {
154 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
155 "(MCI) %s: Wait for Reg0x%08x = 0x%08x timeout.\n",
156 __func__, address, bit_position);
157 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
158 "(MCI) INT_RAW = 0x%08x, RX_MSG_RAW = 0x%08x\n",
159 OS_REG_READ(ah, AR_MCI_INTERRUPT_RAW),
160 OS_REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_RAW));
161 time_out = 0;
162 }
163 return time_out;
164 }
165
ar9300_mci_remote_reset(struct ath_hal * ah,HAL_BOOL wait_done)166 void ar9300_mci_remote_reset(struct ath_hal *ah, HAL_BOOL wait_done)
167 {
168 u_int32_t payload[4] = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffff00};
169
170 ar9300_mci_send_message(ah, MCI_REMOTE_RESET, 0, payload, 16,
171 wait_done, AH_FALSE);
172
173 OS_DELAY(5);
174 }
175
ar9300_mci_send_lna_transfer(struct ath_hal * ah,HAL_BOOL wait_done)176 void ar9300_mci_send_lna_transfer(struct ath_hal *ah, HAL_BOOL wait_done)
177 {
178 u_int32_t payload = 0x00000000;
179
180 ar9300_mci_send_message(ah, MCI_LNA_TRANS, 0, &payload, 1,
181 wait_done, AH_FALSE);
182 }
183
ar9300_mci_send_req_wake(struct ath_hal * ah,HAL_BOOL wait_done)184 static void ar9300_mci_send_req_wake(struct ath_hal *ah, HAL_BOOL wait_done)
185 {
186 ar9300_mci_send_message(ah, MCI_REQ_WAKE,
187 HAL_MCI_FLAG_DISABLE_TIMESTAMP, AH_NULL, 0, wait_done, AH_FALSE);
188
189 OS_DELAY(5);
190 }
191
ar9300_mci_send_sys_waking(struct ath_hal * ah,HAL_BOOL wait_done)192 void ar9300_mci_send_sys_waking(struct ath_hal *ah, HAL_BOOL wait_done)
193 {
194 ar9300_mci_send_message(ah, MCI_SYS_WAKING,
195 HAL_MCI_FLAG_DISABLE_TIMESTAMP, AH_NULL, 0, wait_done, AH_FALSE);
196 }
197
ar9300_mci_send_lna_take(struct ath_hal * ah,HAL_BOOL wait_done)198 static void ar9300_mci_send_lna_take(struct ath_hal *ah, HAL_BOOL wait_done)
199 {
200 u_int32_t payload = 0x70000000;
201
202 /* LNA gain index is set to 7. */
203 ar9300_mci_send_message(ah, MCI_LNA_TAKE,
204 HAL_MCI_FLAG_DISABLE_TIMESTAMP, &payload, 1, wait_done, AH_FALSE);
205 }
206
ar9300_mci_send_sys_sleeping(struct ath_hal * ah,HAL_BOOL wait_done)207 static void ar9300_mci_send_sys_sleeping(struct ath_hal *ah, HAL_BOOL wait_done)
208 {
209 ar9300_mci_send_message(ah, MCI_SYS_SLEEPING,
210 HAL_MCI_FLAG_DISABLE_TIMESTAMP, AH_NULL, 0, wait_done, AH_FALSE);
211 }
212
213 static void
ar9300_mci_send_coex_version_query(struct ath_hal * ah,HAL_BOOL wait_done)214 ar9300_mci_send_coex_version_query(struct ath_hal *ah, HAL_BOOL wait_done)
215 {
216 struct ath_hal_9300 *ahp = AH9300(ah);
217 u_int32_t payload[4] = {0, 0, 0, 0};
218
219 if ((ahp->ah_mci_coex_bt_version_known == AH_FALSE) &&
220 (ahp->ah_mci_bt_state != MCI_BT_SLEEP)) {
221 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) Send Coex version query.\n");
222 MCI_GPM_SET_TYPE_OPCODE(payload,
223 MCI_GPM_COEX_AGENT, MCI_GPM_COEX_VERSION_QUERY);
224 ar9300_mci_send_message(ah, MCI_GPM, 0, payload, 16, wait_done, AH_TRUE);
225 }
226 }
227
228 static void
ar9300_mci_send_coex_version_response(struct ath_hal * ah,HAL_BOOL wait_done)229 ar9300_mci_send_coex_version_response(struct ath_hal *ah, HAL_BOOL wait_done)
230 {
231 struct ath_hal_9300 *ahp = AH9300(ah);
232 u_int32_t payload[4] = {0, 0, 0, 0};
233
234 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) Send Coex version response.\n");
235 MCI_GPM_SET_TYPE_OPCODE(payload,
236 MCI_GPM_COEX_AGENT, MCI_GPM_COEX_VERSION_RESPONSE);
237 *(((u_int8_t *)payload) + MCI_GPM_COEX_B_MAJOR_VERSION) =
238 ahp->ah_mci_coex_major_version_wlan;
239 *(((u_int8_t *)payload) + MCI_GPM_COEX_B_MINOR_VERSION) =
240 ahp->ah_mci_coex_minor_version_wlan;
241 ar9300_mci_send_message(ah, MCI_GPM, 0, payload, 16, wait_done, AH_TRUE);
242 }
243
244 static void
ar9300_mci_send_coex_wlan_channels(struct ath_hal * ah,HAL_BOOL wait_done)245 ar9300_mci_send_coex_wlan_channels(struct ath_hal *ah, HAL_BOOL wait_done)
246 {
247 struct ath_hal_9300 *ahp = AH9300(ah);
248 u_int32_t *payload = &ahp->ah_mci_coex_wlan_channels[0];
249
250 if ((ahp->ah_mci_coex_wlan_channels_update == AH_TRUE) &&
251 (ahp->ah_mci_bt_state != MCI_BT_SLEEP))
252 {
253 MCI_GPM_SET_TYPE_OPCODE(payload,
254 MCI_GPM_COEX_AGENT, MCI_GPM_COEX_WLAN_CHANNELS);
255 ar9300_mci_send_message(ah, MCI_GPM, 0, payload, 16, wait_done, AH_TRUE);
256 MCI_GPM_SET_TYPE_OPCODE(payload, 0xff, 0xff);
257 }
258 }
259
ar9300_mci_send_coex_bt_status_query(struct ath_hal * ah,HAL_BOOL wait_done,u_int8_t query_type)260 static void ar9300_mci_send_coex_bt_status_query(struct ath_hal *ah,
261 HAL_BOOL wait_done, u_int8_t query_type)
262 {
263 struct ath_hal_9300 *ahp = AH9300(ah);
264 u_int32_t pld[4] = {0, 0, 0, 0};
265 HAL_BOOL query_btinfo = query_type &
266 (MCI_GPM_COEX_QUERY_BT_ALL_INFO | MCI_GPM_COEX_QUERY_BT_TOPOLOGY);
267
268 if (ahp->ah_mci_bt_state != MCI_BT_SLEEP) {
269 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
270 "(MCI) Send Coex BT Status Query 0x%02X\n", query_type);
271 MCI_GPM_SET_TYPE_OPCODE(pld,
272 MCI_GPM_COEX_AGENT, MCI_GPM_COEX_STATUS_QUERY);
273 *(((u_int8_t *)pld) + MCI_GPM_COEX_B_BT_BITMAP) = query_type;
274 /*
275 * If bt_status_query message is thought not sent successfully,
276 * then ah_mci_need_flush_btinfo should be set again.
277 */
278 if (!ar9300_mci_send_message(ah, MCI_GPM, 0, pld, 16, wait_done, AH_TRUE))
279 {
280 if (query_btinfo) {
281 ahp->ah_mci_need_flush_btinfo = AH_TRUE;
282 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
283 "(MCI) send bt_status_query fail, set flush flag again\n");
284 }
285 }
286 if (query_btinfo) {
287 ahp->ah_mci_query_bt = AH_FALSE;
288 }
289 }
290 }
291
ar9300_mci_send_coex_halt_bt_gpm(struct ath_hal * ah,HAL_BOOL halt,HAL_BOOL wait_done)292 void ar9300_mci_send_coex_halt_bt_gpm(struct ath_hal *ah,
293 HAL_BOOL halt, HAL_BOOL wait_done)
294 {
295 struct ath_hal_9300 *ahp = AH9300(ah);
296 u_int32_t payload[4] = {0, 0, 0, 0};
297
298 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
299 "(MCI) Send Coex %s BT GPM.\n", (halt == AH_TRUE)?"HALT":"UNHALT");
300
301 MCI_GPM_SET_TYPE_OPCODE(payload,
302 MCI_GPM_COEX_AGENT, MCI_GPM_COEX_HALT_BT_GPM);
303 if (halt == AH_TRUE) {
304 ahp->ah_mci_query_bt = AH_TRUE;
305 /* Send next UNHALT no matter HALT sent or not */
306 ahp->ah_mci_unhalt_bt_gpm = AH_TRUE;
307 ahp->ah_mci_need_flush_btinfo = AH_TRUE;
308 *(((u_int8_t *)payload) + MCI_GPM_COEX_B_HALT_STATE) =
309 MCI_GPM_COEX_BT_GPM_HALT;
310 }
311 else {
312 *(((u_int8_t *)payload) + MCI_GPM_COEX_B_HALT_STATE) =
313 MCI_GPM_COEX_BT_GPM_UNHALT;
314 }
315 ar9300_mci_send_message(ah, MCI_GPM, 0, payload, 16, wait_done, AH_TRUE);
316 }
317
ar9300_mci_send_coex_bt_flags(struct ath_hal * ah,HAL_BOOL wait_done,u_int8_t opcode,u_int32_t bt_flags)318 static HAL_BOOL ar9300_mci_send_coex_bt_flags(struct ath_hal *ah, HAL_BOOL wait_done,
319 u_int8_t opcode, u_int32_t bt_flags)
320 {
321 // struct ath_hal_9300 *ahp = AH9300(ah);
322 u_int32_t pld[4] = {0, 0, 0, 0};
323
324 MCI_GPM_SET_TYPE_OPCODE(pld,
325 MCI_GPM_COEX_AGENT, MCI_GPM_COEX_BT_UPDATE_FLAGS);
326
327 *(((u_int8_t *)pld) + MCI_GPM_COEX_B_BT_FLAGS_OP) = opcode;
328 *(((u_int8_t *)pld) + MCI_GPM_COEX_W_BT_FLAGS + 0) = bt_flags & 0xFF;
329 *(((u_int8_t *)pld) + MCI_GPM_COEX_W_BT_FLAGS + 1) =
330 (bt_flags >> 8) & 0xFF;
331 *(((u_int8_t *)pld) + MCI_GPM_COEX_W_BT_FLAGS + 2) =
332 (bt_flags >> 16) & 0xFF;
333 *(((u_int8_t *)pld) + MCI_GPM_COEX_W_BT_FLAGS + 3) =
334 (bt_flags >> 24) & 0xFF;
335
336 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
337 "(MCI) BT_MCI_FLAGS: Send Coex BT Update Flags %s 0x%08x\n",
338 (opcode == MCI_GPM_COEX_BT_FLAGS_READ)?"READ":
339 ((opcode == MCI_GPM_COEX_BT_FLAGS_SET)?"SET":"CLEAR"),
340 bt_flags);
341
342 return ar9300_mci_send_message(ah, MCI_GPM, 0, pld, 16, wait_done, AH_TRUE);
343 }
344
ar9300_mci_2g5g_changed(struct ath_hal * ah,HAL_BOOL is_2g)345 void ar9300_mci_2g5g_changed(struct ath_hal *ah, HAL_BOOL is_2g)
346 {
347 struct ath_hal_9300 *ahp = AH9300(ah);
348
349 if (ahp->ah_mci_coex_2g5g_update == AH_FALSE) {
350 if (ahp->ah_mci_coex_is_2g == is_2g) {
351 //HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) BT_MCI_FLAGS: not changed\n");
352 } else {
353 ahp->ah_mci_coex_2g5g_update = AH_TRUE;
354 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) BT_MCI_FLAGS: changed\n");
355 }
356 } else {
357 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) BT_MCI_FLAGS: force send\n");
358 }
359 ahp->ah_mci_coex_is_2g = is_2g;
360 }
361
ar9300_mci_send_2g5g_status(struct ath_hal * ah,HAL_BOOL wait_done)362 static void ar9300_mci_send_2g5g_status(struct ath_hal *ah, HAL_BOOL wait_done)
363 {
364 struct ath_hal_9300 *ahp = AH9300(ah);
365 u_int32_t new_flags, to_set, to_clear;
366
367 if ((AR_SREV_JUPITER_20_OR_LATER(ah) || AR_SREV_APHRODITE(ah)) &&
368 (ahp->ah_mci_coex_2g5g_update == AH_TRUE) &&
369 (ahp->ah_mci_bt_state != MCI_BT_SLEEP))
370 {
371 if (ahp->ah_mci_coex_is_2g) {
372 new_flags = HAL_MCI_2G_FLAGS;
373 to_clear = HAL_MCI_2G_FLAGS_CLEAR_MASK;
374 to_set = HAL_MCI_2G_FLAGS_SET_MASK;
375 } else {
376 new_flags = HAL_MCI_5G_FLAGS;
377 to_clear = HAL_MCI_5G_FLAGS_CLEAR_MASK;
378 to_set = HAL_MCI_5G_FLAGS_SET_MASK;
379 }
380 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
381 "(MCI) BT_MCI_FLAGS: %s (0x%08x) clr=0x%08x, set=0x%08x\n",
382 ahp->ah_mci_coex_is_2g?"2G":"5G", new_flags, to_clear, to_set);
383 if (to_clear) {
384 ar9300_mci_send_coex_bt_flags(ah, wait_done,
385 MCI_GPM_COEX_BT_FLAGS_CLEAR, to_clear);
386 }
387 if (to_set) {
388 ar9300_mci_send_coex_bt_flags(ah, wait_done,
389 MCI_GPM_COEX_BT_FLAGS_SET, to_set);
390 }
391 }
392 if (AR_SREV_JUPITER_10(ah) && (ahp->ah_mci_bt_state != MCI_BT_SLEEP)) {
393 ahp->ah_mci_coex_2g5g_update = AH_FALSE;
394 }
395 }
396
ar9300_mci_2g5g_switch(struct ath_hal * ah,HAL_BOOL wait_done)397 void ar9300_mci_2g5g_switch(struct ath_hal *ah, HAL_BOOL wait_done)
398 {
399 struct ath_hal_9300 *ahp = AH9300(ah);
400
401 if (ahp->ah_mci_coex_2g5g_update)
402 {
403 if (ahp->ah_mci_coex_is_2g) {
404 ar9300_mci_send_2g5g_status(ah, AH_TRUE);
405
406 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) Send LNA trans\n");
407 ar9300_mci_send_lna_transfer(ah, AH_TRUE);
408 OS_DELAY(5);
409
410 OS_REG_CLR_BIT(ah, AR_MCI_TX_CTRL,
411 AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE);
412 if (AR_SREV_JUPITER_20_OR_LATER(ah) || AR_SREV_APHRODITE(ah)) {
413 OS_REG_CLR_BIT(ah, AR_GLB_CONTROL,
414 AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL);
415 if (!(ah->ah_config.ath_hal_mci_config &
416 ATH_MCI_CONFIG_DISABLE_OSLA))
417 {
418 ar9300_mci_osla_setup(ah, AH_TRUE);
419 }
420 }
421 } else {
422 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) Send LNA take\n");
423 ar9300_mci_send_lna_take(ah, AH_TRUE);
424 OS_DELAY(5);
425
426 OS_REG_SET_BIT(ah, AR_MCI_TX_CTRL,
427 AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE);
428 if (AR_SREV_JUPITER_20_OR_LATER(ah) || AR_SREV_APHRODITE(ah)) {
429 OS_REG_SET_BIT(ah, AR_GLB_CONTROL,
430 AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL);
431 ar9300_mci_osla_setup(ah, AH_FALSE);
432 }
433
434 ar9300_mci_send_2g5g_status(ah, AH_TRUE);
435 }
436 }
437
438 /*
439 * Update self gen chain mask. Also set basic set for
440 * txbf.
441 */
442 if (AR_SREV_JUPITER(ah)) {
443 if (ahp->ah_mci_coex_is_2g) {
444 ahp->ah_reduced_self_gen_mask = AH_TRUE;
445 OS_REG_WRITE(ah, AR_SELFGEN_MASK, 0x02);
446 ar9300_txbf_set_basic_set(ah);
447 }
448 else {
449 ahp->ah_reduced_self_gen_mask = AH_FALSE;
450 ar9300_txbf_set_basic_set(ah);
451 }
452 }
453 }
454
ar9300_mci_mute_bt(struct ath_hal * ah)455 void ar9300_mci_mute_bt(struct ath_hal *ah)
456 {
457
458 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "%s: called\n", __func__);
459
460 /* disable all MCI messages */
461 OS_REG_WRITE(ah, AR_MCI_MSG_ATTRIBUTES_TABLE, 0xFFFF0000);
462 OS_REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS0, 0xFFFFFFFF);
463 OS_REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS1, 0xFFFFFFFF);
464 OS_REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS2, 0xFFFFFFFF);
465 OS_REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS3, 0xFFFFFFFF);
466 OS_REG_SET_BIT(ah, AR_MCI_TX_CTRL, AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE);
467 /* wait pending HW messages to flush out */
468 OS_DELAY(10);
469
470 /*
471 * Send LNA_TAKE and SYS_SLEEPING when
472 * 1. reset not after resuming from full sleep
473 * 2. before reset MCI RX, to quiet BT and avoid MCI RX misalignment
474 */
475 if (MCI_ANT_ARCH_PA_LNA_SHARED(ah->ah_config.ath_hal_mci_config)) {
476 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) Send LNA take\n");
477 ar9300_mci_send_lna_take(ah, AH_TRUE);
478 OS_DELAY(5);
479 }
480 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) Send sys sleeping\n");
481 ar9300_mci_send_sys_sleeping(ah, AH_TRUE);
482 }
483
ar9300_mci_observation_set_up(struct ath_hal * ah)484 static void ar9300_mci_observation_set_up(struct ath_hal *ah)
485 {
486 /*
487 * Set up the observation bus in order to monitor MCI bus
488 * through GPIOs (0, 1, 2, and 3).
489 */
490 /*
491 OS_REG_WRITE(ah, AR_GPIO_INTR_POL, 0x00420000);
492 OS_REG_WRITE(ah, AR_GPIO_OE_OUT, 0x000000ff); // 4050
493 OS_REG_WRITE(ah, AR_GPIO_OUTPUT_MUX1, 0x000bdab4); // 4068
494 OS_REG_WRITE(ah, AR_OBS, 0x0000004b); // 4088
495 OS_REG_WRITE(ah, AR_DIAG_SW, 0x080c0000);
496 OS_REG_WRITE(ah, AR_MACMISC, 0x0001a000);
497 OS_REG_WRITE(ah, AR_PHY_TEST, 0x00080000); // a360
498 OS_REG_WRITE(ah, AR_PHY_TEST_CTL_STATUS, 0xe0000000); // a364
499 */
500 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "%s: called; config=0x%08x\n",
501 __func__, ah->ah_config.ath_hal_mci_config);
502
503 if (ah->ah_config.ath_hal_mci_config &
504 ATH_MCI_CONFIG_MCI_OBS_MCI)
505 {
506 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "%s: CONFIG_MCI_OBS_MCI\n", __func__);
507 ar9300_gpio_cfg_output(ah, 3, HAL_GPIO_OUTPUT_MUX_AS_MCI_WLAN_DATA);
508 ar9300_gpio_cfg_output(ah, 2, HAL_GPIO_OUTPUT_MUX_AS_MCI_WLAN_CLK);
509 ar9300_gpio_cfg_output(ah, 1, HAL_GPIO_OUTPUT_MUX_AS_MCI_BT_DATA);
510 ar9300_gpio_cfg_output(ah, 0, HAL_GPIO_OUTPUT_MUX_AS_MCI_BT_CLK);
511 }
512 else if (ah->ah_config.ath_hal_mci_config &
513 ATH_MCI_CONFIG_MCI_OBS_TXRX)
514 {
515 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "%s: CONFIG_MCI_OBS_TXRX\n", __func__);
516 ar9300_gpio_cfg_output(ah, 3, HAL_GPIO_OUTPUT_MUX_AS_WL_IN_TX);
517 ar9300_gpio_cfg_output(ah, 2, HAL_GPIO_OUTPUT_MUX_AS_WL_IN_RX);
518 ar9300_gpio_cfg_output(ah, 1, HAL_GPIO_OUTPUT_MUX_AS_BT_IN_TX);
519 ar9300_gpio_cfg_output(ah, 0, HAL_GPIO_OUTPUT_MUX_AS_BT_IN_RX);
520 ar9300_gpio_cfg_output(ah, 5, HAL_GPIO_OUTPUT_MUX_AS_OUTPUT);
521 }
522 else if (ah->ah_config.ath_hal_mci_config &
523 ATH_MCI_CONFIG_MCI_OBS_BT)
524 {
525 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "%s: CONFIG_MCI_OBS_BT\n", __func__);
526 ar9300_gpio_cfg_output(ah, 3, HAL_GPIO_OUTPUT_MUX_AS_BT_IN_TX);
527 ar9300_gpio_cfg_output(ah, 2, HAL_GPIO_OUTPUT_MUX_AS_BT_IN_RX);
528 ar9300_gpio_cfg_output(ah, 1, HAL_GPIO_OUTPUT_MUX_AS_MCI_BT_DATA);
529 ar9300_gpio_cfg_output(ah, 0, HAL_GPIO_OUTPUT_MUX_AS_MCI_BT_CLK);
530 }
531 else {
532 return;
533 }
534
535 OS_REG_SET_BIT(ah,
536 AR_HOSTIF_REG(ah, AR_GPIO_INPUT_EN_VAL), AR_GPIO_JTAG_DISABLE);
537
538 if (AR_SREV_JUPITER_20_OR_LATER(ah) || AR_SREV_APHRODITE(ah)) {
539 OS_REG_RMW_FIELD(ah, AR_GLB_CONTROL, AR_GLB_DS_JTAG_DISABLE, 1);
540 OS_REG_RMW_FIELD(ah, AR_GLB_CONTROL, AR_GLB_WLAN_UART_INTF_EN, 0);
541 OS_REG_WRITE(ah, AR_GLB_GPIO_CONTROL,
542 (OS_REG_READ(ah, AR_GLB_GPIO_CONTROL) |
543 ATH_MCI_CONFIG_MCI_OBS_GPIO));
544 }
545
546 OS_REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2, AR_BTCOEX_CTRL2_GPIO_OBS_SEL, 0);
547 OS_REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2, AR_BTCOEX_CTRL2_MAC_BB_OBS_SEL, 1);
548 OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_OBS), 0x4b);
549 OS_REG_RMW_FIELD(ah, AR_DIAG_SW, AR_DIAG_OBS_PT_SEL1, 0x03);
550 OS_REG_RMW_FIELD(ah, AR_DIAG_SW, AR_DIAG_OBS_PT_SEL2, 0x01);
551 OS_REG_RMW_FIELD(ah, AR_MACMISC, AR_MACMISC_MISC_OBS_BUS_LSB, 0x02);
552 OS_REG_RMW_FIELD(ah, AR_MACMISC, AR_MACMISC_MISC_OBS_BUS_MSB, 0x03);
553 //OS_REG_RMW_FIELD(ah, AR_PHY_TEST, AR_PHY_TEST_BBB_OBS_SEL, 0x01);
554 OS_REG_RMW_FIELD(ah, AR_PHY_TEST_CTL_STATUS,
555 AR_PHY_TEST_CTL_DEBUGPORT_SEL, 0x07);
556 }
557
ar9300_mci_process_gpm_extra(struct ath_hal * ah,u_int8_t gpm_type,u_int8_t gpm_opcode,u_int32_t * p_gpm)558 static void ar9300_mci_process_gpm_extra(struct ath_hal *ah,
559 u_int8_t gpm_type, u_int8_t gpm_opcode, u_int32_t *p_gpm)
560 {
561 struct ath_hal_9300 *ahp = AH9300(ah);
562 u_int8_t *p_data = (u_int8_t *) p_gpm;
563
564 switch (gpm_type)
565 {
566 case MCI_GPM_COEX_AGENT:
567 switch (gpm_opcode)
568 {
569 case MCI_GPM_COEX_VERSION_QUERY:
570 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
571 "(MCI) Recv GPM COEX Version Query.\n");
572 ar9300_mci_send_coex_version_response(ah, AH_TRUE);
573 break;
574
575 case MCI_GPM_COEX_VERSION_RESPONSE:
576 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
577 "(MCI) Recv GPM COEX Version Response.\n");
578 ahp->ah_mci_coex_major_version_bt =
579 *(p_data + MCI_GPM_COEX_B_MAJOR_VERSION);
580 ahp->ah_mci_coex_minor_version_bt =
581 *(p_data + MCI_GPM_COEX_B_MINOR_VERSION);
582 ahp->ah_mci_coex_bt_version_known = AH_TRUE;
583 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
584 "(MCI) BT Coex version: %d.%d\n",
585 ahp->ah_mci_coex_major_version_bt,
586 ahp->ah_mci_coex_minor_version_bt);
587 break;
588
589 case MCI_GPM_COEX_STATUS_QUERY:
590 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
591 "(MCI) Recv GPM COEX Status Query = 0x%02X.\n",
592 *(p_data + MCI_GPM_COEX_B_WLAN_BITMAP));
593 //if ((*(p_data + MCI_GPM_COEX_B_WLAN_BITMAP)) &
594 // MCI_GPM_COEX_QUERY_WLAN_ALL_INFO)
595 {
596 ahp->ah_mci_coex_wlan_channels_update = AH_TRUE;
597 ar9300_mci_send_coex_wlan_channels(ah, AH_TRUE);
598 }
599 break;
600
601 case MCI_GPM_COEX_BT_PROFILE_INFO:
602 ahp->ah_mci_query_bt = AH_TRUE;
603 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
604 "(MCI) Recv GPM COEX BT_Profile_Info (drop&query)\n");
605 break;
606
607 case MCI_GPM_COEX_BT_STATUS_UPDATE:
608 ahp->ah_mci_query_bt = AH_TRUE;
609 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
610 "(MCI) Recv GPM COEX BT_Status_Update "
611 "SEQ=%d (drop&query)\n",
612 *(p_gpm + 3));
613 break;
614
615 default:
616 break;
617 }
618 default:
619 break;
620 }
621 }
622
ar9300_mci_wait_for_gpm(struct ath_hal * ah,u_int8_t gpm_type,u_int8_t gpm_opcode,int32_t time_out)623 u_int32_t ar9300_mci_wait_for_gpm(struct ath_hal *ah, u_int8_t gpm_type,
624 u_int8_t gpm_opcode, int32_t time_out)
625 {
626 u_int32_t *p_gpm = NULL, mismatch = 0, more_data = HAL_MCI_GPM_NOMORE;
627 struct ath_hal_9300 *ahp = AH9300(ah);
628 HAL_BOOL b_is_bt_cal_done = (gpm_type == MCI_GPM_BT_CAL_DONE);
629 u_int32_t offset;
630 u_int8_t recv_type = 0, recv_opcode = 0;
631
632 if (time_out == 0) {
633 more_data = HAL_MCI_GPM_MORE;
634 }
635
636 while (time_out > 0)
637 {
638 if (p_gpm != NULL) {
639 MCI_GPM_RECYCLE(p_gpm);
640 p_gpm = NULL;
641 }
642
643 if (more_data != HAL_MCI_GPM_MORE) {
644 time_out = ar9300_mci_wait_for_interrupt(ah,
645 AR_MCI_INTERRUPT_RX_MSG_RAW,
646 AR_MCI_INTERRUPT_RX_MSG_GPM,
647 time_out);
648 }
649
650 if (time_out) {
651 offset = ar9300_mci_state(ah,
652 HAL_MCI_STATE_NEXT_GPM_OFFSET, &more_data);
653
654 if (offset == HAL_MCI_GPM_INVALID) {
655 continue;
656 }
657 p_gpm = (u_int32_t *) (ahp->ah_mci_gpm_buf + offset);
658 ar9300_mci_print_msg(ah, AH_FALSE, MCI_GPM, 16, p_gpm);
659
660 recv_type = MCI_GPM_TYPE(p_gpm);
661 recv_opcode = MCI_GPM_OPCODE(p_gpm);
662
663 if (MCI_GPM_IS_CAL_TYPE(recv_type)) {
664 if (recv_type == gpm_type) {
665 if ((gpm_type == MCI_GPM_BT_CAL_DONE) && !b_is_bt_cal_done)
666 {
667 gpm_type = MCI_GPM_BT_CAL_GRANT;
668 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
669 "(MCI) Rcv BT_CAL_DONE. Now Wait BT_CAL_GRANT\n");
670 continue;
671 }
672 if (gpm_type == MCI_GPM_BT_CAL_GRANT) {
673 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
674 "(MCI) BT_CAL_GRANT seq=%d, req_count=%d\n",
675 *(p_gpm + 2), *(p_gpm + 3));
676 }
677 break;
678 }
679 }
680 else {
681 if ((recv_type == gpm_type) && (recv_opcode == gpm_opcode)) {
682 break;
683 }
684 }
685
686 /* not expected message */
687
688 /*
689 * Check if it's cal_grant
690 *
691 * When we're waiting for cal_grant in reset routine, it's
692 * possible that BT sends out cal_request at the same time.
693 * Since BT's calibration doesn't happen that often, we'll
694 * let BT completes calibration then we continue to wait
695 * for cal_grant from BT.
696 * Orginal: Wait BT_CAL_GRANT.
697 * New: Receive BT_CAL_REQ -> send WLAN_CAL_GRANT -> wait
698 * BT_CAL_DONE -> Wait BT_CAL_GRANT.
699 */
700 if ((gpm_type == MCI_GPM_BT_CAL_GRANT) &&
701 (recv_type == MCI_GPM_BT_CAL_REQ))
702 {
703 u_int32_t payload[4] = {0, 0, 0, 0};
704
705 gpm_type = MCI_GPM_BT_CAL_DONE;
706 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
707 "(MCI) Rcv BT_CAL_REQ. Send WLAN_CAL_GRANT.\n");
708
709 MCI_GPM_SET_CAL_TYPE(payload, MCI_GPM_WLAN_CAL_GRANT);
710 ar9300_mci_send_message(ah, MCI_GPM, 0, payload, 16,
711 AH_FALSE, AH_FALSE);
712
713 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
714 "(MCI) Now wait for BT_CAL_DONE.\n");
715 continue;
716 }
717 else {
718 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
719 "(MCI) GPM subtype not match 0x%x\n", *(p_gpm + 1));
720 mismatch++;
721 ar9300_mci_process_gpm_extra(ah, recv_type, recv_opcode, p_gpm);
722 }
723 }
724 }
725 if (p_gpm != NULL) {
726 MCI_GPM_RECYCLE(p_gpm);
727 p_gpm = NULL;
728 }
729
730 if (time_out <= 0) {
731 time_out = 0;
732 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
733 "(MCI) GPM receiving timeout, mismatch = %d\n", mismatch);
734 } else {
735 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
736 "(MCI) Receive GPM type=0x%x, code=0x%x\n", gpm_type, gpm_opcode);
737 }
738
739 while (more_data == HAL_MCI_GPM_MORE) {
740 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) discard remaining GPM\n");
741 offset = ar9300_mci_state(ah,
742 HAL_MCI_STATE_NEXT_GPM_OFFSET, &more_data);
743
744 if (offset == HAL_MCI_GPM_INVALID) {
745 break;
746 }
747 p_gpm = (u_int32_t *) (ahp->ah_mci_gpm_buf + offset);
748 ar9300_mci_print_msg(ah, AH_FALSE, MCI_GPM, 16, p_gpm);
749 recv_type = MCI_GPM_TYPE(p_gpm);
750 recv_opcode = MCI_GPM_OPCODE(p_gpm);
751 if (!MCI_GPM_IS_CAL_TYPE(recv_type)) {
752 ar9300_mci_process_gpm_extra(ah, recv_type, recv_opcode, p_gpm);
753 }
754 MCI_GPM_RECYCLE(p_gpm);
755 }
756
757 return time_out;
758 }
759
ar9300_mci_prep_interface(struct ath_hal * ah)760 static void ar9300_mci_prep_interface(struct ath_hal *ah)
761 {
762 struct ath_hal_9300 *ahp = AH9300(ah);
763 u_int32_t saved_mci_int_en;
764 u_int32_t mci_timeout = 150;
765
766 ahp->ah_mci_bt_state = MCI_BT_SLEEP;
767
768 saved_mci_int_en = OS_REG_READ(ah, AR_MCI_INTERRUPT_EN);
769 OS_REG_WRITE(ah, AR_MCI_INTERRUPT_EN, 0);
770
771 OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,
772 OS_REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_RAW));
773 OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RAW,
774 OS_REG_READ(ah, AR_MCI_INTERRUPT_RAW));
775
776 /* Remote Reset */
777 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) %s: Reset sequence start\n", __func__);
778 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) send REMOTE_RESET\n");
779 ar9300_mci_remote_reset(ah, AH_TRUE);
780
781 /*
782 * This delay is required for the reset delay worst case value 255 in
783 * MCI_COMMAND2 register
784 */
785 if (AR_SREV_JUPITER_10(ah)) {
786 OS_DELAY(252);
787 }
788
789 /* Send REQ_WAKE to BT */
790 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) %s: Send REQ_WAKE to remote(BT)\n",
791 __func__);
792
793 ar9300_mci_send_req_wake(ah, AH_TRUE);
794
795 if (ar9300_mci_wait_for_interrupt(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,
796 AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING, 500))
797 {
798 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
799 "(MCI) %s: Saw SYS_WAKING from remote(BT)\n", __func__);
800 ahp->ah_mci_bt_state = MCI_BT_AWAKE;
801
802 if (AR_SREV_JUPITER_10(ah)) {
803 OS_DELAY(10);
804 }
805 /*
806 * We don't need to send more remote_reset at this moment.
807 *
808 * If BT receive first remote_reset, then BT HW will be cleaned up and
809 * will be able to receive req_wake and BT HW will respond sys_waking.
810 * In this case, WLAN will receive BT's HW sys_waking.
811 *
812 * Otherwise, if BT SW missed initial remote_reset, that remote_reset
813 * will still clean up BT MCI RX, and the req_wake will wake BT up,
814 * and BT SW will respond this req_wake with a remote_reset and
815 * sys_waking. In this case, WLAN will receive BT's SW sys_waking.
816 *
817 * In either case, BT's RX is cleaned up. So we don't need to reply
818 * BT's remote_reset now, if any.
819 *
820 * Similarly, if in any case, WLAN can receive BT's sys_waking, that
821 * means WLAN's RX is also fine.
822 */
823
824 /* Send SYS_WAKING to BT */
825 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
826 "(MCI) %s: Send SW SYS_WAKING to remot(BT)\n", __func__);
827 ar9300_mci_send_sys_waking(ah, AH_TRUE);
828
829 OS_DELAY(10);
830
831 /*
832 * Set BT priority interrupt value to be 0xff to
833 * avoid having too many BT PRIORITY interrupts.
834 */
835
836 OS_REG_WRITE(ah, AR_MCI_BT_PRI0, 0xFFFFFFFF);
837 OS_REG_WRITE(ah, AR_MCI_BT_PRI1, 0xFFFFFFFF);
838 OS_REG_WRITE(ah, AR_MCI_BT_PRI2, 0xFFFFFFFF);
839 OS_REG_WRITE(ah, AR_MCI_BT_PRI3, 0xFFFFFFFF);
840 OS_REG_WRITE(ah, AR_MCI_BT_PRI, 0X000000FF);
841
842 /*
843 * A contention reset will be received after send out sys_waking.
844 * Also BT priority interrupt bits will be set. Clear those bits
845 * before the next step.
846 */
847 OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,
848 AR_MCI_INTERRUPT_RX_MSG_CONT_RST);
849 OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, AR_MCI_INTERRUPT_BT_PRI);
850
851 if (AR_SREV_JUPITER_10(ah) ||
852 (ahp->ah_mci_coex_is_2g &&
853 MCI_ANT_ARCH_PA_LNA_SHARED(ah->ah_config.ath_hal_mci_config))) {
854 /* Send LNA_TRANS */
855 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) %s: Send LNA_TRANS to BT\n",
856 __func__);
857 ar9300_mci_send_lna_transfer(ah, AH_TRUE);
858
859 OS_DELAY(5);
860 }
861
862 if (AR_SREV_JUPITER_10(ah) ||
863 (ahp->ah_mci_coex_is_2g && !ahp->ah_mci_coex_2g5g_update &&
864 MCI_ANT_ARCH_PA_LNA_SHARED(ah->ah_config.ath_hal_mci_config))) {
865 if (ar9300_mci_wait_for_interrupt(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,
866 AR_MCI_INTERRUPT_RX_MSG_LNA_INFO, mci_timeout)) {
867 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
868 "(MCI) %s: WLAN has control over the LNA & BT obeys it\n",
869 __func__);
870 } else {
871 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
872 "(MCI) %s: BT did not respond to LNA_TRANS!\n", __func__);
873 //ahp->ah_mci_bt_state = MCI_BT_SLEEP;
874 }
875 }
876
877 if (AR_SREV_JUPITER_10(ah)) {
878 /* Send another remote_reset to deassert BT clk_req. */
879 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
880 "(MCI) %s: Another remote_reset to deassert clk_req.\n",
881 __func__);
882 ar9300_mci_remote_reset(ah, AH_TRUE);
883 OS_DELAY(252);
884 }
885 }
886
887 /* Clear the extra redundant SYS_WAKING from BT */
888 if ((ahp->ah_mci_bt_state == MCI_BT_AWAKE) &&
889 (OS_REG_READ_FIELD(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,
890 AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING)) &&
891 (OS_REG_READ_FIELD(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,
892 AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING) == 0))
893 {
894 OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,
895 AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING);
896 OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RAW,
897 AR_MCI_INTERRUPT_REMOTE_SLEEP_UPDATE);
898 }
899
900 OS_REG_WRITE(ah, AR_MCI_INTERRUPT_EN, saved_mci_int_en);
901 }
902
ar9300_mci_setup(struct ath_hal * ah,u_int32_t gpm_addr,void * gpm_buf,u_int16_t len,u_int32_t sched_addr)903 void ar9300_mci_setup(struct ath_hal *ah, u_int32_t gpm_addr,
904 void *gpm_buf, u_int16_t len,
905 u_int32_t sched_addr)
906 {
907 struct ath_hal_9300 *ahp = AH9300(ah);
908 void *sched_buf = (void *)((char *) gpm_buf + (sched_addr - gpm_addr));
909
910 ahp->ah_mci_gpm_addr = gpm_addr;
911 ahp->ah_mci_gpm_buf = gpm_buf;
912 ahp->ah_mci_gpm_len = len;
913 ahp->ah_mci_sched_addr = sched_addr;
914 ahp->ah_mci_sched_buf = sched_buf;
915
916 ar9300_mci_reset(ah, AH_TRUE, AH_TRUE, AH_TRUE);
917 }
918
ar9300_mci_disable_interrupt(struct ath_hal * ah)919 void ar9300_mci_disable_interrupt(struct ath_hal *ah)
920 {
921 OS_REG_WRITE(ah, AR_MCI_INTERRUPT_EN, 0);
922 OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_EN, 0);
923 }
924
ar9300_mci_enable_interrupt(struct ath_hal * ah)925 void ar9300_mci_enable_interrupt(struct ath_hal *ah)
926 {
927 OS_REG_WRITE(ah, AR_MCI_INTERRUPT_EN, AR_MCI_INTERRUPT_DEFAULT);
928 OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_EN,
929 AR_MCI_INTERRUPT_RX_MSG_DEFAULT);
930 }
931
ar9300_mci_set_btcoex_ctrl_9565_1ANT(struct ath_hal * ah)932 static void ar9300_mci_set_btcoex_ctrl_9565_1ANT(struct ath_hal *ah)
933 {
934 uint32_t regval;
935
936 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "%s: called\n", __func__);
937 regval = SM(1, AR_BTCOEX_CTRL_JUPITER_MODE) |
938 SM(1, AR_BTCOEX_CTRL_WBTIMER_EN) |
939 SM(1, AR_BTCOEX_CTRL_PA_SHARED) |
940 SM(1, AR_BTCOEX_CTRL_LNA_SHARED) |
941 SM(1, AR_BTCOEX_CTRL_NUM_ANTENNAS) |
942 SM(1, AR_BTCOEX_CTRL_RX_CHAIN_MASK) |
943 SM(0, AR_BTCOEX_CTRL_1_CHAIN_ACK) |
944 SM(0, AR_BTCOEX_CTRL_1_CHAIN_BCN) |
945 SM(0, AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN);
946
947 OS_REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2,
948 AR_BTCOEX_CTRL2_TX_CHAIN_MASK, 0x1);
949 OS_REG_WRITE(ah, AR_BTCOEX_CTRL, regval);
950 }
951
ar9300_mci_set_btcoex_ctrl_9565_2ANT(struct ath_hal * ah)952 static void ar9300_mci_set_btcoex_ctrl_9565_2ANT(struct ath_hal *ah)
953 {
954 uint32_t regval;
955
956 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "%s: called\n", __func__);
957 regval = SM(1, AR_BTCOEX_CTRL_JUPITER_MODE) |
958 SM(1, AR_BTCOEX_CTRL_WBTIMER_EN) |
959 SM(0, AR_BTCOEX_CTRL_PA_SHARED) |
960 SM(0, AR_BTCOEX_CTRL_LNA_SHARED) |
961 SM(2, AR_BTCOEX_CTRL_NUM_ANTENNAS) |
962 SM(1, AR_BTCOEX_CTRL_RX_CHAIN_MASK) |
963 SM(0, AR_BTCOEX_CTRL_1_CHAIN_ACK) |
964 SM(0, AR_BTCOEX_CTRL_1_CHAIN_BCN) |
965 SM(0, AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN);
966
967 OS_REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2,
968 AR_BTCOEX_CTRL2_TX_CHAIN_MASK, 0x0);
969 OS_REG_WRITE(ah, AR_BTCOEX_CTRL, regval);
970 }
971
ar9300_mci_set_btcoex_ctrl_9462(struct ath_hal * ah)972 static void ar9300_mci_set_btcoex_ctrl_9462(struct ath_hal *ah)
973 {
974 uint32_t regval;
975
976 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "%s: called\n", __func__);
977 regval = SM(1, AR_BTCOEX_CTRL_JUPITER_MODE) |
978 SM(1, AR_BTCOEX_CTRL_WBTIMER_EN) |
979 SM(1, AR_BTCOEX_CTRL_PA_SHARED) |
980 SM(1, AR_BTCOEX_CTRL_LNA_SHARED) |
981 SM(2, AR_BTCOEX_CTRL_NUM_ANTENNAS) |
982 SM(3, AR_BTCOEX_CTRL_RX_CHAIN_MASK) |
983 SM(0, AR_BTCOEX_CTRL_1_CHAIN_ACK) |
984 SM(0, AR_BTCOEX_CTRL_1_CHAIN_BCN) |
985 SM(0, AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN);
986
987 if (AR_SREV_JUPITER_10(ah)) {
988 regval |= SM(1, AR_BTCOEX_CTRL_SPDT_ENABLE_10);
989 }
990
991 OS_REG_WRITE(ah, AR_BTCOEX_CTRL, regval);
992 }
993
ar9300_mci_reset(struct ath_hal * ah,HAL_BOOL en_int,HAL_BOOL is_2g,HAL_BOOL is_full_sleep)994 void ar9300_mci_reset(struct ath_hal *ah, HAL_BOOL en_int, HAL_BOOL is_2g,
995 HAL_BOOL is_full_sleep)
996 {
997 struct ath_hal_9300 *ahp = AH9300(ah);
998 // struct ath_hal_private *ahpriv = AH_PRIVATE(ah);
999 u_int32_t regval;
1000
1001 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) %s: full_sleep = %d, is_2g = %d\n",
1002 __func__, is_full_sleep, is_2g);
1003
1004 if (!ahp->ah_mci_gpm_addr && !ahp->ah_mci_sched_addr) {
1005 /* GPM buffer and scheduling message buffer are not allocated */
1006 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1007 "(MCI) GPM and SCHEDULE buffers not allocated\n");
1008 return;
1009 }
1010
1011 if (OS_REG_READ(ah, AR_BTCOEX_CTRL) == 0xdeadbeef) {
1012 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1013 "(MCI) %s: ### It's deadbeef, quit mcireset()\n", __func__);
1014 return;
1015 }
1016
1017 /* Program MCI DMA related registers */
1018 OS_REG_WRITE(ah, AR_MCI_GPM_0, ahp->ah_mci_gpm_addr);
1019 OS_REG_WRITE(ah, AR_MCI_GPM_1, ahp->ah_mci_gpm_len);
1020 OS_REG_WRITE(ah, AR_MCI_SCHD_TABLE_0, ahp->ah_mci_sched_addr);
1021
1022 /*
1023 * To avoid MCI state machine be affected by incoming remote MCI messages,
1024 * MCI mode will be enabled later, right before reset the MCI TX and RX.
1025 */
1026 if (AR_SREV_APHRODITE(ah)) {
1027 uint8_t ant = MS(ah->ah_config.ath_hal_mci_config,
1028 ATH_MCI_CONFIG_ANT_ARCH);
1029 if (ant == ATH_MCI_ANT_ARCH_1_ANT_PA_LNA_SHARED)
1030 ar9300_mci_set_btcoex_ctrl_9565_1ANT(ah);
1031 else
1032 ar9300_mci_set_btcoex_ctrl_9565_2ANT(ah);
1033 } else {
1034 ar9300_mci_set_btcoex_ctrl_9462(ah);
1035 }
1036
1037
1038 if (is_2g && (AR_SREV_JUPITER_20_OR_LATER(ah) || AR_SREV_APHRODITE(ah)) &&
1039 !(ah->ah_config.ath_hal_mci_config &
1040 ATH_MCI_CONFIG_DISABLE_OSLA))
1041 {
1042 ar9300_mci_osla_setup(ah, AH_TRUE);
1043 }
1044 else {
1045 ar9300_mci_osla_setup(ah, AH_FALSE);
1046 }
1047
1048 if (AR_SREV_JUPITER_20_OR_LATER(ah) || AR_SREV_APHRODITE(ah)) {
1049 OS_REG_SET_BIT(ah, AR_GLB_CONTROL, AR_BTCOEX_CTRL_SPDT_ENABLE);
1050
1051 OS_REG_RMW_FIELD(ah, AR_BTCOEX_CTRL3,
1052 AR_BTCOEX_CTRL3_CONT_INFO_TIMEOUT, 20);
1053 }
1054
1055 OS_REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2, AR_BTCOEX_CTRL2_RX_DEWEIGHT, 0);
1056
1057 OS_REG_RMW_FIELD(ah, AR_PCU_MISC, AR_PCU_BT_ANT_PREVENT_RX, 0);
1058
1059 /* Set the time out to 3.125ms (5 BT slots) */
1060 OS_REG_RMW_FIELD(ah, AR_BTCOEX_WL_LNA, AR_BTCOEX_WL_LNA_TIMEOUT, 0x3D090);
1061
1062 if (ah->ah_config.ath_hal_mci_config & ATH_MCI_CONFIG_CONCUR_TX) {
1063 u_int8_t i;
1064 u_int32_t const *pmax_tx_pwr;
1065
1066 if ((ah->ah_config.ath_hal_mci_config &
1067 ATH_MCI_CONFIG_CONCUR_TX) == ATH_MCI_CONCUR_TX_SHARED_CHN)
1068 {
1069 ahp->ah_mci_concur_tx_en = (ahp->ah_bt_coex_flag &
1070 HAL_BT_COEX_FLAG_MCI_MAX_TX_PWR) ? AH_TRUE : AH_FALSE;
1071
1072 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) concur_tx_en = %d\n",
1073 ahp->ah_mci_concur_tx_en);
1074 /*
1075 * We're not relying on HW to reduce WLAN tx power.
1076 * Set the max tx power table to 0x7f for all.
1077 */
1078 #if 0
1079 if (AH_PRIVATE(ah)->ah_curchan) {
1080 chan_flags = AH_PRIVATE(ah)->ah_curchan->channel_flags;
1081 }
1082 if (chan_flags == CHANNEL_G_HT20) {
1083 pmax_tx_pwr = &mci_concur_tx_max_pwr[2][0];
1084 }
1085 else if (chan_flags == CHANNEL_G) {
1086 pmax_tx_pwr = &mci_concur_tx_max_pwr[1][0];
1087 }
1088 else if ((chan_flags == CHANNEL_G_HT40PLUS) ||
1089 (chan_flags == CHANNEL_G_HT40MINUS))
1090 {
1091 pmax_tx_pwr = &mci_concur_tx_max_pwr[3][0];
1092 }
1093 else {
1094 pmax_tx_pwr = &mci_concur_tx_max_pwr[0][0];
1095 }
1096
1097 if (ahp->ah_mci_concur_tx_en) {
1098 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1099 "(MCI) chan flags = 0x%x, max_tx_pwr = %d dBm\n",
1100 chan_flags,
1101 (MS(pmax_tx_pwr[2],
1102 ATH_MCI_CONCUR_TX_LOWEST_PWR_MASK) >> 1));
1103 }
1104 #else
1105 pmax_tx_pwr = &mci_concur_tx_max_pwr[0][0];
1106 #endif
1107 }
1108 else if ((ah->ah_config.ath_hal_mci_config &
1109 ATH_MCI_CONFIG_CONCUR_TX) == ATH_MCI_CONCUR_TX_UNSHARED_CHN)
1110 {
1111 pmax_tx_pwr = &mci_concur_tx_max_pwr[0][0];
1112 ahp->ah_mci_concur_tx_en = AH_TRUE;
1113 }
1114 else {
1115 pmax_tx_pwr = &mci_concur_tx_max_pwr[0][0];
1116 ahp->ah_mci_concur_tx_en = AH_TRUE;
1117 }
1118
1119 /* Default is using rate based TPC. */
1120 OS_REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2,
1121 AR_BTCOEX_CTRL2_DESC_BASED_TXPWR_ENABLE, 0);
1122 OS_REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2,
1123 AR_BTCOEX_CTRL2_TXPWR_THRESH, 0x7f);
1124 OS_REG_RMW_FIELD(ah, AR_BTCOEX_CTRL,
1125 AR_BTCOEX_CTRL_REDUCE_TXPWR, 0);
1126 for (i = 0; i < 8; i++) {
1127 OS_REG_WRITE(ah, AR_BTCOEX_MAX_TXPWR(i), pmax_tx_pwr[i]);
1128 }
1129 }
1130
1131 regval = MS(ah->ah_config.ath_hal_mci_config,
1132 ATH_MCI_CONFIG_CLK_DIV);
1133 OS_REG_RMW_FIELD(ah, AR_MCI_TX_CTRL, AR_MCI_TX_CTRL_CLK_DIV, regval);
1134
1135 OS_REG_SET_BIT(ah, AR_BTCOEX_CTRL, AR_BTCOEX_CTRL_MCI_MODE_EN);
1136
1137 /* Resetting the Rx and Tx paths of MCI */
1138 regval = OS_REG_READ(ah, AR_MCI_COMMAND2);
1139 regval |= SM(1, AR_MCI_COMMAND2_RESET_TX);
1140 OS_REG_WRITE(ah, AR_MCI_COMMAND2, regval);
1141 OS_DELAY(1);
1142 regval &= ~SM(1, AR_MCI_COMMAND2_RESET_TX);
1143 OS_REG_WRITE(ah, AR_MCI_COMMAND2, regval);
1144
1145 if (is_full_sleep) {
1146 ar9300_mci_mute_bt(ah);
1147 OS_DELAY(100);
1148 }
1149
1150 regval |= SM(1, AR_MCI_COMMAND2_RESET_RX);
1151 OS_REG_WRITE(ah, AR_MCI_COMMAND2, regval);
1152 OS_DELAY(1);
1153 regval &= ~SM(1, AR_MCI_COMMAND2_RESET_RX);
1154 OS_REG_WRITE(ah, AR_MCI_COMMAND2, regval);
1155
1156 ar9300_mci_state(ah, HAL_MCI_STATE_INIT_GPM_OFFSET, NULL);
1157 OS_REG_WRITE(ah, AR_MCI_MSG_ATTRIBUTES_TABLE,
1158 (SM(0xe801, AR_MCI_MSG_ATTRIBUTES_TABLE_INVALID_HDR) |
1159 SM(0x0000, AR_MCI_MSG_ATTRIBUTES_TABLE_CHECKSUM)));
1160 if (MCI_ANT_ARCH_PA_LNA_SHARED(ah->ah_config.ath_hal_mci_config)) {
1161 OS_REG_CLR_BIT(ah, AR_MCI_TX_CTRL, AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE);
1162 } else {
1163 OS_REG_SET_BIT(ah, AR_MCI_TX_CTRL, AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE);
1164 }
1165
1166 if (AR_SREV_JUPITER_20_OR_LATER(ah) || AR_SREV_APHRODITE(ah)) {
1167 ar9300_mci_observation_set_up(ah);
1168 }
1169
1170 ahp->ah_mci_ready = AH_TRUE;
1171 ar9300_mci_prep_interface(ah);
1172
1173 if (en_int) {
1174 ar9300_mci_enable_interrupt(ah);
1175 }
1176
1177 #if ATH_SUPPORT_AIC
1178 if (ahp->ah_aic_enabled) {
1179 ar9300_aic_start_normal(ah);
1180 }
1181 #endif
1182 }
1183
ar9300_mci_queue_unsent_gpm(struct ath_hal * ah,u_int8_t header,u_int32_t * payload,HAL_BOOL queue)1184 static void ar9300_mci_queue_unsent_gpm(struct ath_hal *ah, u_int8_t header,
1185 u_int32_t *payload, HAL_BOOL queue)
1186 {
1187 struct ath_hal_9300 *ahp = AH9300(ah);
1188 u_int8_t type, opcode;
1189
1190 if (queue == AH_TRUE) {
1191 if (payload != NULL) {
1192 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1193 "(MCI) ERROR: Send fail: %02x: %02x %02x %02x\n",
1194 header,
1195 *(((u_int8_t *)payload) + 4),
1196 *(((u_int8_t *)payload) + 5),
1197 *(((u_int8_t *)payload) + 6));
1198 } else {
1199 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1200 "(MCI) ERROR: Send fail: %02x\n", header);
1201 }
1202 }
1203 /* check if the message is to be queued */
1204 if (header == MCI_GPM) {
1205 type = MCI_GPM_TYPE(payload);
1206 opcode = MCI_GPM_OPCODE(payload);
1207
1208 if (type == MCI_GPM_COEX_AGENT) {
1209 switch (opcode)
1210 {
1211 case MCI_GPM_COEX_BT_UPDATE_FLAGS:
1212 if (AR_SREV_JUPITER_10(ah)) {
1213 break;
1214 }
1215 if (*(((u_int8_t *)payload) + MCI_GPM_COEX_B_BT_FLAGS_OP) ==
1216 MCI_GPM_COEX_BT_FLAGS_READ)
1217 {
1218 break;
1219 }
1220 ahp->ah_mci_coex_2g5g_update = queue;
1221 if (queue == AH_TRUE) {
1222 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1223 "(MCI) BT_MCI_FLAGS: 2G5G status <queued> %s.\n",
1224 ahp->ah_mci_coex_is_2g?"2G":"5G");
1225 }
1226 else {
1227 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1228 "(MCI) BT_MCI_FLAGS: 2G5G status <sent> %s.\n",
1229 ahp->ah_mci_coex_is_2g?"2G":"5G");
1230 }
1231 break;
1232
1233 case MCI_GPM_COEX_WLAN_CHANNELS:
1234 ahp->ah_mci_coex_wlan_channels_update = queue;
1235 if (queue == AH_TRUE) {
1236 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1237 "(MCI) WLAN channel map <queued>.\n");
1238 }
1239 else {
1240 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1241 "(MCI) WLAN channel map <sent>.\n");
1242 }
1243 break;
1244
1245 case MCI_GPM_COEX_HALT_BT_GPM:
1246 if (*(((u_int8_t *)payload) + MCI_GPM_COEX_B_HALT_STATE) ==
1247 MCI_GPM_COEX_BT_GPM_UNHALT)
1248 {
1249 ahp->ah_mci_unhalt_bt_gpm = queue;
1250 if (queue == AH_TRUE) {
1251 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1252 "(MCI) UNHALT BT GPM <queued>.\n");
1253 }
1254 else {
1255 ahp->ah_mci_halted_bt_gpm = AH_FALSE;
1256 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1257 "(MCI) UNHALT BT GPM <sent>.\n");
1258 }
1259 }
1260 if (*(((u_int8_t *)payload) + MCI_GPM_COEX_B_HALT_STATE) ==
1261 MCI_GPM_COEX_BT_GPM_HALT)
1262 {
1263 ahp->ah_mci_halted_bt_gpm = !queue;
1264 if (queue == AH_TRUE) {
1265 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1266 "(MCI) HALT BT GPM <not sent>.\n");
1267 }
1268 else {
1269 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1270 "(MCI) HALT BT GPM <sent>.\n");
1271 }
1272 }
1273 break;
1274
1275 default:
1276 break;
1277 }
1278 }
1279 }
1280 }
1281
ar9300_mci_send_message(struct ath_hal * ah,u_int8_t header,u_int32_t flag,u_int32_t * payload,u_int8_t len,HAL_BOOL wait_done,HAL_BOOL check_bt)1282 HAL_BOOL ar9300_mci_send_message(struct ath_hal *ah, u_int8_t header,
1283 u_int32_t flag, u_int32_t *payload,
1284 u_int8_t len, HAL_BOOL wait_done, HAL_BOOL check_bt)
1285 {
1286 int i;
1287 struct ath_hal_9300 *ahp = AH9300(ah);
1288 HAL_BOOL msg_sent = AH_FALSE;
1289 u_int32_t regval;
1290 u_int32_t saved_mci_int_en = OS_REG_READ(ah, AR_MCI_INTERRUPT_EN);
1291
1292 regval = OS_REG_READ(ah, AR_BTCOEX_CTRL);
1293 if ((regval == 0xdeadbeef) || !(regval & AR_BTCOEX_CTRL_MCI_MODE_EN)) {
1294 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1295 "(MCI) %s: Not send 0x%x. MCI is not enabled. full_sleep = %d\n",
1296 __func__, header, ahp->ah_chip_full_sleep);
1297 ar9300_mci_queue_unsent_gpm(ah, header, payload, AH_TRUE);
1298 return AH_FALSE;
1299 }
1300 else if (check_bt && (ahp->ah_mci_bt_state == MCI_BT_SLEEP)) {
1301 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1302 "(MCI) %s: Don't send message(0x%x). BT is in sleep state\n",
1303 __func__, header);
1304 ar9300_mci_queue_unsent_gpm(ah, header, payload, AH_TRUE);
1305 return AH_FALSE;
1306 }
1307
1308 if (wait_done) {
1309 OS_REG_WRITE(ah, AR_MCI_INTERRUPT_EN, 0);
1310 }
1311
1312 /* Need to clear SW_MSG_DONE raw bit before wait */
1313 OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RAW,
1314 AR_MCI_INTERRUPT_SW_MSG_DONE | AR_MCI_INTERRUPT_MSG_FAIL_MASK);
1315
1316 if (payload != AH_NULL) {
1317 for (i = 0; (i*4) < len; i++) {
1318 OS_REG_WRITE(ah, (AR_MCI_TX_PAYLOAD0 + i*4), *(payload + i));
1319 }
1320 }
1321 ar9300_mci_print_msg(ah, AH_TRUE, header, len, payload);
1322
1323 OS_REG_WRITE(ah, AR_MCI_COMMAND0,
1324 (SM((flag & HAL_MCI_FLAG_DISABLE_TIMESTAMP),
1325 AR_MCI_COMMAND0_DISABLE_TIMESTAMP) |
1326 SM(len, AR_MCI_COMMAND0_LEN) |
1327 SM(header, AR_MCI_COMMAND0_HEADER)));
1328
1329 if (wait_done &&
1330 ar9300_mci_wait_for_interrupt(ah, AR_MCI_INTERRUPT_RAW,
1331 AR_MCI_INTERRUPT_SW_MSG_DONE, 500) == 0)
1332 {
1333 ar9300_mci_queue_unsent_gpm(ah, header, payload, AH_TRUE);
1334 }
1335 else {
1336 ar9300_mci_queue_unsent_gpm(ah, header, payload, AH_FALSE);
1337 msg_sent = AH_TRUE;
1338 }
1339
1340 if (wait_done) {
1341 OS_REG_WRITE(ah, AR_MCI_INTERRUPT_EN, saved_mci_int_en);
1342 }
1343
1344 return msg_sent;
1345 }
1346
ar9300_mci_get_interrupt(struct ath_hal * ah,u_int32_t * mci_int,u_int32_t * mci_int_rx_msg)1347 u_int32_t ar9300_mci_get_interrupt(struct ath_hal *ah, u_int32_t *mci_int,
1348 u_int32_t *mci_int_rx_msg)
1349 {
1350 struct ath_hal_9300 *ahp = AH9300(ah);
1351
1352 *mci_int = ahp->ah_mci_int_raw;
1353 *mci_int_rx_msg = ahp->ah_mci_int_rx_msg;
1354
1355 /* Clean int bits after the values are read. */
1356 ahp->ah_mci_int_raw = 0;
1357 ahp->ah_mci_int_rx_msg = 0;
1358
1359 return 0;
1360 }
1361
ar9300_mci_check_int(struct ath_hal * ah,u_int32_t ints)1362 u_int32_t ar9300_mci_check_int(struct ath_hal *ah, u_int32_t ints)
1363 {
1364 u_int32_t reg;
1365
1366 reg = OS_REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_RAW);
1367 return ((reg & ints) == ints);
1368 }
1369
ar9300_mci_sync_bt_state(struct ath_hal * ah)1370 void ar9300_mci_sync_bt_state(struct ath_hal *ah)
1371 {
1372 struct ath_hal_9300 *ahp = AH9300(ah);
1373 u_int32_t cur_bt_state;
1374
1375 cur_bt_state = ar9300_mci_state(ah, HAL_MCI_STATE_REMOTE_SLEEP, NULL);
1376 if (ahp->ah_mci_bt_state != cur_bt_state) {
1377 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1378 "(MCI) %s: BT state mismatches. old: %d, new: %d\n",
1379 __func__, ahp->ah_mci_bt_state, cur_bt_state);
1380 ahp->ah_mci_bt_state = cur_bt_state;
1381 }
1382 if (ahp->ah_mci_bt_state != MCI_BT_SLEEP) {
1383 #if MCI_QUERY_BT_VERSION_VERBOSE
1384 ar9300_mci_send_coex_version_query(ah, AH_TRUE);
1385 #endif
1386 ar9300_mci_send_coex_wlan_channels(ah, AH_TRUE);
1387 if (ahp->ah_mci_unhalt_bt_gpm == AH_TRUE) {
1388 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) %s: UNHALT BT GPM\n", __func__);
1389 ar9300_mci_send_coex_halt_bt_gpm(ah, AH_FALSE, AH_TRUE);
1390 }
1391 }
1392 }
1393
ar9300_mci_is_gpm_valid(struct ath_hal * ah,u_int32_t msg_index)1394 static HAL_BOOL ar9300_mci_is_gpm_valid(struct ath_hal *ah, u_int32_t msg_index)
1395 {
1396 struct ath_hal_9300 *ahp = AH9300(ah);
1397 u_int32_t *payload;
1398 u_int32_t recv_type, offset = msg_index << 4;
1399
1400 if (msg_index == HAL_MCI_GPM_INVALID) {
1401 return AH_FALSE;
1402 }
1403
1404 payload = (u_int32_t *) (ahp->ah_mci_gpm_buf + offset);
1405 recv_type = MCI_GPM_TYPE(payload);
1406
1407 if (recv_type == MCI_GPM_RSVD_PATTERN) {
1408 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) Skip RSVD GPM\n");
1409 return AH_FALSE;
1410 }
1411
1412 return AH_TRUE;
1413 }
1414
1415 u_int32_t
ar9300_mci_state(struct ath_hal * ah,u_int32_t state_type,u_int32_t * p_data)1416 ar9300_mci_state(struct ath_hal *ah, u_int32_t state_type, u_int32_t *p_data)
1417 {
1418 u_int32_t value = 0, more_gpm = 0, gpm_ptr;
1419 struct ath_hal_9300 *ahp = AH9300(ah);
1420
1421 switch (state_type) {
1422 case HAL_MCI_STATE_ENABLE:
1423 if (AH_PRIVATE(ah)->ah_caps.halMciSupport && ahp->ah_mci_ready) {
1424 value = OS_REG_READ(ah, AR_BTCOEX_CTRL);
1425 if ((value == 0xdeadbeef) || (value == 0xffffffff)) {
1426 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1427 "(MCI) BTCOEX_CTRL = 0xdeadbeef\n");
1428 value = 0;
1429 }
1430 }
1431 value &= AR_BTCOEX_CTRL_MCI_MODE_EN;
1432 break;
1433
1434 case HAL_MCI_STATE_INIT_GPM_OFFSET:
1435 value = MS(OS_REG_READ(ah, AR_MCI_GPM_1), AR_MCI_GPM_WRITE_PTR);
1436 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1437 "(MCI) %s: GPM initial WRITE_PTR=%d.\n", __func__, value);
1438 ahp->ah_mci_gpm_idx = value;
1439 break;
1440
1441 case HAL_MCI_STATE_NEXT_GPM_OFFSET:
1442 case HAL_MCI_STATE_LAST_GPM_OFFSET:
1443 /*
1444 * This could be useful to avoid new GPM message interrupt which
1445 * may lead to spurious interrupt after power sleep, or multiple
1446 * entry of ath_coex_mci_intr().
1447 * Adding empty GPM check by returning HAL_MCI_GPM_INVALID can
1448 * alleviate this effect, but clearing GPM RX interrupt bit is
1449 * safe, because whether this is called from HAL or LMAC, there
1450 * must be an interrupt bit set/triggered initially.
1451 */
1452 OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,
1453 AR_MCI_INTERRUPT_RX_MSG_GPM);
1454
1455 gpm_ptr = MS(OS_REG_READ(ah, AR_MCI_GPM_1), AR_MCI_GPM_WRITE_PTR);
1456 value = gpm_ptr;
1457
1458 if (value == 0) {
1459 value = ahp->ah_mci_gpm_len - 1;
1460 }
1461 else if (value >= ahp->ah_mci_gpm_len) {
1462 if (value != 0xFFFF) {
1463 value = 0;
1464 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1465 "(MCI) %s: GPM offset out of range.\n", __func__);
1466 }
1467 }
1468 else {
1469 value--;
1470 }
1471
1472 if (value == 0xFFFF) {
1473 value = HAL_MCI_GPM_INVALID;
1474 more_gpm = HAL_MCI_GPM_NOMORE;
1475 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1476 "(MCI) %s: GPM ptr invalid "
1477 "@ptr=%d, @offset=%d, more=NOMORE.\n",
1478 __func__, gpm_ptr, value);
1479 }
1480 else if (state_type == HAL_MCI_STATE_NEXT_GPM_OFFSET) {
1481 if (gpm_ptr == ahp->ah_mci_gpm_idx) {
1482 value = HAL_MCI_GPM_INVALID;
1483 more_gpm = HAL_MCI_GPM_NOMORE;
1484 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1485 "(MCI) %s: GPM message not available "
1486 "@ptr=%d, @offset=%d, more=NOMORE.\n",
1487 __func__, gpm_ptr, value);
1488 }
1489 else {
1490 while (1) {
1491 u_int32_t temp_index;
1492
1493 /* skip reserved GPM if any */
1494 if (value != ahp->ah_mci_gpm_idx) {
1495 more_gpm = HAL_MCI_GPM_MORE;
1496 }
1497 else {
1498 more_gpm = HAL_MCI_GPM_NOMORE;
1499 }
1500 temp_index = ahp->ah_mci_gpm_idx;
1501 ahp->ah_mci_gpm_idx++;
1502 if (ahp->ah_mci_gpm_idx >= ahp->ah_mci_gpm_len) {
1503 ahp->ah_mci_gpm_idx = 0;
1504 }
1505 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1506 "(MCI) %s: GPM message got "
1507 "@ptr=%d, @offset=%d, more=%s.\n",
1508 __func__, gpm_ptr, temp_index,
1509 (more_gpm == HAL_MCI_GPM_MORE)?"MORE":"NOMORE");
1510 if (ar9300_mci_is_gpm_valid(ah, temp_index)) {
1511 value = temp_index;
1512 break;
1513 }
1514 if (more_gpm == HAL_MCI_GPM_NOMORE) {
1515 value = HAL_MCI_GPM_INVALID;
1516 break;
1517 }
1518 }
1519 }
1520 if (p_data != NULL) {
1521 *p_data = more_gpm;
1522 }
1523 }
1524 if (value != HAL_MCI_GPM_INVALID) {
1525 value <<= 4;
1526 }
1527 break;
1528
1529 case HAL_MCI_STATE_LAST_SCHD_MSG_OFFSET:
1530 value = MS(OS_REG_READ(ah, AR_MCI_RX_STATUS),
1531 AR_MCI_RX_LAST_SCHD_MSG_INDEX);
1532
1533 #if AH_MCI_DEBUG_PRINT_SCHED
1534 {
1535 u_int32_t index = value;
1536 u_int32_t prev_index, sched_idx;
1537 u_int32_t *pld;
1538 u_int8_t *pld8;
1539 u_int32_t wbtimer = OS_REG_READ(ah, AR_BTCOEX_WBTIMER);
1540 u_int32_t schd_ctl = OS_REG_READ(ah, AR_MCI_HW_SCHD_TBL_CTL);
1541
1542 if (index > 0) {
1543 prev_index = index - 1;
1544 } else {
1545 prev_index = index;
1546 }
1547
1548 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) SCHED\n");
1549 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1550 "(MCI) SCHED SCHD_TBL_CTRL=0x%08x, WBTIMER=0x%08x (%d)\n",
1551 schd_ctl, wbtimer, wbtimer);
1552 for (sched_idx = prev_index; sched_idx <= index; sched_idx++) {
1553 pld = (u_int32_t *) (ahp->ah_mci_sched_buf + (sched_idx << 4));
1554 pld8 = (u_int8_t *) pld;
1555
1556 ar9300_mci_print_msg(ah, AH_FALSE, MCI_SCHD_INFO, 16, pld);
1557 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1558 "(MCI) SCHED idx=%d, T1=0x%08x (%d), T2=0x%08x (%d)\n",
1559 sched_idx,
1560 pld[0], pld[0], pld[1], pld[1]);
1561 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1562 "(MCI) SCHED addr=%d %s pwr=%d prio=%d %s link=%d\n",
1563 pld8[11] >> 4,
1564 (pld8[11] & 0x08)?"TX":"RX",
1565 (int8_t) (((pld8[11] & 0x07) << 5) | (pld8[10] >> 3)),
1566 (((pld8[10] & 0x07) << 5) | (pld8[9] >> 3)),
1567 (pld8[9] & 0x04)?"LE":"BR/EDR",
1568 (((pld8[9] & 0x03) << 2) | (pld8[8] >> 6)));
1569 }
1570 }
1571 #endif /* AH_MCI_DEBUG_PRINT_SCHED */
1572
1573 /* Make it in bytes */
1574 value <<= 4;
1575 break;
1576
1577 case HAL_MCI_STATE_REMOTE_SLEEP:
1578 value = MS(OS_REG_READ(ah, AR_MCI_RX_STATUS),
1579 AR_MCI_RX_REMOTE_SLEEP) ? MCI_BT_SLEEP : MCI_BT_AWAKE;
1580 break;
1581
1582 case HAL_MCI_STATE_CONT_RSSI_POWER:
1583 value = MS(ahp->ah_mci_cont_status,
1584 AR_MCI_CONT_RSSI_POWER);
1585 break;
1586
1587 case HAL_MCI_STATE_CONT_PRIORITY:
1588 value = MS(ahp->ah_mci_cont_status,
1589 AR_MCI_CONT_RRIORITY);
1590 break;
1591
1592 case HAL_MCI_STATE_CONT_TXRX:
1593 value = MS(ahp->ah_mci_cont_status,
1594 AR_MCI_CONT_TXRX);
1595 break;
1596
1597 case HAL_MCI_STATE_BT:
1598 value = ahp->ah_mci_bt_state;
1599 break;
1600
1601 case HAL_MCI_STATE_SET_BT_SLEEP:
1602 ahp->ah_mci_bt_state = MCI_BT_SLEEP;
1603 break;
1604
1605 case HAL_MCI_STATE_SET_BT_AWAKE:
1606 ahp->ah_mci_bt_state = MCI_BT_AWAKE;
1607 ar9300_mci_send_coex_version_query(ah, AH_TRUE);
1608 ar9300_mci_send_coex_wlan_channels(ah, AH_TRUE);
1609 if (ahp->ah_mci_unhalt_bt_gpm == AH_TRUE) {
1610 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1611 "(MCI) %s: UNHALT BT GPM\n", __func__);
1612 ar9300_mci_send_coex_halt_bt_gpm(ah, AH_FALSE, AH_TRUE);
1613 }
1614 ar9300_mci_2g5g_switch(ah, AH_TRUE);
1615 break;
1616
1617 case HAL_MCI_STATE_SET_BT_CAL_START:
1618 ahp->ah_mci_bt_state = MCI_BT_CAL_START;
1619 break;
1620
1621 case HAL_MCI_STATE_SET_BT_CAL:
1622 ahp->ah_mci_bt_state = MCI_BT_CAL;
1623 break;
1624
1625 case HAL_MCI_STATE_RESET_REQ_WAKE:
1626 ar9300_mci_reset_req_wakeup(ah);
1627 ahp->ah_mci_coex_2g5g_update = AH_TRUE;
1628
1629 if ((AR_SREV_JUPITER_20_OR_LATER(ah) || AR_SREV_APHRODITE(ah)) &&
1630 (ah->ah_config.ath_hal_mci_config &
1631 ATH_MCI_CONFIG_MCI_OBS_MASK))
1632 {
1633 /* Check if we still have control of the GPIOs */
1634 if ((OS_REG_READ(ah, AR_GLB_GPIO_CONTROL) &
1635 ATH_MCI_CONFIG_MCI_OBS_GPIO) !=
1636 ATH_MCI_CONFIG_MCI_OBS_GPIO)
1637 {
1638 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1639 "(MCI) Reconfigure observation\n");
1640 ar9300_mci_observation_set_up(ah);
1641 }
1642 }
1643
1644 break;
1645
1646 case HAL_MCI_STATE_SEND_WLAN_COEX_VERSION:
1647 ar9300_mci_send_coex_version_response(ah, AH_TRUE);
1648 break;
1649
1650 case HAL_MCI_STATE_SET_BT_COEX_VERSION:
1651 if (p_data == NULL) {
1652 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1653 "(MCI) Error: Set BT Coex version with NULL data !!!\n");
1654 }
1655 else {
1656 ahp->ah_mci_coex_major_version_bt = (*p_data >> 8) & 0xff;
1657 ahp->ah_mci_coex_minor_version_bt = (*p_data) & 0xff;
1658 ahp->ah_mci_coex_bt_version_known = AH_TRUE;
1659 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) BT version set: %d.%d\n",
1660 ahp->ah_mci_coex_major_version_bt,
1661 ahp->ah_mci_coex_minor_version_bt);
1662 }
1663 break;
1664
1665 case HAL_MCI_STATE_SEND_WLAN_CHANNELS:
1666 if (p_data != NULL)
1667 {
1668 if (((ahp->ah_mci_coex_wlan_channels[1] & 0xffff0000) ==
1669 (*(p_data + 1) & 0xffff0000)) &&
1670 (ahp->ah_mci_coex_wlan_channels[2] == *(p_data + 2)) &&
1671 (ahp->ah_mci_coex_wlan_channels[3] == *(p_data + 3)))
1672 {
1673 break;
1674 }
1675 ahp->ah_mci_coex_wlan_channels[0] = *p_data++;
1676 ahp->ah_mci_coex_wlan_channels[1] = *p_data++;
1677 ahp->ah_mci_coex_wlan_channels[2] = *p_data++;
1678 ahp->ah_mci_coex_wlan_channels[3] = *p_data++;
1679 }
1680 ahp->ah_mci_coex_wlan_channels_update = AH_TRUE;
1681 ar9300_mci_send_coex_wlan_channels(ah, AH_TRUE);
1682 break;
1683
1684 case HAL_MCI_STATE_SEND_VERSION_QUERY:
1685 ar9300_mci_send_coex_version_query(ah, AH_TRUE);
1686 break;
1687
1688 case HAL_MCI_STATE_SEND_STATUS_QUERY:
1689 if (AR_SREV_JUPITER_10(ah)) {
1690 ar9300_mci_send_coex_bt_status_query(ah, AH_TRUE,
1691 MCI_GPM_COEX_QUERY_BT_ALL_INFO);
1692 } else {
1693 ar9300_mci_send_coex_bt_status_query(ah, AH_TRUE,
1694 MCI_GPM_COEX_QUERY_BT_TOPOLOGY);
1695 }
1696 break;
1697
1698 case HAL_MCI_STATE_NEED_FLUSH_BT_INFO:
1699 /*
1700 * ah_mci_unhalt_bt_gpm means whether it's needed to send
1701 * UNHALT message. It's set whenever there's a request to send HALT
1702 * message. ah_mci_halted_bt_gpm means whether HALT message is sent
1703 * out successfully.
1704 *
1705 * Checking (ah_mci_unhalt_bt_gpm == AH_FALSE) instead of checking
1706 * (ahp->ah_mci_halted_bt_gpm == AH_FALSE) will make sure currently is
1707 * in UNHALT-ed mode and BT can respond to status query.
1708 */
1709 if ((ahp->ah_mci_unhalt_bt_gpm == AH_FALSE) &&
1710 (ahp->ah_mci_need_flush_btinfo == AH_TRUE))
1711 {
1712 value = 1;
1713 }
1714 else {
1715 value = 0;
1716 }
1717 if (p_data != NULL) {
1718 ahp->ah_mci_need_flush_btinfo = (*p_data != 0)? AH_TRUE : AH_FALSE;
1719 }
1720 break;
1721
1722 case HAL_MCI_STATE_SET_CONCUR_TX_PRI:
1723 if (p_data) {
1724 ahp->ah_mci_stomp_none_tx_pri = *p_data & 0xff;
1725 ahp->ah_mci_stomp_low_tx_pri = (*p_data >> 8) & 0xff;
1726 ahp->ah_mci_stomp_all_tx_pri = (*p_data >> 16) & 0xff;
1727 }
1728 break;
1729
1730 case HAL_MCI_STATE_RECOVER_RX:
1731 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) hal RECOVER_RX\n");
1732 ar9300_mci_prep_interface(ah);
1733 ahp->ah_mci_query_bt = AH_TRUE;
1734 ahp->ah_mci_need_flush_btinfo = AH_TRUE;
1735 ar9300_mci_send_coex_wlan_channels(ah, AH_TRUE);
1736 ar9300_mci_2g5g_switch(ah, AH_TRUE);
1737 break;
1738
1739 case HAL_MCI_STATE_DEBUG:
1740 if (p_data != NULL) {
1741 if (*p_data == HAL_MCI_STATE_DEBUG_REQ_BT_DEBUG) {
1742 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) QUERY_BT_DEBUG\n");
1743 ar9300_mci_send_coex_bt_status_query(ah, AH_TRUE,
1744 MCI_GPM_COEX_QUERY_BT_DEBUG);
1745 OS_DELAY(10);
1746 if (AR_SREV_JUPITER_20_OR_LATER(ah) || AR_SREV_APHRODITE(ah)) {
1747 ar9300_mci_send_coex_bt_flags(ah, AH_TRUE,
1748 MCI_GPM_COEX_BT_FLAGS_READ, 0);
1749 }
1750 }
1751 }
1752 break;
1753
1754 case HAL_MCI_STATE_NEED_FTP_STOMP:
1755 value = (ah->ah_config.ath_hal_mci_config &
1756 ATH_MCI_CONFIG_DISABLE_FTP_STOMP) ? 0 : 1;
1757 break;
1758
1759 case HAL_MCI_STATE_NEED_TUNING:
1760 value = (ah->ah_config.ath_hal_mci_config &
1761 ATH_MCI_CONFIG_DISABLE_TUNING) ? 0 : 1;
1762 break;
1763
1764 case HAL_MCI_STATE_SHARED_CHAIN_CONCUR_TX:
1765 value = ((ah->ah_config.ath_hal_mci_config &
1766 ATH_MCI_CONFIG_CONCUR_TX) ==
1767 ATH_MCI_CONCUR_TX_SHARED_CHN)? 1 : 0;
1768 break;
1769
1770 default:
1771 break;
1772 }
1773 return value;
1774 }
1775
ar9300_mci_detach(struct ath_hal * ah)1776 void ar9300_mci_detach(struct ath_hal *ah)
1777 {
1778 /* Turn off MCI and Jupiter mode. */
1779 OS_REG_WRITE(ah, AR_BTCOEX_CTRL, 0x00);
1780 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) ar9300_mci_detach\n");
1781 ar9300_mci_disable_interrupt(ah);
1782 }
1783
1784 /*
1785 * Low priority BT: 0 - 59(0x3b)
1786 * High priority BT: 60 - 125(0x7d)
1787 * Critical BT: 126 - 255
1788
1789 BTCOEX_WL_WEIGHTS0_VALUE0 ; // wl_idle
1790 BTCOEX_WL_WEIGHTS0_VALUE1 ; // sw_ctrl[3] - all_stomp
1791 BTCOEX_WL_WEIGHTS0_VALUE2 ; // sw_ctrl[2] - all_not_stomp
1792 BTCOEX_WL_WEIGHTS0_VALUE3 ; // sw_ctrl[1] - pa_pre_distortion
1793 BTCOEX_WL_WEIGHTS1_VALUE0 ; // sw_ctrl[0] - general purpose
1794 BTCOEX_WL_WEIGHTS1_VALUE1 ; // tm_wl_wait_beacon
1795 BTCOEX_WL_WEIGHTS1_VALUE2 ; // ts_state_wait_ack_cts
1796 BTCOEX_WL_WEIGHTS1_VALUE3 ; // self_gen
1797 BTCOEX_WL_WEIGHTS2_VALUE0 ; // idle
1798 BTCOEX_WL_WEIGHTS2_VALUE1 ; // rx
1799 BTCOEX_WL_WEIGHTS2_VALUE2 ; // tx
1800 BTCOEX_WL_WEIGHTS2_VALUE3 ; // rx + tx
1801 BTCOEX_WL_WEIGHTS3_VALUE0 ; // tx
1802 BTCOEX_WL_WEIGHTS3_VALUE1 ; // rx
1803 BTCOEX_WL_WEIGHTS3_VALUE2 ; // tx
1804 BTCOEX_WL_WEIGHTS3_VALUE3 ; // rx + tx
1805
1806 Stomp all:
1807 ah_bt_coex_wlan_weight[0] = 0x00007d00
1808 ah_bt_coex_wlan_weight[1] = 0x7d7d7d00
1809 ah_bt_coex_wlan_weight[2] = 0x7d7d7d00
1810 ah_bt_coex_wlan_weight[3] = 0x7d7d7d7d
1811 Stomp low:
1812 ah_bt_coex_wlan_weight[0] = 0x00007d00
1813 ah_bt_coex_wlan_weight[1] = 0x7d3b3b00
1814 ah_bt_coex_wlan_weight[2] = 0x3b3b3b00
1815 ah_bt_coex_wlan_weight[3] = 0x3b3b3b3b
1816 Stomp none:
1817 ah_bt_coex_wlan_weight[0] = 0x00007d00
1818 ah_bt_coex_wlan_weight[1] = 0x7d000000
1819 ah_bt_coex_wlan_weight[2] = 0x00000000
1820 ah_bt_coex_wlan_weight[3] = 0x00000000
1821 */
1822
ar9300_mci_bt_coex_set_weights(struct ath_hal * ah,u_int32_t stomp_type)1823 void ar9300_mci_bt_coex_set_weights(struct ath_hal *ah, u_int32_t stomp_type)
1824 {
1825 struct ath_hal_9300 *ahp = AH9300(ah);
1826 // struct ath_hal_private *ahpriv = AH_PRIVATE(ah);
1827 u_int32_t tx_priority = 0;
1828
1829 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "%s: stomp_type=%d\n", __func__, stomp_type);
1830
1831 switch (stomp_type) {
1832 case HAL_BT_COEX_STOMP_ALL:
1833 ahp->ah_bt_coex_wlan_weight[0] = JUPITER_STOMP_ALL_WLAN_WGHT0;
1834 ahp->ah_bt_coex_wlan_weight[1] = JUPITER_STOMP_ALL_WLAN_WGHT1;
1835 ahp->ah_bt_coex_wlan_weight[2] = JUPITER_STOMP_ALL_WLAN_WGHT2;
1836 ahp->ah_bt_coex_wlan_weight[3] = JUPITER_STOMP_ALL_WLAN_WGHT3;
1837 if (ahp->ah_mci_concur_tx_en && ahp->ah_mci_stomp_all_tx_pri) {
1838 tx_priority = ahp->ah_mci_stomp_all_tx_pri;
1839 }
1840 break;
1841 case HAL_BT_COEX_STOMP_LOW:
1842 if (ahp->ah_bt_coex_flag & HAL_BT_COEX_FLAG_MCI_FTP_STOMP_RX) {
1843 ahp->ah_bt_coex_wlan_weight[0] = JUPITER_STOMP_LOW_FTP_WLAN_WGHT0;
1844 ahp->ah_bt_coex_wlan_weight[1] = JUPITER_STOMP_LOW_FTP_WLAN_WGHT1;
1845 ahp->ah_bt_coex_wlan_weight[2] = JUPITER_STOMP_LOW_FTP_WLAN_WGHT2;
1846 ahp->ah_bt_coex_wlan_weight[3] = JUPITER_STOMP_LOW_FTP_WLAN_WGHT3;
1847 }
1848 else {
1849 ahp->ah_bt_coex_wlan_weight[0] = JUPITER_STOMP_LOW_WLAN_WGHT0;
1850 ahp->ah_bt_coex_wlan_weight[1] = JUPITER_STOMP_LOW_WLAN_WGHT1;
1851 ahp->ah_bt_coex_wlan_weight[2] = JUPITER_STOMP_LOW_WLAN_WGHT2;
1852 ahp->ah_bt_coex_wlan_weight[3] = JUPITER_STOMP_LOW_WLAN_WGHT3;
1853 }
1854 if (ahp->ah_mci_concur_tx_en && ahp->ah_mci_stomp_low_tx_pri) {
1855 tx_priority = ahp->ah_mci_stomp_low_tx_pri;
1856 }
1857 if (ah->ah_config.ath_hal_mci_config &
1858 ATH_MCI_CONFIG_MCI_OBS_TXRX)
1859 {
1860 ar9300_gpio_set(ah, 5, 1);
1861 }
1862 break;
1863 case HAL_BT_COEX_STOMP_ALL_FORCE:
1864 ahp->ah_bt_coex_wlan_weight[0] = JUPITER_STOMP_ALL_FORCE_WLAN_WGHT0;
1865 ahp->ah_bt_coex_wlan_weight[1] = JUPITER_STOMP_ALL_FORCE_WLAN_WGHT1;
1866 ahp->ah_bt_coex_wlan_weight[2] = JUPITER_STOMP_ALL_FORCE_WLAN_WGHT2;
1867 ahp->ah_bt_coex_wlan_weight[3] = JUPITER_STOMP_ALL_FORCE_WLAN_WGHT3;
1868 break;
1869 case HAL_BT_COEX_STOMP_LOW_FORCE:
1870 ahp->ah_bt_coex_wlan_weight[0] = JUPITER_STOMP_LOW_FORCE_WLAN_WGHT0;
1871 ahp->ah_bt_coex_wlan_weight[1] = JUPITER_STOMP_LOW_FORCE_WLAN_WGHT1;
1872 ahp->ah_bt_coex_wlan_weight[2] = JUPITER_STOMP_LOW_FORCE_WLAN_WGHT2;
1873 ahp->ah_bt_coex_wlan_weight[3] = JUPITER_STOMP_LOW_FORCE_WLAN_WGHT3;
1874 if (ahp->ah_mci_concur_tx_en && ahp->ah_mci_stomp_low_tx_pri) {
1875 tx_priority = ahp->ah_mci_stomp_low_tx_pri;
1876 }
1877 break;
1878 case HAL_BT_COEX_STOMP_NONE:
1879 case HAL_BT_COEX_NO_STOMP:
1880 ahp->ah_bt_coex_wlan_weight[0] = JUPITER_STOMP_NONE_WLAN_WGHT0;
1881 ahp->ah_bt_coex_wlan_weight[1] = JUPITER_STOMP_NONE_WLAN_WGHT1;
1882 ahp->ah_bt_coex_wlan_weight[2] = JUPITER_STOMP_NONE_WLAN_WGHT2;
1883 ahp->ah_bt_coex_wlan_weight[3] = JUPITER_STOMP_NONE_WLAN_WGHT3;
1884 if (ahp->ah_mci_concur_tx_en && ahp->ah_mci_stomp_none_tx_pri) {
1885 tx_priority = ahp->ah_mci_stomp_none_tx_pri;
1886 }
1887 if (ah->ah_config.ath_hal_mci_config &
1888 ATH_MCI_CONFIG_MCI_OBS_TXRX)
1889 {
1890 ar9300_gpio_set(ah, 5, 0);
1891 }
1892 break;
1893 case HAL_BT_COEX_STOMP_AUDIO:
1894 ahp->ah_bt_coex_wlan_weight[0] = 0xffffff01;
1895 ahp->ah_bt_coex_wlan_weight[1] = 0xffffffff;
1896 ahp->ah_bt_coex_wlan_weight[2] = 0xffffff01;
1897 ahp->ah_bt_coex_wlan_weight[3] = 0xffffffff;
1898 break;
1899 default:
1900 /* There is a forceWeight from registry */
1901 ahp->ah_bt_coex_wlan_weight[0] = stomp_type;
1902 ahp->ah_bt_coex_wlan_weight[1] = stomp_type;
1903 break;
1904 }
1905
1906 if (ahp->ah_mci_concur_tx_en && tx_priority) {
1907 ahp->ah_bt_coex_wlan_weight[1] &= ~MCI_CONCUR_TX_WLAN_WGHT1_MASK;
1908 ahp->ah_bt_coex_wlan_weight[1] |=
1909 SM(tx_priority, MCI_CONCUR_TX_WLAN_WGHT1_MASK);
1910 ahp->ah_bt_coex_wlan_weight[2] &= ~MCI_CONCUR_TX_WLAN_WGHT2_MASK;
1911 ahp->ah_bt_coex_wlan_weight[2] |=
1912 SM(tx_priority, MCI_CONCUR_TX_WLAN_WGHT2_MASK);
1913 ahp->ah_bt_coex_wlan_weight[3] &= ~MCI_CONCUR_TX_WLAN_WGHT3_MASK;
1914 ahp->ah_bt_coex_wlan_weight[3] |=
1915 SM(tx_priority, MCI_CONCUR_TX_WLAN_WGHT3_MASK);
1916 ahp->ah_bt_coex_wlan_weight[3] &= ~MCI_CONCUR_TX_WLAN_WGHT3_MASK2;
1917 ahp->ah_bt_coex_wlan_weight[3] |=
1918 SM(tx_priority, MCI_CONCUR_TX_WLAN_WGHT3_MASK2);
1919 }
1920 // if (ah->ah_config.ath_hal_mci_config &
1921 // ATH_MCI_CONFIG_MCI_WEIGHT_DBG)
1922 // {
1923 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1924 "(MCI) Set weights: 0x%08x 0x%08x 0x%08x 0x%08x\n",
1925 ahp->ah_bt_coex_wlan_weight[0],
1926 ahp->ah_bt_coex_wlan_weight[1],
1927 ahp->ah_bt_coex_wlan_weight[2],
1928 ahp->ah_bt_coex_wlan_weight[3]);
1929 // }
1930 }
1931
ar9300_mci_bt_coex_disable(struct ath_hal * ah)1932 void ar9300_mci_bt_coex_disable(struct ath_hal *ah)
1933 {
1934 struct ath_hal_9300 *ahp = AH9300(ah);
1935
1936 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1937 "(MCI) %s: Set weight to stomp none.\n", __func__);
1938
1939 ar9300_mci_bt_coex_set_weights(ah, HAL_BT_COEX_STOMP_NONE);
1940
1941 /*
1942 * In Jupiter, when coex is disabled, we just set weight
1943 * table to be in favor of WLAN.
1944 */
1945 OS_REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS0, ahp->ah_bt_coex_wlan_weight[0]);
1946 OS_REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS1, ahp->ah_bt_coex_wlan_weight[1]);
1947 OS_REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS2, ahp->ah_bt_coex_wlan_weight[2]);
1948 OS_REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS3, ahp->ah_bt_coex_wlan_weight[3]);
1949
1950 ahp->ah_bt_coex_enabled = AH_FALSE;
1951 }
1952
ar9300_mci_bt_coex_enable(struct ath_hal * ah)1953 int ar9300_mci_bt_coex_enable(struct ath_hal *ah)
1954 {
1955 struct ath_hal_9300 *ahp = AH9300(ah);
1956
1957 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) %s: called\n", __func__);
1958
1959 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1960 "(MCI) Write weights: 0x%08x 0x%08x 0x%08x 0x%08x\n",
1961 ahp->ah_bt_coex_wlan_weight[0],
1962 ahp->ah_bt_coex_wlan_weight[1],
1963 ahp->ah_bt_coex_wlan_weight[2],
1964 ahp->ah_bt_coex_wlan_weight[3]);
1965
1966
1967 /* Mainly change the WLAN weight table */
1968 OS_REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS0, ahp->ah_bt_coex_wlan_weight[0]);
1969 OS_REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS1, ahp->ah_bt_coex_wlan_weight[1]);
1970 OS_REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS2, ahp->ah_bt_coex_wlan_weight[2]);
1971 OS_REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS3, ahp->ah_bt_coex_wlan_weight[3]);
1972
1973 /* Send ACK even when BT has higher priority. */
1974 OS_REG_RMW_FIELD(ah, AR_QUIET1, AR_QUIET1_QUIET_ACK_CTS_ENABLE, 1);
1975
1976 if (ahp->ah_bt_coex_flag & HAL_BT_COEX_FLAG_LOW_ACK_PWR) {
1977 OS_REG_WRITE(ah, AR_TPC, HAL_BT_COEX_LOW_ACK_POWER);
1978 }
1979 else {
1980 OS_REG_WRITE(ah, AR_TPC, HAL_BT_COEX_HIGH_ACK_POWER);
1981 }
1982
1983 ahp->ah_bt_coex_enabled = AH_TRUE;
1984
1985 return 0;
1986 }
1987
1988 #endif /* ATH_SUPPORT_MCI */
1989