1 /* 2 * Copyright (c) 2008-2011 Atheros Communications Inc. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 #include <linux/export.h> 18 #include "hw.h" 19 #include "hw-ops.h" 20 #include "ar9003_phy.h" 21 #include "ar9003_mci.h" 22 #include "ar9003_aic.h" 23 24 static void ar9003_mci_reset_req_wakeup(struct ath_hw *ah) 25 { 26 REG_RMW_FIELD(ah, AR_MCI_COMMAND2, 27 AR_MCI_COMMAND2_RESET_REQ_WAKEUP, 1); 28 udelay(1); 29 REG_RMW_FIELD(ah, AR_MCI_COMMAND2, 30 AR_MCI_COMMAND2_RESET_REQ_WAKEUP, 0); 31 } 32 33 static int ar9003_mci_wait_for_interrupt(struct ath_hw *ah, u32 address, 34 u32 bit_position, int time_out) 35 { 36 struct ath_common *common = ath9k_hw_common(ah); 37 38 while (time_out) { 39 if (!(REG_READ(ah, address) & bit_position)) { 40 udelay(10); 41 time_out -= 10; 42 43 if (time_out < 0) 44 break; 45 else 46 continue; 47 } 48 REG_WRITE(ah, address, bit_position); 49 50 if (address != AR_MCI_INTERRUPT_RX_MSG_RAW) 51 break; 52 53 if (bit_position & AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE) 54 ar9003_mci_reset_req_wakeup(ah); 55 56 if (bit_position & (AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING | 57 AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING)) 58 REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, 59 AR_MCI_INTERRUPT_REMOTE_SLEEP_UPDATE); 60 61 REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, AR_MCI_INTERRUPT_RX_MSG); 62 break; 63 } 64 65 if (time_out <= 0) { 66 ath_dbg(common, MCI, 67 "MCI Wait for Reg 0x%08x = 0x%08x timeout\n", 68 address, bit_position); 69 ath_dbg(common, MCI, 70 "MCI INT_RAW = 0x%08x, RX_MSG_RAW = 0x%08x\n", 71 REG_READ(ah, AR_MCI_INTERRUPT_RAW), 72 REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_RAW)); 73 time_out = 0; 74 } 75 76 return time_out; 77 } 78 79 static void ar9003_mci_remote_reset(struct ath_hw *ah, bool wait_done) 80 { 81 u32 payload[4] = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffff00}; 82 83 ar9003_mci_send_message(ah, MCI_REMOTE_RESET, 0, payload, 16, 84 wait_done, false); 85 udelay(5); 86 } 87 88 static void ar9003_mci_send_lna_transfer(struct ath_hw *ah, bool wait_done) 89 { 90 u32 payload = 0x00000000; 91 92 ar9003_mci_send_message(ah, MCI_LNA_TRANS, 0, &payload, 1, 93 wait_done, false); 94 } 95 96 static void ar9003_mci_send_req_wake(struct ath_hw *ah, bool wait_done) 97 { 98 ar9003_mci_send_message(ah, MCI_REQ_WAKE, MCI_FLAG_DISABLE_TIMESTAMP, 99 NULL, 0, wait_done, false); 100 udelay(5); 101 } 102 103 static void ar9003_mci_send_sys_waking(struct ath_hw *ah, bool wait_done) 104 { 105 ar9003_mci_send_message(ah, MCI_SYS_WAKING, MCI_FLAG_DISABLE_TIMESTAMP, 106 NULL, 0, wait_done, false); 107 } 108 109 static void ar9003_mci_send_lna_take(struct ath_hw *ah, bool wait_done) 110 { 111 u32 payload = 0x70000000; 112 113 ar9003_mci_send_message(ah, MCI_LNA_TAKE, 0, &payload, 1, 114 wait_done, false); 115 } 116 117 static void ar9003_mci_send_sys_sleeping(struct ath_hw *ah, bool wait_done) 118 { 119 ar9003_mci_send_message(ah, MCI_SYS_SLEEPING, 120 MCI_FLAG_DISABLE_TIMESTAMP, 121 NULL, 0, wait_done, false); 122 } 123 124 static void ar9003_mci_send_coex_version_query(struct ath_hw *ah, 125 bool wait_done) 126 { 127 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; 128 u32 payload[4] = {0, 0, 0, 0}; 129 130 if (mci->bt_version_known || 131 (mci->bt_state == MCI_BT_SLEEP)) 132 return; 133 134 MCI_GPM_SET_TYPE_OPCODE(payload, MCI_GPM_COEX_AGENT, 135 MCI_GPM_COEX_VERSION_QUERY); 136 ar9003_mci_send_message(ah, MCI_GPM, 0, payload, 16, wait_done, true); 137 } 138 139 static void ar9003_mci_send_coex_version_response(struct ath_hw *ah, 140 bool wait_done) 141 { 142 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; 143 u32 payload[4] = {0, 0, 0, 0}; 144 145 MCI_GPM_SET_TYPE_OPCODE(payload, MCI_GPM_COEX_AGENT, 146 MCI_GPM_COEX_VERSION_RESPONSE); 147 *(((u8 *)payload) + MCI_GPM_COEX_B_MAJOR_VERSION) = 148 mci->wlan_ver_major; 149 *(((u8 *)payload) + MCI_GPM_COEX_B_MINOR_VERSION) = 150 mci->wlan_ver_minor; 151 ar9003_mci_send_message(ah, MCI_GPM, 0, payload, 16, wait_done, true); 152 } 153 154 static void ar9003_mci_send_coex_wlan_channels(struct ath_hw *ah, 155 bool wait_done) 156 { 157 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; 158 u32 *payload = &mci->wlan_channels[0]; 159 160 if (!mci->wlan_channels_update || 161 (mci->bt_state == MCI_BT_SLEEP)) 162 return; 163 164 MCI_GPM_SET_TYPE_OPCODE(payload, MCI_GPM_COEX_AGENT, 165 MCI_GPM_COEX_WLAN_CHANNELS); 166 ar9003_mci_send_message(ah, MCI_GPM, 0, payload, 16, wait_done, true); 167 MCI_GPM_SET_TYPE_OPCODE(payload, 0xff, 0xff); 168 } 169 170 static void ar9003_mci_send_coex_bt_status_query(struct ath_hw *ah, 171 bool wait_done, u8 query_type) 172 { 173 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; 174 u32 payload[4] = {0, 0, 0, 0}; 175 bool query_btinfo; 176 177 if (mci->bt_state == MCI_BT_SLEEP) 178 return; 179 180 query_btinfo = !!(query_type & (MCI_GPM_COEX_QUERY_BT_ALL_INFO | 181 MCI_GPM_COEX_QUERY_BT_TOPOLOGY)); 182 MCI_GPM_SET_TYPE_OPCODE(payload, MCI_GPM_COEX_AGENT, 183 MCI_GPM_COEX_STATUS_QUERY); 184 185 *(((u8 *)payload) + MCI_GPM_COEX_B_BT_BITMAP) = query_type; 186 187 /* 188 * If bt_status_query message is not sent successfully, 189 * then need_flush_btinfo should be set again. 190 */ 191 if (!ar9003_mci_send_message(ah, MCI_GPM, 0, payload, 16, 192 wait_done, true)) { 193 if (query_btinfo) 194 mci->need_flush_btinfo = true; 195 } 196 197 if (query_btinfo) 198 mci->query_bt = false; 199 } 200 201 static void ar9003_mci_send_coex_halt_bt_gpm(struct ath_hw *ah, bool halt, 202 bool wait_done) 203 { 204 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; 205 u32 payload[4] = {0, 0, 0, 0}; 206 207 MCI_GPM_SET_TYPE_OPCODE(payload, MCI_GPM_COEX_AGENT, 208 MCI_GPM_COEX_HALT_BT_GPM); 209 210 if (halt) { 211 mci->query_bt = true; 212 /* Send next unhalt no matter halt sent or not */ 213 mci->unhalt_bt_gpm = true; 214 mci->need_flush_btinfo = true; 215 *(((u8 *)payload) + MCI_GPM_COEX_B_HALT_STATE) = 216 MCI_GPM_COEX_BT_GPM_HALT; 217 } else 218 *(((u8 *)payload) + MCI_GPM_COEX_B_HALT_STATE) = 219 MCI_GPM_COEX_BT_GPM_UNHALT; 220 221 ar9003_mci_send_message(ah, MCI_GPM, 0, payload, 16, wait_done, true); 222 } 223 224 static void ar9003_mci_prep_interface(struct ath_hw *ah) 225 { 226 struct ath_common *common = ath9k_hw_common(ah); 227 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; 228 u32 saved_mci_int_en; 229 u32 mci_timeout = 150; 230 231 mci->bt_state = MCI_BT_SLEEP; 232 saved_mci_int_en = REG_READ(ah, AR_MCI_INTERRUPT_EN); 233 234 REG_WRITE(ah, AR_MCI_INTERRUPT_EN, 0); 235 REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, 236 REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_RAW)); 237 REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, 238 REG_READ(ah, AR_MCI_INTERRUPT_RAW)); 239 240 ar9003_mci_remote_reset(ah, true); 241 ar9003_mci_send_req_wake(ah, true); 242 243 if (!ar9003_mci_wait_for_interrupt(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, 244 AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING, 500)) 245 goto clear_redunt; 246 247 mci->bt_state = MCI_BT_AWAKE; 248 249 /* 250 * we don't need to send more remote_reset at this moment. 251 * If BT receive first remote_reset, then BT HW will 252 * be cleaned up and will be able to receive req_wake 253 * and BT HW will respond sys_waking. 254 * In this case, WLAN will receive BT's HW sys_waking. 255 * Otherwise, if BT SW missed initial remote_reset, 256 * that remote_reset will still clean up BT MCI RX, 257 * and the req_wake will wake BT up, 258 * and BT SW will respond this req_wake with a remote_reset and 259 * sys_waking. In this case, WLAN will receive BT's SW 260 * sys_waking. In either case, BT's RX is cleaned up. So we 261 * don't need to reply BT's remote_reset now, if any. 262 * Similarly, if in any case, WLAN can receive BT's sys_waking, 263 * that means WLAN's RX is also fine. 264 */ 265 ar9003_mci_send_sys_waking(ah, true); 266 udelay(10); 267 268 /* 269 * Set BT priority interrupt value to be 0xff to 270 * avoid having too many BT PRIORITY interrupts. 271 */ 272 REG_WRITE(ah, AR_MCI_BT_PRI0, 0xFFFFFFFF); 273 REG_WRITE(ah, AR_MCI_BT_PRI1, 0xFFFFFFFF); 274 REG_WRITE(ah, AR_MCI_BT_PRI2, 0xFFFFFFFF); 275 REG_WRITE(ah, AR_MCI_BT_PRI3, 0xFFFFFFFF); 276 REG_WRITE(ah, AR_MCI_BT_PRI, 0X000000FF); 277 278 /* 279 * A contention reset will be received after send out 280 * sys_waking. Also BT priority interrupt bits will be set. 281 * Clear those bits before the next step. 282 */ 283 284 REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, 285 AR_MCI_INTERRUPT_RX_MSG_CONT_RST); 286 REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, AR_MCI_INTERRUPT_BT_PRI); 287 288 if (mci->is_2g && MCI_ANT_ARCH_PA_LNA_SHARED(mci)) { 289 ar9003_mci_send_lna_transfer(ah, true); 290 udelay(5); 291 } 292 293 if (mci->is_2g && !mci->update_2g5g && MCI_ANT_ARCH_PA_LNA_SHARED(mci)) { 294 if (ar9003_mci_wait_for_interrupt(ah, 295 AR_MCI_INTERRUPT_RX_MSG_RAW, 296 AR_MCI_INTERRUPT_RX_MSG_LNA_INFO, 297 mci_timeout)) 298 ath_dbg(common, MCI, 299 "MCI WLAN has control over the LNA & BT obeys it\n"); 300 else 301 ath_dbg(common, MCI, 302 "MCI BT didn't respond to LNA_TRANS\n"); 303 } 304 305 clear_redunt: 306 /* Clear the extra redundant SYS_WAKING from BT */ 307 if ((mci->bt_state == MCI_BT_AWAKE) && 308 (REG_READ_FIELD(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, 309 AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING)) && 310 (REG_READ_FIELD(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, 311 AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING) == 0)) { 312 REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, 313 AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING); 314 REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, 315 AR_MCI_INTERRUPT_REMOTE_SLEEP_UPDATE); 316 } 317 318 REG_WRITE(ah, AR_MCI_INTERRUPT_EN, saved_mci_int_en); 319 } 320 321 void ar9003_mci_set_full_sleep(struct ath_hw *ah) 322 { 323 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; 324 325 if (ar9003_mci_state(ah, MCI_STATE_ENABLE) && 326 (mci->bt_state != MCI_BT_SLEEP) && 327 !mci->halted_bt_gpm) { 328 ar9003_mci_send_coex_halt_bt_gpm(ah, true, true); 329 } 330 331 mci->ready = false; 332 } 333 334 static void ar9003_mci_disable_interrupt(struct ath_hw *ah) 335 { 336 REG_WRITE(ah, AR_MCI_INTERRUPT_EN, 0); 337 REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_EN, 0); 338 } 339 340 static void ar9003_mci_enable_interrupt(struct ath_hw *ah) 341 { 342 REG_WRITE(ah, AR_MCI_INTERRUPT_EN, AR_MCI_INTERRUPT_DEFAULT); 343 REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_EN, 344 AR_MCI_INTERRUPT_RX_MSG_DEFAULT); 345 } 346 347 static bool ar9003_mci_check_int(struct ath_hw *ah, u32 ints) 348 { 349 u32 intr; 350 351 intr = REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_RAW); 352 return ((intr & ints) == ints); 353 } 354 355 void ar9003_mci_get_interrupt(struct ath_hw *ah, u32 *raw_intr, 356 u32 *rx_msg_intr) 357 { 358 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; 359 360 *raw_intr = mci->raw_intr; 361 *rx_msg_intr = mci->rx_msg_intr; 362 363 /* Clean int bits after the values are read. */ 364 mci->raw_intr = 0; 365 mci->rx_msg_intr = 0; 366 } 367 EXPORT_SYMBOL(ar9003_mci_get_interrupt); 368 369 void ar9003_mci_get_isr(struct ath_hw *ah, enum ath9k_int *masked) 370 { 371 struct ath_common *common = ath9k_hw_common(ah); 372 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; 373 u32 raw_intr, rx_msg_intr; 374 375 rx_msg_intr = REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_RAW); 376 raw_intr = REG_READ(ah, AR_MCI_INTERRUPT_RAW); 377 378 if ((raw_intr == 0xdeadbeef) || (rx_msg_intr == 0xdeadbeef)) { 379 ath_dbg(common, MCI, 380 "MCI gets 0xdeadbeef during int processing\n"); 381 } else { 382 mci->rx_msg_intr |= rx_msg_intr; 383 mci->raw_intr |= raw_intr; 384 *masked |= ATH9K_INT_MCI; 385 386 if (rx_msg_intr & AR_MCI_INTERRUPT_RX_MSG_CONT_INFO) 387 mci->cont_status = REG_READ(ah, AR_MCI_CONT_STATUS); 388 389 REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, rx_msg_intr); 390 REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, raw_intr); 391 } 392 } 393 394 static void ar9003_mci_2g5g_changed(struct ath_hw *ah, bool is_2g) 395 { 396 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; 397 398 if (!mci->update_2g5g && 399 (mci->is_2g != is_2g)) 400 mci->update_2g5g = true; 401 402 mci->is_2g = is_2g; 403 } 404 405 static bool ar9003_mci_is_gpm_valid(struct ath_hw *ah, u32 msg_index) 406 { 407 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; 408 u32 *payload; 409 u32 recv_type, offset; 410 411 if (msg_index == MCI_GPM_INVALID) 412 return false; 413 414 offset = msg_index << 4; 415 416 payload = (u32 *)(mci->gpm_buf + offset); 417 recv_type = MCI_GPM_TYPE(payload); 418 419 if (recv_type == MCI_GPM_RSVD_PATTERN) 420 return false; 421 422 return true; 423 } 424 425 static void ar9003_mci_observation_set_up(struct ath_hw *ah) 426 { 427 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; 428 429 if (mci->config & ATH_MCI_CONFIG_MCI_OBS_MCI) { 430 ath9k_hw_cfg_output(ah, 3, AR_GPIO_OUTPUT_MUX_AS_MCI_WLAN_DATA); 431 ath9k_hw_cfg_output(ah, 2, AR_GPIO_OUTPUT_MUX_AS_MCI_WLAN_CLK); 432 ath9k_hw_cfg_output(ah, 1, AR_GPIO_OUTPUT_MUX_AS_MCI_BT_DATA); 433 ath9k_hw_cfg_output(ah, 0, AR_GPIO_OUTPUT_MUX_AS_MCI_BT_CLK); 434 } else if (mci->config & ATH_MCI_CONFIG_MCI_OBS_TXRX) { 435 ath9k_hw_cfg_output(ah, 3, AR_GPIO_OUTPUT_MUX_AS_WL_IN_TX); 436 ath9k_hw_cfg_output(ah, 2, AR_GPIO_OUTPUT_MUX_AS_WL_IN_RX); 437 ath9k_hw_cfg_output(ah, 1, AR_GPIO_OUTPUT_MUX_AS_BT_IN_TX); 438 ath9k_hw_cfg_output(ah, 0, AR_GPIO_OUTPUT_MUX_AS_BT_IN_RX); 439 ath9k_hw_cfg_output(ah, 5, AR_GPIO_OUTPUT_MUX_AS_OUTPUT); 440 } else if (mci->config & ATH_MCI_CONFIG_MCI_OBS_BT) { 441 ath9k_hw_cfg_output(ah, 3, AR_GPIO_OUTPUT_MUX_AS_BT_IN_TX); 442 ath9k_hw_cfg_output(ah, 2, AR_GPIO_OUTPUT_MUX_AS_BT_IN_RX); 443 ath9k_hw_cfg_output(ah, 1, AR_GPIO_OUTPUT_MUX_AS_MCI_BT_DATA); 444 ath9k_hw_cfg_output(ah, 0, AR_GPIO_OUTPUT_MUX_AS_MCI_BT_CLK); 445 } else 446 return; 447 448 REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE); 449 450 REG_RMW_FIELD(ah, AR_PHY_GLB_CONTROL, AR_GLB_DS_JTAG_DISABLE, 1); 451 REG_RMW_FIELD(ah, AR_PHY_GLB_CONTROL, AR_GLB_WLAN_UART_INTF_EN, 0); 452 REG_SET_BIT(ah, AR_GLB_GPIO_CONTROL, ATH_MCI_CONFIG_MCI_OBS_GPIO); 453 454 REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2, AR_BTCOEX_CTRL2_GPIO_OBS_SEL, 0); 455 REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2, AR_BTCOEX_CTRL2_MAC_BB_OBS_SEL, 1); 456 REG_WRITE(ah, AR_OBS, 0x4b); 457 REG_RMW_FIELD(ah, AR_DIAG_SW, AR_DIAG_OBS_PT_SEL1, 0x03); 458 REG_RMW_FIELD(ah, AR_DIAG_SW, AR_DIAG_OBS_PT_SEL2, 0x01); 459 REG_RMW_FIELD(ah, AR_MACMISC, AR_MACMISC_MISC_OBS_BUS_LSB, 0x02); 460 REG_RMW_FIELD(ah, AR_MACMISC, AR_MACMISC_MISC_OBS_BUS_MSB, 0x03); 461 REG_RMW_FIELD(ah, AR_PHY_TEST_CTL_STATUS, 462 AR_PHY_TEST_CTL_DEBUGPORT_SEL, 0x07); 463 } 464 465 static bool ar9003_mci_send_coex_bt_flags(struct ath_hw *ah, bool wait_done, 466 u8 opcode, u32 bt_flags) 467 { 468 u32 pld[4] = {0, 0, 0, 0}; 469 470 MCI_GPM_SET_TYPE_OPCODE(pld, MCI_GPM_COEX_AGENT, 471 MCI_GPM_COEX_BT_UPDATE_FLAGS); 472 473 *(((u8 *)pld) + MCI_GPM_COEX_B_BT_FLAGS_OP) = opcode; 474 *(((u8 *)pld) + MCI_GPM_COEX_W_BT_FLAGS + 0) = bt_flags & 0xFF; 475 *(((u8 *)pld) + MCI_GPM_COEX_W_BT_FLAGS + 1) = (bt_flags >> 8) & 0xFF; 476 *(((u8 *)pld) + MCI_GPM_COEX_W_BT_FLAGS + 2) = (bt_flags >> 16) & 0xFF; 477 *(((u8 *)pld) + MCI_GPM_COEX_W_BT_FLAGS + 3) = (bt_flags >> 24) & 0xFF; 478 479 return ar9003_mci_send_message(ah, MCI_GPM, 0, pld, 16, 480 wait_done, true); 481 } 482 483 static void ar9003_mci_sync_bt_state(struct ath_hw *ah) 484 { 485 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; 486 u32 cur_bt_state; 487 488 cur_bt_state = ar9003_mci_state(ah, MCI_STATE_REMOTE_SLEEP); 489 490 if (mci->bt_state != cur_bt_state) 491 mci->bt_state = cur_bt_state; 492 493 if (mci->bt_state != MCI_BT_SLEEP) { 494 495 ar9003_mci_send_coex_version_query(ah, true); 496 ar9003_mci_send_coex_wlan_channels(ah, true); 497 498 if (mci->unhalt_bt_gpm == true) 499 ar9003_mci_send_coex_halt_bt_gpm(ah, false, true); 500 } 501 } 502 503 void ar9003_mci_check_bt(struct ath_hw *ah) 504 { 505 struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci; 506 507 if (!mci_hw->ready) 508 return; 509 510 /* 511 * check BT state again to make 512 * sure it's not changed. 513 */ 514 ar9003_mci_sync_bt_state(ah); 515 ar9003_mci_2g5g_switch(ah, true); 516 517 if ((mci_hw->bt_state == MCI_BT_AWAKE) && 518 (mci_hw->query_bt == true)) { 519 mci_hw->need_flush_btinfo = true; 520 } 521 } 522 523 static void ar9003_mci_process_gpm_extra(struct ath_hw *ah, u8 gpm_type, 524 u8 gpm_opcode, u32 *p_gpm) 525 { 526 struct ath_common *common = ath9k_hw_common(ah); 527 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; 528 u8 *p_data = (u8 *) p_gpm; 529 530 if (gpm_type != MCI_GPM_COEX_AGENT) 531 return; 532 533 switch (gpm_opcode) { 534 case MCI_GPM_COEX_VERSION_QUERY: 535 ath_dbg(common, MCI, "MCI Recv GPM COEX Version Query\n"); 536 ar9003_mci_send_coex_version_response(ah, true); 537 break; 538 case MCI_GPM_COEX_VERSION_RESPONSE: 539 ath_dbg(common, MCI, "MCI Recv GPM COEX Version Response\n"); 540 mci->bt_ver_major = 541 *(p_data + MCI_GPM_COEX_B_MAJOR_VERSION); 542 mci->bt_ver_minor = 543 *(p_data + MCI_GPM_COEX_B_MINOR_VERSION); 544 mci->bt_version_known = true; 545 ath_dbg(common, MCI, "MCI BT Coex version: %d.%d\n", 546 mci->bt_ver_major, mci->bt_ver_minor); 547 break; 548 case MCI_GPM_COEX_STATUS_QUERY: 549 ath_dbg(common, MCI, 550 "MCI Recv GPM COEX Status Query = 0x%02X\n", 551 *(p_data + MCI_GPM_COEX_B_WLAN_BITMAP)); 552 mci->wlan_channels_update = true; 553 ar9003_mci_send_coex_wlan_channels(ah, true); 554 break; 555 case MCI_GPM_COEX_BT_PROFILE_INFO: 556 mci->query_bt = true; 557 ath_dbg(common, MCI, "MCI Recv GPM COEX BT_Profile_Info\n"); 558 break; 559 case MCI_GPM_COEX_BT_STATUS_UPDATE: 560 mci->query_bt = true; 561 ath_dbg(common, MCI, 562 "MCI Recv GPM COEX BT_Status_Update SEQ=%d (drop&query)\n", 563 *(p_gpm + 3)); 564 break; 565 default: 566 break; 567 } 568 } 569 570 static u32 ar9003_mci_wait_for_gpm(struct ath_hw *ah, u8 gpm_type, 571 u8 gpm_opcode, int time_out) 572 { 573 struct ath_common *common = ath9k_hw_common(ah); 574 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; 575 u32 *p_gpm = NULL, mismatch = 0, more_data; 576 u32 offset; 577 u8 recv_type = 0, recv_opcode = 0; 578 bool b_is_bt_cal_done = (gpm_type == MCI_GPM_BT_CAL_DONE); 579 580 more_data = time_out ? MCI_GPM_NOMORE : MCI_GPM_MORE; 581 582 while (time_out > 0) { 583 if (p_gpm) { 584 MCI_GPM_RECYCLE(p_gpm); 585 p_gpm = NULL; 586 } 587 588 if (more_data != MCI_GPM_MORE) 589 time_out = ar9003_mci_wait_for_interrupt(ah, 590 AR_MCI_INTERRUPT_RX_MSG_RAW, 591 AR_MCI_INTERRUPT_RX_MSG_GPM, 592 time_out); 593 594 if (!time_out) 595 break; 596 597 offset = ar9003_mci_get_next_gpm_offset(ah, &more_data); 598 599 if (offset == MCI_GPM_INVALID) 600 continue; 601 602 p_gpm = (u32 *) (mci->gpm_buf + offset); 603 recv_type = MCI_GPM_TYPE(p_gpm); 604 recv_opcode = MCI_GPM_OPCODE(p_gpm); 605 606 if (MCI_GPM_IS_CAL_TYPE(recv_type)) { 607 if (recv_type == gpm_type) { 608 if ((gpm_type == MCI_GPM_BT_CAL_DONE) && 609 !b_is_bt_cal_done) { 610 gpm_type = MCI_GPM_BT_CAL_GRANT; 611 continue; 612 } 613 break; 614 } 615 } else if ((recv_type == gpm_type) && 616 (recv_opcode == gpm_opcode)) 617 break; 618 619 /* 620 * check if it's cal_grant 621 * 622 * When we're waiting for cal_grant in reset routine, 623 * it's possible that BT sends out cal_request at the 624 * same time. Since BT's calibration doesn't happen 625 * that often, we'll let BT completes calibration then 626 * we continue to wait for cal_grant from BT. 627 * Orginal: Wait BT_CAL_GRANT. 628 * New: Receive BT_CAL_REQ -> send WLAN_CAL_GRANT->wait 629 * BT_CAL_DONE -> Wait BT_CAL_GRANT. 630 */ 631 632 if ((gpm_type == MCI_GPM_BT_CAL_GRANT) && 633 (recv_type == MCI_GPM_BT_CAL_REQ)) { 634 635 u32 payload[4] = {0, 0, 0, 0}; 636 637 gpm_type = MCI_GPM_BT_CAL_DONE; 638 MCI_GPM_SET_CAL_TYPE(payload, 639 MCI_GPM_WLAN_CAL_GRANT); 640 ar9003_mci_send_message(ah, MCI_GPM, 0, payload, 16, 641 false, false); 642 continue; 643 } else { 644 ath_dbg(common, MCI, "MCI GPM subtype not match 0x%x\n", 645 *(p_gpm + 1)); 646 mismatch++; 647 ar9003_mci_process_gpm_extra(ah, recv_type, 648 recv_opcode, p_gpm); 649 } 650 } 651 652 if (p_gpm) { 653 MCI_GPM_RECYCLE(p_gpm); 654 p_gpm = NULL; 655 } 656 657 if (time_out <= 0) 658 time_out = 0; 659 660 while (more_data == MCI_GPM_MORE) { 661 offset = ar9003_mci_get_next_gpm_offset(ah, &more_data); 662 if (offset == MCI_GPM_INVALID) 663 break; 664 665 p_gpm = (u32 *) (mci->gpm_buf + offset); 666 recv_type = MCI_GPM_TYPE(p_gpm); 667 recv_opcode = MCI_GPM_OPCODE(p_gpm); 668 669 if (!MCI_GPM_IS_CAL_TYPE(recv_type)) 670 ar9003_mci_process_gpm_extra(ah, recv_type, 671 recv_opcode, p_gpm); 672 673 MCI_GPM_RECYCLE(p_gpm); 674 } 675 676 return time_out; 677 } 678 679 bool ar9003_mci_start_reset(struct ath_hw *ah, struct ath9k_channel *chan) 680 { 681 struct ath_common *common = ath9k_hw_common(ah); 682 struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci; 683 u32 payload[4] = {0, 0, 0, 0}; 684 685 ar9003_mci_2g5g_changed(ah, IS_CHAN_2GHZ(chan)); 686 687 if (mci_hw->bt_state != MCI_BT_CAL_START) 688 return false; 689 690 mci_hw->bt_state = MCI_BT_CAL; 691 692 /* 693 * MCI FIX: disable mci interrupt here. This is to avoid 694 * SW_MSG_DONE or RX_MSG bits to trigger MCI_INT and 695 * lead to mci_intr reentry. 696 */ 697 ar9003_mci_disable_interrupt(ah); 698 699 MCI_GPM_SET_CAL_TYPE(payload, MCI_GPM_WLAN_CAL_GRANT); 700 ar9003_mci_send_message(ah, MCI_GPM, 0, payload, 701 16, true, false); 702 703 /* Wait BT calibration to be completed for 25ms */ 704 705 if (ar9003_mci_wait_for_gpm(ah, MCI_GPM_BT_CAL_DONE, 706 0, 25000)) 707 ath_dbg(common, MCI, "MCI BT_CAL_DONE received\n"); 708 else 709 ath_dbg(common, MCI, 710 "MCI BT_CAL_DONE not received\n"); 711 712 mci_hw->bt_state = MCI_BT_AWAKE; 713 /* MCI FIX: enable mci interrupt here */ 714 ar9003_mci_enable_interrupt(ah); 715 716 return true; 717 } 718 719 int ar9003_mci_end_reset(struct ath_hw *ah, struct ath9k_channel *chan, 720 struct ath9k_hw_cal_data *caldata) 721 { 722 struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci; 723 724 if (!mci_hw->ready) 725 return 0; 726 727 if (!IS_CHAN_2GHZ(chan) || (mci_hw->bt_state != MCI_BT_SLEEP)) 728 goto exit; 729 730 if (!ar9003_mci_check_int(ah, AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET) && 731 !ar9003_mci_check_int(ah, AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE)) 732 goto exit; 733 734 /* 735 * BT is sleeping. Check if BT wakes up during 736 * WLAN calibration. If BT wakes up during 737 * WLAN calibration, need to go through all 738 * message exchanges again and recal. 739 */ 740 REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, 741 (AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET | 742 AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE)); 743 744 ar9003_mci_remote_reset(ah, true); 745 ar9003_mci_send_sys_waking(ah, true); 746 udelay(1); 747 748 if (IS_CHAN_2GHZ(chan)) 749 ar9003_mci_send_lna_transfer(ah, true); 750 751 mci_hw->bt_state = MCI_BT_AWAKE; 752 753 REG_CLR_BIT(ah, AR_PHY_TIMING4, 754 1 << AR_PHY_TIMING_CONTROL4_DO_GAIN_DC_IQ_CAL_SHIFT); 755 756 if (caldata) { 757 clear_bit(TXIQCAL_DONE, &caldata->cal_flags); 758 clear_bit(TXCLCAL_DONE, &caldata->cal_flags); 759 clear_bit(RTT_DONE, &caldata->cal_flags); 760 } 761 762 if (!ath9k_hw_init_cal(ah, chan)) 763 return -EIO; 764 765 REG_SET_BIT(ah, AR_PHY_TIMING4, 766 1 << AR_PHY_TIMING_CONTROL4_DO_GAIN_DC_IQ_CAL_SHIFT); 767 768 exit: 769 ar9003_mci_enable_interrupt(ah); 770 return 0; 771 } 772 773 static void ar9003_mci_mute_bt(struct ath_hw *ah) 774 { 775 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; 776 777 /* disable all MCI messages */ 778 REG_WRITE(ah, AR_MCI_MSG_ATTRIBUTES_TABLE, 0xffff0000); 779 REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS0, 0xffffffff); 780 REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS1, 0xffffffff); 781 REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS2, 0xffffffff); 782 REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS3, 0xffffffff); 783 REG_SET_BIT(ah, AR_MCI_TX_CTRL, AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE); 784 785 /* wait pending HW messages to flush out */ 786 udelay(10); 787 788 /* 789 * Send LNA_TAKE and SYS_SLEEPING when 790 * 1. reset not after resuming from full sleep 791 * 2. before reset MCI RX, to quiet BT and avoid MCI RX misalignment 792 */ 793 if (MCI_ANT_ARCH_PA_LNA_SHARED(mci)) { 794 ar9003_mci_send_lna_take(ah, true); 795 udelay(5); 796 } 797 798 ar9003_mci_send_sys_sleeping(ah, true); 799 } 800 801 static void ar9003_mci_osla_setup(struct ath_hw *ah, bool enable) 802 { 803 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; 804 u32 thresh; 805 806 if (!enable) { 807 REG_CLR_BIT(ah, AR_BTCOEX_CTRL, 808 AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN); 809 return; 810 } 811 REG_RMW_FIELD(ah, AR_MCI_SCHD_TABLE_2, AR_MCI_SCHD_TABLE_2_HW_BASED, 1); 812 REG_RMW_FIELD(ah, AR_MCI_SCHD_TABLE_2, 813 AR_MCI_SCHD_TABLE_2_MEM_BASED, 1); 814 815 if (AR_SREV_9565(ah)) 816 REG_RMW_FIELD(ah, AR_MCI_MISC, AR_MCI_MISC_HW_FIX_EN, 1); 817 818 if (!(mci->config & ATH_MCI_CONFIG_DISABLE_AGGR_THRESH)) { 819 thresh = MS(mci->config, ATH_MCI_CONFIG_AGGR_THRESH); 820 REG_RMW_FIELD(ah, AR_BTCOEX_CTRL, 821 AR_BTCOEX_CTRL_AGGR_THRESH, thresh); 822 REG_RMW_FIELD(ah, AR_BTCOEX_CTRL, 823 AR_BTCOEX_CTRL_TIME_TO_NEXT_BT_THRESH_EN, 1); 824 } else 825 REG_RMW_FIELD(ah, AR_BTCOEX_CTRL, 826 AR_BTCOEX_CTRL_TIME_TO_NEXT_BT_THRESH_EN, 0); 827 828 REG_RMW_FIELD(ah, AR_BTCOEX_CTRL, 829 AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN, 1); 830 } 831 832 static void ar9003_mci_stat_setup(struct ath_hw *ah) 833 { 834 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; 835 836 if (!AR_SREV_9565(ah)) 837 return; 838 839 if (mci->config & ATH_MCI_CONFIG_MCI_STAT_DBG) { 840 REG_RMW_FIELD(ah, AR_MCI_DBG_CNT_CTRL, 841 AR_MCI_DBG_CNT_CTRL_ENABLE, 1); 842 REG_RMW_FIELD(ah, AR_MCI_DBG_CNT_CTRL, 843 AR_MCI_DBG_CNT_CTRL_BT_LINKID, 844 MCI_STAT_ALL_BT_LINKID); 845 } else { 846 REG_RMW_FIELD(ah, AR_MCI_DBG_CNT_CTRL, 847 AR_MCI_DBG_CNT_CTRL_ENABLE, 0); 848 } 849 } 850 851 static void ar9003_mci_set_btcoex_ctrl_9565_1ANT(struct ath_hw *ah) 852 { 853 u32 regval; 854 855 regval = SM(1, AR_BTCOEX_CTRL_AR9462_MODE) | 856 SM(1, AR_BTCOEX_CTRL_WBTIMER_EN) | 857 SM(1, AR_BTCOEX_CTRL_PA_SHARED) | 858 SM(1, AR_BTCOEX_CTRL_LNA_SHARED) | 859 SM(1, AR_BTCOEX_CTRL_NUM_ANTENNAS) | 860 SM(1, AR_BTCOEX_CTRL_RX_CHAIN_MASK) | 861 SM(0, AR_BTCOEX_CTRL_1_CHAIN_ACK) | 862 SM(0, AR_BTCOEX_CTRL_1_CHAIN_BCN) | 863 SM(0, AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN); 864 865 REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2, 866 AR_BTCOEX_CTRL2_TX_CHAIN_MASK, 0x1); 867 REG_WRITE(ah, AR_BTCOEX_CTRL, regval); 868 } 869 870 static void ar9003_mci_set_btcoex_ctrl_9565_2ANT(struct ath_hw *ah) 871 { 872 u32 regval; 873 874 regval = SM(1, AR_BTCOEX_CTRL_AR9462_MODE) | 875 SM(1, AR_BTCOEX_CTRL_WBTIMER_EN) | 876 SM(0, AR_BTCOEX_CTRL_PA_SHARED) | 877 SM(0, AR_BTCOEX_CTRL_LNA_SHARED) | 878 SM(2, AR_BTCOEX_CTRL_NUM_ANTENNAS) | 879 SM(1, AR_BTCOEX_CTRL_RX_CHAIN_MASK) | 880 SM(0, AR_BTCOEX_CTRL_1_CHAIN_ACK) | 881 SM(0, AR_BTCOEX_CTRL_1_CHAIN_BCN) | 882 SM(0, AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN); 883 884 REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2, 885 AR_BTCOEX_CTRL2_TX_CHAIN_MASK, 0x0); 886 REG_WRITE(ah, AR_BTCOEX_CTRL, regval); 887 } 888 889 static void ar9003_mci_set_btcoex_ctrl_9462(struct ath_hw *ah) 890 { 891 u32 regval; 892 893 regval = SM(1, AR_BTCOEX_CTRL_AR9462_MODE) | 894 SM(1, AR_BTCOEX_CTRL_WBTIMER_EN) | 895 SM(1, AR_BTCOEX_CTRL_PA_SHARED) | 896 SM(1, AR_BTCOEX_CTRL_LNA_SHARED) | 897 SM(2, AR_BTCOEX_CTRL_NUM_ANTENNAS) | 898 SM(3, AR_BTCOEX_CTRL_RX_CHAIN_MASK) | 899 SM(0, AR_BTCOEX_CTRL_1_CHAIN_ACK) | 900 SM(0, AR_BTCOEX_CTRL_1_CHAIN_BCN) | 901 SM(0, AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN); 902 903 REG_WRITE(ah, AR_BTCOEX_CTRL, regval); 904 } 905 906 int ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g, 907 bool is_full_sleep) 908 { 909 struct ath_common *common = ath9k_hw_common(ah); 910 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; 911 u32 regval, i; 912 913 ath_dbg(common, MCI, "MCI Reset (full_sleep = %d, is_2g = %d)\n", 914 is_full_sleep, is_2g); 915 916 if (REG_READ(ah, AR_BTCOEX_CTRL) == 0xdeadbeef) { 917 ath_err(common, "BTCOEX control register is dead\n"); 918 return -EINVAL; 919 } 920 921 /* Program MCI DMA related registers */ 922 REG_WRITE(ah, AR_MCI_GPM_0, mci->gpm_addr); 923 REG_WRITE(ah, AR_MCI_GPM_1, mci->gpm_len); 924 REG_WRITE(ah, AR_MCI_SCHD_TABLE_0, mci->sched_addr); 925 926 /* 927 * To avoid MCI state machine be affected by incoming remote MCI msgs, 928 * MCI mode will be enabled later, right before reset the MCI TX and RX. 929 */ 930 if (AR_SREV_9565(ah)) { 931 u8 ant = MS(mci->config, ATH_MCI_CONFIG_ANT_ARCH); 932 933 if (ant == ATH_MCI_ANT_ARCH_1_ANT_PA_LNA_SHARED) 934 ar9003_mci_set_btcoex_ctrl_9565_1ANT(ah); 935 else 936 ar9003_mci_set_btcoex_ctrl_9565_2ANT(ah); 937 } else { 938 ar9003_mci_set_btcoex_ctrl_9462(ah); 939 } 940 941 if (is_2g && !(mci->config & ATH_MCI_CONFIG_DISABLE_OSLA)) 942 ar9003_mci_osla_setup(ah, true); 943 else 944 ar9003_mci_osla_setup(ah, false); 945 946 REG_SET_BIT(ah, AR_PHY_GLB_CONTROL, 947 AR_BTCOEX_CTRL_SPDT_ENABLE); 948 REG_RMW_FIELD(ah, AR_BTCOEX_CTRL3, 949 AR_BTCOEX_CTRL3_CONT_INFO_TIMEOUT, 20); 950 951 REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2, AR_BTCOEX_CTRL2_RX_DEWEIGHT, 0); 952 REG_RMW_FIELD(ah, AR_PCU_MISC, AR_PCU_BT_ANT_PREVENT_RX, 0); 953 954 /* Set the time out to 3.125ms (5 BT slots) */ 955 REG_RMW_FIELD(ah, AR_BTCOEX_WL_LNA, AR_BTCOEX_WL_LNA_TIMEOUT, 0x3D090); 956 957 /* concurrent tx priority */ 958 if (mci->config & ATH_MCI_CONFIG_CONCUR_TX) { 959 REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2, 960 AR_BTCOEX_CTRL2_DESC_BASED_TXPWR_ENABLE, 0); 961 REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2, 962 AR_BTCOEX_CTRL2_TXPWR_THRESH, 0x7f); 963 REG_RMW_FIELD(ah, AR_BTCOEX_CTRL, 964 AR_BTCOEX_CTRL_REDUCE_TXPWR, 0); 965 for (i = 0; i < 8; i++) 966 REG_WRITE(ah, AR_BTCOEX_MAX_TXPWR(i), 0x7f7f7f7f); 967 } 968 969 regval = MS(mci->config, ATH_MCI_CONFIG_CLK_DIV); 970 REG_RMW_FIELD(ah, AR_MCI_TX_CTRL, AR_MCI_TX_CTRL_CLK_DIV, regval); 971 REG_SET_BIT(ah, AR_BTCOEX_CTRL, AR_BTCOEX_CTRL_MCI_MODE_EN); 972 973 /* Resetting the Rx and Tx paths of MCI */ 974 regval = REG_READ(ah, AR_MCI_COMMAND2); 975 regval |= SM(1, AR_MCI_COMMAND2_RESET_TX); 976 REG_WRITE(ah, AR_MCI_COMMAND2, regval); 977 978 udelay(1); 979 980 regval &= ~SM(1, AR_MCI_COMMAND2_RESET_TX); 981 REG_WRITE(ah, AR_MCI_COMMAND2, regval); 982 983 if (is_full_sleep) { 984 ar9003_mci_mute_bt(ah); 985 udelay(100); 986 } 987 988 /* Check pending GPM msg before MCI Reset Rx */ 989 ar9003_mci_check_gpm_offset(ah); 990 991 regval |= SM(1, AR_MCI_COMMAND2_RESET_RX); 992 REG_WRITE(ah, AR_MCI_COMMAND2, regval); 993 udelay(1); 994 regval &= ~SM(1, AR_MCI_COMMAND2_RESET_RX); 995 REG_WRITE(ah, AR_MCI_COMMAND2, regval); 996 997 /* Init GPM offset after MCI Reset Rx */ 998 ar9003_mci_state(ah, MCI_STATE_INIT_GPM_OFFSET); 999 1000 REG_WRITE(ah, AR_MCI_MSG_ATTRIBUTES_TABLE, 1001 (SM(0xe801, AR_MCI_MSG_ATTRIBUTES_TABLE_INVALID_HDR) | 1002 SM(0x0000, AR_MCI_MSG_ATTRIBUTES_TABLE_CHECKSUM))); 1003 1004 if (MCI_ANT_ARCH_PA_LNA_SHARED(mci)) 1005 REG_CLR_BIT(ah, AR_MCI_TX_CTRL, 1006 AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE); 1007 else 1008 REG_SET_BIT(ah, AR_MCI_TX_CTRL, 1009 AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE); 1010 1011 ar9003_mci_observation_set_up(ah); 1012 1013 mci->ready = true; 1014 ar9003_mci_prep_interface(ah); 1015 ar9003_mci_stat_setup(ah); 1016 1017 if (en_int) 1018 ar9003_mci_enable_interrupt(ah); 1019 1020 if (ath9k_hw_is_aic_enabled(ah)) 1021 ar9003_aic_start_normal(ah); 1022 1023 return 0; 1024 } 1025 1026 void ar9003_mci_stop_bt(struct ath_hw *ah, bool save_fullsleep) 1027 { 1028 struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci; 1029 1030 ar9003_mci_disable_interrupt(ah); 1031 1032 if (mci_hw->ready && !save_fullsleep) { 1033 ar9003_mci_mute_bt(ah); 1034 udelay(20); 1035 REG_WRITE(ah, AR_BTCOEX_CTRL, 0); 1036 } 1037 1038 mci_hw->bt_state = MCI_BT_SLEEP; 1039 mci_hw->ready = false; 1040 } 1041 1042 static void ar9003_mci_send_2g5g_status(struct ath_hw *ah, bool wait_done) 1043 { 1044 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; 1045 u32 new_flags, to_set, to_clear; 1046 1047 if (!mci->update_2g5g || (mci->bt_state == MCI_BT_SLEEP)) 1048 return; 1049 1050 if (mci->is_2g) { 1051 new_flags = MCI_2G_FLAGS; 1052 to_clear = MCI_2G_FLAGS_CLEAR_MASK; 1053 to_set = MCI_2G_FLAGS_SET_MASK; 1054 } else { 1055 new_flags = MCI_5G_FLAGS; 1056 to_clear = MCI_5G_FLAGS_CLEAR_MASK; 1057 to_set = MCI_5G_FLAGS_SET_MASK; 1058 } 1059 1060 if (to_clear) 1061 ar9003_mci_send_coex_bt_flags(ah, wait_done, 1062 MCI_GPM_COEX_BT_FLAGS_CLEAR, 1063 to_clear); 1064 if (to_set) 1065 ar9003_mci_send_coex_bt_flags(ah, wait_done, 1066 MCI_GPM_COEX_BT_FLAGS_SET, 1067 to_set); 1068 } 1069 1070 static void ar9003_mci_queue_unsent_gpm(struct ath_hw *ah, u8 header, 1071 u32 *payload, bool queue) 1072 { 1073 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; 1074 u8 type, opcode; 1075 1076 /* check if the message is to be queued */ 1077 if (header != MCI_GPM) 1078 return; 1079 1080 type = MCI_GPM_TYPE(payload); 1081 opcode = MCI_GPM_OPCODE(payload); 1082 1083 if (type != MCI_GPM_COEX_AGENT) 1084 return; 1085 1086 switch (opcode) { 1087 case MCI_GPM_COEX_BT_UPDATE_FLAGS: 1088 if (*(((u8 *)payload) + MCI_GPM_COEX_B_BT_FLAGS_OP) == 1089 MCI_GPM_COEX_BT_FLAGS_READ) 1090 break; 1091 1092 mci->update_2g5g = queue; 1093 1094 break; 1095 case MCI_GPM_COEX_WLAN_CHANNELS: 1096 mci->wlan_channels_update = queue; 1097 break; 1098 case MCI_GPM_COEX_HALT_BT_GPM: 1099 if (*(((u8 *)payload) + MCI_GPM_COEX_B_HALT_STATE) == 1100 MCI_GPM_COEX_BT_GPM_UNHALT) { 1101 mci->unhalt_bt_gpm = queue; 1102 1103 if (!queue) 1104 mci->halted_bt_gpm = false; 1105 } 1106 1107 if (*(((u8 *)payload) + MCI_GPM_COEX_B_HALT_STATE) == 1108 MCI_GPM_COEX_BT_GPM_HALT) { 1109 1110 mci->halted_bt_gpm = !queue; 1111 } 1112 1113 break; 1114 default: 1115 break; 1116 } 1117 } 1118 1119 void ar9003_mci_2g5g_switch(struct ath_hw *ah, bool force) 1120 { 1121 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; 1122 1123 if (!mci->update_2g5g && !force) 1124 return; 1125 1126 if (mci->is_2g) { 1127 ar9003_mci_send_2g5g_status(ah, true); 1128 ar9003_mci_send_lna_transfer(ah, true); 1129 udelay(5); 1130 1131 REG_CLR_BIT(ah, AR_MCI_TX_CTRL, 1132 AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE); 1133 REG_CLR_BIT(ah, AR_PHY_GLB_CONTROL, 1134 AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL); 1135 1136 if (!(mci->config & ATH_MCI_CONFIG_DISABLE_OSLA)) 1137 ar9003_mci_osla_setup(ah, true); 1138 1139 if (AR_SREV_9462(ah)) 1140 REG_WRITE(ah, AR_SELFGEN_MASK, 0x02); 1141 } else { 1142 ar9003_mci_send_lna_take(ah, true); 1143 udelay(5); 1144 1145 REG_SET_BIT(ah, AR_MCI_TX_CTRL, 1146 AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE); 1147 REG_SET_BIT(ah, AR_PHY_GLB_CONTROL, 1148 AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL); 1149 1150 ar9003_mci_osla_setup(ah, false); 1151 ar9003_mci_send_2g5g_status(ah, true); 1152 } 1153 } 1154 1155 bool ar9003_mci_send_message(struct ath_hw *ah, u8 header, u32 flag, 1156 u32 *payload, u8 len, bool wait_done, 1157 bool check_bt) 1158 { 1159 struct ath_common *common = ath9k_hw_common(ah); 1160 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; 1161 bool msg_sent = false; 1162 u32 regval; 1163 u32 saved_mci_int_en; 1164 int i; 1165 1166 saved_mci_int_en = REG_READ(ah, AR_MCI_INTERRUPT_EN); 1167 regval = REG_READ(ah, AR_BTCOEX_CTRL); 1168 1169 if ((regval == 0xdeadbeef) || !(regval & AR_BTCOEX_CTRL_MCI_MODE_EN)) { 1170 ath_dbg(common, MCI, 1171 "MCI Not sending 0x%x. MCI is not enabled. full_sleep = %d\n", 1172 header, (ah->power_mode == ATH9K_PM_FULL_SLEEP) ? 1 : 0); 1173 ar9003_mci_queue_unsent_gpm(ah, header, payload, true); 1174 return false; 1175 } else if (check_bt && (mci->bt_state == MCI_BT_SLEEP)) { 1176 ath_dbg(common, MCI, 1177 "MCI Don't send message 0x%x. BT is in sleep state\n", 1178 header); 1179 ar9003_mci_queue_unsent_gpm(ah, header, payload, true); 1180 return false; 1181 } 1182 1183 if (wait_done) 1184 REG_WRITE(ah, AR_MCI_INTERRUPT_EN, 0); 1185 1186 /* Need to clear SW_MSG_DONE raw bit before wait */ 1187 1188 REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, 1189 (AR_MCI_INTERRUPT_SW_MSG_DONE | 1190 AR_MCI_INTERRUPT_MSG_FAIL_MASK)); 1191 1192 if (payload) { 1193 for (i = 0; (i * 4) < len; i++) 1194 REG_WRITE(ah, (AR_MCI_TX_PAYLOAD0 + i * 4), 1195 *(payload + i)); 1196 } 1197 1198 REG_WRITE(ah, AR_MCI_COMMAND0, 1199 (SM((flag & MCI_FLAG_DISABLE_TIMESTAMP), 1200 AR_MCI_COMMAND0_DISABLE_TIMESTAMP) | 1201 SM(len, AR_MCI_COMMAND0_LEN) | 1202 SM(header, AR_MCI_COMMAND0_HEADER))); 1203 1204 if (wait_done && 1205 !(ar9003_mci_wait_for_interrupt(ah, AR_MCI_INTERRUPT_RAW, 1206 AR_MCI_INTERRUPT_SW_MSG_DONE, 500))) 1207 ar9003_mci_queue_unsent_gpm(ah, header, payload, true); 1208 else { 1209 ar9003_mci_queue_unsent_gpm(ah, header, payload, false); 1210 msg_sent = true; 1211 } 1212 1213 if (wait_done) 1214 REG_WRITE(ah, AR_MCI_INTERRUPT_EN, saved_mci_int_en); 1215 1216 return msg_sent; 1217 } 1218 EXPORT_SYMBOL(ar9003_mci_send_message); 1219 1220 void ar9003_mci_init_cal_req(struct ath_hw *ah, bool *is_reusable) 1221 { 1222 struct ath_common *common = ath9k_hw_common(ah); 1223 struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci; 1224 u32 pld[4] = {0, 0, 0, 0}; 1225 1226 if ((mci_hw->bt_state != MCI_BT_AWAKE) || 1227 (mci_hw->config & ATH_MCI_CONFIG_DISABLE_MCI_CAL)) 1228 return; 1229 1230 MCI_GPM_SET_CAL_TYPE(pld, MCI_GPM_WLAN_CAL_REQ); 1231 pld[MCI_GPM_WLAN_CAL_W_SEQUENCE] = mci_hw->wlan_cal_seq++; 1232 1233 ar9003_mci_send_message(ah, MCI_GPM, 0, pld, 16, true, false); 1234 1235 if (ar9003_mci_wait_for_gpm(ah, MCI_GPM_BT_CAL_GRANT, 0, 50000)) { 1236 ath_dbg(common, MCI, "MCI BT_CAL_GRANT received\n"); 1237 } else { 1238 *is_reusable = false; 1239 ath_dbg(common, MCI, "MCI BT_CAL_GRANT not received\n"); 1240 } 1241 } 1242 1243 void ar9003_mci_init_cal_done(struct ath_hw *ah) 1244 { 1245 struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci; 1246 u32 pld[4] = {0, 0, 0, 0}; 1247 1248 if ((mci_hw->bt_state != MCI_BT_AWAKE) || 1249 (mci_hw->config & ATH_MCI_CONFIG_DISABLE_MCI_CAL)) 1250 return; 1251 1252 MCI_GPM_SET_CAL_TYPE(pld, MCI_GPM_WLAN_CAL_DONE); 1253 pld[MCI_GPM_WLAN_CAL_W_SEQUENCE] = mci_hw->wlan_cal_done++; 1254 ar9003_mci_send_message(ah, MCI_GPM, 0, pld, 16, true, false); 1255 } 1256 1257 int ar9003_mci_setup(struct ath_hw *ah, u32 gpm_addr, void *gpm_buf, 1258 u16 len, u32 sched_addr) 1259 { 1260 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; 1261 1262 mci->gpm_addr = gpm_addr; 1263 mci->gpm_buf = gpm_buf; 1264 mci->gpm_len = len; 1265 mci->sched_addr = sched_addr; 1266 1267 return ar9003_mci_reset(ah, true, true, true); 1268 } 1269 EXPORT_SYMBOL(ar9003_mci_setup); 1270 1271 void ar9003_mci_cleanup(struct ath_hw *ah) 1272 { 1273 /* Turn off MCI and Jupiter mode. */ 1274 REG_WRITE(ah, AR_BTCOEX_CTRL, 0x00); 1275 ar9003_mci_disable_interrupt(ah); 1276 } 1277 EXPORT_SYMBOL(ar9003_mci_cleanup); 1278 1279 u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type) 1280 { 1281 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; 1282 u32 value = 0, tsf; 1283 u8 query_type; 1284 1285 switch (state_type) { 1286 case MCI_STATE_ENABLE: 1287 if (mci->ready) { 1288 value = REG_READ(ah, AR_BTCOEX_CTRL); 1289 1290 if ((value == 0xdeadbeef) || (value == 0xffffffff)) 1291 value = 0; 1292 } 1293 value &= AR_BTCOEX_CTRL_MCI_MODE_EN; 1294 break; 1295 case MCI_STATE_INIT_GPM_OFFSET: 1296 value = MS(REG_READ(ah, AR_MCI_GPM_1), AR_MCI_GPM_WRITE_PTR); 1297 1298 if (value < mci->gpm_len) 1299 mci->gpm_idx = value; 1300 else 1301 mci->gpm_idx = 0; 1302 break; 1303 case MCI_STATE_LAST_SCHD_MSG_OFFSET: 1304 value = MS(REG_READ(ah, AR_MCI_RX_STATUS), 1305 AR_MCI_RX_LAST_SCHD_MSG_INDEX); 1306 /* Make it in bytes */ 1307 value <<= 4; 1308 break; 1309 case MCI_STATE_REMOTE_SLEEP: 1310 value = MS(REG_READ(ah, AR_MCI_RX_STATUS), 1311 AR_MCI_RX_REMOTE_SLEEP) ? 1312 MCI_BT_SLEEP : MCI_BT_AWAKE; 1313 break; 1314 case MCI_STATE_SET_BT_AWAKE: 1315 mci->bt_state = MCI_BT_AWAKE; 1316 ar9003_mci_send_coex_version_query(ah, true); 1317 ar9003_mci_send_coex_wlan_channels(ah, true); 1318 1319 if (mci->unhalt_bt_gpm) 1320 ar9003_mci_send_coex_halt_bt_gpm(ah, false, true); 1321 1322 ar9003_mci_2g5g_switch(ah, false); 1323 break; 1324 case MCI_STATE_RESET_REQ_WAKE: 1325 ar9003_mci_reset_req_wakeup(ah); 1326 mci->update_2g5g = true; 1327 1328 if (mci->config & ATH_MCI_CONFIG_MCI_OBS_MASK) { 1329 /* Check if we still have control of the GPIOs */ 1330 if ((REG_READ(ah, AR_GLB_GPIO_CONTROL) & 1331 ATH_MCI_CONFIG_MCI_OBS_GPIO) != 1332 ATH_MCI_CONFIG_MCI_OBS_GPIO) { 1333 ar9003_mci_observation_set_up(ah); 1334 } 1335 } 1336 break; 1337 case MCI_STATE_SEND_WLAN_COEX_VERSION: 1338 ar9003_mci_send_coex_version_response(ah, true); 1339 break; 1340 case MCI_STATE_SEND_VERSION_QUERY: 1341 ar9003_mci_send_coex_version_query(ah, true); 1342 break; 1343 case MCI_STATE_SEND_STATUS_QUERY: 1344 query_type = MCI_GPM_COEX_QUERY_BT_TOPOLOGY; 1345 ar9003_mci_send_coex_bt_status_query(ah, true, query_type); 1346 break; 1347 case MCI_STATE_RECOVER_RX: 1348 tsf = ath9k_hw_gettsf32(ah); 1349 if ((tsf - mci->last_recovery) <= MCI_RECOVERY_DUR_TSF) { 1350 ath_dbg(ath9k_hw_common(ah), MCI, 1351 "(MCI) ignore Rx recovery\n"); 1352 break; 1353 } 1354 ath_dbg(ath9k_hw_common(ah), MCI, "(MCI) RECOVER RX\n"); 1355 mci->last_recovery = tsf; 1356 ar9003_mci_prep_interface(ah); 1357 mci->query_bt = true; 1358 mci->need_flush_btinfo = true; 1359 ar9003_mci_send_coex_wlan_channels(ah, true); 1360 ar9003_mci_2g5g_switch(ah, false); 1361 break; 1362 case MCI_STATE_NEED_FTP_STOMP: 1363 value = !(mci->config & ATH_MCI_CONFIG_DISABLE_FTP_STOMP); 1364 break; 1365 case MCI_STATE_NEED_FLUSH_BT_INFO: 1366 value = (!mci->unhalt_bt_gpm && mci->need_flush_btinfo) ? 1 : 0; 1367 mci->need_flush_btinfo = false; 1368 break; 1369 case MCI_STATE_AIC_CAL: 1370 if (ath9k_hw_is_aic_enabled(ah)) 1371 value = ar9003_aic_calibration(ah); 1372 break; 1373 case MCI_STATE_AIC_START: 1374 if (ath9k_hw_is_aic_enabled(ah)) 1375 ar9003_aic_start_normal(ah); 1376 break; 1377 case MCI_STATE_AIC_CAL_RESET: 1378 if (ath9k_hw_is_aic_enabled(ah)) 1379 value = ar9003_aic_cal_reset(ah); 1380 break; 1381 case MCI_STATE_AIC_CAL_SINGLE: 1382 if (ath9k_hw_is_aic_enabled(ah)) 1383 value = ar9003_aic_calibration_single(ah); 1384 break; 1385 default: 1386 break; 1387 } 1388 1389 return value; 1390 } 1391 EXPORT_SYMBOL(ar9003_mci_state); 1392 1393 void ar9003_mci_bt_gain_ctrl(struct ath_hw *ah) 1394 { 1395 struct ath_common *common = ath9k_hw_common(ah); 1396 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; 1397 1398 ath_dbg(common, MCI, "Give LNA and SPDT control to BT\n"); 1399 1400 ar9003_mci_send_lna_take(ah, true); 1401 udelay(50); 1402 1403 REG_SET_BIT(ah, AR_PHY_GLB_CONTROL, AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL); 1404 mci->is_2g = false; 1405 mci->update_2g5g = true; 1406 ar9003_mci_send_2g5g_status(ah, true); 1407 1408 /* Force another 2g5g update at next scanning */ 1409 mci->update_2g5g = true; 1410 } 1411 1412 void ar9003_mci_set_power_awake(struct ath_hw *ah) 1413 { 1414 u32 btcoex_ctrl2, diag_sw; 1415 int i; 1416 u8 lna_ctrl, bt_sleep; 1417 1418 for (i = 0; i < AH_WAIT_TIMEOUT; i++) { 1419 btcoex_ctrl2 = REG_READ(ah, AR_BTCOEX_CTRL2); 1420 if (btcoex_ctrl2 != 0xdeadbeef) 1421 break; 1422 udelay(AH_TIME_QUANTUM); 1423 } 1424 REG_WRITE(ah, AR_BTCOEX_CTRL2, (btcoex_ctrl2 | BIT(23))); 1425 1426 for (i = 0; i < AH_WAIT_TIMEOUT; i++) { 1427 diag_sw = REG_READ(ah, AR_DIAG_SW); 1428 if (diag_sw != 0xdeadbeef) 1429 break; 1430 udelay(AH_TIME_QUANTUM); 1431 } 1432 REG_WRITE(ah, AR_DIAG_SW, (diag_sw | BIT(27) | BIT(19) | BIT(18))); 1433 lna_ctrl = REG_READ(ah, AR_OBS_BUS_CTRL) & 0x3; 1434 bt_sleep = MS(REG_READ(ah, AR_MCI_RX_STATUS), AR_MCI_RX_REMOTE_SLEEP); 1435 1436 REG_WRITE(ah, AR_BTCOEX_CTRL2, btcoex_ctrl2); 1437 REG_WRITE(ah, AR_DIAG_SW, diag_sw); 1438 1439 if (bt_sleep && (lna_ctrl == 2)) { 1440 REG_SET_BIT(ah, AR_BTCOEX_RC, 0x1); 1441 REG_CLR_BIT(ah, AR_BTCOEX_RC, 0x1); 1442 udelay(50); 1443 } 1444 } 1445 1446 void ar9003_mci_check_gpm_offset(struct ath_hw *ah) 1447 { 1448 struct ath_common *common = ath9k_hw_common(ah); 1449 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; 1450 u32 offset; 1451 1452 /* 1453 * This should only be called before "MAC Warm Reset" or "MCI Reset Rx". 1454 */ 1455 offset = MS(REG_READ(ah, AR_MCI_GPM_1), AR_MCI_GPM_WRITE_PTR); 1456 if (mci->gpm_idx == offset) 1457 return; 1458 ath_dbg(common, MCI, "GPM cached write pointer mismatch %d %d\n", 1459 mci->gpm_idx, offset); 1460 mci->query_bt = true; 1461 mci->need_flush_btinfo = true; 1462 mci->gpm_idx = 0; 1463 } 1464 1465 u32 ar9003_mci_get_next_gpm_offset(struct ath_hw *ah, u32 *more) 1466 { 1467 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; 1468 u32 offset, more_gpm = 0, gpm_ptr; 1469 1470 /* 1471 * This could be useful to avoid new GPM message interrupt which 1472 * may lead to spurious interrupt after power sleep, or multiple 1473 * entry of ath_mci_intr(). 1474 * Adding empty GPM check by returning HAL_MCI_GPM_INVALID can 1475 * alleviate this effect, but clearing GPM RX interrupt bit is 1476 * safe, because whether this is called from hw or driver code 1477 * there must be an interrupt bit set/triggered initially 1478 */ 1479 REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, 1480 AR_MCI_INTERRUPT_RX_MSG_GPM); 1481 1482 gpm_ptr = MS(REG_READ(ah, AR_MCI_GPM_1), AR_MCI_GPM_WRITE_PTR); 1483 offset = gpm_ptr; 1484 1485 if (!offset) 1486 offset = mci->gpm_len - 1; 1487 else if (offset >= mci->gpm_len) { 1488 if (offset != 0xFFFF) 1489 offset = 0; 1490 } else { 1491 offset--; 1492 } 1493 1494 if ((offset == 0xFFFF) || (gpm_ptr == mci->gpm_idx)) { 1495 offset = MCI_GPM_INVALID; 1496 more_gpm = MCI_GPM_NOMORE; 1497 goto out; 1498 } 1499 for (;;) { 1500 u32 temp_index; 1501 1502 /* skip reserved GPM if any */ 1503 1504 if (offset != mci->gpm_idx) 1505 more_gpm = MCI_GPM_MORE; 1506 else 1507 more_gpm = MCI_GPM_NOMORE; 1508 1509 temp_index = mci->gpm_idx; 1510 1511 if (temp_index >= mci->gpm_len) 1512 temp_index = 0; 1513 1514 mci->gpm_idx++; 1515 1516 if (mci->gpm_idx >= mci->gpm_len) 1517 mci->gpm_idx = 0; 1518 1519 if (ar9003_mci_is_gpm_valid(ah, temp_index)) { 1520 offset = temp_index; 1521 break; 1522 } 1523 1524 if (more_gpm == MCI_GPM_NOMORE) { 1525 offset = MCI_GPM_INVALID; 1526 break; 1527 } 1528 } 1529 1530 if (offset != MCI_GPM_INVALID) 1531 offset <<= 4; 1532 out: 1533 if (more) 1534 *more = more_gpm; 1535 1536 return offset; 1537 } 1538 EXPORT_SYMBOL(ar9003_mci_get_next_gpm_offset); 1539 1540 void ar9003_mci_set_bt_version(struct ath_hw *ah, u8 major, u8 minor) 1541 { 1542 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; 1543 1544 mci->bt_ver_major = major; 1545 mci->bt_ver_minor = minor; 1546 mci->bt_version_known = true; 1547 ath_dbg(ath9k_hw_common(ah), MCI, "MCI BT version set: %d.%d\n", 1548 mci->bt_ver_major, mci->bt_ver_minor); 1549 } 1550 EXPORT_SYMBOL(ar9003_mci_set_bt_version); 1551 1552 void ar9003_mci_send_wlan_channels(struct ath_hw *ah) 1553 { 1554 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; 1555 1556 mci->wlan_channels_update = true; 1557 ar9003_mci_send_coex_wlan_channels(ah, true); 1558 } 1559 EXPORT_SYMBOL(ar9003_mci_send_wlan_channels); 1560 1561 u16 ar9003_mci_get_max_txpower(struct ath_hw *ah, u8 ctlmode) 1562 { 1563 if (!ah->btcoex_hw.mci.concur_tx) 1564 goto out; 1565 1566 if (ctlmode == CTL_2GHT20) 1567 return ATH_BTCOEX_HT20_MAX_TXPOWER; 1568 else if (ctlmode == CTL_2GHT40) 1569 return ATH_BTCOEX_HT40_MAX_TXPOWER; 1570 1571 out: 1572 return -1; 1573 } 1574