1250003Sadrian/* 2250003Sadrian * Copyright (c) 2013 Qualcomm Atheros, Inc. 3250003Sadrian * 4250003Sadrian * Permission to use, copy, modify, and/or distribute this software for any 5250003Sadrian * purpose with or without fee is hereby granted, provided that the above 6250003Sadrian * copyright notice and this permission notice appear in all copies. 7250003Sadrian * 8250003Sadrian * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 9250003Sadrian * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 10250003Sadrian * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 11250003Sadrian * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 12250003Sadrian * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 13250003Sadrian * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 14250003Sadrian * PERFORMANCE OF THIS SOFTWARE. 15250003Sadrian */ 16250003Sadrian 17250003Sadrian 18250003Sadrian#include "opt_ah.h" 19250003Sadrian 20250003Sadrian#include "ah.h" 21250003Sadrian#include "ah_internal.h" 22250003Sadrian 23250003Sadrian#include "ar9300/ar9300.h" 24250003Sadrian#include "ar9300/ar9300reg.h" 25250003Sadrian#include "ar9300/ar9300phy.h" 26250003Sadrian 27250003Sadrian#if ATH_SUPPORT_MCI 28250003Sadrian 29250003Sadrian#define AH_MCI_REMOTE_RESET_INTERVAL_US 500 30250003Sadrian#define AH_MCI_DEBUG_PRINT_SCHED 0 31250003Sadrian 32250003Sadrianstatic void ar9300_mci_print_msg(struct ath_hal *ah, HAL_BOOL send,u_int8_t hdr, 33250003Sadrian int len, u_int32_t *pl) 34250003Sadrian{ 35250008Sadrian#if 0 36250003Sadrian char s[128]; 37250003Sadrian char *p = s; 38250003Sadrian int i; 39250003Sadrian u_int8_t *p_data = (u_int8_t *) pl; 40250003Sadrian 41250003Sadrian if (send) { 42250003Sadrian p += snprintf(s, 60, 43250003Sadrian "(MCI) >>>>> Hdr: %02X, Len: %d, Payload:", hdr, len); 44250003Sadrian } 45250003Sadrian else { 46250003Sadrian p += snprintf(s, 60, 47250003Sadrian "(MCI) <<<<< Hdr: %02X, Len: %d, Payload:", hdr, len); 48250003Sadrian } 49250003Sadrian for ( i=0; i<len; i++) 50250003Sadrian { 51250003Sadrian p += snprintf(p, 60, " %02x", *(p_data + i)); 52250003Sadrian } 53250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, "%s\n", s); 54250003Sadrian/* 55250003Sadrian for ( i=0; i<(len + 3)/4; i++) 56250003Sadrian { 57250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) 0x%08x\n", *(pl + i)); 58250003Sadrian } 59250003Sadrian*/ 60250003Sadrian#endif 61250003Sadrian} 62250003Sadrian 63250003Sadrianstatic 64250003Sadrianvoid ar9300_mci_osla_setup(struct ath_hal *ah, HAL_BOOL enable) 65250003Sadrian{ 66250008Sadrian// struct ath_hal_9300 *ahp = AH9300(ah); 67250003Sadrian u_int32_t thresh; 68250003Sadrian 69250003Sadrian if (enable) { 70250003Sadrian OS_REG_RMW_FIELD(ah, AR_MCI_SCHD_TABLE_2, AR_MCI_SCHD_TABLE_2_HW_BASED, 1); 71250003Sadrian OS_REG_RMW_FIELD(ah, AR_MCI_SCHD_TABLE_2, AR_MCI_SCHD_TABLE_2_MEM_BASED, 1); 72250003Sadrian 73250008Sadrian if (!(ah->ah_config.ath_hal_mci_config & 74250003Sadrian ATH_MCI_CONFIG_DISABLE_AGGR_THRESH)) 75250003Sadrian { 76250008Sadrian thresh = MS(ah->ah_config.ath_hal_mci_config, 77250003Sadrian ATH_MCI_CONFIG_AGGR_THRESH); 78250003Sadrian OS_REG_RMW_FIELD(ah, AR_BTCOEX_CTRL, 79250003Sadrian AR_BTCOEX_CTRL_AGGR_THRESH, thresh); 80250003Sadrian OS_REG_RMW_FIELD(ah, AR_BTCOEX_CTRL, 81250003Sadrian AR_BTCOEX_CTRL_TIME_TO_NEXT_BT_THRESH_EN, 1); 82250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, 83250003Sadrian "(MCI) SCHED aggr thresh: on, thresh=%d (%d.%d%%)\n", 84250003Sadrian thresh, (thresh + 1)*125/10, (thresh + 1)*125%10); 85250003Sadrian 86250003Sadrian } 87250003Sadrian else { 88250003Sadrian OS_REG_RMW_FIELD(ah, AR_BTCOEX_CTRL, 89250003Sadrian AR_BTCOEX_CTRL_TIME_TO_NEXT_BT_THRESH_EN, 0); 90250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) SCHED aggr thresh: off\n"); 91250003Sadrian } 92250003Sadrian OS_REG_RMW_FIELD(ah, AR_BTCOEX_CTRL, 93250003Sadrian AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN, 1); 94250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) SCHED one step look ahead: on\n"); 95250003Sadrian } 96250003Sadrian else { 97250003Sadrian OS_REG_CLR_BIT(ah, AR_BTCOEX_CTRL, 98250003Sadrian AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN); 99250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) SCHED one step look ahead: off\n"); 100250003Sadrian } 101250003Sadrian} 102250003Sadrian 103250003Sadrianstatic void ar9300_mci_reset_req_wakeup(struct ath_hal *ah) 104250003Sadrian{ 105250003Sadrian /* to be tested in emulation */ 106250003Sadrian if (AR_SREV_JUPITER_20(ah) || AR_SREV_APHRODITE(ah)) { 107250003Sadrian OS_REG_RMW_FIELD(ah, AR_MCI_COMMAND2, 108250003Sadrian AR_MCI_COMMAND2_RESET_REQ_WAKEUP, 1); 109250003Sadrian OS_DELAY(1); 110250003Sadrian OS_REG_RMW_FIELD(ah, AR_MCI_COMMAND2, 111250003Sadrian AR_MCI_COMMAND2_RESET_REQ_WAKEUP, 0); 112250003Sadrian } 113250003Sadrian} 114250003Sadrian 115250003Sadrianstatic int32_t ar9300_mci_wait_for_interrupt(struct ath_hal *ah, 116250003Sadrian u_int32_t address, 117250003Sadrian u_int32_t bit_position, 118250003Sadrian int32_t time_out) 119250003Sadrian{ 120250008Sadrian int data; //, loop; 121250003Sadrian 122250003Sadrian while (time_out) { 123250003Sadrian data = OS_REG_READ(ah, address); 124250003Sadrian 125250003Sadrian if (data & bit_position) { 126250003Sadrian OS_REG_WRITE(ah, address, bit_position); 127250003Sadrian if (address == AR_MCI_INTERRUPT_RX_MSG_RAW) { 128250003Sadrian if (bit_position & AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE) { 129250003Sadrian ar9300_mci_reset_req_wakeup(ah); 130250003Sadrian } 131250003Sadrian if (bit_position & (AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING | 132250003Sadrian AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING)) 133250003Sadrian { 134250003Sadrian OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, 135250003Sadrian AR_MCI_INTERRUPT_REMOTE_SLEEP_UPDATE); 136250003Sadrian } 137250003Sadrian OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, AR_MCI_INTERRUPT_RX_MSG); 138250003Sadrian } 139250003Sadrian break; 140250003Sadrian } 141250003Sadrian 142250003Sadrian OS_DELAY(10); 143250003Sadrian time_out -= 10; 144250003Sadrian if (time_out < 0) { 145250003Sadrian break; 146250003Sadrian } 147250003Sadrian } 148250003Sadrian 149250003Sadrian if (time_out <= 0) { 150250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, 151250003Sadrian "(MCI) %s: Wait for Reg0x%08x = 0x%08x timeout.\n", 152250003Sadrian __func__, address, bit_position); 153250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, 154250003Sadrian "(MCI) INT_RAW = 0x%08x, RX_MSG_RAW = 0x%08x", 155250003Sadrian OS_REG_READ(ah, AR_MCI_INTERRUPT_RAW), 156250003Sadrian OS_REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_RAW)); 157250003Sadrian time_out = 0; 158250003Sadrian } 159250003Sadrian return time_out; 160250003Sadrian} 161250003Sadrian 162250003Sadrianvoid ar9300_mci_remote_reset(struct ath_hal *ah, HAL_BOOL wait_done) 163250003Sadrian{ 164250003Sadrian u_int32_t payload[4] = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffff00}; 165250003Sadrian 166250003Sadrian ar9300_mci_send_message(ah, MCI_REMOTE_RESET, 0, payload, 16, 167250003Sadrian wait_done, AH_FALSE); 168250003Sadrian 169250003Sadrian OS_DELAY(5); 170250003Sadrian} 171250003Sadrian 172250003Sadrianvoid ar9300_mci_send_lna_transfer(struct ath_hal *ah, HAL_BOOL wait_done) 173250003Sadrian{ 174250003Sadrian u_int32_t payload = 0x00000000; 175250003Sadrian 176250003Sadrian ar9300_mci_send_message(ah, MCI_LNA_TRANS, 0, &payload, 1, 177250003Sadrian wait_done, AH_FALSE); 178250003Sadrian} 179250003Sadrian 180250003Sadrianstatic void ar9300_mci_send_req_wake(struct ath_hal *ah, HAL_BOOL wait_done) 181250003Sadrian{ 182250003Sadrian ar9300_mci_send_message(ah, MCI_REQ_WAKE, 183250003Sadrian HAL_MCI_FLAG_DISABLE_TIMESTAMP, AH_NULL, 0, wait_done, AH_FALSE); 184250003Sadrian 185250003Sadrian OS_DELAY(5); 186250003Sadrian} 187250003Sadrian 188250003Sadrianvoid ar9300_mci_send_sys_waking(struct ath_hal *ah, HAL_BOOL wait_done) 189250003Sadrian{ 190250003Sadrian ar9300_mci_send_message(ah, MCI_SYS_WAKING, 191250003Sadrian HAL_MCI_FLAG_DISABLE_TIMESTAMP, AH_NULL, 0, wait_done, AH_FALSE); 192250003Sadrian} 193250003Sadrian 194250003Sadrianstatic void ar9300_mci_send_lna_take(struct ath_hal *ah, HAL_BOOL wait_done) 195250003Sadrian{ 196250003Sadrian u_int32_t payload = 0x70000000; 197250003Sadrian 198250003Sadrian /* LNA gain index is set to 7. */ 199250003Sadrian ar9300_mci_send_message(ah, MCI_LNA_TAKE, 200250003Sadrian HAL_MCI_FLAG_DISABLE_TIMESTAMP, &payload, 1, wait_done, AH_FALSE); 201250003Sadrian} 202250003Sadrian 203250003Sadrianstatic void ar9300_mci_send_sys_sleeping(struct ath_hal *ah, HAL_BOOL wait_done) 204250003Sadrian{ 205250003Sadrian ar9300_mci_send_message(ah, MCI_SYS_SLEEPING, 206250003Sadrian HAL_MCI_FLAG_DISABLE_TIMESTAMP, AH_NULL, 0, wait_done, AH_FALSE); 207250003Sadrian} 208250003Sadrian 209250003Sadrianstatic void 210250003Sadrianar9300_mci_send_coex_version_query(struct ath_hal *ah, HAL_BOOL wait_done) 211250003Sadrian{ 212250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 213250003Sadrian u_int32_t payload[4] = {0, 0, 0, 0}; 214250003Sadrian 215250003Sadrian if ((ahp->ah_mci_coex_bt_version_known == AH_FALSE) && 216250003Sadrian (ahp->ah_mci_bt_state != MCI_BT_SLEEP)) { 217250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) Send Coex version query.\n"); 218250003Sadrian MCI_GPM_SET_TYPE_OPCODE(payload, 219250003Sadrian MCI_GPM_COEX_AGENT, MCI_GPM_COEX_VERSION_QUERY); 220250003Sadrian ar9300_mci_send_message(ah, MCI_GPM, 0, payload, 16, wait_done, AH_TRUE); 221250003Sadrian } 222250003Sadrian} 223250003Sadrian 224250003Sadrianstatic void 225250003Sadrianar9300_mci_send_coex_version_response(struct ath_hal *ah, HAL_BOOL wait_done) 226250003Sadrian{ 227250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 228250003Sadrian u_int32_t payload[4] = {0, 0, 0, 0}; 229250003Sadrian 230250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) Send Coex version response.\n"); 231250003Sadrian MCI_GPM_SET_TYPE_OPCODE(payload, 232250003Sadrian MCI_GPM_COEX_AGENT, MCI_GPM_COEX_VERSION_RESPONSE); 233250003Sadrian *(((u_int8_t *)payload) + MCI_GPM_COEX_B_MAJOR_VERSION) = 234250003Sadrian ahp->ah_mci_coex_major_version_wlan; 235250003Sadrian *(((u_int8_t *)payload) + MCI_GPM_COEX_B_MINOR_VERSION) = 236250003Sadrian ahp->ah_mci_coex_minor_version_wlan; 237250003Sadrian ar9300_mci_send_message(ah, MCI_GPM, 0, payload, 16, wait_done, AH_TRUE); 238250003Sadrian} 239250003Sadrian 240250003Sadrianstatic void 241250003Sadrianar9300_mci_send_coex_wlan_channels(struct ath_hal *ah, HAL_BOOL wait_done) 242250003Sadrian{ 243250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 244250003Sadrian u_int32_t *payload = &ahp->ah_mci_coex_wlan_channels[0]; 245250003Sadrian 246250003Sadrian if ((ahp->ah_mci_coex_wlan_channels_update == AH_TRUE) && 247250003Sadrian (ahp->ah_mci_bt_state != MCI_BT_SLEEP)) 248250003Sadrian { 249250003Sadrian MCI_GPM_SET_TYPE_OPCODE(payload, 250250003Sadrian MCI_GPM_COEX_AGENT, MCI_GPM_COEX_WLAN_CHANNELS); 251250003Sadrian ar9300_mci_send_message(ah, MCI_GPM, 0, payload, 16, wait_done, AH_TRUE); 252250003Sadrian MCI_GPM_SET_TYPE_OPCODE(payload, 0xff, 0xff); 253250003Sadrian } 254250003Sadrian} 255250003Sadrian 256250003Sadrianstatic void ar9300_mci_send_coex_bt_status_query(struct ath_hal *ah, 257250003Sadrian HAL_BOOL wait_done, u_int8_t query_type) 258250003Sadrian{ 259250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 260250003Sadrian u_int32_t pld[4] = {0, 0, 0, 0}; 261250003Sadrian HAL_BOOL query_btinfo = query_type & 262250003Sadrian (MCI_GPM_COEX_QUERY_BT_ALL_INFO | MCI_GPM_COEX_QUERY_BT_TOPOLOGY); 263250003Sadrian 264250003Sadrian if (ahp->ah_mci_bt_state != MCI_BT_SLEEP) { 265250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, 266250003Sadrian "(MCI) Send Coex BT Status Query 0x%02X\n", query_type); 267250003Sadrian MCI_GPM_SET_TYPE_OPCODE(pld, 268250003Sadrian MCI_GPM_COEX_AGENT, MCI_GPM_COEX_STATUS_QUERY); 269250003Sadrian *(((u_int8_t *)pld) + MCI_GPM_COEX_B_BT_BITMAP) = query_type; 270250003Sadrian /* 271250003Sadrian * If bt_status_query message is thought not sent successfully, 272250003Sadrian * then ah_mci_need_flush_btinfo should be set again. 273250003Sadrian */ 274250003Sadrian if (!ar9300_mci_send_message(ah, MCI_GPM, 0, pld, 16, wait_done, AH_TRUE)) 275250003Sadrian { 276250003Sadrian if (query_btinfo) { 277250003Sadrian ahp->ah_mci_need_flush_btinfo = AH_TRUE; 278250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, 279250003Sadrian "(MCI) send bt_status_query fail, set flush flag again\n"); 280250003Sadrian } 281250003Sadrian } 282250003Sadrian if (query_btinfo) { 283250003Sadrian ahp->ah_mci_query_bt = AH_FALSE; 284250003Sadrian } 285250003Sadrian } 286250003Sadrian} 287250003Sadrian 288250003Sadrianvoid ar9300_mci_send_coex_halt_bt_gpm(struct ath_hal *ah, 289250003Sadrian HAL_BOOL halt, HAL_BOOL wait_done) 290250003Sadrian{ 291250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 292250003Sadrian u_int32_t payload[4] = {0, 0, 0, 0}; 293250003Sadrian 294250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, 295250003Sadrian "(MCI) Send Coex %s BT GPM.\n", (halt == AH_TRUE)?"HALT":"UNHALT"); 296250003Sadrian 297250003Sadrian MCI_GPM_SET_TYPE_OPCODE(payload, 298250003Sadrian MCI_GPM_COEX_AGENT, MCI_GPM_COEX_HALT_BT_GPM); 299250003Sadrian if (halt == AH_TRUE) { 300250003Sadrian ahp->ah_mci_query_bt = AH_TRUE; 301250003Sadrian /* Send next UNHALT no matter HALT sent or not */ 302250003Sadrian ahp->ah_mci_unhalt_bt_gpm = AH_TRUE; 303250003Sadrian ahp->ah_mci_need_flush_btinfo = AH_TRUE; 304250003Sadrian *(((u_int8_t *)payload) + MCI_GPM_COEX_B_HALT_STATE) = 305250003Sadrian MCI_GPM_COEX_BT_GPM_HALT; 306250003Sadrian } 307250003Sadrian else { 308250003Sadrian *(((u_int8_t *)payload) + MCI_GPM_COEX_B_HALT_STATE) = 309250003Sadrian MCI_GPM_COEX_BT_GPM_UNHALT; 310250003Sadrian } 311250003Sadrian ar9300_mci_send_message(ah, MCI_GPM, 0, payload, 16, wait_done, AH_TRUE); 312250003Sadrian} 313250003Sadrian 314250003Sadrianstatic HAL_BOOL ar9300_mci_send_coex_bt_flags(struct ath_hal *ah, HAL_BOOL wait_done, 315250003Sadrian u_int8_t opcode, u_int32_t bt_flags) 316250003Sadrian{ 317250008Sadrian// struct ath_hal_9300 *ahp = AH9300(ah); 318250003Sadrian u_int32_t pld[4] = {0, 0, 0, 0}; 319250003Sadrian 320250003Sadrian MCI_GPM_SET_TYPE_OPCODE(pld, 321250003Sadrian MCI_GPM_COEX_AGENT, MCI_GPM_COEX_BT_UPDATE_FLAGS); 322250003Sadrian 323250003Sadrian *(((u_int8_t *)pld) + MCI_GPM_COEX_B_BT_FLAGS_OP) = opcode; 324250003Sadrian *(((u_int8_t *)pld) + MCI_GPM_COEX_W_BT_FLAGS + 0) = bt_flags & 0xFF; 325250003Sadrian *(((u_int8_t *)pld) + MCI_GPM_COEX_W_BT_FLAGS + 1) = 326250003Sadrian (bt_flags >> 8) & 0xFF; 327250003Sadrian *(((u_int8_t *)pld) + MCI_GPM_COEX_W_BT_FLAGS + 2) = 328250003Sadrian (bt_flags >> 16) & 0xFF; 329250003Sadrian *(((u_int8_t *)pld) + MCI_GPM_COEX_W_BT_FLAGS + 3) = 330250003Sadrian (bt_flags >> 24) & 0xFF; 331250003Sadrian 332250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, 333250003Sadrian "(MCI) BT_MCI_FLAGS: Send Coex BT Update Flags %s 0x%08x\n", 334250003Sadrian (opcode == MCI_GPM_COEX_BT_FLAGS_READ)?"READ": 335250003Sadrian ((opcode == MCI_GPM_COEX_BT_FLAGS_SET)?"SET":"CLEAR"), 336250003Sadrian bt_flags); 337250003Sadrian 338250003Sadrian return ar9300_mci_send_message(ah, MCI_GPM, 0, pld, 16, wait_done, AH_TRUE); 339250003Sadrian} 340250003Sadrian 341250003Sadrianvoid ar9300_mci_2g5g_changed(struct ath_hal *ah, HAL_BOOL is_2g) 342250003Sadrian{ 343250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 344250003Sadrian 345250003Sadrian if (ahp->ah_mci_coex_2g5g_update == AH_FALSE) { 346250003Sadrian if (ahp->ah_mci_coex_is_2g == is_2g) { 347250003Sadrian //HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) BT_MCI_FLAGS: not changed\n"); 348250003Sadrian } else { 349250003Sadrian ahp->ah_mci_coex_2g5g_update = AH_TRUE; 350250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) BT_MCI_FLAGS: changed\n"); 351250003Sadrian } 352250003Sadrian } else { 353250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) BT_MCI_FLAGS: force send\n"); 354250003Sadrian } 355250003Sadrian ahp->ah_mci_coex_is_2g = is_2g; 356250003Sadrian} 357250003Sadrian 358250003Sadrianstatic void ar9300_mci_send_2g5g_status(struct ath_hal *ah, HAL_BOOL wait_done) 359250003Sadrian{ 360250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 361250003Sadrian u_int32_t new_flags, to_set, to_clear; 362250003Sadrian 363250003Sadrian if ((AR_SREV_JUPITER_20(ah) || AR_SREV_APHRODITE(ah)) && 364250003Sadrian (ahp->ah_mci_coex_2g5g_update == AH_TRUE) && 365250003Sadrian (ahp->ah_mci_bt_state != MCI_BT_SLEEP)) 366250003Sadrian { 367250003Sadrian if (ahp->ah_mci_coex_is_2g) { 368250003Sadrian new_flags = HAL_MCI_2G_FLAGS; 369250003Sadrian to_clear = HAL_MCI_2G_FLAGS_CLEAR_MASK; 370250003Sadrian to_set = HAL_MCI_2G_FLAGS_SET_MASK; 371250003Sadrian } else { 372250003Sadrian new_flags = HAL_MCI_5G_FLAGS; 373250003Sadrian to_clear = HAL_MCI_5G_FLAGS_CLEAR_MASK; 374250003Sadrian to_set = HAL_MCI_5G_FLAGS_SET_MASK; 375250003Sadrian } 376250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, 377250003Sadrian "(MCI) BT_MCI_FLAGS: %s (0x%08x) clr=0x%08x, set=0x%08x\n", 378250003Sadrian ahp->ah_mci_coex_is_2g?"2G":"5G", new_flags, to_clear, to_set); 379250003Sadrian if (to_clear) { 380250003Sadrian ar9300_mci_send_coex_bt_flags(ah, wait_done, 381250003Sadrian MCI_GPM_COEX_BT_FLAGS_CLEAR, to_clear); 382250003Sadrian } 383250003Sadrian if (to_set) { 384250003Sadrian ar9300_mci_send_coex_bt_flags(ah, wait_done, 385250003Sadrian MCI_GPM_COEX_BT_FLAGS_SET, to_set); 386250003Sadrian } 387250003Sadrian } 388250003Sadrian if (AR_SREV_JUPITER_10(ah) && (ahp->ah_mci_bt_state != MCI_BT_SLEEP)) { 389250003Sadrian ahp->ah_mci_coex_2g5g_update = AH_FALSE; 390250003Sadrian } 391250003Sadrian} 392250003Sadrian 393250003Sadrianvoid ar9300_mci_2g5g_switch(struct ath_hal *ah, HAL_BOOL wait_done) 394250003Sadrian{ 395250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 396250003Sadrian 397250003Sadrian if (ahp->ah_mci_coex_2g5g_update) 398250003Sadrian { 399250003Sadrian if (ahp->ah_mci_coex_is_2g) { 400250003Sadrian ar9300_mci_send_2g5g_status(ah, AH_TRUE); 401250003Sadrian 402250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) Send LNA trans\n"); 403250003Sadrian ar9300_mci_send_lna_transfer(ah, AH_TRUE); 404250003Sadrian OS_DELAY(5); 405250003Sadrian 406250003Sadrian OS_REG_CLR_BIT(ah, AR_MCI_TX_CTRL, 407250003Sadrian AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE); 408250003Sadrian if (AR_SREV_JUPITER_20(ah) || AR_SREV_APHRODITE(ah)) { 409250003Sadrian OS_REG_CLR_BIT(ah, AR_GLB_CONTROL, 410250003Sadrian AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL); 411250008Sadrian if (!(ah->ah_config.ath_hal_mci_config & 412250003Sadrian ATH_MCI_CONFIG_DISABLE_OSLA)) 413250003Sadrian { 414250003Sadrian ar9300_mci_osla_setup(ah, AH_TRUE); 415250003Sadrian } 416250003Sadrian } 417250003Sadrian } else { 418250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) Send LNA take\n"); 419250003Sadrian ar9300_mci_send_lna_take(ah, AH_TRUE); 420250003Sadrian OS_DELAY(5); 421250003Sadrian 422250003Sadrian OS_REG_SET_BIT(ah, AR_MCI_TX_CTRL, 423250003Sadrian AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE); 424250003Sadrian if (AR_SREV_JUPITER_20(ah) || AR_SREV_APHRODITE(ah)) { 425250003Sadrian OS_REG_SET_BIT(ah, AR_GLB_CONTROL, 426250003Sadrian AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL); 427250003Sadrian ar9300_mci_osla_setup(ah, AH_FALSE); 428250003Sadrian } 429250003Sadrian 430250003Sadrian ar9300_mci_send_2g5g_status(ah, AH_TRUE); 431250003Sadrian } 432250003Sadrian } 433250003Sadrian 434250003Sadrian /* 435250003Sadrian * Update self gen chain mask. Also set basic set for 436250003Sadrian * txbf. 437250003Sadrian */ 438250003Sadrian if (AR_SREV_JUPITER(ah)) { 439250003Sadrian if (ahp->ah_mci_coex_is_2g) { 440250003Sadrian ahp->ah_reduced_self_gen_mask = AH_TRUE; 441250003Sadrian OS_REG_WRITE(ah, AR_SELFGEN_MASK, 0x02); 442250003Sadrian ar9300_txbf_set_basic_set(ah); 443250003Sadrian } 444250003Sadrian else { 445250003Sadrian ahp->ah_reduced_self_gen_mask = AH_FALSE; 446250003Sadrian ar9300_txbf_set_basic_set(ah); 447250003Sadrian } 448250003Sadrian } 449250003Sadrian} 450250003Sadrian 451250003Sadrianvoid ar9300_mci_mute_bt(struct ath_hal *ah) 452250003Sadrian{ 453250003Sadrian /* disable all MCI messages */ 454250003Sadrian OS_REG_WRITE(ah, AR_MCI_MSG_ATTRIBUTES_TABLE, 0xFFFF0000); 455250003Sadrian OS_REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS0, 0xFFFFFFFF); 456250003Sadrian OS_REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS1, 0xFFFFFFFF); 457250003Sadrian OS_REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS2, 0xFFFFFFFF); 458250003Sadrian OS_REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS3, 0xFFFFFFFF); 459250003Sadrian OS_REG_SET_BIT(ah, AR_MCI_TX_CTRL, AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE); 460250003Sadrian /* wait pending HW messages to flush out */ 461250003Sadrian OS_DELAY(10); 462250003Sadrian 463250003Sadrian /* 464250003Sadrian * Send LNA_TAKE and SYS_SLEEPING when 465250003Sadrian * 1. reset not after resuming from full sleep 466250003Sadrian * 2. before reset MCI RX, to quiet BT and avoid MCI RX misalignment 467250003Sadrian */ 468250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) Send LNA take\n"); 469250003Sadrian ar9300_mci_send_lna_take(ah, AH_TRUE); 470250003Sadrian OS_DELAY(5); 471250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) Send sys sleeping\n"); 472250003Sadrian ar9300_mci_send_sys_sleeping(ah, AH_TRUE); 473250003Sadrian} 474250003Sadrian 475250003Sadrianstatic void ar9300_mci_observation_set_up(struct ath_hal *ah) 476250003Sadrian{ 477250003Sadrian /* 478250003Sadrian * Set up the observation bus in order to monitor MCI bus 479250003Sadrian * through GPIOs (0, 1, 2, and 3). 480250003Sadrian */ 481250003Sadrian /* 482250003Sadrian OS_REG_WRITE(ah, AR_GPIO_INTR_POL, 0x00420000); 483250003Sadrian OS_REG_WRITE(ah, AR_GPIO_OE_OUT, 0x000000ff); // 4050 484250003Sadrian OS_REG_WRITE(ah, AR_GPIO_OUTPUT_MUX1, 0x000bdab4); // 4068 485250003Sadrian OS_REG_WRITE(ah, AR_OBS, 0x0000004b); // 4088 486250003Sadrian OS_REG_WRITE(ah, AR_DIAG_SW, 0x080c0000); 487250003Sadrian OS_REG_WRITE(ah, AR_MACMISC, 0x0001a000); 488250003Sadrian OS_REG_WRITE(ah, AR_PHY_TEST, 0x00080000); // a360 489250003Sadrian OS_REG_WRITE(ah, AR_PHY_TEST_CTL_STATUS, 0xe0000000); // a364 490250003Sadrian */ 491250003Sadrian 492250008Sadrian if (ah->ah_config.ath_hal_mci_config & 493250003Sadrian ATH_MCI_CONFIG_MCI_OBS_MCI) 494250003Sadrian { 495250003Sadrian ar9300_gpio_cfg_output(ah, 3, HAL_GPIO_OUTPUT_MUX_AS_MCI_WLAN_DATA); 496250003Sadrian ar9300_gpio_cfg_output(ah, 2, HAL_GPIO_OUTPUT_MUX_AS_MCI_WLAN_CLK); 497250003Sadrian ar9300_gpio_cfg_output(ah, 1, HAL_GPIO_OUTPUT_MUX_AS_MCI_BT_DATA); 498250003Sadrian ar9300_gpio_cfg_output(ah, 0, HAL_GPIO_OUTPUT_MUX_AS_MCI_BT_CLK); 499250003Sadrian } 500250008Sadrian else if (ah->ah_config.ath_hal_mci_config & 501250003Sadrian ATH_MCI_CONFIG_MCI_OBS_TXRX) 502250003Sadrian { 503250003Sadrian ar9300_gpio_cfg_output(ah, 3, HAL_GPIO_OUTPUT_MUX_AS_WL_IN_TX); 504250003Sadrian ar9300_gpio_cfg_output(ah, 2, HAL_GPIO_OUTPUT_MUX_AS_WL_IN_RX); 505250003Sadrian ar9300_gpio_cfg_output(ah, 1, HAL_GPIO_OUTPUT_MUX_AS_BT_IN_TX); 506250003Sadrian ar9300_gpio_cfg_output(ah, 0, HAL_GPIO_OUTPUT_MUX_AS_BT_IN_RX); 507250003Sadrian ar9300_gpio_cfg_output(ah, 5, HAL_GPIO_OUTPUT_MUX_AS_OUTPUT); 508250003Sadrian } 509250008Sadrian else if (ah->ah_config.ath_hal_mci_config & 510250003Sadrian ATH_MCI_CONFIG_MCI_OBS_BT) 511250003Sadrian { 512250003Sadrian ar9300_gpio_cfg_output(ah, 3, HAL_GPIO_OUTPUT_MUX_AS_BT_IN_TX); 513250003Sadrian ar9300_gpio_cfg_output(ah, 2, HAL_GPIO_OUTPUT_MUX_AS_BT_IN_RX); 514250003Sadrian ar9300_gpio_cfg_output(ah, 1, HAL_GPIO_OUTPUT_MUX_AS_MCI_BT_DATA); 515250003Sadrian ar9300_gpio_cfg_output(ah, 0, HAL_GPIO_OUTPUT_MUX_AS_MCI_BT_CLK); 516250003Sadrian } 517250003Sadrian else { 518250003Sadrian return; 519250003Sadrian } 520250003Sadrian 521250003Sadrian OS_REG_SET_BIT(ah, 522250003Sadrian AR_HOSTIF_REG(ah, AR_GPIO_INPUT_EN_VAL), AR_GPIO_JTAG_DISABLE); 523250003Sadrian 524250003Sadrian if (AR_SREV_JUPITER_20_OR_LATER(ah) || AR_SREV_APHRODITE(ah)) { 525250003Sadrian OS_REG_RMW_FIELD(ah, AR_GLB_CONTROL, AR_GLB_DS_JTAG_DISABLE, 1); 526250003Sadrian OS_REG_RMW_FIELD(ah, AR_GLB_CONTROL, AR_GLB_WLAN_UART_INTF_EN, 0); 527250003Sadrian OS_REG_WRITE(ah, AR_GLB_GPIO_CONTROL, 528250003Sadrian (OS_REG_READ(ah, AR_GLB_GPIO_CONTROL) | 529250003Sadrian ATH_MCI_CONFIG_MCI_OBS_GPIO)); 530250003Sadrian } 531250003Sadrian 532250003Sadrian OS_REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2, AR_BTCOEX_CTRL2_GPIO_OBS_SEL, 0); 533250003Sadrian OS_REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2, AR_BTCOEX_CTRL2_MAC_BB_OBS_SEL, 1); 534250003Sadrian OS_REG_WRITE(ah, AR_HOSTIF_REG(ah, AR_OBS), 0x4b); 535250003Sadrian OS_REG_RMW_FIELD(ah, AR_DIAG_SW, AR_DIAG_OBS_PT_SEL1, 0x03); 536250003Sadrian OS_REG_RMW_FIELD(ah, AR_DIAG_SW, AR_DIAG_OBS_PT_SEL2, 0x01); 537250003Sadrian OS_REG_RMW_FIELD(ah, AR_MACMISC, AR_MACMISC_MISC_OBS_BUS_LSB, 0x02); 538250003Sadrian OS_REG_RMW_FIELD(ah, AR_MACMISC, AR_MACMISC_MISC_OBS_BUS_MSB, 0x03); 539250003Sadrian //OS_REG_RMW_FIELD(ah, AR_PHY_TEST, AR_PHY_TEST_BBB_OBS_SEL, 0x01); 540250003Sadrian OS_REG_RMW_FIELD(ah, AR_PHY_TEST_CTL_STATUS, 541250003Sadrian AR_PHY_TEST_CTL_DEBUGPORT_SEL, 0x07); 542250003Sadrian} 543250003Sadrian 544250003Sadrianstatic void ar9300_mci_process_gpm_extra(struct ath_hal *ah, 545250003Sadrian u_int8_t gpm_type, u_int8_t gpm_opcode, u_int32_t *p_gpm) 546250003Sadrian{ 547250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 548250003Sadrian u_int8_t *p_data = (u_int8_t *) p_gpm; 549250003Sadrian 550250003Sadrian switch (gpm_type) 551250003Sadrian { 552250003Sadrian case MCI_GPM_COEX_AGENT: 553250003Sadrian switch (gpm_opcode) 554250003Sadrian { 555250003Sadrian case MCI_GPM_COEX_VERSION_QUERY: 556250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, 557250003Sadrian "(MCI) Recv GPM COEX Version Query.\n"); 558250003Sadrian ar9300_mci_send_coex_version_response(ah, AH_TRUE); 559250003Sadrian break; 560250003Sadrian 561250003Sadrian case MCI_GPM_COEX_VERSION_RESPONSE: 562250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, 563250003Sadrian "(MCI) Recv GPM COEX Version Response.\n"); 564250003Sadrian ahp->ah_mci_coex_major_version_bt = 565250003Sadrian *(p_data + MCI_GPM_COEX_B_MAJOR_VERSION); 566250003Sadrian ahp->ah_mci_coex_minor_version_bt = 567250003Sadrian *(p_data + MCI_GPM_COEX_B_MINOR_VERSION); 568250003Sadrian ahp->ah_mci_coex_bt_version_known = AH_TRUE; 569250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, 570250003Sadrian "(MCI) BT Coex version: %d.%d\n", 571250003Sadrian ahp->ah_mci_coex_major_version_bt, 572250003Sadrian ahp->ah_mci_coex_minor_version_bt); 573250003Sadrian break; 574250003Sadrian 575250003Sadrian case MCI_GPM_COEX_STATUS_QUERY: 576250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, 577250003Sadrian "(MCI) Recv GPM COEX Status Query = 0x%02X.\n", 578250003Sadrian *(p_data + MCI_GPM_COEX_B_WLAN_BITMAP)); 579250003Sadrian //if ((*(p_data + MCI_GPM_COEX_B_WLAN_BITMAP)) & 580250003Sadrian // MCI_GPM_COEX_QUERY_WLAN_ALL_INFO) 581250003Sadrian { 582250003Sadrian ahp->ah_mci_coex_wlan_channels_update = AH_TRUE; 583250003Sadrian ar9300_mci_send_coex_wlan_channels(ah, AH_TRUE); 584250003Sadrian } 585250003Sadrian break; 586250003Sadrian 587250003Sadrian case MCI_GPM_COEX_BT_PROFILE_INFO: 588250003Sadrian ahp->ah_mci_query_bt = AH_TRUE; 589250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, 590250003Sadrian "(MCI) Recv GPM COEX BT_Profile_Info (drop&query)\n"); 591250003Sadrian break; 592250003Sadrian 593250003Sadrian case MCI_GPM_COEX_BT_STATUS_UPDATE: 594250003Sadrian ahp->ah_mci_query_bt = AH_TRUE; 595250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, 596250003Sadrian "(MCI) Recv GPM COEX BT_Status_Update " 597250003Sadrian "SEQ=%d (drop&query)\n", 598250003Sadrian *(p_gpm + 3)); 599250003Sadrian break; 600250003Sadrian 601250003Sadrian default: 602250003Sadrian break; 603250003Sadrian } 604250003Sadrian default: 605250003Sadrian break; 606250003Sadrian } 607250003Sadrian} 608250003Sadrian 609250003Sadrianu_int32_t ar9300_mci_wait_for_gpm(struct ath_hal *ah, u_int8_t gpm_type, 610250003Sadrian u_int8_t gpm_opcode, int32_t time_out) 611250003Sadrian{ 612250003Sadrian u_int32_t *p_gpm = NULL, mismatch = 0, more_data = HAL_MCI_GPM_NOMORE; 613250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 614250003Sadrian HAL_BOOL b_is_bt_cal_done = (gpm_type == MCI_GPM_BT_CAL_DONE); 615250003Sadrian u_int32_t offset; 616250003Sadrian u_int8_t recv_type = 0, recv_opcode = 0; 617250003Sadrian 618250003Sadrian if (time_out == 0) { 619250003Sadrian more_data = HAL_MCI_GPM_MORE; 620250003Sadrian } 621250003Sadrian 622250003Sadrian while (time_out > 0) 623250003Sadrian { 624250003Sadrian if (p_gpm != NULL) { 625250003Sadrian MCI_GPM_RECYCLE(p_gpm); 626250003Sadrian p_gpm = NULL; 627250003Sadrian } 628250003Sadrian 629250003Sadrian if (more_data != HAL_MCI_GPM_MORE) { 630250003Sadrian time_out = ar9300_mci_wait_for_interrupt(ah, 631250003Sadrian AR_MCI_INTERRUPT_RX_MSG_RAW, 632250003Sadrian AR_MCI_INTERRUPT_RX_MSG_GPM, 633250003Sadrian time_out); 634250003Sadrian } 635250003Sadrian 636250003Sadrian if (time_out) { 637250003Sadrian offset = ar9300_mci_state(ah, 638250003Sadrian HAL_MCI_STATE_NEXT_GPM_OFFSET, &more_data); 639250003Sadrian 640250003Sadrian if (offset == HAL_MCI_GPM_INVALID) { 641250003Sadrian continue; 642250003Sadrian } 643250003Sadrian p_gpm = (u_int32_t *) (ahp->ah_mci_gpm_buf + offset); 644250003Sadrian ar9300_mci_print_msg(ah, AH_FALSE, MCI_GPM, 16, p_gpm); 645250003Sadrian 646250003Sadrian recv_type = MCI_GPM_TYPE(p_gpm); 647250003Sadrian recv_opcode = MCI_GPM_OPCODE(p_gpm); 648250003Sadrian 649250003Sadrian if (MCI_GPM_IS_CAL_TYPE(recv_type)) { 650250003Sadrian if (recv_type == gpm_type) { 651250003Sadrian if ((gpm_type == MCI_GPM_BT_CAL_DONE) && !b_is_bt_cal_done) 652250003Sadrian { 653250003Sadrian gpm_type = MCI_GPM_BT_CAL_GRANT; 654250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, 655250003Sadrian "(MCI) Rcv BT_CAL_DONE. Now Wait BT_CAL_GRANT\n"); 656250003Sadrian continue; 657250003Sadrian } 658250003Sadrian if (gpm_type == MCI_GPM_BT_CAL_GRANT) { 659250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, 660250003Sadrian "(MCI) BT_CAL_GRANT seq=%d, req_count=%d\n", 661250003Sadrian *(p_gpm + 2), *(p_gpm + 3)); 662250003Sadrian } 663250003Sadrian break; 664250003Sadrian } 665250003Sadrian } 666250003Sadrian else { 667250003Sadrian if ((recv_type == gpm_type) && (recv_opcode == gpm_opcode)) { 668250003Sadrian break; 669250003Sadrian } 670250003Sadrian } 671250003Sadrian 672250003Sadrian /* not expected message */ 673250003Sadrian 674250003Sadrian /* 675250003Sadrian * Check if it's cal_grant 676250003Sadrian * 677250003Sadrian * When we're waiting for cal_grant in reset routine, it's 678250003Sadrian * possible that BT sends out cal_request at the same time. 679250003Sadrian * Since BT's calibration doesn't happen that often, we'll 680250003Sadrian * let BT completes calibration then we continue to wait 681250003Sadrian * for cal_grant from BT. 682250003Sadrian * Orginal: Wait BT_CAL_GRANT. 683250003Sadrian * New: Receive BT_CAL_REQ -> send WLAN_CAL_GRANT -> wait 684250003Sadrian * BT_CAL_DONE -> Wait BT_CAL_GRANT. 685250003Sadrian */ 686250003Sadrian if ((gpm_type == MCI_GPM_BT_CAL_GRANT) && 687250003Sadrian (recv_type == MCI_GPM_BT_CAL_REQ)) 688250003Sadrian { 689250003Sadrian u_int32_t payload[4] = {0, 0, 0, 0}; 690250003Sadrian 691250003Sadrian gpm_type = MCI_GPM_BT_CAL_DONE; 692250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, 693250003Sadrian "(MCI) Rcv BT_CAL_REQ. Send WLAN_CAL_GRANT.\n"); 694250003Sadrian 695250003Sadrian MCI_GPM_SET_CAL_TYPE(payload, MCI_GPM_WLAN_CAL_GRANT); 696250003Sadrian ar9300_mci_send_message(ah, MCI_GPM, 0, payload, 16, 697250003Sadrian AH_FALSE, AH_FALSE); 698250003Sadrian 699250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, 700250003Sadrian "(MCI) Now wait for BT_CAL_DONE.\n"); 701250003Sadrian continue; 702250003Sadrian } 703250003Sadrian else { 704250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, 705250003Sadrian "(MCI) GPM subtype not match 0x%x\n", *(p_gpm + 1)); 706250003Sadrian mismatch++; 707250003Sadrian ar9300_mci_process_gpm_extra(ah, recv_type, recv_opcode, p_gpm); 708250003Sadrian } 709250003Sadrian } 710250003Sadrian } 711250003Sadrian if (p_gpm != NULL) { 712250003Sadrian MCI_GPM_RECYCLE(p_gpm); 713250003Sadrian p_gpm = NULL; 714250003Sadrian } 715250003Sadrian 716250003Sadrian if (time_out <= 0) { 717250003Sadrian time_out = 0; 718250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, 719250003Sadrian "(MCI) GPM receiving timeout, mismatch = %d\n", mismatch); 720250003Sadrian } else { 721250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, 722250003Sadrian "(MCI) Receive GPM type=0x%x, code=0x%x\n", gpm_type, gpm_opcode); 723250003Sadrian } 724250003Sadrian 725250003Sadrian while (more_data == HAL_MCI_GPM_MORE) { 726250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) discard remaining GPM\n"); 727250003Sadrian offset = ar9300_mci_state(ah, 728250003Sadrian HAL_MCI_STATE_NEXT_GPM_OFFSET, &more_data); 729250003Sadrian 730250003Sadrian if (offset == HAL_MCI_GPM_INVALID) { 731250003Sadrian break; 732250003Sadrian } 733250003Sadrian p_gpm = (u_int32_t *) (ahp->ah_mci_gpm_buf + offset); 734250003Sadrian ar9300_mci_print_msg(ah, AH_FALSE, MCI_GPM, 16, p_gpm); 735250003Sadrian recv_type = MCI_GPM_TYPE(p_gpm); 736250003Sadrian recv_opcode = MCI_GPM_OPCODE(p_gpm); 737250003Sadrian if (!MCI_GPM_IS_CAL_TYPE(recv_type)) { 738250003Sadrian ar9300_mci_process_gpm_extra(ah, recv_type, recv_opcode, p_gpm); 739250003Sadrian } 740250003Sadrian MCI_GPM_RECYCLE(p_gpm); 741250003Sadrian } 742250003Sadrian 743250003Sadrian return time_out; 744250003Sadrian} 745250003Sadrian 746250003Sadrianstatic void ar9300_mci_prep_interface(struct ath_hal *ah) 747250003Sadrian{ 748250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 749250003Sadrian u_int32_t saved_mci_int_en; 750250003Sadrian u_int32_t mci_timeout = 150; 751250003Sadrian 752250003Sadrian ahp->ah_mci_bt_state = MCI_BT_SLEEP; 753250003Sadrian 754250003Sadrian saved_mci_int_en = OS_REG_READ(ah, AR_MCI_INTERRUPT_EN); 755250003Sadrian OS_REG_WRITE(ah, AR_MCI_INTERRUPT_EN, 0); 756250003Sadrian 757250003Sadrian OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, 758250003Sadrian OS_REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_RAW)); 759250003Sadrian OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, 760250003Sadrian OS_REG_READ(ah, AR_MCI_INTERRUPT_RAW)); 761250003Sadrian 762250003Sadrian /* Remote Reset */ 763250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) %s: Reset sequence start\n", __func__); 764250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) send REMOTE_RESET\n"); 765250003Sadrian ar9300_mci_remote_reset(ah, AH_TRUE); 766250003Sadrian 767250003Sadrian /* 768250003Sadrian * This delay is required for the reset delay worst case value 255 in 769250003Sadrian * MCI_COMMAND2 register 770250003Sadrian */ 771250003Sadrian if (AR_SREV_JUPITER_10(ah)) { 772250003Sadrian OS_DELAY(252); 773250003Sadrian } 774250003Sadrian 775250003Sadrian /* Send REQ_WAKE to BT */ 776250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) %s: Send REQ_WAKE to remote(BT)\n", 777250003Sadrian __func__); 778250003Sadrian 779250003Sadrian ar9300_mci_send_req_wake(ah, AH_TRUE); 780250003Sadrian 781250003Sadrian if (ar9300_mci_wait_for_interrupt(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, 782250003Sadrian AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING, 500)) 783250003Sadrian { 784250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, 785250003Sadrian "(MCI) %s: Saw SYS_WAKING from remote(BT)\n", __func__); 786250003Sadrian ahp->ah_mci_bt_state = MCI_BT_AWAKE; 787250003Sadrian 788250003Sadrian if (AR_SREV_JUPITER_10(ah)) { 789250003Sadrian OS_DELAY(10); 790250003Sadrian } 791250003Sadrian /* 792250003Sadrian * We don't need to send more remote_reset at this moment. 793250003Sadrian * 794250003Sadrian * If BT receive first remote_reset, then BT HW will be cleaned up and 795250003Sadrian * will be able to receive req_wake and BT HW will respond sys_waking. 796250003Sadrian * In this case, WLAN will receive BT's HW sys_waking. 797250003Sadrian * 798250003Sadrian * Otherwise, if BT SW missed initial remote_reset, that remote_reset 799250003Sadrian * will still clean up BT MCI RX, and the req_wake will wake BT up, 800250003Sadrian * and BT SW will respond this req_wake with a remote_reset and 801250003Sadrian * sys_waking. In this case, WLAN will receive BT's SW sys_waking. 802250003Sadrian * 803250003Sadrian * In either case, BT's RX is cleaned up. So we don't need to reply 804250003Sadrian * BT's remote_reset now, if any. 805250003Sadrian * 806250003Sadrian * Similarly, if in any case, WLAN can receive BT's sys_waking, that 807250003Sadrian * means WLAN's RX is also fine. 808250003Sadrian */ 809250003Sadrian 810250003Sadrian /* Send SYS_WAKING to BT */ 811250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, 812250003Sadrian "(MCI) %s: Send SW SYS_WAKING to remot(BT)\n", __func__); 813250003Sadrian ar9300_mci_send_sys_waking(ah, AH_TRUE); 814250003Sadrian 815250003Sadrian OS_DELAY(10); 816250003Sadrian 817250003Sadrian /* 818250003Sadrian * Set BT priority interrupt value to be 0xff to 819250003Sadrian * avoid having too many BT PRIORITY interrupts. 820250003Sadrian */ 821250003Sadrian 822250003Sadrian OS_REG_WRITE(ah, AR_MCI_BT_PRI0, 0xFFFFFFFF); 823250003Sadrian OS_REG_WRITE(ah, AR_MCI_BT_PRI1, 0xFFFFFFFF); 824250003Sadrian OS_REG_WRITE(ah, AR_MCI_BT_PRI2, 0xFFFFFFFF); 825250003Sadrian OS_REG_WRITE(ah, AR_MCI_BT_PRI3, 0xFFFFFFFF); 826250003Sadrian OS_REG_WRITE(ah, AR_MCI_BT_PRI, 0X000000FF); 827250003Sadrian 828250003Sadrian /* 829250003Sadrian * A contention reset will be received after send out sys_waking. 830250003Sadrian * Also BT priority interrupt bits will be set. Clear those bits 831250003Sadrian * before the next step. 832250003Sadrian */ 833250003Sadrian OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, 834250003Sadrian AR_MCI_INTERRUPT_RX_MSG_CONT_RST); 835250003Sadrian OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, AR_MCI_INTERRUPT_BT_PRI); 836250003Sadrian 837250003Sadrian if (AR_SREV_JUPITER_10(ah) || ahp->ah_mci_coex_is_2g) { 838250003Sadrian /* Send LNA_TRANS */ 839250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) %s: Send LNA_TRANS to BT\n", 840250003Sadrian __func__); 841250003Sadrian ar9300_mci_send_lna_transfer(ah, AH_TRUE); 842250003Sadrian 843250003Sadrian OS_DELAY(5); 844250003Sadrian } 845250003Sadrian 846250003Sadrian if (AR_SREV_JUPITER_10(ah) || 847250003Sadrian (ahp->ah_mci_coex_is_2g && !ahp->ah_mci_coex_2g5g_update)) 848250003Sadrian { 849250003Sadrian if (ar9300_mci_wait_for_interrupt(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, 850250003Sadrian AR_MCI_INTERRUPT_RX_MSG_LNA_INFO, mci_timeout)) { 851250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, 852250003Sadrian "(MCI) %s: WLAN has control over the LNA & BT obeys it\n", 853250003Sadrian __func__); 854250003Sadrian } else { 855250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, 856250003Sadrian "(MCI) %s: BT did not respond to LNA_TRANS!\n", __func__); 857250003Sadrian //ahp->ah_mci_bt_state = MCI_BT_SLEEP; 858250003Sadrian } 859250003Sadrian } 860250003Sadrian 861250003Sadrian if (AR_SREV_JUPITER_10(ah)) { 862250003Sadrian /* Send another remote_reset to deassert BT clk_req. */ 863250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, 864250003Sadrian "(MCI) %s: Another remote_reset to deassert clk_req.\n", 865250003Sadrian __func__); 866250003Sadrian ar9300_mci_remote_reset(ah, AH_TRUE); 867250003Sadrian OS_DELAY(252); 868250003Sadrian } 869250003Sadrian } 870250003Sadrian 871250003Sadrian /* Clear the extra redundant SYS_WAKING from BT */ 872250003Sadrian if ((ahp->ah_mci_bt_state == MCI_BT_AWAKE) && 873250003Sadrian (OS_REG_READ_FIELD(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, 874250003Sadrian AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING)) && 875250003Sadrian (OS_REG_READ_FIELD(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, 876250003Sadrian AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING) == 0)) 877250003Sadrian { 878250003Sadrian OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, 879250003Sadrian AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING); 880250003Sadrian OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, 881250003Sadrian AR_MCI_INTERRUPT_REMOTE_SLEEP_UPDATE); 882250003Sadrian } 883250003Sadrian 884250003Sadrian OS_REG_WRITE(ah, AR_MCI_INTERRUPT_EN, saved_mci_int_en); 885250003Sadrian} 886250003Sadrian 887250003Sadrianvoid ar9300_mci_setup(struct ath_hal *ah, u_int32_t gpm_addr, 888250003Sadrian void *gpm_buf, u_int16_t len, 889250003Sadrian u_int32_t sched_addr) 890250003Sadrian{ 891250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 892250003Sadrian void *sched_buf = (void *)((char *) gpm_buf + (sched_addr - gpm_addr)); 893250003Sadrian 894250003Sadrian ahp->ah_mci_gpm_addr = gpm_addr; 895250003Sadrian ahp->ah_mci_gpm_buf = gpm_buf; 896250003Sadrian ahp->ah_mci_gpm_len = len; 897250003Sadrian ahp->ah_mci_sched_addr = sched_addr; 898250003Sadrian ahp->ah_mci_sched_buf = sched_buf; 899250003Sadrian 900250003Sadrian ar9300_mci_reset(ah, AH_TRUE, AH_TRUE, AH_TRUE); 901250003Sadrian} 902250003Sadrian 903250003Sadrianvoid ar9300_mci_disable_interrupt(struct ath_hal *ah) 904250003Sadrian{ 905250003Sadrian OS_REG_WRITE(ah, AR_MCI_INTERRUPT_EN, 0); 906250003Sadrian OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_EN, 0); 907250003Sadrian} 908250003Sadrian 909250003Sadrianvoid ar9300_mci_enable_interrupt(struct ath_hal *ah) 910250003Sadrian{ 911250003Sadrian OS_REG_WRITE(ah, AR_MCI_INTERRUPT_EN, AR_MCI_INTERRUPT_DEFAULT); 912250003Sadrian OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_EN, 913250003Sadrian AR_MCI_INTERRUPT_RX_MSG_DEFAULT); 914250003Sadrian} 915250003Sadrian 916250003Sadrianvoid ar9300_mci_reset(struct ath_hal *ah, HAL_BOOL en_int, HAL_BOOL is_2g, 917250003Sadrian HAL_BOOL is_full_sleep) 918250003Sadrian{ 919250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 920250008Sadrian// struct ath_hal_private *ahpriv = AH_PRIVATE(ah); 921250003Sadrian u_int32_t regval; 922250003Sadrian 923250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) %s: full_sleep = %d, is_2g = %d\n", 924250003Sadrian __func__, is_full_sleep, is_2g); 925250003Sadrian 926250003Sadrian if (!ahp->ah_mci_gpm_addr && !ahp->ah_mci_sched_addr) { 927250003Sadrian /* GPM buffer and scheduling message buffer are not allocated */ 928250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, 929250003Sadrian "(MCI) GPM and SCHEDULE buffers not allocated\n"); 930250003Sadrian return; 931250003Sadrian } 932250003Sadrian 933250003Sadrian if (OS_REG_READ(ah, AR_BTCOEX_CTRL) == 0xdeadbeef) { 934250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, 935250003Sadrian "(MCI) %s: ### It's deadbeef, quit mcireset()\n", __func__); 936250003Sadrian return; 937250003Sadrian } 938250003Sadrian 939250003Sadrian /* Program MCI DMA related registers */ 940250003Sadrian OS_REG_WRITE(ah, AR_MCI_GPM_0, ahp->ah_mci_gpm_addr); 941250003Sadrian OS_REG_WRITE(ah, AR_MCI_GPM_1, ahp->ah_mci_gpm_len); 942250003Sadrian OS_REG_WRITE(ah, AR_MCI_SCHD_TABLE_0, ahp->ah_mci_sched_addr); 943250003Sadrian 944250003Sadrian /* 945250003Sadrian * To avoid MCI state machine be affected by incoming remote MCI messages, 946250003Sadrian * MCI mode will be enabled later, right before reset the MCI TX and RX. 947250003Sadrian */ 948250003Sadrian regval = SM(1, AR_BTCOEX_CTRL_JUPITER_MODE) | 949250003Sadrian SM(1, AR_BTCOEX_CTRL_WBTIMER_EN) | 950250003Sadrian SM(1, AR_BTCOEX_CTRL_PA_SHARED) | 951250003Sadrian SM(1, AR_BTCOEX_CTRL_LNA_SHARED) | 952250003Sadrian SM(2, AR_BTCOEX_CTRL_NUM_ANTENNAS) | 953250003Sadrian SM(3, AR_BTCOEX_CTRL_RX_CHAIN_MASK) | 954250003Sadrian SM(0, AR_BTCOEX_CTRL_1_CHAIN_ACK) | 955250003Sadrian SM(0, AR_BTCOEX_CTRL_1_CHAIN_BCN) | 956250003Sadrian SM(0, AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN); 957250003Sadrian 958250003Sadrian if (AR_SREV_JUPITER_10(ah)) { 959250003Sadrian regval |= SM(1, AR_BTCOEX_CTRL_SPDT_ENABLE_10); 960250003Sadrian } 961250003Sadrian 962250003Sadrian OS_REG_WRITE(ah, AR_BTCOEX_CTRL, regval); 963250003Sadrian 964250003Sadrian if (is_2g && (AR_SREV_JUPITER_20(ah) || AR_SREV_APHRODITE(ah)) && 965250008Sadrian !(ah->ah_config.ath_hal_mci_config & 966250003Sadrian ATH_MCI_CONFIG_DISABLE_OSLA)) 967250003Sadrian { 968250003Sadrian ar9300_mci_osla_setup(ah, AH_TRUE); 969250003Sadrian } 970250003Sadrian else { 971250003Sadrian ar9300_mci_osla_setup(ah, AH_FALSE); 972250003Sadrian } 973250003Sadrian 974250003Sadrian if (AR_SREV_JUPITER_20(ah) || AR_SREV_APHRODITE(ah)) { 975250003Sadrian OS_REG_SET_BIT(ah, AR_GLB_CONTROL, AR_BTCOEX_CTRL_SPDT_ENABLE); 976250003Sadrian 977250003Sadrian OS_REG_RMW_FIELD(ah, AR_BTCOEX_CTRL3, 978250003Sadrian AR_BTCOEX_CTRL3_CONT_INFO_TIMEOUT, 20); 979250003Sadrian } 980250003Sadrian 981250003Sadrian OS_REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2, AR_BTCOEX_CTRL2_RX_DEWEIGHT, 0); 982250003Sadrian 983250003Sadrian OS_REG_RMW_FIELD(ah, AR_PCU_MISC, AR_PCU_BT_ANT_PREVENT_RX, 0); 984250003Sadrian 985250008Sadrian if (ah->ah_config.ath_hal_mci_config & ATH_MCI_CONFIG_CONCUR_TX) { 986250003Sadrian u_int8_t i; 987250003Sadrian u_int32_t const *pmax_tx_pwr; 988250003Sadrian 989250008Sadrian if ((ah->ah_config.ath_hal_mci_config & 990250003Sadrian ATH_MCI_CONFIG_CONCUR_TX) == ATH_MCI_CONCUR_TX_SHARED_CHN) 991250003Sadrian { 992250003Sadrian ahp->ah_mci_concur_tx_en = (ahp->ah_bt_coex_flag & 993250003Sadrian HAL_BT_COEX_FLAG_MCI_MAX_TX_PWR) ? AH_TRUE : AH_FALSE; 994250003Sadrian 995250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) concur_tx_en = %d\n", 996250003Sadrian ahp->ah_mci_concur_tx_en); 997250003Sadrian /* 998250003Sadrian * We're not relying on HW to reduce WLAN tx power. 999250003Sadrian * Set the max tx power table to 0x7f for all. 1000250003Sadrian */ 1001250003Sadrian#if 0 1002250003Sadrian if (AH_PRIVATE(ah)->ah_curchan) { 1003250003Sadrian chan_flags = AH_PRIVATE(ah)->ah_curchan->channel_flags; 1004250003Sadrian } 1005250003Sadrian if (chan_flags == CHANNEL_G_HT20) { 1006250003Sadrian pmax_tx_pwr = &mci_concur_tx_max_pwr[2][0]; 1007250003Sadrian } 1008250003Sadrian else if (chan_flags == CHANNEL_G) { 1009250003Sadrian pmax_tx_pwr = &mci_concur_tx_max_pwr[1][0]; 1010250003Sadrian } 1011250003Sadrian else if ((chan_flags == CHANNEL_G_HT40PLUS) || 1012250003Sadrian (chan_flags == CHANNEL_G_HT40MINUS)) 1013250003Sadrian { 1014250003Sadrian pmax_tx_pwr = &mci_concur_tx_max_pwr[3][0]; 1015250003Sadrian } 1016250003Sadrian else { 1017250003Sadrian pmax_tx_pwr = &mci_concur_tx_max_pwr[0][0]; 1018250003Sadrian } 1019250003Sadrian 1020250003Sadrian if (ahp->ah_mci_concur_tx_en) { 1021250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, 1022250003Sadrian "(MCI) chan flags = 0x%x, max_tx_pwr = %d dBm\n", 1023250003Sadrian chan_flags, 1024250003Sadrian (MS(pmax_tx_pwr[2], 1025250003Sadrian ATH_MCI_CONCUR_TX_LOWEST_PWR_MASK) >> 1)); 1026250003Sadrian } 1027250003Sadrian#else 1028250003Sadrian pmax_tx_pwr = &mci_concur_tx_max_pwr[0][0]; 1029250003Sadrian#endif 1030250003Sadrian } 1031250008Sadrian else if ((ah->ah_config.ath_hal_mci_config & 1032250003Sadrian ATH_MCI_CONFIG_CONCUR_TX) == ATH_MCI_CONCUR_TX_UNSHARED_CHN) 1033250003Sadrian { 1034250003Sadrian pmax_tx_pwr = &mci_concur_tx_max_pwr[0][0]; 1035250003Sadrian ahp->ah_mci_concur_tx_en = AH_TRUE; 1036250003Sadrian } 1037250003Sadrian else { 1038250003Sadrian pmax_tx_pwr = &mci_concur_tx_max_pwr[0][0]; 1039250003Sadrian ahp->ah_mci_concur_tx_en = AH_TRUE; 1040250003Sadrian } 1041250003Sadrian 1042250003Sadrian /* Default is using rate based TPC. */ 1043250003Sadrian OS_REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2, 1044250003Sadrian AR_BTCOEX_CTRL2_DESC_BASED_TXPWR_ENABLE, 0); 1045250003Sadrian OS_REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2, 1046250003Sadrian AR_BTCOEX_CTRL2_TXPWR_THRESH, 0x7f); 1047250003Sadrian OS_REG_RMW_FIELD(ah, AR_BTCOEX_CTRL, 1048250003Sadrian AR_BTCOEX_CTRL_REDUCE_TXPWR, 0); 1049250003Sadrian for (i = 0; i < 8; i++) { 1050250003Sadrian OS_REG_WRITE(ah, AR_BTCOEX_MAX_TXPWR(i), pmax_tx_pwr[i]); 1051250003Sadrian } 1052250003Sadrian } 1053250003Sadrian 1054250008Sadrian regval = MS(ah->ah_config.ath_hal_mci_config, 1055250003Sadrian ATH_MCI_CONFIG_CLK_DIV); 1056250003Sadrian OS_REG_RMW_FIELD(ah, AR_MCI_TX_CTRL, AR_MCI_TX_CTRL_CLK_DIV, regval); 1057250003Sadrian 1058250003Sadrian OS_REG_SET_BIT(ah, AR_BTCOEX_CTRL, AR_BTCOEX_CTRL_MCI_MODE_EN); 1059250003Sadrian 1060250003Sadrian /* Resetting the Rx and Tx paths of MCI */ 1061250003Sadrian regval = OS_REG_READ(ah, AR_MCI_COMMAND2); 1062250003Sadrian regval |= SM(1, AR_MCI_COMMAND2_RESET_TX); 1063250003Sadrian OS_REG_WRITE(ah, AR_MCI_COMMAND2, regval); 1064250003Sadrian OS_DELAY(1); 1065250003Sadrian regval &= ~SM(1, AR_MCI_COMMAND2_RESET_TX); 1066250003Sadrian OS_REG_WRITE(ah, AR_MCI_COMMAND2, regval); 1067250003Sadrian 1068250003Sadrian if (is_full_sleep) { 1069250003Sadrian ar9300_mci_mute_bt(ah); 1070250003Sadrian OS_DELAY(100); 1071250003Sadrian } 1072250003Sadrian 1073250003Sadrian regval |= SM(1, AR_MCI_COMMAND2_RESET_RX); 1074250003Sadrian OS_REG_WRITE(ah, AR_MCI_COMMAND2, regval); 1075250003Sadrian OS_DELAY(1); 1076250003Sadrian regval &= ~SM(1, AR_MCI_COMMAND2_RESET_RX); 1077250003Sadrian OS_REG_WRITE(ah, AR_MCI_COMMAND2, regval); 1078250003Sadrian 1079250003Sadrian ar9300_mci_state(ah, HAL_MCI_STATE_INIT_GPM_OFFSET, NULL); 1080250003Sadrian OS_REG_WRITE(ah, AR_MCI_MSG_ATTRIBUTES_TABLE, 1081250003Sadrian (SM(0xe801, AR_MCI_MSG_ATTRIBUTES_TABLE_INVALID_HDR) | 1082250003Sadrian SM(0x0000, AR_MCI_MSG_ATTRIBUTES_TABLE_CHECKSUM))); 1083250003Sadrian OS_REG_CLR_BIT(ah, AR_MCI_TX_CTRL, AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE); 1084250003Sadrian 1085250003Sadrian if (AR_SREV_JUPITER_20_OR_LATER(ah) || AR_SREV_APHRODITE(ah)) { 1086250003Sadrian ar9300_mci_observation_set_up(ah); 1087250003Sadrian } 1088250003Sadrian 1089250003Sadrian ahp->ah_mci_ready = AH_TRUE; 1090250003Sadrian ar9300_mci_prep_interface(ah); 1091250003Sadrian 1092250003Sadrian if (en_int) { 1093250003Sadrian ar9300_mci_enable_interrupt(ah); 1094250003Sadrian } 1095250003Sadrian 1096250003Sadrian#if ATH_SUPPORT_AIC 1097250003Sadrian if (ahp->ah_aic_enabled) { 1098250003Sadrian ar9300_aic_start_normal(ah); 1099250003Sadrian } 1100250003Sadrian#endif 1101250003Sadrian} 1102250003Sadrian 1103250003Sadrianstatic void ar9300_mci_queue_unsent_gpm(struct ath_hal *ah, u_int8_t header, 1104250003Sadrian u_int32_t *payload, HAL_BOOL queue) 1105250003Sadrian{ 1106250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 1107250003Sadrian u_int8_t type, opcode; 1108250003Sadrian 1109250003Sadrian if (queue == AH_TRUE) { 1110250003Sadrian if (payload != NULL) { 1111250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, 1112250003Sadrian "(MCI) ERROR: Send fail: %02x: %02x %02x %02x\n", 1113250003Sadrian header, 1114250003Sadrian *(((u_int8_t *)payload) + 4), 1115250003Sadrian *(((u_int8_t *)payload) + 5), 1116250003Sadrian *(((u_int8_t *)payload) + 6)); 1117250003Sadrian } else { 1118250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, 1119250003Sadrian "(MCI) ERROR: Send fail: %02x\n", header); 1120250003Sadrian } 1121250003Sadrian } 1122250003Sadrian /* check if the message is to be queued */ 1123250003Sadrian if (header == MCI_GPM) { 1124250003Sadrian type = MCI_GPM_TYPE(payload); 1125250003Sadrian opcode = MCI_GPM_OPCODE(payload); 1126250003Sadrian 1127250003Sadrian if (type == MCI_GPM_COEX_AGENT) { 1128250003Sadrian switch (opcode) 1129250003Sadrian { 1130250003Sadrian case MCI_GPM_COEX_BT_UPDATE_FLAGS: 1131250003Sadrian if (AR_SREV_JUPITER_10(ah)) { 1132250003Sadrian break; 1133250003Sadrian } 1134250003Sadrian if (*(((u_int8_t *)payload) + MCI_GPM_COEX_B_BT_FLAGS_OP) == 1135250003Sadrian MCI_GPM_COEX_BT_FLAGS_READ) 1136250003Sadrian { 1137250003Sadrian break; 1138250003Sadrian } 1139250003Sadrian ahp->ah_mci_coex_2g5g_update = queue; 1140250003Sadrian if (queue == AH_TRUE) { 1141250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, 1142250003Sadrian "(MCI) BT_MCI_FLAGS: 2G5G status <queued> %s.\n", 1143250003Sadrian ahp->ah_mci_coex_is_2g?"2G":"5G"); 1144250003Sadrian } 1145250003Sadrian else { 1146250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, 1147250003Sadrian "(MCI) BT_MCI_FLAGS: 2G5G status <sent> %s.\n", 1148250003Sadrian ahp->ah_mci_coex_is_2g?"2G":"5G"); 1149250003Sadrian } 1150250003Sadrian break; 1151250003Sadrian 1152250003Sadrian case MCI_GPM_COEX_WLAN_CHANNELS: 1153250003Sadrian ahp->ah_mci_coex_wlan_channels_update = queue; 1154250003Sadrian if (queue == AH_TRUE) { 1155250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, 1156250003Sadrian "(MCI) WLAN channel map <queued>.\n"); 1157250003Sadrian } 1158250003Sadrian else { 1159250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, 1160250003Sadrian "(MCI) WLAN channel map <sent>.\n"); 1161250003Sadrian } 1162250003Sadrian break; 1163250003Sadrian 1164250003Sadrian case MCI_GPM_COEX_HALT_BT_GPM: 1165250003Sadrian if (*(((u_int8_t *)payload) + MCI_GPM_COEX_B_HALT_STATE) == 1166250003Sadrian MCI_GPM_COEX_BT_GPM_UNHALT) 1167250003Sadrian { 1168250003Sadrian ahp->ah_mci_unhalt_bt_gpm = queue; 1169250003Sadrian if (queue == AH_TRUE) { 1170250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, 1171250003Sadrian "(MCI) UNHALT BT GPM <queued>.\n"); 1172250003Sadrian } 1173250003Sadrian else { 1174250003Sadrian ahp->ah_mci_halted_bt_gpm = AH_FALSE; 1175250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, 1176250003Sadrian "(MCI) UNHALT BT GPM <sent>.\n"); 1177250003Sadrian } 1178250003Sadrian } 1179250003Sadrian if (*(((u_int8_t *)payload) + MCI_GPM_COEX_B_HALT_STATE) == 1180250003Sadrian MCI_GPM_COEX_BT_GPM_HALT) 1181250003Sadrian { 1182250003Sadrian ahp->ah_mci_halted_bt_gpm = !queue; 1183250003Sadrian if (queue == AH_TRUE) { 1184250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, 1185250003Sadrian "(MCI) HALT BT GPM <not sent>.\n"); 1186250003Sadrian } 1187250003Sadrian else { 1188250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, 1189250003Sadrian "(MCI) HALT BT GPM <sent>.\n"); 1190250003Sadrian } 1191250003Sadrian } 1192250003Sadrian break; 1193250003Sadrian 1194250003Sadrian default: 1195250003Sadrian break; 1196250003Sadrian } 1197250003Sadrian } 1198250003Sadrian } 1199250003Sadrian} 1200250003Sadrian 1201250003SadrianHAL_BOOL ar9300_mci_send_message(struct ath_hal *ah, u_int8_t header, 1202250003Sadrian u_int32_t flag, u_int32_t *payload, 1203250003Sadrian u_int8_t len, HAL_BOOL wait_done, HAL_BOOL check_bt) 1204250003Sadrian{ 1205250003Sadrian int i; 1206250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 1207250003Sadrian HAL_BOOL msg_sent = AH_FALSE; 1208250003Sadrian u_int32_t regval; 1209250003Sadrian u_int32_t saved_mci_int_en = OS_REG_READ(ah, AR_MCI_INTERRUPT_EN); 1210250003Sadrian 1211250003Sadrian regval = OS_REG_READ(ah, AR_BTCOEX_CTRL); 1212250003Sadrian if ((regval == 0xdeadbeef) || !(regval & AR_BTCOEX_CTRL_MCI_MODE_EN)) { 1213250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, 1214250003Sadrian "(MCI) %s: Not send 0x%x. MCI is not enabled. full_sleep = %d\n", 1215250003Sadrian __func__, header, ahp->ah_chip_full_sleep); 1216250003Sadrian ar9300_mci_queue_unsent_gpm(ah, header, payload, AH_TRUE); 1217250003Sadrian return AH_FALSE; 1218250003Sadrian } 1219250003Sadrian else if (check_bt && (ahp->ah_mci_bt_state == MCI_BT_SLEEP)) { 1220250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, 1221250003Sadrian "(MCI) %s: Don't send message(0x%x). BT is in sleep state\n", 1222250003Sadrian __func__, header); 1223250003Sadrian ar9300_mci_queue_unsent_gpm(ah, header, payload, AH_TRUE); 1224250003Sadrian return AH_FALSE; 1225250003Sadrian } 1226250003Sadrian 1227250003Sadrian if (wait_done) { 1228250003Sadrian OS_REG_WRITE(ah, AR_MCI_INTERRUPT_EN, 0); 1229250003Sadrian } 1230250003Sadrian 1231250003Sadrian /* Need to clear SW_MSG_DONE raw bit before wait */ 1232250003Sadrian OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, 1233250003Sadrian AR_MCI_INTERRUPT_SW_MSG_DONE | AR_MCI_INTERRUPT_MSG_FAIL_MASK); 1234250003Sadrian 1235250003Sadrian if (payload != AH_NULL) { 1236250003Sadrian for (i = 0; (i*4) < len; i++) { 1237250003Sadrian OS_REG_WRITE(ah, (AR_MCI_TX_PAYLOAD0 + i*4), *(payload + i)); 1238250003Sadrian } 1239250003Sadrian } 1240250003Sadrian ar9300_mci_print_msg(ah, AH_TRUE, header, len, payload); 1241250003Sadrian 1242250003Sadrian OS_REG_WRITE(ah, AR_MCI_COMMAND0, 1243250003Sadrian (SM((flag & HAL_MCI_FLAG_DISABLE_TIMESTAMP), 1244250003Sadrian AR_MCI_COMMAND0_DISABLE_TIMESTAMP) | 1245250003Sadrian SM(len, AR_MCI_COMMAND0_LEN) | 1246250003Sadrian SM(header, AR_MCI_COMMAND0_HEADER))); 1247250003Sadrian 1248250003Sadrian if (wait_done && 1249250003Sadrian ar9300_mci_wait_for_interrupt(ah, AR_MCI_INTERRUPT_RAW, 1250250003Sadrian AR_MCI_INTERRUPT_SW_MSG_DONE, 500) == 0) 1251250003Sadrian { 1252250003Sadrian ar9300_mci_queue_unsent_gpm(ah, header, payload, AH_TRUE); 1253250003Sadrian } 1254250003Sadrian else { 1255250003Sadrian ar9300_mci_queue_unsent_gpm(ah, header, payload, AH_FALSE); 1256250003Sadrian msg_sent = AH_TRUE; 1257250003Sadrian } 1258250003Sadrian 1259250003Sadrian if (wait_done) { 1260250003Sadrian OS_REG_WRITE(ah, AR_MCI_INTERRUPT_EN, saved_mci_int_en); 1261250003Sadrian } 1262250003Sadrian 1263250003Sadrian return msg_sent; 1264250003Sadrian} 1265250003Sadrian 1266250003Sadrianu_int32_t ar9300_mci_get_interrupt(struct ath_hal *ah, u_int32_t *mci_int, 1267250003Sadrian u_int32_t *mci_int_rx_msg) 1268250003Sadrian{ 1269250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 1270250003Sadrian 1271250003Sadrian *mci_int = ahp->ah_mci_int_raw; 1272250003Sadrian *mci_int_rx_msg = ahp->ah_mci_int_rx_msg; 1273250003Sadrian 1274250003Sadrian /* Clean int bits after the values are read. */ 1275250003Sadrian ahp->ah_mci_int_raw = 0; 1276250003Sadrian ahp->ah_mci_int_rx_msg = 0; 1277250003Sadrian 1278250003Sadrian return 0; 1279250003Sadrian} 1280250003Sadrian 1281250003Sadrianu_int32_t ar9300_mci_check_int(struct ath_hal *ah, u_int32_t ints) 1282250003Sadrian{ 1283250003Sadrian u_int32_t reg; 1284250003Sadrian 1285250003Sadrian reg = OS_REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_RAW); 1286250003Sadrian return ((reg & ints) == ints); 1287250003Sadrian} 1288250003Sadrian 1289250003Sadrianvoid ar9300_mci_sync_bt_state(struct ath_hal *ah) 1290250003Sadrian{ 1291250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 1292250003Sadrian u_int32_t cur_bt_state; 1293250003Sadrian 1294250003Sadrian cur_bt_state = ar9300_mci_state(ah, HAL_MCI_STATE_REMOTE_SLEEP, NULL); 1295250003Sadrian if (ahp->ah_mci_bt_state != cur_bt_state) { 1296250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, 1297250003Sadrian "(MCI) %s: BT state mismatches. old: %d, new: %d\n", 1298250003Sadrian __func__, ahp->ah_mci_bt_state, cur_bt_state); 1299250003Sadrian ahp->ah_mci_bt_state = cur_bt_state; 1300250003Sadrian } 1301250003Sadrian if (ahp->ah_mci_bt_state != MCI_BT_SLEEP) { 1302250003Sadrian#if MCI_QUERY_BT_VERSION_VERBOSE 1303250003Sadrian ar9300_mci_send_coex_version_query(ah, AH_TRUE); 1304250003Sadrian#endif 1305250003Sadrian ar9300_mci_send_coex_wlan_channels(ah, AH_TRUE); 1306250003Sadrian if (ahp->ah_mci_unhalt_bt_gpm == AH_TRUE) { 1307250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) %s: UNHALT BT GPM\n", __func__); 1308250003Sadrian ar9300_mci_send_coex_halt_bt_gpm(ah, AH_FALSE, AH_TRUE); 1309250003Sadrian } 1310250003Sadrian } 1311250003Sadrian} 1312250003Sadrian 1313250003Sadrianstatic HAL_BOOL ar9300_mci_is_gpm_valid(struct ath_hal *ah, u_int32_t msg_index) 1314250003Sadrian{ 1315250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 1316250003Sadrian u_int32_t *payload; 1317250003Sadrian u_int32_t recv_type, offset = msg_index << 4; 1318250003Sadrian 1319250003Sadrian if (msg_index == HAL_MCI_GPM_INVALID) { 1320250003Sadrian return AH_FALSE; 1321250003Sadrian } 1322250003Sadrian 1323250003Sadrian payload = (u_int32_t *) (ahp->ah_mci_gpm_buf + offset); 1324250003Sadrian recv_type = MCI_GPM_TYPE(payload); 1325250003Sadrian 1326250003Sadrian if (recv_type == MCI_GPM_RSVD_PATTERN) { 1327250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) Skip RSVD GPM\n"); 1328250003Sadrian return AH_FALSE; 1329250003Sadrian } 1330250003Sadrian 1331250003Sadrian return AH_TRUE; 1332250003Sadrian} 1333250003Sadrian 1334250003Sadrianu_int32_t 1335250003Sadrianar9300_mci_state(struct ath_hal *ah, u_int32_t state_type, u_int32_t *p_data) 1336250003Sadrian{ 1337250003Sadrian u_int32_t value = 0, more_gpm = 0, gpm_ptr; 1338250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 1339250003Sadrian 1340250003Sadrian switch (state_type) { 1341250003Sadrian case HAL_MCI_STATE_ENABLE: 1342250008Sadrian if (AH_PRIVATE(ah)->ah_caps.halMciSupport && ahp->ah_mci_ready) { 1343250003Sadrian value = OS_REG_READ(ah, AR_BTCOEX_CTRL); 1344250003Sadrian if ((value == 0xdeadbeef) || (value == 0xffffffff)) { 1345250003Sadrian // HALDEBUG(ah, HAL_DEBUG_BT_COEX, 1346250003Sadrian // "(MCI) BTCOEX_CTRL = 0xdeadbeef\n"); 1347250003Sadrian value = 0; 1348250003Sadrian } 1349250003Sadrian } 1350250003Sadrian value &= AR_BTCOEX_CTRL_MCI_MODE_EN; 1351250003Sadrian break; 1352250003Sadrian 1353250003Sadrian case HAL_MCI_STATE_INIT_GPM_OFFSET: 1354250003Sadrian value = MS(OS_REG_READ(ah, AR_MCI_GPM_1), AR_MCI_GPM_WRITE_PTR); 1355250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, 1356250003Sadrian "(MCI) %s: GPM initial WRITE_PTR=%d.\n", __func__, value); 1357250003Sadrian ahp->ah_mci_gpm_idx = value; 1358250003Sadrian break; 1359250003Sadrian 1360250003Sadrian case HAL_MCI_STATE_NEXT_GPM_OFFSET: 1361250003Sadrian case HAL_MCI_STATE_LAST_GPM_OFFSET: 1362250003Sadrian /* 1363250003Sadrian * This could be useful to avoid new GPM message interrupt which 1364250003Sadrian * may lead to spurious interrupt after power sleep, or multiple 1365250003Sadrian * entry of ath_coex_mci_intr(). 1366250003Sadrian * Adding empty GPM check by returning HAL_MCI_GPM_INVALID can 1367250003Sadrian * alleviate this effect, but clearing GPM RX interrupt bit is 1368250003Sadrian * safe, because whether this is called from HAL or LMAC, there 1369250003Sadrian * must be an interrupt bit set/triggered initially. 1370250003Sadrian */ 1371250003Sadrian OS_REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, 1372250003Sadrian AR_MCI_INTERRUPT_RX_MSG_GPM); 1373250003Sadrian 1374250003Sadrian gpm_ptr = MS(OS_REG_READ(ah, AR_MCI_GPM_1), AR_MCI_GPM_WRITE_PTR); 1375250003Sadrian value = gpm_ptr; 1376250003Sadrian 1377250003Sadrian if (value == 0) { 1378250003Sadrian value = ahp->ah_mci_gpm_len - 1; 1379250003Sadrian } 1380250003Sadrian else if (value >= ahp->ah_mci_gpm_len) { 1381250003Sadrian if (value != 0xFFFF) { 1382250003Sadrian value = 0; 1383250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, 1384250003Sadrian "(MCI) %s: GPM offset out of range.\n", __func__); 1385250003Sadrian } 1386250003Sadrian } 1387250003Sadrian else { 1388250003Sadrian value--; 1389250003Sadrian } 1390250003Sadrian 1391250003Sadrian if (value == 0xFFFF) { 1392250003Sadrian value = HAL_MCI_GPM_INVALID; 1393250003Sadrian more_gpm = HAL_MCI_GPM_NOMORE; 1394250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, 1395250003Sadrian "(MCI) %s: GPM ptr invalid " 1396250003Sadrian "@ptr=%d, @offset=%d, more=NOMORE.\n", 1397250003Sadrian __func__, gpm_ptr, value); 1398250003Sadrian } 1399250003Sadrian else if (state_type == HAL_MCI_STATE_NEXT_GPM_OFFSET) { 1400250003Sadrian if (gpm_ptr == ahp->ah_mci_gpm_idx) { 1401250003Sadrian value = HAL_MCI_GPM_INVALID; 1402250003Sadrian more_gpm = HAL_MCI_GPM_NOMORE; 1403250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, 1404250003Sadrian "(MCI) %s: GPM message not available " 1405250003Sadrian "@ptr=%d, @offset=%d, more=NOMORE.\n", 1406250003Sadrian __func__, gpm_ptr, value); 1407250003Sadrian } 1408250003Sadrian else { 1409250003Sadrian while (1) { 1410250003Sadrian u_int32_t temp_index; 1411250003Sadrian 1412250003Sadrian /* skip reserved GPM if any */ 1413250003Sadrian if (value != ahp->ah_mci_gpm_idx) { 1414250003Sadrian more_gpm = HAL_MCI_GPM_MORE; 1415250003Sadrian } 1416250003Sadrian else { 1417250003Sadrian more_gpm = HAL_MCI_GPM_NOMORE; 1418250003Sadrian } 1419250003Sadrian temp_index = ahp->ah_mci_gpm_idx; 1420250003Sadrian ahp->ah_mci_gpm_idx++; 1421250003Sadrian if (ahp->ah_mci_gpm_idx >= ahp->ah_mci_gpm_len) { 1422250003Sadrian ahp->ah_mci_gpm_idx = 0; 1423250003Sadrian } 1424250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, 1425250003Sadrian "(MCI) %s: GPM message got " 1426250003Sadrian "@ptr=%d, @offset=%d, more=%s.\n", 1427250003Sadrian __func__, gpm_ptr, temp_index, 1428250003Sadrian (more_gpm == HAL_MCI_GPM_MORE)?"MORE":"NOMORE"); 1429250003Sadrian if (ar9300_mci_is_gpm_valid(ah, temp_index)) { 1430250003Sadrian value = temp_index; 1431250003Sadrian break; 1432250003Sadrian } 1433250003Sadrian if (more_gpm == HAL_MCI_GPM_NOMORE) { 1434250003Sadrian value = HAL_MCI_GPM_INVALID; 1435250003Sadrian break; 1436250003Sadrian } 1437250003Sadrian } 1438250003Sadrian } 1439250003Sadrian if (p_data != NULL) { 1440250003Sadrian *p_data = more_gpm; 1441250003Sadrian } 1442250003Sadrian } 1443250003Sadrian if (value != HAL_MCI_GPM_INVALID) { 1444250003Sadrian value <<= 4; 1445250003Sadrian } 1446250003Sadrian break; 1447250003Sadrian 1448250003Sadrian case HAL_MCI_STATE_LAST_SCHD_MSG_OFFSET: 1449250003Sadrian value = MS(OS_REG_READ(ah, AR_MCI_RX_STATUS), 1450250003Sadrian AR_MCI_RX_LAST_SCHD_MSG_INDEX); 1451250003Sadrian 1452250003Sadrian#if AH_MCI_DEBUG_PRINT_SCHED 1453250003Sadrian { 1454250003Sadrian u_int32_t index = value; 1455250003Sadrian u_int32_t prev_index, sched_idx; 1456250003Sadrian u_int32_t *pld; 1457250003Sadrian u_int8_t *pld8; 1458250003Sadrian u_int32_t wbtimer = OS_REG_READ(ah, AR_BTCOEX_WBTIMER); 1459250003Sadrian u_int32_t schd_ctl = OS_REG_READ(ah, AR_MCI_HW_SCHD_TBL_CTL); 1460250003Sadrian 1461250003Sadrian if (index > 0) { 1462250003Sadrian prev_index = index - 1; 1463250003Sadrian } else { 1464250003Sadrian prev_index = index; 1465250003Sadrian } 1466250003Sadrian 1467250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) SCHED\n"); 1468250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, 1469250003Sadrian "(MCI) SCHED SCHD_TBL_CTRL=0x%08x, WBTIMER=0x%08x (%d)\n", 1470250003Sadrian schd_ctl, wbtimer, wbtimer); 1471250003Sadrian for (sched_idx = prev_index; sched_idx <= index; sched_idx++) { 1472250003Sadrian pld = (u_int32_t *) (ahp->ah_mci_sched_buf + (sched_idx << 4)); 1473250003Sadrian pld8 = (u_int8_t *) pld; 1474250003Sadrian 1475250003Sadrian ar9300_mci_print_msg(ah, AH_FALSE, MCI_SCHD_INFO, 16, pld); 1476250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, 1477250003Sadrian "(MCI) SCHED idx=%d, T1=0x%08x (%d), T2=0x%08x (%d)\n", 1478250003Sadrian sched_idx, 1479250003Sadrian pld[0], pld[0], pld[1], pld[1]); 1480250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, 1481250003Sadrian "(MCI) SCHED addr=%d %s pwr=%d prio=%d %s link=%d\n", 1482250003Sadrian pld8[11] >> 4, 1483250003Sadrian (pld8[11] & 0x08)?"TX":"RX", 1484250003Sadrian (int8_t) (((pld8[11] & 0x07) << 5) | (pld8[10] >> 3)), 1485250003Sadrian (((pld8[10] & 0x07) << 5) | (pld8[9] >> 3)), 1486250003Sadrian (pld8[9] & 0x04)?"LE":"BR/EDR", 1487250003Sadrian (((pld8[9] & 0x03) << 2) | (pld8[8] >> 6))); 1488250003Sadrian } 1489250003Sadrian } 1490250003Sadrian#endif /* AH_MCI_DEBUG_PRINT_SCHED */ 1491250003Sadrian 1492250003Sadrian /* Make it in bytes */ 1493250003Sadrian value <<= 4; 1494250003Sadrian break; 1495250003Sadrian 1496250003Sadrian case HAL_MCI_STATE_REMOTE_SLEEP: 1497250003Sadrian value = MS(OS_REG_READ(ah, AR_MCI_RX_STATUS), 1498250003Sadrian AR_MCI_RX_REMOTE_SLEEP) ? MCI_BT_SLEEP : MCI_BT_AWAKE; 1499250003Sadrian break; 1500250003Sadrian 1501250003Sadrian case HAL_MCI_STATE_CONT_RSSI_POWER: 1502250003Sadrian value = MS(ahp->ah_mci_cont_status, 1503250003Sadrian AR_MCI_CONT_RSSI_POWER); 1504250003Sadrian break; 1505250003Sadrian 1506250003Sadrian case HAL_MCI_STATE_CONT_PRIORITY: 1507250003Sadrian value = MS(ahp->ah_mci_cont_status, 1508250003Sadrian AR_MCI_CONT_RRIORITY); 1509250003Sadrian break; 1510250003Sadrian 1511250003Sadrian case HAL_MCI_STATE_CONT_TXRX: 1512250003Sadrian value = MS(ahp->ah_mci_cont_status, 1513250003Sadrian AR_MCI_CONT_TXRX); 1514250003Sadrian break; 1515250003Sadrian 1516250003Sadrian case HAL_MCI_STATE_BT: 1517250003Sadrian value = ahp->ah_mci_bt_state; 1518250003Sadrian break; 1519250003Sadrian 1520250003Sadrian case HAL_MCI_STATE_SET_BT_SLEEP: 1521250003Sadrian ahp->ah_mci_bt_state = MCI_BT_SLEEP; 1522250003Sadrian break; 1523250003Sadrian 1524250003Sadrian case HAL_MCI_STATE_SET_BT_AWAKE: 1525250003Sadrian ahp->ah_mci_bt_state = MCI_BT_AWAKE; 1526250003Sadrian ar9300_mci_send_coex_version_query(ah, AH_TRUE); 1527250003Sadrian ar9300_mci_send_coex_wlan_channels(ah, AH_TRUE); 1528250003Sadrian if (ahp->ah_mci_unhalt_bt_gpm == AH_TRUE) { 1529250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, 1530250003Sadrian "(MCI) %s: UNHALT BT GPM\n", __func__); 1531250003Sadrian ar9300_mci_send_coex_halt_bt_gpm(ah, AH_FALSE, AH_TRUE); 1532250003Sadrian } 1533250003Sadrian ar9300_mci_2g5g_switch(ah, AH_TRUE); 1534250003Sadrian break; 1535250003Sadrian 1536250003Sadrian case HAL_MCI_STATE_SET_BT_CAL_START: 1537250003Sadrian ahp->ah_mci_bt_state = MCI_BT_CAL_START; 1538250003Sadrian break; 1539250003Sadrian 1540250003Sadrian case HAL_MCI_STATE_SET_BT_CAL: 1541250003Sadrian ahp->ah_mci_bt_state = MCI_BT_CAL; 1542250003Sadrian break; 1543250003Sadrian 1544250003Sadrian case HAL_MCI_STATE_RESET_REQ_WAKE: 1545250003Sadrian ar9300_mci_reset_req_wakeup(ah); 1546250003Sadrian ahp->ah_mci_coex_2g5g_update = AH_TRUE; 1547250003Sadrian 1548250003Sadrian if ((AR_SREV_JUPITER_20_OR_LATER(ah) || AR_SREV_APHRODITE(ah)) && 1549250008Sadrian (ah->ah_config.ath_hal_mci_config & 1550250003Sadrian ATH_MCI_CONFIG_MCI_OBS_MASK)) 1551250003Sadrian { 1552250003Sadrian /* Check if we still have control of the GPIOs */ 1553250003Sadrian if ((OS_REG_READ(ah, AR_GLB_GPIO_CONTROL) & 1554250003Sadrian ATH_MCI_CONFIG_MCI_OBS_GPIO) != 1555250003Sadrian ATH_MCI_CONFIG_MCI_OBS_GPIO) 1556250003Sadrian { 1557250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, 1558250003Sadrian "(MCI) Reconfigure observation\n"); 1559250003Sadrian ar9300_mci_observation_set_up(ah); 1560250003Sadrian } 1561250003Sadrian } 1562250003Sadrian 1563250003Sadrian break; 1564250003Sadrian 1565250003Sadrian case HAL_MCI_STATE_SEND_WLAN_COEX_VERSION: 1566250003Sadrian ar9300_mci_send_coex_version_response(ah, AH_TRUE); 1567250003Sadrian break; 1568250003Sadrian 1569250003Sadrian case HAL_MCI_STATE_SET_BT_COEX_VERSION: 1570250003Sadrian if (p_data == NULL) { 1571250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, 1572250003Sadrian "(MCI) Error: Set BT Coex version with NULL data !!!\n"); 1573250003Sadrian } 1574250003Sadrian else { 1575250003Sadrian ahp->ah_mci_coex_major_version_bt = (*p_data >> 8) & 0xff; 1576250003Sadrian ahp->ah_mci_coex_minor_version_bt = (*p_data) & 0xff; 1577250003Sadrian ahp->ah_mci_coex_bt_version_known = AH_TRUE; 1578250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) BT version set: %d.%d\n", 1579250003Sadrian ahp->ah_mci_coex_major_version_bt, 1580250003Sadrian ahp->ah_mci_coex_minor_version_bt); 1581250003Sadrian } 1582250003Sadrian break; 1583250003Sadrian 1584250003Sadrian case HAL_MCI_STATE_SEND_WLAN_CHANNELS: 1585250003Sadrian if (p_data != NULL) 1586250003Sadrian { 1587250003Sadrian if (((ahp->ah_mci_coex_wlan_channels[1] & 0xffff0000) == 1588250003Sadrian (*(p_data + 1) & 0xffff0000)) && 1589250003Sadrian (ahp->ah_mci_coex_wlan_channels[2] == *(p_data + 2)) && 1590250003Sadrian (ahp->ah_mci_coex_wlan_channels[3] == *(p_data + 3))) 1591250003Sadrian { 1592250003Sadrian break; 1593250003Sadrian } 1594250003Sadrian ahp->ah_mci_coex_wlan_channels[0] = *p_data++; 1595250003Sadrian ahp->ah_mci_coex_wlan_channels[1] = *p_data++; 1596250003Sadrian ahp->ah_mci_coex_wlan_channels[2] = *p_data++; 1597250003Sadrian ahp->ah_mci_coex_wlan_channels[3] = *p_data++; 1598250003Sadrian } 1599250003Sadrian ahp->ah_mci_coex_wlan_channels_update = AH_TRUE; 1600250003Sadrian ar9300_mci_send_coex_wlan_channels(ah, AH_TRUE); 1601250003Sadrian break; 1602250003Sadrian 1603250003Sadrian case HAL_MCI_STATE_SEND_VERSION_QUERY: 1604250003Sadrian ar9300_mci_send_coex_version_query(ah, AH_TRUE); 1605250003Sadrian break; 1606250003Sadrian 1607250003Sadrian case HAL_MCI_STATE_SEND_STATUS_QUERY: 1608250003Sadrian if (AR_SREV_JUPITER_10(ah)) { 1609250003Sadrian ar9300_mci_send_coex_bt_status_query(ah, AH_TRUE, 1610250003Sadrian MCI_GPM_COEX_QUERY_BT_ALL_INFO); 1611250003Sadrian } else { 1612250003Sadrian ar9300_mci_send_coex_bt_status_query(ah, AH_TRUE, 1613250003Sadrian MCI_GPM_COEX_QUERY_BT_TOPOLOGY); 1614250003Sadrian } 1615250003Sadrian break; 1616250003Sadrian 1617250003Sadrian case HAL_MCI_STATE_NEED_FLUSH_BT_INFO: 1618250003Sadrian /* 1619250003Sadrian * ah_mci_unhalt_bt_gpm means whether it's needed to send 1620250003Sadrian * UNHALT message. It's set whenever there's a request to send HALT 1621250003Sadrian * message. ah_mci_halted_bt_gpm means whether HALT message is sent 1622250003Sadrian * out successfully. 1623250003Sadrian * 1624250003Sadrian * Checking (ah_mci_unhalt_bt_gpm == AH_FALSE) instead of checking 1625250003Sadrian * (ahp->ah_mci_halted_bt_gpm == AH_FALSE) will make sure currently is 1626250003Sadrian * in UNHALT-ed mode and BT can respond to status query. 1627250003Sadrian */ 1628250003Sadrian if ((ahp->ah_mci_unhalt_bt_gpm == AH_FALSE) && 1629250003Sadrian (ahp->ah_mci_need_flush_btinfo == AH_TRUE)) 1630250003Sadrian { 1631250003Sadrian value = 1; 1632250003Sadrian } 1633250003Sadrian else { 1634250003Sadrian value = 0; 1635250003Sadrian } 1636250003Sadrian if (p_data != NULL) { 1637250008Sadrian ahp->ah_mci_need_flush_btinfo = (*p_data != 0)? AH_TRUE : AH_FALSE; 1638250003Sadrian } 1639250003Sadrian break; 1640250003Sadrian 1641250003Sadrian case HAL_MCI_STATE_SET_CONCUR_TX_PRI: 1642250003Sadrian if (p_data) { 1643250003Sadrian ahp->ah_mci_stomp_none_tx_pri = *p_data & 0xff; 1644250003Sadrian ahp->ah_mci_stomp_low_tx_pri = (*p_data >> 8) & 0xff; 1645250003Sadrian ahp->ah_mci_stomp_all_tx_pri = (*p_data >> 16) & 0xff; 1646250003Sadrian } 1647250003Sadrian break; 1648250003Sadrian 1649250003Sadrian case HAL_MCI_STATE_RECOVER_RX: 1650250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) hal RECOVER_RX\n"); 1651250003Sadrian ar9300_mci_prep_interface(ah); 1652250003Sadrian ahp->ah_mci_query_bt = AH_TRUE; 1653250003Sadrian ahp->ah_mci_need_flush_btinfo = AH_TRUE; 1654250003Sadrian ar9300_mci_send_coex_wlan_channels(ah, AH_TRUE); 1655250003Sadrian ar9300_mci_2g5g_switch(ah, AH_TRUE); 1656250003Sadrian break; 1657250003Sadrian 1658250003Sadrian case HAL_MCI_STATE_DEBUG: 1659250003Sadrian if (p_data != NULL) { 1660250003Sadrian if (*p_data == HAL_MCI_STATE_DEBUG_REQ_BT_DEBUG) { 1661250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) QUERY_BT_DEBUG\n"); 1662250003Sadrian ar9300_mci_send_coex_bt_status_query(ah, AH_TRUE, 1663250003Sadrian MCI_GPM_COEX_QUERY_BT_DEBUG); 1664250003Sadrian OS_DELAY(10); 1665250003Sadrian if (AR_SREV_JUPITER_20(ah) || AR_SREV_APHRODITE(ah)) { 1666250003Sadrian ar9300_mci_send_coex_bt_flags(ah, AH_TRUE, 1667250003Sadrian MCI_GPM_COEX_BT_FLAGS_READ, 0); 1668250003Sadrian } 1669250003Sadrian } 1670250003Sadrian } 1671250003Sadrian break; 1672250003Sadrian 1673250003Sadrian case HAL_MCI_STATE_NEED_FTP_STOMP: 1674250008Sadrian value = (ah->ah_config.ath_hal_mci_config & 1675250003Sadrian ATH_MCI_CONFIG_DISABLE_FTP_STOMP) ? 0 : 1; 1676250003Sadrian break; 1677250003Sadrian 1678250003Sadrian case HAL_MCI_STATE_NEED_TUNING: 1679250008Sadrian value = (ah->ah_config.ath_hal_mci_config & 1680250003Sadrian ATH_MCI_CONFIG_DISABLE_TUNING) ? 0 : 1; 1681250003Sadrian break; 1682250003Sadrian 1683250003Sadrian case HAL_MCI_STATE_SHARED_CHAIN_CONCUR_TX: 1684250008Sadrian value = ((ah->ah_config.ath_hal_mci_config & 1685250003Sadrian ATH_MCI_CONFIG_CONCUR_TX) == 1686250003Sadrian ATH_MCI_CONCUR_TX_SHARED_CHN)? 1 : 0; 1687250003Sadrian break; 1688250003Sadrian 1689250003Sadrian default: 1690250003Sadrian break; 1691250003Sadrian } 1692250003Sadrian return value; 1693250003Sadrian} 1694250003Sadrian 1695250003Sadrianvoid ar9300_mci_detach(struct ath_hal *ah) 1696250003Sadrian{ 1697250003Sadrian /* Turn off MCI and Jupiter mode. */ 1698250003Sadrian OS_REG_WRITE(ah, AR_BTCOEX_CTRL, 0x00); 1699250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, "(MCI) ar9300_mci_detach\n"); 1700250003Sadrian ar9300_mci_disable_interrupt(ah); 1701250003Sadrian} 1702250003Sadrian 1703250003Sadrian/* 1704250003Sadrian * Low priority BT: 0 - 59(0x3b) 1705250003Sadrian * High priority BT: 60 - 125(0x7d) 1706250003Sadrian * Critical BT: 126 - 255 1707250003Sadrian 1708250003Sadrian BTCOEX_WL_WEIGHTS0_VALUE0 ; // wl_idle 1709250003Sadrian BTCOEX_WL_WEIGHTS0_VALUE1 ; // sw_ctrl[3] - all_stomp 1710250003Sadrian BTCOEX_WL_WEIGHTS0_VALUE2 ; // sw_ctrl[2] - all_not_stomp 1711250003Sadrian BTCOEX_WL_WEIGHTS0_VALUE3 ; // sw_ctrl[1] - pa_pre_distortion 1712250003Sadrian BTCOEX_WL_WEIGHTS1_VALUE0 ; // sw_ctrl[0] - general purpose 1713250003Sadrian BTCOEX_WL_WEIGHTS1_VALUE1 ; // tm_wl_wait_beacon 1714250003Sadrian BTCOEX_WL_WEIGHTS1_VALUE2 ; // ts_state_wait_ack_cts 1715250003Sadrian BTCOEX_WL_WEIGHTS1_VALUE3 ; // self_gen 1716250003Sadrian BTCOEX_WL_WEIGHTS2_VALUE0 ; // idle 1717250003Sadrian BTCOEX_WL_WEIGHTS2_VALUE1 ; // rx 1718250003Sadrian BTCOEX_WL_WEIGHTS2_VALUE2 ; // tx 1719250003Sadrian BTCOEX_WL_WEIGHTS2_VALUE3 ; // rx + tx 1720250003Sadrian BTCOEX_WL_WEIGHTS3_VALUE0 ; // tx 1721250003Sadrian BTCOEX_WL_WEIGHTS3_VALUE1 ; // rx 1722250003Sadrian BTCOEX_WL_WEIGHTS3_VALUE2 ; // tx 1723250003Sadrian BTCOEX_WL_WEIGHTS3_VALUE3 ; // rx + tx 1724250003Sadrian 1725250003Sadrian Stomp all: 1726250003Sadrian ah_bt_coex_wlan_weight[0] = 0x00007d00 1727250003Sadrian ah_bt_coex_wlan_weight[1] = 0x7d7d7d00 1728250003Sadrian ah_bt_coex_wlan_weight[2] = 0x7d7d7d00 1729250003Sadrian ah_bt_coex_wlan_weight[3] = 0x7d7d7d7d 1730250003Sadrian Stomp low: 1731250003Sadrian ah_bt_coex_wlan_weight[0] = 0x00007d00 1732250003Sadrian ah_bt_coex_wlan_weight[1] = 0x7d3b3b00 1733250003Sadrian ah_bt_coex_wlan_weight[2] = 0x3b3b3b00 1734250003Sadrian ah_bt_coex_wlan_weight[3] = 0x3b3b3b3b 1735250003Sadrian Stomp none: 1736250003Sadrian ah_bt_coex_wlan_weight[0] = 0x00007d00 1737250003Sadrian ah_bt_coex_wlan_weight[1] = 0x7d000000 1738250003Sadrian ah_bt_coex_wlan_weight[2] = 0x00000000 1739250003Sadrian ah_bt_coex_wlan_weight[3] = 0x00000000 1740250003Sadrian*/ 1741250003Sadrian 1742250003Sadrianvoid ar9300_mci_bt_coex_set_weights(struct ath_hal *ah, u_int32_t stomp_type) 1743250003Sadrian{ 1744250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 1745250008Sadrian// struct ath_hal_private *ahpriv = AH_PRIVATE(ah); 1746250003Sadrian u_int32_t tx_priority = 0; 1747250003Sadrian 1748250003Sadrian switch (stomp_type) { 1749250003Sadrian case HAL_BT_COEX_STOMP_ALL: 1750250003Sadrian ahp->ah_bt_coex_wlan_weight[0] = JUPITER_STOMP_ALL_WLAN_WGHT0; 1751250003Sadrian ahp->ah_bt_coex_wlan_weight[1] = JUPITER_STOMP_ALL_WLAN_WGHT1; 1752250003Sadrian ahp->ah_bt_coex_wlan_weight[2] = JUPITER_STOMP_ALL_WLAN_WGHT2; 1753250003Sadrian ahp->ah_bt_coex_wlan_weight[3] = JUPITER_STOMP_ALL_WLAN_WGHT3; 1754250003Sadrian if (ahp->ah_mci_concur_tx_en && ahp->ah_mci_stomp_all_tx_pri) { 1755250003Sadrian tx_priority = ahp->ah_mci_stomp_all_tx_pri; 1756250003Sadrian } 1757250003Sadrian break; 1758250003Sadrian case HAL_BT_COEX_STOMP_LOW: 1759250003Sadrian if (ahp->ah_bt_coex_flag & HAL_BT_COEX_FLAG_MCI_FTP_STOMP_RX) { 1760250003Sadrian ahp->ah_bt_coex_wlan_weight[0] = JUPITER_STOMP_LOW_FTP_WLAN_WGHT0; 1761250003Sadrian ahp->ah_bt_coex_wlan_weight[1] = JUPITER_STOMP_LOW_FTP_WLAN_WGHT1; 1762250003Sadrian ahp->ah_bt_coex_wlan_weight[2] = JUPITER_STOMP_LOW_FTP_WLAN_WGHT2; 1763250003Sadrian ahp->ah_bt_coex_wlan_weight[3] = JUPITER_STOMP_LOW_FTP_WLAN_WGHT3; 1764250003Sadrian } 1765250003Sadrian else { 1766250003Sadrian ahp->ah_bt_coex_wlan_weight[0] = JUPITER_STOMP_LOW_WLAN_WGHT0; 1767250003Sadrian ahp->ah_bt_coex_wlan_weight[1] = JUPITER_STOMP_LOW_WLAN_WGHT1; 1768250003Sadrian ahp->ah_bt_coex_wlan_weight[2] = JUPITER_STOMP_LOW_WLAN_WGHT2; 1769250003Sadrian ahp->ah_bt_coex_wlan_weight[3] = JUPITER_STOMP_LOW_WLAN_WGHT3; 1770250003Sadrian } 1771250003Sadrian if (ahp->ah_mci_concur_tx_en && ahp->ah_mci_stomp_low_tx_pri) { 1772250003Sadrian tx_priority = ahp->ah_mci_stomp_low_tx_pri; 1773250003Sadrian } 1774250008Sadrian if (ah->ah_config.ath_hal_mci_config & 1775250003Sadrian ATH_MCI_CONFIG_MCI_OBS_TXRX) 1776250003Sadrian { 1777250003Sadrian ar9300_gpio_set(ah, 5, 1); 1778250003Sadrian } 1779250003Sadrian break; 1780250003Sadrian case HAL_BT_COEX_STOMP_ALL_FORCE: 1781250003Sadrian ahp->ah_bt_coex_wlan_weight[0] = JUPITER_STOMP_ALL_FORCE_WLAN_WGHT0; 1782250003Sadrian ahp->ah_bt_coex_wlan_weight[1] = JUPITER_STOMP_ALL_FORCE_WLAN_WGHT1; 1783250003Sadrian ahp->ah_bt_coex_wlan_weight[2] = JUPITER_STOMP_ALL_FORCE_WLAN_WGHT2; 1784250003Sadrian ahp->ah_bt_coex_wlan_weight[3] = JUPITER_STOMP_ALL_FORCE_WLAN_WGHT3; 1785250003Sadrian break; 1786250003Sadrian case HAL_BT_COEX_STOMP_LOW_FORCE: 1787250003Sadrian ahp->ah_bt_coex_wlan_weight[0] = JUPITER_STOMP_LOW_FORCE_WLAN_WGHT0; 1788250003Sadrian ahp->ah_bt_coex_wlan_weight[1] = JUPITER_STOMP_LOW_FORCE_WLAN_WGHT1; 1789250003Sadrian ahp->ah_bt_coex_wlan_weight[2] = JUPITER_STOMP_LOW_FORCE_WLAN_WGHT2; 1790250003Sadrian ahp->ah_bt_coex_wlan_weight[3] = JUPITER_STOMP_LOW_FORCE_WLAN_WGHT3; 1791250003Sadrian if (ahp->ah_mci_concur_tx_en && ahp->ah_mci_stomp_low_tx_pri) { 1792250003Sadrian tx_priority = ahp->ah_mci_stomp_low_tx_pri; 1793250003Sadrian } 1794250003Sadrian break; 1795250003Sadrian case HAL_BT_COEX_STOMP_NONE: 1796250003Sadrian case HAL_BT_COEX_NO_STOMP: 1797250003Sadrian ahp->ah_bt_coex_wlan_weight[0] = JUPITER_STOMP_NONE_WLAN_WGHT0; 1798250003Sadrian ahp->ah_bt_coex_wlan_weight[1] = JUPITER_STOMP_NONE_WLAN_WGHT1; 1799250003Sadrian ahp->ah_bt_coex_wlan_weight[2] = JUPITER_STOMP_NONE_WLAN_WGHT2; 1800250003Sadrian ahp->ah_bt_coex_wlan_weight[3] = JUPITER_STOMP_NONE_WLAN_WGHT3; 1801250003Sadrian if (ahp->ah_mci_concur_tx_en && ahp->ah_mci_stomp_none_tx_pri) { 1802250003Sadrian tx_priority = ahp->ah_mci_stomp_none_tx_pri; 1803250003Sadrian } 1804250008Sadrian if (ah->ah_config.ath_hal_mci_config & 1805250003Sadrian ATH_MCI_CONFIG_MCI_OBS_TXRX) 1806250003Sadrian { 1807250003Sadrian ar9300_gpio_set(ah, 5, 0); 1808250003Sadrian } 1809250003Sadrian break; 1810250003Sadrian default: 1811250003Sadrian /* There is a forceWeight from registry */ 1812250003Sadrian ahp->ah_bt_coex_wlan_weight[0] = stomp_type; 1813250003Sadrian ahp->ah_bt_coex_wlan_weight[1] = stomp_type; 1814250003Sadrian break; 1815250003Sadrian } 1816250003Sadrian 1817250003Sadrian if (ahp->ah_mci_concur_tx_en && tx_priority) { 1818250003Sadrian ahp->ah_bt_coex_wlan_weight[1] &= ~MCI_CONCUR_TX_WLAN_WGHT1_MASK; 1819250003Sadrian ahp->ah_bt_coex_wlan_weight[1] |= 1820250003Sadrian SM(tx_priority, MCI_CONCUR_TX_WLAN_WGHT1_MASK); 1821250003Sadrian ahp->ah_bt_coex_wlan_weight[2] &= ~MCI_CONCUR_TX_WLAN_WGHT2_MASK; 1822250003Sadrian ahp->ah_bt_coex_wlan_weight[2] |= 1823250003Sadrian SM(tx_priority, MCI_CONCUR_TX_WLAN_WGHT2_MASK); 1824250003Sadrian ahp->ah_bt_coex_wlan_weight[3] &= ~MCI_CONCUR_TX_WLAN_WGHT3_MASK; 1825250003Sadrian ahp->ah_bt_coex_wlan_weight[3] |= 1826250003Sadrian SM(tx_priority, MCI_CONCUR_TX_WLAN_WGHT3_MASK); 1827250003Sadrian ahp->ah_bt_coex_wlan_weight[3] &= ~MCI_CONCUR_TX_WLAN_WGHT3_MASK2; 1828250003Sadrian ahp->ah_bt_coex_wlan_weight[3] |= 1829250003Sadrian SM(tx_priority, MCI_CONCUR_TX_WLAN_WGHT3_MASK2); 1830250003Sadrian } 1831250008Sadrian if (ah->ah_config.ath_hal_mci_config & 1832250003Sadrian ATH_MCI_CONFIG_MCI_WEIGHT_DBG) 1833250003Sadrian { 1834250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, 1835250003Sadrian "(MCI) Set weights: 0x%08x 0x%08x 0x%08x 0x%08x\n", 1836250003Sadrian ahp->ah_bt_coex_wlan_weight[0], 1837250003Sadrian ahp->ah_bt_coex_wlan_weight[1], 1838250003Sadrian ahp->ah_bt_coex_wlan_weight[2], 1839250003Sadrian ahp->ah_bt_coex_wlan_weight[3]); 1840250003Sadrian } 1841250003Sadrian} 1842250003Sadrian 1843250003Sadrianvoid ar9300_mci_bt_coex_disable(struct ath_hal *ah) 1844250003Sadrian{ 1845250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 1846250003Sadrian 1847250003Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, 1848250003Sadrian "(MCI) %s: Set weight to stomp none.\n", __func__); 1849250003Sadrian 1850250003Sadrian ar9300_mci_bt_coex_set_weights(ah, HAL_BT_COEX_STOMP_NONE); 1851250003Sadrian 1852250003Sadrian /* 1853250003Sadrian * In Jupiter, when coex is disabled, we just set weight 1854250003Sadrian * table to be in favor of WLAN. 1855250003Sadrian */ 1856250003Sadrian OS_REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS0, ahp->ah_bt_coex_wlan_weight[0]); 1857250003Sadrian OS_REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS1, ahp->ah_bt_coex_wlan_weight[1]); 1858250003Sadrian OS_REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS2, ahp->ah_bt_coex_wlan_weight[2]); 1859250003Sadrian OS_REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS3, ahp->ah_bt_coex_wlan_weight[3]); 1860250003Sadrian 1861250003Sadrian ahp->ah_bt_coex_enabled = AH_FALSE; 1862250003Sadrian} 1863250003Sadrian 1864250003Sadrianint ar9300_mci_bt_coex_enable(struct ath_hal *ah) 1865250003Sadrian{ 1866250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 1867250003Sadrian 1868250003Sadrian /* Mainly change the WLAN weight table */ 1869250003Sadrian OS_REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS0, ahp->ah_bt_coex_wlan_weight[0]); 1870250003Sadrian OS_REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS1, ahp->ah_bt_coex_wlan_weight[1]); 1871250003Sadrian OS_REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS2, ahp->ah_bt_coex_wlan_weight[2]); 1872250003Sadrian OS_REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS3, ahp->ah_bt_coex_wlan_weight[3]); 1873250003Sadrian 1874250003Sadrian /* Send ACK even when BT has higher priority. */ 1875250003Sadrian OS_REG_RMW_FIELD(ah, AR_QUIET1, AR_QUIET1_QUIET_ACK_CTS_ENABLE, 1); 1876250003Sadrian 1877250003Sadrian if (ahp->ah_bt_coex_flag & HAL_BT_COEX_FLAG_LOW_ACK_PWR) { 1878250003Sadrian OS_REG_WRITE(ah, AR_TPC, HAL_BT_COEX_LOW_ACK_POWER); 1879250003Sadrian } 1880250003Sadrian else { 1881250003Sadrian OS_REG_WRITE(ah, AR_TPC, HAL_BT_COEX_HIGH_ACK_POWER); 1882250003Sadrian } 1883250003Sadrian 1884250003Sadrian ahp->ah_bt_coex_enabled = AH_TRUE; 1885250003Sadrian 1886250003Sadrian return 0; 1887250003Sadrian} 1888250003Sadrian 1889250003Sadrian#endif /* ATH_SUPPORT_MCI */ 1890