0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #include <linux/export.h>
0018 #include "hw.h"
0019 #include "hw-ops.h"
0020 #include "ar9003_phy.h"
0021 #include "ar9003_mci.h"
0022 #include "ar9003_aic.h"
0023
0024 static void ar9003_mci_reset_req_wakeup(struct ath_hw *ah)
0025 {
0026 REG_RMW_FIELD(ah, AR_MCI_COMMAND2,
0027 AR_MCI_COMMAND2_RESET_REQ_WAKEUP, 1);
0028 udelay(1);
0029 REG_RMW_FIELD(ah, AR_MCI_COMMAND2,
0030 AR_MCI_COMMAND2_RESET_REQ_WAKEUP, 0);
0031 }
0032
0033 static int ar9003_mci_wait_for_interrupt(struct ath_hw *ah, u32 address,
0034 u32 bit_position, int time_out)
0035 {
0036 struct ath_common *common = ath9k_hw_common(ah);
0037
0038 while (time_out) {
0039 if (!(REG_READ(ah, address) & bit_position)) {
0040 udelay(10);
0041 time_out -= 10;
0042
0043 if (time_out < 0)
0044 break;
0045 else
0046 continue;
0047 }
0048 REG_WRITE(ah, address, bit_position);
0049
0050 if (address != AR_MCI_INTERRUPT_RX_MSG_RAW)
0051 break;
0052
0053 if (bit_position & AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE)
0054 ar9003_mci_reset_req_wakeup(ah);
0055
0056 if (bit_position & (AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING |
0057 AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING))
0058 REG_WRITE(ah, AR_MCI_INTERRUPT_RAW,
0059 AR_MCI_INTERRUPT_REMOTE_SLEEP_UPDATE);
0060
0061 REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, AR_MCI_INTERRUPT_RX_MSG);
0062 break;
0063 }
0064
0065 if (time_out <= 0) {
0066 ath_dbg(common, MCI,
0067 "MCI Wait for Reg 0x%08x = 0x%08x timeout\n",
0068 address, bit_position);
0069 ath_dbg(common, MCI,
0070 "MCI INT_RAW = 0x%08x, RX_MSG_RAW = 0x%08x\n",
0071 REG_READ(ah, AR_MCI_INTERRUPT_RAW),
0072 REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_RAW));
0073 time_out = 0;
0074 }
0075
0076 return time_out;
0077 }
0078
0079 static void ar9003_mci_remote_reset(struct ath_hw *ah, bool wait_done)
0080 {
0081 u32 payload[4] = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffff00};
0082
0083 ar9003_mci_send_message(ah, MCI_REMOTE_RESET, 0, payload, 16,
0084 wait_done, false);
0085 udelay(5);
0086 }
0087
0088 static void ar9003_mci_send_lna_transfer(struct ath_hw *ah, bool wait_done)
0089 {
0090 u32 payload = 0x00000000;
0091
0092 ar9003_mci_send_message(ah, MCI_LNA_TRANS, 0, &payload, 1,
0093 wait_done, false);
0094 }
0095
0096 static void ar9003_mci_send_req_wake(struct ath_hw *ah, bool wait_done)
0097 {
0098 ar9003_mci_send_message(ah, MCI_REQ_WAKE, MCI_FLAG_DISABLE_TIMESTAMP,
0099 NULL, 0, wait_done, false);
0100 udelay(5);
0101 }
0102
0103 static void ar9003_mci_send_sys_waking(struct ath_hw *ah, bool wait_done)
0104 {
0105 ar9003_mci_send_message(ah, MCI_SYS_WAKING, MCI_FLAG_DISABLE_TIMESTAMP,
0106 NULL, 0, wait_done, false);
0107 }
0108
0109 static void ar9003_mci_send_lna_take(struct ath_hw *ah, bool wait_done)
0110 {
0111 u32 payload = 0x70000000;
0112
0113 ar9003_mci_send_message(ah, MCI_LNA_TAKE, 0, &payload, 1,
0114 wait_done, false);
0115 }
0116
0117 static void ar9003_mci_send_sys_sleeping(struct ath_hw *ah, bool wait_done)
0118 {
0119 ar9003_mci_send_message(ah, MCI_SYS_SLEEPING,
0120 MCI_FLAG_DISABLE_TIMESTAMP,
0121 NULL, 0, wait_done, false);
0122 }
0123
0124 static void ar9003_mci_send_coex_version_query(struct ath_hw *ah,
0125 bool wait_done)
0126 {
0127 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
0128 u32 payload[4] = {0, 0, 0, 0};
0129
0130 if (mci->bt_version_known ||
0131 (mci->bt_state == MCI_BT_SLEEP))
0132 return;
0133
0134 MCI_GPM_SET_TYPE_OPCODE(payload, MCI_GPM_COEX_AGENT,
0135 MCI_GPM_COEX_VERSION_QUERY);
0136 ar9003_mci_send_message(ah, MCI_GPM, 0, payload, 16, wait_done, true);
0137 }
0138
0139 static void ar9003_mci_send_coex_version_response(struct ath_hw *ah,
0140 bool wait_done)
0141 {
0142 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
0143 u32 payload[4] = {0, 0, 0, 0};
0144
0145 MCI_GPM_SET_TYPE_OPCODE(payload, MCI_GPM_COEX_AGENT,
0146 MCI_GPM_COEX_VERSION_RESPONSE);
0147 *(((u8 *)payload) + MCI_GPM_COEX_B_MAJOR_VERSION) =
0148 mci->wlan_ver_major;
0149 *(((u8 *)payload) + MCI_GPM_COEX_B_MINOR_VERSION) =
0150 mci->wlan_ver_minor;
0151 ar9003_mci_send_message(ah, MCI_GPM, 0, payload, 16, wait_done, true);
0152 }
0153
0154 static void ar9003_mci_send_coex_wlan_channels(struct ath_hw *ah,
0155 bool wait_done)
0156 {
0157 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
0158 u32 *payload = &mci->wlan_channels[0];
0159
0160 if (!mci->wlan_channels_update ||
0161 (mci->bt_state == MCI_BT_SLEEP))
0162 return;
0163
0164 MCI_GPM_SET_TYPE_OPCODE(payload, MCI_GPM_COEX_AGENT,
0165 MCI_GPM_COEX_WLAN_CHANNELS);
0166 ar9003_mci_send_message(ah, MCI_GPM, 0, payload, 16, wait_done, true);
0167 MCI_GPM_SET_TYPE_OPCODE(payload, 0xff, 0xff);
0168 }
0169
0170 static void ar9003_mci_send_coex_bt_status_query(struct ath_hw *ah,
0171 bool wait_done, u8 query_type)
0172 {
0173 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
0174 u32 payload[4] = {0, 0, 0, 0};
0175 bool query_btinfo;
0176
0177 if (mci->bt_state == MCI_BT_SLEEP)
0178 return;
0179
0180 query_btinfo = !!(query_type & (MCI_GPM_COEX_QUERY_BT_ALL_INFO |
0181 MCI_GPM_COEX_QUERY_BT_TOPOLOGY));
0182 MCI_GPM_SET_TYPE_OPCODE(payload, MCI_GPM_COEX_AGENT,
0183 MCI_GPM_COEX_STATUS_QUERY);
0184
0185 *(((u8 *)payload) + MCI_GPM_COEX_B_BT_BITMAP) = query_type;
0186
0187
0188
0189
0190
0191 if (!ar9003_mci_send_message(ah, MCI_GPM, 0, payload, 16,
0192 wait_done, true)) {
0193 if (query_btinfo)
0194 mci->need_flush_btinfo = true;
0195 }
0196
0197 if (query_btinfo)
0198 mci->query_bt = false;
0199 }
0200
0201 static void ar9003_mci_send_coex_halt_bt_gpm(struct ath_hw *ah, bool halt,
0202 bool wait_done)
0203 {
0204 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
0205 u32 payload[4] = {0, 0, 0, 0};
0206
0207 MCI_GPM_SET_TYPE_OPCODE(payload, MCI_GPM_COEX_AGENT,
0208 MCI_GPM_COEX_HALT_BT_GPM);
0209
0210 if (halt) {
0211 mci->query_bt = true;
0212
0213 mci->unhalt_bt_gpm = true;
0214 mci->need_flush_btinfo = true;
0215 *(((u8 *)payload) + MCI_GPM_COEX_B_HALT_STATE) =
0216 MCI_GPM_COEX_BT_GPM_HALT;
0217 } else
0218 *(((u8 *)payload) + MCI_GPM_COEX_B_HALT_STATE) =
0219 MCI_GPM_COEX_BT_GPM_UNHALT;
0220
0221 ar9003_mci_send_message(ah, MCI_GPM, 0, payload, 16, wait_done, true);
0222 }
0223
0224 static void ar9003_mci_prep_interface(struct ath_hw *ah)
0225 {
0226 struct ath_common *common = ath9k_hw_common(ah);
0227 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
0228 u32 saved_mci_int_en;
0229 u32 mci_timeout = 150;
0230
0231 mci->bt_state = MCI_BT_SLEEP;
0232 saved_mci_int_en = REG_READ(ah, AR_MCI_INTERRUPT_EN);
0233
0234 REG_WRITE(ah, AR_MCI_INTERRUPT_EN, 0);
0235 REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,
0236 REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_RAW));
0237 REG_WRITE(ah, AR_MCI_INTERRUPT_RAW,
0238 REG_READ(ah, AR_MCI_INTERRUPT_RAW));
0239
0240 ar9003_mci_remote_reset(ah, true);
0241 ar9003_mci_send_req_wake(ah, true);
0242
0243 if (!ar9003_mci_wait_for_interrupt(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,
0244 AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING, 500))
0245 goto clear_redunt;
0246
0247 mci->bt_state = MCI_BT_AWAKE;
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261
0262
0263
0264
0265 ar9003_mci_send_sys_waking(ah, true);
0266 udelay(10);
0267
0268
0269
0270
0271
0272 REG_WRITE(ah, AR_MCI_BT_PRI0, 0xFFFFFFFF);
0273 REG_WRITE(ah, AR_MCI_BT_PRI1, 0xFFFFFFFF);
0274 REG_WRITE(ah, AR_MCI_BT_PRI2, 0xFFFFFFFF);
0275 REG_WRITE(ah, AR_MCI_BT_PRI3, 0xFFFFFFFF);
0276 REG_WRITE(ah, AR_MCI_BT_PRI, 0X000000FF);
0277
0278
0279
0280
0281
0282
0283
0284 REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,
0285 AR_MCI_INTERRUPT_RX_MSG_CONT_RST);
0286 REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, AR_MCI_INTERRUPT_BT_PRI);
0287
0288 if (mci->is_2g && MCI_ANT_ARCH_PA_LNA_SHARED(mci)) {
0289 ar9003_mci_send_lna_transfer(ah, true);
0290 udelay(5);
0291 }
0292
0293 if (mci->is_2g && !mci->update_2g5g && MCI_ANT_ARCH_PA_LNA_SHARED(mci)) {
0294 if (ar9003_mci_wait_for_interrupt(ah,
0295 AR_MCI_INTERRUPT_RX_MSG_RAW,
0296 AR_MCI_INTERRUPT_RX_MSG_LNA_INFO,
0297 mci_timeout))
0298 ath_dbg(common, MCI,
0299 "MCI WLAN has control over the LNA & BT obeys it\n");
0300 else
0301 ath_dbg(common, MCI,
0302 "MCI BT didn't respond to LNA_TRANS\n");
0303 }
0304
0305 clear_redunt:
0306
0307 if ((mci->bt_state == MCI_BT_AWAKE) &&
0308 (REG_READ_FIELD(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,
0309 AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING)) &&
0310 (REG_READ_FIELD(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,
0311 AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING) == 0)) {
0312 REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,
0313 AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING);
0314 REG_WRITE(ah, AR_MCI_INTERRUPT_RAW,
0315 AR_MCI_INTERRUPT_REMOTE_SLEEP_UPDATE);
0316 }
0317
0318 REG_WRITE(ah, AR_MCI_INTERRUPT_EN, saved_mci_int_en);
0319 }
0320
0321 void ar9003_mci_set_full_sleep(struct ath_hw *ah)
0322 {
0323 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
0324
0325 if (ar9003_mci_state(ah, MCI_STATE_ENABLE) &&
0326 (mci->bt_state != MCI_BT_SLEEP) &&
0327 !mci->halted_bt_gpm) {
0328 ar9003_mci_send_coex_halt_bt_gpm(ah, true, true);
0329 }
0330
0331 mci->ready = false;
0332 }
0333
0334 static void ar9003_mci_disable_interrupt(struct ath_hw *ah)
0335 {
0336 REG_WRITE(ah, AR_MCI_INTERRUPT_EN, 0);
0337 REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_EN, 0);
0338 }
0339
0340 static void ar9003_mci_enable_interrupt(struct ath_hw *ah)
0341 {
0342 REG_WRITE(ah, AR_MCI_INTERRUPT_EN, AR_MCI_INTERRUPT_DEFAULT);
0343 REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_EN,
0344 AR_MCI_INTERRUPT_RX_MSG_DEFAULT);
0345 }
0346
0347 static bool ar9003_mci_check_int(struct ath_hw *ah, u32 ints)
0348 {
0349 u32 intr;
0350
0351 intr = REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_RAW);
0352 return ((intr & ints) == ints);
0353 }
0354
0355 void ar9003_mci_get_interrupt(struct ath_hw *ah, u32 *raw_intr,
0356 u32 *rx_msg_intr)
0357 {
0358 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
0359
0360 *raw_intr = mci->raw_intr;
0361 *rx_msg_intr = mci->rx_msg_intr;
0362
0363
0364 mci->raw_intr = 0;
0365 mci->rx_msg_intr = 0;
0366 }
0367 EXPORT_SYMBOL(ar9003_mci_get_interrupt);
0368
0369 void ar9003_mci_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
0370 {
0371 struct ath_common *common = ath9k_hw_common(ah);
0372 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
0373 u32 raw_intr, rx_msg_intr;
0374
0375 rx_msg_intr = REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_RAW);
0376 raw_intr = REG_READ(ah, AR_MCI_INTERRUPT_RAW);
0377
0378 if ((raw_intr == 0xdeadbeef) || (rx_msg_intr == 0xdeadbeef)) {
0379 ath_dbg(common, MCI,
0380 "MCI gets 0xdeadbeef during int processing\n");
0381 } else {
0382 mci->rx_msg_intr |= rx_msg_intr;
0383 mci->raw_intr |= raw_intr;
0384 *masked |= ATH9K_INT_MCI;
0385
0386 if (rx_msg_intr & AR_MCI_INTERRUPT_RX_MSG_CONT_INFO)
0387 mci->cont_status = REG_READ(ah, AR_MCI_CONT_STATUS);
0388
0389 REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, rx_msg_intr);
0390 REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, raw_intr);
0391 }
0392 }
0393
0394 static void ar9003_mci_2g5g_changed(struct ath_hw *ah, bool is_2g)
0395 {
0396 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
0397
0398 if (!mci->update_2g5g &&
0399 (mci->is_2g != is_2g))
0400 mci->update_2g5g = true;
0401
0402 mci->is_2g = is_2g;
0403 }
0404
0405 static bool ar9003_mci_is_gpm_valid(struct ath_hw *ah, u32 msg_index)
0406 {
0407 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
0408 u32 *payload;
0409 u32 recv_type, offset;
0410
0411 if (msg_index == MCI_GPM_INVALID)
0412 return false;
0413
0414 offset = msg_index << 4;
0415
0416 payload = (u32 *)(mci->gpm_buf + offset);
0417 recv_type = MCI_GPM_TYPE(payload);
0418
0419 if (recv_type == MCI_GPM_RSVD_PATTERN)
0420 return false;
0421
0422 return true;
0423 }
0424
0425 static void ar9003_mci_observation_set_up(struct ath_hw *ah)
0426 {
0427 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
0428
0429 if (mci->config & ATH_MCI_CONFIG_MCI_OBS_MCI) {
0430 ath9k_hw_gpio_request_out(ah, 3, NULL,
0431 AR_GPIO_OUTPUT_MUX_AS_MCI_WLAN_DATA);
0432 ath9k_hw_gpio_request_out(ah, 2, NULL,
0433 AR_GPIO_OUTPUT_MUX_AS_MCI_WLAN_CLK);
0434 ath9k_hw_gpio_request_out(ah, 1, NULL,
0435 AR_GPIO_OUTPUT_MUX_AS_MCI_BT_DATA);
0436 ath9k_hw_gpio_request_out(ah, 0, NULL,
0437 AR_GPIO_OUTPUT_MUX_AS_MCI_BT_CLK);
0438 } else if (mci->config & ATH_MCI_CONFIG_MCI_OBS_TXRX) {
0439 ath9k_hw_gpio_request_out(ah, 3, NULL,
0440 AR_GPIO_OUTPUT_MUX_AS_WL_IN_TX);
0441 ath9k_hw_gpio_request_out(ah, 2, NULL,
0442 AR_GPIO_OUTPUT_MUX_AS_WL_IN_RX);
0443 ath9k_hw_gpio_request_out(ah, 1, NULL,
0444 AR_GPIO_OUTPUT_MUX_AS_BT_IN_TX);
0445 ath9k_hw_gpio_request_out(ah, 0, NULL,
0446 AR_GPIO_OUTPUT_MUX_AS_BT_IN_RX);
0447 ath9k_hw_gpio_request_out(ah, 5, NULL,
0448 AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
0449 } else if (mci->config & ATH_MCI_CONFIG_MCI_OBS_BT) {
0450 ath9k_hw_gpio_request_out(ah, 3, NULL,
0451 AR_GPIO_OUTPUT_MUX_AS_BT_IN_TX);
0452 ath9k_hw_gpio_request_out(ah, 2, NULL,
0453 AR_GPIO_OUTPUT_MUX_AS_BT_IN_RX);
0454 ath9k_hw_gpio_request_out(ah, 1, NULL,
0455 AR_GPIO_OUTPUT_MUX_AS_MCI_BT_DATA);
0456 ath9k_hw_gpio_request_out(ah, 0, NULL,
0457 AR_GPIO_OUTPUT_MUX_AS_MCI_BT_CLK);
0458 } else
0459 return;
0460
0461 REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE);
0462
0463 REG_RMW_FIELD(ah, AR_PHY_GLB_CONTROL, AR_GLB_DS_JTAG_DISABLE, 1);
0464 REG_RMW_FIELD(ah, AR_PHY_GLB_CONTROL, AR_GLB_WLAN_UART_INTF_EN, 0);
0465 REG_SET_BIT(ah, AR_GLB_GPIO_CONTROL, ATH_MCI_CONFIG_MCI_OBS_GPIO);
0466
0467 REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2, AR_BTCOEX_CTRL2_GPIO_OBS_SEL, 0);
0468 REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2, AR_BTCOEX_CTRL2_MAC_BB_OBS_SEL, 1);
0469 REG_WRITE(ah, AR_OBS, 0x4b);
0470 REG_RMW_FIELD(ah, AR_DIAG_SW, AR_DIAG_OBS_PT_SEL1, 0x03);
0471 REG_RMW_FIELD(ah, AR_DIAG_SW, AR_DIAG_OBS_PT_SEL2, 0x01);
0472 REG_RMW_FIELD(ah, AR_MACMISC, AR_MACMISC_MISC_OBS_BUS_LSB, 0x02);
0473 REG_RMW_FIELD(ah, AR_MACMISC, AR_MACMISC_MISC_OBS_BUS_MSB, 0x03);
0474 REG_RMW_FIELD(ah, AR_PHY_TEST_CTL_STATUS,
0475 AR_PHY_TEST_CTL_DEBUGPORT_SEL, 0x07);
0476 }
0477
0478 static bool ar9003_mci_send_coex_bt_flags(struct ath_hw *ah, bool wait_done,
0479 u8 opcode, u32 bt_flags)
0480 {
0481 u32 pld[4] = {0, 0, 0, 0};
0482
0483 MCI_GPM_SET_TYPE_OPCODE(pld, MCI_GPM_COEX_AGENT,
0484 MCI_GPM_COEX_BT_UPDATE_FLAGS);
0485
0486 *(((u8 *)pld) + MCI_GPM_COEX_B_BT_FLAGS_OP) = opcode;
0487 *(((u8 *)pld) + MCI_GPM_COEX_W_BT_FLAGS + 0) = bt_flags & 0xFF;
0488 *(((u8 *)pld) + MCI_GPM_COEX_W_BT_FLAGS + 1) = (bt_flags >> 8) & 0xFF;
0489 *(((u8 *)pld) + MCI_GPM_COEX_W_BT_FLAGS + 2) = (bt_flags >> 16) & 0xFF;
0490 *(((u8 *)pld) + MCI_GPM_COEX_W_BT_FLAGS + 3) = (bt_flags >> 24) & 0xFF;
0491
0492 return ar9003_mci_send_message(ah, MCI_GPM, 0, pld, 16,
0493 wait_done, true);
0494 }
0495
0496 static void ar9003_mci_sync_bt_state(struct ath_hw *ah)
0497 {
0498 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
0499 u32 cur_bt_state;
0500
0501 cur_bt_state = ar9003_mci_state(ah, MCI_STATE_REMOTE_SLEEP);
0502
0503 if (mci->bt_state != cur_bt_state)
0504 mci->bt_state = cur_bt_state;
0505
0506 if (mci->bt_state != MCI_BT_SLEEP) {
0507
0508 ar9003_mci_send_coex_version_query(ah, true);
0509 ar9003_mci_send_coex_wlan_channels(ah, true);
0510
0511 if (mci->unhalt_bt_gpm == true)
0512 ar9003_mci_send_coex_halt_bt_gpm(ah, false, true);
0513 }
0514 }
0515
0516 void ar9003_mci_check_bt(struct ath_hw *ah)
0517 {
0518 struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci;
0519
0520 if (!mci_hw->ready)
0521 return;
0522
0523
0524
0525
0526
0527 ar9003_mci_sync_bt_state(ah);
0528 ar9003_mci_2g5g_switch(ah, true);
0529
0530 if ((mci_hw->bt_state == MCI_BT_AWAKE) &&
0531 (mci_hw->query_bt == true)) {
0532 mci_hw->need_flush_btinfo = true;
0533 }
0534 }
0535
0536 static void ar9003_mci_process_gpm_extra(struct ath_hw *ah, u8 gpm_type,
0537 u8 gpm_opcode, u32 *p_gpm)
0538 {
0539 struct ath_common *common = ath9k_hw_common(ah);
0540 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
0541 u8 *p_data = (u8 *) p_gpm;
0542
0543 if (gpm_type != MCI_GPM_COEX_AGENT)
0544 return;
0545
0546 switch (gpm_opcode) {
0547 case MCI_GPM_COEX_VERSION_QUERY:
0548 ath_dbg(common, MCI, "MCI Recv GPM COEX Version Query\n");
0549 ar9003_mci_send_coex_version_response(ah, true);
0550 break;
0551 case MCI_GPM_COEX_VERSION_RESPONSE:
0552 ath_dbg(common, MCI, "MCI Recv GPM COEX Version Response\n");
0553 mci->bt_ver_major =
0554 *(p_data + MCI_GPM_COEX_B_MAJOR_VERSION);
0555 mci->bt_ver_minor =
0556 *(p_data + MCI_GPM_COEX_B_MINOR_VERSION);
0557 mci->bt_version_known = true;
0558 ath_dbg(common, MCI, "MCI BT Coex version: %d.%d\n",
0559 mci->bt_ver_major, mci->bt_ver_minor);
0560 break;
0561 case MCI_GPM_COEX_STATUS_QUERY:
0562 ath_dbg(common, MCI,
0563 "MCI Recv GPM COEX Status Query = 0x%02X\n",
0564 *(p_data + MCI_GPM_COEX_B_WLAN_BITMAP));
0565 mci->wlan_channels_update = true;
0566 ar9003_mci_send_coex_wlan_channels(ah, true);
0567 break;
0568 case MCI_GPM_COEX_BT_PROFILE_INFO:
0569 mci->query_bt = true;
0570 ath_dbg(common, MCI, "MCI Recv GPM COEX BT_Profile_Info\n");
0571 break;
0572 case MCI_GPM_COEX_BT_STATUS_UPDATE:
0573 mci->query_bt = true;
0574 ath_dbg(common, MCI,
0575 "MCI Recv GPM COEX BT_Status_Update SEQ=%d (drop&query)\n",
0576 *(p_gpm + 3));
0577 break;
0578 default:
0579 break;
0580 }
0581 }
0582
0583 static u32 ar9003_mci_wait_for_gpm(struct ath_hw *ah, u8 gpm_type,
0584 u8 gpm_opcode, int time_out)
0585 {
0586 struct ath_common *common = ath9k_hw_common(ah);
0587 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
0588 u32 *p_gpm = NULL, mismatch = 0, more_data;
0589 u32 offset;
0590 u8 recv_type = 0, recv_opcode = 0;
0591 bool b_is_bt_cal_done = (gpm_type == MCI_GPM_BT_CAL_DONE);
0592
0593 more_data = time_out ? MCI_GPM_NOMORE : MCI_GPM_MORE;
0594
0595 while (time_out > 0) {
0596 if (p_gpm) {
0597 MCI_GPM_RECYCLE(p_gpm);
0598 p_gpm = NULL;
0599 }
0600
0601 if (more_data != MCI_GPM_MORE)
0602 time_out = ar9003_mci_wait_for_interrupt(ah,
0603 AR_MCI_INTERRUPT_RX_MSG_RAW,
0604 AR_MCI_INTERRUPT_RX_MSG_GPM,
0605 time_out);
0606
0607 if (!time_out)
0608 break;
0609
0610 offset = ar9003_mci_get_next_gpm_offset(ah, &more_data);
0611
0612 if (offset == MCI_GPM_INVALID)
0613 continue;
0614
0615 p_gpm = (u32 *) (mci->gpm_buf + offset);
0616 recv_type = MCI_GPM_TYPE(p_gpm);
0617 recv_opcode = MCI_GPM_OPCODE(p_gpm);
0618
0619 if (MCI_GPM_IS_CAL_TYPE(recv_type)) {
0620 if (recv_type == gpm_type) {
0621 if ((gpm_type == MCI_GPM_BT_CAL_DONE) &&
0622 !b_is_bt_cal_done) {
0623 gpm_type = MCI_GPM_BT_CAL_GRANT;
0624 continue;
0625 }
0626 break;
0627 }
0628 } else if ((recv_type == gpm_type) &&
0629 (recv_opcode == gpm_opcode))
0630 break;
0631
0632
0633
0634
0635
0636
0637
0638
0639
0640
0641
0642
0643
0644
0645 if ((gpm_type == MCI_GPM_BT_CAL_GRANT) &&
0646 (recv_type == MCI_GPM_BT_CAL_REQ)) {
0647
0648 u32 payload[4] = {0, 0, 0, 0};
0649
0650 gpm_type = MCI_GPM_BT_CAL_DONE;
0651 MCI_GPM_SET_CAL_TYPE(payload,
0652 MCI_GPM_WLAN_CAL_GRANT);
0653 ar9003_mci_send_message(ah, MCI_GPM, 0, payload, 16,
0654 false, false);
0655 continue;
0656 } else {
0657 ath_dbg(common, MCI, "MCI GPM subtype not match 0x%x\n",
0658 *(p_gpm + 1));
0659 mismatch++;
0660 ar9003_mci_process_gpm_extra(ah, recv_type,
0661 recv_opcode, p_gpm);
0662 }
0663 }
0664
0665 if (p_gpm) {
0666 MCI_GPM_RECYCLE(p_gpm);
0667 p_gpm = NULL;
0668 }
0669
0670 if (time_out <= 0)
0671 time_out = 0;
0672
0673 while (more_data == MCI_GPM_MORE) {
0674 offset = ar9003_mci_get_next_gpm_offset(ah, &more_data);
0675 if (offset == MCI_GPM_INVALID)
0676 break;
0677
0678 p_gpm = (u32 *) (mci->gpm_buf + offset);
0679 recv_type = MCI_GPM_TYPE(p_gpm);
0680 recv_opcode = MCI_GPM_OPCODE(p_gpm);
0681
0682 if (!MCI_GPM_IS_CAL_TYPE(recv_type))
0683 ar9003_mci_process_gpm_extra(ah, recv_type,
0684 recv_opcode, p_gpm);
0685
0686 MCI_GPM_RECYCLE(p_gpm);
0687 }
0688
0689 return time_out;
0690 }
0691
0692 bool ar9003_mci_start_reset(struct ath_hw *ah, struct ath9k_channel *chan)
0693 {
0694 struct ath_common *common = ath9k_hw_common(ah);
0695 struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci;
0696 u32 payload[4] = {0, 0, 0, 0};
0697
0698 ar9003_mci_2g5g_changed(ah, IS_CHAN_2GHZ(chan));
0699
0700 if (mci_hw->bt_state != MCI_BT_CAL_START)
0701 return false;
0702
0703 mci_hw->bt_state = MCI_BT_CAL;
0704
0705
0706
0707
0708
0709
0710 ar9003_mci_disable_interrupt(ah);
0711
0712 MCI_GPM_SET_CAL_TYPE(payload, MCI_GPM_WLAN_CAL_GRANT);
0713 ar9003_mci_send_message(ah, MCI_GPM, 0, payload,
0714 16, true, false);
0715
0716
0717
0718 if (ar9003_mci_wait_for_gpm(ah, MCI_GPM_BT_CAL_DONE,
0719 0, 25000))
0720 ath_dbg(common, MCI, "MCI BT_CAL_DONE received\n");
0721 else
0722 ath_dbg(common, MCI,
0723 "MCI BT_CAL_DONE not received\n");
0724
0725 mci_hw->bt_state = MCI_BT_AWAKE;
0726
0727 ar9003_mci_enable_interrupt(ah);
0728
0729 return true;
0730 }
0731
0732 int ar9003_mci_end_reset(struct ath_hw *ah, struct ath9k_channel *chan,
0733 struct ath9k_hw_cal_data *caldata)
0734 {
0735 struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci;
0736
0737 if (!mci_hw->ready)
0738 return 0;
0739
0740 if (!IS_CHAN_2GHZ(chan) || (mci_hw->bt_state != MCI_BT_SLEEP))
0741 goto exit;
0742
0743 if (!ar9003_mci_check_int(ah, AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET) &&
0744 !ar9003_mci_check_int(ah, AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE))
0745 goto exit;
0746
0747
0748
0749
0750
0751
0752
0753 REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,
0754 (AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET |
0755 AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE));
0756
0757 ar9003_mci_remote_reset(ah, true);
0758 ar9003_mci_send_sys_waking(ah, true);
0759 udelay(1);
0760
0761 if (IS_CHAN_2GHZ(chan))
0762 ar9003_mci_send_lna_transfer(ah, true);
0763
0764 mci_hw->bt_state = MCI_BT_AWAKE;
0765
0766 REG_CLR_BIT(ah, AR_PHY_TIMING4,
0767 1 << AR_PHY_TIMING_CONTROL4_DO_GAIN_DC_IQ_CAL_SHIFT);
0768
0769 if (caldata) {
0770 clear_bit(TXIQCAL_DONE, &caldata->cal_flags);
0771 clear_bit(TXCLCAL_DONE, &caldata->cal_flags);
0772 clear_bit(RTT_DONE, &caldata->cal_flags);
0773 }
0774
0775 if (!ath9k_hw_init_cal(ah, chan))
0776 return -EIO;
0777
0778 REG_SET_BIT(ah, AR_PHY_TIMING4,
0779 1 << AR_PHY_TIMING_CONTROL4_DO_GAIN_DC_IQ_CAL_SHIFT);
0780
0781 exit:
0782 ar9003_mci_enable_interrupt(ah);
0783 return 0;
0784 }
0785
0786 static void ar9003_mci_mute_bt(struct ath_hw *ah)
0787 {
0788 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
0789
0790
0791 REG_WRITE(ah, AR_MCI_MSG_ATTRIBUTES_TABLE, 0xffff0000);
0792 REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS0, 0xffffffff);
0793 REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS1, 0xffffffff);
0794 REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS2, 0xffffffff);
0795 REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS3, 0xffffffff);
0796 REG_SET_BIT(ah, AR_MCI_TX_CTRL, AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE);
0797
0798
0799 udelay(10);
0800
0801
0802
0803
0804
0805
0806 if (MCI_ANT_ARCH_PA_LNA_SHARED(mci)) {
0807 ar9003_mci_send_lna_take(ah, true);
0808 udelay(5);
0809 }
0810
0811 ar9003_mci_send_sys_sleeping(ah, true);
0812 }
0813
0814 static void ar9003_mci_osla_setup(struct ath_hw *ah, bool enable)
0815 {
0816 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
0817 u32 thresh;
0818
0819 if (!enable) {
0820 REG_CLR_BIT(ah, AR_BTCOEX_CTRL,
0821 AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN);
0822 return;
0823 }
0824 REG_RMW_FIELD(ah, AR_MCI_SCHD_TABLE_2, AR_MCI_SCHD_TABLE_2_HW_BASED, 1);
0825 REG_RMW_FIELD(ah, AR_MCI_SCHD_TABLE_2,
0826 AR_MCI_SCHD_TABLE_2_MEM_BASED, 1);
0827
0828 if (AR_SREV_9565(ah))
0829 REG_RMW_FIELD(ah, AR_MCI_MISC, AR_MCI_MISC_HW_FIX_EN, 1);
0830
0831 if (!(mci->config & ATH_MCI_CONFIG_DISABLE_AGGR_THRESH)) {
0832 thresh = MS(mci->config, ATH_MCI_CONFIG_AGGR_THRESH);
0833 REG_RMW_FIELD(ah, AR_BTCOEX_CTRL,
0834 AR_BTCOEX_CTRL_AGGR_THRESH, thresh);
0835 REG_RMW_FIELD(ah, AR_BTCOEX_CTRL,
0836 AR_BTCOEX_CTRL_TIME_TO_NEXT_BT_THRESH_EN, 1);
0837 } else
0838 REG_RMW_FIELD(ah, AR_BTCOEX_CTRL,
0839 AR_BTCOEX_CTRL_TIME_TO_NEXT_BT_THRESH_EN, 0);
0840
0841 REG_RMW_FIELD(ah, AR_BTCOEX_CTRL,
0842 AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN, 1);
0843 }
0844
0845 static void ar9003_mci_stat_setup(struct ath_hw *ah)
0846 {
0847 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
0848
0849 if (!AR_SREV_9565(ah))
0850 return;
0851
0852 if (mci->config & ATH_MCI_CONFIG_MCI_STAT_DBG) {
0853 REG_RMW_FIELD(ah, AR_MCI_DBG_CNT_CTRL,
0854 AR_MCI_DBG_CNT_CTRL_ENABLE, 1);
0855 REG_RMW_FIELD(ah, AR_MCI_DBG_CNT_CTRL,
0856 AR_MCI_DBG_CNT_CTRL_BT_LINKID,
0857 MCI_STAT_ALL_BT_LINKID);
0858 } else {
0859 REG_RMW_FIELD(ah, AR_MCI_DBG_CNT_CTRL,
0860 AR_MCI_DBG_CNT_CTRL_ENABLE, 0);
0861 }
0862 }
0863
0864 static void ar9003_mci_set_btcoex_ctrl_9565_1ANT(struct ath_hw *ah)
0865 {
0866 u32 regval;
0867
0868 regval = SM(1, AR_BTCOEX_CTRL_AR9462_MODE) |
0869 SM(1, AR_BTCOEX_CTRL_WBTIMER_EN) |
0870 SM(1, AR_BTCOEX_CTRL_PA_SHARED) |
0871 SM(1, AR_BTCOEX_CTRL_LNA_SHARED) |
0872 SM(1, AR_BTCOEX_CTRL_NUM_ANTENNAS) |
0873 SM(1, AR_BTCOEX_CTRL_RX_CHAIN_MASK) |
0874 SM(0, AR_BTCOEX_CTRL_1_CHAIN_ACK) |
0875 SM(0, AR_BTCOEX_CTRL_1_CHAIN_BCN) |
0876 SM(0, AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN);
0877
0878 REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2,
0879 AR_BTCOEX_CTRL2_TX_CHAIN_MASK, 0x1);
0880 REG_WRITE(ah, AR_BTCOEX_CTRL, regval);
0881 }
0882
0883 static void ar9003_mci_set_btcoex_ctrl_9565_2ANT(struct ath_hw *ah)
0884 {
0885 u32 regval;
0886
0887 regval = SM(1, AR_BTCOEX_CTRL_AR9462_MODE) |
0888 SM(1, AR_BTCOEX_CTRL_WBTIMER_EN) |
0889 SM(0, AR_BTCOEX_CTRL_PA_SHARED) |
0890 SM(0, AR_BTCOEX_CTRL_LNA_SHARED) |
0891 SM(2, AR_BTCOEX_CTRL_NUM_ANTENNAS) |
0892 SM(1, AR_BTCOEX_CTRL_RX_CHAIN_MASK) |
0893 SM(0, AR_BTCOEX_CTRL_1_CHAIN_ACK) |
0894 SM(0, AR_BTCOEX_CTRL_1_CHAIN_BCN) |
0895 SM(0, AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN);
0896
0897 REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2,
0898 AR_BTCOEX_CTRL2_TX_CHAIN_MASK, 0x0);
0899 REG_WRITE(ah, AR_BTCOEX_CTRL, regval);
0900 }
0901
0902 static void ar9003_mci_set_btcoex_ctrl_9462(struct ath_hw *ah)
0903 {
0904 u32 regval;
0905
0906 regval = SM(1, AR_BTCOEX_CTRL_AR9462_MODE) |
0907 SM(1, AR_BTCOEX_CTRL_WBTIMER_EN) |
0908 SM(1, AR_BTCOEX_CTRL_PA_SHARED) |
0909 SM(1, AR_BTCOEX_CTRL_LNA_SHARED) |
0910 SM(2, AR_BTCOEX_CTRL_NUM_ANTENNAS) |
0911 SM(3, AR_BTCOEX_CTRL_RX_CHAIN_MASK) |
0912 SM(0, AR_BTCOEX_CTRL_1_CHAIN_ACK) |
0913 SM(0, AR_BTCOEX_CTRL_1_CHAIN_BCN) |
0914 SM(0, AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN);
0915
0916 REG_WRITE(ah, AR_BTCOEX_CTRL, regval);
0917 }
0918
0919 int ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g,
0920 bool is_full_sleep)
0921 {
0922 struct ath_common *common = ath9k_hw_common(ah);
0923 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
0924 u32 regval, i;
0925
0926 ath_dbg(common, MCI, "MCI Reset (full_sleep = %d, is_2g = %d)\n",
0927 is_full_sleep, is_2g);
0928
0929 if (REG_READ(ah, AR_BTCOEX_CTRL) == 0xdeadbeef) {
0930 ath_err(common, "BTCOEX control register is dead\n");
0931 return -EINVAL;
0932 }
0933
0934
0935 REG_WRITE(ah, AR_MCI_GPM_0, mci->gpm_addr);
0936 REG_WRITE(ah, AR_MCI_GPM_1, mci->gpm_len);
0937 REG_WRITE(ah, AR_MCI_SCHD_TABLE_0, mci->sched_addr);
0938
0939
0940
0941
0942
0943 if (AR_SREV_9565(ah)) {
0944 u8 ant = MS(mci->config, ATH_MCI_CONFIG_ANT_ARCH);
0945
0946 if (ant == ATH_MCI_ANT_ARCH_1_ANT_PA_LNA_SHARED)
0947 ar9003_mci_set_btcoex_ctrl_9565_1ANT(ah);
0948 else
0949 ar9003_mci_set_btcoex_ctrl_9565_2ANT(ah);
0950 } else {
0951 ar9003_mci_set_btcoex_ctrl_9462(ah);
0952 }
0953
0954 if (is_2g && !(mci->config & ATH_MCI_CONFIG_DISABLE_OSLA))
0955 ar9003_mci_osla_setup(ah, true);
0956 else
0957 ar9003_mci_osla_setup(ah, false);
0958
0959 REG_SET_BIT(ah, AR_PHY_GLB_CONTROL,
0960 AR_BTCOEX_CTRL_SPDT_ENABLE);
0961 REG_RMW_FIELD(ah, AR_BTCOEX_CTRL3,
0962 AR_BTCOEX_CTRL3_CONT_INFO_TIMEOUT, 20);
0963
0964 REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2, AR_BTCOEX_CTRL2_RX_DEWEIGHT, 0);
0965 REG_RMW_FIELD(ah, AR_PCU_MISC, AR_PCU_BT_ANT_PREVENT_RX, 0);
0966
0967
0968 REG_RMW_FIELD(ah, AR_BTCOEX_WL_LNA, AR_BTCOEX_WL_LNA_TIMEOUT, 0x3D090);
0969
0970
0971 if (mci->config & ATH_MCI_CONFIG_CONCUR_TX) {
0972 REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2,
0973 AR_BTCOEX_CTRL2_DESC_BASED_TXPWR_ENABLE, 0);
0974 REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2,
0975 AR_BTCOEX_CTRL2_TXPWR_THRESH, 0x7f);
0976 REG_RMW_FIELD(ah, AR_BTCOEX_CTRL,
0977 AR_BTCOEX_CTRL_REDUCE_TXPWR, 0);
0978 for (i = 0; i < 8; i++)
0979 REG_WRITE(ah, AR_BTCOEX_MAX_TXPWR(i), 0x7f7f7f7f);
0980 }
0981
0982 regval = MS(mci->config, ATH_MCI_CONFIG_CLK_DIV);
0983 REG_RMW_FIELD(ah, AR_MCI_TX_CTRL, AR_MCI_TX_CTRL_CLK_DIV, regval);
0984 REG_SET_BIT(ah, AR_BTCOEX_CTRL, AR_BTCOEX_CTRL_MCI_MODE_EN);
0985
0986
0987 regval = REG_READ(ah, AR_MCI_COMMAND2);
0988 regval |= SM(1, AR_MCI_COMMAND2_RESET_TX);
0989 REG_WRITE(ah, AR_MCI_COMMAND2, regval);
0990
0991 udelay(1);
0992
0993 regval &= ~SM(1, AR_MCI_COMMAND2_RESET_TX);
0994 REG_WRITE(ah, AR_MCI_COMMAND2, regval);
0995
0996 if (is_full_sleep) {
0997 ar9003_mci_mute_bt(ah);
0998 udelay(100);
0999 }
1000
1001
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
1011 ar9003_mci_state(ah, MCI_STATE_INIT_GPM_OFFSET);
1012
1013 REG_WRITE(ah, AR_MCI_MSG_ATTRIBUTES_TABLE,
1014 (SM(0xe801, AR_MCI_MSG_ATTRIBUTES_TABLE_INVALID_HDR) |
1015 SM(0x0000, AR_MCI_MSG_ATTRIBUTES_TABLE_CHECKSUM)));
1016
1017 if (MCI_ANT_ARCH_PA_LNA_SHARED(mci))
1018 REG_CLR_BIT(ah, AR_MCI_TX_CTRL,
1019 AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE);
1020 else
1021 REG_SET_BIT(ah, AR_MCI_TX_CTRL,
1022 AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE);
1023
1024 ar9003_mci_observation_set_up(ah);
1025
1026 mci->ready = true;
1027 ar9003_mci_prep_interface(ah);
1028 ar9003_mci_stat_setup(ah);
1029
1030 if (en_int)
1031 ar9003_mci_enable_interrupt(ah);
1032
1033 if (ath9k_hw_is_aic_enabled(ah))
1034 ar9003_aic_start_normal(ah);
1035
1036 return 0;
1037 }
1038
1039 void ar9003_mci_stop_bt(struct ath_hw *ah, bool save_fullsleep)
1040 {
1041 struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci;
1042
1043 ar9003_mci_disable_interrupt(ah);
1044
1045 if (mci_hw->ready && !save_fullsleep) {
1046 ar9003_mci_mute_bt(ah);
1047 udelay(20);
1048 REG_WRITE(ah, AR_BTCOEX_CTRL, 0);
1049 }
1050
1051 mci_hw->bt_state = MCI_BT_SLEEP;
1052 mci_hw->ready = false;
1053 }
1054
1055 static void ar9003_mci_send_2g5g_status(struct ath_hw *ah, bool wait_done)
1056 {
1057 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
1058 u32 to_set, to_clear;
1059
1060 if (!mci->update_2g5g || (mci->bt_state == MCI_BT_SLEEP))
1061 return;
1062
1063 if (mci->is_2g) {
1064 to_clear = MCI_2G_FLAGS_CLEAR_MASK;
1065 to_set = MCI_2G_FLAGS_SET_MASK;
1066 } else {
1067 to_clear = MCI_5G_FLAGS_CLEAR_MASK;
1068 to_set = MCI_5G_FLAGS_SET_MASK;
1069 }
1070
1071 if (to_clear)
1072 ar9003_mci_send_coex_bt_flags(ah, wait_done,
1073 MCI_GPM_COEX_BT_FLAGS_CLEAR,
1074 to_clear);
1075 if (to_set)
1076 ar9003_mci_send_coex_bt_flags(ah, wait_done,
1077 MCI_GPM_COEX_BT_FLAGS_SET,
1078 to_set);
1079 }
1080
1081 static void ar9003_mci_queue_unsent_gpm(struct ath_hw *ah, u8 header,
1082 u32 *payload, bool queue)
1083 {
1084 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
1085 u8 type, opcode;
1086
1087
1088 if (header != MCI_GPM)
1089 return;
1090
1091 type = MCI_GPM_TYPE(payload);
1092 opcode = MCI_GPM_OPCODE(payload);
1093
1094 if (type != MCI_GPM_COEX_AGENT)
1095 return;
1096
1097 switch (opcode) {
1098 case MCI_GPM_COEX_BT_UPDATE_FLAGS:
1099 if (*(((u8 *)payload) + MCI_GPM_COEX_B_BT_FLAGS_OP) ==
1100 MCI_GPM_COEX_BT_FLAGS_READ)
1101 break;
1102
1103 mci->update_2g5g = queue;
1104
1105 break;
1106 case MCI_GPM_COEX_WLAN_CHANNELS:
1107 mci->wlan_channels_update = queue;
1108 break;
1109 case MCI_GPM_COEX_HALT_BT_GPM:
1110 if (*(((u8 *)payload) + MCI_GPM_COEX_B_HALT_STATE) ==
1111 MCI_GPM_COEX_BT_GPM_UNHALT) {
1112 mci->unhalt_bt_gpm = queue;
1113
1114 if (!queue)
1115 mci->halted_bt_gpm = false;
1116 }
1117
1118 if (*(((u8 *)payload) + MCI_GPM_COEX_B_HALT_STATE) ==
1119 MCI_GPM_COEX_BT_GPM_HALT) {
1120
1121 mci->halted_bt_gpm = !queue;
1122 }
1123
1124 break;
1125 default:
1126 break;
1127 }
1128 }
1129
1130 void ar9003_mci_2g5g_switch(struct ath_hw *ah, bool force)
1131 {
1132 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
1133
1134 if (!mci->update_2g5g && !force)
1135 return;
1136
1137 if (mci->is_2g) {
1138 ar9003_mci_send_2g5g_status(ah, true);
1139 ar9003_mci_send_lna_transfer(ah, true);
1140 udelay(5);
1141
1142 REG_CLR_BIT(ah, AR_MCI_TX_CTRL,
1143 AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE);
1144 REG_CLR_BIT(ah, AR_PHY_GLB_CONTROL,
1145 AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL);
1146
1147 if (!(mci->config & ATH_MCI_CONFIG_DISABLE_OSLA))
1148 ar9003_mci_osla_setup(ah, true);
1149
1150 if (AR_SREV_9462(ah))
1151 REG_WRITE(ah, AR_SELFGEN_MASK, 0x02);
1152 } else {
1153 ar9003_mci_send_lna_take(ah, true);
1154 udelay(5);
1155
1156 REG_SET_BIT(ah, AR_MCI_TX_CTRL,
1157 AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE);
1158 REG_SET_BIT(ah, AR_PHY_GLB_CONTROL,
1159 AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL);
1160
1161 ar9003_mci_osla_setup(ah, false);
1162 ar9003_mci_send_2g5g_status(ah, true);
1163 }
1164 }
1165
1166 bool ar9003_mci_send_message(struct ath_hw *ah, u8 header, u32 flag,
1167 u32 *payload, u8 len, bool wait_done,
1168 bool check_bt)
1169 {
1170 struct ath_common *common = ath9k_hw_common(ah);
1171 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
1172 bool msg_sent = false;
1173 u32 regval;
1174 u32 saved_mci_int_en;
1175 int i;
1176
1177 saved_mci_int_en = REG_READ(ah, AR_MCI_INTERRUPT_EN);
1178 regval = REG_READ(ah, AR_BTCOEX_CTRL);
1179
1180 if ((regval == 0xdeadbeef) || !(regval & AR_BTCOEX_CTRL_MCI_MODE_EN)) {
1181 ath_dbg(common, MCI,
1182 "MCI Not sending 0x%x. MCI is not enabled. full_sleep = %d\n",
1183 header, (ah->power_mode == ATH9K_PM_FULL_SLEEP) ? 1 : 0);
1184 ar9003_mci_queue_unsent_gpm(ah, header, payload, true);
1185 return false;
1186 } else if (check_bt && (mci->bt_state == MCI_BT_SLEEP)) {
1187 ath_dbg(common, MCI,
1188 "MCI Don't send message 0x%x. BT is in sleep state\n",
1189 header);
1190 ar9003_mci_queue_unsent_gpm(ah, header, payload, true);
1191 return false;
1192 }
1193
1194 if (wait_done)
1195 REG_WRITE(ah, AR_MCI_INTERRUPT_EN, 0);
1196
1197
1198
1199 REG_WRITE(ah, AR_MCI_INTERRUPT_RAW,
1200 (AR_MCI_INTERRUPT_SW_MSG_DONE |
1201 AR_MCI_INTERRUPT_MSG_FAIL_MASK));
1202
1203 if (payload) {
1204 for (i = 0; (i * 4) < len; i++)
1205 REG_WRITE(ah, (AR_MCI_TX_PAYLOAD0 + i * 4),
1206 *(payload + i));
1207 }
1208
1209 REG_WRITE(ah, AR_MCI_COMMAND0,
1210 (SM((flag & MCI_FLAG_DISABLE_TIMESTAMP),
1211 AR_MCI_COMMAND0_DISABLE_TIMESTAMP) |
1212 SM(len, AR_MCI_COMMAND0_LEN) |
1213 SM(header, AR_MCI_COMMAND0_HEADER)));
1214
1215 if (wait_done &&
1216 !(ar9003_mci_wait_for_interrupt(ah, AR_MCI_INTERRUPT_RAW,
1217 AR_MCI_INTERRUPT_SW_MSG_DONE, 500)))
1218 ar9003_mci_queue_unsent_gpm(ah, header, payload, true);
1219 else {
1220 ar9003_mci_queue_unsent_gpm(ah, header, payload, false);
1221 msg_sent = true;
1222 }
1223
1224 if (wait_done)
1225 REG_WRITE(ah, AR_MCI_INTERRUPT_EN, saved_mci_int_en);
1226
1227 return msg_sent;
1228 }
1229 EXPORT_SYMBOL(ar9003_mci_send_message);
1230
1231 void ar9003_mci_init_cal_req(struct ath_hw *ah, bool *is_reusable)
1232 {
1233 struct ath_common *common = ath9k_hw_common(ah);
1234 struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci;
1235 u32 pld[4] = {0, 0, 0, 0};
1236
1237 if ((mci_hw->bt_state != MCI_BT_AWAKE) ||
1238 (mci_hw->config & ATH_MCI_CONFIG_DISABLE_MCI_CAL))
1239 return;
1240
1241 MCI_GPM_SET_CAL_TYPE(pld, MCI_GPM_WLAN_CAL_REQ);
1242 pld[MCI_GPM_WLAN_CAL_W_SEQUENCE] = mci_hw->wlan_cal_seq++;
1243
1244 ar9003_mci_send_message(ah, MCI_GPM, 0, pld, 16, true, false);
1245
1246 if (ar9003_mci_wait_for_gpm(ah, MCI_GPM_BT_CAL_GRANT, 0, 50000)) {
1247 ath_dbg(common, MCI, "MCI BT_CAL_GRANT received\n");
1248 } else {
1249 *is_reusable = false;
1250 ath_dbg(common, MCI, "MCI BT_CAL_GRANT not received\n");
1251 }
1252 }
1253
1254 void ar9003_mci_init_cal_done(struct ath_hw *ah)
1255 {
1256 struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci;
1257 u32 pld[4] = {0, 0, 0, 0};
1258
1259 if ((mci_hw->bt_state != MCI_BT_AWAKE) ||
1260 (mci_hw->config & ATH_MCI_CONFIG_DISABLE_MCI_CAL))
1261 return;
1262
1263 MCI_GPM_SET_CAL_TYPE(pld, MCI_GPM_WLAN_CAL_DONE);
1264 pld[MCI_GPM_WLAN_CAL_W_SEQUENCE] = mci_hw->wlan_cal_done++;
1265 ar9003_mci_send_message(ah, MCI_GPM, 0, pld, 16, true, false);
1266 }
1267
1268 int ar9003_mci_setup(struct ath_hw *ah, u32 gpm_addr, void *gpm_buf,
1269 u16 len, u32 sched_addr)
1270 {
1271 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
1272
1273 mci->gpm_addr = gpm_addr;
1274 mci->gpm_buf = gpm_buf;
1275 mci->gpm_len = len;
1276 mci->sched_addr = sched_addr;
1277
1278 return ar9003_mci_reset(ah, true, true, true);
1279 }
1280 EXPORT_SYMBOL(ar9003_mci_setup);
1281
1282 void ar9003_mci_cleanup(struct ath_hw *ah)
1283 {
1284
1285 REG_WRITE(ah, AR_BTCOEX_CTRL, 0x00);
1286 ar9003_mci_disable_interrupt(ah);
1287 }
1288 EXPORT_SYMBOL(ar9003_mci_cleanup);
1289
1290 u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type)
1291 {
1292 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
1293 u32 value = 0, tsf;
1294 u8 query_type;
1295
1296 switch (state_type) {
1297 case MCI_STATE_ENABLE:
1298 if (mci->ready) {
1299 value = REG_READ(ah, AR_BTCOEX_CTRL);
1300
1301 if ((value == 0xdeadbeef) || (value == 0xffffffff))
1302 value = 0;
1303 }
1304 value &= AR_BTCOEX_CTRL_MCI_MODE_EN;
1305 break;
1306 case MCI_STATE_INIT_GPM_OFFSET:
1307 value = MS(REG_READ(ah, AR_MCI_GPM_1), AR_MCI_GPM_WRITE_PTR);
1308
1309 if (value < mci->gpm_len)
1310 mci->gpm_idx = value;
1311 else
1312 mci->gpm_idx = 0;
1313 break;
1314 case MCI_STATE_LAST_SCHD_MSG_OFFSET:
1315 value = MS(REG_READ(ah, AR_MCI_RX_STATUS),
1316 AR_MCI_RX_LAST_SCHD_MSG_INDEX);
1317
1318 value <<= 4;
1319 break;
1320 case MCI_STATE_REMOTE_SLEEP:
1321 value = MS(REG_READ(ah, AR_MCI_RX_STATUS),
1322 AR_MCI_RX_REMOTE_SLEEP) ?
1323 MCI_BT_SLEEP : MCI_BT_AWAKE;
1324 break;
1325 case MCI_STATE_SET_BT_AWAKE:
1326 mci->bt_state = MCI_BT_AWAKE;
1327 ar9003_mci_send_coex_version_query(ah, true);
1328 ar9003_mci_send_coex_wlan_channels(ah, true);
1329
1330 if (mci->unhalt_bt_gpm)
1331 ar9003_mci_send_coex_halt_bt_gpm(ah, false, true);
1332
1333 ar9003_mci_2g5g_switch(ah, false);
1334 break;
1335 case MCI_STATE_RESET_REQ_WAKE:
1336 ar9003_mci_reset_req_wakeup(ah);
1337 mci->update_2g5g = true;
1338
1339 if (mci->config & ATH_MCI_CONFIG_MCI_OBS_MASK) {
1340
1341 if ((REG_READ(ah, AR_GLB_GPIO_CONTROL) &
1342 ATH_MCI_CONFIG_MCI_OBS_GPIO) !=
1343 ATH_MCI_CONFIG_MCI_OBS_GPIO) {
1344 ar9003_mci_observation_set_up(ah);
1345 }
1346 }
1347 break;
1348 case MCI_STATE_SEND_WLAN_COEX_VERSION:
1349 ar9003_mci_send_coex_version_response(ah, true);
1350 break;
1351 case MCI_STATE_SEND_VERSION_QUERY:
1352 ar9003_mci_send_coex_version_query(ah, true);
1353 break;
1354 case MCI_STATE_SEND_STATUS_QUERY:
1355 query_type = MCI_GPM_COEX_QUERY_BT_TOPOLOGY;
1356 ar9003_mci_send_coex_bt_status_query(ah, true, query_type);
1357 break;
1358 case MCI_STATE_RECOVER_RX:
1359 tsf = ath9k_hw_gettsf32(ah);
1360 if ((tsf - mci->last_recovery) <= MCI_RECOVERY_DUR_TSF) {
1361 ath_dbg(ath9k_hw_common(ah), MCI,
1362 "(MCI) ignore Rx recovery\n");
1363 break;
1364 }
1365 ath_dbg(ath9k_hw_common(ah), MCI, "(MCI) RECOVER RX\n");
1366 mci->last_recovery = tsf;
1367 ar9003_mci_prep_interface(ah);
1368 mci->query_bt = true;
1369 mci->need_flush_btinfo = true;
1370 ar9003_mci_send_coex_wlan_channels(ah, true);
1371 ar9003_mci_2g5g_switch(ah, false);
1372 break;
1373 case MCI_STATE_NEED_FTP_STOMP:
1374 value = !(mci->config & ATH_MCI_CONFIG_DISABLE_FTP_STOMP);
1375 break;
1376 case MCI_STATE_NEED_FLUSH_BT_INFO:
1377 value = (!mci->unhalt_bt_gpm && mci->need_flush_btinfo) ? 1 : 0;
1378 mci->need_flush_btinfo = false;
1379 break;
1380 case MCI_STATE_AIC_CAL:
1381 if (ath9k_hw_is_aic_enabled(ah))
1382 value = ar9003_aic_calibration(ah);
1383 break;
1384 case MCI_STATE_AIC_START:
1385 if (ath9k_hw_is_aic_enabled(ah))
1386 ar9003_aic_start_normal(ah);
1387 break;
1388 case MCI_STATE_AIC_CAL_RESET:
1389 if (ath9k_hw_is_aic_enabled(ah))
1390 value = ar9003_aic_cal_reset(ah);
1391 break;
1392 case MCI_STATE_AIC_CAL_SINGLE:
1393 if (ath9k_hw_is_aic_enabled(ah))
1394 value = ar9003_aic_calibration_single(ah);
1395 break;
1396 default:
1397 break;
1398 }
1399
1400 return value;
1401 }
1402 EXPORT_SYMBOL(ar9003_mci_state);
1403
1404 void ar9003_mci_bt_gain_ctrl(struct ath_hw *ah)
1405 {
1406 struct ath_common *common = ath9k_hw_common(ah);
1407 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
1408
1409 ath_dbg(common, MCI, "Give LNA and SPDT control to BT\n");
1410
1411 ar9003_mci_send_lna_take(ah, true);
1412 udelay(50);
1413
1414 REG_SET_BIT(ah, AR_PHY_GLB_CONTROL, AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL);
1415 mci->is_2g = false;
1416 mci->update_2g5g = true;
1417 ar9003_mci_send_2g5g_status(ah, true);
1418
1419
1420 mci->update_2g5g = true;
1421 }
1422
1423 void ar9003_mci_set_power_awake(struct ath_hw *ah)
1424 {
1425 u32 btcoex_ctrl2, diag_sw;
1426 int i;
1427 u8 lna_ctrl, bt_sleep;
1428
1429 for (i = 0; i < AH_WAIT_TIMEOUT; i++) {
1430 btcoex_ctrl2 = REG_READ(ah, AR_BTCOEX_CTRL2);
1431 if (btcoex_ctrl2 != 0xdeadbeef)
1432 break;
1433 udelay(AH_TIME_QUANTUM);
1434 }
1435 REG_WRITE(ah, AR_BTCOEX_CTRL2, (btcoex_ctrl2 | BIT(23)));
1436
1437 for (i = 0; i < AH_WAIT_TIMEOUT; i++) {
1438 diag_sw = REG_READ(ah, AR_DIAG_SW);
1439 if (diag_sw != 0xdeadbeef)
1440 break;
1441 udelay(AH_TIME_QUANTUM);
1442 }
1443 REG_WRITE(ah, AR_DIAG_SW, (diag_sw | BIT(27) | BIT(19) | BIT(18)));
1444 lna_ctrl = REG_READ(ah, AR_OBS_BUS_CTRL) & 0x3;
1445 bt_sleep = MS(REG_READ(ah, AR_MCI_RX_STATUS), AR_MCI_RX_REMOTE_SLEEP);
1446
1447 REG_WRITE(ah, AR_BTCOEX_CTRL2, btcoex_ctrl2);
1448 REG_WRITE(ah, AR_DIAG_SW, diag_sw);
1449
1450 if (bt_sleep && (lna_ctrl == 2)) {
1451 REG_SET_BIT(ah, AR_BTCOEX_RC, 0x1);
1452 REG_CLR_BIT(ah, AR_BTCOEX_RC, 0x1);
1453 udelay(50);
1454 }
1455 }
1456
1457 void ar9003_mci_check_gpm_offset(struct ath_hw *ah)
1458 {
1459 struct ath_common *common = ath9k_hw_common(ah);
1460 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
1461 u32 offset;
1462
1463
1464
1465
1466 offset = MS(REG_READ(ah, AR_MCI_GPM_1), AR_MCI_GPM_WRITE_PTR);
1467 if (mci->gpm_idx == offset)
1468 return;
1469 ath_dbg(common, MCI, "GPM cached write pointer mismatch %d %d\n",
1470 mci->gpm_idx, offset);
1471 mci->query_bt = true;
1472 mci->need_flush_btinfo = true;
1473 mci->gpm_idx = 0;
1474 }
1475
1476 u32 ar9003_mci_get_next_gpm_offset(struct ath_hw *ah, u32 *more)
1477 {
1478 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
1479 u32 offset, more_gpm = 0, gpm_ptr;
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490 REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,
1491 AR_MCI_INTERRUPT_RX_MSG_GPM);
1492
1493 gpm_ptr = MS(REG_READ(ah, AR_MCI_GPM_1), AR_MCI_GPM_WRITE_PTR);
1494 offset = gpm_ptr;
1495
1496 if (!offset)
1497 offset = mci->gpm_len - 1;
1498 else if (offset >= mci->gpm_len) {
1499 if (offset != 0xFFFF)
1500 offset = 0;
1501 } else {
1502 offset--;
1503 }
1504
1505 if ((offset == 0xFFFF) || (gpm_ptr == mci->gpm_idx)) {
1506 offset = MCI_GPM_INVALID;
1507 more_gpm = MCI_GPM_NOMORE;
1508 goto out;
1509 }
1510 for (;;) {
1511 u32 temp_index;
1512
1513
1514
1515 if (offset != mci->gpm_idx)
1516 more_gpm = MCI_GPM_MORE;
1517 else
1518 more_gpm = MCI_GPM_NOMORE;
1519
1520 temp_index = mci->gpm_idx;
1521
1522 if (temp_index >= mci->gpm_len)
1523 temp_index = 0;
1524
1525 mci->gpm_idx++;
1526
1527 if (mci->gpm_idx >= mci->gpm_len)
1528 mci->gpm_idx = 0;
1529
1530 if (ar9003_mci_is_gpm_valid(ah, temp_index)) {
1531 offset = temp_index;
1532 break;
1533 }
1534
1535 if (more_gpm == MCI_GPM_NOMORE) {
1536 offset = MCI_GPM_INVALID;
1537 break;
1538 }
1539 }
1540
1541 if (offset != MCI_GPM_INVALID)
1542 offset <<= 4;
1543 out:
1544 if (more)
1545 *more = more_gpm;
1546
1547 return offset;
1548 }
1549 EXPORT_SYMBOL(ar9003_mci_get_next_gpm_offset);
1550
1551 void ar9003_mci_set_bt_version(struct ath_hw *ah, u8 major, u8 minor)
1552 {
1553 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
1554
1555 mci->bt_ver_major = major;
1556 mci->bt_ver_minor = minor;
1557 mci->bt_version_known = true;
1558 ath_dbg(ath9k_hw_common(ah), MCI, "MCI BT version set: %d.%d\n",
1559 mci->bt_ver_major, mci->bt_ver_minor);
1560 }
1561 EXPORT_SYMBOL(ar9003_mci_set_bt_version);
1562
1563 void ar9003_mci_send_wlan_channels(struct ath_hw *ah)
1564 {
1565 struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
1566
1567 mci->wlan_channels_update = true;
1568 ar9003_mci_send_coex_wlan_channels(ah, true);
1569 }
1570 EXPORT_SYMBOL(ar9003_mci_send_wlan_channels);
1571
1572 u16 ar9003_mci_get_max_txpower(struct ath_hw *ah, u8 ctlmode)
1573 {
1574 if (!ah->btcoex_hw.mci.concur_tx)
1575 goto out;
1576
1577 if (ctlmode == CTL_2GHT20)
1578 return ATH_BTCOEX_HT20_MAX_TXPOWER;
1579 else if (ctlmode == CTL_2GHT40)
1580 return ATH_BTCOEX_HT40_MAX_TXPOWER;
1581
1582 out:
1583 return -1;
1584 }