diff options
author | Vivek Natarajan <vivek.natraj@gmail.com> | 2009-07-23 01:29:57 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-07-27 15:24:19 -0400 |
commit | ac88b6ecdfa629fd1261dab1504d78a56fd4cabf (patch) | |
tree | 8a0c683e25c223477315c6b4d55b53ece0787785 | |
parent | 3fa52056f3a8e755708241d5795e6d3e6f55ad85 (diff) |
ath9k: Add support for AR9287 based chipsets.
Signed-off-by: Vivek Natarajan <vnatarajan@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/ath/ath9k/calib.c | 22 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/eeprom.c | 1203 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/eeprom.h | 163 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/hw.c | 110 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/hw.h | 4 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/main.c | 3 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/pci.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/phy.h | 1 |
8 files changed, 1482 insertions, 26 deletions
diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index 1f0c5fe4a68b..d1bbb02af8de 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c | |||
@@ -116,7 +116,7 @@ static void ath9k_hw_do_getnf(struct ath_hw *ah, | |||
116 | "NF calibrated [ctl] [chain 1] is %d\n", nf); | 116 | "NF calibrated [ctl] [chain 1] is %d\n", nf); |
117 | nfarray[1] = nf; | 117 | nfarray[1] = nf; |
118 | 118 | ||
119 | if (!AR_SREV_9280(ah)) { | 119 | if (!AR_SREV_9280(ah) && !AR_SREV_9287(ah)) { |
120 | nf = MS(REG_READ(ah, AR_PHY_CH2_CCA), | 120 | nf = MS(REG_READ(ah, AR_PHY_CH2_CCA), |
121 | AR_PHY_CH2_MINCCA_PWR); | 121 | AR_PHY_CH2_MINCCA_PWR); |
122 | if (nf & 0x100) | 122 | if (nf & 0x100) |
@@ -154,7 +154,7 @@ static void ath9k_hw_do_getnf(struct ath_hw *ah, | |||
154 | "NF calibrated [ext] [chain 1] is %d\n", nf); | 154 | "NF calibrated [ext] [chain 1] is %d\n", nf); |
155 | nfarray[4] = nf; | 155 | nfarray[4] = nf; |
156 | 156 | ||
157 | if (!AR_SREV_9280(ah)) { | 157 | if (!AR_SREV_9280(ah) && !AR_SREV_9287(ah)) { |
158 | nf = MS(REG_READ(ah, AR_PHY_CH2_EXT_CCA), | 158 | nf = MS(REG_READ(ah, AR_PHY_CH2_EXT_CCA), |
159 | AR_PHY_CH2_EXT_MINCCA_PWR); | 159 | AR_PHY_CH2_EXT_MINCCA_PWR); |
160 | if (nf & 0x100) | 160 | if (nf & 0x100) |
@@ -613,7 +613,7 @@ void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) | |||
613 | 613 | ||
614 | if (AR_SREV_9285(ah)) | 614 | if (AR_SREV_9285(ah)) |
615 | chainmask = 0x9; | 615 | chainmask = 0x9; |
616 | else if (AR_SREV_9280(ah)) | 616 | else if (AR_SREV_9280(ah) || AR_SREV_9287(ah)) |
617 | chainmask = 0x1B; | 617 | chainmask = 0x1B; |
618 | else | 618 | else |
619 | chainmask = 0x3F; | 619 | chainmask = 0x3F; |
@@ -873,7 +873,7 @@ bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, | |||
873 | if (AR_SREV_9285_11_OR_LATER(ah)) | 873 | if (AR_SREV_9285_11_OR_LATER(ah)) |
874 | ath9k_hw_9285_pa_cal(ah); | 874 | ath9k_hw_9285_pa_cal(ah); |
875 | 875 | ||
876 | if (OLC_FOR_AR9280_20_LATER) | 876 | if (OLC_FOR_AR9280_20_LATER || OLC_FOR_AR9287_10_LATER) |
877 | ath9k_olc_temp_compensation(ah); | 877 | ath9k_olc_temp_compensation(ah); |
878 | ath9k_hw_getnf(ah, chan); | 878 | ath9k_hw_getnf(ah, chan); |
879 | ath9k_hw_loadnf(ah, ah->curchan); | 879 | ath9k_hw_loadnf(ah, ah->curchan); |
@@ -929,8 +929,11 @@ bool ath9k_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) | |||
929 | return false; | 929 | return false; |
930 | } else { | 930 | } else { |
931 | if (AR_SREV_9280_10_OR_LATER(ah)) { | 931 | if (AR_SREV_9280_10_OR_LATER(ah)) { |
932 | REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); | 932 | if (!AR_SREV_9287_10_OR_LATER(ah)) |
933 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); | 933 | REG_CLR_BIT(ah, AR_PHY_ADC_CTL, |
934 | AR_PHY_ADC_CTL_OFF_PWDADC); | ||
935 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, | ||
936 | AR_PHY_AGC_CONTROL_FLTR_CAL); | ||
934 | } | 937 | } |
935 | 938 | ||
936 | /* Calibrate the AGC */ | 939 | /* Calibrate the AGC */ |
@@ -948,8 +951,11 @@ bool ath9k_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) | |||
948 | } | 951 | } |
949 | 952 | ||
950 | if (AR_SREV_9280_10_OR_LATER(ah)) { | 953 | if (AR_SREV_9280_10_OR_LATER(ah)) { |
951 | REG_SET_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); | 954 | if (!AR_SREV_9287_10_OR_LATER(ah)) |
952 | REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); | 955 | REG_SET_BIT(ah, AR_PHY_ADC_CTL, |
956 | AR_PHY_ADC_CTL_OFF_PWDADC); | ||
957 | REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, | ||
958 | AR_PHY_AGC_CONTROL_FLTR_CAL); | ||
953 | } | 959 | } |
954 | } | 960 | } |
955 | 961 | ||
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.c b/drivers/net/wireless/ath/ath9k/eeprom.c index df41ed5fd7c4..9b1d960dc80f 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.c +++ b/drivers/net/wireless/ath/ath9k/eeprom.c | |||
@@ -2781,11 +2781,1210 @@ static struct eeprom_ops eep_def_ops = { | |||
2781 | .get_spur_channel = ath9k_hw_def_get_spur_channel | 2781 | .get_spur_channel = ath9k_hw_def_get_spur_channel |
2782 | }; | 2782 | }; |
2783 | 2783 | ||
2784 | |||
2785 | static int ath9k_hw_AR9287_get_eeprom_ver(struct ath_hw *ah) | ||
2786 | { | ||
2787 | return (ah->eeprom.map9287.baseEepHeader.version >> 12) & 0xF; | ||
2788 | } | ||
2789 | |||
2790 | static int ath9k_hw_AR9287_get_eeprom_rev(struct ath_hw *ah) | ||
2791 | { | ||
2792 | return (ah->eeprom.map9287.baseEepHeader.version) & 0xFFF; | ||
2793 | } | ||
2794 | |||
2795 | static bool ath9k_hw_AR9287_fill_eeprom(struct ath_hw *ah) | ||
2796 | { | ||
2797 | struct ar9287_eeprom_t *eep = &ah->eeprom.map9287; | ||
2798 | u16 *eep_data; | ||
2799 | int addr, eep_start_loc = AR9287_EEP_START_LOC; | ||
2800 | eep_data = (u16 *)eep; | ||
2801 | if (!ath9k_hw_use_flash(ah)) { | ||
2802 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
2803 | "Reading from EEPROM, not flash\n"); | ||
2804 | } | ||
2805 | |||
2806 | for (addr = 0; addr < sizeof(struct ar9287_eeprom_t) / sizeof(u16); | ||
2807 | addr++) { | ||
2808 | if (!ath9k_hw_nvram_read(ah, addr + eep_start_loc, eep_data)) { | ||
2809 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
2810 | "Unable to read eeprom region \n"); | ||
2811 | return false; | ||
2812 | } | ||
2813 | eep_data++; | ||
2814 | } | ||
2815 | return true; | ||
2816 | } | ||
2817 | static int ath9k_hw_AR9287_check_eeprom(struct ath_hw *ah) | ||
2818 | { | ||
2819 | #define SIZE_EEPROM_87 (sizeof(struct ar9287_eeprom_t) / sizeof(u16)) | ||
2820 | u32 sum = 0, el, integer; | ||
2821 | u16 temp, word, magic, magic2, *eepdata; | ||
2822 | int i, addr; | ||
2823 | bool need_swap = false; | ||
2824 | struct ar9287_eeprom_t *eep = &ah->eeprom.map9287; | ||
2825 | |||
2826 | if (!ath9k_hw_use_flash(ah)) { | ||
2827 | if (!ath9k_hw_nvram_read | ||
2828 | (ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) { | ||
2829 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | ||
2830 | "Reading Magic # failed\n"); | ||
2831 | return false; | ||
2832 | } | ||
2833 | |||
2834 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
2835 | "Read Magic = 0x%04X\n", magic); | ||
2836 | if (magic != AR5416_EEPROM_MAGIC) { | ||
2837 | |||
2838 | |||
2839 | magic2 = swab16(magic); | ||
2840 | |||
2841 | if (magic2 == AR5416_EEPROM_MAGIC) { | ||
2842 | need_swap = true; | ||
2843 | eepdata = (u16 *)(&ah->eeprom); | ||
2844 | |||
2845 | for (addr = 0; addr < SIZE_EEPROM_87; addr++) { | ||
2846 | temp = swab16(*eepdata); | ||
2847 | *eepdata = temp; | ||
2848 | eepdata++; | ||
2849 | } | ||
2850 | } else { | ||
2851 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | ||
2852 | "Invalid EEPROM Magic. " | ||
2853 | "endianness mismatch.\n"); | ||
2854 | return -EINVAL; } | ||
2855 | } | ||
2856 | } | ||
2857 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "need_swap = %s.\n", need_swap ? | ||
2858 | "True" : "False"); | ||
2859 | |||
2860 | if (need_swap) | ||
2861 | el = swab16(ah->eeprom.map9287.baseEepHeader.length); | ||
2862 | else | ||
2863 | el = ah->eeprom.map9287.baseEepHeader.length; | ||
2864 | |||
2865 | eepdata = (u16 *)(&ah->eeprom); | ||
2866 | for (i = 0; i < min(el, SIZE_EEPROM_87); i++) | ||
2867 | sum ^= *eepdata++; | ||
2868 | |||
2869 | if (need_swap) { | ||
2870 | word = swab16(eep->baseEepHeader.length); | ||
2871 | eep->baseEepHeader.length = word; | ||
2872 | |||
2873 | word = swab16(eep->baseEepHeader.checksum); | ||
2874 | eep->baseEepHeader.checksum = word; | ||
2875 | |||
2876 | word = swab16(eep->baseEepHeader.version); | ||
2877 | eep->baseEepHeader.version = word; | ||
2878 | |||
2879 | word = swab16(eep->baseEepHeader.regDmn[0]); | ||
2880 | eep->baseEepHeader.regDmn[0] = word; | ||
2881 | |||
2882 | word = swab16(eep->baseEepHeader.regDmn[1]); | ||
2883 | eep->baseEepHeader.regDmn[1] = word; | ||
2884 | |||
2885 | word = swab16(eep->baseEepHeader.rfSilent); | ||
2886 | eep->baseEepHeader.rfSilent = word; | ||
2887 | |||
2888 | word = swab16(eep->baseEepHeader.blueToothOptions); | ||
2889 | eep->baseEepHeader.blueToothOptions = word; | ||
2890 | |||
2891 | word = swab16(eep->baseEepHeader.deviceCap); | ||
2892 | eep->baseEepHeader.deviceCap = word; | ||
2893 | |||
2894 | integer = swab32(eep->modalHeader.antCtrlCommon); | ||
2895 | eep->modalHeader.antCtrlCommon = integer; | ||
2896 | |||
2897 | for (i = 0; i < AR9287_MAX_CHAINS; i++) { | ||
2898 | integer = swab32(eep->modalHeader.antCtrlChain[i]); | ||
2899 | eep->modalHeader.antCtrlChain[i] = integer; | ||
2900 | } | ||
2901 | |||
2902 | for (i = 0; i < AR9287_EEPROM_MODAL_SPURS; i++) { | ||
2903 | word = swab16(eep->modalHeader.spurChans[i].spurChan); | ||
2904 | eep->modalHeader.spurChans[i].spurChan = word; | ||
2905 | } | ||
2906 | } | ||
2907 | |||
2908 | if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR9287_EEP_VER | ||
2909 | || ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) { | ||
2910 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | ||
2911 | "Bad EEPROM checksum 0x%x or revision 0x%04x\n", | ||
2912 | sum, ah->eep_ops->get_eeprom_ver(ah)); | ||
2913 | return -EINVAL; | ||
2914 | } | ||
2915 | |||
2916 | return 0; | ||
2917 | #undef SIZE_EEPROM_87 | ||
2918 | } | ||
2919 | |||
2920 | static u32 ath9k_hw_AR9287_get_eeprom(struct ath_hw *ah, | ||
2921 | enum eeprom_param param) | ||
2922 | { | ||
2923 | struct ar9287_eeprom_t *eep = &ah->eeprom.map9287; | ||
2924 | struct modal_eep_ar9287_header *pModal = &eep->modalHeader; | ||
2925 | struct base_eep_ar9287_header *pBase = &eep->baseEepHeader; | ||
2926 | u16 ver_minor; | ||
2927 | |||
2928 | ver_minor = pBase->version & AR9287_EEP_VER_MINOR_MASK; | ||
2929 | switch (param) { | ||
2930 | case EEP_NFTHRESH_2: | ||
2931 | return pModal->noiseFloorThreshCh[0]; | ||
2932 | case AR_EEPROM_MAC(0): | ||
2933 | return pBase->macAddr[0] << 8 | pBase->macAddr[1]; | ||
2934 | case AR_EEPROM_MAC(1): | ||
2935 | return pBase->macAddr[2] << 8 | pBase->macAddr[3]; | ||
2936 | case AR_EEPROM_MAC(2): | ||
2937 | return pBase->macAddr[4] << 8 | pBase->macAddr[5]; | ||
2938 | case EEP_REG_0: | ||
2939 | return pBase->regDmn[0]; | ||
2940 | case EEP_REG_1: | ||
2941 | return pBase->regDmn[1]; | ||
2942 | case EEP_OP_CAP: | ||
2943 | return pBase->deviceCap; | ||
2944 | case EEP_OP_MODE: | ||
2945 | return pBase->opCapFlags; | ||
2946 | case EEP_RF_SILENT: | ||
2947 | return pBase->rfSilent; | ||
2948 | case EEP_MINOR_REV: | ||
2949 | return ver_minor; | ||
2950 | case EEP_TX_MASK: | ||
2951 | return pBase->txMask; | ||
2952 | case EEP_RX_MASK: | ||
2953 | return pBase->rxMask; | ||
2954 | case EEP_DEV_TYPE: | ||
2955 | return pBase->deviceType; | ||
2956 | case EEP_OL_PWRCTRL: | ||
2957 | return pBase->openLoopPwrCntl; | ||
2958 | case EEP_TEMPSENSE_SLOPE: | ||
2959 | if (ver_minor >= AR9287_EEP_MINOR_VER_2) | ||
2960 | return pBase->tempSensSlope; | ||
2961 | else | ||
2962 | return 0; | ||
2963 | case EEP_TEMPSENSE_SLOPE_PAL_ON: | ||
2964 | if (ver_minor >= AR9287_EEP_MINOR_VER_3) | ||
2965 | return pBase->tempSensSlopePalOn; | ||
2966 | else | ||
2967 | return 0; | ||
2968 | default: | ||
2969 | return 0; | ||
2970 | } | ||
2971 | } | ||
2972 | |||
2973 | |||
2974 | static void ath9k_hw_get_AR9287_gain_boundaries_pdadcs(struct ath_hw *ah, | ||
2975 | struct ath9k_channel *chan, | ||
2976 | struct cal_data_per_freq_ar9287 *pRawDataSet, | ||
2977 | u8 *bChans, u16 availPiers, | ||
2978 | u16 tPdGainOverlap, int16_t *pMinCalPower, | ||
2979 | u16 *pPdGainBoundaries, u8 *pPDADCValues, | ||
2980 | u16 numXpdGains) | ||
2981 | { | ||
2982 | #define TMP_VAL_VPD_TABLE \ | ||
2983 | ((vpdTableI[i][sizeCurrVpdTable - 1] + (ss - maxIndex + 1) * vpdStep)); | ||
2984 | int i, j, k; | ||
2985 | int16_t ss; | ||
2986 | u16 idxL = 0, idxR = 0, numPiers; | ||
2987 | u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR; | ||
2988 | u8 minPwrT4[AR9287_NUM_PD_GAINS]; | ||
2989 | u8 maxPwrT4[AR9287_NUM_PD_GAINS]; | ||
2990 | int16_t vpdStep; | ||
2991 | int16_t tmpVal; | ||
2992 | u16 sizeCurrVpdTable, maxIndex, tgtIndex; | ||
2993 | bool match; | ||
2994 | int16_t minDelta = 0; | ||
2995 | struct chan_centers centers; | ||
2996 | static u8 vpdTableL[AR5416_EEP4K_NUM_PD_GAINS] | ||
2997 | [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; | ||
2998 | static u8 vpdTableR[AR5416_EEP4K_NUM_PD_GAINS] | ||
2999 | [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; | ||
3000 | static u8 vpdTableI[AR5416_EEP4K_NUM_PD_GAINS] | ||
3001 | [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; | ||
3002 | |||
3003 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); | ||
3004 | for (numPiers = 0; numPiers < availPiers; numPiers++) { | ||
3005 | if (bChans[numPiers] == AR9287_BCHAN_UNUSED) | ||
3006 | break; | ||
3007 | } | ||
3008 | |||
3009 | match = ath9k_hw_get_lower_upper_index( | ||
3010 | (u8)FREQ2FBIN(centers.synth_center, | ||
3011 | IS_CHAN_2GHZ(chan)), bChans, numPiers, | ||
3012 | &idxL, &idxR); | ||
3013 | |||
3014 | if (match) { | ||
3015 | for (i = 0; i < numXpdGains; i++) { | ||
3016 | minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0]; | ||
3017 | maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4]; | ||
3018 | ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], | ||
3019 | pRawDataSet[idxL].pwrPdg[i], | ||
3020 | pRawDataSet[idxL].vpdPdg[i], | ||
3021 | AR9287_PD_GAIN_ICEPTS, vpdTableI[i]); | ||
3022 | } | ||
3023 | } else { | ||
3024 | for (i = 0; i < numXpdGains; i++) { | ||
3025 | pVpdL = pRawDataSet[idxL].vpdPdg[i]; | ||
3026 | pPwrL = pRawDataSet[idxL].pwrPdg[i]; | ||
3027 | pVpdR = pRawDataSet[idxR].vpdPdg[i]; | ||
3028 | pPwrR = pRawDataSet[idxR].pwrPdg[i]; | ||
3029 | |||
3030 | minPwrT4[i] = max(pPwrL[0], pPwrR[0]); | ||
3031 | |||
3032 | maxPwrT4[i] = | ||
3033 | min(pPwrL[AR9287_PD_GAIN_ICEPTS - 1], | ||
3034 | pPwrR[AR9287_PD_GAIN_ICEPTS - 1]); | ||
3035 | |||
3036 | ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], | ||
3037 | pPwrL, pVpdL, | ||
3038 | AR9287_PD_GAIN_ICEPTS, | ||
3039 | vpdTableL[i]); | ||
3040 | ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], | ||
3041 | pPwrR, pVpdR, | ||
3042 | AR9287_PD_GAIN_ICEPTS, | ||
3043 | vpdTableR[i]); | ||
3044 | |||
3045 | for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) { | ||
3046 | vpdTableI[i][j] = | ||
3047 | (u8)(ath9k_hw_interpolate((u16) | ||
3048 | FREQ2FBIN(centers. synth_center, | ||
3049 | IS_CHAN_2GHZ(chan)), | ||
3050 | bChans[idxL], bChans[idxR], | ||
3051 | vpdTableL[i][j], vpdTableR[i][j])); | ||
3052 | } | ||
3053 | } | ||
3054 | } | ||
3055 | *pMinCalPower = (int16_t)(minPwrT4[0] / 2); | ||
3056 | |||
3057 | k = 0; | ||
3058 | for (i = 0; i < numXpdGains; i++) { | ||
3059 | if (i == (numXpdGains - 1)) | ||
3060 | pPdGainBoundaries[i] = (u16)(maxPwrT4[i] / 2); | ||
3061 | else | ||
3062 | pPdGainBoundaries[i] = (u16)((maxPwrT4[i] + | ||
3063 | minPwrT4[i+1]) / 4); | ||
3064 | |||
3065 | pPdGainBoundaries[i] = min((u16)AR5416_MAX_RATE_POWER, | ||
3066 | pPdGainBoundaries[i]); | ||
3067 | |||
3068 | |||
3069 | if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) { | ||
3070 | minDelta = pPdGainBoundaries[0] - 23; | ||
3071 | pPdGainBoundaries[0] = 23; | ||
3072 | } else | ||
3073 | minDelta = 0; | ||
3074 | |||
3075 | if (i == 0) { | ||
3076 | if (AR_SREV_9280_10_OR_LATER(ah)) | ||
3077 | ss = (int16_t)(0 - (minPwrT4[i] / 2)); | ||
3078 | else | ||
3079 | ss = 0; | ||
3080 | } else | ||
3081 | ss = (int16_t)((pPdGainBoundaries[i-1] - | ||
3082 | (minPwrT4[i] / 2)) - | ||
3083 | tPdGainOverlap + 1 + minDelta); | ||
3084 | |||
3085 | vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]); | ||
3086 | vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep); | ||
3087 | while ((ss < 0) && (k < (AR9287_NUM_PDADC_VALUES - 1))) { | ||
3088 | tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep); | ||
3089 | pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal); | ||
3090 | ss++; | ||
3091 | } | ||
3092 | |||
3093 | sizeCurrVpdTable = (u8)((maxPwrT4[i] - minPwrT4[i]) / 2 + 1); | ||
3094 | tgtIndex = (u8)(pPdGainBoundaries[i] + | ||
3095 | tPdGainOverlap - (minPwrT4[i] / 2)); | ||
3096 | maxIndex = (tgtIndex < sizeCurrVpdTable) ? | ||
3097 | tgtIndex : sizeCurrVpdTable; | ||
3098 | |||
3099 | while ((ss < maxIndex) && (k < (AR9287_NUM_PDADC_VALUES - 1))) | ||
3100 | pPDADCValues[k++] = vpdTableI[i][ss++]; | ||
3101 | |||
3102 | vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] - | ||
3103 | vpdTableI[i][sizeCurrVpdTable - 2]); | ||
3104 | vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep); | ||
3105 | if (tgtIndex > maxIndex) { | ||
3106 | while ((ss <= tgtIndex) && | ||
3107 | (k < (AR9287_NUM_PDADC_VALUES - 1))) { | ||
3108 | tmpVal = (int16_t) TMP_VAL_VPD_TABLE; | ||
3109 | pPDADCValues[k++] = (u8)((tmpVal > 255) ? | ||
3110 | 255 : tmpVal); | ||
3111 | ss++; | ||
3112 | } | ||
3113 | } | ||
3114 | } | ||
3115 | |||
3116 | while (i < AR9287_PD_GAINS_IN_MASK) { | ||
3117 | pPdGainBoundaries[i] = pPdGainBoundaries[i-1]; | ||
3118 | i++; | ||
3119 | } | ||
3120 | |||
3121 | while (k < AR9287_NUM_PDADC_VALUES) { | ||
3122 | pPDADCValues[k] = pPDADCValues[k-1]; | ||
3123 | k++; | ||
3124 | } | ||
3125 | |||
3126 | #undef TMP_VAL_VPD_TABLE | ||
3127 | } | ||
3128 | |||
3129 | static void ar9287_eeprom_get_tx_gain_index(struct ath_hw *ah, | ||
3130 | struct ath9k_channel *chan, | ||
3131 | struct cal_data_op_loop_ar9287 *pRawDatasetOpLoop, | ||
3132 | u8 *pCalChans, u16 availPiers, | ||
3133 | int8_t *pPwr) | ||
3134 | { | ||
3135 | u8 pcdac, i = 0; | ||
3136 | u16 idxL = 0, idxR = 0, numPiers; | ||
3137 | bool match; | ||
3138 | struct chan_centers centers; | ||
3139 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); | ||
3140 | for (numPiers = 0; numPiers < availPiers; numPiers++) { | ||
3141 | if (pCalChans[numPiers] == AR9287_BCHAN_UNUSED) | ||
3142 | break; | ||
3143 | } | ||
3144 | |||
3145 | match = ath9k_hw_get_lower_upper_index( | ||
3146 | (u8)FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan)), | ||
3147 | pCalChans, numPiers, | ||
3148 | &idxL, &idxR); | ||
3149 | |||
3150 | if (match) { | ||
3151 | pcdac = pRawDatasetOpLoop[idxL].pcdac[0][0]; | ||
3152 | *pPwr = pRawDatasetOpLoop[idxL].pwrPdg[0][0]; | ||
3153 | } else { | ||
3154 | pcdac = pRawDatasetOpLoop[idxR].pcdac[0][0]; | ||
3155 | *pPwr = (pRawDatasetOpLoop[idxL].pwrPdg[0][0] + | ||
3156 | pRawDatasetOpLoop[idxR].pwrPdg[0][0])/2; | ||
3157 | } | ||
3158 | |||
3159 | while ((pcdac > ah->originalGain[i]) && | ||
3160 | (i < (AR9280_TX_GAIN_TABLE_SIZE - 1))) | ||
3161 | i++; | ||
3162 | } | ||
3163 | |||
3164 | static void ar9287_eeprom_olpc_set_pdadcs(struct ath_hw *ah, | ||
3165 | int32_t txPower, u16 chain) | ||
3166 | { | ||
3167 | u32 tmpVal; | ||
3168 | u32 a; | ||
3169 | |||
3170 | tmpVal = REG_READ(ah, 0xa270); | ||
3171 | tmpVal = tmpVal & 0xFCFFFFFF; | ||
3172 | tmpVal = tmpVal | (0x3 << 24); | ||
3173 | REG_WRITE(ah, 0xa270, tmpVal); | ||
3174 | |||
3175 | tmpVal = REG_READ(ah, 0xb270); | ||
3176 | tmpVal = tmpVal & 0xFCFFFFFF; | ||
3177 | tmpVal = tmpVal | (0x3 << 24); | ||
3178 | REG_WRITE(ah, 0xb270, tmpVal); | ||
3179 | |||
3180 | if (chain == 0) { | ||
3181 | tmpVal = REG_READ(ah, 0xa398); | ||
3182 | tmpVal = tmpVal & 0xff00ffff; | ||
3183 | a = (txPower)&0xff; | ||
3184 | tmpVal = tmpVal | (a << 16); | ||
3185 | REG_WRITE(ah, 0xa398, tmpVal); | ||
3186 | } | ||
3187 | |||
3188 | if (chain == 1) { | ||
3189 | tmpVal = REG_READ(ah, 0xb398); | ||
3190 | tmpVal = tmpVal & 0xff00ffff; | ||
3191 | a = (txPower)&0xff; | ||
3192 | tmpVal = tmpVal | (a << 16); | ||
3193 | REG_WRITE(ah, 0xb398, tmpVal); | ||
3194 | } | ||
3195 | } | ||
3196 | |||
3197 | |||
3198 | static void ath9k_hw_set_AR9287_power_cal_table(struct ath_hw *ah, | ||
3199 | struct ath9k_channel *chan, int16_t *pTxPowerIndexOffset) | ||
3200 | { | ||
3201 | struct cal_data_per_freq_ar9287 *pRawDataset; | ||
3202 | struct cal_data_op_loop_ar9287 *pRawDatasetOpenLoop; | ||
3203 | u8 *pCalBChans = NULL; | ||
3204 | u16 pdGainOverlap_t2; | ||
3205 | u8 pdadcValues[AR9287_NUM_PDADC_VALUES]; | ||
3206 | u16 gainBoundaries[AR9287_PD_GAINS_IN_MASK]; | ||
3207 | u16 numPiers = 0, i, j; | ||
3208 | int16_t tMinCalPower; | ||
3209 | u16 numXpdGain, xpdMask; | ||
3210 | u16 xpdGainValues[AR9287_NUM_PD_GAINS] = {0, 0, 0, 0}; | ||
3211 | u32 reg32, regOffset, regChainOffset; | ||
3212 | int16_t modalIdx, diff = 0; | ||
3213 | struct ar9287_eeprom_t *pEepData = &ah->eeprom.map9287; | ||
3214 | modalIdx = IS_CHAN_2GHZ(chan) ? 1 : 0; | ||
3215 | xpdMask = pEepData->modalHeader.xpdGain; | ||
3216 | if ((pEepData->baseEepHeader.version & AR9287_EEP_VER_MINOR_MASK) >= | ||
3217 | AR9287_EEP_MINOR_VER_2) | ||
3218 | pdGainOverlap_t2 = pEepData->modalHeader.pdGainOverlap; | ||
3219 | else | ||
3220 | pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5), | ||
3221 | AR_PHY_TPCRG5_PD_GAIN_OVERLAP)); | ||
3222 | |||
3223 | if (IS_CHAN_2GHZ(chan)) { | ||
3224 | pCalBChans = pEepData->calFreqPier2G; | ||
3225 | numPiers = AR9287_NUM_2G_CAL_PIERS; | ||
3226 | if (ath9k_hw_AR9287_get_eeprom(ah, EEP_OL_PWRCTRL)) { | ||
3227 | pRawDatasetOpenLoop = | ||
3228 | (struct cal_data_op_loop_ar9287 *) | ||
3229 | pEepData->calPierData2G[0]; | ||
3230 | ah->initPDADC = pRawDatasetOpenLoop->vpdPdg[0][0]; | ||
3231 | } | ||
3232 | } | ||
3233 | |||
3234 | numXpdGain = 0; | ||
3235 | for (i = 1; i <= AR9287_PD_GAINS_IN_MASK; i++) { | ||
3236 | if ((xpdMask >> (AR9287_PD_GAINS_IN_MASK - i)) & 1) { | ||
3237 | if (numXpdGain >= AR9287_NUM_PD_GAINS) | ||
3238 | break; | ||
3239 | xpdGainValues[numXpdGain] = | ||
3240 | (u16)(AR9287_PD_GAINS_IN_MASK-i); | ||
3241 | numXpdGain++; | ||
3242 | } | ||
3243 | } | ||
3244 | |||
3245 | REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN, | ||
3246 | (numXpdGain - 1) & 0x3); | ||
3247 | REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1, | ||
3248 | xpdGainValues[0]); | ||
3249 | REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2, | ||
3250 | xpdGainValues[1]); | ||
3251 | REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3, | ||
3252 | xpdGainValues[2]); | ||
3253 | |||
3254 | for (i = 0; i < AR9287_MAX_CHAINS; i++) { | ||
3255 | regChainOffset = i * 0x1000; | ||
3256 | if (pEepData->baseEepHeader.txMask & (1 << i)) { | ||
3257 | pRawDatasetOpenLoop = (struct cal_data_op_loop_ar9287 *) | ||
3258 | pEepData->calPierData2G[i]; | ||
3259 | if (ath9k_hw_AR9287_get_eeprom(ah, EEP_OL_PWRCTRL)) { | ||
3260 | int8_t txPower; | ||
3261 | ar9287_eeprom_get_tx_gain_index(ah, chan, | ||
3262 | pRawDatasetOpenLoop, | ||
3263 | pCalBChans, numPiers, | ||
3264 | &txPower); | ||
3265 | ar9287_eeprom_olpc_set_pdadcs(ah, txPower, i); | ||
3266 | } else { | ||
3267 | pRawDataset = | ||
3268 | (struct cal_data_per_freq_ar9287 *) | ||
3269 | pEepData->calPierData2G[i]; | ||
3270 | ath9k_hw_get_AR9287_gain_boundaries_pdadcs( | ||
3271 | ah, chan, pRawDataset, | ||
3272 | pCalBChans, numPiers, | ||
3273 | pdGainOverlap_t2, | ||
3274 | &tMinCalPower, gainBoundaries, | ||
3275 | pdadcValues, numXpdGain); | ||
3276 | } | ||
3277 | |||
3278 | if (i == 0) { | ||
3279 | if (!ath9k_hw_AR9287_get_eeprom( | ||
3280 | ah, EEP_OL_PWRCTRL)) { | ||
3281 | REG_WRITE(ah, AR_PHY_TPCRG5 + | ||
3282 | regChainOffset, | ||
3283 | SM(pdGainOverlap_t2, | ||
3284 | AR_PHY_TPCRG5_PD_GAIN_OVERLAP) | | ||
3285 | SM(gainBoundaries[0], | ||
3286 | AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1) | ||
3287 | | SM(gainBoundaries[1], | ||
3288 | AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2) | ||
3289 | | SM(gainBoundaries[2], | ||
3290 | AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3) | ||
3291 | | SM(gainBoundaries[3], | ||
3292 | AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4)); | ||
3293 | } | ||
3294 | } | ||
3295 | |||
3296 | if ((int32_t)AR9287_PWR_TABLE_OFFSET_DB != | ||
3297 | pEepData->baseEepHeader.pwrTableOffset) { | ||
3298 | diff = (u16) | ||
3299 | (pEepData->baseEepHeader.pwrTableOffset | ||
3300 | - (int32_t)AR9287_PWR_TABLE_OFFSET_DB); | ||
3301 | diff *= 2; | ||
3302 | |||
3303 | for (j = 0; | ||
3304 | j < ((u16)AR9287_NUM_PDADC_VALUES-diff); | ||
3305 | j++) | ||
3306 | pdadcValues[j] = pdadcValues[j+diff]; | ||
3307 | |||
3308 | for (j = (u16)(AR9287_NUM_PDADC_VALUES-diff); | ||
3309 | j < AR9287_NUM_PDADC_VALUES; j++) | ||
3310 | pdadcValues[j] = | ||
3311 | pdadcValues[ | ||
3312 | AR9287_NUM_PDADC_VALUES-diff]; | ||
3313 | } | ||
3314 | if (!ath9k_hw_AR9287_get_eeprom(ah, EEP_OL_PWRCTRL)) { | ||
3315 | regOffset = AR_PHY_BASE + (672 << 2) + | ||
3316 | regChainOffset; | ||
3317 | for (j = 0; j < 32; j++) { | ||
3318 | reg32 = ((pdadcValues[4*j + 0] | ||
3319 | & 0xFF) << 0) | | ||
3320 | ((pdadcValues[4*j + 1] | ||
3321 | & 0xFF) << 8) | | ||
3322 | ((pdadcValues[4*j + 2] | ||
3323 | & 0xFF) << 16) | | ||
3324 | ((pdadcValues[4*j + 3] | ||
3325 | & 0xFF) << 24) ; | ||
3326 | REG_WRITE(ah, regOffset, reg32); | ||
3327 | |||
3328 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
3329 | "PDADC (%d,%4x): %4.4x %8.8x\n", | ||
3330 | i, regChainOffset, regOffset, | ||
3331 | reg32); | ||
3332 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
3333 | "PDADC: Chain %d | " | ||
3334 | "PDADC %3d Value %3d | " | ||
3335 | "PDADC %3d Value %3d | " | ||
3336 | "PDADC %3d Value %3d | " | ||
3337 | "PDADC %3d Value %3d |\n", | ||
3338 | i, 4 * j, pdadcValues[4 * j], | ||
3339 | 4 * j + 1, | ||
3340 | pdadcValues[4 * j + 1], | ||
3341 | 4 * j + 2, | ||
3342 | pdadcValues[4 * j + 2], | ||
3343 | 4 * j + 3, | ||
3344 | pdadcValues[4 * j + 3]); | ||
3345 | |||
3346 | regOffset += 4; | ||
3347 | } | ||
3348 | } | ||
3349 | } | ||
3350 | } | ||
3351 | |||
3352 | *pTxPowerIndexOffset = 0; | ||
3353 | } | ||
3354 | |||
3355 | |||
3356 | static void ath9k_hw_set_AR9287_power_per_rate_table(struct ath_hw *ah, | ||
3357 | struct ath9k_channel *chan, int16_t *ratesArray, u16 cfgCtl, | ||
3358 | u16 AntennaReduction, u16 twiceMaxRegulatoryPower, | ||
3359 | u16 powerLimit) | ||
3360 | { | ||
3361 | #define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 | ||
3362 | #define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10 | ||
3363 | |||
3364 | u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER; | ||
3365 | static const u16 tpScaleReductionTable[5] = { 0, 3, 6, 9, | ||
3366 | AR5416_MAX_RATE_POWER }; | ||
3367 | int i; | ||
3368 | int16_t twiceLargestAntenna; | ||
3369 | struct cal_ctl_data_ar9287 *rep; | ||
3370 | struct cal_target_power_leg targetPowerOfdm = {0, {0, 0, 0, 0} }, | ||
3371 | targetPowerCck = {0, {0, 0, 0, 0} }; | ||
3372 | struct cal_target_power_leg targetPowerOfdmExt = {0, {0, 0, 0, 0} }, | ||
3373 | targetPowerCckExt = {0, {0, 0, 0, 0} }; | ||
3374 | struct cal_target_power_ht targetPowerHt20, | ||
3375 | targetPowerHt40 = {0, {0, 0, 0, 0} }; | ||
3376 | u16 scaledPower = 0, minCtlPower, maxRegAllowedPower; | ||
3377 | u16 ctlModesFor11g[] = {CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, | ||
3378 | CTL_11G_EXT, CTL_2GHT40}; | ||
3379 | u16 numCtlModes = 0, *pCtlMode = NULL, ctlMode, freq; | ||
3380 | struct chan_centers centers; | ||
3381 | int tx_chainmask; | ||
3382 | u16 twiceMinEdgePower; | ||
3383 | struct ar9287_eeprom_t *pEepData = &ah->eeprom.map9287; | ||
3384 | tx_chainmask = ah->txchainmask; | ||
3385 | |||
3386 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); | ||
3387 | |||
3388 | twiceLargestAntenna = max(pEepData->modalHeader.antennaGainCh[0], | ||
3389 | pEepData->modalHeader.antennaGainCh[1]); | ||
3390 | |||
3391 | twiceLargestAntenna = (int16_t)min((AntennaReduction) - | ||
3392 | twiceLargestAntenna, 0); | ||
3393 | |||
3394 | maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna; | ||
3395 | if (ah->regulatory.tp_scale != ATH9K_TP_SCALE_MAX) | ||
3396 | maxRegAllowedPower -= | ||
3397 | (tpScaleReductionTable[(ah->regulatory.tp_scale)] * 2); | ||
3398 | |||
3399 | scaledPower = min(powerLimit, maxRegAllowedPower); | ||
3400 | |||
3401 | switch (ar5416_get_ntxchains(tx_chainmask)) { | ||
3402 | case 1: | ||
3403 | break; | ||
3404 | case 2: | ||
3405 | scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN; | ||
3406 | break; | ||
3407 | case 3: | ||
3408 | scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN; | ||
3409 | break; | ||
3410 | } | ||
3411 | scaledPower = max((u16)0, scaledPower); | ||
3412 | |||
3413 | if (IS_CHAN_2GHZ(chan)) { | ||
3414 | numCtlModes = ARRAY_SIZE(ctlModesFor11g) - | ||
3415 | SUB_NUM_CTL_MODES_AT_2G_40; | ||
3416 | pCtlMode = ctlModesFor11g; | ||
3417 | |||
3418 | ath9k_hw_get_legacy_target_powers(ah, chan, | ||
3419 | pEepData->calTargetPowerCck, | ||
3420 | AR9287_NUM_2G_CCK_TARGET_POWERS, | ||
3421 | &targetPowerCck, 4, false); | ||
3422 | ath9k_hw_get_legacy_target_powers(ah, chan, | ||
3423 | pEepData->calTargetPower2G, | ||
3424 | AR9287_NUM_2G_20_TARGET_POWERS, | ||
3425 | &targetPowerOfdm, 4, false); | ||
3426 | ath9k_hw_get_target_powers(ah, chan, | ||
3427 | pEepData->calTargetPower2GHT20, | ||
3428 | AR9287_NUM_2G_20_TARGET_POWERS, | ||
3429 | &targetPowerHt20, 8, false); | ||
3430 | |||
3431 | if (IS_CHAN_HT40(chan)) { | ||
3432 | numCtlModes = ARRAY_SIZE(ctlModesFor11g); | ||
3433 | ath9k_hw_get_target_powers(ah, chan, | ||
3434 | pEepData->calTargetPower2GHT40, | ||
3435 | AR9287_NUM_2G_40_TARGET_POWERS, | ||
3436 | &targetPowerHt40, 8, true); | ||
3437 | ath9k_hw_get_legacy_target_powers(ah, chan, | ||
3438 | pEepData->calTargetPowerCck, | ||
3439 | AR9287_NUM_2G_CCK_TARGET_POWERS, | ||
3440 | &targetPowerCckExt, 4, true); | ||
3441 | ath9k_hw_get_legacy_target_powers(ah, chan, | ||
3442 | pEepData->calTargetPower2G, | ||
3443 | AR9287_NUM_2G_20_TARGET_POWERS, | ||
3444 | &targetPowerOfdmExt, 4, true); | ||
3445 | } | ||
3446 | } | ||
3447 | |||
3448 | for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) { | ||
3449 | |||
3450 | bool isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) || | ||
3451 | (pCtlMode[ctlMode] == CTL_2GHT40); | ||
3452 | if (isHt40CtlMode) | ||
3453 | freq = centers.synth_center; | ||
3454 | else if (pCtlMode[ctlMode] & EXT_ADDITIVE) | ||
3455 | freq = centers.ext_center; | ||
3456 | else | ||
3457 | freq = centers.ctl_center; | ||
3458 | |||
3459 | |||
3460 | if (ah->eep_ops->get_eeprom_ver(ah) == 14 && | ||
3461 | ah->eep_ops->get_eeprom_rev(ah) <= 2) | ||
3462 | twiceMaxEdgePower = AR5416_MAX_RATE_POWER; | ||
3463 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
3464 | "LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d," | ||
3465 | "EXT_ADDITIVE %d\n", ctlMode, numCtlModes, | ||
3466 | isHt40CtlMode, (pCtlMode[ctlMode] & EXT_ADDITIVE)); | ||
3467 | for (i = 0; (i < AR9287_NUM_CTLS) | ||
3468 | && pEepData->ctlIndex[i]; i++) { | ||
3469 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
3470 | "LOOP-Ctlidx %d: cfgCtl 0x%2.2x" | ||
3471 | "pCtlMode 0x%2.2x ctlIndex 0x%2.2x" | ||
3472 | "chan %d chanctl=xxxx\n", | ||
3473 | i, cfgCtl, pCtlMode[ctlMode], | ||
3474 | pEepData->ctlIndex[i], chan->channel); | ||
3475 | |||
3476 | if ((((cfgCtl & ~CTL_MODE_M) | | ||
3477 | (pCtlMode[ctlMode] & CTL_MODE_M)) == | ||
3478 | pEepData->ctlIndex[i]) || | ||
3479 | (((cfgCtl & ~CTL_MODE_M) | | ||
3480 | (pCtlMode[ctlMode] & CTL_MODE_M)) == | ||
3481 | ((pEepData->ctlIndex[i] & | ||
3482 | CTL_MODE_M) | SD_NO_CTL))) { | ||
3483 | |||
3484 | rep = &(pEepData->ctlData[i]); | ||
3485 | twiceMinEdgePower = ath9k_hw_get_max_edge_power( | ||
3486 | freq, | ||
3487 | rep->ctlEdges[ar5416_get_ntxchains( | ||
3488 | tx_chainmask) - 1], | ||
3489 | IS_CHAN_2GHZ(chan), AR5416_NUM_BAND_EDGES); | ||
3490 | |||
3491 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
3492 | "MATCH-EE_IDX %d: ch %d is2 %d" | ||
3493 | "2xMinEdge %d chainmask %d chains %d\n", | ||
3494 | i, freq, IS_CHAN_2GHZ(chan), | ||
3495 | twiceMinEdgePower, tx_chainmask, | ||
3496 | ar5416_get_ntxchains(tx_chainmask)); | ||
3497 | |||
3498 | if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) | ||
3499 | twiceMaxEdgePower = min( | ||
3500 | twiceMaxEdgePower, | ||
3501 | twiceMinEdgePower); | ||
3502 | else { | ||
3503 | twiceMaxEdgePower = twiceMinEdgePower; | ||
3504 | break; | ||
3505 | } | ||
3506 | } | ||
3507 | } | ||
3508 | |||
3509 | minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower); | ||
3510 | |||
3511 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
3512 | "SEL-Min ctlMode %d pCtlMode %d 2xMaxEdge %d" | ||
3513 | "sP %d minCtlPwr %d\n", | ||
3514 | ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower, | ||
3515 | scaledPower, minCtlPower); | ||
3516 | |||
3517 | |||
3518 | switch (pCtlMode[ctlMode]) { | ||
3519 | |||
3520 | case CTL_11B: | ||
3521 | for (i = 0; | ||
3522 | i < ARRAY_SIZE(targetPowerCck.tPow2x); | ||
3523 | i++) { | ||
3524 | targetPowerCck.tPow2x[i] = (u8)min( | ||
3525 | (u16)targetPowerCck.tPow2x[i], | ||
3526 | minCtlPower); | ||
3527 | } | ||
3528 | break; | ||
3529 | case CTL_11A: | ||
3530 | case CTL_11G: | ||
3531 | for (i = 0; | ||
3532 | i < ARRAY_SIZE(targetPowerOfdm.tPow2x); | ||
3533 | i++) { | ||
3534 | targetPowerOfdm.tPow2x[i] = (u8)min( | ||
3535 | (u16)targetPowerOfdm.tPow2x[i], | ||
3536 | minCtlPower); | ||
3537 | } | ||
3538 | break; | ||
3539 | case CTL_5GHT20: | ||
3540 | case CTL_2GHT20: | ||
3541 | for (i = 0; | ||
3542 | i < ARRAY_SIZE(targetPowerHt20.tPow2x); | ||
3543 | i++) { | ||
3544 | targetPowerHt20.tPow2x[i] = (u8)min( | ||
3545 | (u16)targetPowerHt20.tPow2x[i], | ||
3546 | minCtlPower); | ||
3547 | } | ||
3548 | break; | ||
3549 | case CTL_11B_EXT: | ||
3550 | targetPowerCckExt.tPow2x[0] = (u8)min( | ||
3551 | (u16)targetPowerCckExt.tPow2x[0], | ||
3552 | minCtlPower); | ||
3553 | break; | ||
3554 | case CTL_11A_EXT: | ||
3555 | case CTL_11G_EXT: | ||
3556 | targetPowerOfdmExt.tPow2x[0] = (u8)min( | ||
3557 | (u16)targetPowerOfdmExt.tPow2x[0], | ||
3558 | minCtlPower); | ||
3559 | break; | ||
3560 | case CTL_5GHT40: | ||
3561 | case CTL_2GHT40: | ||
3562 | for (i = 0; | ||
3563 | i < ARRAY_SIZE(targetPowerHt40.tPow2x); | ||
3564 | i++) { | ||
3565 | targetPowerHt40.tPow2x[i] = (u8)min( | ||
3566 | (u16)targetPowerHt40.tPow2x[i], | ||
3567 | minCtlPower); | ||
3568 | } | ||
3569 | break; | ||
3570 | default: | ||
3571 | break; | ||
3572 | } | ||
3573 | } | ||
3574 | |||
3575 | ratesArray[rate6mb] = ratesArray[rate9mb] = ratesArray[rate12mb] = | ||
3576 | ratesArray[rate18mb] = ratesArray[rate24mb] = | ||
3577 | targetPowerOfdm.tPow2x[0]; | ||
3578 | ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1]; | ||
3579 | ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2]; | ||
3580 | ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3]; | ||
3581 | ratesArray[rateXr] = targetPowerOfdm.tPow2x[0]; | ||
3582 | |||
3583 | for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++) | ||
3584 | ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i]; | ||
3585 | |||
3586 | if (IS_CHAN_2GHZ(chan)) { | ||
3587 | ratesArray[rate1l] = targetPowerCck.tPow2x[0]; | ||
3588 | ratesArray[rate2s] = ratesArray[rate2l] = | ||
3589 | targetPowerCck.tPow2x[1]; | ||
3590 | ratesArray[rate5_5s] = ratesArray[rate5_5l] = | ||
3591 | targetPowerCck.tPow2x[2]; | ||
3592 | ratesArray[rate11s] = ratesArray[rate11l] = | ||
3593 | targetPowerCck.tPow2x[3]; | ||
3594 | } | ||
3595 | if (IS_CHAN_HT40(chan)) { | ||
3596 | for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) | ||
3597 | ratesArray[rateHt40_0 + i] = targetPowerHt40.tPow2x[i]; | ||
3598 | |||
3599 | ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0]; | ||
3600 | ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0]; | ||
3601 | ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0]; | ||
3602 | if (IS_CHAN_2GHZ(chan)) | ||
3603 | ratesArray[rateExtCck] = targetPowerCckExt.tPow2x[0]; | ||
3604 | } | ||
3605 | #undef REDUCE_SCALED_POWER_BY_TWO_CHAIN | ||
3606 | #undef REDUCE_SCALED_POWER_BY_THREE_CHAIN | ||
3607 | } | ||
3608 | |||
3609 | static void ath9k_hw_AR9287_set_txpower(struct ath_hw *ah, | ||
3610 | struct ath9k_channel *chan, u16 cfgCtl, | ||
3611 | u8 twiceAntennaReduction, u8 twiceMaxRegulatoryPower, | ||
3612 | u8 powerLimit) | ||
3613 | { | ||
3614 | #define INCREASE_MAXPOW_BY_TWO_CHAIN 6 | ||
3615 | #define INCREASE_MAXPOW_BY_THREE_CHAIN 10 | ||
3616 | struct ar9287_eeprom_t *pEepData = &ah->eeprom.map9287; | ||
3617 | struct modal_eep_ar9287_header *pModal = &pEepData->modalHeader; | ||
3618 | int16_t ratesArray[Ar5416RateSize]; | ||
3619 | int16_t txPowerIndexOffset = 0; | ||
3620 | u8 ht40PowerIncForPdadc = 2; | ||
3621 | int i; | ||
3622 | memset(ratesArray, 0, sizeof(ratesArray)); | ||
3623 | |||
3624 | if ((pEepData->baseEepHeader.version & AR9287_EEP_VER_MINOR_MASK) >= | ||
3625 | AR9287_EEP_MINOR_VER_2) | ||
3626 | ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc; | ||
3627 | |||
3628 | ath9k_hw_set_AR9287_power_per_rate_table(ah, chan, | ||
3629 | &ratesArray[0], cfgCtl, | ||
3630 | twiceAntennaReduction, | ||
3631 | twiceMaxRegulatoryPower, | ||
3632 | powerLimit); | ||
3633 | |||
3634 | |||
3635 | ath9k_hw_set_AR9287_power_cal_table(ah, chan, &txPowerIndexOffset); | ||
3636 | |||
3637 | for (i = 0; i < ARRAY_SIZE(ratesArray); i++) { | ||
3638 | ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]); | ||
3639 | if (ratesArray[i] > AR9287_MAX_RATE_POWER) | ||
3640 | ratesArray[i] = AR9287_MAX_RATE_POWER; | ||
3641 | } | ||
3642 | |||
3643 | if (AR_SREV_9280_10_OR_LATER(ah)) { | ||
3644 | for (i = 0; i < Ar5416RateSize; i++) | ||
3645 | ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2; | ||
3646 | } | ||
3647 | |||
3648 | |||
3649 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE1, | ||
3650 | ATH9K_POW_SM(ratesArray[rate18mb], 24) | ||
3651 | | ATH9K_POW_SM(ratesArray[rate12mb], 16) | ||
3652 | | ATH9K_POW_SM(ratesArray[rate9mb], 8) | ||
3653 | | ATH9K_POW_SM(ratesArray[rate6mb], 0) | ||
3654 | ); | ||
3655 | |||
3656 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE2, | ||
3657 | ATH9K_POW_SM(ratesArray[rate54mb], 24) | ||
3658 | | ATH9K_POW_SM(ratesArray[rate48mb], 16) | ||
3659 | | ATH9K_POW_SM(ratesArray[rate36mb], 8) | ||
3660 | | ATH9K_POW_SM(ratesArray[rate24mb], 0) | ||
3661 | ); | ||
3662 | |||
3663 | if (IS_CHAN_2GHZ(chan)) { | ||
3664 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE3, | ||
3665 | ATH9K_POW_SM(ratesArray[rate2s], 24) | ||
3666 | | ATH9K_POW_SM(ratesArray[rate2l], 16) | ||
3667 | | ATH9K_POW_SM(ratesArray[rateXr], 8) | ||
3668 | | ATH9K_POW_SM(ratesArray[rate1l], 0) | ||
3669 | ); | ||
3670 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE4, | ||
3671 | ATH9K_POW_SM(ratesArray[rate11s], 24) | ||
3672 | | ATH9K_POW_SM(ratesArray[rate11l], 16) | ||
3673 | | ATH9K_POW_SM(ratesArray[rate5_5s], 8) | ||
3674 | | ATH9K_POW_SM(ratesArray[rate5_5l], 0) | ||
3675 | ); | ||
3676 | } | ||
3677 | |||
3678 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE5, | ||
3679 | ATH9K_POW_SM(ratesArray[rateHt20_3], 24) | ||
3680 | | ATH9K_POW_SM(ratesArray[rateHt20_2], 16) | ||
3681 | | ATH9K_POW_SM(ratesArray[rateHt20_1], 8) | ||
3682 | | ATH9K_POW_SM(ratesArray[rateHt20_0], 0) | ||
3683 | ); | ||
3684 | |||
3685 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE6, | ||
3686 | ATH9K_POW_SM(ratesArray[rateHt20_7], 24) | ||
3687 | | ATH9K_POW_SM(ratesArray[rateHt20_6], 16) | ||
3688 | | ATH9K_POW_SM(ratesArray[rateHt20_5], 8) | ||
3689 | | ATH9K_POW_SM(ratesArray[rateHt20_4], 0) | ||
3690 | ); | ||
3691 | |||
3692 | if (IS_CHAN_HT40(chan)) { | ||
3693 | if (ath9k_hw_AR9287_get_eeprom(ah, EEP_OL_PWRCTRL)) { | ||
3694 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE7, | ||
3695 | ATH9K_POW_SM(ratesArray[rateHt40_3], 24) | ||
3696 | | ATH9K_POW_SM(ratesArray[rateHt40_2], 16) | ||
3697 | | ATH9K_POW_SM(ratesArray[rateHt40_1], 8) | ||
3698 | | ATH9K_POW_SM(ratesArray[rateHt40_0], 0) | ||
3699 | ); | ||
3700 | |||
3701 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE8, | ||
3702 | ATH9K_POW_SM(ratesArray[rateHt40_7], 24) | ||
3703 | | ATH9K_POW_SM(ratesArray[rateHt40_6], 16) | ||
3704 | | ATH9K_POW_SM(ratesArray[rateHt40_5], 8) | ||
3705 | | ATH9K_POW_SM(ratesArray[rateHt40_4], 0) | ||
3706 | ); | ||
3707 | } else { | ||
3708 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE7, | ||
3709 | ATH9K_POW_SM(ratesArray[rateHt40_3] + | ||
3710 | ht40PowerIncForPdadc, 24) | ||
3711 | | ATH9K_POW_SM(ratesArray[rateHt40_2] + | ||
3712 | ht40PowerIncForPdadc, 16) | ||
3713 | | ATH9K_POW_SM(ratesArray[rateHt40_1] + | ||
3714 | ht40PowerIncForPdadc, 8) | ||
3715 | | ATH9K_POW_SM(ratesArray[rateHt40_0] + | ||
3716 | ht40PowerIncForPdadc, 0) | ||
3717 | ); | ||
3718 | |||
3719 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE8, | ||
3720 | ATH9K_POW_SM(ratesArray[rateHt40_7] + | ||
3721 | ht40PowerIncForPdadc, 24) | ||
3722 | | ATH9K_POW_SM(ratesArray[rateHt40_6] + | ||
3723 | ht40PowerIncForPdadc, 16) | ||
3724 | | ATH9K_POW_SM(ratesArray[rateHt40_5] + | ||
3725 | ht40PowerIncForPdadc, 8) | ||
3726 | | ATH9K_POW_SM(ratesArray[rateHt40_4] + | ||
3727 | ht40PowerIncForPdadc, 0) | ||
3728 | ); | ||
3729 | |||
3730 | } | ||
3731 | |||
3732 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE9, | ||
3733 | ATH9K_POW_SM(ratesArray[rateExtOfdm], 24) | ||
3734 | | ATH9K_POW_SM(ratesArray[rateExtCck], 16) | ||
3735 | | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8) | ||
3736 | | ATH9K_POW_SM(ratesArray[rateDupCck], 0) | ||
3737 | ); | ||
3738 | } | ||
3739 | |||
3740 | |||
3741 | if (IS_CHAN_2GHZ(chan)) | ||
3742 | i = rate1l; | ||
3743 | else | ||
3744 | i = rate6mb; | ||
3745 | |||
3746 | if (AR_SREV_9280_10_OR_LATER(ah)) | ||
3747 | ah->regulatory.max_power_level = | ||
3748 | ratesArray[i] + AR9287_PWR_TABLE_OFFSET_DB * 2; | ||
3749 | else | ||
3750 | ah->regulatory.max_power_level = ratesArray[i]; | ||
3751 | |||
3752 | switch (ar5416_get_ntxchains(ah->txchainmask)) { | ||
3753 | case 1: | ||
3754 | break; | ||
3755 | case 2: | ||
3756 | ah->regulatory.max_power_level += | ||
3757 | INCREASE_MAXPOW_BY_TWO_CHAIN; | ||
3758 | break; | ||
3759 | case 3: | ||
3760 | ah->regulatory.max_power_level += | ||
3761 | INCREASE_MAXPOW_BY_THREE_CHAIN; | ||
3762 | break; | ||
3763 | default: | ||
3764 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
3765 | "Invalid chainmask configuration\n"); | ||
3766 | break; | ||
3767 | } | ||
3768 | } | ||
3769 | |||
3770 | static void ath9k_hw_AR9287_set_addac(struct ath_hw *ah, | ||
3771 | struct ath9k_channel *chan) | ||
3772 | { | ||
3773 | return; | ||
3774 | } | ||
3775 | |||
3776 | static void ath9k_hw_AR9287_set_board_values(struct ath_hw *ah, | ||
3777 | struct ath9k_channel *chan) | ||
3778 | { | ||
3779 | struct ar9287_eeprom_t *eep = &ah->eeprom.map9287; | ||
3780 | struct modal_eep_ar9287_header *pModal = &eep->modalHeader; | ||
3781 | |||
3782 | u16 antWrites[AR9287_ANT_16S]; | ||
3783 | u32 regChainOffset; | ||
3784 | u8 txRxAttenLocal; | ||
3785 | int i, j, offset_num; | ||
3786 | |||
3787 | pModal = &eep->modalHeader; | ||
3788 | |||
3789 | antWrites[0] = (u16)((pModal->antCtrlCommon >> 28) & 0xF); | ||
3790 | antWrites[1] = (u16)((pModal->antCtrlCommon >> 24) & 0xF); | ||
3791 | antWrites[2] = (u16)((pModal->antCtrlCommon >> 20) & 0xF); | ||
3792 | antWrites[3] = (u16)((pModal->antCtrlCommon >> 16) & 0xF); | ||
3793 | antWrites[4] = (u16)((pModal->antCtrlCommon >> 12) & 0xF); | ||
3794 | antWrites[5] = (u16)((pModal->antCtrlCommon >> 8) & 0xF); | ||
3795 | antWrites[6] = (u16)((pModal->antCtrlCommon >> 4) & 0xF); | ||
3796 | antWrites[7] = (u16)(pModal->antCtrlCommon & 0xF); | ||
3797 | |||
3798 | offset_num = 8; | ||
3799 | |||
3800 | for (i = 0, j = offset_num; i < AR9287_MAX_CHAINS; i++) { | ||
3801 | antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 28) & 0xf); | ||
3802 | antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 10) & 0x3); | ||
3803 | antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 8) & 0x3); | ||
3804 | antWrites[j++] = 0; | ||
3805 | antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 6) & 0x3); | ||
3806 | antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 4) & 0x3); | ||
3807 | antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 2) & 0x3); | ||
3808 | antWrites[j++] = (u16)(pModal->antCtrlChain[i] & 0x3); | ||
3809 | } | ||
3810 | |||
3811 | |||
3812 | REG_WRITE(ah, AR_PHY_SWITCH_COM, | ||
3813 | ah->eep_ops->get_eeprom_antenna_cfg(ah, chan)); | ||
3814 | |||
3815 | for (i = 0; i < AR9287_MAX_CHAINS; i++) { | ||
3816 | regChainOffset = i * 0x1000; | ||
3817 | |||
3818 | REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset, | ||
3819 | pModal->antCtrlChain[i]); | ||
3820 | |||
3821 | REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset, | ||
3822 | (REG_READ(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset) | ||
3823 | & ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF | | ||
3824 | AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) | | ||
3825 | SM(pModal->iqCalICh[i], | ||
3826 | AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) | | ||
3827 | SM(pModal->iqCalQCh[i], | ||
3828 | AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF)); | ||
3829 | |||
3830 | txRxAttenLocal = pModal->txRxAttenCh[i]; | ||
3831 | |||
3832 | REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, | ||
3833 | AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, | ||
3834 | pModal->bswMargin[i]); | ||
3835 | REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, | ||
3836 | AR_PHY_GAIN_2GHZ_XATTEN1_DB, | ||
3837 | pModal->bswAtten[i]); | ||
3838 | REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset, | ||
3839 | AR9280_PHY_RXGAIN_TXRX_ATTEN, | ||
3840 | txRxAttenLocal); | ||
3841 | REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset, | ||
3842 | AR9280_PHY_RXGAIN_TXRX_MARGIN, | ||
3843 | pModal->rxTxMarginCh[i]); | ||
3844 | } | ||
3845 | |||
3846 | |||
3847 | if (IS_CHAN_HT40(chan)) | ||
3848 | REG_RMW_FIELD(ah, AR_PHY_SETTLING, | ||
3849 | AR_PHY_SETTLING_SWITCH, pModal->swSettleHt40); | ||
3850 | else | ||
3851 | REG_RMW_FIELD(ah, AR_PHY_SETTLING, | ||
3852 | AR_PHY_SETTLING_SWITCH, pModal->switchSettling); | ||
3853 | |||
3854 | REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, | ||
3855 | AR_PHY_DESIRED_SZ_ADC, pModal->adcDesiredSize); | ||
3856 | |||
3857 | REG_WRITE(ah, AR_PHY_RF_CTL4, | ||
3858 | SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF) | ||
3859 | | SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAB_OFF) | ||
3860 | | SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAA_ON) | ||
3861 | | SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAB_ON)); | ||
3862 | |||
3863 | REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, | ||
3864 | AR_PHY_TX_END_TO_A2_RX_ON, pModal->txEndToRxOn); | ||
3865 | |||
3866 | REG_RMW_FIELD(ah, AR_PHY_CCA, | ||
3867 | AR9280_PHY_CCA_THRESH62, pModal->thresh62); | ||
3868 | REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, | ||
3869 | AR_PHY_EXT_CCA0_THRESH62, pModal->thresh62); | ||
3870 | |||
3871 | ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0, AR9287_AN_RF2G3_DB1, | ||
3872 | AR9287_AN_RF2G3_DB1_S, pModal->db1); | ||
3873 | ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0, AR9287_AN_RF2G3_DB2, | ||
3874 | AR9287_AN_RF2G3_DB2_S, pModal->db2); | ||
3875 | ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0, | ||
3876 | AR9287_AN_RF2G3_OB_CCK, | ||
3877 | AR9287_AN_RF2G3_OB_CCK_S, pModal->ob_cck); | ||
3878 | ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0, | ||
3879 | AR9287_AN_RF2G3_OB_PSK, | ||
3880 | AR9287_AN_RF2G3_OB_PSK_S, pModal->ob_psk); | ||
3881 | ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0, | ||
3882 | AR9287_AN_RF2G3_OB_QAM, | ||
3883 | AR9287_AN_RF2G3_OB_QAM_S, pModal->ob_qam); | ||
3884 | ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0, | ||
3885 | AR9287_AN_RF2G3_OB_PAL_OFF, | ||
3886 | AR9287_AN_RF2G3_OB_PAL_OFF_S, | ||
3887 | pModal->ob_pal_off); | ||
3888 | |||
3889 | ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1, | ||
3890 | AR9287_AN_RF2G3_DB1, AR9287_AN_RF2G3_DB1_S, | ||
3891 | pModal->db1); | ||
3892 | ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1, AR9287_AN_RF2G3_DB2, | ||
3893 | AR9287_AN_RF2G3_DB2_S, pModal->db2); | ||
3894 | ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1, | ||
3895 | AR9287_AN_RF2G3_OB_CCK, | ||
3896 | AR9287_AN_RF2G3_OB_CCK_S, pModal->ob_cck); | ||
3897 | ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1, | ||
3898 | AR9287_AN_RF2G3_OB_PSK, | ||
3899 | AR9287_AN_RF2G3_OB_PSK_S, pModal->ob_psk); | ||
3900 | ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1, | ||
3901 | AR9287_AN_RF2G3_OB_QAM, | ||
3902 | AR9287_AN_RF2G3_OB_QAM_S, pModal->ob_qam); | ||
3903 | ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1, | ||
3904 | AR9287_AN_RF2G3_OB_PAL_OFF, | ||
3905 | AR9287_AN_RF2G3_OB_PAL_OFF_S, | ||
3906 | pModal->ob_pal_off); | ||
3907 | |||
3908 | REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, | ||
3909 | AR_PHY_TX_END_DATA_START, pModal->txFrameToDataStart); | ||
3910 | REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, | ||
3911 | AR_PHY_TX_END_PA_ON, pModal->txFrameToPaOn); | ||
3912 | |||
3913 | ath9k_hw_analog_shift_rmw(ah, AR9287_AN_TOP2, | ||
3914 | AR9287_AN_TOP2_XPABIAS_LVL, | ||
3915 | AR9287_AN_TOP2_XPABIAS_LVL_S, | ||
3916 | pModal->xpaBiasLvl); | ||
3917 | } | ||
3918 | |||
3919 | static u8 ath9k_hw_AR9287_get_num_ant_config(struct ath_hw *ah, | ||
3920 | enum ieee80211_band freq_band) | ||
3921 | { | ||
3922 | return 1; | ||
3923 | } | ||
3924 | |||
3925 | |||
3926 | |||
3927 | |||
3928 | static u16 ath9k_hw_AR9287_get_eeprom_antenna_cfg(struct ath_hw *ah, | ||
3929 | struct ath9k_channel *chan) | ||
3930 | { | ||
3931 | struct ar9287_eeprom_t *eep = &ah->eeprom.map9287; | ||
3932 | struct modal_eep_ar9287_header *pModal = &eep->modalHeader; | ||
3933 | return pModal->antCtrlCommon & 0xFFFF; | ||
3934 | } | ||
3935 | |||
3936 | |||
3937 | static u16 ath9k_hw_AR9287_get_spur_channel(struct ath_hw *ah, | ||
3938 | u16 i, bool is2GHz) | ||
3939 | { | ||
3940 | #define EEP_MAP9287_SPURCHAN \ | ||
3941 | (ah->eeprom.map9287.modalHeader.spurChans[i].spurChan) | ||
3942 | u16 spur_val = AR_NO_SPUR; | ||
3943 | |||
3944 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | ||
3945 | "Getting spur idx %d is2Ghz. %d val %x\n", | ||
3946 | i, is2GHz, ah->config.spurchans[i][is2GHz]); | ||
3947 | |||
3948 | switch (ah->config.spurmode) { | ||
3949 | case SPUR_DISABLE: | ||
3950 | break; | ||
3951 | case SPUR_ENABLE_IOCTL: | ||
3952 | spur_val = ah->config.spurchans[i][is2GHz]; | ||
3953 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | ||
3954 | "Getting spur val from new loc. %d\n", spur_val); | ||
3955 | break; | ||
3956 | case SPUR_ENABLE_EEPROM: | ||
3957 | spur_val = EEP_MAP9287_SPURCHAN; | ||
3958 | break; | ||
3959 | } | ||
3960 | |||
3961 | return spur_val; | ||
3962 | |||
3963 | #undef EEP_MAP9287_SPURCHAN | ||
3964 | } | ||
3965 | |||
3966 | static struct eeprom_ops eep_AR9287_ops = { | ||
3967 | .check_eeprom = ath9k_hw_AR9287_check_eeprom, | ||
3968 | .get_eeprom = ath9k_hw_AR9287_get_eeprom, | ||
3969 | .fill_eeprom = ath9k_hw_AR9287_fill_eeprom, | ||
3970 | .get_eeprom_ver = ath9k_hw_AR9287_get_eeprom_ver, | ||
3971 | .get_eeprom_rev = ath9k_hw_AR9287_get_eeprom_rev, | ||
3972 | .get_num_ant_config = ath9k_hw_AR9287_get_num_ant_config, | ||
3973 | .get_eeprom_antenna_cfg = ath9k_hw_AR9287_get_eeprom_antenna_cfg, | ||
3974 | .set_board_values = ath9k_hw_AR9287_set_board_values, | ||
3975 | .set_addac = ath9k_hw_AR9287_set_addac, | ||
3976 | .set_txpower = ath9k_hw_AR9287_set_txpower, | ||
3977 | .get_spur_channel = ath9k_hw_AR9287_get_spur_channel | ||
3978 | }; | ||
3979 | |||
3980 | |||
2784 | int ath9k_hw_eeprom_attach(struct ath_hw *ah) | 3981 | int ath9k_hw_eeprom_attach(struct ath_hw *ah) |
2785 | { | 3982 | { |
2786 | int status; | 3983 | int status; |
2787 | 3984 | if (AR_SREV_9287(ah)) { | |
2788 | if (AR_SREV_9285(ah)) { | 3985 | ah->eep_map = EEP_MAP_AR9287; |
3986 | ah->eep_ops = &eep_AR9287_ops; | ||
3987 | } else if (AR_SREV_9285(ah)) { | ||
2789 | ah->eep_map = EEP_MAP_4KBITS; | 3988 | ah->eep_map = EEP_MAP_4KBITS; |
2790 | ah->eep_ops = &eep_4k_ops; | 3989 | ah->eep_ops = &eep_4k_ops; |
2791 | } else { | 3990 | } else { |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h index 67b8bd12941a..7ddd016a99ff 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.h +++ b/drivers/net/wireless/ath/ath9k/eeprom.h | |||
@@ -100,6 +100,8 @@ | |||
100 | #define AR5416_VER_MASK (eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) | 100 | #define AR5416_VER_MASK (eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) |
101 | #define OLC_FOR_AR9280_20_LATER (AR_SREV_9280_20_OR_LATER(ah) && \ | 101 | #define OLC_FOR_AR9280_20_LATER (AR_SREV_9280_20_OR_LATER(ah) && \ |
102 | ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)) | 102 | ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)) |
103 | #define OLC_FOR_AR9287_10_LATER (AR_SREV_9287_10_OR_LATER(ah) && \ | ||
104 | ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)) | ||
103 | 105 | ||
104 | #define AR_EEPROM_RFSILENT_GPIO_SEL 0x001c | 106 | #define AR_EEPROM_RFSILENT_GPIO_SEL 0x001c |
105 | #define AR_EEPROM_RFSILENT_GPIO_SEL_S 2 | 107 | #define AR_EEPROM_RFSILENT_GPIO_SEL_S 2 |
@@ -176,6 +178,57 @@ | |||
176 | 178 | ||
177 | #define AR9280_TX_GAIN_TABLE_SIZE 22 | 179 | #define AR9280_TX_GAIN_TABLE_SIZE 22 |
178 | 180 | ||
181 | #define AR9287_EEP_VER 0xE | ||
182 | #define AR9287_EEP_VER_MINOR_MASK 0xFFF | ||
183 | #define AR9287_EEP_MINOR_VER_1 0x1 | ||
184 | #define AR9287_EEP_MINOR_VER_2 0x2 | ||
185 | #define AR9287_EEP_MINOR_VER_3 0x3 | ||
186 | #define AR9287_EEP_MINOR_VER AR9287_EEP_MINOR_VER_3 | ||
187 | #define AR9287_EEP_MINOR_VER_b AR9287_EEP_MINOR_VER | ||
188 | #define AR9287_EEP_NO_BACK_VER AR9287_EEP_MINOR_VER_1 | ||
189 | |||
190 | #define AR9287_EEP_START_LOC 128 | ||
191 | #define AR9287_NUM_2G_CAL_PIERS 3 | ||
192 | #define AR9287_NUM_2G_CCK_TARGET_POWERS 3 | ||
193 | #define AR9287_NUM_2G_20_TARGET_POWERS 3 | ||
194 | #define AR9287_NUM_2G_40_TARGET_POWERS 3 | ||
195 | #define AR9287_NUM_CTLS 12 | ||
196 | #define AR9287_NUM_BAND_EDGES 4 | ||
197 | #define AR9287_NUM_PD_GAINS 4 | ||
198 | #define AR9287_PD_GAINS_IN_MASK 4 | ||
199 | #define AR9287_PD_GAIN_ICEPTS 1 | ||
200 | #define AR9287_EEPROM_MODAL_SPURS 5 | ||
201 | #define AR9287_MAX_RATE_POWER 63 | ||
202 | #define AR9287_NUM_PDADC_VALUES 128 | ||
203 | #define AR9287_NUM_RATES 16 | ||
204 | #define AR9287_BCHAN_UNUSED 0xFF | ||
205 | #define AR9287_MAX_PWR_RANGE_IN_HALF_DB 64 | ||
206 | #define AR9287_OPFLAGS_11A 0x01 | ||
207 | #define AR9287_OPFLAGS_11G 0x02 | ||
208 | #define AR9287_OPFLAGS_2G_HT40 0x08 | ||
209 | #define AR9287_OPFLAGS_2G_HT20 0x20 | ||
210 | #define AR9287_OPFLAGS_5G_HT40 0x04 | ||
211 | #define AR9287_OPFLAGS_5G_HT20 0x10 | ||
212 | #define AR9287_EEPMISC_BIG_ENDIAN 0x01 | ||
213 | #define AR9287_EEPMISC_WOW 0x02 | ||
214 | #define AR9287_MAX_CHAINS 2 | ||
215 | #define AR9287_ANT_16S 32 | ||
216 | #define AR9287_custdatasize 20 | ||
217 | |||
218 | #define AR9287_NUM_ANT_CHAIN_FIELDS 6 | ||
219 | #define AR9287_NUM_ANT_COMMON_FIELDS 4 | ||
220 | #define AR9287_SIZE_ANT_CHAIN_FIELD 2 | ||
221 | #define AR9287_SIZE_ANT_COMMON_FIELD 4 | ||
222 | #define AR9287_ANT_CHAIN_MASK 0x3 | ||
223 | #define AR9287_ANT_COMMON_MASK 0xf | ||
224 | #define AR9287_CHAIN_0_IDX 0 | ||
225 | #define AR9287_CHAIN_1_IDX 1 | ||
226 | #define AR9287_DATA_SZ 32 | ||
227 | |||
228 | #define AR9287_PWR_TABLE_OFFSET_DB -5 | ||
229 | |||
230 | #define AR9287_CHECKSUM_LOCATION (AR9287_EEP_START_LOC + 1) | ||
231 | |||
179 | enum eeprom_param { | 232 | enum eeprom_param { |
180 | EEP_NFTHRESH_5, | 233 | EEP_NFTHRESH_5, |
181 | EEP_NFTHRESH_2, | 234 | EEP_NFTHRESH_2, |
@@ -199,7 +252,11 @@ enum eeprom_param { | |||
199 | EEP_OL_PWRCTRL, | 252 | EEP_OL_PWRCTRL, |
200 | EEP_RC_CHAIN_MASK, | 253 | EEP_RC_CHAIN_MASK, |
201 | EEP_DAC_HPWR_5G, | 254 | EEP_DAC_HPWR_5G, |
202 | EEP_FRAC_N_5G | 255 | EEP_FRAC_N_5G, |
256 | EEP_DEV_TYPE, | ||
257 | EEP_TEMPSENSE_SLOPE, | ||
258 | EEP_TEMPSENSE_SLOPE_PAL_ON, | ||
259 | EEP_PWR_TABLE_OFFSET | ||
203 | }; | 260 | }; |
204 | 261 | ||
205 | enum ar5416_rates { | 262 | enum ar5416_rates { |
@@ -368,6 +425,65 @@ struct modal_eep_4k_header { | |||
368 | struct spur_chan spurChans[AR5416_EEPROM_MODAL_SPURS]; | 425 | struct spur_chan spurChans[AR5416_EEPROM_MODAL_SPURS]; |
369 | } __packed; | 426 | } __packed; |
370 | 427 | ||
428 | struct base_eep_ar9287_header { | ||
429 | u16 length; | ||
430 | u16 checksum; | ||
431 | u16 version; | ||
432 | u8 opCapFlags; | ||
433 | u8 eepMisc; | ||
434 | u16 regDmn[2]; | ||
435 | u8 macAddr[6]; | ||
436 | u8 rxMask; | ||
437 | u8 txMask; | ||
438 | u16 rfSilent; | ||
439 | u16 blueToothOptions; | ||
440 | u16 deviceCap; | ||
441 | u32 binBuildNumber; | ||
442 | u8 deviceType; | ||
443 | u8 openLoopPwrCntl; | ||
444 | int8_t pwrTableOffset; | ||
445 | int8_t tempSensSlope; | ||
446 | int8_t tempSensSlopePalOn; | ||
447 | u8 futureBase[29]; | ||
448 | } __packed; | ||
449 | |||
450 | struct modal_eep_ar9287_header { | ||
451 | u32 antCtrlChain[AR9287_MAX_CHAINS]; | ||
452 | u32 antCtrlCommon; | ||
453 | int8_t antennaGainCh[AR9287_MAX_CHAINS]; | ||
454 | u8 switchSettling; | ||
455 | u8 txRxAttenCh[AR9287_MAX_CHAINS]; | ||
456 | u8 rxTxMarginCh[AR9287_MAX_CHAINS]; | ||
457 | int8_t adcDesiredSize; | ||
458 | u8 txEndToXpaOff; | ||
459 | u8 txEndToRxOn; | ||
460 | u8 txFrameToXpaOn; | ||
461 | u8 thresh62; | ||
462 | int8_t noiseFloorThreshCh[AR9287_MAX_CHAINS]; | ||
463 | u8 xpdGain; | ||
464 | u8 xpd; | ||
465 | int8_t iqCalICh[AR9287_MAX_CHAINS]; | ||
466 | int8_t iqCalQCh[AR9287_MAX_CHAINS]; | ||
467 | u8 pdGainOverlap; | ||
468 | u8 xpaBiasLvl; | ||
469 | u8 txFrameToDataStart; | ||
470 | u8 txFrameToPaOn; | ||
471 | u8 ht40PowerIncForPdadc; | ||
472 | u8 bswAtten[AR9287_MAX_CHAINS]; | ||
473 | u8 bswMargin[AR9287_MAX_CHAINS]; | ||
474 | u8 swSettleHt40; | ||
475 | u8 version; | ||
476 | u8 db1; | ||
477 | u8 db2; | ||
478 | u8 ob_cck; | ||
479 | u8 ob_psk; | ||
480 | u8 ob_qam; | ||
481 | u8 ob_pal_off; | ||
482 | u8 futureModal[30]; | ||
483 | struct spur_chan spurChans[AR9287_EEPROM_MODAL_SPURS]; | ||
484 | } __packed; | ||
485 | |||
486 | |||
371 | 487 | ||
372 | struct cal_data_per_freq { | 488 | struct cal_data_per_freq { |
373 | u8 pwrPdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS]; | 489 | u8 pwrPdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS]; |
@@ -402,6 +518,29 @@ struct cal_ctl_edges { | |||
402 | } __packed; | 518 | } __packed; |
403 | #endif | 519 | #endif |
404 | 520 | ||
521 | struct cal_data_op_loop_ar9287 { | ||
522 | u8 pwrPdg[2][5]; | ||
523 | u8 vpdPdg[2][5]; | ||
524 | u8 pcdac[2][5]; | ||
525 | u8 empty[2][5]; | ||
526 | } __packed; | ||
527 | |||
528 | |||
529 | struct cal_data_per_freq_ar9287 { | ||
530 | u8 pwrPdg[AR9287_NUM_PD_GAINS][AR9287_PD_GAIN_ICEPTS]; | ||
531 | u8 vpdPdg[AR9287_NUM_PD_GAINS][AR9287_PD_GAIN_ICEPTS]; | ||
532 | } __packed; | ||
533 | |||
534 | union cal_data_per_freq_ar9287_u { | ||
535 | struct cal_data_op_loop_ar9287 calDataOpen; | ||
536 | struct cal_data_per_freq_ar9287 calDataClose; | ||
537 | } __packed; | ||
538 | |||
539 | struct cal_ctl_data_ar9287 { | ||
540 | struct cal_ctl_edges | ||
541 | ctlEdges[AR9287_MAX_CHAINS][AR9287_NUM_BAND_EDGES]; | ||
542 | } __packed; | ||
543 | |||
405 | struct cal_ctl_data { | 544 | struct cal_ctl_data { |
406 | struct cal_ctl_edges | 545 | struct cal_ctl_edges |
407 | ctlEdges[AR5416_MAX_CHAINS][AR5416_NUM_BAND_EDGES]; | 546 | ctlEdges[AR5416_MAX_CHAINS][AR5416_NUM_BAND_EDGES]; |
@@ -461,6 +600,27 @@ struct ar5416_eeprom_4k { | |||
461 | u8 padding; | 600 | u8 padding; |
462 | } __packed; | 601 | } __packed; |
463 | 602 | ||
603 | struct ar9287_eeprom_t { | ||
604 | struct base_eep_ar9287_header baseEepHeader; | ||
605 | u8 custData[AR9287_DATA_SZ]; | ||
606 | struct modal_eep_ar9287_header modalHeader; | ||
607 | u8 calFreqPier2G[AR9287_NUM_2G_CAL_PIERS]; | ||
608 | union cal_data_per_freq_ar9287_u | ||
609 | calPierData2G[AR9287_MAX_CHAINS][AR9287_NUM_2G_CAL_PIERS]; | ||
610 | struct cal_target_power_leg | ||
611 | calTargetPowerCck[AR9287_NUM_2G_CCK_TARGET_POWERS]; | ||
612 | struct cal_target_power_leg | ||
613 | calTargetPower2G[AR9287_NUM_2G_20_TARGET_POWERS]; | ||
614 | struct cal_target_power_ht | ||
615 | calTargetPower2GHT20[AR9287_NUM_2G_20_TARGET_POWERS]; | ||
616 | struct cal_target_power_ht | ||
617 | calTargetPower2GHT40[AR9287_NUM_2G_40_TARGET_POWERS]; | ||
618 | u8 ctlIndex[AR9287_NUM_CTLS]; | ||
619 | struct cal_ctl_data_ar9287 ctlData[AR9287_NUM_CTLS]; | ||
620 | u8 padding; | ||
621 | } __packed; | ||
622 | |||
623 | |||
464 | enum reg_ext_bitmap { | 624 | enum reg_ext_bitmap { |
465 | REG_EXT_JAPAN_MIDBAND = 1, | 625 | REG_EXT_JAPAN_MIDBAND = 1, |
466 | REG_EXT_FCC_DFS_HT40 = 2, | 626 | REG_EXT_FCC_DFS_HT40 = 2, |
@@ -480,6 +640,7 @@ struct ath9k_country_entry { | |||
480 | enum ath9k_eep_map { | 640 | enum ath9k_eep_map { |
481 | EEP_MAP_DEFAULT = 0x0, | 641 | EEP_MAP_DEFAULT = 0x0, |
482 | EEP_MAP_4KBITS, | 642 | EEP_MAP_4KBITS, |
643 | EEP_MAP_AR9287, | ||
483 | EEP_MAP_MAX | 644 | EEP_MAP_MAX |
484 | }; | 645 | }; |
485 | 646 | ||
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 605803ae9ed8..da3226994de7 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
@@ -380,6 +380,9 @@ static const char *ath9k_hw_devname(u16 devid) | |||
380 | return "Atheros 9280"; | 380 | return "Atheros 9280"; |
381 | case AR9285_DEVID_PCIE: | 381 | case AR9285_DEVID_PCIE: |
382 | return "Atheros 9285"; | 382 | return "Atheros 9285"; |
383 | case AR5416_DEVID_AR9287_PCI: | ||
384 | case AR5416_DEVID_AR9287_PCIE: | ||
385 | return "Atheros 9287"; | ||
383 | } | 386 | } |
384 | 387 | ||
385 | return NULL; | 388 | return NULL; |
@@ -660,7 +663,8 @@ static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc, | |||
660 | if ((ah->hw_version.macVersion != AR_SREV_VERSION_5416_PCI) && | 663 | if ((ah->hw_version.macVersion != AR_SREV_VERSION_5416_PCI) && |
661 | (ah->hw_version.macVersion != AR_SREV_VERSION_5416_PCIE) && | 664 | (ah->hw_version.macVersion != AR_SREV_VERSION_5416_PCIE) && |
662 | (ah->hw_version.macVersion != AR_SREV_VERSION_9160) && | 665 | (ah->hw_version.macVersion != AR_SREV_VERSION_9160) && |
663 | (!AR_SREV_9100(ah)) && (!AR_SREV_9280(ah)) && (!AR_SREV_9285(ah))) { | 666 | (!AR_SREV_9100(ah)) && (!AR_SREV_9280(ah)) && |
667 | (!AR_SREV_9285(ah)) && (!AR_SREV_9287(ah))) { | ||
664 | DPRINTF(sc, ATH_DBG_FATAL, | 668 | DPRINTF(sc, ATH_DBG_FATAL, |
665 | "Mac Chip Rev 0x%02x.%x is not supported by " | 669 | "Mac Chip Rev 0x%02x.%x is not supported by " |
666 | "this driver\n", ah->hw_version.macVersion, | 670 | "this driver\n", ah->hw_version.macVersion, |
@@ -700,8 +704,37 @@ static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc, | |||
700 | ah->ani_function = ATH9K_ANI_ALL; | 704 | ah->ani_function = ATH9K_ANI_ALL; |
701 | if (AR_SREV_9280_10_OR_LATER(ah)) | 705 | if (AR_SREV_9280_10_OR_LATER(ah)) |
702 | ah->ani_function &= ~ATH9K_ANI_NOISE_IMMUNITY_LEVEL; | 706 | ah->ani_function &= ~ATH9K_ANI_NOISE_IMMUNITY_LEVEL; |
707 | if (AR_SREV_9287_11_OR_LATER(ah)) { | ||
708 | INIT_INI_ARRAY(&ah->iniModes, ar9287Modes_9287_1_1, | ||
709 | ARRAY_SIZE(ar9287Modes_9287_1_1), 6); | ||
710 | INIT_INI_ARRAY(&ah->iniCommon, ar9287Common_9287_1_1, | ||
711 | ARRAY_SIZE(ar9287Common_9287_1_1), 2); | ||
712 | if (ah->config.pcie_clock_req) | ||
713 | INIT_INI_ARRAY(&ah->iniPcieSerdes, | ||
714 | ar9287PciePhy_clkreq_off_L1_9287_1_1, | ||
715 | ARRAY_SIZE(ar9287PciePhy_clkreq_off_L1_9287_1_1), 2); | ||
716 | else | ||
717 | INIT_INI_ARRAY(&ah->iniPcieSerdes, | ||
718 | ar9287PciePhy_clkreq_always_on_L1_9287_1_1, | ||
719 | ARRAY_SIZE(ar9287PciePhy_clkreq_always_on_L1_9287_1_1), | ||
720 | 2); | ||
721 | } else if (AR_SREV_9287_10_OR_LATER(ah)) { | ||
722 | INIT_INI_ARRAY(&ah->iniModes, ar9287Modes_9287_1_0, | ||
723 | ARRAY_SIZE(ar9287Modes_9287_1_0), 6); | ||
724 | INIT_INI_ARRAY(&ah->iniCommon, ar9287Common_9287_1_0, | ||
725 | ARRAY_SIZE(ar9287Common_9287_1_0), 2); | ||
726 | |||
727 | if (ah->config.pcie_clock_req) | ||
728 | INIT_INI_ARRAY(&ah->iniPcieSerdes, | ||
729 | ar9287PciePhy_clkreq_off_L1_9287_1_0, | ||
730 | ARRAY_SIZE(ar9287PciePhy_clkreq_off_L1_9287_1_0), 2); | ||
731 | else | ||
732 | INIT_INI_ARRAY(&ah->iniPcieSerdes, | ||
733 | ar9287PciePhy_clkreq_always_on_L1_9287_1_0, | ||
734 | ARRAY_SIZE(ar9287PciePhy_clkreq_always_on_L1_9287_1_0), | ||
735 | 2); | ||
736 | } else if (AR_SREV_9285_12_OR_LATER(ah)) { | ||
703 | 737 | ||
704 | if (AR_SREV_9285_12_OR_LATER(ah)) { | ||
705 | 738 | ||
706 | INIT_INI_ARRAY(&ah->iniModes, ar9285Modes_9285_1_2, | 739 | INIT_INI_ARRAY(&ah->iniModes, ar9285Modes_9285_1_2, |
707 | ARRAY_SIZE(ar9285Modes_9285_1_2), 6); | 740 | ARRAY_SIZE(ar9285Modes_9285_1_2), 6); |
@@ -842,7 +875,28 @@ static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc, | |||
842 | if (ecode != 0) | 875 | if (ecode != 0) |
843 | goto bad; | 876 | goto bad; |
844 | 877 | ||
845 | if (AR_SREV_9285_12_OR_LATER(ah)) { | 878 | if (AR_SREV_9287_11(ah)) |
879 | INIT_INI_ARRAY(&ah->iniModesRxGain, | ||
880 | ar9287Modes_rx_gain_9287_1_1, | ||
881 | ARRAY_SIZE(ar9287Modes_rx_gain_9287_1_1), 6); | ||
882 | else if (AR_SREV_9287_10(ah)) | ||
883 | INIT_INI_ARRAY(&ah->iniModesRxGain, | ||
884 | ar9287Modes_rx_gain_9287_1_0, | ||
885 | ARRAY_SIZE(ar9287Modes_rx_gain_9287_1_0), 6); | ||
886 | else if (AR_SREV_9280_20(ah)) | ||
887 | ath9k_hw_init_rxgain_ini(ah); | ||
888 | |||
889 | if (AR_SREV_9287_11(ah)) { | ||
890 | INIT_INI_ARRAY(&ah->iniModesTxGain, | ||
891 | ar9287Modes_tx_gain_9287_1_1, | ||
892 | ARRAY_SIZE(ar9287Modes_tx_gain_9287_1_1), 6); | ||
893 | } else if (AR_SREV_9287_10(ah)) { | ||
894 | INIT_INI_ARRAY(&ah->iniModesTxGain, | ||
895 | ar9287Modes_tx_gain_9287_1_0, | ||
896 | ARRAY_SIZE(ar9287Modes_tx_gain_9287_1_0), 6); | ||
897 | } else if (AR_SREV_9280_20(ah)) { | ||
898 | ath9k_hw_init_txgain_ini(ah); | ||
899 | } else if (AR_SREV_9285_12_OR_LATER(ah)) { | ||
846 | u32 txgain_type = ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE); | 900 | u32 txgain_type = ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE); |
847 | 901 | ||
848 | /* txgain table */ | 902 | /* txgain table */ |
@@ -858,14 +912,6 @@ static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc, | |||
858 | 912 | ||
859 | } | 913 | } |
860 | 914 | ||
861 | /* rxgain table */ | ||
862 | if (AR_SREV_9280_20(ah)) | ||
863 | ath9k_hw_init_rxgain_ini(ah); | ||
864 | |||
865 | /* txgain table */ | ||
866 | if (AR_SREV_9280_20(ah)) | ||
867 | ath9k_hw_init_txgain_ini(ah); | ||
868 | |||
869 | ath9k_hw_fill_cap_info(ah); | 915 | ath9k_hw_fill_cap_info(ah); |
870 | 916 | ||
871 | if ((ah->hw_version.devid == AR9280_DEVID_PCI) && | 917 | if ((ah->hw_version.devid == AR9280_DEVID_PCI) && |
@@ -1165,6 +1211,8 @@ struct ath_hw *ath9k_hw_attach(u16 devid, struct ath_softc *sc, int *error) | |||
1165 | case AR9280_DEVID_PCI: | 1211 | case AR9280_DEVID_PCI: |
1166 | case AR9280_DEVID_PCIE: | 1212 | case AR9280_DEVID_PCIE: |
1167 | case AR9285_DEVID_PCIE: | 1213 | case AR9285_DEVID_PCIE: |
1214 | case AR5416_DEVID_AR9287_PCI: | ||
1215 | case AR5416_DEVID_AR9287_PCIE: | ||
1168 | ah = ath9k_hw_do_attach(devid, sc, error); | 1216 | ah = ath9k_hw_do_attach(devid, sc, error); |
1169 | break; | 1217 | break; |
1170 | default: | 1218 | default: |
@@ -1341,10 +1389,11 @@ static int ath9k_hw_process_ini(struct ath_hw *ah, | |||
1341 | DO_DELAY(regWrites); | 1389 | DO_DELAY(regWrites); |
1342 | } | 1390 | } |
1343 | 1391 | ||
1344 | if (AR_SREV_9280(ah)) | 1392 | if (AR_SREV_9280(ah) || AR_SREV_9287_10_OR_LATER(ah)) |
1345 | REG_WRITE_ARRAY(&ah->iniModesRxGain, modesIndex, regWrites); | 1393 | REG_WRITE_ARRAY(&ah->iniModesRxGain, modesIndex, regWrites); |
1346 | 1394 | ||
1347 | if (AR_SREV_9280(ah) || AR_SREV_9285_12_OR_LATER(ah)) | 1395 | if (AR_SREV_9280(ah) || AR_SREV_9285_12_OR_LATER(ah) || |
1396 | AR_SREV_9287_10_OR_LATER(ah)) | ||
1348 | REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites); | 1397 | REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites); |
1349 | 1398 | ||
1350 | for (i = 0; i < ah->iniCommon.ia_rows; i++) { | 1399 | for (i = 0; i < ah->iniCommon.ia_rows; i++) { |
@@ -2254,6 +2303,16 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
2254 | if (AR_SREV_9280_10_OR_LATER(ah)) | 2303 | if (AR_SREV_9280_10_OR_LATER(ah)) |
2255 | REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE); | 2304 | REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE); |
2256 | 2305 | ||
2306 | if (AR_SREV_9287_10_OR_LATER(ah)) { | ||
2307 | /* Enable ASYNC FIFO */ | ||
2308 | REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3, | ||
2309 | AR_MAC_PCU_ASYNC_FIFO_REG3_DATAPATH_SEL); | ||
2310 | REG_SET_BIT(ah, AR_PHY_MODE, AR_PHY_MODE_ASYNCFIFO); | ||
2311 | REG_CLR_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3, | ||
2312 | AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET); | ||
2313 | REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3, | ||
2314 | AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET); | ||
2315 | } | ||
2257 | r = ath9k_hw_process_ini(ah, chan, sc->tx_chan_width); | 2316 | r = ath9k_hw_process_ini(ah, chan, sc->tx_chan_width); |
2258 | if (r) | 2317 | if (r) |
2259 | return r; | 2318 | return r; |
@@ -2330,6 +2389,27 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
2330 | 2389 | ||
2331 | ath9k_hw_init_user_settings(ah); | 2390 | ath9k_hw_init_user_settings(ah); |
2332 | 2391 | ||
2392 | if (AR_SREV_9287_10_OR_LATER(ah)) { | ||
2393 | REG_WRITE(ah, AR_D_GBL_IFS_SIFS, | ||
2394 | AR_D_GBL_IFS_SIFS_ASYNC_FIFO_DUR); | ||
2395 | REG_WRITE(ah, AR_D_GBL_IFS_SLOT, | ||
2396 | AR_D_GBL_IFS_SLOT_ASYNC_FIFO_DUR); | ||
2397 | REG_WRITE(ah, AR_D_GBL_IFS_EIFS, | ||
2398 | AR_D_GBL_IFS_EIFS_ASYNC_FIFO_DUR); | ||
2399 | |||
2400 | REG_WRITE(ah, AR_TIME_OUT, AR_TIME_OUT_ACK_CTS_ASYNC_FIFO_DUR); | ||
2401 | REG_WRITE(ah, AR_USEC, AR_USEC_ASYNC_FIFO_DUR); | ||
2402 | |||
2403 | REG_SET_BIT(ah, AR_MAC_PCU_LOGIC_ANALYZER, | ||
2404 | AR_MAC_PCU_LOGIC_ANALYZER_DISBUG20768); | ||
2405 | REG_RMW_FIELD(ah, AR_AHB_MODE, AR_AHB_CUSTOM_BURST_EN, | ||
2406 | AR_AHB_CUSTOM_BURST_ASYNC_FIFO_VAL); | ||
2407 | } | ||
2408 | if (AR_SREV_9287_10_OR_LATER(ah)) { | ||
2409 | REG_SET_BIT(ah, AR_PCU_MISC_MODE2, | ||
2410 | AR_PCU_MISC_MODE2_ENABLE_AGGWEP); | ||
2411 | } | ||
2412 | |||
2333 | REG_WRITE(ah, AR_STA_ID1, | 2413 | REG_WRITE(ah, AR_STA_ID1, |
2334 | REG_READ(ah, AR_STA_ID1) | AR_STA_ID1_PRESERVE_SEQNUM); | 2414 | REG_READ(ah, AR_STA_ID1) | AR_STA_ID1_PRESERVE_SEQNUM); |
2335 | 2415 | ||
@@ -3644,7 +3724,9 @@ u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio) | |||
3644 | if (gpio >= ah->caps.num_gpio_pins) | 3724 | if (gpio >= ah->caps.num_gpio_pins) |
3645 | return 0xffffffff; | 3725 | return 0xffffffff; |
3646 | 3726 | ||
3647 | if (AR_SREV_9285_10_OR_LATER(ah)) | 3727 | if (AR_SREV_9287_10_OR_LATER(ah)) |
3728 | return MS_REG_READ(AR9287, gpio) != 0; | ||
3729 | else if (AR_SREV_9285_10_OR_LATER(ah)) | ||
3648 | return MS_REG_READ(AR9285, gpio) != 0; | 3730 | return MS_REG_READ(AR9285, gpio) != 0; |
3649 | else if (AR_SREV_9280_10_OR_LATER(ah)) | 3731 | else if (AR_SREV_9280_10_OR_LATER(ah)) |
3650 | return MS_REG_READ(AR928X, gpio) != 0; | 3732 | return MS_REG_READ(AR928X, gpio) != 0; |
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 28bffdb365a2..37f7d3defb82 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
@@ -42,6 +42,9 @@ | |||
42 | #define AR_SUBVENDOR_ID_NEW_A 0x7065 | 42 | #define AR_SUBVENDOR_ID_NEW_A 0x7065 |
43 | #define AR5416_MAGIC 0x19641014 | 43 | #define AR5416_MAGIC 0x19641014 |
44 | 44 | ||
45 | #define AR5416_DEVID_AR9287_PCI 0x002D | ||
46 | #define AR5416_DEVID_AR9287_PCIE 0x002E | ||
47 | |||
45 | /* Register read/write primitives */ | 48 | /* Register read/write primitives */ |
46 | #define REG_WRITE(_ah, _reg, _val) ath9k_iowrite32((_ah), (_reg), (_val)) | 49 | #define REG_WRITE(_ah, _reg, _val) ath9k_iowrite32((_ah), (_reg), (_val)) |
47 | #define REG_READ(_ah, _reg) ath9k_ioread32((_ah), (_reg)) | 50 | #define REG_READ(_ah, _reg) ath9k_ioread32((_ah), (_reg)) |
@@ -400,6 +403,7 @@ struct ath_hw { | |||
400 | union { | 403 | union { |
401 | struct ar5416_eeprom_def def; | 404 | struct ar5416_eeprom_def def; |
402 | struct ar5416_eeprom_4k map4k; | 405 | struct ar5416_eeprom_4k map4k; |
406 | struct ar9287_eeprom_t map9287; | ||
403 | } eeprom; | 407 | } eeprom; |
404 | const struct eeprom_ops *eep_ops; | 408 | const struct eeprom_ops *eep_ops; |
405 | enum ath9k_eep_map eep_map; | 409 | enum ath9k_eep_map eep_map; |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index b3e07e79daec..1c648db10920 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -2751,7 +2751,8 @@ static struct { | |||
2751 | { AR_SREV_VERSION_9100, "9100" }, | 2751 | { AR_SREV_VERSION_9100, "9100" }, |
2752 | { AR_SREV_VERSION_9160, "9160" }, | 2752 | { AR_SREV_VERSION_9160, "9160" }, |
2753 | { AR_SREV_VERSION_9280, "9280" }, | 2753 | { AR_SREV_VERSION_9280, "9280" }, |
2754 | { AR_SREV_VERSION_9285, "9285" } | 2754 | { AR_SREV_VERSION_9285, "9285" }, |
2755 | { AR_SREV_VERSION_9287, "9287" } | ||
2755 | }; | 2756 | }; |
2756 | 2757 | ||
2757 | static struct { | 2758 | static struct { |
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index 170c5b32e49b..cd4841be80af 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c | |||
@@ -25,6 +25,8 @@ static struct pci_device_id ath_pci_id_table[] __devinitdata = { | |||
25 | { PCI_VDEVICE(ATHEROS, 0x0029) }, /* PCI */ | 25 | { PCI_VDEVICE(ATHEROS, 0x0029) }, /* PCI */ |
26 | { PCI_VDEVICE(ATHEROS, 0x002A) }, /* PCI-E */ | 26 | { PCI_VDEVICE(ATHEROS, 0x002A) }, /* PCI-E */ |
27 | { PCI_VDEVICE(ATHEROS, 0x002B) }, /* PCI-E */ | 27 | { PCI_VDEVICE(ATHEROS, 0x002B) }, /* PCI-E */ |
28 | { PCI_VDEVICE(ATHEROS, 0x002D) }, /* PCI */ | ||
29 | { PCI_VDEVICE(ATHEROS, 0x002E) }, /* PCI-E */ | ||
28 | { 0 } | 30 | { 0 } |
29 | }; | 31 | }; |
30 | 32 | ||
diff --git a/drivers/net/wireless/ath/ath9k/phy.h b/drivers/net/wireless/ath/ath9k/phy.h index c70f530642f6..de4fadadbce5 100644 --- a/drivers/net/wireless/ath/ath9k/phy.h +++ b/drivers/net/wireless/ath/ath9k/phy.h | |||
@@ -375,6 +375,7 @@ bool ath9k_hw_init_rf(struct ath_hw *ah, | |||
375 | #define AR_PHY_CHAN_INFO_GAIN 0x9CFC | 375 | #define AR_PHY_CHAN_INFO_GAIN 0x9CFC |
376 | 376 | ||
377 | #define AR_PHY_MODE 0xA200 | 377 | #define AR_PHY_MODE 0xA200 |
378 | #define AR_PHY_MODE_ASYNCFIFO 0x80 | ||
378 | #define AR_PHY_MODE_AR2133 0x08 | 379 | #define AR_PHY_MODE_AR2133 0x08 |
379 | #define AR_PHY_MODE_AR5111 0x00 | 380 | #define AR_PHY_MODE_AR5111 0x00 |
380 | #define AR_PHY_MODE_AR5112 0x08 | 381 | #define AR_PHY_MODE_AR5112 0x08 |