ath9k_hw: Configure internal regulator for AR9485
authorVasanthakumar Thiagarajan <vasanth@atheros.com>
Tue, 7 Dec 2010 10:20:39 +0000 (02:20 -0800)
committerJohn W. Linville <linville@tuxdriver.com>
Tue, 7 Dec 2010 21:34:58 +0000 (16:34 -0500)
Signed-off-by: Vasanthakumar Thiagarajan <vasanth@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
drivers/net/wireless/ath/ath9k/ar9003_phy.h

index 45fe5c2ec3b91448e89a4dee83e0e7d7328f71b2..c02e43d5c9c93e9cc015a9edbb2e20ee921ecd15 100644 (file)
@@ -3653,29 +3653,88 @@ static void ar9003_hw_atten_apply(struct ath_hw *ah, struct ath9k_channel *chan)
        }
 }
 
+static bool is_pmu_set(struct ath_hw *ah, u32 pmu_reg, int pmu_set)
+{
+       int timeout = 100;
+
+       while (pmu_set != REG_READ(ah, pmu_reg)) {
+               if (timeout-- == 0)
+                       return false;
+               REG_WRITE(ah, pmu_reg, pmu_set);
+               udelay(10);
+       }
+
+       return true;
+}
+
 static void ar9003_hw_internal_regulator_apply(struct ath_hw *ah)
 {
        int internal_regulator =
                ath9k_hw_ar9300_get_eeprom(ah, EEP_INTERNAL_REGULATOR);
 
        if (internal_regulator) {
-               /* Internal regulator is ON. Write swreg register. */
-               int swreg = ath9k_hw_ar9300_get_eeprom(ah, EEP_SWREG);
-               REG_WRITE(ah, AR_RTC_REG_CONTROL1,
-               REG_READ(ah, AR_RTC_REG_CONTROL1) &
-                        (~AR_RTC_REG_CONTROL1_SWREG_PROGRAM));
-               REG_WRITE(ah, AR_RTC_REG_CONTROL0, swreg);
-               /* Set REG_CONTROL1.SWREG_PROGRAM */
-               REG_WRITE(ah, AR_RTC_REG_CONTROL1,
-                         REG_READ(ah,
-                                  AR_RTC_REG_CONTROL1) |
-                                  AR_RTC_REG_CONTROL1_SWREG_PROGRAM);
+               if (AR_SREV_9485(ah)) {
+                       int reg_pmu_set;
+
+                       reg_pmu_set = REG_READ(ah, AR_PHY_PMU2) & ~AR_PHY_PMU2_PGM;
+                       REG_WRITE(ah, AR_PHY_PMU2, reg_pmu_set);
+                       if (!is_pmu_set(ah, AR_PHY_PMU2, reg_pmu_set))
+                               return;
+
+                       reg_pmu_set = (5 << 1) | (7 << 4) | (1 << 8) |
+                                     (7 << 14) | (6 << 17) | (1 << 20) |
+                                     (3 << 24) | (1 << 28);
+
+                       REG_WRITE(ah, AR_PHY_PMU1, reg_pmu_set);
+                       if (!is_pmu_set(ah, AR_PHY_PMU1, reg_pmu_set))
+                               return;
+
+                       reg_pmu_set = (REG_READ(ah, AR_PHY_PMU2) & ~0xFFC00000)
+                                       | (4 << 26);
+                       REG_WRITE(ah, AR_PHY_PMU2, reg_pmu_set);
+                       if (!is_pmu_set(ah, AR_PHY_PMU2, reg_pmu_set))
+                               return;
+
+                       reg_pmu_set = (REG_READ(ah, AR_PHY_PMU2) & ~0x00200000)
+                                       | (1 << 21);
+                       REG_WRITE(ah, AR_PHY_PMU2, reg_pmu_set);
+                       if (!is_pmu_set(ah, AR_PHY_PMU2, reg_pmu_set))
+                               return;
+               } else {
+                       /* Internal regulator is ON. Write swreg register. */
+                       int swreg = ath9k_hw_ar9300_get_eeprom(ah, EEP_SWREG);
+                       REG_WRITE(ah, AR_RTC_REG_CONTROL1,
+                                 REG_READ(ah, AR_RTC_REG_CONTROL1) &
+                                 (~AR_RTC_REG_CONTROL1_SWREG_PROGRAM));
+                       REG_WRITE(ah, AR_RTC_REG_CONTROL0, swreg);
+                       /* Set REG_CONTROL1.SWREG_PROGRAM */
+                       REG_WRITE(ah, AR_RTC_REG_CONTROL1,
+                                 REG_READ(ah,
+                                          AR_RTC_REG_CONTROL1) |
+                                          AR_RTC_REG_CONTROL1_SWREG_PROGRAM);
+               }
        } else {
-               REG_WRITE(ah, AR_RTC_SLEEP_CLK,
-                         (REG_READ(ah,
-                                   AR_RTC_SLEEP_CLK) |
-                                   AR_RTC_FORCE_SWREG_PRD));
+               if (AR_SREV_9485(ah)) {
+                       REG_RMW_FIELD(ah, AR_PHY_PMU2, AR_PHY_PMU2_PGM, 0);
+                       while (REG_READ_FIELD(ah, AR_PHY_PMU2,
+                                             AR_PHY_PMU2_PGM))
+                               udelay(10);
+
+                       REG_RMW_FIELD(ah, AR_PHY_PMU1, AR_PHY_PMU1_PWD, 0x1);
+                       while (!REG_READ_FIELD(ah, AR_PHY_PMU1,
+                                              AR_PHY_PMU1_PWD))
+                               udelay(10);
+                       REG_RMW_FIELD(ah, AR_PHY_PMU2, AR_PHY_PMU2_PGM, 0x1);
+                       while (!REG_READ_FIELD(ah, AR_PHY_PMU2,
+                                             AR_PHY_PMU2_PGM))
+                               udelay(10);
+               } else
+                       REG_WRITE(ah, AR_RTC_SLEEP_CLK,
+                                 (REG_READ(ah,
+                                  AR_RTC_SLEEP_CLK) |
+                                  AR_RTC_FORCE_SWREG_PRD));
        }
+
 }
 
 static void ath9k_hw_ar9300_set_board_values(struct ath_hw *ah,
index 6e0d4adc1a6bd7baeec2a8086970308ee0bbcd04..8de3ffd5a92b7cab361cab7d4efc11733036c077 100644 (file)
 #define AR_CH0_TOP2_XPABIASLVL         0xf000
 #define AR_CH0_TOP2_XPABIASLVL_S       12
 
+#define AR_PHY_PMU1            0x16c40
+#define AR_PHY_PMU1_PWD                0x1
+#define AR_PHY_PMU1_PWD_S      0
+
+#define AR_PHY_PMU2            0x16c44
+#define AR_PHY_PMU2_PGM                0x00200000
+#define AR_PHY_PMU2_PGM_S      21
+
 #define AR_PHY_RX1DB_BIQUAD_LONG_SHIFT         0x00380000
 #define AR_PHY_RX1DB_BIQUAD_LONG_SHIFT_S       19
 #define AR_PHY_RX6DB_BIQUAD_LONG_SHIFT         0x00c00000