From ac45c12dfb3f727a5a7a3332ed9c11b4a5ab287e Mon Sep 17 00:00:00 2001 From: Senthil Balasubramanian Date: Wed, 22 Dec 2010 21:14:20 +0530 Subject: ath9k_hw: Fix incorrect macversion and macrev checks There are few places where we are checking for macversion and revsions before RTC is powered ON. However we are reading the macversion and revisions only after RTC is powered ON and so both macversion and revisions are actully zero and this leads to incorrect srev checks Incorrect srev checks can cause registers to be configured wrongly and can cause unexpected behavior. Fixing this seems to address the ASPM issue that we have observed. The laptop becomes very slow and hangs mostly with ASPM L1 enabled without this fix. fix this by reading the macversion and revisisons even before we start using them. There is no reason why should we delay reading this info until RTC is powered on as this is just a register information. Cc: Stable Kernel Signed-off-by: Senthil Balasubramanian Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless/ath/ath9k/hw.c') diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 1afb8bb8575..c0838c216aa 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -492,6 +492,8 @@ static int __ath9k_hw_init(struct ath_hw *ah) if (ah->hw_version.devid == AR5416_AR9100_DEVID) ah->hw_version.macVersion = AR_SREV_VERSION_9100; + ath9k_hw_read_revisions(ah); + if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) { ath_err(common, "Couldn't reset chip\n"); return -EIO; @@ -1079,8 +1081,6 @@ static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah) return false; } - ath9k_hw_read_revisions(ah); - return ath9k_hw_set_reset(ah, ATH9K_RESET_WARM); } -- cgit v1.2.3-70-g09d2 From 0a8d7cb0c8182df7a28ad719780071178c386f0f Mon Sep 17 00:00:00 2001 From: Senthil Balasubramanian Date: Wed, 22 Dec 2010 19:17:18 +0530 Subject: ath9k_hw: read and backup AR_WA register value even before chip reset on. We need to read and backup AR_WA register value permanently and reading this after the chip is awakened results in this register being zeroed out. This seems to fix the ASPM with L1 enabled issue that we have observed. The laptop becomes very slow and hangs mostly with ASPM L1 enabled without this fix. Cc: Stable Kernel Signed-off-by: Senthil Balasubramanian Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'drivers/net/wireless/ath/ath9k/hw.c') diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index c0838c216aa..bc92b4579b2 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -494,6 +494,15 @@ static int __ath9k_hw_init(struct ath_hw *ah) ath9k_hw_read_revisions(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 (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) { ath_err(common, "Couldn't reset chip\n"); return -EIO; @@ -562,14 +571,6 @@ static int __ath9k_hw_init(struct ath_hw *ah) ath9k_hw_init_mode_regs(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) ath9k_hw_configpcipowersave(ah, 0, 0); -- cgit v1.2.3-70-g09d2 From 00e0003e0969517c5a447ac3173442dfbdb0613b Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 26 Jan 2011 21:59:05 +0530 Subject: ath9k_hw: Fix opmode initialization Commit "ath9k_hw: Relocate Opmode initialization" moved the opmode initialization before the STA_ID1 register was programmed with defaults. This changed the original behaviour because the re-programming code doesn't take into account the existing value in the register. Both ath9k and ath9k_htc were not affected by this change because the opmode is re-initialized after every reset, when RX is started. Revert to the original behavior, except keep it outside the REGWRITE block. This would help remove extraneous opmode calls in the driver core. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless/ath/ath9k/hw.c') diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index bc92b4579b2..48d121c24eb 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1346,8 +1346,6 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, ath9k_hw_spur_mitigate_freq(ah, chan); ah->eep_ops->set_board_values(ah, chan); - ath9k_hw_set_operating_mode(ah, ah->opmode); - ENABLE_REGWRITE_BUFFER(ah); REG_WRITE(ah, AR_STA_ID0, get_unaligned_le32(common->macaddr)); @@ -1365,6 +1363,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, REGWRITE_BUFFER_FLUSH(ah); + ath9k_hw_set_operating_mode(ah, ah->opmode); + r = ath9k_hw_rf_set_freq(ah, chan); if (r) return r; -- cgit v1.2.3-70-g09d2 From b141581923ab4904052174e3b4eb17cc3ce8632c Mon Sep 17 00:00:00 2001 From: Vivek Natarajan Date: Thu, 27 Jan 2011 14:45:07 +0530 Subject: ath9k_hw: Add a function to read sqsum_dvc. Add a function to observe the delta VC of BB_PLL. For a good chip, the sqsum_dvc is below 2000. Signed-off-by: Vivek Natarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 13 +++++++++++++ drivers/net/wireless/ath/ath9k/hw.h | 1 + drivers/net/wireless/ath/ath9k/reg.h | 6 ++++++ 3 files changed, 20 insertions(+) (limited to 'drivers/net/wireless/ath/ath9k/hw.c') diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 48d121c24eb..0e64d766605 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -668,6 +668,19 @@ static void ath9k_hw_init_qos(struct ath_hw *ah) REGWRITE_BUFFER_FLUSH(ah); } +unsigned long ar9003_get_pll_sqsum_dvc(struct ath_hw *ah) +{ + REG_WRITE(ah, PLL3, (REG_READ(ah, PLL3) & ~(PLL3_DO_MEAS_MASK))); + udelay(100); + REG_WRITE(ah, PLL3, (REG_READ(ah, PLL3) | PLL3_DO_MEAS_MASK)); + + while ((REG_READ(ah, PLL4) & PLL4_MEAS_DONE) == 0) + udelay(100); + + return (REG_READ(ah, PLL3) & SQSUM_DVC_MASK) >> 3; +} +EXPORT_SYMBOL(ar9003_get_pll_sqsum_dvc); + static void ath9k_hw_init_pll(struct ath_hw *ah, struct ath9k_channel *chan) { diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index c2b3515deea..8c688a12cba 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -928,6 +928,7 @@ void ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64); void ath9k_hw_reset_tsf(struct ath_hw *ah); void ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting); void ath9k_hw_init_global_settings(struct ath_hw *ah); +unsigned long ar9003_get_pll_sqsum_dvc(struct ath_hw *ah); void ath9k_hw_set11nmac2040(struct ath_hw *ah); void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period); void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index 4df5659c6c1..264aea7919e 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -1129,6 +1129,12 @@ enum { #define AR_RTC_PLL_CLKSEL 0x00000300 #define AR_RTC_PLL_CLKSEL_S 8 +#define PLL3 0x16188 +#define PLL3_DO_MEAS_MASK 0x40000000 +#define PLL4 0x1618c +#define PLL4_MEAS_DONE 0x8 +#define SQSUM_DVC_MASK 0x007ffff8 + #define AR_RTC_RESET \ ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0040) : 0x7040) #define AR_RTC_RESET_EN (0x00000001) -- cgit v1.2.3-70-g09d2 From 22983c301f01b297a6f85de4757108c6b0eac792 Mon Sep 17 00:00:00 2001 From: Vivek Natarajan Date: Thu, 27 Jan 2011 14:45:09 +0530 Subject: ath9k_hw: DDR_PLL and BB_PLL need correct setting. Updates from the analog team for AR9485 chipsets to set DDR_PLL2 and DDR_PLL3. Also program the BB_PLL ki and kd value. Signed-off-by: Vivek Natarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 26 +++++++++++++++++++++++++- drivers/net/wireless/ath/ath9k/reg.h | 11 +++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless/ath/ath9k/hw.c') diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 0e64d766605..ca6f10b8947 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -681,13 +681,37 @@ unsigned long ar9003_get_pll_sqsum_dvc(struct ath_hw *ah) } EXPORT_SYMBOL(ar9003_get_pll_sqsum_dvc); +#define DPLL2_KD_VAL 0x3D +#define DPLL2_KI_VAL 0x06 +#define DPLL3_PHASE_SHIFT_VAL 0x1 + static void ath9k_hw_init_pll(struct ath_hw *ah, struct ath9k_channel *chan) { u32 pll; - if (AR_SREV_9485(ah)) + if (AR_SREV_9485(ah)) { REG_WRITE(ah, AR_RTC_PLL_CONTROL2, 0x886666); + REG_WRITE(ah, AR_CH0_DDR_DPLL2, 0x19e82f01); + + REG_RMW_FIELD(ah, AR_CH0_DDR_DPLL3, + AR_CH0_DPLL3_PHASE_SHIFT, DPLL3_PHASE_SHIFT_VAL); + + REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x1142c); + udelay(100); + + REG_WRITE(ah, AR_RTC_PLL_CONTROL2, 0x886666); + + REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, + AR_CH0_DPLL2_KD, DPLL2_KD_VAL); + REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, + AR_CH0_DPLL2_KI, DPLL2_KI_VAL); + + REG_RMW_FIELD(ah, AR_CH0_BB_DPLL3, + AR_CH0_DPLL3_PHASE_SHIFT, DPLL3_PHASE_SHIFT_VAL); + REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x142c); + udelay(110); + } pll = ath9k_hw_compute_pll_control(ah, chan); diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index 264aea7919e..b262e98709d 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -1083,6 +1083,17 @@ enum { #define AR_ENT_OTP 0x40d8 #define AR_ENT_OTP_CHAIN2_DISABLE 0x00020000 #define AR_ENT_OTP_MPSD 0x00800000 +#define AR_CH0_BB_DPLL2 0x16184 +#define AR_CH0_BB_DPLL3 0x16188 +#define AR_CH0_DDR_DPLL2 0x16244 +#define AR_CH0_DDR_DPLL3 0x16248 +#define AR_CH0_DPLL2_KD 0x03F80000 +#define AR_CH0_DPLL2_KD_S 19 +#define AR_CH0_DPLL2_KI 0x3C000000 +#define AR_CH0_DPLL2_KI_S 26 +#define AR_CH0_DPLL3_PHASE_SHIFT 0x3F800000 +#define AR_CH0_DPLL3_PHASE_SHIFT_S 23 +#define AR_PHY_CCA_NOM_VAL_2GHZ -118 #define AR_RTC_9300_PLL_DIV 0x000003ff #define AR_RTC_9300_PLL_DIV_S 0 -- cgit v1.2.3-70-g09d2 From 320d6c1b56de5f461c6062625b9664095f90ee95 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Mon, 21 Feb 2011 17:07:12 +0530 Subject: ath9k_hw: Fix power on reset Commit "ath9k_hw: add an extra delay when reseting AR_RTC_RESET" added an extra udelay to the reset routine. As the required delay is already present, remove this. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/net/wireless/ath/ath9k/hw.c') diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index f9cf8155181..9a3438174f8 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1100,7 +1100,6 @@ static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah) REG_WRITE(ah, AR_RC, AR_RC_AHB); REG_WRITE(ah, AR_RTC_RESET, 0); - udelay(2); REGWRITE_BUFFER_FLUSH(ah); -- cgit v1.2.3-70-g09d2 From 75e03512455827eb2c09e057578ae23178a93cf8 Mon Sep 17 00:00:00 2001 From: Vivek Natarajan Date: Thu, 10 Mar 2011 11:05:42 +0530 Subject: ath9k_hw: Fix PLL initialization for AR9485. Increase the delay to make sure the initialization of pll passes. Signed-off-by: Vivek Natarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless/ath/ath9k/hw.c') diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 9a3438174f8..338b07502f1 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -701,7 +701,7 @@ static void ath9k_hw_init_pll(struct ath_hw *ah, AR_CH0_DPLL3_PHASE_SHIFT, DPLL3_PHASE_SHIFT_VAL); REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x1142c); - udelay(100); + udelay(1000); REG_WRITE(ah, AR_RTC_PLL_CONTROL2, 0x886666); @@ -713,7 +713,7 @@ static void ath9k_hw_init_pll(struct ath_hw *ah, REG_RMW_FIELD(ah, AR_CH0_BB_DPLL3, AR_CH0_DPLL3_PHASE_SHIFT, DPLL3_PHASE_SHIFT_VAL); REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x142c); - udelay(110); + udelay(1000); } pll = ath9k_hw_compute_pll_control(ah, chan); -- cgit v1.2.3-70-g09d2