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_gpio_request_out(ah, 3, NULL, 431 AR_GPIO_OUTPUT_MUX_AS_MCI_WLAN_DATA); 432 ath9k_hw_gpio_request_out(ah, 2, NULL, 433 AR_GPIO_OUTPUT_MUX_AS_MCI_WLAN_CLK); 434 ath9k_hw_gpio_request_out(ah, 1, NULL, 435 AR_GPIO_OUTPUT_MUX_AS_MCI_BT_DATA); 436 ath9k_hw_gpio_request_out(ah, 0, NULL, 437 AR_GPIO_OUTPUT_MUX_AS_MCI_BT_CLK); 438 } else if (mci->config & ATH_MCI_CONFIG_MCI_OBS_TXRX) { 439 ath9k_hw_gpio_request_out(ah, 3, NULL, 440 AR_GPIO_OUTPUT_MUX_AS_WL_IN_TX); 441 ath9k_hw_gpio_request_out(ah, 2, NULL, 442 AR_GPIO_OUTPUT_MUX_AS_WL_IN_RX); 443 ath9k_hw_gpio_request_out(ah, 1, NULL, 444 AR_GPIO_OUTPUT_MUX_AS_BT_IN_TX); 445 ath9k_hw_gpio_request_out(ah, 0, NULL, 446 AR_GPIO_OUTPUT_MUX_AS_BT_IN_RX); 447 ath9k_hw_gpio_request_out(ah, 5, NULL, 448 AR_GPIO_OUTPUT_MUX_AS_OUTPUT); 449 } else if (mci->config & ATH_MCI_CONFIG_MCI_OBS_BT) { 450 ath9k_hw_gpio_request_out(ah, 3, NULL, 451 AR_GPIO_OUTPUT_MUX_AS_BT_IN_TX); 452 ath9k_hw_gpio_request_out(ah, 2, NULL, 453 AR_GPIO_OUTPUT_MUX_AS_BT_IN_RX); 454 ath9k_hw_gpio_request_out(ah, 1, NULL, 455 AR_GPIO_OUTPUT_MUX_AS_MCI_BT_DATA); 456 ath9k_hw_gpio_request_out(ah, 0, NULL, 457 AR_GPIO_OUTPUT_MUX_AS_MCI_BT_CLK); 458 } else 459 return; 460 461 REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE); 462 463 REG_RMW_FIELD(ah, AR_PHY_GLB_CONTROL, AR_GLB_DS_JTAG_DISABLE, 1); 464 REG_RMW_FIELD(ah, AR_PHY_GLB_CONTROL, AR_GLB_WLAN_UART_INTF_EN, 0); 465 REG_SET_BIT(ah, AR_GLB_GPIO_CONTROL, ATH_MCI_CONFIG_MCI_OBS_GPIO); 466 467 REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2, AR_BTCOEX_CTRL2_GPIO_OBS_SEL, 0); 468 REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2, AR_BTCOEX_CTRL2_MAC_BB_OBS_SEL, 1); 469 REG_WRITE(ah, AR_OBS, 0x4b); 470 REG_RMW_FIELD(ah, AR_DIAG_SW, AR_DIAG_OBS_PT_SEL1, 0x03); 471 REG_RMW_FIELD(ah, AR_DIAG_SW, AR_DIAG_OBS_PT_SEL2, 0x01); 472 REG_RMW_FIELD(ah, AR_MACMISC, AR_MACMISC_MISC_OBS_BUS_LSB, 0x02); 473 REG_RMW_FIELD(ah, AR_MACMISC, AR_MACMISC_MISC_OBS_BUS_MSB, 0x03); 474 REG_RMW_FIELD(ah, AR_PHY_TEST_CTL_STATUS, 475 AR_PHY_TEST_CTL_DEBUGPORT_SEL, 0x07); 476 } 477 478 static bool ar9003_mci_send_coex_bt_flags(struct ath_hw *ah, bool wait_done, 479 u8 opcode, u32 bt_flags) 480 { 481 u32 pld[4] = {0, 0, 0, 0}; 482 483 MCI_GPM_SET_TYPE_OPCODE(pld, MCI_GPM_COEX_AGENT, 484 MCI_GPM_COEX_BT_UPDATE_FLAGS); 485 486 *(((u8 *)pld) + MCI_GPM_COEX_B_BT_FLAGS_OP) = opcode; 487 *(((u8 *)pld) + MCI_GPM_COEX_W_BT_FLAGS + 0) = bt_flags & 0xFF; 488 *(((u8 *)pld) + MCI_GPM_COEX_W_BT_FLAGS + 1) = (bt_flags >> 8) & 0xFF; 489 *(((u8 *)pld) + MCI_GPM_COEX_W_BT_FLAGS + 2) = (bt_flags >> 16) & 0xFF; 490 *(((u8 *)pld) + MCI_GPM_COEX_W_BT_FLAGS + 3) = (bt_flags >> 24) & 0xFF; 491 492 return ar9003_mci_send_message(ah, MCI_GPM, 0, pld, 16, 493 wait_done, true); 494 } 495 496 static void ar9003_mci_sync_bt_state(struct ath_hw *ah) 497 { 498 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; 499 u32 cur_bt_state; 500 501 cur_bt_state = ar9003_mci_state(ah, MCI_STATE_REMOTE_SLEEP); 502 503 if (mci->bt_state != cur_bt_state) 504 mci->bt_state = cur_bt_state; 505 506 if (mci->bt_state != MCI_BT_SLEEP) { 507 508 ar9003_mci_send_coex_version_query(ah, true); 509 ar9003_mci_send_coex_wlan_channels(ah, true); 510 511 if (mci->unhalt_bt_gpm == true) 512 ar9003_mci_send_coex_halt_bt_gpm(ah, false, true); 513 } 514 } 515 516 void ar9003_mci_check_bt(struct ath_hw *ah) 517 { 518 struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci; 519 520 if (!mci_hw->ready) 521 return; 522 523 /* 524 * check BT state again to make 525 * sure it's not changed. 526 */ 527 ar9003_mci_sync_bt_state(ah); 528 ar9003_mci_2g5g_switch(ah, true); 529 530 if ((mci_hw->bt_state == MCI_BT_AWAKE) && 531 (mci_hw->query_bt == true)) { 532 mci_hw->need_flush_btinfo = true; 533 } 534 } 535 536 static void ar9003_mci_process_gpm_extra(struct ath_hw *ah, u8 gpm_type, 537 u8 gpm_opcode, u32 *p_gpm) 538 { 539 struct ath_common *common = ath9k_hw_common(ah); 540 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; 541 u8 *p_data = (u8 *) p_gpm; 542 543 if (gpm_type != MCI_GPM_COEX_AGENT) 544 return; 545 546 switch (gpm_opcode) { 547 case MCI_GPM_COEX_VERSION_QUERY: 548 ath_dbg(common, MCI, "MCI Recv GPM COEX Version Query\n"); 549 ar9003_mci_send_coex_version_response(ah, true); 550 break; 551 case MCI_GPM_COEX_VERSION_RESPONSE: 552 ath_dbg(common, MCI, "MCI Recv GPM COEX Version Response\n"); 553 mci->bt_ver_major = 554 *(p_data + MCI_GPM_COEX_B_MAJOR_VERSION); 555 mci->bt_ver_minor = 556 *(p_data + MCI_GPM_COEX_B_MINOR_VERSION); 557 mci->bt_version_known = true; 558 ath_dbg(common, MCI, "MCI BT Coex version: %d.%d\n", 559 mci->bt_ver_major, mci->bt_ver_minor); 560 break; 561 case MCI_GPM_COEX_STATUS_QUERY: 562 ath_dbg(common, MCI, 563 "MCI Recv GPM COEX Status Query = 0x%02X\n", 564 *(p_data + MCI_GPM_COEX_B_WLAN_BITMAP)); 565 mci->wlan_channels_update = true; 566 ar9003_mci_send_coex_wlan_channels(ah, true); 567 break; 568 case MCI_GPM_COEX_BT_PROFILE_INFO: 569 mci->query_bt = true; 570 ath_dbg(common, MCI, "MCI Recv GPM COEX BT_Profile_Info\n"); 571 break; 572 case MCI_GPM_COEX_BT_STATUS_UPDATE: 573 mci->query_bt = true; 574 ath_dbg(common, MCI, 575 "MCI Recv GPM COEX BT_Status_Update SEQ=%d (drop&query)\n", 576 *(p_gpm + 3)); 577 break; 578 default: 579 break; 580 } 581 } 582 583 static u32 ar9003_mci_wait_for_gpm(struct ath_hw *ah, u8 gpm_type, 584 u8 gpm_opcode, int time_out) 585 { 586 struct ath_common *common = ath9k_hw_common(ah); 587 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; 588 u32 *p_gpm = NULL, more_data; 589 u32 offset; 590 u8 recv_type = 0, recv_opcode = 0; 591 bool b_is_bt_cal_done = (gpm_type == MCI_GPM_BT_CAL_DONE); 592 593 more_data = time_out ? MCI_GPM_NOMORE : MCI_GPM_MORE; 594 595 while (time_out > 0) { 596 if (p_gpm) { 597 MCI_GPM_RECYCLE(p_gpm); 598 p_gpm = NULL; 599 } 600 601 if (more_data != MCI_GPM_MORE) 602 time_out = ar9003_mci_wait_for_interrupt(ah, 603 AR_MCI_INTERRUPT_RX_MSG_RAW, 604 AR_MCI_INTERRUPT_RX_MSG_GPM, 605 time_out); 606 607 if (!time_out) 608 break; 609 610 offset = ar9003_mci_get_next_gpm_offset(ah, &more_data); 611 612 if (offset == MCI_GPM_INVALID) 613 continue; 614 615 p_gpm = (u32 *) (mci->gpm_buf + offset); 616 recv_type = MCI_GPM_TYPE(p_gpm); 617 recv_opcode = MCI_GPM_OPCODE(p_gpm); 618 619 if (MCI_GPM_IS_CAL_TYPE(recv_type)) { 620 if (recv_type == gpm_type) { 621 if ((gpm_type == MCI_GPM_BT_CAL_DONE) && 622 !b_is_bt_cal_done) { 623 gpm_type = MCI_GPM_BT_CAL_GRANT; 624 continue; 625 } 626 break; 627 } 628 } else if ((recv_type == gpm_type) && 629 (recv_opcode == gpm_opcode)) 630 break; 631 632 /* 633 * check if it's cal_grant 634 * 635 * When we're waiting for cal_grant in reset routine, 636 * it's possible that BT sends out cal_request at the 637 * same time. Since BT's calibration doesn't happen 638 * that often, we'll let BT completes calibration then 639 * we continue to wait for cal_grant from BT. 640 * Orginal: Wait BT_CAL_GRANT. 641 * New: Receive BT_CAL_REQ -> send WLAN_CAL_GRANT->wait 642 * BT_CAL_DONE -> Wait BT_CAL_GRANT. 643 */ 644 645 if ((gpm_type == MCI_GPM_BT_CAL_GRANT) && 646 (recv_type == MCI_GPM_BT_CAL_REQ)) { 647 648 u32 payload[4] = {0, 0, 0, 0}; 649 650 gpm_type = MCI_GPM_BT_CAL_DONE; 651 MCI_GPM_SET_CAL_TYPE(payload, 652 MCI_GPM_WLAN_CAL_GRANT); 653 ar9003_mci_send_message(ah, MCI_GPM, 0, payload, 16, 654 false, false); 655 continue; 656 } else { 657 ath_dbg(common, MCI, "MCI GPM subtype not match 0x%x\n", 658 *(p_gpm + 1)); 659 ar9003_mci_process_gpm_extra(ah, recv_type, 660 recv_opcode, p_gpm); 661 } 662 } 663 664 if (p_gpm) { 665 MCI_GPM_RECYCLE(p_gpm); 666 p_gpm = NULL; 667 } 668 669 if (time_out <= 0) 670 time_out = 0; 671 672 while (more_data == MCI_GPM_MORE) { 673 offset = ar9003_mci_get_next_gpm_offset(ah, &more_data); 674 if (offset == MCI_GPM_INVALID) 675 break; 676 677 p_gpm = (u32 *) (mci->gpm_buf + offset); 678 recv_type = MCI_GPM_TYPE(p_gpm); 679 recv_opcode = MCI_GPM_OPCODE(p_gpm); 680 681 if (!MCI_GPM_IS_CAL_TYPE(recv_type)) 682 ar9003_mci_process_gpm_extra(ah, recv_type, 683 recv_opcode, p_gpm); 684 685 MCI_GPM_RECYCLE(p_gpm); 686 } 687 688 return time_out; 689 } 690 691 bool ar9003_mci_start_reset(struct ath_hw *ah, struct ath9k_channel *chan) 692 { 693 struct ath_common *common = ath9k_hw_common(ah); 694 struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci; 695 u32 payload[4] = {0, 0, 0, 0}; 696 697 ar9003_mci_2g5g_changed(ah, IS_CHAN_2GHZ(chan)); 698 699 if (mci_hw->bt_state != MCI_BT_CAL_START) 700 return false; 701 702 mci_hw->bt_state = MCI_BT_CAL; 703 704 /* 705 * MCI FIX: disable mci interrupt here. This is to avoid 706 * SW_MSG_DONE or RX_MSG bits to trigger MCI_INT and 707 * lead to mci_intr reentry. 708 */ 709 ar9003_mci_disable_interrupt(ah); 710 711 MCI_GPM_SET_CAL_TYPE(payload, MCI_GPM_WLAN_CAL_GRANT); 712 ar9003_mci_send_message(ah, MCI_GPM, 0, payload, 713 16, true, false); 714 715 /* Wait BT calibration to be completed for 25ms */ 716 717 if (ar9003_mci_wait_for_gpm(ah, MCI_GPM_BT_CAL_DONE, 718 0, 25000)) 719 ath_dbg(common, MCI, "MCI BT_CAL_DONE received\n"); 720 else 721 ath_dbg(common, MCI, 722 "MCI BT_CAL_DONE not received\n"); 723 724 mci_hw->bt_state = MCI_BT_AWAKE; 725 /* MCI FIX: enable mci interrupt here */ 726 ar9003_mci_enable_interrupt(ah); 727 728 return true; 729 } 730 731 int ar9003_mci_end_reset(struct ath_hw *ah, struct ath9k_channel *chan, 732 struct ath9k_hw_cal_data *caldata) 733 { 734 struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci; 735 736 if (!mci_hw->ready) 737 return 0; 738 739 if (!IS_CHAN_2GHZ(chan) || (mci_hw->bt_state != MCI_BT_SLEEP)) 740 goto exit; 741 742 if (!ar9003_mci_check_int(ah, AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET) && 743 !ar9003_mci_check_int(ah, AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE)) 744 goto exit; 745 746 /* 747 * BT is sleeping. Check if BT wakes up during 748 * WLAN calibration. If BT wakes up during 749 * WLAN calibration, need to go through all 750 * message exchanges again and recal. 751 */ 752 REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, 753 (AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET | 754 AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE)); 755 756 ar9003_mci_remote_reset(ah, true); 757 ar9003_mci_send_sys_waking(ah, true); 758 udelay(1); 759 760 if (IS_CHAN_2GHZ(chan)) 761 ar9003_mci_send_lna_transfer(ah, true); 762 763 mci_hw->bt_state = MCI_BT_AWAKE; 764 765 REG_CLR_BIT(ah, AR_PHY_TIMING4, 766 1 << AR_PHY_TIMING_CONTROL4_DO_GAIN_DC_IQ_CAL_SHIFT); 767 768 if (caldata) { 769 clear_bit(TXIQCAL_DONE, &caldata->cal_flags); 770 clear_bit(TXCLCAL_DONE, &caldata->cal_flags); 771 clear_bit(RTT_DONE, &caldata->cal_flags); 772 } 773 774 if (!ath9k_hw_init_cal(ah, chan)) 775 return -EIO; 776 777 REG_SET_BIT(ah, AR_PHY_TIMING4, 778 1 << AR_PHY_TIMING_CONTROL4_DO_GAIN_DC_IQ_CAL_SHIFT); 779 780 exit: 781 ar9003_mci_enable_interrupt(ah); 782 return 0; 783 } 784 785 static void ar9003_mci_mute_bt(struct ath_hw *ah) 786 { 787 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; 788 789 /* disable all MCI messages */ 790 REG_WRITE(ah, AR_MCI_MSG_ATTRIBUTES_TABLE, 0xffff0000); 791 REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS0, 0xffffffff); 792 REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS1, 0xffffffff); 793 REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS2, 0xffffffff); 794 REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS3, 0xffffffff); 795 REG_SET_BIT(ah, AR_MCI_TX_CTRL, AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE); 796 797 /* wait pending HW messages to flush out */ 798 udelay(10); 799 800 /* 801 * Send LNA_TAKE and SYS_SLEEPING when 802 * 1. reset not after resuming from full sleep 803 * 2. before reset MCI RX, to quiet BT and avoid MCI RX misalignment 804 */ 805 if (MCI_ANT_ARCH_PA_LNA_SHARED(mci)) { 806 ar9003_mci_send_lna_take(ah, true); 807 udelay(5); 808 } 809 810 ar9003_mci_send_sys_sleeping(ah, true); 811 } 812 813 static void ar9003_mci_osla_setup(struct ath_hw *ah, bool enable) 814 { 815 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; 816 u32 thresh; 817 818 if (!enable) { 819 REG_CLR_BIT(ah, AR_BTCOEX_CTRL, 820 AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN); 821 return; 822 } 823 REG_RMW_FIELD(ah, AR_MCI_SCHD_TABLE_2, AR_MCI_SCHD_TABLE_2_HW_BASED, 1); 824 REG_RMW_FIELD(ah, AR_MCI_SCHD_TABLE_2, 825 AR_MCI_SCHD_TABLE_2_MEM_BASED, 1); 826 827 if (AR_SREV_9565(ah)) 828 REG_RMW_FIELD(ah, AR_MCI_MISC, AR_MCI_MISC_HW_FIX_EN, 1); 829 830 if (!(mci->config & ATH_MCI_CONFIG_DISABLE_AGGR_THRESH)) { 831 thresh = MS(mci->config, ATH_MCI_CONFIG_AGGR_THRESH); 832 REG_RMW_FIELD(ah, AR_BTCOEX_CTRL, 833 AR_BTCOEX_CTRL_AGGR_THRESH, thresh); 834 REG_RMW_FIELD(ah, AR_BTCOEX_CTRL, 835 AR_BTCOEX_CTRL_TIME_TO_NEXT_BT_THRESH_EN, 1); 836 } else 837 REG_RMW_FIELD(ah, AR_BTCOEX_CTRL, 838 AR_BTCOEX_CTRL_TIME_TO_NEXT_BT_THRESH_EN, 0); 839 840 REG_RMW_FIELD(ah, AR_BTCOEX_CTRL, 841 AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN, 1); 842 } 843 844 static void ar9003_mci_stat_setup(struct ath_hw *ah) 845 { 846 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; 847 848 if (!AR_SREV_9565(ah)) 849 return; 850 851 if (mci->config & ATH_MCI_CONFIG_MCI_STAT_DBG) { 852 REG_RMW_FIELD(ah, AR_MCI_DBG_CNT_CTRL, 853 AR_MCI_DBG_CNT_CTRL_ENABLE, 1); 854 REG_RMW_FIELD(ah, AR_MCI_DBG_CNT_CTRL, 855 AR_MCI_DBG_CNT_CTRL_BT_LINKID, 856 MCI_STAT_ALL_BT_LINKID); 857 } else { 858 REG_RMW_FIELD(ah, AR_MCI_DBG_CNT_CTRL, 859 AR_MCI_DBG_CNT_CTRL_ENABLE, 0); 860 } 861 } 862 863 static void ar9003_mci_set_btcoex_ctrl_9565_1ANT(struct ath_hw *ah) 864 { 865 u32 regval; 866 867 regval = SM(1, AR_BTCOEX_CTRL_AR9462_MODE) | 868 SM(1, AR_BTCOEX_CTRL_WBTIMER_EN) | 869 SM(1, AR_BTCOEX_CTRL_PA_SHARED) | 870 SM(1, AR_BTCOEX_CTRL_LNA_SHARED) | 871 SM(1, AR_BTCOEX_CTRL_NUM_ANTENNAS) | 872 SM(1, AR_BTCOEX_CTRL_RX_CHAIN_MASK) | 873 SM(0, AR_BTCOEX_CTRL_1_CHAIN_ACK) | 874 SM(0, AR_BTCOEX_CTRL_1_CHAIN_BCN) | 875 SM(0, AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN); 876 877 REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2, 878 AR_BTCOEX_CTRL2_TX_CHAIN_MASK, 0x1); 879 REG_WRITE(ah, AR_BTCOEX_CTRL, regval); 880 } 881 882 static void ar9003_mci_set_btcoex_ctrl_9565_2ANT(struct ath_hw *ah) 883 { 884 u32 regval; 885 886 regval = SM(1, AR_BTCOEX_CTRL_AR9462_MODE) | 887 SM(1, AR_BTCOEX_CTRL_WBTIMER_EN) | 888 SM(0, AR_BTCOEX_CTRL_PA_SHARED) | 889 SM(0, AR_BTCOEX_CTRL_LNA_SHARED) | 890 SM(2, AR_BTCOEX_CTRL_NUM_ANTENNAS) | 891 SM(1, AR_BTCOEX_CTRL_RX_CHAIN_MASK) | 892 SM(0, AR_BTCOEX_CTRL_1_CHAIN_ACK) | 893 SM(0, AR_BTCOEX_CTRL_1_CHAIN_BCN) | 894 SM(0, AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN); 895 896 REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2, 897 AR_BTCOEX_CTRL2_TX_CHAIN_MASK, 0x0); 898 REG_WRITE(ah, AR_BTCOEX_CTRL, regval); 899 } 900 901 static void ar9003_mci_set_btcoex_ctrl_9462(struct ath_hw *ah) 902 { 903 u32 regval; 904 905 regval = SM(1, AR_BTCOEX_CTRL_AR9462_MODE) | 906 SM(1, AR_BTCOEX_CTRL_WBTIMER_EN) | 907 SM(1, AR_BTCOEX_CTRL_PA_SHARED) | 908 SM(1, AR_BTCOEX_CTRL_LNA_SHARED) | 909 SM(2, AR_BTCOEX_CTRL_NUM_ANTENNAS) | 910 SM(3, AR_BTCOEX_CTRL_RX_CHAIN_MASK) | 911 SM(0, AR_BTCOEX_CTRL_1_CHAIN_ACK) | 912 SM(0, AR_BTCOEX_CTRL_1_CHAIN_BCN) | 913 SM(0, AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN); 914 915 REG_WRITE(ah, AR_BTCOEX_CTRL, regval); 916 } 917 918 int ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g, 919 bool is_full_sleep) 920 { 921 struct ath_common *common = ath9k_hw_common(ah); 922 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; 923 u32 regval, i; 924 925 ath_dbg(common, MCI, "MCI Reset (full_sleep = %d, is_2g = %d)\n", 926 is_full_sleep, is_2g); 927 928 if (REG_READ(ah, AR_BTCOEX_CTRL) == 0xdeadbeef) { 929 ath_err(common, "BTCOEX control register is dead\n"); 930 return -EINVAL; 931 } 932 933 /* Program MCI DMA related registers */ 934 REG_WRITE(ah, AR_MCI_GPM_0, mci->gpm_addr); 935 REG_WRITE(ah, AR_MCI_GPM_1, mci->gpm_len); 936 REG_WRITE(ah, AR_MCI_SCHD_TABLE_0, mci->sched_addr); 937 938 /* 939 * To avoid MCI state machine be affected by incoming remote MCI msgs, 940 * MCI mode will be enabled later, right before reset the MCI TX and RX. 941 */ 942 if (AR_SREV_9565(ah)) { 943 u8 ant = MS(mci->config, ATH_MCI_CONFIG_ANT_ARCH); 944 945 if (ant == ATH_MCI_ANT_ARCH_1_ANT_PA_LNA_SHARED) 946 ar9003_mci_set_btcoex_ctrl_9565_1ANT(ah); 947 else 948 ar9003_mci_set_btcoex_ctrl_9565_2ANT(ah); 949 } else { 950 ar9003_mci_set_btcoex_ctrl_9462(ah); 951 } 952 953 if (is_2g && !(mci->config & ATH_MCI_CONFIG_DISABLE_OSLA)) 954 ar9003_mci_osla_setup(ah, true); 955 else 956 ar9003_mci_osla_setup(ah, false); 957 958 REG_SET_BIT(ah, AR_PHY_GLB_CONTROL, 959 AR_BTCOEX_CTRL_SPDT_ENABLE); 960 REG_RMW_FIELD(ah, AR_BTCOEX_CTRL3, 961 AR_BTCOEX_CTRL3_CONT_INFO_TIMEOUT, 20); 962 963 REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2, AR_BTCOEX_CTRL2_RX_DEWEIGHT, 0); 964 REG_RMW_FIELD(ah, AR_PCU_MISC, AR_PCU_BT_ANT_PREVENT_RX, 0); 965 966 /* Set the time out to 3.125ms (5 BT slots) */ 967 REG_RMW_FIELD(ah, AR_BTCOEX_WL_LNA, AR_BTCOEX_WL_LNA_TIMEOUT, 0x3D090); 968 969 /* concurrent tx priority */ 970 if (mci->config & ATH_MCI_CONFIG_CONCUR_TX) { 971 REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2, 972 AR_BTCOEX_CTRL2_DESC_BASED_TXPWR_ENABLE, 0); 973 REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2, 974 AR_BTCOEX_CTRL2_TXPWR_THRESH, 0x7f); 975 REG_RMW_FIELD(ah, AR_BTCOEX_CTRL, 976 AR_BTCOEX_CTRL_REDUCE_TXPWR, 0); 977 for (i = 0; i < 8; i++) 978 REG_WRITE(ah, AR_BTCOEX_MAX_TXPWR(i), 0x7f7f7f7f); 979 } 980 981 regval = MS(mci->config, ATH_MCI_CONFIG_CLK_DIV); 982 REG_RMW_FIELD(ah, AR_MCI_TX_CTRL, AR_MCI_TX_CTRL_CLK_DIV, regval); 983 REG_SET_BIT(ah, AR_BTCOEX_CTRL, AR_BTCOEX_CTRL_MCI_MODE_EN); 984 985 /* Resetting the Rx and Tx paths of MCI */ 986 regval = REG_READ(ah, AR_MCI_COMMAND2); 987 regval |= SM(1, AR_MCI_COMMAND2_RESET_TX); 988 REG_WRITE(ah, AR_MCI_COMMAND2, regval); 989 990 udelay(1); 991 992 regval &= ~SM(1, AR_MCI_COMMAND2_RESET_TX); 993 REG_WRITE(ah, AR_MCI_COMMAND2, regval); 994 995 if (is_full_sleep) { 996 ar9003_mci_mute_bt(ah); 997 udelay(100); 998 } 999 1000 /* Check pending GPM msg before MCI Reset Rx */ 1001 ar9003_mci_check_gpm_offset(ah); 1002 1003 regval |= SM(1, AR_MCI_COMMAND2_RESET_RX); 1004 REG_WRITE(ah, AR_MCI_COMMAND2, regval); 1005 udelay(1); 1006 regval &= ~SM(1, AR_MCI_COMMAND2_RESET_RX); 1007 REG_WRITE(ah, AR_MCI_COMMAND2, regval); 1008 1009 /* Init GPM offset after MCI Reset Rx */ 1010 ar9003_mci_state(ah, MCI_STATE_INIT_GPM_OFFSET); 1011 1012 REG_WRITE(ah, AR_MCI_MSG_ATTRIBUTES_TABLE, 1013 (SM(0xe801, AR_MCI_MSG_ATTRIBUTES_TABLE_INVALID_HDR) | 1014 SM(0x0000, AR_MCI_MSG_ATTRIBUTES_TABLE_CHECKSUM))); 1015 1016 if (MCI_ANT_ARCH_PA_LNA_SHARED(mci)) 1017 REG_CLR_BIT(ah, AR_MCI_TX_CTRL, 1018 AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE); 1019 else 1020 REG_SET_BIT(ah, AR_MCI_TX_CTRL, 1021 AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE); 1022 1023 ar9003_mci_observation_set_up(ah); 1024 1025 mci->ready = true; 1026 ar9003_mci_prep_interface(ah); 1027 ar9003_mci_stat_setup(ah); 1028 1029 if (en_int) 1030 ar9003_mci_enable_interrupt(ah); 1031 1032 if (ath9k_hw_is_aic_enabled(ah)) 1033 ar9003_aic_start_normal(ah); 1034 1035 return 0; 1036 } 1037 1038 void ar9003_mci_stop_bt(struct ath_hw *ah, bool save_fullsleep) 1039 { 1040 struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci; 1041 1042 ar9003_mci_disable_interrupt(ah); 1043 1044 if (mci_hw->ready && !save_fullsleep) { 1045 ar9003_mci_mute_bt(ah); 1046 udelay(20); 1047 REG_WRITE(ah, AR_BTCOEX_CTRL, 0); 1048 } 1049 1050 mci_hw->bt_state = MCI_BT_SLEEP; 1051 mci_hw->ready = false; 1052 } 1053 1054 static void ar9003_mci_send_2g5g_status(struct ath_hw *ah, bool wait_done) 1055 { 1056 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; 1057 u32 to_set, to_clear; 1058 1059 if (!mci->update_2g5g || (mci->bt_state == MCI_BT_SLEEP)) 1060 return; 1061 1062 if (mci->is_2g) { 1063 to_clear = MCI_2G_FLAGS_CLEAR_MASK; 1064 to_set = MCI_2G_FLAGS_SET_MASK; 1065 } else { 1066 to_clear = MCI_5G_FLAGS_CLEAR_MASK; 1067 to_set = MCI_5G_FLAGS_SET_MASK; 1068 } 1069 1070 if (to_clear) 1071 ar9003_mci_send_coex_bt_flags(ah, wait_done, 1072 MCI_GPM_COEX_BT_FLAGS_CLEAR, 1073 to_clear); 1074 if (to_set) 1075 ar9003_mci_send_coex_bt_flags(ah, wait_done, 1076 MCI_GPM_COEX_BT_FLAGS_SET, 1077 to_set); 1078 } 1079 1080 static void ar9003_mci_queue_unsent_gpm(struct ath_hw *ah, u8 header, 1081 u32 *payload, bool queue) 1082 { 1083 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; 1084 u8 type, opcode; 1085 1086 /* check if the message is to be queued */ 1087 if (header != MCI_GPM) 1088 return; 1089 1090 type = MCI_GPM_TYPE(payload); 1091 opcode = MCI_GPM_OPCODE(payload); 1092 1093 if (type != MCI_GPM_COEX_AGENT) 1094 return; 1095 1096 switch (opcode) { 1097 case MCI_GPM_COEX_BT_UPDATE_FLAGS: 1098 if (*(((u8 *)payload) + MCI_GPM_COEX_B_BT_FLAGS_OP) == 1099 MCI_GPM_COEX_BT_FLAGS_READ) 1100 break; 1101 1102 mci->update_2g5g = queue; 1103 1104 break; 1105 case MCI_GPM_COEX_WLAN_CHANNELS: 1106 mci->wlan_channels_update = queue; 1107 break; 1108 case MCI_GPM_COEX_HALT_BT_GPM: 1109 if (*(((u8 *)payload) + MCI_GPM_COEX_B_HALT_STATE) == 1110 MCI_GPM_COEX_BT_GPM_UNHALT) { 1111 mci->unhalt_bt_gpm = queue; 1112 1113 if (!queue) 1114 mci->halted_bt_gpm = false; 1115 } 1116 1117 if (*(((u8 *)payload) + MCI_GPM_COEX_B_HALT_STATE) == 1118 MCI_GPM_COEX_BT_GPM_HALT) { 1119 1120 mci->halted_bt_gpm = !queue; 1121 } 1122 1123 break; 1124 default: 1125 break; 1126 } 1127 } 1128 1129 void ar9003_mci_2g5g_switch(struct ath_hw *ah, bool force) 1130 { 1131 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; 1132 1133 if (!mci->update_2g5g && !force) 1134 return; 1135 1136 if (mci->is_2g) { 1137 ar9003_mci_send_2g5g_status(ah, true); 1138 ar9003_mci_send_lna_transfer(ah, true); 1139 udelay(5); 1140 1141 REG_CLR_BIT(ah, AR_MCI_TX_CTRL, 1142 AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE); 1143 REG_CLR_BIT(ah, AR_PHY_GLB_CONTROL, 1144 AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL); 1145 1146 if (!(mci->config & ATH_MCI_CONFIG_DISABLE_OSLA)) 1147 ar9003_mci_osla_setup(ah, true); 1148 1149 if (AR_SREV_9462(ah)) 1150 REG_WRITE(ah, AR_SELFGEN_MASK, 0x02); 1151 } else { 1152 ar9003_mci_send_lna_take(ah, true); 1153 udelay(5); 1154 1155 REG_SET_BIT(ah, AR_MCI_TX_CTRL, 1156 AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE); 1157 REG_SET_BIT(ah, AR_PHY_GLB_CONTROL, 1158 AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL); 1159 1160 ar9003_mci_osla_setup(ah, false); 1161 ar9003_mci_send_2g5g_status(ah, true); 1162 } 1163 } 1164 1165 bool ar9003_mci_send_message(struct ath_hw *ah, u8 header, u32 flag, 1166 u32 *payload, u8 len, bool wait_done, 1167 bool check_bt) 1168 { 1169 struct ath_common *common = ath9k_hw_common(ah); 1170 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; 1171 bool msg_sent = false; 1172 u32 regval; 1173 u32 saved_mci_int_en; 1174 int i; 1175 1176 saved_mci_int_en = REG_READ(ah, AR_MCI_INTERRUPT_EN); 1177 regval = REG_READ(ah, AR_BTCOEX_CTRL); 1178 1179 if ((regval == 0xdeadbeef) || !(regval & AR_BTCOEX_CTRL_MCI_MODE_EN)) { 1180 ath_dbg(common, MCI, 1181 "MCI Not sending 0x%x. MCI is not enabled. full_sleep = %d\n", 1182 header, (ah->power_mode == ATH9K_PM_FULL_SLEEP) ? 1 : 0); 1183 ar9003_mci_queue_unsent_gpm(ah, header, payload, true); 1184 return false; 1185 } else if (check_bt && (mci->bt_state == MCI_BT_SLEEP)) { 1186 ath_dbg(common, MCI, 1187 "MCI Don't send message 0x%x. BT is in sleep state\n", 1188 header); 1189 ar9003_mci_queue_unsent_gpm(ah, header, payload, true); 1190 return false; 1191 } 1192 1193 if (wait_done) 1194 REG_WRITE(ah, AR_MCI_INTERRUPT_EN, 0); 1195 1196 /* Need to clear SW_MSG_DONE raw bit before wait */ 1197 1198 REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, 1199 (AR_MCI_INTERRUPT_SW_MSG_DONE | 1200 AR_MCI_INTERRUPT_MSG_FAIL_MASK)); 1201 1202 if (payload) { 1203 for (i = 0; (i * 4) < len; i++) 1204 REG_WRITE(ah, (AR_MCI_TX_PAYLOAD0 + i * 4), 1205 *(payload + i)); 1206 } 1207 1208 REG_WRITE(ah, AR_MCI_COMMAND0, 1209 (SM((flag & MCI_FLAG_DISABLE_TIMESTAMP), 1210 AR_MCI_COMMAND0_DISABLE_TIMESTAMP) | 1211 SM(len, AR_MCI_COMMAND0_LEN) | 1212 SM(header, AR_MCI_COMMAND0_HEADER))); 1213 1214 if (wait_done && 1215 !(ar9003_mci_wait_for_interrupt(ah, AR_MCI_INTERRUPT_RAW, 1216 AR_MCI_INTERRUPT_SW_MSG_DONE, 500))) 1217 ar9003_mci_queue_unsent_gpm(ah, header, payload, true); 1218 else { 1219 ar9003_mci_queue_unsent_gpm(ah, header, payload, false); 1220 msg_sent = true; 1221 } 1222 1223 if (wait_done) 1224 REG_WRITE(ah, AR_MCI_INTERRUPT_EN, saved_mci_int_en); 1225 1226 return msg_sent; 1227 } 1228 EXPORT_SYMBOL(ar9003_mci_send_message); 1229 1230 void ar9003_mci_init_cal_req(struct ath_hw *ah, bool *is_reusable) 1231 { 1232 struct ath_common *common = ath9k_hw_common(ah); 1233 struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci; 1234 u32 pld[4] = {0, 0, 0, 0}; 1235 1236 if ((mci_hw->bt_state != MCI_BT_AWAKE) || 1237 (mci_hw->config & ATH_MCI_CONFIG_DISABLE_MCI_CAL)) 1238 return; 1239 1240 MCI_GPM_SET_CAL_TYPE(pld, MCI_GPM_WLAN_CAL_REQ); 1241 pld[MCI_GPM_WLAN_CAL_W_SEQUENCE] = mci_hw->wlan_cal_seq++; 1242 1243 ar9003_mci_send_message(ah, MCI_GPM, 0, pld, 16, true, false); 1244 1245 if (ar9003_mci_wait_for_gpm(ah, MCI_GPM_BT_CAL_GRANT, 0, 50000)) { 1246 ath_dbg(common, MCI, "MCI BT_CAL_GRANT received\n"); 1247 } else { 1248 *is_reusable = false; 1249 ath_dbg(common, MCI, "MCI BT_CAL_GRANT not received\n"); 1250 } 1251 } 1252 1253 void ar9003_mci_init_cal_done(struct ath_hw *ah) 1254 { 1255 struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci; 1256 u32 pld[4] = {0, 0, 0, 0}; 1257 1258 if ((mci_hw->bt_state != MCI_BT_AWAKE) || 1259 (mci_hw->config & ATH_MCI_CONFIG_DISABLE_MCI_CAL)) 1260 return; 1261 1262 MCI_GPM_SET_CAL_TYPE(pld, MCI_GPM_WLAN_CAL_DONE); 1263 pld[MCI_GPM_WLAN_CAL_W_SEQUENCE] = mci_hw->wlan_cal_done++; 1264 ar9003_mci_send_message(ah, MCI_GPM, 0, pld, 16, true, false); 1265 } 1266 1267 int ar9003_mci_setup(struct ath_hw *ah, u32 gpm_addr, void *gpm_buf, 1268 u16 len, u32 sched_addr) 1269 { 1270 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; 1271 1272 mci->gpm_addr = gpm_addr; 1273 mci->gpm_buf = gpm_buf; 1274 mci->gpm_len = len; 1275 mci->sched_addr = sched_addr; 1276 1277 return ar9003_mci_reset(ah, true, true, true); 1278 } 1279 EXPORT_SYMBOL(ar9003_mci_setup); 1280 1281 void ar9003_mci_cleanup(struct ath_hw *ah) 1282 { 1283 /* Turn off MCI and Jupiter mode. */ 1284 REG_WRITE(ah, AR_BTCOEX_CTRL, 0x00); 1285 ar9003_mci_disable_interrupt(ah); 1286 } 1287 EXPORT_SYMBOL(ar9003_mci_cleanup); 1288 1289 u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type) 1290 { 1291 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; 1292 u32 value = 0, tsf; 1293 u8 query_type; 1294 1295 switch (state_type) { 1296 case MCI_STATE_ENABLE: 1297 if (mci->ready) { 1298 value = REG_READ(ah, AR_BTCOEX_CTRL); 1299 1300 if ((value == 0xdeadbeef) || (value == 0xffffffff)) 1301 value = 0; 1302 } 1303 value &= AR_BTCOEX_CTRL_MCI_MODE_EN; 1304 break; 1305 case MCI_STATE_INIT_GPM_OFFSET: 1306 value = MS(REG_READ(ah, AR_MCI_GPM_1), AR_MCI_GPM_WRITE_PTR); 1307 1308 if (value < mci->gpm_len) 1309 mci->gpm_idx = value; 1310 else 1311 mci->gpm_idx = 0; 1312 break; 1313 case MCI_STATE_LAST_SCHD_MSG_OFFSET: 1314 value = MS(REG_READ(ah, AR_MCI_RX_STATUS), 1315 AR_MCI_RX_LAST_SCHD_MSG_INDEX); 1316 /* Make it in bytes */ 1317 value <<= 4; 1318 break; 1319 case MCI_STATE_REMOTE_SLEEP: 1320 value = MS(REG_READ(ah, AR_MCI_RX_STATUS), 1321 AR_MCI_RX_REMOTE_SLEEP) ? 1322 MCI_BT_SLEEP : MCI_BT_AWAKE; 1323 break; 1324 case MCI_STATE_SET_BT_AWAKE: 1325 mci->bt_state = MCI_BT_AWAKE; 1326 ar9003_mci_send_coex_version_query(ah, true); 1327 ar9003_mci_send_coex_wlan_channels(ah, true); 1328 1329 if (mci->unhalt_bt_gpm) 1330 ar9003_mci_send_coex_halt_bt_gpm(ah, false, true); 1331 1332 ar9003_mci_2g5g_switch(ah, false); 1333 break; 1334 case MCI_STATE_RESET_REQ_WAKE: 1335 ar9003_mci_reset_req_wakeup(ah); 1336 mci->update_2g5g = true; 1337 1338 if (mci->config & ATH_MCI_CONFIG_MCI_OBS_MASK) { 1339 /* Check if we still have control of the GPIOs */ 1340 if ((REG_READ(ah, AR_GLB_GPIO_CONTROL) & 1341 ATH_MCI_CONFIG_MCI_OBS_GPIO) != 1342 ATH_MCI_CONFIG_MCI_OBS_GPIO) { 1343 ar9003_mci_observation_set_up(ah); 1344 } 1345 } 1346 break; 1347 case MCI_STATE_SEND_WLAN_COEX_VERSION: 1348 ar9003_mci_send_coex_version_response(ah, true); 1349 break; 1350 case MCI_STATE_SEND_VERSION_QUERY: 1351 ar9003_mci_send_coex_version_query(ah, true); 1352 break; 1353 case MCI_STATE_SEND_STATUS_QUERY: 1354 query_type = MCI_GPM_COEX_QUERY_BT_TOPOLOGY; 1355 ar9003_mci_send_coex_bt_status_query(ah, true, query_type); 1356 break; 1357 case MCI_STATE_RECOVER_RX: 1358 tsf = ath9k_hw_gettsf32(ah); 1359 if ((tsf - mci->last_recovery) <= MCI_RECOVERY_DUR_TSF) { 1360 ath_dbg(ath9k_hw_common(ah), MCI, 1361 "(MCI) ignore Rx recovery\n"); 1362 break; 1363 } 1364 ath_dbg(ath9k_hw_common(ah), MCI, "(MCI) RECOVER RX\n"); 1365 mci->last_recovery = tsf; 1366 ar9003_mci_prep_interface(ah); 1367 mci->query_bt = true; 1368 mci->need_flush_btinfo = true; 1369 ar9003_mci_send_coex_wlan_channels(ah, true); 1370 ar9003_mci_2g5g_switch(ah, false); 1371 break; 1372 case MCI_STATE_NEED_FTP_STOMP: 1373 value = !(mci->config & ATH_MCI_CONFIG_DISABLE_FTP_STOMP); 1374 break; 1375 case MCI_STATE_NEED_FLUSH_BT_INFO: 1376 value = (!mci->unhalt_bt_gpm && mci->need_flush_btinfo) ? 1 : 0; 1377 mci->need_flush_btinfo = false; 1378 break; 1379 case MCI_STATE_AIC_CAL: 1380 if (ath9k_hw_is_aic_enabled(ah)) 1381 value = ar9003_aic_calibration(ah); 1382 break; 1383 case MCI_STATE_AIC_START: 1384 if (ath9k_hw_is_aic_enabled(ah)) 1385 ar9003_aic_start_normal(ah); 1386 break; 1387 case MCI_STATE_AIC_CAL_RESET: 1388 if (ath9k_hw_is_aic_enabled(ah)) 1389 value = ar9003_aic_cal_reset(ah); 1390 break; 1391 case MCI_STATE_AIC_CAL_SINGLE: 1392 if (ath9k_hw_is_aic_enabled(ah)) 1393 value = ar9003_aic_calibration_single(ah); 1394 break; 1395 default: 1396 break; 1397 } 1398 1399 return value; 1400 } 1401 EXPORT_SYMBOL(ar9003_mci_state); 1402 1403 void ar9003_mci_bt_gain_ctrl(struct ath_hw *ah) 1404 { 1405 struct ath_common *common = ath9k_hw_common(ah); 1406 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; 1407 1408 ath_dbg(common, MCI, "Give LNA and SPDT control to BT\n"); 1409 1410 ar9003_mci_send_lna_take(ah, true); 1411 udelay(50); 1412 1413 REG_SET_BIT(ah, AR_PHY_GLB_CONTROL, AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL); 1414 mci->is_2g = false; 1415 mci->update_2g5g = true; 1416 ar9003_mci_send_2g5g_status(ah, true); 1417 1418 /* Force another 2g5g update at next scanning */ 1419 mci->update_2g5g = true; 1420 } 1421 1422 void ar9003_mci_set_power_awake(struct ath_hw *ah) 1423 { 1424 u32 btcoex_ctrl2, diag_sw; 1425 int i; 1426 u8 lna_ctrl, bt_sleep; 1427 1428 for (i = 0; i < AH_WAIT_TIMEOUT; i++) { 1429 btcoex_ctrl2 = REG_READ(ah, AR_BTCOEX_CTRL2); 1430 if (btcoex_ctrl2 != 0xdeadbeef) 1431 break; 1432 udelay(AH_TIME_QUANTUM); 1433 } 1434 REG_WRITE(ah, AR_BTCOEX_CTRL2, (btcoex_ctrl2 | BIT(23))); 1435 1436 for (i = 0; i < AH_WAIT_TIMEOUT; i++) { 1437 diag_sw = REG_READ(ah, AR_DIAG_SW); 1438 if (diag_sw != 0xdeadbeef) 1439 break; 1440 udelay(AH_TIME_QUANTUM); 1441 } 1442 REG_WRITE(ah, AR_DIAG_SW, (diag_sw | BIT(27) | BIT(19) | BIT(18))); 1443 lna_ctrl = REG_READ(ah, AR_OBS_BUS_CTRL) & 0x3; 1444 bt_sleep = MS(REG_READ(ah, AR_MCI_RX_STATUS), AR_MCI_RX_REMOTE_SLEEP); 1445 1446 REG_WRITE(ah, AR_BTCOEX_CTRL2, btcoex_ctrl2); 1447 REG_WRITE(ah, AR_DIAG_SW, diag_sw); 1448 1449 if (bt_sleep && (lna_ctrl == 2)) { 1450 REG_SET_BIT(ah, AR_BTCOEX_RC, 0x1); 1451 REG_CLR_BIT(ah, AR_BTCOEX_RC, 0x1); 1452 udelay(50); 1453 } 1454 } 1455 1456 void ar9003_mci_check_gpm_offset(struct ath_hw *ah) 1457 { 1458 struct ath_common *common = ath9k_hw_common(ah); 1459 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; 1460 u32 offset; 1461 1462 /* 1463 * This should only be called before "MAC Warm Reset" or "MCI Reset Rx". 1464 */ 1465 offset = MS(REG_READ(ah, AR_MCI_GPM_1), AR_MCI_GPM_WRITE_PTR); 1466 if (mci->gpm_idx == offset) 1467 return; 1468 ath_dbg(common, MCI, "GPM cached write pointer mismatch %d %d\n", 1469 mci->gpm_idx, offset); 1470 mci->query_bt = true; 1471 mci->need_flush_btinfo = true; 1472 mci->gpm_idx = 0; 1473 } 1474 1475 u32 ar9003_mci_get_next_gpm_offset(struct ath_hw *ah, u32 *more) 1476 { 1477 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; 1478 u32 offset, more_gpm = 0, gpm_ptr; 1479 1480 /* 1481 * This could be useful to avoid new GPM message interrupt which 1482 * may lead to spurious interrupt after power sleep, or multiple 1483 * entry of ath_mci_intr(). 1484 * Adding empty GPM check by returning HAL_MCI_GPM_INVALID can 1485 * alleviate this effect, but clearing GPM RX interrupt bit is 1486 * safe, because whether this is called from hw or driver code 1487 * there must be an interrupt bit set/triggered initially 1488 */ 1489 REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, 1490 AR_MCI_INTERRUPT_RX_MSG_GPM); 1491 1492 gpm_ptr = MS(REG_READ(ah, AR_MCI_GPM_1), AR_MCI_GPM_WRITE_PTR); 1493 offset = gpm_ptr; 1494 1495 if (!offset) 1496 offset = mci->gpm_len - 1; 1497 else if (offset >= mci->gpm_len) { 1498 if (offset != 0xFFFF) 1499 offset = 0; 1500 } else { 1501 offset--; 1502 } 1503 1504 if ((offset == 0xFFFF) || (gpm_ptr == mci->gpm_idx)) { 1505 offset = MCI_GPM_INVALID; 1506 more_gpm = MCI_GPM_NOMORE; 1507 goto out; 1508 } 1509 for (;;) { 1510 u32 temp_index; 1511 1512 /* skip reserved GPM if any */ 1513 1514 if (offset != mci->gpm_idx) 1515 more_gpm = MCI_GPM_MORE; 1516 else 1517 more_gpm = MCI_GPM_NOMORE; 1518 1519 temp_index = mci->gpm_idx; 1520 1521 if (temp_index >= mci->gpm_len) 1522 temp_index = 0; 1523 1524 mci->gpm_idx++; 1525 1526 if (mci->gpm_idx >= mci->gpm_len) 1527 mci->gpm_idx = 0; 1528 1529 if (ar9003_mci_is_gpm_valid(ah, temp_index)) { 1530 offset = temp_index; 1531 break; 1532 } 1533 1534 if (more_gpm == MCI_GPM_NOMORE) { 1535 offset = MCI_GPM_INVALID; 1536 break; 1537 } 1538 } 1539 1540 if (offset != MCI_GPM_INVALID) 1541 offset <<= 4; 1542 out: 1543 if (more) 1544 *more = more_gpm; 1545 1546 return offset; 1547 } 1548 EXPORT_SYMBOL(ar9003_mci_get_next_gpm_offset); 1549 1550 void ar9003_mci_set_bt_version(struct ath_hw *ah, u8 major, u8 minor) 1551 { 1552 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; 1553 1554 mci->bt_ver_major = major; 1555 mci->bt_ver_minor = minor; 1556 mci->bt_version_known = true; 1557 ath_dbg(ath9k_hw_common(ah), MCI, "MCI BT version set: %d.%d\n", 1558 mci->bt_ver_major, mci->bt_ver_minor); 1559 } 1560 EXPORT_SYMBOL(ar9003_mci_set_bt_version); 1561 1562 void ar9003_mci_send_wlan_channels(struct ath_hw *ah) 1563 { 1564 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; 1565 1566 mci->wlan_channels_update = true; 1567 ar9003_mci_send_coex_wlan_channels(ah, true); 1568 } 1569 EXPORT_SYMBOL(ar9003_mci_send_wlan_channels); 1570 1571 u16 ar9003_mci_get_max_txpower(struct ath_hw *ah, u8 ctlmode) 1572 { 1573 if (!ah->btcoex_hw.mci.concur_tx) 1574 goto out; 1575 1576 if (ctlmode == CTL_2GHT20) 1577 return ATH_BTCOEX_HT20_MAX_TXPOWER; 1578 else if (ctlmode == CTL_2GHT40) 1579 return ATH_BTCOEX_HT40_MAX_TXPOWER; 1580 1581 out: 1582 return -1; 1583 } 1584