ath9k_hw: Fix AR9462 power consumption on idle associated

The HW statemachine is sometimes found stuck in the state
WL_LNA_CTRL_DISABLE when BT is in sleep, which will cause
TX_HOLD always asserted and resmgr stuck in PENDING_TX state

Signed-off-by: Rajkumar Manoharan <rmanohar@qca.qualcomm.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
Rajkumar Manoharan 2012-06-11 12:19:31 +05:30 committed by John W. Linville
parent 8389fb3fd7
commit 9dd9b0dc1d
3 changed files with 45 additions and 2 deletions

View File

@ -1404,3 +1404,37 @@ void ar9003_mci_bt_gain_ctrl(struct ath_hw *ah)
/* Force another 2g5g update at next scanning */ /* Force another 2g5g update at next scanning */
mci->update_2g5g = true; mci->update_2g5g = true;
} }
void ar9003_mci_set_power_awake(struct ath_hw *ah)
{
u32 btcoex_ctrl2, diag_sw;
int i;
u8 lna_ctrl, bt_sleep;
for (i = 0; i < AH_WAIT_TIMEOUT; i++) {
btcoex_ctrl2 = REG_READ(ah, AR_BTCOEX_CTRL2);
if (btcoex_ctrl2 != 0xdeadbeef)
break;
udelay(AH_TIME_QUANTUM);
}
REG_WRITE(ah, AR_BTCOEX_CTRL2, (btcoex_ctrl2 | BIT(23)));
for (i = 0; i < AH_WAIT_TIMEOUT; i++) {
diag_sw = REG_READ(ah, AR_DIAG_SW);
if (diag_sw != 0xdeadbeef)
break;
udelay(AH_TIME_QUANTUM);
}
REG_WRITE(ah, AR_DIAG_SW, (diag_sw | BIT(27) | BIT(19) | BIT(18)));
lna_ctrl = REG_READ(ah, AR_OBS_BUS_CTRL) & 0x3;
bt_sleep = REG_READ(ah, AR_MCI_RX_STATUS) & AR_MCI_RX_REMOTE_SLEEP;
REG_WRITE(ah, AR_BTCOEX_CTRL2, btcoex_ctrl2);
REG_WRITE(ah, AR_DIAG_SW, diag_sw);
if (bt_sleep && (lna_ctrl == 2)) {
REG_SET_BIT(ah, AR_BTCOEX_RC, 0x1);
REG_CLR_BIT(ah, AR_BTCOEX_RC, 0x1);
udelay(50);
}
}

View File

@ -265,8 +265,6 @@ void ar9003_mci_setup(struct ath_hw *ah, u32 gpm_addr, void *gpm_buf,
void ar9003_mci_cleanup(struct ath_hw *ah); void ar9003_mci_cleanup(struct ath_hw *ah);
void ar9003_mci_get_interrupt(struct ath_hw *ah, u32 *raw_intr, void ar9003_mci_get_interrupt(struct ath_hw *ah, u32 *raw_intr,
u32 *rx_msg_intr); u32 *rx_msg_intr);
void ar9003_mci_bt_gain_ctrl(struct ath_hw *ah);
/* /*
* These functions are used by ath9k_hw. * These functions are used by ath9k_hw.
*/ */
@ -285,6 +283,8 @@ int ar9003_mci_end_reset(struct ath_hw *ah, struct ath9k_channel *chan,
void ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g, void ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g,
bool is_full_sleep); bool is_full_sleep);
void ar9003_mci_get_isr(struct ath_hw *ah, enum ath9k_int *masked); void ar9003_mci_get_isr(struct ath_hw *ah, enum ath9k_int *masked);
void ar9003_mci_bt_gain_ctrl(struct ath_hw *ah);
void ar9003_mci_set_power_awake(struct ath_hw *ah);
#else #else
@ -322,6 +322,12 @@ static inline void ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g,
static inline void ar9003_mci_get_isr(struct ath_hw *ah, enum ath9k_int *masked) static inline void ar9003_mci_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
{ {
} }
static inline void ar9003_mci_bt_gain_ctrl(struct ath_hw *ah)
{
}
static inline void ar9003_mci_set_power_awake(struct ath_hw *ah)
{
}
#endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */ #endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */
#endif #endif

View File

@ -2111,6 +2111,9 @@ static bool ath9k_hw_set_power_awake(struct ath_hw *ah)
AR_RTC_FORCE_WAKE_EN); AR_RTC_FORCE_WAKE_EN);
udelay(50); udelay(50);
if (ath9k_hw_mci_is_enabled(ah))
ar9003_mci_set_power_awake(ah);
for (i = POWER_UP_TIME / 50; i > 0; i--) { for (i = POWER_UP_TIME / 50; i > 0; i--) {
val = REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M; val = REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M;
if (val == AR_RTC_STATUS_ON) if (val == AR_RTC_STATUS_ON)