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