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 new_flags, 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 new_flags = MCI_2G_FLAGS; 1065 to_clear = MCI_2G_FLAGS_CLEAR_MASK; 1066 to_set = MCI_2G_FLAGS_SET_MASK; 1067 } else { 1068 new_flags = MCI_5G_FLAGS; 1069 to_clear = MCI_5G_FLAGS_CLEAR_MASK; 1070 to_set = MCI_5G_FLAGS_SET_MASK; 1071 } 1072 1073 if (to_clear) 1074 ar9003_mci_send_coex_bt_flags(ah, wait_done, 1075 MCI_GPM_COEX_BT_FLAGS_CLEAR, 1076 to_clear); 1077 if (to_set) 1078 ar9003_mci_send_coex_bt_flags(ah, wait_done, 1079 MCI_GPM_COEX_BT_FLAGS_SET, 1080 to_set); 1081 } 1082 1083 static void ar9003_mci_queue_unsent_gpm(struct ath_hw *ah, u8 header, 1084 u32 *payload, bool queue) 1085 { 1086 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; 1087 u8 type, opcode; 1088 1089 /* check if the message is to be queued */ 1090 if (header != MCI_GPM) 1091 return; 1092 1093 type = MCI_GPM_TYPE(payload); 1094 opcode = MCI_GPM_OPCODE(payload); 1095 1096 if (type != MCI_GPM_COEX_AGENT) 1097 return; 1098 1099 switch (opcode) { 1100 case MCI_GPM_COEX_BT_UPDATE_FLAGS: 1101 if (*(((u8 *)payload) + MCI_GPM_COEX_B_BT_FLAGS_OP) == 1102 MCI_GPM_COEX_BT_FLAGS_READ) 1103 break; 1104 1105 mci->update_2g5g = queue; 1106 1107 break; 1108 case MCI_GPM_COEX_WLAN_CHANNELS: 1109 mci->wlan_channels_update = queue; 1110 break; 1111 case MCI_GPM_COEX_HALT_BT_GPM: 1112 if (*(((u8 *)payload) + MCI_GPM_COEX_B_HALT_STATE) == 1113 MCI_GPM_COEX_BT_GPM_UNHALT) { 1114 mci->unhalt_bt_gpm = queue; 1115 1116 if (!queue) 1117 mci->halted_bt_gpm = false; 1118 } 1119 1120 if (*(((u8 *)payload) + MCI_GPM_COEX_B_HALT_STATE) == 1121 MCI_GPM_COEX_BT_GPM_HALT) { 1122 1123 mci->halted_bt_gpm = !queue; 1124 } 1125 1126 break; 1127 default: 1128 break; 1129 } 1130 } 1131 1132 void ar9003_mci_2g5g_switch(struct ath_hw *ah, bool force) 1133 { 1134 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; 1135 1136 if (!mci->update_2g5g && !force) 1137 return; 1138 1139 if (mci->is_2g) { 1140 ar9003_mci_send_2g5g_status(ah, true); 1141 ar9003_mci_send_lna_transfer(ah, true); 1142 udelay(5); 1143 1144 REG_CLR_BIT(ah, AR_MCI_TX_CTRL, 1145 AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE); 1146 REG_CLR_BIT(ah, AR_PHY_GLB_CONTROL, 1147 AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL); 1148 1149 if (!(mci->config & ATH_MCI_CONFIG_DISABLE_OSLA)) 1150 ar9003_mci_osla_setup(ah, true); 1151 1152 if (AR_SREV_9462(ah)) 1153 REG_WRITE(ah, AR_SELFGEN_MASK, 0x02); 1154 } else { 1155 ar9003_mci_send_lna_take(ah, true); 1156 udelay(5); 1157 1158 REG_SET_BIT(ah, AR_MCI_TX_CTRL, 1159 AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE); 1160 REG_SET_BIT(ah, AR_PHY_GLB_CONTROL, 1161 AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL); 1162 1163 ar9003_mci_osla_setup(ah, false); 1164 ar9003_mci_send_2g5g_status(ah, true); 1165 } 1166 } 1167 1168 bool ar9003_mci_send_message(struct ath_hw *ah, u8 header, u32 flag, 1169 u32 *payload, u8 len, bool wait_done, 1170 bool check_bt) 1171 { 1172 struct ath_common *common = ath9k_hw_common(ah); 1173 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; 1174 bool msg_sent = false; 1175 u32 regval; 1176 u32 saved_mci_int_en; 1177 int i; 1178 1179 saved_mci_int_en = REG_READ(ah, AR_MCI_INTERRUPT_EN); 1180 regval = REG_READ(ah, AR_BTCOEX_CTRL); 1181 1182 if ((regval == 0xdeadbeef) || !(regval & AR_BTCOEX_CTRL_MCI_MODE_EN)) { 1183 ath_dbg(common, MCI, 1184 "MCI Not sending 0x%x. MCI is not enabled. full_sleep = %d\n", 1185 header, (ah->power_mode == ATH9K_PM_FULL_SLEEP) ? 1 : 0); 1186 ar9003_mci_queue_unsent_gpm(ah, header, payload, true); 1187 return false; 1188 } else if (check_bt && (mci->bt_state == MCI_BT_SLEEP)) { 1189 ath_dbg(common, MCI, 1190 "MCI Don't send message 0x%x. BT is in sleep state\n", 1191 header); 1192 ar9003_mci_queue_unsent_gpm(ah, header, payload, true); 1193 return false; 1194 } 1195 1196 if (wait_done) 1197 REG_WRITE(ah, AR_MCI_INTERRUPT_EN, 0); 1198 1199 /* Need to clear SW_MSG_DONE raw bit before wait */ 1200 1201 REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, 1202 (AR_MCI_INTERRUPT_SW_MSG_DONE | 1203 AR_MCI_INTERRUPT_MSG_FAIL_MASK)); 1204 1205 if (payload) { 1206 for (i = 0; (i * 4) < len; i++) 1207 REG_WRITE(ah, (AR_MCI_TX_PAYLOAD0 + i * 4), 1208 *(payload + i)); 1209 } 1210 1211 REG_WRITE(ah, AR_MCI_COMMAND0, 1212 (SM((flag & MCI_FLAG_DISABLE_TIMESTAMP), 1213 AR_MCI_COMMAND0_DISABLE_TIMESTAMP) | 1214 SM(len, AR_MCI_COMMAND0_LEN) | 1215 SM(header, AR_MCI_COMMAND0_HEADER))); 1216 1217 if (wait_done && 1218 !(ar9003_mci_wait_for_interrupt(ah, AR_MCI_INTERRUPT_RAW, 1219 AR_MCI_INTERRUPT_SW_MSG_DONE, 500))) 1220 ar9003_mci_queue_unsent_gpm(ah, header, payload, true); 1221 else { 1222 ar9003_mci_queue_unsent_gpm(ah, header, payload, false); 1223 msg_sent = true; 1224 } 1225 1226 if (wait_done) 1227 REG_WRITE(ah, AR_MCI_INTERRUPT_EN, saved_mci_int_en); 1228 1229 return msg_sent; 1230 } 1231 EXPORT_SYMBOL(ar9003_mci_send_message); 1232 1233 void ar9003_mci_init_cal_req(struct ath_hw *ah, bool *is_reusable) 1234 { 1235 struct ath_common *common = ath9k_hw_common(ah); 1236 struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci; 1237 u32 pld[4] = {0, 0, 0, 0}; 1238 1239 if ((mci_hw->bt_state != MCI_BT_AWAKE) || 1240 (mci_hw->config & ATH_MCI_CONFIG_DISABLE_MCI_CAL)) 1241 return; 1242 1243 MCI_GPM_SET_CAL_TYPE(pld, MCI_GPM_WLAN_CAL_REQ); 1244 pld[MCI_GPM_WLAN_CAL_W_SEQUENCE] = mci_hw->wlan_cal_seq++; 1245 1246 ar9003_mci_send_message(ah, MCI_GPM, 0, pld, 16, true, false); 1247 1248 if (ar9003_mci_wait_for_gpm(ah, MCI_GPM_BT_CAL_GRANT, 0, 50000)) { 1249 ath_dbg(common, MCI, "MCI BT_CAL_GRANT received\n"); 1250 } else { 1251 *is_reusable = false; 1252 ath_dbg(common, MCI, "MCI BT_CAL_GRANT not received\n"); 1253 } 1254 } 1255 1256 void ar9003_mci_init_cal_done(struct ath_hw *ah) 1257 { 1258 struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci; 1259 u32 pld[4] = {0, 0, 0, 0}; 1260 1261 if ((mci_hw->bt_state != MCI_BT_AWAKE) || 1262 (mci_hw->config & ATH_MCI_CONFIG_DISABLE_MCI_CAL)) 1263 return; 1264 1265 MCI_GPM_SET_CAL_TYPE(pld, MCI_GPM_WLAN_CAL_DONE); 1266 pld[MCI_GPM_WLAN_CAL_W_SEQUENCE] = mci_hw->wlan_cal_done++; 1267 ar9003_mci_send_message(ah, MCI_GPM, 0, pld, 16, true, false); 1268 } 1269 1270 int ar9003_mci_setup(struct ath_hw *ah, u32 gpm_addr, void *gpm_buf, 1271 u16 len, u32 sched_addr) 1272 { 1273 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; 1274 1275 mci->gpm_addr = gpm_addr; 1276 mci->gpm_buf = gpm_buf; 1277 mci->gpm_len = len; 1278 mci->sched_addr = sched_addr; 1279 1280 return ar9003_mci_reset(ah, true, true, true); 1281 } 1282 EXPORT_SYMBOL(ar9003_mci_setup); 1283 1284 void ar9003_mci_cleanup(struct ath_hw *ah) 1285 { 1286 /* Turn off MCI and Jupiter mode. */ 1287 REG_WRITE(ah, AR_BTCOEX_CTRL, 0x00); 1288 ar9003_mci_disable_interrupt(ah); 1289 } 1290 EXPORT_SYMBOL(ar9003_mci_cleanup); 1291 1292 u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type) 1293 { 1294 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; 1295 u32 value = 0, tsf; 1296 u8 query_type; 1297 1298 switch (state_type) { 1299 case MCI_STATE_ENABLE: 1300 if (mci->ready) { 1301 value = REG_READ(ah, AR_BTCOEX_CTRL); 1302 1303 if ((value == 0xdeadbeef) || (value == 0xffffffff)) 1304 value = 0; 1305 } 1306 value &= AR_BTCOEX_CTRL_MCI_MODE_EN; 1307 break; 1308 case MCI_STATE_INIT_GPM_OFFSET: 1309 value = MS(REG_READ(ah, AR_MCI_GPM_1), AR_MCI_GPM_WRITE_PTR); 1310 1311 if (value < mci->gpm_len) 1312 mci->gpm_idx = value; 1313 else 1314 mci->gpm_idx = 0; 1315 break; 1316 case MCI_STATE_LAST_SCHD_MSG_OFFSET: 1317 value = MS(REG_READ(ah, AR_MCI_RX_STATUS), 1318 AR_MCI_RX_LAST_SCHD_MSG_INDEX); 1319 /* Make it in bytes */ 1320 value <<= 4; 1321 break; 1322 case MCI_STATE_REMOTE_SLEEP: 1323 value = MS(REG_READ(ah, AR_MCI_RX_STATUS), 1324 AR_MCI_RX_REMOTE_SLEEP) ? 1325 MCI_BT_SLEEP : MCI_BT_AWAKE; 1326 break; 1327 case MCI_STATE_SET_BT_AWAKE: 1328 mci->bt_state = MCI_BT_AWAKE; 1329 ar9003_mci_send_coex_version_query(ah, true); 1330 ar9003_mci_send_coex_wlan_channels(ah, true); 1331 1332 if (mci->unhalt_bt_gpm) 1333 ar9003_mci_send_coex_halt_bt_gpm(ah, false, true); 1334 1335 ar9003_mci_2g5g_switch(ah, false); 1336 break; 1337 case MCI_STATE_RESET_REQ_WAKE: 1338 ar9003_mci_reset_req_wakeup(ah); 1339 mci->update_2g5g = true; 1340 1341 if (mci->config & ATH_MCI_CONFIG_MCI_OBS_MASK) { 1342 /* Check if we still have control of the GPIOs */ 1343 if ((REG_READ(ah, AR_GLB_GPIO_CONTROL) & 1344 ATH_MCI_CONFIG_MCI_OBS_GPIO) != 1345 ATH_MCI_CONFIG_MCI_OBS_GPIO) { 1346 ar9003_mci_observation_set_up(ah); 1347 } 1348 } 1349 break; 1350 case MCI_STATE_SEND_WLAN_COEX_VERSION: 1351 ar9003_mci_send_coex_version_response(ah, true); 1352 break; 1353 case MCI_STATE_SEND_VERSION_QUERY: 1354 ar9003_mci_send_coex_version_query(ah, true); 1355 break; 1356 case MCI_STATE_SEND_STATUS_QUERY: 1357 query_type = MCI_GPM_COEX_QUERY_BT_TOPOLOGY; 1358 ar9003_mci_send_coex_bt_status_query(ah, true, query_type); 1359 break; 1360 case MCI_STATE_RECOVER_RX: 1361 tsf = ath9k_hw_gettsf32(ah); 1362 if ((tsf - mci->last_recovery) <= MCI_RECOVERY_DUR_TSF) { 1363 ath_dbg(ath9k_hw_common(ah), MCI, 1364 "(MCI) ignore Rx recovery\n"); 1365 break; 1366 } 1367 ath_dbg(ath9k_hw_common(ah), MCI, "(MCI) RECOVER RX\n"); 1368 mci->last_recovery = tsf; 1369 ar9003_mci_prep_interface(ah); 1370 mci->query_bt = true; 1371 mci->need_flush_btinfo = true; 1372 ar9003_mci_send_coex_wlan_channels(ah, true); 1373 ar9003_mci_2g5g_switch(ah, false); 1374 break; 1375 case MCI_STATE_NEED_FTP_STOMP: 1376 value = !(mci->config & ATH_MCI_CONFIG_DISABLE_FTP_STOMP); 1377 break; 1378 case MCI_STATE_NEED_FLUSH_BT_INFO: 1379 value = (!mci->unhalt_bt_gpm && mci->need_flush_btinfo) ? 1 : 0; 1380 mci->need_flush_btinfo = false; 1381 break; 1382 case MCI_STATE_AIC_CAL: 1383 if (ath9k_hw_is_aic_enabled(ah)) 1384 value = ar9003_aic_calibration(ah); 1385 break; 1386 case MCI_STATE_AIC_START: 1387 if (ath9k_hw_is_aic_enabled(ah)) 1388 ar9003_aic_start_normal(ah); 1389 break; 1390 case MCI_STATE_AIC_CAL_RESET: 1391 if (ath9k_hw_is_aic_enabled(ah)) 1392 value = ar9003_aic_cal_reset(ah); 1393 break; 1394 case MCI_STATE_AIC_CAL_SINGLE: 1395 if (ath9k_hw_is_aic_enabled(ah)) 1396 value = ar9003_aic_calibration_single(ah); 1397 break; 1398 default: 1399 break; 1400 } 1401 1402 return value; 1403 } 1404 EXPORT_SYMBOL(ar9003_mci_state); 1405 1406 void ar9003_mci_bt_gain_ctrl(struct ath_hw *ah) 1407 { 1408 struct ath_common *common = ath9k_hw_common(ah); 1409 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; 1410 1411 ath_dbg(common, MCI, "Give LNA and SPDT control to BT\n"); 1412 1413 ar9003_mci_send_lna_take(ah, true); 1414 udelay(50); 1415 1416 REG_SET_BIT(ah, AR_PHY_GLB_CONTROL, AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL); 1417 mci->is_2g = false; 1418 mci->update_2g5g = true; 1419 ar9003_mci_send_2g5g_status(ah, true); 1420 1421 /* Force another 2g5g update at next scanning */ 1422 mci->update_2g5g = true; 1423 } 1424 1425 void ar9003_mci_set_power_awake(struct ath_hw *ah) 1426 { 1427 u32 btcoex_ctrl2, diag_sw; 1428 int i; 1429 u8 lna_ctrl, bt_sleep; 1430 1431 for (i = 0; i < AH_WAIT_TIMEOUT; i++) { 1432 btcoex_ctrl2 = REG_READ(ah, AR_BTCOEX_CTRL2); 1433 if (btcoex_ctrl2 != 0xdeadbeef) 1434 break; 1435 udelay(AH_TIME_QUANTUM); 1436 } 1437 REG_WRITE(ah, AR_BTCOEX_CTRL2, (btcoex_ctrl2 | BIT(23))); 1438 1439 for (i = 0; i < AH_WAIT_TIMEOUT; i++) { 1440 diag_sw = REG_READ(ah, AR_DIAG_SW); 1441 if (diag_sw != 0xdeadbeef) 1442 break; 1443 udelay(AH_TIME_QUANTUM); 1444 } 1445 REG_WRITE(ah, AR_DIAG_SW, (diag_sw | BIT(27) | BIT(19) | BIT(18))); 1446 lna_ctrl = REG_READ(ah, AR_OBS_BUS_CTRL) & 0x3; 1447 bt_sleep = MS(REG_READ(ah, AR_MCI_RX_STATUS), AR_MCI_RX_REMOTE_SLEEP); 1448 1449 REG_WRITE(ah, AR_BTCOEX_CTRL2, btcoex_ctrl2); 1450 REG_WRITE(ah, AR_DIAG_SW, diag_sw); 1451 1452 if (bt_sleep && (lna_ctrl == 2)) { 1453 REG_SET_BIT(ah, AR_BTCOEX_RC, 0x1); 1454 REG_CLR_BIT(ah, AR_BTCOEX_RC, 0x1); 1455 udelay(50); 1456 } 1457 } 1458 1459 void ar9003_mci_check_gpm_offset(struct ath_hw *ah) 1460 { 1461 struct ath_common *common = ath9k_hw_common(ah); 1462 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; 1463 u32 offset; 1464 1465 /* 1466 * This should only be called before "MAC Warm Reset" or "MCI Reset Rx". 1467 */ 1468 offset = MS(REG_READ(ah, AR_MCI_GPM_1), AR_MCI_GPM_WRITE_PTR); 1469 if (mci->gpm_idx == offset) 1470 return; 1471 ath_dbg(common, MCI, "GPM cached write pointer mismatch %d %d\n", 1472 mci->gpm_idx, offset); 1473 mci->query_bt = true; 1474 mci->need_flush_btinfo = true; 1475 mci->gpm_idx = 0; 1476 } 1477 1478 u32 ar9003_mci_get_next_gpm_offset(struct ath_hw *ah, u32 *more) 1479 { 1480 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; 1481 u32 offset, more_gpm = 0, gpm_ptr; 1482 1483 /* 1484 * This could be useful to avoid new GPM message interrupt which 1485 * may lead to spurious interrupt after power sleep, or multiple 1486 * entry of ath_mci_intr(). 1487 * Adding empty GPM check by returning HAL_MCI_GPM_INVALID can 1488 * alleviate this effect, but clearing GPM RX interrupt bit is 1489 * safe, because whether this is called from hw or driver code 1490 * there must be an interrupt bit set/triggered initially 1491 */ 1492 REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, 1493 AR_MCI_INTERRUPT_RX_MSG_GPM); 1494 1495 gpm_ptr = MS(REG_READ(ah, AR_MCI_GPM_1), AR_MCI_GPM_WRITE_PTR); 1496 offset = gpm_ptr; 1497 1498 if (!offset) 1499 offset = mci->gpm_len - 1; 1500 else if (offset >= mci->gpm_len) { 1501 if (offset != 0xFFFF) 1502 offset = 0; 1503 } else { 1504 offset--; 1505 } 1506 1507 if ((offset == 0xFFFF) || (gpm_ptr == mci->gpm_idx)) { 1508 offset = MCI_GPM_INVALID; 1509 more_gpm = MCI_GPM_NOMORE; 1510 goto out; 1511 } 1512 for (;;) { 1513 u32 temp_index; 1514 1515 /* skip reserved GPM if any */ 1516 1517 if (offset != mci->gpm_idx) 1518 more_gpm = MCI_GPM_MORE; 1519 else 1520 more_gpm = MCI_GPM_NOMORE; 1521 1522 temp_index = mci->gpm_idx; 1523 1524 if (temp_index >= mci->gpm_len) 1525 temp_index = 0; 1526 1527 mci->gpm_idx++; 1528 1529 if (mci->gpm_idx >= mci->gpm_len) 1530 mci->gpm_idx = 0; 1531 1532 if (ar9003_mci_is_gpm_valid(ah, temp_index)) { 1533 offset = temp_index; 1534 break; 1535 } 1536 1537 if (more_gpm == MCI_GPM_NOMORE) { 1538 offset = MCI_GPM_INVALID; 1539 break; 1540 } 1541 } 1542 1543 if (offset != MCI_GPM_INVALID) 1544 offset <<= 4; 1545 out: 1546 if (more) 1547 *more = more_gpm; 1548 1549 return offset; 1550 } 1551 EXPORT_SYMBOL(ar9003_mci_get_next_gpm_offset); 1552 1553 void ar9003_mci_set_bt_version(struct ath_hw *ah, u8 major, u8 minor) 1554 { 1555 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; 1556 1557 mci->bt_ver_major = major; 1558 mci->bt_ver_minor = minor; 1559 mci->bt_version_known = true; 1560 ath_dbg(ath9k_hw_common(ah), MCI, "MCI BT version set: %d.%d\n", 1561 mci->bt_ver_major, mci->bt_ver_minor); 1562 } 1563 EXPORT_SYMBOL(ar9003_mci_set_bt_version); 1564 1565 void ar9003_mci_send_wlan_channels(struct ath_hw *ah) 1566 { 1567 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; 1568 1569 mci->wlan_channels_update = true; 1570 ar9003_mci_send_coex_wlan_channels(ah, true); 1571 } 1572 EXPORT_SYMBOL(ar9003_mci_send_wlan_channels); 1573 1574 u16 ar9003_mci_get_max_txpower(struct ath_hw *ah, u8 ctlmode) 1575 { 1576 if (!ah->btcoex_hw.mci.concur_tx) 1577 goto out; 1578 1579 if (ctlmode == CTL_2GHT20) 1580 return ATH_BTCOEX_HT20_MAX_TXPOWER; 1581 else if (ctlmode == CTL_2GHT40) 1582 return ATH_BTCOEX_HT40_MAX_TXPOWER; 1583 1584 out: 1585 return -1; 1586 } 1587