diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/ar9003_mci.c')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ar9003_mci.c | 457 |
1 files changed, 232 insertions, 225 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mci.c b/drivers/net/wireless/ath/ath9k/ar9003_mci.c index ffbb180..b1ced2a 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mci.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mci.c @@ -35,31 +35,30 @@ static int ar9003_mci_wait_for_interrupt(struct ath_hw *ah, u32 address, struct ath_common *common = ath9k_hw_common(ah); while (time_out) { - if (REG_READ(ah, address) & bit_position) { - REG_WRITE(ah, address, bit_position); - - if (address == AR_MCI_INTERRUPT_RX_MSG_RAW) { - if (bit_position & - AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE) - ar9003_mci_reset_req_wakeup(ah); - - if (bit_position & - (AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING | - AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING)) - REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, - AR_MCI_INTERRUPT_REMOTE_SLEEP_UPDATE); - - REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, - AR_MCI_INTERRUPT_RX_MSG); - } - break; - } + if (!(REG_READ(ah, address) & bit_position)) { + udelay(10); + time_out -= 10; - udelay(10); - time_out -= 10; + if (time_out < 0) + break; + else + continue; + } + REG_WRITE(ah, address, bit_position); - if (time_out < 0) + if (address != AR_MCI_INTERRUPT_RX_MSG_RAW) break; + + if (bit_position & AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE) + ar9003_mci_reset_req_wakeup(ah); + + if (bit_position & (AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING | + AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING)) + REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, + AR_MCI_INTERRUPT_REMOTE_SLEEP_UPDATE); + + REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, AR_MCI_INTERRUPT_RX_MSG); + break; } if (time_out <= 0) { @@ -127,14 +126,13 @@ static void ar9003_mci_send_coex_version_query(struct ath_hw *ah, struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; u32 payload[4] = {0, 0, 0, 0}; - if (!mci->bt_version_known && - (mci->bt_state != MCI_BT_SLEEP)) { - MCI_GPM_SET_TYPE_OPCODE(payload, - MCI_GPM_COEX_AGENT, - MCI_GPM_COEX_VERSION_QUERY); - ar9003_mci_send_message(ah, MCI_GPM, 0, payload, 16, - wait_done, true); - } + if (mci->bt_version_known || + (mci->bt_state == MCI_BT_SLEEP)) + return; + + MCI_GPM_SET_TYPE_OPCODE(payload, MCI_GPM_COEX_AGENT, + MCI_GPM_COEX_VERSION_QUERY); + ar9003_mci_send_message(ah, MCI_GPM, 0, payload, 16, wait_done, true); } static void ar9003_mci_send_coex_version_response(struct ath_hw *ah, @@ -158,15 +156,14 @@ static void ar9003_mci_send_coex_wlan_channels(struct ath_hw *ah, struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; u32 *payload = &mci->wlan_channels[0]; - if ((mci->wlan_channels_update == true) && - (mci->bt_state != MCI_BT_SLEEP)) { - MCI_GPM_SET_TYPE_OPCODE(payload, - MCI_GPM_COEX_AGENT, - MCI_GPM_COEX_WLAN_CHANNELS); - ar9003_mci_send_message(ah, MCI_GPM, 0, payload, 16, - wait_done, true); - MCI_GPM_SET_TYPE_OPCODE(payload, 0xff, 0xff); - } + if (!mci->wlan_channels_update || + (mci->bt_state == MCI_BT_SLEEP)) + return; + + MCI_GPM_SET_TYPE_OPCODE(payload, MCI_GPM_COEX_AGENT, + MCI_GPM_COEX_WLAN_CHANNELS); + ar9003_mci_send_message(ah, MCI_GPM, 0, payload, 16, wait_done, true); + MCI_GPM_SET_TYPE_OPCODE(payload, 0xff, 0xff); } static void ar9003_mci_send_coex_bt_status_query(struct ath_hw *ah, @@ -174,29 +171,30 @@ static void ar9003_mci_send_coex_bt_status_query(struct ath_hw *ah, { struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; u32 payload[4] = {0, 0, 0, 0}; - bool query_btinfo = !!(query_type & (MCI_GPM_COEX_QUERY_BT_ALL_INFO | - MCI_GPM_COEX_QUERY_BT_TOPOLOGY)); - - if (mci->bt_state != MCI_BT_SLEEP) { + bool query_btinfo; - MCI_GPM_SET_TYPE_OPCODE(payload, MCI_GPM_COEX_AGENT, - MCI_GPM_COEX_STATUS_QUERY); + if (mci->bt_state == MCI_BT_SLEEP) + return; - *(((u8 *)payload) + MCI_GPM_COEX_B_BT_BITMAP) = query_type; + query_btinfo = !!(query_type & (MCI_GPM_COEX_QUERY_BT_ALL_INFO | + MCI_GPM_COEX_QUERY_BT_TOPOLOGY)); + MCI_GPM_SET_TYPE_OPCODE(payload, MCI_GPM_COEX_AGENT, + MCI_GPM_COEX_STATUS_QUERY); - /* - * If bt_status_query message is not sent successfully, - * then need_flush_btinfo should be set again. - */ - if (!ar9003_mci_send_message(ah, MCI_GPM, 0, payload, 16, - wait_done, true)) { - if (query_btinfo) - mci->need_flush_btinfo = true; - } + *(((u8 *)payload) + MCI_GPM_COEX_B_BT_BITMAP) = query_type; + /* + * If bt_status_query message is not sent successfully, + * then need_flush_btinfo should be set again. + */ + if (!ar9003_mci_send_message(ah, MCI_GPM, 0, payload, 16, + wait_done, true)) { if (query_btinfo) - mci->query_bt = false; + mci->need_flush_btinfo = true; } + + if (query_btinfo) + mci->query_bt = false; } static void ar9003_mci_send_coex_halt_bt_gpm(struct ath_hw *ah, bool halt, @@ -241,73 +239,73 @@ static void ar9003_mci_prep_interface(struct ath_hw *ah) ar9003_mci_remote_reset(ah, true); ar9003_mci_send_req_wake(ah, true); - if (ar9003_mci_wait_for_interrupt(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, - AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING, 500)) { + if (!ar9003_mci_wait_for_interrupt(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, + AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING, 500)) + goto clear_redunt; - mci->bt_state = MCI_BT_AWAKE; + mci->bt_state = MCI_BT_AWAKE; - /* - * we don't need to send more remote_reset at this moment. - * If BT receive first remote_reset, then BT HW will - * be cleaned up and will be able to receive req_wake - * and BT HW will respond sys_waking. - * In this case, WLAN will receive BT's HW sys_waking. - * Otherwise, if BT SW missed initial remote_reset, - * that remote_reset will still clean up BT MCI RX, - * and the req_wake will wake BT up, - * and BT SW will respond this req_wake with a remote_reset and - * sys_waking. In this case, WLAN will receive BT's SW - * sys_waking. In either case, BT's RX is cleaned up. So we - * don't need to reply BT's remote_reset now, if any. - * Similarly, if in any case, WLAN can receive BT's sys_waking, - * that means WLAN's RX is also fine. - */ - ar9003_mci_send_sys_waking(ah, true); - udelay(10); + /* + * we don't need to send more remote_reset at this moment. + * If BT receive first remote_reset, then BT HW will + * be cleaned up and will be able to receive req_wake + * and BT HW will respond sys_waking. + * In this case, WLAN will receive BT's HW sys_waking. + * Otherwise, if BT SW missed initial remote_reset, + * that remote_reset will still clean up BT MCI RX, + * and the req_wake will wake BT up, + * and BT SW will respond this req_wake with a remote_reset and + * sys_waking. In this case, WLAN will receive BT's SW + * sys_waking. In either case, BT's RX is cleaned up. So we + * don't need to reply BT's remote_reset now, if any. + * Similarly, if in any case, WLAN can receive BT's sys_waking, + * that means WLAN's RX is also fine. + */ + ar9003_mci_send_sys_waking(ah, true); + udelay(10); - /* - * Set BT priority interrupt value to be 0xff to - * avoid having too many BT PRIORITY interrupts. - */ - REG_WRITE(ah, AR_MCI_BT_PRI0, 0xFFFFFFFF); - REG_WRITE(ah, AR_MCI_BT_PRI1, 0xFFFFFFFF); - REG_WRITE(ah, AR_MCI_BT_PRI2, 0xFFFFFFFF); - REG_WRITE(ah, AR_MCI_BT_PRI3, 0xFFFFFFFF); - REG_WRITE(ah, AR_MCI_BT_PRI, 0X000000FF); + /* + * Set BT priority interrupt value to be 0xff to + * avoid having too many BT PRIORITY interrupts. + */ + REG_WRITE(ah, AR_MCI_BT_PRI0, 0xFFFFFFFF); + REG_WRITE(ah, AR_MCI_BT_PRI1, 0xFFFFFFFF); + REG_WRITE(ah, AR_MCI_BT_PRI2, 0xFFFFFFFF); + REG_WRITE(ah, AR_MCI_BT_PRI3, 0xFFFFFFFF); + REG_WRITE(ah, AR_MCI_BT_PRI, 0X000000FF); - /* - * A contention reset will be received after send out - * sys_waking. Also BT priority interrupt bits will be set. - * Clear those bits before the next step. - */ + /* + * A contention reset will be received after send out + * sys_waking. Also BT priority interrupt bits will be set. + * Clear those bits before the next step. + */ - REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, - AR_MCI_INTERRUPT_RX_MSG_CONT_RST); - REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, - AR_MCI_INTERRUPT_BT_PRI); + REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, + AR_MCI_INTERRUPT_RX_MSG_CONT_RST); + REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, AR_MCI_INTERRUPT_BT_PRI); - if (mci->is_2g) { - ar9003_mci_send_lna_transfer(ah, true); - udelay(5); - } + if (mci->is_2g) { + ar9003_mci_send_lna_transfer(ah, true); + udelay(5); + } - if ((mci->is_2g && !mci->update_2g5g)) { - if (ar9003_mci_wait_for_interrupt(ah, - AR_MCI_INTERRUPT_RX_MSG_RAW, - AR_MCI_INTERRUPT_RX_MSG_LNA_INFO, - mci_timeout)) - ath_dbg(common, MCI, - "MCI WLAN has control over the LNA & BT obeys it\n"); - else - ath_dbg(common, MCI, - "MCI BT didn't respond to LNA_TRANS\n"); - } + if ((mci->is_2g && !mci->update_2g5g)) { + if (ar9003_mci_wait_for_interrupt(ah, + AR_MCI_INTERRUPT_RX_MSG_RAW, + AR_MCI_INTERRUPT_RX_MSG_LNA_INFO, + mci_timeout)) + ath_dbg(common, MCI, + "MCI WLAN has control over the LNA & BT obeys it\n"); + else + ath_dbg(common, MCI, + "MCI BT didn't respond to LNA_TRANS\n"); } +clear_redunt: /* Clear the extra redundant SYS_WAKING from BT */ if ((mci->bt_state == MCI_BT_AWAKE) && - (REG_READ_FIELD(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, - AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING)) && + (REG_READ_FIELD(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, + AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING)) && (REG_READ_FIELD(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING) == 0)) { REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, @@ -330,7 +328,6 @@ void ar9003_mci_set_full_sleep(struct ath_hw *ah) } mci->ready = false; - REG_WRITE(ah, AR_RTC_KEEP_AWAKE, 0x2); } static void ar9003_mci_disable_interrupt(struct ath_hw *ah) @@ -615,9 +612,9 @@ static u32 ar9003_mci_wait_for_gpm(struct ath_hw *ah, u8 gpm_type, } break; } - } else if ((recv_type == gpm_type) && (recv_opcode == gpm_opcode)) { + } else if ((recv_type == gpm_type) && + (recv_opcode == gpm_opcode)) break; - } /* * check if it's cal_grant @@ -731,38 +728,38 @@ int ar9003_mci_end_reset(struct ath_hw *ah, struct ath9k_channel *chan, if (!IS_CHAN_2GHZ(chan) || (mci_hw->bt_state != MCI_BT_SLEEP)) goto exit; - if (ar9003_mci_check_int(ah, AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET) || - ar9003_mci_check_int(ah, AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE)) { + if (!ar9003_mci_check_int(ah, AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET) && + !ar9003_mci_check_int(ah, AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE)) + goto exit; - /* - * BT is sleeping. Check if BT wakes up during - * WLAN calibration. If BT wakes up during - * WLAN calibration, need to go through all - * message exchanges again and recal. - */ - REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, - AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET | - AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE); + /* + * BT is sleeping. Check if BT wakes up during + * WLAN calibration. If BT wakes up during + * WLAN calibration, need to go through all + * message exchanges again and recal. + */ + REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, + (AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET | + AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE)); - ar9003_mci_remote_reset(ah, true); - ar9003_mci_send_sys_waking(ah, true); - udelay(1); + ar9003_mci_remote_reset(ah, true); + ar9003_mci_send_sys_waking(ah, true); + udelay(1); - if (IS_CHAN_2GHZ(chan)) - ar9003_mci_send_lna_transfer(ah, true); + if (IS_CHAN_2GHZ(chan)) + ar9003_mci_send_lna_transfer(ah, true); - mci_hw->bt_state = MCI_BT_AWAKE; + mci_hw->bt_state = MCI_BT_AWAKE; - if (caldata) { - caldata->done_txiqcal_once = false; - caldata->done_txclcal_once = false; - caldata->rtt_done = false; - } + if (caldata) { + caldata->done_txiqcal_once = false; + caldata->done_txclcal_once = false; + caldata->rtt_done = false; + } - if (!ath9k_hw_init_cal(ah, chan)) - return -EIO; + if (!ath9k_hw_init_cal(ah, chan)) + return -EIO; - } exit: ar9003_mci_enable_interrupt(ah); return 0; @@ -798,29 +795,27 @@ static void ar9003_mci_osla_setup(struct ath_hw *ah, bool enable) struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; u32 thresh; - if (enable) { - REG_RMW_FIELD(ah, AR_MCI_SCHD_TABLE_2, - AR_MCI_SCHD_TABLE_2_HW_BASED, 1); - REG_RMW_FIELD(ah, AR_MCI_SCHD_TABLE_2, - AR_MCI_SCHD_TABLE_2_MEM_BASED, 1); - - if (!(mci->config & ATH_MCI_CONFIG_DISABLE_AGGR_THRESH)) { - thresh = MS(mci->config, ATH_MCI_CONFIG_AGGR_THRESH); - REG_RMW_FIELD(ah, AR_BTCOEX_CTRL, - AR_BTCOEX_CTRL_AGGR_THRESH, thresh); - REG_RMW_FIELD(ah, AR_BTCOEX_CTRL, - AR_BTCOEX_CTRL_TIME_TO_NEXT_BT_THRESH_EN, 1); - } else { - REG_RMW_FIELD(ah, AR_BTCOEX_CTRL, - AR_BTCOEX_CTRL_TIME_TO_NEXT_BT_THRESH_EN, 0); - } - - REG_RMW_FIELD(ah, AR_BTCOEX_CTRL, - AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN, 1); - } else { + if (!enable) { REG_CLR_BIT(ah, AR_BTCOEX_CTRL, AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN); + return; } + REG_RMW_FIELD(ah, AR_MCI_SCHD_TABLE_2, AR_MCI_SCHD_TABLE_2_HW_BASED, 1); + REG_RMW_FIELD(ah, AR_MCI_SCHD_TABLE_2, + AR_MCI_SCHD_TABLE_2_MEM_BASED, 1); + + if (!(mci->config & ATH_MCI_CONFIG_DISABLE_AGGR_THRESH)) { + thresh = MS(mci->config, ATH_MCI_CONFIG_AGGR_THRESH); + REG_RMW_FIELD(ah, AR_BTCOEX_CTRL, + AR_BTCOEX_CTRL_AGGR_THRESH, thresh); + REG_RMW_FIELD(ah, AR_BTCOEX_CTRL, + AR_BTCOEX_CTRL_TIME_TO_NEXT_BT_THRESH_EN, 1); + } else + REG_RMW_FIELD(ah, AR_BTCOEX_CTRL, + AR_BTCOEX_CTRL_TIME_TO_NEXT_BT_THRESH_EN, 0); + + REG_RMW_FIELD(ah, AR_BTCOEX_CTRL, + AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN, 1); } void ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g, @@ -943,26 +938,27 @@ static void ar9003_mci_send_2g5g_status(struct ath_hw *ah, bool wait_done) struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; u32 new_flags, to_set, to_clear; - if (mci->update_2g5g && (mci->bt_state != MCI_BT_SLEEP)) { - if (mci->is_2g) { - new_flags = MCI_2G_FLAGS; - to_clear = MCI_2G_FLAGS_CLEAR_MASK; - to_set = MCI_2G_FLAGS_SET_MASK; - } else { - new_flags = MCI_5G_FLAGS; - to_clear = MCI_5G_FLAGS_CLEAR_MASK; - to_set = MCI_5G_FLAGS_SET_MASK; - } + if (!mci->update_2g5g || (mci->bt_state == MCI_BT_SLEEP)) + return; + + if (mci->is_2g) { + new_flags = MCI_2G_FLAGS; + to_clear = MCI_2G_FLAGS_CLEAR_MASK; + to_set = MCI_2G_FLAGS_SET_MASK; + } else { + new_flags = MCI_5G_FLAGS; + to_clear = MCI_5G_FLAGS_CLEAR_MASK; + to_set = MCI_5G_FLAGS_SET_MASK; + } - if (to_clear) - ar9003_mci_send_coex_bt_flags(ah, wait_done, + if (to_clear) + ar9003_mci_send_coex_bt_flags(ah, wait_done, MCI_GPM_COEX_BT_FLAGS_CLEAR, to_clear); - if (to_set) - ar9003_mci_send_coex_bt_flags(ah, wait_done, + if (to_set) + ar9003_mci_send_coex_bt_flags(ah, wait_done, MCI_GPM_COEX_BT_FLAGS_SET, to_set); - } } static void ar9003_mci_queue_unsent_gpm(struct ath_hw *ah, u8 header, @@ -1018,34 +1014,34 @@ void ar9003_mci_2g5g_switch(struct ath_hw *ah, bool wait_done) { struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; - if (mci->update_2g5g) { - if (mci->is_2g) { - ar9003_mci_send_2g5g_status(ah, true); - ar9003_mci_send_lna_transfer(ah, true); - udelay(5); + if (!mci->update_2g5g) + return; - REG_CLR_BIT(ah, AR_MCI_TX_CTRL, - AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE); - REG_CLR_BIT(ah, AR_PHY_GLB_CONTROL, - AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL); + if (mci->is_2g) { + ar9003_mci_send_2g5g_status(ah, true); + ar9003_mci_send_lna_transfer(ah, true); + udelay(5); - if (!(mci->config & ATH_MCI_CONFIG_DISABLE_OSLA)) { - REG_SET_BIT(ah, AR_BTCOEX_CTRL, - AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN); - } - } else { - ar9003_mci_send_lna_take(ah, true); - udelay(5); - - REG_SET_BIT(ah, AR_MCI_TX_CTRL, - AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE); - REG_SET_BIT(ah, AR_PHY_GLB_CONTROL, - AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL); - REG_CLR_BIT(ah, AR_BTCOEX_CTRL, + REG_CLR_BIT(ah, AR_MCI_TX_CTRL, + AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE); + REG_CLR_BIT(ah, AR_PHY_GLB_CONTROL, + AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL); + + if (!(mci->config & ATH_MCI_CONFIG_DISABLE_OSLA)) + REG_SET_BIT(ah, AR_BTCOEX_CTRL, AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN); + } else { + ar9003_mci_send_lna_take(ah, true); + udelay(5); - ar9003_mci_send_2g5g_status(ah, true); - } + REG_SET_BIT(ah, AR_MCI_TX_CTRL, + AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE); + REG_SET_BIT(ah, AR_PHY_GLB_CONTROL, + AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL); + REG_CLR_BIT(ah, AR_BTCOEX_CTRL, + AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN); + + ar9003_mci_send_2g5g_status(ah, true); } } @@ -1132,7 +1128,7 @@ void ar9003_mci_init_cal_req(struct ath_hw *ah, bool *is_reusable) if (ar9003_mci_wait_for_gpm(ah, MCI_GPM_BT_CAL_GRANT, 0, 50000)) { ath_dbg(common, MCI, "MCI BT_CAL_GRANT received\n"); } else { - is_reusable = false; + *is_reusable = false; ath_dbg(common, MCI, "MCI BT_CAL_GRANT not received\n"); } } @@ -1259,12 +1255,12 @@ u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type, u32 *p_data) } if (p_data) *p_data = more_gpm; - } + } - if (value != MCI_GPM_INVALID) - value <<= 4; + if (value != MCI_GPM_INVALID) + value <<= 4; - break; + break; case MCI_STATE_LAST_SCHD_MSG_OFFSET: value = MS(REG_READ(ah, AR_MCI_RX_STATUS), AR_MCI_RX_LAST_SCHD_MSG_INDEX); @@ -1359,24 +1355,22 @@ u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type, u32 *p_data) ar9003_mci_send_coex_bt_status_query(ah, true, query_type); break; case MCI_STATE_NEED_FLUSH_BT_INFO: - /* - * btcoex_hw.mci.unhalt_bt_gpm means whether it's - * needed to send UNHALT message. It's set whenever - * there's a request to send HALT message. - * mci_halted_bt_gpm means whether HALT message is sent - * out successfully. - * - * Checking (mci_unhalt_bt_gpm == false) instead of - * checking (ah->mci_halted_bt_gpm == false) will make - * sure currently is in UNHALT-ed mode and BT can - * respond to status query. - */ - value = (!mci->unhalt_bt_gpm && - mci->need_flush_btinfo) ? 1 : 0; - if (p_data) - mci->need_flush_btinfo = - (*p_data != 0) ? true : false; - break; + /* + * btcoex_hw.mci.unhalt_bt_gpm means whether it's + * needed to send UNHALT message. It's set whenever + * there's a request to send HALT message. + * mci_halted_bt_gpm means whether HALT message is sent + * out successfully. + * + * Checking (mci_unhalt_bt_gpm == false) instead of + * checking (ah->mci_halted_bt_gpm == false) will make + * sure currently is in UNHALT-ed mode and BT can + * respond to status query. + */ + value = (!mci->unhalt_bt_gpm && mci->need_flush_btinfo) ? 1 : 0; + if (p_data) + mci->need_flush_btinfo = (*p_data != 0) ? true : false; + break; case MCI_STATE_RECOVER_RX: ar9003_mci_prep_interface(ah); mci->query_bt = true; @@ -1387,9 +1381,6 @@ u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type, u32 *p_data) case MCI_STATE_NEED_FTP_STOMP: value = !(mci->config & ATH_MCI_CONFIG_DISABLE_FTP_STOMP); break; - case MCI_STATE_NEED_TUNING: - value = !(mci->config & ATH_MCI_CONFIG_DISABLE_TUNING); - break; default: break; } @@ -1397,3 +1388,19 @@ u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type, u32 *p_data) return value; } EXPORT_SYMBOL(ar9003_mci_state); + +void ar9003_mci_bt_gain_ctrl(struct ath_hw *ah) +{ + struct ath_common *common = ath9k_hw_common(ah); + struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; + + ath_dbg(common, MCI, "Give LNA and SPDT control to BT\n"); + + REG_SET_BIT(ah, AR_PHY_GLB_CONTROL, AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL); + mci->is_2g = false; + mci->update_2g5g = true; + ar9003_mci_send_2g5g_status(ah, true); + + /* Force another 2g5g update at next scanning */ + mci->update_2g5g = true; +} |