diff options
author | David S. Miller <davem@davemloft.net> | 2009-07-30 22:26:55 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-07-30 22:26:55 -0400 |
commit | 2f6d7c1b34403b97fa57473edcb6749d1db5ace3 (patch) | |
tree | 97da33c077b08b72a361ff5a4542b86d190b0164 /drivers/net/wireless/ath/ath9k/eeprom.c | |
parent | df597efb5737063497f1a4f7c996cc9aec294230 (diff) | |
parent | 1e4247d457c6a42e4a05cb7dfa4e6ea1fa65c112 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/eeprom.c')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/eeprom.c | 1203 |
1 files changed, 1201 insertions, 2 deletions
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.c b/drivers/net/wireless/ath/ath9k/eeprom.c index 93e8ce0598a4..6fb1a8034b3c 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 { |