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