aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath9k
diff options
context:
space:
mode:
authorRajkumar Manoharan <rmanohar@qca.qualcomm.com>2012-06-11 02:49:31 -0400
committerJohn W. Linville <linville@tuxdriver.com>2012-06-13 14:35:52 -0400
commit9dd9b0dc1de8031a31b3eaebc6a9c0ab60612026 (patch)
tree84ea6caa93de07d8881b77d657bcb82b72ee1083 /drivers/net/wireless/ath/ath9k
parent8389fb3fd7c0bbe3289578f698917f594e0b6fc9 (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.c34
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_mci.h10
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c3
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
1408void 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,
265void ar9003_mci_cleanup(struct ath_hw *ah); 265void ar9003_mci_cleanup(struct ath_hw *ah);
266void ar9003_mci_get_interrupt(struct ath_hw *ah, u32 *raw_intr, 266void ar9003_mci_get_interrupt(struct ath_hw *ah, u32 *raw_intr,
267 u32 *rx_msg_intr); 267 u32 *rx_msg_intr);
268void 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,
285void ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g, 283void ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g,
286 bool is_full_sleep); 284 bool is_full_sleep);
287void ar9003_mci_get_isr(struct ath_hw *ah, enum ath9k_int *masked); 285void ar9003_mci_get_isr(struct ath_hw *ah, enum ath9k_int *masked);
286void ar9003_mci_bt_gain_ctrl(struct ath_hw *ah);
287void 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,
322static inline void ar9003_mci_get_isr(struct ath_hw *ah, enum ath9k_int *masked) 322static inline void ar9003_mci_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
323{ 323{
324} 324}
325static inline void ar9003_mci_bt_gain_ctrl(struct ath_hw *ah)
326{
327}
328static 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)