mirror of https://gitee.com/openkylin/linux.git
ath9k_hw: Update the PCI WAR register
This patch updates the PCI power save handling code, fixing ASPM hangs and handling device state D3 properly. The WAR register is programmed with the correct values now. Signed-off-by: Sujith <Sujith.Manoharan@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
a55f858852
commit
15ae733b25
|
@ -436,55 +436,84 @@ static void ar9002_hw_configpcipowersave(struct ath_hw *ah,
|
||||||
}
|
}
|
||||||
|
|
||||||
udelay(1000);
|
udelay(1000);
|
||||||
|
}
|
||||||
|
|
||||||
/* set bit 19 to allow forcing of pcie core into L1 state */
|
if (power_off) {
|
||||||
REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
|
/* clear bit 19 to disable L1 */
|
||||||
|
REG_CLR_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
|
||||||
|
|
||||||
/* Several PCIe massages to ensure proper behaviour */
|
val = REG_READ(ah, AR_WA);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set PCIe workaround bits
|
||||||
|
* In AR9280 and AR9285, bit 14 in WA register (disable L1)
|
||||||
|
* should only be set when device enters D3 and be
|
||||||
|
* cleared when device comes back to D0.
|
||||||
|
*/
|
||||||
|
if (ah->config.pcie_waen) {
|
||||||
|
if (ah->config.pcie_waen & AR_WA_D3_L1_DISABLE)
|
||||||
|
val |= AR_WA_D3_L1_DISABLE;
|
||||||
|
} else {
|
||||||
|
if (((AR_SREV_9285(ah) ||
|
||||||
|
AR_SREV_9271(ah) ||
|
||||||
|
AR_SREV_9287(ah)) &&
|
||||||
|
(AR9285_WA_DEFAULT & AR_WA_D3_L1_DISABLE)) ||
|
||||||
|
(AR_SREV_9280(ah) &&
|
||||||
|
(AR9280_WA_DEFAULT & AR_WA_D3_L1_DISABLE))) {
|
||||||
|
val |= AR_WA_D3_L1_DISABLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (AR_SREV_9280(ah) || AR_SREV_9285(ah) || AR_SREV_9287(ah)) {
|
||||||
|
/*
|
||||||
|
* Disable bit 6 and 7 before entering D3 to
|
||||||
|
* prevent system hang.
|
||||||
|
*/
|
||||||
|
val &= ~(AR_WA_BIT6 | AR_WA_BIT7);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (AR_SREV_9285E_20(ah))
|
||||||
|
val |= AR_WA_BIT23;
|
||||||
|
|
||||||
|
REG_WRITE(ah, AR_WA, val);
|
||||||
|
} else {
|
||||||
if (ah->config.pcie_waen) {
|
if (ah->config.pcie_waen) {
|
||||||
val = ah->config.pcie_waen;
|
val = ah->config.pcie_waen;
|
||||||
if (!power_off)
|
if (!power_off)
|
||||||
val &= (~AR_WA_D3_L1_DISABLE);
|
val &= (~AR_WA_D3_L1_DISABLE);
|
||||||
} else {
|
} else {
|
||||||
if (AR_SREV_9285(ah) || AR_SREV_9271(ah) ||
|
if (AR_SREV_9285(ah) ||
|
||||||
|
AR_SREV_9271(ah) ||
|
||||||
AR_SREV_9287(ah)) {
|
AR_SREV_9287(ah)) {
|
||||||
val = AR9285_WA_DEFAULT;
|
val = AR9285_WA_DEFAULT;
|
||||||
if (!power_off)
|
if (!power_off)
|
||||||
val &= (~AR_WA_D3_L1_DISABLE);
|
val &= (~AR_WA_D3_L1_DISABLE);
|
||||||
} else if (AR_SREV_9280(ah)) {
|
}
|
||||||
|
else if (AR_SREV_9280(ah)) {
|
||||||
/*
|
/*
|
||||||
* On AR9280 chips bit 22 of 0x4004 needs to be
|
* For AR9280 chips, bit 22 of 0x4004
|
||||||
* set otherwise card may disappear.
|
* needs to be set.
|
||||||
*/
|
*/
|
||||||
val = AR9280_WA_DEFAULT;
|
val = AR9280_WA_DEFAULT;
|
||||||
if (!power_off)
|
if (!power_off)
|
||||||
val &= (~AR_WA_D3_L1_DISABLE);
|
val &= (~AR_WA_D3_L1_DISABLE);
|
||||||
} else
|
} else {
|
||||||
val = AR_WA_DEFAULT;
|
val = AR_WA_DEFAULT;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* WAR for ASPM system hang */
|
||||||
|
if (AR_SREV_9280(ah) || AR_SREV_9285(ah) || AR_SREV_9287(ah)) {
|
||||||
|
val |= (AR_WA_BIT6 | AR_WA_BIT7);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (AR_SREV_9285E_20(ah))
|
||||||
|
val |= AR_WA_BIT23;
|
||||||
|
|
||||||
REG_WRITE(ah, AR_WA, val);
|
REG_WRITE(ah, AR_WA, val);
|
||||||
}
|
|
||||||
|
|
||||||
if (power_off) {
|
/* set bit 19 to allow forcing of pcie core into L1 state */
|
||||||
/*
|
REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
|
||||||
* Set PCIe workaround bits
|
|
||||||
* bit 14 in WA register (disable L1) should only
|
|
||||||
* be set when device enters D3 and be cleared
|
|
||||||
* when device comes back to D0.
|
|
||||||
*/
|
|
||||||
if (ah->config.pcie_waen) {
|
|
||||||
if (ah->config.pcie_waen & AR_WA_D3_L1_DISABLE)
|
|
||||||
REG_SET_BIT(ah, AR_WA, AR_WA_D3_L1_DISABLE);
|
|
||||||
} else {
|
|
||||||
if (((AR_SREV_9285(ah) || AR_SREV_9271(ah) ||
|
|
||||||
AR_SREV_9287(ah)) &&
|
|
||||||
(AR9285_WA_DEFAULT & AR_WA_D3_L1_DISABLE)) ||
|
|
||||||
(AR_SREV_9280(ah) &&
|
|
||||||
(AR9280_WA_DEFAULT & AR_WA_D3_L1_DISABLE))) {
|
|
||||||
REG_SET_BIT(ah, AR_WA, AR_WA_D3_L1_DISABLE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -700,6 +700,9 @@
|
||||||
#define AR_RC_HOSTIF 0x00000100
|
#define AR_RC_HOSTIF 0x00000100
|
||||||
|
|
||||||
#define AR_WA 0x4004
|
#define AR_WA 0x4004
|
||||||
|
#define AR_WA_BIT6 (1 << 6)
|
||||||
|
#define AR_WA_BIT7 (1 << 7)
|
||||||
|
#define AR_WA_BIT23 (1 << 23)
|
||||||
#define AR_WA_D3_L1_DISABLE (1 << 14)
|
#define AR_WA_D3_L1_DISABLE (1 << 14)
|
||||||
#define AR9285_WA_DEFAULT 0x004a050b
|
#define AR9285_WA_DEFAULT 0x004a050b
|
||||||
#define AR9280_WA_DEFAULT 0x0040073b
|
#define AR9280_WA_DEFAULT 0x0040073b
|
||||||
|
|
Loading…
Reference in New Issue