2 * Copyright (c) 2013 Qualcomm Atheros, Inc.
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.
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.
21 #include "ah_internal.h"
23 #include "ar9300/ar9300.h"
24 #include "ar9300/ar9300reg.h"
25 #include "ar9300/ar9300phy.h"
29 #define AH_MCI_REMOTE_RESET_INTERVAL_US 500
30 #define AH_MCI_DEBUG_PRINT_SCHED 0
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)
39 u_int8_t *p_data = (u_int8_t *) pl;
43 "(MCI) >>>>> Hdr: %02X, Len: %d, Payload:", hdr, len);
47 "(MCI) <<<<< Hdr: %02X, Len: %d, Payload:", hdr, len);
49 for ( i=0; i<len; i++)
51 p += snprintf(p, 60, " %02x", *(p_data + i));
53 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "%s\n", s);
55 for ( i=0; i<(len + 3)/4; i++)
57 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) 0x%08x\n", *(pl + i));
64 void ar9300_mci_osla_setup(struct ath_hal *ah, HAL_BOOL enable)
66 // struct ath_hal_9300 *ahp = AH9300(ah);
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);
73 if (!(ah->ah_config.ath_hal_mci_config &
74 ATH_MCI_CONFIG_DISABLE_AGGR_THRESH))
76 thresh = MS(ah->ah_config.ath_hal_mci_config,
77 ATH_MCI_CONFIG_AGGR_THRESH);
78 OS_REG_RMW_FIELD(ah, AR_BTCOEX_CTRL,
79 AR_BTCOEX_CTRL_AGGR_THRESH, thresh);
80 OS_REG_RMW_FIELD(ah, AR_BTCOEX_CTRL,
81 AR_BTCOEX_CTRL_TIME_TO_NEXT_BT_THRESH_EN, 1);
82 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
83 "(MCI) SCHED aggr thresh: on, thresh=%d (%d.%d%%)\n",
84 thresh, (thresh + 1)*125/10, (thresh + 1)*125%10);
88 OS_REG_RMW_FIELD(ah, AR_BTCOEX_CTRL,
89 AR_BTCOEX_CTRL_TIME_TO_NEXT_BT_THRESH_EN, 0);
90 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) SCHED aggr thresh: off\n");
92 OS_REG_RMW_FIELD(ah, AR_BTCOEX_CTRL,
93 AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN, 1);
94 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) SCHED one step look ahead: on\n");
97 OS_REG_CLR_BIT(ah, AR_BTCOEX_CTRL,
98 AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN);
99 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) SCHED one step look ahead: off\n");
103 static void ar9300_mci_reset_req_wakeup(struct ath_hal *ah)
105 /* to be tested in emulation */
106 if (AR_SREV_JUPITER_20(ah) || AR_SREV_APHRODITE(ah)) {
107 OS_REG_RMW_FIELD(ah, AR_MCI_COMMAND2,
108 AR_MCI_COMMAND2_RESET_REQ_WAKEUP, 1);
110 OS_REG_RMW_FIELD(ah, AR_MCI_COMMAND2,
111 AR_MCI_COMMAND2_RESET_REQ_WAKEUP, 0);
115 static int32_t ar9300_mci_wait_for_interrupt(struct ath_hal *ah,
117 u_int32_t bit_position,
123 data = OS_REG_READ(ah, address);
125 if (data & bit_position) {
126 OS_REG_WRITE(ah, address, bit_position);
127 if (address == AR_MCI_INTERRUPT_RX_MSG_RAW) {
128 if (bit_position & AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE) {
129 ar9300_mci_reset_req_wakeup(ah);
131 if (bit_position & (AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING |
132 AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING))
134 OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RAW,
135 AR_MCI_INTERRUPT_REMOTE_SLEEP_UPDATE);
137 OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, AR_MCI_INTERRUPT_RX_MSG);
150 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
151 "(MCI) %s: Wait for Reg0x%08x = 0x%08x timeout.\n",
152 __func__, address, bit_position);
153 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
154 "(MCI) INT_RAW = 0x%08x, RX_MSG_RAW = 0x%08x",
155 OS_REG_READ(ah, AR_MCI_INTERRUPT_RAW),
156 OS_REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_RAW));
162 void ar9300_mci_remote_reset(struct ath_hal *ah, HAL_BOOL wait_done)
164 u_int32_t payload[4] = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffff00};
166 ar9300_mci_send_message(ah, MCI_REMOTE_RESET, 0, payload, 16,
167 wait_done, AH_FALSE);
172 void ar9300_mci_send_lna_transfer(struct ath_hal *ah, HAL_BOOL wait_done)
174 u_int32_t payload = 0x00000000;
176 ar9300_mci_send_message(ah, MCI_LNA_TRANS, 0, &payload, 1,
177 wait_done, AH_FALSE);
180 static void ar9300_mci_send_req_wake(struct ath_hal *ah, HAL_BOOL wait_done)
182 ar9300_mci_send_message(ah, MCI_REQ_WAKE,
183 HAL_MCI_FLAG_DISABLE_TIMESTAMP, AH_NULL, 0, wait_done, AH_FALSE);
188 void ar9300_mci_send_sys_waking(struct ath_hal *ah, HAL_BOOL wait_done)
190 ar9300_mci_send_message(ah, MCI_SYS_WAKING,
191 HAL_MCI_FLAG_DISABLE_TIMESTAMP, AH_NULL, 0, wait_done, AH_FALSE);
194 static void ar9300_mci_send_lna_take(struct ath_hal *ah, HAL_BOOL wait_done)
196 u_int32_t payload = 0x70000000;
198 /* LNA gain index is set to 7. */
199 ar9300_mci_send_message(ah, MCI_LNA_TAKE,
200 HAL_MCI_FLAG_DISABLE_TIMESTAMP, &payload, 1, wait_done, AH_FALSE);
203 static void ar9300_mci_send_sys_sleeping(struct ath_hal *ah, HAL_BOOL wait_done)
205 ar9300_mci_send_message(ah, MCI_SYS_SLEEPING,
206 HAL_MCI_FLAG_DISABLE_TIMESTAMP, AH_NULL, 0, wait_done, AH_FALSE);
210 ar9300_mci_send_coex_version_query(struct ath_hal *ah, HAL_BOOL wait_done)
212 struct ath_hal_9300 *ahp = AH9300(ah);
213 u_int32_t payload[4] = {0, 0, 0, 0};
215 if ((ahp->ah_mci_coex_bt_version_known == AH_FALSE) &&
216 (ahp->ah_mci_bt_state != MCI_BT_SLEEP)) {
217 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) Send Coex version query.\n");
218 MCI_GPM_SET_TYPE_OPCODE(payload,
219 MCI_GPM_COEX_AGENT, MCI_GPM_COEX_VERSION_QUERY);
220 ar9300_mci_send_message(ah, MCI_GPM, 0, payload, 16, wait_done, AH_TRUE);
225 ar9300_mci_send_coex_version_response(struct ath_hal *ah, HAL_BOOL wait_done)
227 struct ath_hal_9300 *ahp = AH9300(ah);
228 u_int32_t payload[4] = {0, 0, 0, 0};
230 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) Send Coex version response.\n");
231 MCI_GPM_SET_TYPE_OPCODE(payload,
232 MCI_GPM_COEX_AGENT, MCI_GPM_COEX_VERSION_RESPONSE);
233 *(((u_int8_t *)payload) + MCI_GPM_COEX_B_MAJOR_VERSION) =
234 ahp->ah_mci_coex_major_version_wlan;
235 *(((u_int8_t *)payload) + MCI_GPM_COEX_B_MINOR_VERSION) =
236 ahp->ah_mci_coex_minor_version_wlan;
237 ar9300_mci_send_message(ah, MCI_GPM, 0, payload, 16, wait_done, AH_TRUE);
241 ar9300_mci_send_coex_wlan_channels(struct ath_hal *ah, HAL_BOOL wait_done)
243 struct ath_hal_9300 *ahp = AH9300(ah);
244 u_int32_t *payload = &ahp->ah_mci_coex_wlan_channels[0];
246 if ((ahp->ah_mci_coex_wlan_channels_update == AH_TRUE) &&
247 (ahp->ah_mci_bt_state != MCI_BT_SLEEP))
249 MCI_GPM_SET_TYPE_OPCODE(payload,
250 MCI_GPM_COEX_AGENT, MCI_GPM_COEX_WLAN_CHANNELS);
251 ar9300_mci_send_message(ah, MCI_GPM, 0, payload, 16, wait_done, AH_TRUE);
252 MCI_GPM_SET_TYPE_OPCODE(payload, 0xff, 0xff);
256 static void ar9300_mci_send_coex_bt_status_query(struct ath_hal *ah,
257 HAL_BOOL wait_done, u_int8_t query_type)
259 struct ath_hal_9300 *ahp = AH9300(ah);
260 u_int32_t pld[4] = {0, 0, 0, 0};
261 HAL_BOOL query_btinfo = query_type &
262 (MCI_GPM_COEX_QUERY_BT_ALL_INFO | MCI_GPM_COEX_QUERY_BT_TOPOLOGY);
264 if (ahp->ah_mci_bt_state != MCI_BT_SLEEP) {
265 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
266 "(MCI) Send Coex BT Status Query 0x%02X\n", query_type);
267 MCI_GPM_SET_TYPE_OPCODE(pld,
268 MCI_GPM_COEX_AGENT, MCI_GPM_COEX_STATUS_QUERY);
269 *(((u_int8_t *)pld) + MCI_GPM_COEX_B_BT_BITMAP) = query_type;
271 * If bt_status_query message is thought not sent successfully,
272 * then ah_mci_need_flush_btinfo should be set again.
274 if (!ar9300_mci_send_message(ah, MCI_GPM, 0, pld, 16, wait_done, AH_TRUE))
277 ahp->ah_mci_need_flush_btinfo = AH_TRUE;
278 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
279 "(MCI) send bt_status_query fail, set flush flag again\n");
283 ahp->ah_mci_query_bt = AH_FALSE;
288 void ar9300_mci_send_coex_halt_bt_gpm(struct ath_hal *ah,
289 HAL_BOOL halt, HAL_BOOL wait_done)
291 struct ath_hal_9300 *ahp = AH9300(ah);
292 u_int32_t payload[4] = {0, 0, 0, 0};
294 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
295 "(MCI) Send Coex %s BT GPM.\n", (halt == AH_TRUE)?"HALT":"UNHALT");
297 MCI_GPM_SET_TYPE_OPCODE(payload,
298 MCI_GPM_COEX_AGENT, MCI_GPM_COEX_HALT_BT_GPM);
299 if (halt == AH_TRUE) {
300 ahp->ah_mci_query_bt = AH_TRUE;
301 /* Send next UNHALT no matter HALT sent or not */
302 ahp->ah_mci_unhalt_bt_gpm = AH_TRUE;
303 ahp->ah_mci_need_flush_btinfo = AH_TRUE;
304 *(((u_int8_t *)payload) + MCI_GPM_COEX_B_HALT_STATE) =
305 MCI_GPM_COEX_BT_GPM_HALT;
308 *(((u_int8_t *)payload) + MCI_GPM_COEX_B_HALT_STATE) =
309 MCI_GPM_COEX_BT_GPM_UNHALT;
311 ar9300_mci_send_message(ah, MCI_GPM, 0, payload, 16, wait_done, AH_TRUE);
314 static HAL_BOOL ar9300_mci_send_coex_bt_flags(struct ath_hal *ah, HAL_BOOL wait_done,
315 u_int8_t opcode, u_int32_t bt_flags)
317 // struct ath_hal_9300 *ahp = AH9300(ah);
318 u_int32_t pld[4] = {0, 0, 0, 0};
320 MCI_GPM_SET_TYPE_OPCODE(pld,
321 MCI_GPM_COEX_AGENT, MCI_GPM_COEX_BT_UPDATE_FLAGS);
323 *(((u_int8_t *)pld) + MCI_GPM_COEX_B_BT_FLAGS_OP) = opcode;
324 *(((u_int8_t *)pld) + MCI_GPM_COEX_W_BT_FLAGS + 0) = bt_flags & 0xFF;
325 *(((u_int8_t *)pld) + MCI_GPM_COEX_W_BT_FLAGS + 1) =
326 (bt_flags >> 8) & 0xFF;
327 *(((u_int8_t *)pld) + MCI_GPM_COEX_W_BT_FLAGS + 2) =
328 (bt_flags >> 16) & 0xFF;
329 *(((u_int8_t *)pld) + MCI_GPM_COEX_W_BT_FLAGS + 3) =
330 (bt_flags >> 24) & 0xFF;
332 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
333 "(MCI) BT_MCI_FLAGS: Send Coex BT Update Flags %s 0x%08x\n",
334 (opcode == MCI_GPM_COEX_BT_FLAGS_READ)?"READ":
335 ((opcode == MCI_GPM_COEX_BT_FLAGS_SET)?"SET":"CLEAR"),
338 return ar9300_mci_send_message(ah, MCI_GPM, 0, pld, 16, wait_done, AH_TRUE);
341 void ar9300_mci_2g5g_changed(struct ath_hal *ah, HAL_BOOL is_2g)
343 struct ath_hal_9300 *ahp = AH9300(ah);
345 if (ahp->ah_mci_coex_2g5g_update == AH_FALSE) {
346 if (ahp->ah_mci_coex_is_2g == is_2g) {
347 //HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) BT_MCI_FLAGS: not changed\n");
349 ahp->ah_mci_coex_2g5g_update = AH_TRUE;
350 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) BT_MCI_FLAGS: changed\n");
353 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) BT_MCI_FLAGS: force send\n");
355 ahp->ah_mci_coex_is_2g = is_2g;
358 static void ar9300_mci_send_2g5g_status(struct ath_hal *ah, HAL_BOOL wait_done)
360 struct ath_hal_9300 *ahp = AH9300(ah);
361 u_int32_t new_flags, to_set, to_clear;
363 if ((AR_SREV_JUPITER_20(ah) || AR_SREV_APHRODITE(ah)) &&
364 (ahp->ah_mci_coex_2g5g_update == AH_TRUE) &&
365 (ahp->ah_mci_bt_state != MCI_BT_SLEEP))
367 if (ahp->ah_mci_coex_is_2g) {
368 new_flags = HAL_MCI_2G_FLAGS;
369 to_clear = HAL_MCI_2G_FLAGS_CLEAR_MASK;
370 to_set = HAL_MCI_2G_FLAGS_SET_MASK;
372 new_flags = HAL_MCI_5G_FLAGS;
373 to_clear = HAL_MCI_5G_FLAGS_CLEAR_MASK;
374 to_set = HAL_MCI_5G_FLAGS_SET_MASK;
376 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
377 "(MCI) BT_MCI_FLAGS: %s (0x%08x) clr=0x%08x, set=0x%08x\n",
378 ahp->ah_mci_coex_is_2g?"2G":"5G", new_flags, to_clear, to_set);
380 ar9300_mci_send_coex_bt_flags(ah, wait_done,
381 MCI_GPM_COEX_BT_FLAGS_CLEAR, to_clear);
384 ar9300_mci_send_coex_bt_flags(ah, wait_done,
385 MCI_GPM_COEX_BT_FLAGS_SET, to_set);
388 if (AR_SREV_JUPITER_10(ah) && (ahp->ah_mci_bt_state != MCI_BT_SLEEP)) {
389 ahp->ah_mci_coex_2g5g_update = AH_FALSE;
393 void ar9300_mci_2g5g_switch(struct ath_hal *ah, HAL_BOOL wait_done)
395 struct ath_hal_9300 *ahp = AH9300(ah);
397 if (ahp->ah_mci_coex_2g5g_update)
399 if (ahp->ah_mci_coex_is_2g) {
400 ar9300_mci_send_2g5g_status(ah, AH_TRUE);
402 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) Send LNA trans\n");
403 ar9300_mci_send_lna_transfer(ah, AH_TRUE);
406 OS_REG_CLR_BIT(ah, AR_MCI_TX_CTRL,
407 AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE);
408 if (AR_SREV_JUPITER_20(ah) || AR_SREV_APHRODITE(ah)) {
409 OS_REG_CLR_BIT(ah, AR_GLB_CONTROL,
410 AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL);
411 if (!(ah->ah_config.ath_hal_mci_config &
412 ATH_MCI_CONFIG_DISABLE_OSLA))
414 ar9300_mci_osla_setup(ah, AH_TRUE);
418 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) Send LNA take\n");
419 ar9300_mci_send_lna_take(ah, AH_TRUE);
422 OS_REG_SET_BIT(ah, AR_MCI_TX_CTRL,
423 AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE);
424 if (AR_SREV_JUPITER_20(ah) || AR_SREV_APHRODITE(ah)) {
425 OS_REG_SET_BIT(ah, AR_GLB_CONTROL,
426 AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL);
427 ar9300_mci_osla_setup(ah, AH_FALSE);
430 ar9300_mci_send_2g5g_status(ah, AH_TRUE);
435 * Update self gen chain mask. Also set basic set for
438 if (AR_SREV_JUPITER(ah)) {
439 if (ahp->ah_mci_coex_is_2g) {
440 ahp->ah_reduced_self_gen_mask = AH_TRUE;
441 OS_REG_WRITE(ah, AR_SELFGEN_MASK, 0x02);
442 ar9300_txbf_set_basic_set(ah);
445 ahp->ah_reduced_self_gen_mask = AH_FALSE;
446 ar9300_txbf_set_basic_set(ah);
451 void ar9300_mci_mute_bt(struct ath_hal *ah)
453 /* disable all MCI messages */
454 OS_REG_WRITE(ah, AR_MCI_MSG_ATTRIBUTES_TABLE, 0xFFFF0000);
455 OS_REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS0, 0xFFFFFFFF);
456 OS_REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS1, 0xFFFFFFFF);
457 OS_REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS2, 0xFFFFFFFF);
458 OS_REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS3, 0xFFFFFFFF);
459 OS_REG_SET_BIT(ah, AR_MCI_TX_CTRL, AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE);
460 /* wait pending HW messages to flush out */
464 * Send LNA_TAKE and SYS_SLEEPING when
465 * 1. reset not after resuming from full sleep
466 * 2. before reset MCI RX, to quiet BT and avoid MCI RX misalignment
468 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) Send LNA take\n");
469 ar9300_mci_send_lna_take(ah, AH_TRUE);
471 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) Send sys sleeping\n");
472 ar9300_mci_send_sys_sleeping(ah, AH_TRUE);
475 static void ar9300_mci_observation_set_up(struct ath_hal *ah)
478 * Set up the observation bus in order to monitor MCI bus
479 * through GPIOs (0, 1, 2, and 3).
482 OS_REG_WRITE(ah, AR_GPIO_INTR_POL, 0x00420000);
483 OS_REG_WRITE(ah, AR_GPIO_OE_OUT, 0x000000ff); // 4050
484 OS_REG_WRITE(ah, AR_GPIO_OUTPUT_MUX1, 0x000bdab4); // 4068
485 OS_REG_WRITE(ah, AR_OBS, 0x0000004b); // 4088
486 OS_REG_WRITE(ah, AR_DIAG_SW, 0x080c0000);
487 OS_REG_WRITE(ah, AR_MACMISC, 0x0001a000);
488 OS_REG_WRITE(ah, AR_PHY_TEST, 0x00080000); // a360
489 OS_REG_WRITE(ah, AR_PHY_TEST_CTL_STATUS, 0xe0000000); // a364
492 if (ah->ah_config.ath_hal_mci_config &
493 ATH_MCI_CONFIG_MCI_OBS_MCI)
495 ar9300_gpio_cfg_output(ah, 3, HAL_GPIO_OUTPUT_MUX_AS_MCI_WLAN_DATA);
496 ar9300_gpio_cfg_output(ah, 2, HAL_GPIO_OUTPUT_MUX_AS_MCI_WLAN_CLK);
497 ar9300_gpio_cfg_output(ah, 1, HAL_GPIO_OUTPUT_MUX_AS_MCI_BT_DATA);
498 ar9300_gpio_cfg_output(ah, 0, HAL_GPIO_OUTPUT_MUX_AS_MCI_BT_CLK);
500 else if (ah->ah_config.ath_hal_mci_config &
501 ATH_MCI_CONFIG_MCI_OBS_TXRX)
503 ar9300_gpio_cfg_output(ah, 3, HAL_GPIO_OUTPUT_MUX_AS_WL_IN_TX);
504 ar9300_gpio_cfg_output(ah, 2, HAL_GPIO_OUTPUT_MUX_AS_WL_IN_RX);
505 ar9300_gpio_cfg_output(ah, 1, HAL_GPIO_OUTPUT_MUX_AS_BT_IN_TX);
506 ar9300_gpio_cfg_output(ah, 0, HAL_GPIO_OUTPUT_MUX_AS_BT_IN_RX);
507 ar9300_gpio_cfg_output(ah, 5, HAL_GPIO_OUTPUT_MUX_AS_OUTPUT);
509 else if (ah->ah_config.ath_hal_mci_config &
510 ATH_MCI_CONFIG_MCI_OBS_BT)
512 ar9300_gpio_cfg_output(ah, 3, HAL_GPIO_OUTPUT_MUX_AS_BT_IN_TX);
513 ar9300_gpio_cfg_output(ah, 2, HAL_GPIO_OUTPUT_MUX_AS_BT_IN_RX);
514 ar9300_gpio_cfg_output(ah, 1, HAL_GPIO_OUTPUT_MUX_AS_MCI_BT_DATA);
515 ar9300_gpio_cfg_output(ah, 0, HAL_GPIO_OUTPUT_MUX_AS_MCI_BT_CLK);
522 AR_HOSTIF_REG(ah, AR_GPIO_INPUT_EN_VAL), AR_GPIO_JTAG_DISABLE);
524 if (AR_SREV_JUPITER_20_OR_LATER(ah) || AR_SREV_APHRODITE(ah)) {
525 OS_REG_RMW_FIELD(ah, AR_GLB_CONTROL, AR_GLB_DS_JTAG_DISABLE, 1);
526 OS_REG_RMW_FIELD(ah, AR_GLB_CONTROL, AR_GLB_WLAN_UART_INTF_EN, 0);
527 OS_REG_WRITE(ah, AR_GLB_GPIO_CONTROL,
528 (OS_REG_READ(ah, AR_GLB_GPIO_CONTROL) |
529 ATH_MCI_CONFIG_MCI_OBS_GPIO));
532 OS_REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2, AR_BTCOEX_CTRL2_GPIO_OBS_SEL, 0);
533 OS_REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2, AR_BTCOEX_CTRL2_MAC_BB_OBS_SEL, 1);
534 OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_OBS), 0x4b);
535 OS_REG_RMW_FIELD(ah, AR_DIAG_SW, AR_DIAG_OBS_PT_SEL1, 0x03);
536 OS_REG_RMW_FIELD(ah, AR_DIAG_SW, AR_DIAG_OBS_PT_SEL2, 0x01);
537 OS_REG_RMW_FIELD(ah, AR_MACMISC, AR_MACMISC_MISC_OBS_BUS_LSB, 0x02);
538 OS_REG_RMW_FIELD(ah, AR_MACMISC, AR_MACMISC_MISC_OBS_BUS_MSB, 0x03);
539 //OS_REG_RMW_FIELD(ah, AR_PHY_TEST, AR_PHY_TEST_BBB_OBS_SEL, 0x01);
540 OS_REG_RMW_FIELD(ah, AR_PHY_TEST_CTL_STATUS,
541 AR_PHY_TEST_CTL_DEBUGPORT_SEL, 0x07);
544 static void ar9300_mci_process_gpm_extra(struct ath_hal *ah,
545 u_int8_t gpm_type, u_int8_t gpm_opcode, u_int32_t *p_gpm)
547 struct ath_hal_9300 *ahp = AH9300(ah);
548 u_int8_t *p_data = (u_int8_t *) p_gpm;
552 case MCI_GPM_COEX_AGENT:
555 case MCI_GPM_COEX_VERSION_QUERY:
556 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
557 "(MCI) Recv GPM COEX Version Query.\n");
558 ar9300_mci_send_coex_version_response(ah, AH_TRUE);
561 case MCI_GPM_COEX_VERSION_RESPONSE:
562 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
563 "(MCI) Recv GPM COEX Version Response.\n");
564 ahp->ah_mci_coex_major_version_bt =
565 *(p_data + MCI_GPM_COEX_B_MAJOR_VERSION);
566 ahp->ah_mci_coex_minor_version_bt =
567 *(p_data + MCI_GPM_COEX_B_MINOR_VERSION);
568 ahp->ah_mci_coex_bt_version_known = AH_TRUE;
569 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
570 "(MCI) BT Coex version: %d.%d\n",
571 ahp->ah_mci_coex_major_version_bt,
572 ahp->ah_mci_coex_minor_version_bt);
575 case MCI_GPM_COEX_STATUS_QUERY:
576 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
577 "(MCI) Recv GPM COEX Status Query = 0x%02X.\n",
578 *(p_data + MCI_GPM_COEX_B_WLAN_BITMAP));
579 //if ((*(p_data + MCI_GPM_COEX_B_WLAN_BITMAP)) &
580 // MCI_GPM_COEX_QUERY_WLAN_ALL_INFO)
582 ahp->ah_mci_coex_wlan_channels_update = AH_TRUE;
583 ar9300_mci_send_coex_wlan_channels(ah, AH_TRUE);
587 case MCI_GPM_COEX_BT_PROFILE_INFO:
588 ahp->ah_mci_query_bt = AH_TRUE;
589 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
590 "(MCI) Recv GPM COEX BT_Profile_Info (drop&query)\n");
593 case MCI_GPM_COEX_BT_STATUS_UPDATE:
594 ahp->ah_mci_query_bt = AH_TRUE;
595 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
596 "(MCI) Recv GPM COEX BT_Status_Update "
597 "SEQ=%d (drop&query)\n",
609 u_int32_t ar9300_mci_wait_for_gpm(struct ath_hal *ah, u_int8_t gpm_type,
610 u_int8_t gpm_opcode, int32_t time_out)
612 u_int32_t *p_gpm = NULL, mismatch = 0, more_data = HAL_MCI_GPM_NOMORE;
613 struct ath_hal_9300 *ahp = AH9300(ah);
614 HAL_BOOL b_is_bt_cal_done = (gpm_type == MCI_GPM_BT_CAL_DONE);
616 u_int8_t recv_type = 0, recv_opcode = 0;
619 more_data = HAL_MCI_GPM_MORE;
625 MCI_GPM_RECYCLE(p_gpm);
629 if (more_data != HAL_MCI_GPM_MORE) {
630 time_out = ar9300_mci_wait_for_interrupt(ah,
631 AR_MCI_INTERRUPT_RX_MSG_RAW,
632 AR_MCI_INTERRUPT_RX_MSG_GPM,
637 offset = ar9300_mci_state(ah,
638 HAL_MCI_STATE_NEXT_GPM_OFFSET, &more_data);
640 if (offset == HAL_MCI_GPM_INVALID) {
643 p_gpm = (u_int32_t *) (ahp->ah_mci_gpm_buf + offset);
644 ar9300_mci_print_msg(ah, AH_FALSE, MCI_GPM, 16, p_gpm);
646 recv_type = MCI_GPM_TYPE(p_gpm);
647 recv_opcode = MCI_GPM_OPCODE(p_gpm);
649 if (MCI_GPM_IS_CAL_TYPE(recv_type)) {
650 if (recv_type == gpm_type) {
651 if ((gpm_type == MCI_GPM_BT_CAL_DONE) && !b_is_bt_cal_done)
653 gpm_type = MCI_GPM_BT_CAL_GRANT;
654 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
655 "(MCI) Rcv BT_CAL_DONE. Now Wait BT_CAL_GRANT\n");
658 if (gpm_type == MCI_GPM_BT_CAL_GRANT) {
659 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
660 "(MCI) BT_CAL_GRANT seq=%d, req_count=%d\n",
661 *(p_gpm + 2), *(p_gpm + 3));
667 if ((recv_type == gpm_type) && (recv_opcode == gpm_opcode)) {
672 /* not expected message */
675 * Check if it's cal_grant
677 * When we're waiting for cal_grant in reset routine, it's
678 * possible that BT sends out cal_request at the same time.
679 * Since BT's calibration doesn't happen that often, we'll
680 * let BT completes calibration then we continue to wait
681 * for cal_grant from BT.
682 * Orginal: Wait BT_CAL_GRANT.
683 * New: Receive BT_CAL_REQ -> send WLAN_CAL_GRANT -> wait
684 * BT_CAL_DONE -> Wait BT_CAL_GRANT.
686 if ((gpm_type == MCI_GPM_BT_CAL_GRANT) &&
687 (recv_type == MCI_GPM_BT_CAL_REQ))
689 u_int32_t payload[4] = {0, 0, 0, 0};
691 gpm_type = MCI_GPM_BT_CAL_DONE;
692 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
693 "(MCI) Rcv BT_CAL_REQ. Send WLAN_CAL_GRANT.\n");
695 MCI_GPM_SET_CAL_TYPE(payload, MCI_GPM_WLAN_CAL_GRANT);
696 ar9300_mci_send_message(ah, MCI_GPM, 0, payload, 16,
699 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
700 "(MCI) Now wait for BT_CAL_DONE.\n");
704 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
705 "(MCI) GPM subtype not match 0x%x\n", *(p_gpm + 1));
707 ar9300_mci_process_gpm_extra(ah, recv_type, recv_opcode, p_gpm);
712 MCI_GPM_RECYCLE(p_gpm);
718 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
719 "(MCI) GPM receiving timeout, mismatch = %d\n", mismatch);
721 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
722 "(MCI) Receive GPM type=0x%x, code=0x%x\n", gpm_type, gpm_opcode);
725 while (more_data == HAL_MCI_GPM_MORE) {
726 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) discard remaining GPM\n");
727 offset = ar9300_mci_state(ah,
728 HAL_MCI_STATE_NEXT_GPM_OFFSET, &more_data);
730 if (offset == HAL_MCI_GPM_INVALID) {
733 p_gpm = (u_int32_t *) (ahp->ah_mci_gpm_buf + offset);
734 ar9300_mci_print_msg(ah, AH_FALSE, MCI_GPM, 16, p_gpm);
735 recv_type = MCI_GPM_TYPE(p_gpm);
736 recv_opcode = MCI_GPM_OPCODE(p_gpm);
737 if (!MCI_GPM_IS_CAL_TYPE(recv_type)) {
738 ar9300_mci_process_gpm_extra(ah, recv_type, recv_opcode, p_gpm);
740 MCI_GPM_RECYCLE(p_gpm);
746 static void ar9300_mci_prep_interface(struct ath_hal *ah)
748 struct ath_hal_9300 *ahp = AH9300(ah);
749 u_int32_t saved_mci_int_en;
750 u_int32_t mci_timeout = 150;
752 ahp->ah_mci_bt_state = MCI_BT_SLEEP;
754 saved_mci_int_en = OS_REG_READ(ah, AR_MCI_INTERRUPT_EN);
755 OS_REG_WRITE(ah, AR_MCI_INTERRUPT_EN, 0);
757 OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,
758 OS_REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_RAW));
759 OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RAW,
760 OS_REG_READ(ah, AR_MCI_INTERRUPT_RAW));
763 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) %s: Reset sequence start\n", __func__);
764 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) send REMOTE_RESET\n");
765 ar9300_mci_remote_reset(ah, AH_TRUE);
768 * This delay is required for the reset delay worst case value 255 in
769 * MCI_COMMAND2 register
771 if (AR_SREV_JUPITER_10(ah)) {
775 /* Send REQ_WAKE to BT */
776 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) %s: Send REQ_WAKE to remote(BT)\n",
779 ar9300_mci_send_req_wake(ah, AH_TRUE);
781 if (ar9300_mci_wait_for_interrupt(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,
782 AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING, 500))
784 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
785 "(MCI) %s: Saw SYS_WAKING from remote(BT)\n", __func__);
786 ahp->ah_mci_bt_state = MCI_BT_AWAKE;
788 if (AR_SREV_JUPITER_10(ah)) {
792 * We don't need to send more remote_reset at this moment.
794 * If BT receive first remote_reset, then BT HW will be cleaned up and
795 * will be able to receive req_wake and BT HW will respond sys_waking.
796 * In this case, WLAN will receive BT's HW sys_waking.
798 * Otherwise, if BT SW missed initial remote_reset, that remote_reset
799 * will still clean up BT MCI RX, and the req_wake will wake BT up,
800 * and BT SW will respond this req_wake with a remote_reset and
801 * sys_waking. In this case, WLAN will receive BT's SW sys_waking.
803 * In either case, BT's RX is cleaned up. So we don't need to reply
804 * BT's remote_reset now, if any.
806 * Similarly, if in any case, WLAN can receive BT's sys_waking, that
807 * means WLAN's RX is also fine.
810 /* Send SYS_WAKING to BT */
811 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
812 "(MCI) %s: Send SW SYS_WAKING to remot(BT)\n", __func__);
813 ar9300_mci_send_sys_waking(ah, AH_TRUE);
818 * Set BT priority interrupt value to be 0xff to
819 * avoid having too many BT PRIORITY interrupts.
822 OS_REG_WRITE(ah, AR_MCI_BT_PRI0, 0xFFFFFFFF);
823 OS_REG_WRITE(ah, AR_MCI_BT_PRI1, 0xFFFFFFFF);
824 OS_REG_WRITE(ah, AR_MCI_BT_PRI2, 0xFFFFFFFF);
825 OS_REG_WRITE(ah, AR_MCI_BT_PRI3, 0xFFFFFFFF);
826 OS_REG_WRITE(ah, AR_MCI_BT_PRI, 0X000000FF);
829 * A contention reset will be received after send out sys_waking.
830 * Also BT priority interrupt bits will be set. Clear those bits
831 * before the next step.
833 OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,
834 AR_MCI_INTERRUPT_RX_MSG_CONT_RST);
835 OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, AR_MCI_INTERRUPT_BT_PRI);
837 if (AR_SREV_JUPITER_10(ah) || ahp->ah_mci_coex_is_2g) {
839 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) %s: Send LNA_TRANS to BT\n",
841 ar9300_mci_send_lna_transfer(ah, AH_TRUE);
846 if (AR_SREV_JUPITER_10(ah) ||
847 (ahp->ah_mci_coex_is_2g && !ahp->ah_mci_coex_2g5g_update))
849 if (ar9300_mci_wait_for_interrupt(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,
850 AR_MCI_INTERRUPT_RX_MSG_LNA_INFO, mci_timeout)) {
851 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
852 "(MCI) %s: WLAN has control over the LNA & BT obeys it\n",
855 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
856 "(MCI) %s: BT did not respond to LNA_TRANS!\n", __func__);
857 //ahp->ah_mci_bt_state = MCI_BT_SLEEP;
861 if (AR_SREV_JUPITER_10(ah)) {
862 /* Send another remote_reset to deassert BT clk_req. */
863 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
864 "(MCI) %s: Another remote_reset to deassert clk_req.\n",
866 ar9300_mci_remote_reset(ah, AH_TRUE);
871 /* Clear the extra redundant SYS_WAKING from BT */
872 if ((ahp->ah_mci_bt_state == MCI_BT_AWAKE) &&
873 (OS_REG_READ_FIELD(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,
874 AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING)) &&
875 (OS_REG_READ_FIELD(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,
876 AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING) == 0))
878 OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,
879 AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING);
880 OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RAW,
881 AR_MCI_INTERRUPT_REMOTE_SLEEP_UPDATE);
884 OS_REG_WRITE(ah, AR_MCI_INTERRUPT_EN, saved_mci_int_en);
887 void ar9300_mci_setup(struct ath_hal *ah, u_int32_t gpm_addr,
888 void *gpm_buf, u_int16_t len,
889 u_int32_t sched_addr)
891 struct ath_hal_9300 *ahp = AH9300(ah);
892 void *sched_buf = (void *)((char *) gpm_buf + (sched_addr - gpm_addr));
894 ahp->ah_mci_gpm_addr = gpm_addr;
895 ahp->ah_mci_gpm_buf = gpm_buf;
896 ahp->ah_mci_gpm_len = len;
897 ahp->ah_mci_sched_addr = sched_addr;
898 ahp->ah_mci_sched_buf = sched_buf;
900 ar9300_mci_reset(ah, AH_TRUE, AH_TRUE, AH_TRUE);
903 void ar9300_mci_disable_interrupt(struct ath_hal *ah)
905 OS_REG_WRITE(ah, AR_MCI_INTERRUPT_EN, 0);
906 OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_EN, 0);
909 void ar9300_mci_enable_interrupt(struct ath_hal *ah)
911 OS_REG_WRITE(ah, AR_MCI_INTERRUPT_EN, AR_MCI_INTERRUPT_DEFAULT);
912 OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_EN,
913 AR_MCI_INTERRUPT_RX_MSG_DEFAULT);
916 void ar9300_mci_reset(struct ath_hal *ah, HAL_BOOL en_int, HAL_BOOL is_2g,
917 HAL_BOOL is_full_sleep)
919 struct ath_hal_9300 *ahp = AH9300(ah);
920 // struct ath_hal_private *ahpriv = AH_PRIVATE(ah);
923 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) %s: full_sleep = %d, is_2g = %d\n",
924 __func__, is_full_sleep, is_2g);
926 if (!ahp->ah_mci_gpm_addr && !ahp->ah_mci_sched_addr) {
927 /* GPM buffer and scheduling message buffer are not allocated */
928 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
929 "(MCI) GPM and SCHEDULE buffers not allocated\n");
933 if (OS_REG_READ(ah, AR_BTCOEX_CTRL) == 0xdeadbeef) {
934 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
935 "(MCI) %s: ### It's deadbeef, quit mcireset()\n", __func__);
939 /* Program MCI DMA related registers */
940 OS_REG_WRITE(ah, AR_MCI_GPM_0, ahp->ah_mci_gpm_addr);
941 OS_REG_WRITE(ah, AR_MCI_GPM_1, ahp->ah_mci_gpm_len);
942 OS_REG_WRITE(ah, AR_MCI_SCHD_TABLE_0, ahp->ah_mci_sched_addr);
945 * To avoid MCI state machine be affected by incoming remote MCI messages,
946 * MCI mode will be enabled later, right before reset the MCI TX and RX.
948 regval = SM(1, AR_BTCOEX_CTRL_JUPITER_MODE) |
949 SM(1, AR_BTCOEX_CTRL_WBTIMER_EN) |
950 SM(1, AR_BTCOEX_CTRL_PA_SHARED) |
951 SM(1, AR_BTCOEX_CTRL_LNA_SHARED) |
952 SM(2, AR_BTCOEX_CTRL_NUM_ANTENNAS) |
953 SM(3, AR_BTCOEX_CTRL_RX_CHAIN_MASK) |
954 SM(0, AR_BTCOEX_CTRL_1_CHAIN_ACK) |
955 SM(0, AR_BTCOEX_CTRL_1_CHAIN_BCN) |
956 SM(0, AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN);
958 if (AR_SREV_JUPITER_10(ah)) {
959 regval |= SM(1, AR_BTCOEX_CTRL_SPDT_ENABLE_10);
962 OS_REG_WRITE(ah, AR_BTCOEX_CTRL, regval);
964 if (is_2g && (AR_SREV_JUPITER_20(ah) || AR_SREV_APHRODITE(ah)) &&
965 !(ah->ah_config.ath_hal_mci_config &
966 ATH_MCI_CONFIG_DISABLE_OSLA))
968 ar9300_mci_osla_setup(ah, AH_TRUE);
971 ar9300_mci_osla_setup(ah, AH_FALSE);
974 if (AR_SREV_JUPITER_20(ah) || AR_SREV_APHRODITE(ah)) {
975 OS_REG_SET_BIT(ah, AR_GLB_CONTROL, AR_BTCOEX_CTRL_SPDT_ENABLE);
977 OS_REG_RMW_FIELD(ah, AR_BTCOEX_CTRL3,
978 AR_BTCOEX_CTRL3_CONT_INFO_TIMEOUT, 20);
981 OS_REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2, AR_BTCOEX_CTRL2_RX_DEWEIGHT, 0);
983 OS_REG_RMW_FIELD(ah, AR_PCU_MISC, AR_PCU_BT_ANT_PREVENT_RX, 0);
985 if (ah->ah_config.ath_hal_mci_config & ATH_MCI_CONFIG_CONCUR_TX) {
987 u_int32_t const *pmax_tx_pwr;
989 if ((ah->ah_config.ath_hal_mci_config &
990 ATH_MCI_CONFIG_CONCUR_TX) == ATH_MCI_CONCUR_TX_SHARED_CHN)
992 ahp->ah_mci_concur_tx_en = (ahp->ah_bt_coex_flag &
993 HAL_BT_COEX_FLAG_MCI_MAX_TX_PWR) ? AH_TRUE : AH_FALSE;
995 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) concur_tx_en = %d\n",
996 ahp->ah_mci_concur_tx_en);
998 * We're not relying on HW to reduce WLAN tx power.
999 * Set the max tx power table to 0x7f for all.
1002 if (AH_PRIVATE(ah)->ah_curchan) {
1003 chan_flags = AH_PRIVATE(ah)->ah_curchan->channel_flags;
1005 if (chan_flags == CHANNEL_G_HT20) {
1006 pmax_tx_pwr = &mci_concur_tx_max_pwr[2][0];
1008 else if (chan_flags == CHANNEL_G) {
1009 pmax_tx_pwr = &mci_concur_tx_max_pwr[1][0];
1011 else if ((chan_flags == CHANNEL_G_HT40PLUS) ||
1012 (chan_flags == CHANNEL_G_HT40MINUS))
1014 pmax_tx_pwr = &mci_concur_tx_max_pwr[3][0];
1017 pmax_tx_pwr = &mci_concur_tx_max_pwr[0][0];
1020 if (ahp->ah_mci_concur_tx_en) {
1021 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1022 "(MCI) chan flags = 0x%x, max_tx_pwr = %d dBm\n",
1025 ATH_MCI_CONCUR_TX_LOWEST_PWR_MASK) >> 1));
1028 pmax_tx_pwr = &mci_concur_tx_max_pwr[0][0];
1031 else if ((ah->ah_config.ath_hal_mci_config &
1032 ATH_MCI_CONFIG_CONCUR_TX) == ATH_MCI_CONCUR_TX_UNSHARED_CHN)
1034 pmax_tx_pwr = &mci_concur_tx_max_pwr[0][0];
1035 ahp->ah_mci_concur_tx_en = AH_TRUE;
1038 pmax_tx_pwr = &mci_concur_tx_max_pwr[0][0];
1039 ahp->ah_mci_concur_tx_en = AH_TRUE;
1042 /* Default is using rate based TPC. */
1043 OS_REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2,
1044 AR_BTCOEX_CTRL2_DESC_BASED_TXPWR_ENABLE, 0);
1045 OS_REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2,
1046 AR_BTCOEX_CTRL2_TXPWR_THRESH, 0x7f);
1047 OS_REG_RMW_FIELD(ah, AR_BTCOEX_CTRL,
1048 AR_BTCOEX_CTRL_REDUCE_TXPWR, 0);
1049 for (i = 0; i < 8; i++) {
1050 OS_REG_WRITE(ah, AR_BTCOEX_MAX_TXPWR(i), pmax_tx_pwr[i]);
1054 regval = MS(ah->ah_config.ath_hal_mci_config,
1055 ATH_MCI_CONFIG_CLK_DIV);
1056 OS_REG_RMW_FIELD(ah, AR_MCI_TX_CTRL, AR_MCI_TX_CTRL_CLK_DIV, regval);
1058 OS_REG_SET_BIT(ah, AR_BTCOEX_CTRL, AR_BTCOEX_CTRL_MCI_MODE_EN);
1060 /* Resetting the Rx and Tx paths of MCI */
1061 regval = OS_REG_READ(ah, AR_MCI_COMMAND2);
1062 regval |= SM(1, AR_MCI_COMMAND2_RESET_TX);
1063 OS_REG_WRITE(ah, AR_MCI_COMMAND2, regval);
1065 regval &= ~SM(1, AR_MCI_COMMAND2_RESET_TX);
1066 OS_REG_WRITE(ah, AR_MCI_COMMAND2, regval);
1068 if (is_full_sleep) {
1069 ar9300_mci_mute_bt(ah);
1073 regval |= SM(1, AR_MCI_COMMAND2_RESET_RX);
1074 OS_REG_WRITE(ah, AR_MCI_COMMAND2, regval);
1076 regval &= ~SM(1, AR_MCI_COMMAND2_RESET_RX);
1077 OS_REG_WRITE(ah, AR_MCI_COMMAND2, regval);
1079 ar9300_mci_state(ah, HAL_MCI_STATE_INIT_GPM_OFFSET, NULL);
1080 OS_REG_WRITE(ah, AR_MCI_MSG_ATTRIBUTES_TABLE,
1081 (SM(0xe801, AR_MCI_MSG_ATTRIBUTES_TABLE_INVALID_HDR) |
1082 SM(0x0000, AR_MCI_MSG_ATTRIBUTES_TABLE_CHECKSUM)));
1083 OS_REG_CLR_BIT(ah, AR_MCI_TX_CTRL, AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE);
1085 if (AR_SREV_JUPITER_20_OR_LATER(ah) || AR_SREV_APHRODITE(ah)) {
1086 ar9300_mci_observation_set_up(ah);
1089 ahp->ah_mci_ready = AH_TRUE;
1090 ar9300_mci_prep_interface(ah);
1093 ar9300_mci_enable_interrupt(ah);
1097 if (ahp->ah_aic_enabled) {
1098 ar9300_aic_start_normal(ah);
1103 static void ar9300_mci_queue_unsent_gpm(struct ath_hal *ah, u_int8_t header,
1104 u_int32_t *payload, HAL_BOOL queue)
1106 struct ath_hal_9300 *ahp = AH9300(ah);
1107 u_int8_t type, opcode;
1109 if (queue == AH_TRUE) {
1110 if (payload != NULL) {
1111 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1112 "(MCI) ERROR: Send fail: %02x: %02x %02x %02x\n",
1114 *(((u_int8_t *)payload) + 4),
1115 *(((u_int8_t *)payload) + 5),
1116 *(((u_int8_t *)payload) + 6));
1118 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1119 "(MCI) ERROR: Send fail: %02x\n", header);
1122 /* check if the message is to be queued */
1123 if (header == MCI_GPM) {
1124 type = MCI_GPM_TYPE(payload);
1125 opcode = MCI_GPM_OPCODE(payload);
1127 if (type == MCI_GPM_COEX_AGENT) {
1130 case MCI_GPM_COEX_BT_UPDATE_FLAGS:
1131 if (AR_SREV_JUPITER_10(ah)) {
1134 if (*(((u_int8_t *)payload) + MCI_GPM_COEX_B_BT_FLAGS_OP) ==
1135 MCI_GPM_COEX_BT_FLAGS_READ)
1139 ahp->ah_mci_coex_2g5g_update = queue;
1140 if (queue == AH_TRUE) {
1141 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1142 "(MCI) BT_MCI_FLAGS: 2G5G status <queued> %s.\n",
1143 ahp->ah_mci_coex_is_2g?"2G":"5G");
1146 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1147 "(MCI) BT_MCI_FLAGS: 2G5G status <sent> %s.\n",
1148 ahp->ah_mci_coex_is_2g?"2G":"5G");
1152 case MCI_GPM_COEX_WLAN_CHANNELS:
1153 ahp->ah_mci_coex_wlan_channels_update = queue;
1154 if (queue == AH_TRUE) {
1155 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1156 "(MCI) WLAN channel map <queued>.\n");
1159 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1160 "(MCI) WLAN channel map <sent>.\n");
1164 case MCI_GPM_COEX_HALT_BT_GPM:
1165 if (*(((u_int8_t *)payload) + MCI_GPM_COEX_B_HALT_STATE) ==
1166 MCI_GPM_COEX_BT_GPM_UNHALT)
1168 ahp->ah_mci_unhalt_bt_gpm = queue;
1169 if (queue == AH_TRUE) {
1170 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1171 "(MCI) UNHALT BT GPM <queued>.\n");
1174 ahp->ah_mci_halted_bt_gpm = AH_FALSE;
1175 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1176 "(MCI) UNHALT BT GPM <sent>.\n");
1179 if (*(((u_int8_t *)payload) + MCI_GPM_COEX_B_HALT_STATE) ==
1180 MCI_GPM_COEX_BT_GPM_HALT)
1182 ahp->ah_mci_halted_bt_gpm = !queue;
1183 if (queue == AH_TRUE) {
1184 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1185 "(MCI) HALT BT GPM <not sent>.\n");
1188 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1189 "(MCI) HALT BT GPM <sent>.\n");
1201 HAL_BOOL ar9300_mci_send_message(struct ath_hal *ah, u_int8_t header,
1202 u_int32_t flag, u_int32_t *payload,
1203 u_int8_t len, HAL_BOOL wait_done, HAL_BOOL check_bt)
1206 struct ath_hal_9300 *ahp = AH9300(ah);
1207 HAL_BOOL msg_sent = AH_FALSE;
1209 u_int32_t saved_mci_int_en = OS_REG_READ(ah, AR_MCI_INTERRUPT_EN);
1211 regval = OS_REG_READ(ah, AR_BTCOEX_CTRL);
1212 if ((regval == 0xdeadbeef) || !(regval & AR_BTCOEX_CTRL_MCI_MODE_EN)) {
1213 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1214 "(MCI) %s: Not send 0x%x. MCI is not enabled. full_sleep = %d\n",
1215 __func__, header, ahp->ah_chip_full_sleep);
1216 ar9300_mci_queue_unsent_gpm(ah, header, payload, AH_TRUE);
1219 else if (check_bt && (ahp->ah_mci_bt_state == MCI_BT_SLEEP)) {
1220 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1221 "(MCI) %s: Don't send message(0x%x). BT is in sleep state\n",
1223 ar9300_mci_queue_unsent_gpm(ah, header, payload, AH_TRUE);
1228 OS_REG_WRITE(ah, AR_MCI_INTERRUPT_EN, 0);
1231 /* Need to clear SW_MSG_DONE raw bit before wait */
1232 OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RAW,
1233 AR_MCI_INTERRUPT_SW_MSG_DONE | AR_MCI_INTERRUPT_MSG_FAIL_MASK);
1235 if (payload != AH_NULL) {
1236 for (i = 0; (i*4) < len; i++) {
1237 OS_REG_WRITE(ah, (AR_MCI_TX_PAYLOAD0 + i*4), *(payload + i));
1240 ar9300_mci_print_msg(ah, AH_TRUE, header, len, payload);
1242 OS_REG_WRITE(ah, AR_MCI_COMMAND0,
1243 (SM((flag & HAL_MCI_FLAG_DISABLE_TIMESTAMP),
1244 AR_MCI_COMMAND0_DISABLE_TIMESTAMP) |
1245 SM(len, AR_MCI_COMMAND0_LEN) |
1246 SM(header, AR_MCI_COMMAND0_HEADER)));
1249 ar9300_mci_wait_for_interrupt(ah, AR_MCI_INTERRUPT_RAW,
1250 AR_MCI_INTERRUPT_SW_MSG_DONE, 500) == 0)
1252 ar9300_mci_queue_unsent_gpm(ah, header, payload, AH_TRUE);
1255 ar9300_mci_queue_unsent_gpm(ah, header, payload, AH_FALSE);
1260 OS_REG_WRITE(ah, AR_MCI_INTERRUPT_EN, saved_mci_int_en);
1266 u_int32_t ar9300_mci_get_interrupt(struct ath_hal *ah, u_int32_t *mci_int,
1267 u_int32_t *mci_int_rx_msg)
1269 struct ath_hal_9300 *ahp = AH9300(ah);
1271 *mci_int = ahp->ah_mci_int_raw;
1272 *mci_int_rx_msg = ahp->ah_mci_int_rx_msg;
1274 /* Clean int bits after the values are read. */
1275 ahp->ah_mci_int_raw = 0;
1276 ahp->ah_mci_int_rx_msg = 0;
1281 u_int32_t ar9300_mci_check_int(struct ath_hal *ah, u_int32_t ints)
1285 reg = OS_REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_RAW);
1286 return ((reg & ints) == ints);
1289 void ar9300_mci_sync_bt_state(struct ath_hal *ah)
1291 struct ath_hal_9300 *ahp = AH9300(ah);
1292 u_int32_t cur_bt_state;
1294 cur_bt_state = ar9300_mci_state(ah, HAL_MCI_STATE_REMOTE_SLEEP, NULL);
1295 if (ahp->ah_mci_bt_state != cur_bt_state) {
1296 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1297 "(MCI) %s: BT state mismatches. old: %d, new: %d\n",
1298 __func__, ahp->ah_mci_bt_state, cur_bt_state);
1299 ahp->ah_mci_bt_state = cur_bt_state;
1301 if (ahp->ah_mci_bt_state != MCI_BT_SLEEP) {
1302 #if MCI_QUERY_BT_VERSION_VERBOSE
1303 ar9300_mci_send_coex_version_query(ah, AH_TRUE);
1305 ar9300_mci_send_coex_wlan_channels(ah, AH_TRUE);
1306 if (ahp->ah_mci_unhalt_bt_gpm == AH_TRUE) {
1307 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) %s: UNHALT BT GPM\n", __func__);
1308 ar9300_mci_send_coex_halt_bt_gpm(ah, AH_FALSE, AH_TRUE);
1313 static HAL_BOOL ar9300_mci_is_gpm_valid(struct ath_hal *ah, u_int32_t msg_index)
1315 struct ath_hal_9300 *ahp = AH9300(ah);
1317 u_int32_t recv_type, offset = msg_index << 4;
1319 if (msg_index == HAL_MCI_GPM_INVALID) {
1323 payload = (u_int32_t *) (ahp->ah_mci_gpm_buf + offset);
1324 recv_type = MCI_GPM_TYPE(payload);
1326 if (recv_type == MCI_GPM_RSVD_PATTERN) {
1327 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) Skip RSVD GPM\n");
1335 ar9300_mci_state(struct ath_hal *ah, u_int32_t state_type, u_int32_t *p_data)
1337 u_int32_t value = 0, more_gpm = 0, gpm_ptr;
1338 struct ath_hal_9300 *ahp = AH9300(ah);
1340 switch (state_type) {
1341 case HAL_MCI_STATE_ENABLE:
1342 if (AH_PRIVATE(ah)->ah_caps.halMciSupport && ahp->ah_mci_ready) {
1343 value = OS_REG_READ(ah, AR_BTCOEX_CTRL);
1344 if ((value == 0xdeadbeef) || (value == 0xffffffff)) {
1345 // HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1346 // "(MCI) BTCOEX_CTRL = 0xdeadbeef\n");
1350 value &= AR_BTCOEX_CTRL_MCI_MODE_EN;
1353 case HAL_MCI_STATE_INIT_GPM_OFFSET:
1354 value = MS(OS_REG_READ(ah, AR_MCI_GPM_1), AR_MCI_GPM_WRITE_PTR);
1355 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1356 "(MCI) %s: GPM initial WRITE_PTR=%d.\n", __func__, value);
1357 ahp->ah_mci_gpm_idx = value;
1360 case HAL_MCI_STATE_NEXT_GPM_OFFSET:
1361 case HAL_MCI_STATE_LAST_GPM_OFFSET:
1363 * This could be useful to avoid new GPM message interrupt which
1364 * may lead to spurious interrupt after power sleep, or multiple
1365 * entry of ath_coex_mci_intr().
1366 * Adding empty GPM check by returning HAL_MCI_GPM_INVALID can
1367 * alleviate this effect, but clearing GPM RX interrupt bit is
1368 * safe, because whether this is called from HAL or LMAC, there
1369 * must be an interrupt bit set/triggered initially.
1371 OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,
1372 AR_MCI_INTERRUPT_RX_MSG_GPM);
1374 gpm_ptr = MS(OS_REG_READ(ah, AR_MCI_GPM_1), AR_MCI_GPM_WRITE_PTR);
1378 value = ahp->ah_mci_gpm_len - 1;
1380 else if (value >= ahp->ah_mci_gpm_len) {
1381 if (value != 0xFFFF) {
1383 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1384 "(MCI) %s: GPM offset out of range.\n", __func__);
1391 if (value == 0xFFFF) {
1392 value = HAL_MCI_GPM_INVALID;
1393 more_gpm = HAL_MCI_GPM_NOMORE;
1394 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1395 "(MCI) %s: GPM ptr invalid "
1396 "@ptr=%d, @offset=%d, more=NOMORE.\n",
1397 __func__, gpm_ptr, value);
1399 else if (state_type == HAL_MCI_STATE_NEXT_GPM_OFFSET) {
1400 if (gpm_ptr == ahp->ah_mci_gpm_idx) {
1401 value = HAL_MCI_GPM_INVALID;
1402 more_gpm = HAL_MCI_GPM_NOMORE;
1403 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1404 "(MCI) %s: GPM message not available "
1405 "@ptr=%d, @offset=%d, more=NOMORE.\n",
1406 __func__, gpm_ptr, value);
1410 u_int32_t temp_index;
1412 /* skip reserved GPM if any */
1413 if (value != ahp->ah_mci_gpm_idx) {
1414 more_gpm = HAL_MCI_GPM_MORE;
1417 more_gpm = HAL_MCI_GPM_NOMORE;
1419 temp_index = ahp->ah_mci_gpm_idx;
1420 ahp->ah_mci_gpm_idx++;
1421 if (ahp->ah_mci_gpm_idx >= ahp->ah_mci_gpm_len) {
1422 ahp->ah_mci_gpm_idx = 0;
1424 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1425 "(MCI) %s: GPM message got "
1426 "@ptr=%d, @offset=%d, more=%s.\n",
1427 __func__, gpm_ptr, temp_index,
1428 (more_gpm == HAL_MCI_GPM_MORE)?"MORE":"NOMORE");
1429 if (ar9300_mci_is_gpm_valid(ah, temp_index)) {
1433 if (more_gpm == HAL_MCI_GPM_NOMORE) {
1434 value = HAL_MCI_GPM_INVALID;
1439 if (p_data != NULL) {
1443 if (value != HAL_MCI_GPM_INVALID) {
1448 case HAL_MCI_STATE_LAST_SCHD_MSG_OFFSET:
1449 value = MS(OS_REG_READ(ah, AR_MCI_RX_STATUS),
1450 AR_MCI_RX_LAST_SCHD_MSG_INDEX);
1452 #if AH_MCI_DEBUG_PRINT_SCHED
1454 u_int32_t index = value;
1455 u_int32_t prev_index, sched_idx;
1458 u_int32_t wbtimer = OS_REG_READ(ah, AR_BTCOEX_WBTIMER);
1459 u_int32_t schd_ctl = OS_REG_READ(ah, AR_MCI_HW_SCHD_TBL_CTL);
1462 prev_index = index - 1;
1467 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) SCHED\n");
1468 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1469 "(MCI) SCHED SCHD_TBL_CTRL=0x%08x, WBTIMER=0x%08x (%d)\n",
1470 schd_ctl, wbtimer, wbtimer);
1471 for (sched_idx = prev_index; sched_idx <= index; sched_idx++) {
1472 pld = (u_int32_t *) (ahp->ah_mci_sched_buf + (sched_idx << 4));
1473 pld8 = (u_int8_t *) pld;
1475 ar9300_mci_print_msg(ah, AH_FALSE, MCI_SCHD_INFO, 16, pld);
1476 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1477 "(MCI) SCHED idx=%d, T1=0x%08x (%d), T2=0x%08x (%d)\n",
1479 pld[0], pld[0], pld[1], pld[1]);
1480 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1481 "(MCI) SCHED addr=%d %s pwr=%d prio=%d %s link=%d\n",
1483 (pld8[11] & 0x08)?"TX":"RX",
1484 (int8_t) (((pld8[11] & 0x07) << 5) | (pld8[10] >> 3)),
1485 (((pld8[10] & 0x07) << 5) | (pld8[9] >> 3)),
1486 (pld8[9] & 0x04)?"LE":"BR/EDR",
1487 (((pld8[9] & 0x03) << 2) | (pld8[8] >> 6)));
1490 #endif /* AH_MCI_DEBUG_PRINT_SCHED */
1492 /* Make it in bytes */
1496 case HAL_MCI_STATE_REMOTE_SLEEP:
1497 value = MS(OS_REG_READ(ah, AR_MCI_RX_STATUS),
1498 AR_MCI_RX_REMOTE_SLEEP) ? MCI_BT_SLEEP : MCI_BT_AWAKE;
1501 case HAL_MCI_STATE_CONT_RSSI_POWER:
1502 value = MS(ahp->ah_mci_cont_status,
1503 AR_MCI_CONT_RSSI_POWER);
1506 case HAL_MCI_STATE_CONT_PRIORITY:
1507 value = MS(ahp->ah_mci_cont_status,
1508 AR_MCI_CONT_RRIORITY);
1511 case HAL_MCI_STATE_CONT_TXRX:
1512 value = MS(ahp->ah_mci_cont_status,
1516 case HAL_MCI_STATE_BT:
1517 value = ahp->ah_mci_bt_state;
1520 case HAL_MCI_STATE_SET_BT_SLEEP:
1521 ahp->ah_mci_bt_state = MCI_BT_SLEEP;
1524 case HAL_MCI_STATE_SET_BT_AWAKE:
1525 ahp->ah_mci_bt_state = MCI_BT_AWAKE;
1526 ar9300_mci_send_coex_version_query(ah, AH_TRUE);
1527 ar9300_mci_send_coex_wlan_channels(ah, AH_TRUE);
1528 if (ahp->ah_mci_unhalt_bt_gpm == AH_TRUE) {
1529 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1530 "(MCI) %s: UNHALT BT GPM\n", __func__);
1531 ar9300_mci_send_coex_halt_bt_gpm(ah, AH_FALSE, AH_TRUE);
1533 ar9300_mci_2g5g_switch(ah, AH_TRUE);
1536 case HAL_MCI_STATE_SET_BT_CAL_START:
1537 ahp->ah_mci_bt_state = MCI_BT_CAL_START;
1540 case HAL_MCI_STATE_SET_BT_CAL:
1541 ahp->ah_mci_bt_state = MCI_BT_CAL;
1544 case HAL_MCI_STATE_RESET_REQ_WAKE:
1545 ar9300_mci_reset_req_wakeup(ah);
1546 ahp->ah_mci_coex_2g5g_update = AH_TRUE;
1548 if ((AR_SREV_JUPITER_20_OR_LATER(ah) || AR_SREV_APHRODITE(ah)) &&
1549 (ah->ah_config.ath_hal_mci_config &
1550 ATH_MCI_CONFIG_MCI_OBS_MASK))
1552 /* Check if we still have control of the GPIOs */
1553 if ((OS_REG_READ(ah, AR_GLB_GPIO_CONTROL) &
1554 ATH_MCI_CONFIG_MCI_OBS_GPIO) !=
1555 ATH_MCI_CONFIG_MCI_OBS_GPIO)
1557 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1558 "(MCI) Reconfigure observation\n");
1559 ar9300_mci_observation_set_up(ah);
1565 case HAL_MCI_STATE_SEND_WLAN_COEX_VERSION:
1566 ar9300_mci_send_coex_version_response(ah, AH_TRUE);
1569 case HAL_MCI_STATE_SET_BT_COEX_VERSION:
1570 if (p_data == NULL) {
1571 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1572 "(MCI) Error: Set BT Coex version with NULL data !!!\n");
1575 ahp->ah_mci_coex_major_version_bt = (*p_data >> 8) & 0xff;
1576 ahp->ah_mci_coex_minor_version_bt = (*p_data) & 0xff;
1577 ahp->ah_mci_coex_bt_version_known = AH_TRUE;
1578 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) BT version set: %d.%d\n",
1579 ahp->ah_mci_coex_major_version_bt,
1580 ahp->ah_mci_coex_minor_version_bt);
1584 case HAL_MCI_STATE_SEND_WLAN_CHANNELS:
1587 if (((ahp->ah_mci_coex_wlan_channels[1] & 0xffff0000) ==
1588 (*(p_data + 1) & 0xffff0000)) &&
1589 (ahp->ah_mci_coex_wlan_channels[2] == *(p_data + 2)) &&
1590 (ahp->ah_mci_coex_wlan_channels[3] == *(p_data + 3)))
1594 ahp->ah_mci_coex_wlan_channels[0] = *p_data++;
1595 ahp->ah_mci_coex_wlan_channels[1] = *p_data++;
1596 ahp->ah_mci_coex_wlan_channels[2] = *p_data++;
1597 ahp->ah_mci_coex_wlan_channels[3] = *p_data++;
1599 ahp->ah_mci_coex_wlan_channels_update = AH_TRUE;
1600 ar9300_mci_send_coex_wlan_channels(ah, AH_TRUE);
1603 case HAL_MCI_STATE_SEND_VERSION_QUERY:
1604 ar9300_mci_send_coex_version_query(ah, AH_TRUE);
1607 case HAL_MCI_STATE_SEND_STATUS_QUERY:
1608 if (AR_SREV_JUPITER_10(ah)) {
1609 ar9300_mci_send_coex_bt_status_query(ah, AH_TRUE,
1610 MCI_GPM_COEX_QUERY_BT_ALL_INFO);
1612 ar9300_mci_send_coex_bt_status_query(ah, AH_TRUE,
1613 MCI_GPM_COEX_QUERY_BT_TOPOLOGY);
1617 case HAL_MCI_STATE_NEED_FLUSH_BT_INFO:
1619 * ah_mci_unhalt_bt_gpm means whether it's needed to send
1620 * UNHALT message. It's set whenever there's a request to send HALT
1621 * message. ah_mci_halted_bt_gpm means whether HALT message is sent
1624 * Checking (ah_mci_unhalt_bt_gpm == AH_FALSE) instead of checking
1625 * (ahp->ah_mci_halted_bt_gpm == AH_FALSE) will make sure currently is
1626 * in UNHALT-ed mode and BT can respond to status query.
1628 if ((ahp->ah_mci_unhalt_bt_gpm == AH_FALSE) &&
1629 (ahp->ah_mci_need_flush_btinfo == AH_TRUE))
1636 if (p_data != NULL) {
1637 ahp->ah_mci_need_flush_btinfo = (*p_data != 0)? AH_TRUE : AH_FALSE;
1641 case HAL_MCI_STATE_SET_CONCUR_TX_PRI:
1643 ahp->ah_mci_stomp_none_tx_pri = *p_data & 0xff;
1644 ahp->ah_mci_stomp_low_tx_pri = (*p_data >> 8) & 0xff;
1645 ahp->ah_mci_stomp_all_tx_pri = (*p_data >> 16) & 0xff;
1649 case HAL_MCI_STATE_RECOVER_RX:
1650 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) hal RECOVER_RX\n");
1651 ar9300_mci_prep_interface(ah);
1652 ahp->ah_mci_query_bt = AH_TRUE;
1653 ahp->ah_mci_need_flush_btinfo = AH_TRUE;
1654 ar9300_mci_send_coex_wlan_channels(ah, AH_TRUE);
1655 ar9300_mci_2g5g_switch(ah, AH_TRUE);
1658 case HAL_MCI_STATE_DEBUG:
1659 if (p_data != NULL) {
1660 if (*p_data == HAL_MCI_STATE_DEBUG_REQ_BT_DEBUG) {
1661 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) QUERY_BT_DEBUG\n");
1662 ar9300_mci_send_coex_bt_status_query(ah, AH_TRUE,
1663 MCI_GPM_COEX_QUERY_BT_DEBUG);
1665 if (AR_SREV_JUPITER_20(ah) || AR_SREV_APHRODITE(ah)) {
1666 ar9300_mci_send_coex_bt_flags(ah, AH_TRUE,
1667 MCI_GPM_COEX_BT_FLAGS_READ, 0);
1673 case HAL_MCI_STATE_NEED_FTP_STOMP:
1674 value = (ah->ah_config.ath_hal_mci_config &
1675 ATH_MCI_CONFIG_DISABLE_FTP_STOMP) ? 0 : 1;
1678 case HAL_MCI_STATE_NEED_TUNING:
1679 value = (ah->ah_config.ath_hal_mci_config &
1680 ATH_MCI_CONFIG_DISABLE_TUNING) ? 0 : 1;
1683 case HAL_MCI_STATE_SHARED_CHAIN_CONCUR_TX:
1684 value = ((ah->ah_config.ath_hal_mci_config &
1685 ATH_MCI_CONFIG_CONCUR_TX) ==
1686 ATH_MCI_CONCUR_TX_SHARED_CHN)? 1 : 0;
1695 void ar9300_mci_detach(struct ath_hal *ah)
1697 /* Turn off MCI and Jupiter mode. */
1698 OS_REG_WRITE(ah, AR_BTCOEX_CTRL, 0x00);
1699 HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) ar9300_mci_detach\n");
1700 ar9300_mci_disable_interrupt(ah);
1704 * Low priority BT: 0 - 59(0x3b)
1705 * High priority BT: 60 - 125(0x7d)
1706 * Critical BT: 126 - 255
1708 BTCOEX_WL_WEIGHTS0_VALUE0 ; // wl_idle
1709 BTCOEX_WL_WEIGHTS0_VALUE1 ; // sw_ctrl[3] - all_stomp
1710 BTCOEX_WL_WEIGHTS0_VALUE2 ; // sw_ctrl[2] - all_not_stomp
1711 BTCOEX_WL_WEIGHTS0_VALUE3 ; // sw_ctrl[1] - pa_pre_distortion
1712 BTCOEX_WL_WEIGHTS1_VALUE0 ; // sw_ctrl[0] - general purpose
1713 BTCOEX_WL_WEIGHTS1_VALUE1 ; // tm_wl_wait_beacon
1714 BTCOEX_WL_WEIGHTS1_VALUE2 ; // ts_state_wait_ack_cts
1715 BTCOEX_WL_WEIGHTS1_VALUE3 ; // self_gen
1716 BTCOEX_WL_WEIGHTS2_VALUE0 ; // idle
1717 BTCOEX_WL_WEIGHTS2_VALUE1 ; // rx
1718 BTCOEX_WL_WEIGHTS2_VALUE2 ; // tx
1719 BTCOEX_WL_WEIGHTS2_VALUE3 ; // rx + tx
1720 BTCOEX_WL_WEIGHTS3_VALUE0 ; // tx
1721 BTCOEX_WL_WEIGHTS3_VALUE1 ; // rx
1722 BTCOEX_WL_WEIGHTS3_VALUE2 ; // tx
1723 BTCOEX_WL_WEIGHTS3_VALUE3 ; // rx + tx
1726 ah_bt_coex_wlan_weight[0] = 0x00007d00
1727 ah_bt_coex_wlan_weight[1] = 0x7d7d7d00
1728 ah_bt_coex_wlan_weight[2] = 0x7d7d7d00
1729 ah_bt_coex_wlan_weight[3] = 0x7d7d7d7d
1731 ah_bt_coex_wlan_weight[0] = 0x00007d00
1732 ah_bt_coex_wlan_weight[1] = 0x7d3b3b00
1733 ah_bt_coex_wlan_weight[2] = 0x3b3b3b00
1734 ah_bt_coex_wlan_weight[3] = 0x3b3b3b3b
1736 ah_bt_coex_wlan_weight[0] = 0x00007d00
1737 ah_bt_coex_wlan_weight[1] = 0x7d000000
1738 ah_bt_coex_wlan_weight[2] = 0x00000000
1739 ah_bt_coex_wlan_weight[3] = 0x00000000
1742 void ar9300_mci_bt_coex_set_weights(struct ath_hal *ah, u_int32_t stomp_type)
1744 struct ath_hal_9300 *ahp = AH9300(ah);
1745 // struct ath_hal_private *ahpriv = AH_PRIVATE(ah);
1746 u_int32_t tx_priority = 0;
1748 switch (stomp_type) {
1749 case HAL_BT_COEX_STOMP_ALL:
1750 ahp->ah_bt_coex_wlan_weight[0] = JUPITER_STOMP_ALL_WLAN_WGHT0;
1751 ahp->ah_bt_coex_wlan_weight[1] = JUPITER_STOMP_ALL_WLAN_WGHT1;
1752 ahp->ah_bt_coex_wlan_weight[2] = JUPITER_STOMP_ALL_WLAN_WGHT2;
1753 ahp->ah_bt_coex_wlan_weight[3] = JUPITER_STOMP_ALL_WLAN_WGHT3;
1754 if (ahp->ah_mci_concur_tx_en && ahp->ah_mci_stomp_all_tx_pri) {
1755 tx_priority = ahp->ah_mci_stomp_all_tx_pri;
1758 case HAL_BT_COEX_STOMP_LOW:
1759 if (ahp->ah_bt_coex_flag & HAL_BT_COEX_FLAG_MCI_FTP_STOMP_RX) {
1760 ahp->ah_bt_coex_wlan_weight[0] = JUPITER_STOMP_LOW_FTP_WLAN_WGHT0;
1761 ahp->ah_bt_coex_wlan_weight[1] = JUPITER_STOMP_LOW_FTP_WLAN_WGHT1;
1762 ahp->ah_bt_coex_wlan_weight[2] = JUPITER_STOMP_LOW_FTP_WLAN_WGHT2;
1763 ahp->ah_bt_coex_wlan_weight[3] = JUPITER_STOMP_LOW_FTP_WLAN_WGHT3;
1766 ahp->ah_bt_coex_wlan_weight[0] = JUPITER_STOMP_LOW_WLAN_WGHT0;
1767 ahp->ah_bt_coex_wlan_weight[1] = JUPITER_STOMP_LOW_WLAN_WGHT1;
1768 ahp->ah_bt_coex_wlan_weight[2] = JUPITER_STOMP_LOW_WLAN_WGHT2;
1769 ahp->ah_bt_coex_wlan_weight[3] = JUPITER_STOMP_LOW_WLAN_WGHT3;
1771 if (ahp->ah_mci_concur_tx_en && ahp->ah_mci_stomp_low_tx_pri) {
1772 tx_priority = ahp->ah_mci_stomp_low_tx_pri;
1774 if (ah->ah_config.ath_hal_mci_config &
1775 ATH_MCI_CONFIG_MCI_OBS_TXRX)
1777 ar9300_gpio_set(ah, 5, 1);
1780 case HAL_BT_COEX_STOMP_ALL_FORCE:
1781 ahp->ah_bt_coex_wlan_weight[0] = JUPITER_STOMP_ALL_FORCE_WLAN_WGHT0;
1782 ahp->ah_bt_coex_wlan_weight[1] = JUPITER_STOMP_ALL_FORCE_WLAN_WGHT1;
1783 ahp->ah_bt_coex_wlan_weight[2] = JUPITER_STOMP_ALL_FORCE_WLAN_WGHT2;
1784 ahp->ah_bt_coex_wlan_weight[3] = JUPITER_STOMP_ALL_FORCE_WLAN_WGHT3;
1786 case HAL_BT_COEX_STOMP_LOW_FORCE:
1787 ahp->ah_bt_coex_wlan_weight[0] = JUPITER_STOMP_LOW_FORCE_WLAN_WGHT0;
1788 ahp->ah_bt_coex_wlan_weight[1] = JUPITER_STOMP_LOW_FORCE_WLAN_WGHT1;
1789 ahp->ah_bt_coex_wlan_weight[2] = JUPITER_STOMP_LOW_FORCE_WLAN_WGHT2;
1790 ahp->ah_bt_coex_wlan_weight[3] = JUPITER_STOMP_LOW_FORCE_WLAN_WGHT3;
1791 if (ahp->ah_mci_concur_tx_en && ahp->ah_mci_stomp_low_tx_pri) {
1792 tx_priority = ahp->ah_mci_stomp_low_tx_pri;
1795 case HAL_BT_COEX_STOMP_NONE:
1796 case HAL_BT_COEX_NO_STOMP:
1797 ahp->ah_bt_coex_wlan_weight[0] = JUPITER_STOMP_NONE_WLAN_WGHT0;
1798 ahp->ah_bt_coex_wlan_weight[1] = JUPITER_STOMP_NONE_WLAN_WGHT1;
1799 ahp->ah_bt_coex_wlan_weight[2] = JUPITER_STOMP_NONE_WLAN_WGHT2;
1800 ahp->ah_bt_coex_wlan_weight[3] = JUPITER_STOMP_NONE_WLAN_WGHT3;
1801 if (ahp->ah_mci_concur_tx_en && ahp->ah_mci_stomp_none_tx_pri) {
1802 tx_priority = ahp->ah_mci_stomp_none_tx_pri;
1804 if (ah->ah_config.ath_hal_mci_config &
1805 ATH_MCI_CONFIG_MCI_OBS_TXRX)
1807 ar9300_gpio_set(ah, 5, 0);
1811 /* There is a forceWeight from registry */
1812 ahp->ah_bt_coex_wlan_weight[0] = stomp_type;
1813 ahp->ah_bt_coex_wlan_weight[1] = stomp_type;
1817 if (ahp->ah_mci_concur_tx_en && tx_priority) {
1818 ahp->ah_bt_coex_wlan_weight[1] &= ~MCI_CONCUR_TX_WLAN_WGHT1_MASK;
1819 ahp->ah_bt_coex_wlan_weight[1] |=
1820 SM(tx_priority, MCI_CONCUR_TX_WLAN_WGHT1_MASK);
1821 ahp->ah_bt_coex_wlan_weight[2] &= ~MCI_CONCUR_TX_WLAN_WGHT2_MASK;
1822 ahp->ah_bt_coex_wlan_weight[2] |=
1823 SM(tx_priority, MCI_CONCUR_TX_WLAN_WGHT2_MASK);
1824 ahp->ah_bt_coex_wlan_weight[3] &= ~MCI_CONCUR_TX_WLAN_WGHT3_MASK;
1825 ahp->ah_bt_coex_wlan_weight[3] |=
1826 SM(tx_priority, MCI_CONCUR_TX_WLAN_WGHT3_MASK);
1827 ahp->ah_bt_coex_wlan_weight[3] &= ~MCI_CONCUR_TX_WLAN_WGHT3_MASK2;
1828 ahp->ah_bt_coex_wlan_weight[3] |=
1829 SM(tx_priority, MCI_CONCUR_TX_WLAN_WGHT3_MASK2);
1831 if (ah->ah_config.ath_hal_mci_config &
1832 ATH_MCI_CONFIG_MCI_WEIGHT_DBG)
1834 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1835 "(MCI) Set weights: 0x%08x 0x%08x 0x%08x 0x%08x\n",
1836 ahp->ah_bt_coex_wlan_weight[0],
1837 ahp->ah_bt_coex_wlan_weight[1],
1838 ahp->ah_bt_coex_wlan_weight[2],
1839 ahp->ah_bt_coex_wlan_weight[3]);
1843 void ar9300_mci_bt_coex_disable(struct ath_hal *ah)
1845 struct ath_hal_9300 *ahp = AH9300(ah);
1847 HALDEBUG(ah, HAL_DEBUG_BT_COEX,
1848 "(MCI) %s: Set weight to stomp none.\n", __func__);
1850 ar9300_mci_bt_coex_set_weights(ah, HAL_BT_COEX_STOMP_NONE);
1853 * In Jupiter, when coex is disabled, we just set weight
1854 * table to be in favor of WLAN.
1856 OS_REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS0, ahp->ah_bt_coex_wlan_weight[0]);
1857 OS_REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS1, ahp->ah_bt_coex_wlan_weight[1]);
1858 OS_REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS2, ahp->ah_bt_coex_wlan_weight[2]);
1859 OS_REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS3, ahp->ah_bt_coex_wlan_weight[3]);
1861 ahp->ah_bt_coex_enabled = AH_FALSE;
1864 int ar9300_mci_bt_coex_enable(struct ath_hal *ah)
1866 struct ath_hal_9300 *ahp = AH9300(ah);
1868 /* Mainly change the WLAN weight table */
1869 OS_REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS0, ahp->ah_bt_coex_wlan_weight[0]);
1870 OS_REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS1, ahp->ah_bt_coex_wlan_weight[1]);
1871 OS_REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS2, ahp->ah_bt_coex_wlan_weight[2]);
1872 OS_REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS3, ahp->ah_bt_coex_wlan_weight[3]);
1874 /* Send ACK even when BT has higher priority. */
1875 OS_REG_RMW_FIELD(ah, AR_QUIET1, AR_QUIET1_QUIET_ACK_CTS_ENABLE, 1);
1877 if (ahp->ah_bt_coex_flag & HAL_BT_COEX_FLAG_LOW_ACK_PWR) {
1878 OS_REG_WRITE(ah, AR_TPC, HAL_BT_COEX_LOW_ACK_POWER);
1881 OS_REG_WRITE(ah, AR_TPC, HAL_BT_COEX_HIGH_ACK_POWER);
1884 ahp->ah_bt_coex_enabled = AH_TRUE;
1889 #endif /* ATH_SUPPORT_MCI */