|
@@ -1514,6 +1514,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
|
|
struct ath9k_hw_cal_data *caldata, bool bChannelChange)
|
|
struct ath9k_hw_cal_data *caldata, bool bChannelChange)
|
|
{
|
|
{
|
|
struct ath_common *common = ath9k_hw_common(ah);
|
|
struct ath_common *common = ath9k_hw_common(ah);
|
|
|
|
+ struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci;
|
|
u32 saveLedState;
|
|
u32 saveLedState;
|
|
struct ath9k_channel *curchan = ah->curchan;
|
|
struct ath9k_channel *curchan = ah->curchan;
|
|
u32 saveDefAntenna;
|
|
u32 saveDefAntenna;
|
|
@@ -1521,6 +1522,53 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
|
|
u64 tsf = 0;
|
|
u64 tsf = 0;
|
|
int i, r;
|
|
int i, r;
|
|
bool allow_fbs = false;
|
|
bool allow_fbs = false;
|
|
|
|
+ bool mci = !!(ah->caps.hw_caps & ATH9K_HW_CAP_MCI);
|
|
|
|
+ bool save_fullsleep = ah->chip_fullsleep;
|
|
|
|
+
|
|
|
|
+ if (mci) {
|
|
|
|
+
|
|
|
|
+ ar9003_mci_2g5g_changed(ah, IS_CHAN_2GHZ(chan));
|
|
|
|
+
|
|
|
|
+ if (mci_hw->bt_state == MCI_BT_CAL_START) {
|
|
|
|
+ u32 payload[4] = {0, 0, 0, 0};
|
|
|
|
+
|
|
|
|
+ ath_dbg(common, ATH_DBG_MCI, "MCI stop rx for BT CAL");
|
|
|
|
+
|
|
|
|
+ mci_hw->bt_state = MCI_BT_CAL;
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * MCI FIX: disable mci interrupt here. This is to avoid
|
|
|
|
+ * SW_MSG_DONE or RX_MSG bits to trigger MCI_INT and
|
|
|
|
+ * lead to mci_intr reentry.
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+ ar9003_mci_disable_interrupt(ah);
|
|
|
|
+
|
|
|
|
+ ath_dbg(common, ATH_DBG_MCI, "send WLAN_CAL_GRANT");
|
|
|
|
+ MCI_GPM_SET_CAL_TYPE(payload, MCI_GPM_WLAN_CAL_GRANT);
|
|
|
|
+ ar9003_mci_send_message(ah, MCI_GPM, 0, payload,
|
|
|
|
+ 16, true, false);
|
|
|
|
+
|
|
|
|
+ ath_dbg(common, ATH_DBG_MCI, "\nMCI BT is calibrating");
|
|
|
|
+
|
|
|
|
+ /* Wait BT calibration to be completed for 25ms */
|
|
|
|
+
|
|
|
|
+ if (ar9003_mci_wait_for_gpm(ah, MCI_GPM_BT_CAL_DONE,
|
|
|
|
+ 0, 25000))
|
|
|
|
+ ath_dbg(common, ATH_DBG_MCI,
|
|
|
|
+ "MCI got BT_CAL_DONE\n");
|
|
|
|
+ else
|
|
|
|
+ ath_dbg(common, ATH_DBG_MCI,
|
|
|
|
+ "MCI ### BT cal takes to long, force"
|
|
|
|
+ "bt_state to be bt_awake\n");
|
|
|
|
+ mci_hw->bt_state = MCI_BT_AWAKE;
|
|
|
|
+ /* MCI FIX: enable mci interrupt here */
|
|
|
|
+ ar9003_mci_enable_interrupt(ah);
|
|
|
|
+
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
|
|
if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
|
|
if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
|
|
return -EIO;
|
|
return -EIO;
|
|
@@ -1558,12 +1606,29 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
|
|
if (ath9k_hw_channel_change(ah, chan)) {
|
|
if (ath9k_hw_channel_change(ah, chan)) {
|
|
ath9k_hw_loadnf(ah, ah->curchan);
|
|
ath9k_hw_loadnf(ah, ah->curchan);
|
|
ath9k_hw_start_nfcal(ah, true);
|
|
ath9k_hw_start_nfcal(ah, true);
|
|
|
|
+ if (mci && mci_hw->ready)
|
|
|
|
+ ar9003_mci_2g5g_switch(ah, true);
|
|
|
|
+
|
|
if (AR_SREV_9271(ah))
|
|
if (AR_SREV_9271(ah))
|
|
ar9002_hw_load_ani_reg(ah, chan);
|
|
ar9002_hw_load_ani_reg(ah, chan);
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if (mci) {
|
|
|
|
+ ar9003_mci_disable_interrupt(ah);
|
|
|
|
+
|
|
|
|
+ if (mci_hw->ready && !save_fullsleep) {
|
|
|
|
+ ar9003_mci_mute_bt(ah);
|
|
|
|
+ udelay(20);
|
|
|
|
+ REG_WRITE(ah, AR_BTCOEX_CTRL, 0);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ mci_hw->bt_state = MCI_BT_SLEEP;
|
|
|
|
+ mci_hw->ready = false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
saveDefAntenna = REG_READ(ah, AR_DEF_ANTENNA);
|
|
saveDefAntenna = REG_READ(ah, AR_DEF_ANTENNA);
|
|
if (saveDefAntenna == 0)
|
|
if (saveDefAntenna == 0)
|
|
saveDefAntenna = 1;
|
|
saveDefAntenna = 1;
|
|
@@ -1619,6 +1684,9 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
|
|
if (r)
|
|
if (r)
|
|
return r;
|
|
return r;
|
|
|
|
|
|
|
|
+ if (mci)
|
|
|
|
+ ar9003_mci_reset(ah, false, IS_CHAN_2GHZ(chan), save_fullsleep);
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* Some AR91xx SoC devices frequently fail to accept TSF writes
|
|
* Some AR91xx SoC devices frequently fail to accept TSF writes
|
|
* right after the chip reset. When that happens, write a new
|
|
* right after the chip reset. When that happens, write a new
|
|
@@ -1736,6 +1804,55 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
|
|
ath9k_hw_loadnf(ah, chan);
|
|
ath9k_hw_loadnf(ah, chan);
|
|
ath9k_hw_start_nfcal(ah, true);
|
|
ath9k_hw_start_nfcal(ah, true);
|
|
|
|
|
|
|
|
+ if (mci && mci_hw->ready) {
|
|
|
|
+
|
|
|
|
+ if (IS_CHAN_2GHZ(chan) &&
|
|
|
|
+ (mci_hw->bt_state == MCI_BT_SLEEP)) {
|
|
|
|
+
|
|
|
|
+ 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)) {
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * 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.
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+ ath_dbg(common, ATH_DBG_MCI, "MCI BT wakes up"
|
|
|
|
+ "during WLAN calibration\n");
|
|
|
|
+
|
|
|
|
+ REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,
|
|
|
|
+ AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET |
|
|
|
|
+ AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE);
|
|
|
|
+ ath_dbg(common, ATH_DBG_MCI, "MCI send"
|
|
|
|
+ "REMOTE_RESET\n");
|
|
|
|
+ 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);
|
|
|
|
+
|
|
|
|
+ mci_hw->bt_state = MCI_BT_AWAKE;
|
|
|
|
+
|
|
|
|
+ ath_dbg(common, ATH_DBG_MCI, "MCI re-cal\n");
|
|
|
|
+
|
|
|
|
+ if (caldata) {
|
|
|
|
+ caldata->done_txiqcal_once = false;
|
|
|
|
+ caldata->done_txclcal_once = false;
|
|
|
|
+ caldata->rtt_hist.num_readings = 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (!ath9k_hw_init_cal(ah, chan))
|
|
|
|
+ return -EIO;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ ar9003_mci_enable_interrupt(ah);
|
|
|
|
+ }
|
|
|
|
+
|
|
ENABLE_REGWRITE_BUFFER(ah);
|
|
ENABLE_REGWRITE_BUFFER(ah);
|
|
|
|
|
|
ath9k_hw_restore_chainmask(ah);
|
|
ath9k_hw_restore_chainmask(ah);
|
|
@@ -1778,6 +1895,21 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
|
|
if (ah->btcoex_hw.enabled)
|
|
if (ah->btcoex_hw.enabled)
|
|
ath9k_hw_btcoex_enable(ah);
|
|
ath9k_hw_btcoex_enable(ah);
|
|
|
|
|
|
|
|
+ if (mci && mci_hw->ready) {
|
|
|
|
+ /*
|
|
|
|
+ * check BT state again to make
|
|
|
|
+ * sure it's not changed.
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+ ar9003_mci_sync_bt_state(ah);
|
|
|
|
+ ar9003_mci_2g5g_switch(ah, true);
|
|
|
|
+
|
|
|
|
+ if ((mci_hw->bt_state == MCI_BT_AWAKE) &&
|
|
|
|
+ (mci_hw->query_bt == true)) {
|
|
|
|
+ mci_hw->need_flush_btinfo = true;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
if (AR_SREV_9300_20_OR_LATER(ah)) {
|
|
if (AR_SREV_9300_20_OR_LATER(ah)) {
|
|
ar9003_hw_bb_watchdog_config(ah);
|
|
ar9003_hw_bb_watchdog_config(ah);
|
|
|
|
|