Skip to content

Commit

Permalink
ath9k_hw: Fix AR9462 power consumption on idle associated
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Rajkumar Manoharan authored and John W. Linville committed Jun 13, 2012
1 parent 8389fb3 commit 9dd9b0d
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 2 deletions.
34 changes: 34 additions & 0 deletions drivers/net/wireless/ath/ath9k/ar9003_mci.c
Original file line number Diff line number Diff line change
Expand Up @@ -1404,3 +1404,37 @@ void ar9003_mci_bt_gain_ctrl(struct ath_hw *ah)
/* Force another 2g5g update at next scanning */
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);
}
}
10 changes: 8 additions & 2 deletions drivers/net/wireless/ath/ath9k/ar9003_mci.h
Original file line number Diff line number Diff line change
Expand Up @@ -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_get_interrupt(struct ath_hw *ah, u32 *raw_intr,
u32 *rx_msg_intr);
void ar9003_mci_bt_gain_ctrl(struct ath_hw *ah);

/*
* These functions are used by ath9k_hw.
*/
Expand All @@ -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,
bool is_full_sleep);
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

Expand Down Expand Up @@ -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_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
3 changes: 3 additions & 0 deletions drivers/net/wireless/ath/ath9k/hw.c
Original file line number Diff line number Diff line change
Expand Up @@ -2111,6 +2111,9 @@ static bool ath9k_hw_set_power_awake(struct ath_hw *ah)
AR_RTC_FORCE_WAKE_EN);
udelay(50);

if (ath9k_hw_mci_is_enabled(ah))
ar9003_mci_set_power_awake(ah);

for (i = POWER_UP_TIME / 50; i > 0; i--) {
val = REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M;
if (val == AR_RTC_STATUS_ON)
Expand Down

0 comments on commit 9dd9b0d

Please sign in to comment.