diff options
author | Rajkumar Manoharan <rmanohar@qca.qualcomm.com> | 2012-06-11 02:49:31 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-06-13 14:35:52 -0400 |
commit | 9dd9b0dc1de8031a31b3eaebc6a9c0ab60612026 (patch) | |
tree | 84ea6caa93de07d8881b77d657bcb82b72ee1083 /drivers/net/wireless/ath/ath9k | |
parent | 8389fb3fd7c0bbe3289578f698917f594e0b6fc9 (diff) |
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>
Diffstat (limited to 'drivers/net/wireless/ath/ath9k')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ar9003_mci.c | 34 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ar9003_mci.h | 10 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/hw.c | 3 |
3 files changed, 45 insertions, 2 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mci.c b/drivers/net/wireless/ath/ath9k/ar9003_mci.c index b1ced2a76da3..13907f63bdc0 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mci.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mci.c | |||
@@ -1404,3 +1404,37 @@ void ar9003_mci_bt_gain_ctrl(struct ath_hw *ah) | |||
1404 | /* Force another 2g5g update at next scanning */ | 1404 | /* Force another 2g5g update at next scanning */ |
1405 | mci->update_2g5g = true; | 1405 | mci->update_2g5g = true; |
1406 | } | 1406 | } |
1407 | |||
1408 | void ar9003_mci_set_power_awake(struct ath_hw *ah) | ||
1409 | { | ||
1410 | u32 btcoex_ctrl2, diag_sw; | ||
1411 | int i; | ||
1412 | u8 lna_ctrl, bt_sleep; | ||
1413 | |||
1414 | for (i = 0; i < AH_WAIT_TIMEOUT; i++) { | ||
1415 | btcoex_ctrl2 = REG_READ(ah, AR_BTCOEX_CTRL2); | ||
1416 | if (btcoex_ctrl2 != 0xdeadbeef) | ||
1417 | break; | ||
1418 | udelay(AH_TIME_QUANTUM); | ||
1419 | } | ||
1420 | REG_WRITE(ah, AR_BTCOEX_CTRL2, (btcoex_ctrl2 | BIT(23))); | ||
1421 | |||
1422 | for (i = 0; i < AH_WAIT_TIMEOUT; i++) { | ||
1423 | diag_sw = REG_READ(ah, AR_DIAG_SW); | ||
1424 | if (diag_sw != 0xdeadbeef) | ||
1425 | break; | ||
1426 | udelay(AH_TIME_QUANTUM); | ||
1427 | } | ||
1428 | REG_WRITE(ah, AR_DIAG_SW, (diag_sw | BIT(27) | BIT(19) | BIT(18))); | ||
1429 | lna_ctrl = REG_READ(ah, AR_OBS_BUS_CTRL) & 0x3; | ||
1430 | bt_sleep = REG_READ(ah, AR_MCI_RX_STATUS) & AR_MCI_RX_REMOTE_SLEEP; | ||
1431 | |||
1432 | REG_WRITE(ah, AR_BTCOEX_CTRL2, btcoex_ctrl2); | ||
1433 | REG_WRITE(ah, AR_DIAG_SW, diag_sw); | ||
1434 | |||
1435 | if (bt_sleep && (lna_ctrl == 2)) { | ||
1436 | REG_SET_BIT(ah, AR_BTCOEX_RC, 0x1); | ||
1437 | REG_CLR_BIT(ah, AR_BTCOEX_RC, 0x1); | ||
1438 | udelay(50); | ||
1439 | } | ||
1440 | } | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mci.h b/drivers/net/wireless/ath/ath9k/ar9003_mci.h index 10282e2bcdc9..2a8c764281ba 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mci.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_mci.h | |||
@@ -265,8 +265,6 @@ void ar9003_mci_setup(struct ath_hw *ah, u32 gpm_addr, void *gpm_buf, | |||
265 | void ar9003_mci_cleanup(struct ath_hw *ah); | 265 | void ar9003_mci_cleanup(struct ath_hw *ah); |
266 | void ar9003_mci_get_interrupt(struct ath_hw *ah, u32 *raw_intr, | 266 | void ar9003_mci_get_interrupt(struct ath_hw *ah, u32 *raw_intr, |
267 | u32 *rx_msg_intr); | 267 | u32 *rx_msg_intr); |
268 | void ar9003_mci_bt_gain_ctrl(struct ath_hw *ah); | ||
269 | |||
270 | /* | 268 | /* |
271 | * These functions are used by ath9k_hw. | 269 | * These functions are used by ath9k_hw. |
272 | */ | 270 | */ |
@@ -285,6 +283,8 @@ int ar9003_mci_end_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
285 | void ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g, | 283 | void ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g, |
286 | bool is_full_sleep); | 284 | bool is_full_sleep); |
287 | void ar9003_mci_get_isr(struct ath_hw *ah, enum ath9k_int *masked); | 285 | void ar9003_mci_get_isr(struct ath_hw *ah, enum ath9k_int *masked); |
286 | void ar9003_mci_bt_gain_ctrl(struct ath_hw *ah); | ||
287 | void ar9003_mci_set_power_awake(struct ath_hw *ah); | ||
288 | 288 | ||
289 | #else | 289 | #else |
290 | 290 | ||
@@ -322,6 +322,12 @@ static inline void ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g, | |||
322 | static inline void ar9003_mci_get_isr(struct ath_hw *ah, enum ath9k_int *masked) | 322 | static inline void ar9003_mci_get_isr(struct ath_hw *ah, enum ath9k_int *masked) |
323 | { | 323 | { |
324 | } | 324 | } |
325 | static inline void ar9003_mci_bt_gain_ctrl(struct ath_hw *ah) | ||
326 | { | ||
327 | } | ||
328 | static inline void ar9003_mci_set_power_awake(struct ath_hw *ah) | ||
329 | { | ||
330 | } | ||
325 | #endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */ | 331 | #endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */ |
326 | 332 | ||
327 | #endif | 333 | #endif |
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 45e670087e1c..6d893335f42b 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
@@ -2111,6 +2111,9 @@ static bool ath9k_hw_set_power_awake(struct ath_hw *ah) | |||
2111 | AR_RTC_FORCE_WAKE_EN); | 2111 | AR_RTC_FORCE_WAKE_EN); |
2112 | udelay(50); | 2112 | udelay(50); |
2113 | 2113 | ||
2114 | if (ath9k_hw_mci_is_enabled(ah)) | ||
2115 | ar9003_mci_set_power_awake(ah); | ||
2116 | |||
2114 | for (i = POWER_UP_TIME / 50; i > 0; i--) { | 2117 | for (i = POWER_UP_TIME / 50; i > 0; i--) { |
2115 | val = REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M; | 2118 | val = REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M; |
2116 | if (val == AR_RTC_STATUS_ON) | 2119 | if (val == AR_RTC_STATUS_ON) |