Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
[pandora-kernel.git] / drivers / net / wireless / ath / ath9k / hw.c
index 9f01e50..f9cf815 100644 (file)
@@ -495,6 +495,17 @@ 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);
+
+       /*
+        * 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;
@@ -563,14 +574,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);
@@ -668,14 +671,51 @@ 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);
+
+#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);
 
        REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll);
@@ -1082,8 +1122,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);
 }
 
@@ -1348,8 +1386,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));
@@ -1367,6 +1403,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;