Commit 9a658d2b authored by Luis R. Rodriguez's avatar Luis R. Rodriguez Committed by John W. Linville

ath9k_hw: fix ASPM setting for AR9003

The AR_WA register should not be read when in sleep state so
add a variable we can stash its value into for when we need
to set it. Additionally the AR_WA_D3_TO_L1_DISABLE_REAL
(bit 16) needs to be removed.

Cc: Aeolus Yang <aeolus.yang@atheros.com>
Cc: Madhan Jaganathan <madhan.jaganathan@atheros.com>
signed-off-by: default avatarLuis R. Rodriguez <lrodriguez@atheros.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 1047d5ed
...@@ -295,6 +295,8 @@ static void ar9003_hw_configpcipowersave(struct ath_hw *ah, ...@@ -295,6 +295,8 @@ static void ar9003_hw_configpcipowersave(struct ath_hw *ah,
/* Several PCIe massages to ensure proper behaviour */ /* Several PCIe massages to ensure proper behaviour */
if (ah->config.pcie_waen) if (ah->config.pcie_waen)
REG_WRITE(ah, AR_WA, ah->config.pcie_waen); REG_WRITE(ah, AR_WA, ah->config.pcie_waen);
else
REG_WRITE(ah, AR_WA, ah->WARegVal);
} }
} }
......
...@@ -575,14 +575,8 @@ static int __ath9k_hw_init(struct ath_hw *ah) ...@@ -575,14 +575,8 @@ static int __ath9k_hw_init(struct ath_hw *ah)
* This enables PCIe low power mode. * This enables PCIe low power mode.
*/ */
if (AR_SREV_9300_20_OR_LATER(ah)) { if (AR_SREV_9300_20_OR_LATER(ah)) {
u32 regval;
unsigned int i; unsigned int i;
/* Set Bits 16 and 17 in the AR_WA register. */
regval = REG_READ(ah, AR_WA);
regval |= 0x00030000;
REG_WRITE(ah, AR_WA, regval);
for (i = 0; i < ah->iniPcieSerdesLowPower.ia_rows; i++) { for (i = 0; i < ah->iniPcieSerdesLowPower.ia_rows; i++) {
REG_WRITE(ah, REG_WRITE(ah,
INI_RA(&ah->iniPcieSerdesLowPower, i, 0), INI_RA(&ah->iniPcieSerdesLowPower, i, 0),
...@@ -590,6 +584,15 @@ static int __ath9k_hw_init(struct ath_hw *ah) ...@@ -590,6 +584,15 @@ static int __ath9k_hw_init(struct ath_hw *ah)
} }
} }
/*
* Read back AR_WA into a permanent copy and set bits 14 and 17.
* We need to do this to avoid RMW of this register. We cannot
* read the reg when chip is asleep.
*/
ah->WARegVal = REG_READ(ah, AR_WA);
ah->WARegVal |= (AR_WA_D3_L1_DISABLE |
AR_WA_ASPM_TIMER_BASED_DISABLE);
if (ah->is_pciexpress) if (ah->is_pciexpress)
ath9k_hw_configpcipowersave(ah, 0, 0); ath9k_hw_configpcipowersave(ah, 0, 0);
else else
...@@ -1009,6 +1012,11 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type) ...@@ -1009,6 +1012,11 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type)
ENABLE_REGWRITE_BUFFER(ah); ENABLE_REGWRITE_BUFFER(ah);
if (AR_SREV_9300_20_OR_LATER(ah)) {
REG_WRITE(ah, AR_WA, ah->WARegVal);
udelay(10);
}
REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN | REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN |
AR_RTC_FORCE_WAKE_ON_INT); AR_RTC_FORCE_WAKE_ON_INT);
...@@ -1063,6 +1071,11 @@ static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah) ...@@ -1063,6 +1071,11 @@ static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah)
{ {
ENABLE_REGWRITE_BUFFER(ah); ENABLE_REGWRITE_BUFFER(ah);
if (AR_SREV_9300_20_OR_LATER(ah)) {
REG_WRITE(ah, AR_WA, ah->WARegVal);
udelay(10);
}
REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN | REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN |
AR_RTC_FORCE_WAKE_ON_INT); AR_RTC_FORCE_WAKE_ON_INT);
...@@ -1099,6 +1112,11 @@ static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah) ...@@ -1099,6 +1112,11 @@ static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah)
static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type) static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type)
{ {
if (AR_SREV_9300_20_OR_LATER(ah)) {
REG_WRITE(ah, AR_WA, ah->WARegVal);
udelay(10);
}
REG_WRITE(ah, AR_RTC_FORCE_WAKE, REG_WRITE(ah, AR_RTC_FORCE_WAKE,
AR_RTC_FORCE_WAKE_EN | AR_RTC_FORCE_WAKE_ON_INT); AR_RTC_FORCE_WAKE_EN | AR_RTC_FORCE_WAKE_ON_INT);
...@@ -1768,6 +1786,11 @@ static void ath9k_set_power_sleep(struct ath_hw *ah, int setChip) ...@@ -1768,6 +1786,11 @@ static void ath9k_set_power_sleep(struct ath_hw *ah, int setChip)
REG_CLR_BIT(ah, (AR_RTC_RESET), REG_CLR_BIT(ah, (AR_RTC_RESET),
AR_RTC_RESET_EN); AR_RTC_RESET_EN);
} }
/* Clear Bit 14 of AR_WA after putting chip into Full Sleep mode. */
if (AR_SREV_9300_20_OR_LATER(ah))
REG_WRITE(ah, AR_WA,
ah->WARegVal & ~AR_WA_D3_L1_DISABLE);
} }
/* /*
...@@ -1794,6 +1817,10 @@ static void ath9k_set_power_network_sleep(struct ath_hw *ah, int setChip) ...@@ -1794,6 +1817,10 @@ static void ath9k_set_power_network_sleep(struct ath_hw *ah, int setChip)
AR_RTC_FORCE_WAKE_EN); AR_RTC_FORCE_WAKE_EN);
} }
} }
/* Clear Bit 14 of AR_WA after putting chip into Net Sleep mode. */
if (AR_SREV_9300_20_OR_LATER(ah))
REG_WRITE(ah, AR_WA, ah->WARegVal & ~AR_WA_D3_L1_DISABLE);
} }
static bool ath9k_hw_set_power_awake(struct ath_hw *ah, int setChip) static bool ath9k_hw_set_power_awake(struct ath_hw *ah, int setChip)
...@@ -1801,6 +1828,12 @@ static bool ath9k_hw_set_power_awake(struct ath_hw *ah, int setChip) ...@@ -1801,6 +1828,12 @@ static bool ath9k_hw_set_power_awake(struct ath_hw *ah, int setChip)
u32 val; u32 val;
int i; int i;
/* Set Bits 14 and 17 of AR_WA before powering on the chip. */
if (AR_SREV_9300_20_OR_LATER(ah)) {
REG_WRITE(ah, AR_WA, ah->WARegVal);
udelay(10);
}
if (setChip) { if (setChip) {
if ((REG_READ(ah, AR_RTC_STATUS) & if ((REG_READ(ah, AR_RTC_STATUS) &
AR_RTC_STATUS_M) == AR_RTC_STATUS_SHUTDOWN) { AR_RTC_STATUS_M) == AR_RTC_STATUS_SHUTDOWN) {
......
...@@ -819,6 +819,12 @@ struct ath_hw { ...@@ -819,6 +819,12 @@ struct ath_hw {
u32 paprd_gain_table_entries[PAPRD_GAIN_TABLE_ENTRIES]; u32 paprd_gain_table_entries[PAPRD_GAIN_TABLE_ENTRIES];
u8 paprd_gain_table_index[PAPRD_GAIN_TABLE_ENTRIES]; u8 paprd_gain_table_index[PAPRD_GAIN_TABLE_ENTRIES];
/*
* Store the permanent value of Reg 0x4004in WARegVal
* so we dont have to R/M/W. We should not be reading
* this register when in sleep states.
*/
u32 WARegVal;
}; };
static inline struct ath_common *ath9k_hw_common(struct ath_hw *ah) static inline struct ath_common *ath9k_hw_common(struct ath_hw *ah)
......
...@@ -704,6 +704,11 @@ ...@@ -704,6 +704,11 @@
#define AR_WA_BIT7 (1 << 7) #define AR_WA_BIT7 (1 << 7)
#define AR_WA_BIT23 (1 << 23) #define AR_WA_BIT23 (1 << 23)
#define AR_WA_D3_L1_DISABLE (1 << 14) #define AR_WA_D3_L1_DISABLE (1 << 14)
#define AR_WA_D3_TO_L1_DISABLE_REAL (1 << 16)
#define AR_WA_ASPM_TIMER_BASED_DISABLE (1 << 17)
#define AR_WA_RESET_EN (1 << 18) /* Sw Control to enable PCI-Reset to POR (bit 15) */
#define AR_WA_ANALOG_SHIFT (1 << 20)
#define AR_WA_POR_SHORT (1 << 21) /* PCI-E Phy reset control */
#define AR9285_WA_DEFAULT 0x004a050b #define AR9285_WA_DEFAULT 0x004a050b
#define AR9280_WA_DEFAULT 0x0040073b #define AR9280_WA_DEFAULT 0x0040073b
#define AR_WA_DEFAULT 0x0000073f #define AR_WA_DEFAULT 0x0000073f
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment