linux/drivers/net/wireless/ath/ath9k/ar9003_mci.c
<<
>>
Prefs
   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
  23static 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
  32static 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
  78static 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
  87static 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
  95static 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
 102static 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
 108static 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
 116static 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
 123static 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
 138static 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
 153static 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
 169static 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
 200static 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
 223static 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) {
 288                ar9003_mci_send_lna_transfer(ah, true);
 289                udelay(5);
 290        }
 291
 292        if ((mci->is_2g && !mci->update_2g5g)) {
 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
 304clear_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
 320void 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
 333static 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
 339static 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
 346static 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
 354void 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}
 366EXPORT_SYMBOL(ar9003_mci_get_interrupt);
 367
 368void 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
 393static 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
 404static 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
 424static 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
 464static 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
 482static 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
 502void 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
 522static 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
 569static 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, false, &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, false, &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
 678bool 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
 718int 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        if (caldata) {
 753                caldata->done_txiqcal_once = false;
 754                caldata->done_txclcal_once = false;
 755                caldata->rtt_done = false;
 756        }
 757
 758        if (!ath9k_hw_init_cal(ah, chan))
 759                return -EIO;
 760
 761exit:
 762        ar9003_mci_enable_interrupt(ah);
 763        return 0;
 764}
 765
 766static void ar9003_mci_mute_bt(struct ath_hw *ah)
 767{
 768        /* disable all MCI messages */
 769        REG_WRITE(ah, AR_MCI_MSG_ATTRIBUTES_TABLE, 0xffff0000);
 770        REG_SET_BIT(ah, AR_MCI_TX_CTRL, AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE);
 771
 772        /* wait pending HW messages to flush out */
 773        udelay(10);
 774
 775        /*
 776         * Send LNA_TAKE and SYS_SLEEPING when
 777         * 1. reset not after resuming from full sleep
 778         * 2. before reset MCI RX, to quiet BT and avoid MCI RX misalignment
 779         */
 780        ar9003_mci_send_lna_take(ah, true);
 781
 782        udelay(5);
 783
 784        ar9003_mci_send_sys_sleeping(ah, true);
 785}
 786
 787static void ar9003_mci_osla_setup(struct ath_hw *ah, bool enable)
 788{
 789        struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
 790        u32 thresh;
 791
 792        if (!enable) {
 793                REG_CLR_BIT(ah, AR_BTCOEX_CTRL,
 794                            AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN);
 795                return;
 796        }
 797        REG_RMW_FIELD(ah, AR_MCI_SCHD_TABLE_2, AR_MCI_SCHD_TABLE_2_HW_BASED, 1);
 798        REG_RMW_FIELD(ah, AR_MCI_SCHD_TABLE_2,
 799                      AR_MCI_SCHD_TABLE_2_MEM_BASED, 1);
 800
 801        if (!(mci->config & ATH_MCI_CONFIG_DISABLE_AGGR_THRESH)) {
 802                thresh = MS(mci->config, ATH_MCI_CONFIG_AGGR_THRESH);
 803                REG_RMW_FIELD(ah, AR_BTCOEX_CTRL,
 804                              AR_BTCOEX_CTRL_AGGR_THRESH, thresh);
 805                REG_RMW_FIELD(ah, AR_BTCOEX_CTRL,
 806                              AR_BTCOEX_CTRL_TIME_TO_NEXT_BT_THRESH_EN, 1);
 807        } else
 808                REG_RMW_FIELD(ah, AR_BTCOEX_CTRL,
 809                              AR_BTCOEX_CTRL_TIME_TO_NEXT_BT_THRESH_EN, 0);
 810
 811        REG_RMW_FIELD(ah, AR_BTCOEX_CTRL,
 812                      AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN, 1);
 813}
 814
 815void ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g,
 816                      bool is_full_sleep)
 817{
 818        struct ath_common *common = ath9k_hw_common(ah);
 819        struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
 820        u32 regval;
 821
 822        ath_dbg(common, MCI, "MCI Reset (full_sleep = %d, is_2g = %d)\n",
 823                is_full_sleep, is_2g);
 824
 825        if (!mci->gpm_addr && !mci->sched_addr) {
 826                ath_dbg(common, MCI,
 827                        "MCI GPM and schedule buffers are not allocated\n");
 828                return;
 829        }
 830
 831        if (REG_READ(ah, AR_BTCOEX_CTRL) == 0xdeadbeef) {
 832                ath_dbg(common, MCI, "BTCOEX control register is dead\n");
 833                return;
 834        }
 835
 836        /* Program MCI DMA related registers */
 837        REG_WRITE(ah, AR_MCI_GPM_0, mci->gpm_addr);
 838        REG_WRITE(ah, AR_MCI_GPM_1, mci->gpm_len);
 839        REG_WRITE(ah, AR_MCI_SCHD_TABLE_0, mci->sched_addr);
 840
 841        /*
 842        * To avoid MCI state machine be affected by incoming remote MCI msgs,
 843        * MCI mode will be enabled later, right before reset the MCI TX and RX.
 844        */
 845
 846        regval = SM(1, AR_BTCOEX_CTRL_AR9462_MODE) |
 847                 SM(1, AR_BTCOEX_CTRL_WBTIMER_EN) |
 848                 SM(1, AR_BTCOEX_CTRL_PA_SHARED) |
 849                 SM(1, AR_BTCOEX_CTRL_LNA_SHARED) |
 850                 SM(2, AR_BTCOEX_CTRL_NUM_ANTENNAS) |
 851                 SM(3, AR_BTCOEX_CTRL_RX_CHAIN_MASK) |
 852                 SM(0, AR_BTCOEX_CTRL_1_CHAIN_ACK) |
 853                 SM(0, AR_BTCOEX_CTRL_1_CHAIN_BCN) |
 854                 SM(0, AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN);
 855
 856        REG_WRITE(ah, AR_BTCOEX_CTRL, regval);
 857
 858        if (is_2g && !(mci->config & ATH_MCI_CONFIG_DISABLE_OSLA))
 859                ar9003_mci_osla_setup(ah, true);
 860        else
 861                ar9003_mci_osla_setup(ah, false);
 862
 863        REG_SET_BIT(ah, AR_PHY_GLB_CONTROL,
 864                    AR_BTCOEX_CTRL_SPDT_ENABLE);
 865        REG_RMW_FIELD(ah, AR_BTCOEX_CTRL3,
 866                      AR_BTCOEX_CTRL3_CONT_INFO_TIMEOUT, 20);
 867
 868        REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2, AR_BTCOEX_CTRL2_RX_DEWEIGHT, 1);
 869        REG_RMW_FIELD(ah, AR_PCU_MISC, AR_PCU_BT_ANT_PREVENT_RX, 0);
 870
 871        regval = MS(mci->config, ATH_MCI_CONFIG_CLK_DIV);
 872        REG_RMW_FIELD(ah, AR_MCI_TX_CTRL, AR_MCI_TX_CTRL_CLK_DIV, regval);
 873        REG_SET_BIT(ah, AR_BTCOEX_CTRL, AR_BTCOEX_CTRL_MCI_MODE_EN);
 874
 875        /* Resetting the Rx and Tx paths of MCI */
 876        regval = REG_READ(ah, AR_MCI_COMMAND2);
 877        regval |= SM(1, AR_MCI_COMMAND2_RESET_TX);
 878        REG_WRITE(ah, AR_MCI_COMMAND2, regval);
 879
 880        udelay(1);
 881
 882        regval &= ~SM(1, AR_MCI_COMMAND2_RESET_TX);
 883        REG_WRITE(ah, AR_MCI_COMMAND2, regval);
 884
 885        if (is_full_sleep) {
 886                ar9003_mci_mute_bt(ah);
 887                udelay(100);
 888        }
 889
 890        /* Check pending GPM msg before MCI Reset Rx */
 891        ar9003_mci_check_gpm_offset(ah);
 892
 893        regval |= SM(1, AR_MCI_COMMAND2_RESET_RX);
 894        REG_WRITE(ah, AR_MCI_COMMAND2, regval);
 895        udelay(1);
 896        regval &= ~SM(1, AR_MCI_COMMAND2_RESET_RX);
 897        REG_WRITE(ah, AR_MCI_COMMAND2, regval);
 898
 899        ar9003_mci_get_next_gpm_offset(ah, true, NULL);
 900
 901        REG_WRITE(ah, AR_MCI_MSG_ATTRIBUTES_TABLE,
 902                  (SM(0xe801, AR_MCI_MSG_ATTRIBUTES_TABLE_INVALID_HDR) |
 903                   SM(0x0000, AR_MCI_MSG_ATTRIBUTES_TABLE_CHECKSUM)));
 904
 905        REG_CLR_BIT(ah, AR_MCI_TX_CTRL,
 906                    AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE);
 907
 908        ar9003_mci_observation_set_up(ah);
 909
 910        mci->ready = true;
 911        ar9003_mci_prep_interface(ah);
 912
 913        if (en_int)
 914                ar9003_mci_enable_interrupt(ah);
 915}
 916
 917void ar9003_mci_stop_bt(struct ath_hw *ah, bool save_fullsleep)
 918{
 919        struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci;
 920
 921        ar9003_mci_disable_interrupt(ah);
 922
 923        if (mci_hw->ready && !save_fullsleep) {
 924                ar9003_mci_mute_bt(ah);
 925                udelay(20);
 926                REG_WRITE(ah, AR_BTCOEX_CTRL, 0);
 927        }
 928
 929        mci_hw->bt_state = MCI_BT_SLEEP;
 930        mci_hw->ready = false;
 931}
 932
 933static void ar9003_mci_send_2g5g_status(struct ath_hw *ah, bool wait_done)
 934{
 935        struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
 936        u32 new_flags, to_set, to_clear;
 937
 938        if (!mci->update_2g5g || (mci->bt_state == MCI_BT_SLEEP))
 939                return;
 940
 941        if (mci->is_2g) {
 942                new_flags = MCI_2G_FLAGS;
 943                to_clear = MCI_2G_FLAGS_CLEAR_MASK;
 944                to_set = MCI_2G_FLAGS_SET_MASK;
 945        } else {
 946                new_flags = MCI_5G_FLAGS;
 947                to_clear = MCI_5G_FLAGS_CLEAR_MASK;
 948                to_set = MCI_5G_FLAGS_SET_MASK;
 949        }
 950
 951        if (to_clear)
 952                ar9003_mci_send_coex_bt_flags(ah, wait_done,
 953                                              MCI_GPM_COEX_BT_FLAGS_CLEAR,
 954                                              to_clear);
 955        if (to_set)
 956                ar9003_mci_send_coex_bt_flags(ah, wait_done,
 957                                              MCI_GPM_COEX_BT_FLAGS_SET,
 958                                              to_set);
 959}
 960
 961static void ar9003_mci_queue_unsent_gpm(struct ath_hw *ah, u8 header,
 962                                        u32 *payload, bool queue)
 963{
 964        struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
 965        u8 type, opcode;
 966
 967        /* check if the message is to be queued */
 968        if (header != MCI_GPM)
 969                return;
 970
 971        type = MCI_GPM_TYPE(payload);
 972        opcode = MCI_GPM_OPCODE(payload);
 973
 974        if (type != MCI_GPM_COEX_AGENT)
 975                return;
 976
 977        switch (opcode) {
 978        case MCI_GPM_COEX_BT_UPDATE_FLAGS:
 979                if (*(((u8 *)payload) + MCI_GPM_COEX_B_BT_FLAGS_OP) ==
 980                    MCI_GPM_COEX_BT_FLAGS_READ)
 981                        break;
 982
 983                mci->update_2g5g = queue;
 984
 985                break;
 986        case MCI_GPM_COEX_WLAN_CHANNELS:
 987                mci->wlan_channels_update = queue;
 988                break;
 989        case MCI_GPM_COEX_HALT_BT_GPM:
 990                if (*(((u8 *)payload) + MCI_GPM_COEX_B_HALT_STATE) ==
 991                    MCI_GPM_COEX_BT_GPM_UNHALT) {
 992                        mci->unhalt_bt_gpm = queue;
 993
 994                        if (!queue)
 995                                mci->halted_bt_gpm = false;
 996                }
 997
 998                if (*(((u8 *)payload) + MCI_GPM_COEX_B_HALT_STATE) ==
 999                                MCI_GPM_COEX_BT_GPM_HALT) {
1000
1001                        mci->halted_bt_gpm = !queue;
1002                }
1003
1004                break;
1005        default:
1006                break;
1007        }
1008}
1009
1010void ar9003_mci_2g5g_switch(struct ath_hw *ah, bool force)
1011{
1012        struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
1013
1014        if (!mci->update_2g5g && !force)
1015                return;
1016
1017        if (mci->is_2g) {
1018                ar9003_mci_send_2g5g_status(ah, true);
1019                ar9003_mci_send_lna_transfer(ah, true);
1020                udelay(5);
1021
1022                REG_CLR_BIT(ah, AR_MCI_TX_CTRL,
1023                            AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE);
1024                REG_CLR_BIT(ah, AR_PHY_GLB_CONTROL,
1025                            AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL);
1026
1027                if (!(mci->config & ATH_MCI_CONFIG_DISABLE_OSLA))
1028                        ar9003_mci_osla_setup(ah, true);
1029        } else {
1030                ar9003_mci_send_lna_take(ah, true);
1031                udelay(5);
1032
1033                REG_SET_BIT(ah, AR_MCI_TX_CTRL,
1034                            AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE);
1035                REG_SET_BIT(ah, AR_PHY_GLB_CONTROL,
1036                            AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL);
1037
1038                ar9003_mci_osla_setup(ah, false);
1039                ar9003_mci_send_2g5g_status(ah, true);
1040        }
1041}
1042
1043bool ar9003_mci_send_message(struct ath_hw *ah, u8 header, u32 flag,
1044                             u32 *payload, u8 len, bool wait_done,
1045                             bool check_bt)
1046{
1047        struct ath_common *common = ath9k_hw_common(ah);
1048        struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
1049        bool msg_sent = false;
1050        u32 regval;
1051        u32 saved_mci_int_en;
1052        int i;
1053
1054        saved_mci_int_en = REG_READ(ah, AR_MCI_INTERRUPT_EN);
1055        regval = REG_READ(ah, AR_BTCOEX_CTRL);
1056
1057        if ((regval == 0xdeadbeef) || !(regval & AR_BTCOEX_CTRL_MCI_MODE_EN)) {
1058                ath_dbg(common, MCI,
1059                        "MCI Not sending 0x%x. MCI is not enabled. full_sleep = %d\n",
1060                        header, (ah->power_mode == ATH9K_PM_FULL_SLEEP) ? 1 : 0);
1061                ar9003_mci_queue_unsent_gpm(ah, header, payload, true);
1062                return false;
1063        } else if (check_bt && (mci->bt_state == MCI_BT_SLEEP)) {
1064                ath_dbg(common, MCI,
1065                        "MCI Don't send message 0x%x. BT is in sleep state\n",
1066                        header);
1067                ar9003_mci_queue_unsent_gpm(ah, header, payload, true);
1068                return false;
1069        }
1070
1071        if (wait_done)
1072                REG_WRITE(ah, AR_MCI_INTERRUPT_EN, 0);
1073
1074        /* Need to clear SW_MSG_DONE raw bit before wait */
1075
1076        REG_WRITE(ah, AR_MCI_INTERRUPT_RAW,
1077                  (AR_MCI_INTERRUPT_SW_MSG_DONE |
1078                   AR_MCI_INTERRUPT_MSG_FAIL_MASK));
1079
1080        if (payload) {
1081                for (i = 0; (i * 4) < len; i++)
1082                        REG_WRITE(ah, (AR_MCI_TX_PAYLOAD0 + i * 4),
1083                                  *(payload + i));
1084        }
1085
1086        REG_WRITE(ah, AR_MCI_COMMAND0,
1087                  (SM((flag & MCI_FLAG_DISABLE_TIMESTAMP),
1088                      AR_MCI_COMMAND0_DISABLE_TIMESTAMP) |
1089                   SM(len, AR_MCI_COMMAND0_LEN) |
1090                   SM(header, AR_MCI_COMMAND0_HEADER)));
1091
1092        if (wait_done &&
1093            !(ar9003_mci_wait_for_interrupt(ah, AR_MCI_INTERRUPT_RAW,
1094                                            AR_MCI_INTERRUPT_SW_MSG_DONE, 500)))
1095                ar9003_mci_queue_unsent_gpm(ah, header, payload, true);
1096        else {
1097                ar9003_mci_queue_unsent_gpm(ah, header, payload, false);
1098                msg_sent = true;
1099        }
1100
1101        if (wait_done)
1102                REG_WRITE(ah, AR_MCI_INTERRUPT_EN, saved_mci_int_en);
1103
1104        return msg_sent;
1105}
1106EXPORT_SYMBOL(ar9003_mci_send_message);
1107
1108void ar9003_mci_init_cal_req(struct ath_hw *ah, bool *is_reusable)
1109{
1110        struct ath_common *common = ath9k_hw_common(ah);
1111        struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci;
1112        u32 pld[4] = {0, 0, 0, 0};
1113
1114        if ((mci_hw->bt_state != MCI_BT_AWAKE) ||
1115            (mci_hw->config & ATH_MCI_CONFIG_DISABLE_MCI_CAL))
1116                return;
1117
1118        MCI_GPM_SET_CAL_TYPE(pld, MCI_GPM_WLAN_CAL_REQ);
1119        pld[MCI_GPM_WLAN_CAL_W_SEQUENCE] = mci_hw->wlan_cal_seq++;
1120
1121        ar9003_mci_send_message(ah, MCI_GPM, 0, pld, 16, true, false);
1122
1123        if (ar9003_mci_wait_for_gpm(ah, MCI_GPM_BT_CAL_GRANT, 0, 50000)) {
1124                ath_dbg(common, MCI, "MCI BT_CAL_GRANT received\n");
1125        } else {
1126                *is_reusable = false;
1127                ath_dbg(common, MCI, "MCI BT_CAL_GRANT not received\n");
1128        }
1129}
1130
1131void ar9003_mci_init_cal_done(struct ath_hw *ah)
1132{
1133        struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci;
1134        u32 pld[4] = {0, 0, 0, 0};
1135
1136        if ((mci_hw->bt_state != MCI_BT_AWAKE) ||
1137            (mci_hw->config & ATH_MCI_CONFIG_DISABLE_MCI_CAL))
1138                return;
1139
1140        MCI_GPM_SET_CAL_TYPE(pld, MCI_GPM_WLAN_CAL_DONE);
1141        pld[MCI_GPM_WLAN_CAL_W_SEQUENCE] = mci_hw->wlan_cal_done++;
1142        ar9003_mci_send_message(ah, MCI_GPM, 0, pld, 16, true, false);
1143}
1144
1145void ar9003_mci_setup(struct ath_hw *ah, u32 gpm_addr, void *gpm_buf,
1146                      u16 len, u32 sched_addr)
1147{
1148        struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
1149
1150        mci->gpm_addr = gpm_addr;
1151        mci->gpm_buf = gpm_buf;
1152        mci->gpm_len = len;
1153        mci->sched_addr = sched_addr;
1154
1155        ar9003_mci_reset(ah, true, true, true);
1156}
1157EXPORT_SYMBOL(ar9003_mci_setup);
1158
1159void ar9003_mci_cleanup(struct ath_hw *ah)
1160{
1161        /* Turn off MCI and Jupiter mode. */
1162        REG_WRITE(ah, AR_BTCOEX_CTRL, 0x00);
1163        ar9003_mci_disable_interrupt(ah);
1164}
1165EXPORT_SYMBOL(ar9003_mci_cleanup);
1166
1167u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type)
1168{
1169        struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
1170        u32 value = 0;
1171        u8 query_type;
1172
1173        switch (state_type) {
1174        case MCI_STATE_ENABLE:
1175                if (mci->ready) {
1176                        value = REG_READ(ah, AR_BTCOEX_CTRL);
1177
1178                        if ((value == 0xdeadbeef) || (value == 0xffffffff))
1179                                value = 0;
1180                }
1181                value &= AR_BTCOEX_CTRL_MCI_MODE_EN;
1182                break;
1183        case MCI_STATE_LAST_SCHD_MSG_OFFSET:
1184                value = MS(REG_READ(ah, AR_MCI_RX_STATUS),
1185                                    AR_MCI_RX_LAST_SCHD_MSG_INDEX);
1186                /* Make it in bytes */
1187                value <<= 4;
1188                break;
1189        case MCI_STATE_REMOTE_SLEEP:
1190                value = MS(REG_READ(ah, AR_MCI_RX_STATUS),
1191                           AR_MCI_RX_REMOTE_SLEEP) ?
1192                        MCI_BT_SLEEP : MCI_BT_AWAKE;
1193                break;
1194        case MCI_STATE_SET_BT_AWAKE:
1195                mci->bt_state = MCI_BT_AWAKE;
1196                ar9003_mci_send_coex_version_query(ah, true);
1197                ar9003_mci_send_coex_wlan_channels(ah, true);
1198
1199                if (mci->unhalt_bt_gpm)
1200                        ar9003_mci_send_coex_halt_bt_gpm(ah, false, true);
1201
1202                ar9003_mci_2g5g_switch(ah, false);
1203                break;
1204        case MCI_STATE_SET_BT_CAL_START:
1205                mci->bt_state = MCI_BT_CAL_START;
1206                break;
1207        case MCI_STATE_SET_BT_CAL:
1208                mci->bt_state = MCI_BT_CAL;
1209                break;
1210        case MCI_STATE_RESET_REQ_WAKE:
1211                ar9003_mci_reset_req_wakeup(ah);
1212                mci->update_2g5g = true;
1213
1214                if (mci->config & ATH_MCI_CONFIG_MCI_OBS_MASK) {
1215                        /* Check if we still have control of the GPIOs */
1216                        if ((REG_READ(ah, AR_GLB_GPIO_CONTROL) &
1217                             ATH_MCI_CONFIG_MCI_OBS_GPIO) !=
1218                            ATH_MCI_CONFIG_MCI_OBS_GPIO) {
1219                                ar9003_mci_observation_set_up(ah);
1220                        }
1221                }
1222                break;
1223        case MCI_STATE_SEND_WLAN_COEX_VERSION:
1224                ar9003_mci_send_coex_version_response(ah, true);
1225                break;
1226        case MCI_STATE_SEND_VERSION_QUERY:
1227                ar9003_mci_send_coex_version_query(ah, true);
1228                break;
1229        case MCI_STATE_SEND_STATUS_QUERY:
1230                query_type = MCI_GPM_COEX_QUERY_BT_TOPOLOGY;
1231                ar9003_mci_send_coex_bt_status_query(ah, true, query_type);
1232                break;
1233        case MCI_STATE_RECOVER_RX:
1234                ar9003_mci_prep_interface(ah);
1235                mci->query_bt = true;
1236                mci->need_flush_btinfo = true;
1237                ar9003_mci_send_coex_wlan_channels(ah, true);
1238                ar9003_mci_2g5g_switch(ah, false);
1239                break;
1240        case MCI_STATE_NEED_FTP_STOMP:
1241                value = !(mci->config & ATH_MCI_CONFIG_DISABLE_FTP_STOMP);
1242                break;
1243        default:
1244                break;
1245        }
1246
1247        return value;
1248}
1249EXPORT_SYMBOL(ar9003_mci_state);
1250
1251void ar9003_mci_bt_gain_ctrl(struct ath_hw *ah)
1252{
1253        struct ath_common *common = ath9k_hw_common(ah);
1254        struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
1255
1256        ath_dbg(common, MCI, "Give LNA and SPDT control to BT\n");
1257
1258        ar9003_mci_send_lna_take(ah, true);
1259        udelay(50);
1260
1261        REG_SET_BIT(ah, AR_PHY_GLB_CONTROL, AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL);
1262        mci->is_2g = false;
1263        mci->update_2g5g = true;
1264        ar9003_mci_send_2g5g_status(ah, true);
1265
1266        /* Force another 2g5g update at next scanning */
1267        mci->update_2g5g = true;
1268}
1269
1270void ar9003_mci_set_power_awake(struct ath_hw *ah)
1271{
1272        u32 btcoex_ctrl2, diag_sw;
1273        int i;
1274        u8 lna_ctrl, bt_sleep;
1275
1276        for (i = 0; i < AH_WAIT_TIMEOUT; i++) {
1277                btcoex_ctrl2 = REG_READ(ah, AR_BTCOEX_CTRL2);
1278                if (btcoex_ctrl2 != 0xdeadbeef)
1279                        break;
1280                udelay(AH_TIME_QUANTUM);
1281        }
1282        REG_WRITE(ah, AR_BTCOEX_CTRL2, (btcoex_ctrl2 | BIT(23)));
1283
1284        for (i = 0; i < AH_WAIT_TIMEOUT; i++) {
1285                diag_sw = REG_READ(ah, AR_DIAG_SW);
1286                if (diag_sw != 0xdeadbeef)
1287                        break;
1288                udelay(AH_TIME_QUANTUM);
1289        }
1290        REG_WRITE(ah, AR_DIAG_SW, (diag_sw | BIT(27) | BIT(19) | BIT(18)));
1291        lna_ctrl = REG_READ(ah, AR_OBS_BUS_CTRL) & 0x3;
1292        bt_sleep = REG_READ(ah, AR_MCI_RX_STATUS) & AR_MCI_RX_REMOTE_SLEEP;
1293
1294        REG_WRITE(ah, AR_BTCOEX_CTRL2, btcoex_ctrl2);
1295        REG_WRITE(ah, AR_DIAG_SW, diag_sw);
1296
1297        if (bt_sleep && (lna_ctrl == 2)) {
1298                REG_SET_BIT(ah, AR_BTCOEX_RC, 0x1);
1299                REG_CLR_BIT(ah, AR_BTCOEX_RC, 0x1);
1300                udelay(50);
1301        }
1302}
1303
1304void ar9003_mci_check_gpm_offset(struct ath_hw *ah)
1305{
1306        struct ath_common *common = ath9k_hw_common(ah);
1307        struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
1308        u32 offset;
1309
1310        /*
1311         * This should only be called before "MAC Warm Reset" or "MCI Reset Rx".
1312         */
1313        offset = MS(REG_READ(ah, AR_MCI_GPM_1), AR_MCI_GPM_WRITE_PTR);
1314        if (mci->gpm_idx == offset)
1315                return;
1316        ath_dbg(common, MCI, "GPM cached write pointer mismatch %d %d\n",
1317                mci->gpm_idx, offset);
1318        mci->query_bt = true;
1319        mci->need_flush_btinfo = true;
1320        mci->gpm_idx = 0;
1321}
1322
1323u32 ar9003_mci_get_next_gpm_offset(struct ath_hw *ah, bool first, u32 *more)
1324{
1325        struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
1326        u32 offset, more_gpm = 0, gpm_ptr;
1327
1328        if (first) {
1329                gpm_ptr = MS(REG_READ(ah, AR_MCI_GPM_1), AR_MCI_GPM_WRITE_PTR);
1330                mci->gpm_idx = gpm_ptr;
1331                return gpm_ptr;
1332        }
1333
1334        /*
1335         * This could be useful to avoid new GPM message interrupt which
1336         * may lead to spurious interrupt after power sleep, or multiple
1337         * entry of ath_mci_intr().
1338         * Adding empty GPM check by returning HAL_MCI_GPM_INVALID can
1339         * alleviate this effect, but clearing GPM RX interrupt bit is
1340         * safe, because whether this is called from hw or driver code
1341         * there must be an interrupt bit set/triggered initially
1342         */
1343        REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,
1344                        AR_MCI_INTERRUPT_RX_MSG_GPM);
1345
1346        gpm_ptr = MS(REG_READ(ah, AR_MCI_GPM_1), AR_MCI_GPM_WRITE_PTR);
1347        offset = gpm_ptr;
1348
1349        if (!offset)
1350                offset = mci->gpm_len - 1;
1351        else if (offset >= mci->gpm_len) {
1352                if (offset != 0xFFFF)
1353                        offset = 0;
1354        } else {
1355                offset--;
1356        }
1357
1358        if ((offset == 0xFFFF) || (gpm_ptr == mci->gpm_idx)) {
1359                offset = MCI_GPM_INVALID;
1360                more_gpm = MCI_GPM_NOMORE;
1361                goto out;
1362        }
1363        for (;;) {
1364                u32 temp_index;
1365
1366                /* skip reserved GPM if any */
1367
1368                if (offset != mci->gpm_idx)
1369                        more_gpm = MCI_GPM_MORE;
1370                else
1371                        more_gpm = MCI_GPM_NOMORE;
1372
1373                temp_index = mci->gpm_idx;
1374                mci->gpm_idx++;
1375
1376                if (mci->gpm_idx >= mci->gpm_len)
1377                        mci->gpm_idx = 0;
1378
1379                if (ar9003_mci_is_gpm_valid(ah, temp_index)) {
1380                        offset = temp_index;
1381                        break;
1382                }
1383
1384                if (more_gpm == MCI_GPM_NOMORE) {
1385                        offset = MCI_GPM_INVALID;
1386                        break;
1387                }
1388        }
1389
1390        if (offset != MCI_GPM_INVALID)
1391                offset <<= 4;
1392out:
1393        if (more)
1394                *more = more_gpm;
1395
1396        return offset;
1397}
1398EXPORT_SYMBOL(ar9003_mci_get_next_gpm_offset);
1399
1400void ar9003_mci_set_bt_version(struct ath_hw *ah, u8 major, u8 minor)
1401{
1402        struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
1403
1404        mci->bt_ver_major = major;
1405        mci->bt_ver_minor = minor;
1406        mci->bt_version_known = true;
1407        ath_dbg(ath9k_hw_common(ah), MCI, "MCI BT version set: %d.%d\n",
1408                mci->bt_ver_major, mci->bt_ver_minor);
1409}
1410EXPORT_SYMBOL(ar9003_mci_set_bt_version);
1411
1412void ar9003_mci_send_wlan_channels(struct ath_hw *ah)
1413{
1414        struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
1415
1416        mci->wlan_channels_update = true;
1417        ar9003_mci_send_coex_wlan_channels(ah, true);
1418}
1419EXPORT_SYMBOL(ar9003_mci_send_wlan_channels);
1420