iPXE
ath9k_eeprom_4k.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2008-2011 Atheros Communications Inc.
00003  *
00004  * Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
00005  * Original from Linux kernel 3.0.1
00006  *
00007  * Permission to use, copy, modify, and/or distribute this software for any
00008  * purpose with or without fee is hereby granted, provided that the above
00009  * copyright notice and this permission notice appear in all copies.
00010  *
00011  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
00012  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
00013  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
00014  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
00015  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
00016  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
00017  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00018  */
00019 
00020 #include <ipxe/io.h>
00021 
00022 #include "hw.h"
00023 #include "ar9002_phy.h"
00024 
00025 static int ath9k_hw_4k_get_eeprom_ver(struct ath_hw *ah)
00026 {
00027         return ((ah->eeprom.map4k.baseEepHeader.version >> 12) & 0xF);
00028 }
00029 
00030 static int ath9k_hw_4k_get_eeprom_rev(struct ath_hw *ah)
00031 {
00032         return ((ah->eeprom.map4k.baseEepHeader.version) & 0xFFF);
00033 }
00034 
00035 #define SIZE_EEPROM_4K (sizeof(struct ar5416_eeprom_4k) / sizeof(u16))
00036 
00037 static int __ath9k_hw_4k_fill_eeprom(struct ath_hw *ah)
00038 {
00039         struct ath_common *common = ath9k_hw_common(ah);
00040         u16 *eep_data = (u16 *)&ah->eeprom.map4k;
00041         unsigned int addr;
00042         int eep_start_loc = 64;
00043 
00044         for (addr = 0; addr < SIZE_EEPROM_4K; addr++) {
00045                 if (!ath9k_hw_nvram_read(common, addr + eep_start_loc, eep_data)) {
00046                         DBG("ath9k: "
00047                                 "Unable to read eeprom region\n");
00048                         return 0;
00049                 }
00050                 eep_data++;
00051         }
00052 
00053         return 1;
00054 }
00055 
00056 static int __ath9k_hw_usb_4k_fill_eeprom(struct ath_hw *ah)
00057 {
00058         u16 *eep_data = (u16 *)&ah->eeprom.map4k;
00059 
00060         ath9k_hw_usb_gen_fill_eeprom(ah, eep_data, 64, SIZE_EEPROM_4K);
00061 
00062         return 1;
00063 }
00064 
00065 static int ath9k_hw_4k_fill_eeprom(struct ath_hw *ah)
00066 {
00067         struct ath_common *common = ath9k_hw_common(ah);
00068 
00069         if (!ath9k_hw_use_flash(ah)) {
00070                 DBG2("ath9k: "
00071                         "Reading from EEPROM, not flash\n");
00072         }
00073 
00074         if (common->bus_ops->ath_bus_type == ATH_USB)
00075                 return __ath9k_hw_usb_4k_fill_eeprom(ah);
00076         else
00077                 return __ath9k_hw_4k_fill_eeprom(ah);
00078 }
00079 
00080 #undef SIZE_EEPROM_4K
00081 
00082 static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah)
00083 {
00084 #define EEPROM_4K_SIZE (sizeof(struct ar5416_eeprom_4k) / sizeof(u16))
00085         struct ath_common *common = ath9k_hw_common(ah);
00086         struct ar5416_eeprom_4k *eep =
00087                 (struct ar5416_eeprom_4k *) &ah->eeprom.map4k;
00088         u16 *eepdata, temp, magic, magic2;
00089         u32 sum = 0, el;
00090         int need_swap = 0;
00091         unsigned int i, addr;
00092 
00093 
00094         if (!ath9k_hw_use_flash(ah)) {
00095                 if (!ath9k_hw_nvram_read(common, AR5416_EEPROM_MAGIC_OFFSET,
00096                                          &magic)) {
00097                         DBG("ath9k: Reading Magic # failed\n");
00098                         return 0;
00099                 }
00100 
00101                 DBG2("ath9k: "
00102                         "Read Magic = 0x%04X\n", magic);
00103 
00104                 if (magic != AR5416_EEPROM_MAGIC) {
00105                         magic2 = swab16(magic);
00106 
00107                         if (magic2 == AR5416_EEPROM_MAGIC) {
00108                                 need_swap = 1;
00109                                 eepdata = (u16 *) (&ah->eeprom);
00110 
00111                                 for (addr = 0; addr < EEPROM_4K_SIZE; addr++) {
00112                                         temp = swab16(*eepdata);
00113                                         *eepdata = temp;
00114                                         eepdata++;
00115                                 }
00116                         } else {
00117                                 DBG("ath9k: "
00118                                         "Invalid EEPROM Magic. Endianness mismatch.\n");
00119                                 return -EINVAL;
00120                         }
00121                 }
00122         }
00123 
00124         DBG2("ath9k: need_swap = %s.\n",
00125                 need_swap ? "True" : "False");
00126 
00127         if (need_swap)
00128                 el = swab16(ah->eeprom.map4k.baseEepHeader.length);
00129         else
00130                 el = ah->eeprom.map4k.baseEepHeader.length;
00131 
00132         if (el > sizeof(struct ar5416_eeprom_4k))
00133                 el = sizeof(struct ar5416_eeprom_4k) / sizeof(u16);
00134         else
00135                 el = el / sizeof(u16);
00136 
00137         eepdata = (u16 *)(&ah->eeprom);
00138 
00139         for (i = 0; i < el; i++)
00140                 sum ^= *eepdata++;
00141 
00142         if (need_swap) {
00143                 u32 integer;
00144                 u16 word;
00145 
00146                 DBG("ath9k: "
00147                         "EEPROM Endianness is not native.. Changing\n");
00148 
00149                 word = swab16(eep->baseEepHeader.length);
00150                 eep->baseEepHeader.length = word;
00151 
00152                 word = swab16(eep->baseEepHeader.checksum);
00153                 eep->baseEepHeader.checksum = word;
00154 
00155                 word = swab16(eep->baseEepHeader.version);
00156                 eep->baseEepHeader.version = word;
00157 
00158                 word = swab16(eep->baseEepHeader.regDmn[0]);
00159                 eep->baseEepHeader.regDmn[0] = word;
00160 
00161                 word = swab16(eep->baseEepHeader.regDmn[1]);
00162                 eep->baseEepHeader.regDmn[1] = word;
00163 
00164                 word = swab16(eep->baseEepHeader.rfSilent);
00165                 eep->baseEepHeader.rfSilent = word;
00166 
00167                 word = swab16(eep->baseEepHeader.blueToothOptions);
00168                 eep->baseEepHeader.blueToothOptions = word;
00169 
00170                 word = swab16(eep->baseEepHeader.deviceCap);
00171                 eep->baseEepHeader.deviceCap = word;
00172 
00173                 integer = swab32(eep->modalHeader.antCtrlCommon);
00174                 eep->modalHeader.antCtrlCommon = integer;
00175 
00176                 for (i = 0; i < AR5416_EEP4K_MAX_CHAINS; i++) {
00177                         integer = swab32(eep->modalHeader.antCtrlChain[i]);
00178                         eep->modalHeader.antCtrlChain[i] = integer;
00179                 }
00180 
00181                 for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
00182                         word = swab16(eep->modalHeader.spurChans[i].spurChan);
00183                         eep->modalHeader.spurChans[i].spurChan = word;
00184                 }
00185         }
00186 
00187         if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER ||
00188             ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) {
00189                 DBG("ath9k: Bad EEPROM checksum 0x%x or revision 0x%04x\n",
00190                         sum, ah->eep_ops->get_eeprom_ver(ah));
00191                 return -EINVAL;
00192         }
00193 
00194         return 0;
00195 #undef EEPROM_4K_SIZE
00196 }
00197 
00198 static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah,
00199                                   enum eeprom_param param)
00200 {
00201         struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
00202         struct modal_eep_4k_header *pModal = &eep->modalHeader;
00203         struct base_eep_header_4k *pBase = &eep->baseEepHeader;
00204         u16 ver_minor;
00205 
00206         ver_minor = pBase->version & AR5416_EEP_VER_MINOR_MASK;
00207 
00208         switch (param) {
00209         case EEP_NFTHRESH_2:
00210                 return pModal->noiseFloorThreshCh[0];
00211         case EEP_MAC_LSW:
00212                 return pBase->macAddr[0] << 8 | pBase->macAddr[1];
00213         case EEP_MAC_MID:
00214                 return pBase->macAddr[2] << 8 | pBase->macAddr[3];
00215         case EEP_MAC_MSW:
00216                 return pBase->macAddr[4] << 8 | pBase->macAddr[5];
00217         case EEP_REG_0:
00218                 return pBase->regDmn[0];
00219         case EEP_REG_1:
00220                 return pBase->regDmn[1];
00221         case EEP_OP_CAP:
00222                 return pBase->deviceCap;
00223         case EEP_OP_MODE:
00224                 return pBase->opCapFlags;
00225         case EEP_RF_SILENT:
00226                 return pBase->rfSilent;
00227         case EEP_OB_2:
00228                 return pModal->ob_0;
00229         case EEP_DB_2:
00230                 return pModal->db1_1;
00231         case EEP_MINOR_REV:
00232                 return ver_minor;
00233         case EEP_TX_MASK:
00234                 return pBase->txMask;
00235         case EEP_RX_MASK:
00236                 return pBase->rxMask;
00237         case EEP_FRAC_N_5G:
00238                 return 0;
00239         case EEP_PWR_TABLE_OFFSET:
00240                 return AR5416_PWR_TABLE_OFFSET_DB;
00241         case EEP_MODAL_VER:
00242                 return pModal->version;
00243         case EEP_ANT_DIV_CTL1:
00244                 return pModal->antdiv_ctl1;
00245         case EEP_TXGAIN_TYPE:
00246                 if (ver_minor >= AR5416_EEP_MINOR_VER_19)
00247                         return pBase->txGainType;
00248                 else
00249                         return AR5416_EEP_TXGAIN_ORIGINAL;
00250         default:
00251                 return 0;
00252         }
00253 }
00254 
00255 static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah,
00256                                   struct ath9k_channel *chan,
00257                                   int16_t *pTxPowerIndexOffset)
00258 {
00259         struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
00260         struct cal_data_per_freq_4k *pRawDataset;
00261         u8 *pCalBChans = NULL;
00262         u16 pdGainOverlap_t2;
00263         static u8 pdadcValues[AR5416_NUM_PDADC_VALUES];
00264         u16 gainBoundaries[AR5416_PD_GAINS_IN_MASK];
00265         u16 numPiers, i, j;
00266         u16 numXpdGain, xpdMask;
00267         u16 xpdGainValues[AR5416_EEP4K_NUM_PD_GAINS] = { 0, 0 };
00268         u32 reg32, regOffset, regChainOffset;
00269 
00270         xpdMask = pEepData->modalHeader.xpdGain;
00271 
00272         if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
00273             AR5416_EEP_MINOR_VER_2) {
00274                 pdGainOverlap_t2 =
00275                         pEepData->modalHeader.pdGainOverlap;
00276         } else {
00277                 pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5),
00278                                             AR_PHY_TPCRG5_PD_GAIN_OVERLAP));
00279         }
00280 
00281         pCalBChans = pEepData->calFreqPier2G;
00282         numPiers = AR5416_EEP4K_NUM_2G_CAL_PIERS;
00283 
00284         numXpdGain = 0;
00285 
00286         for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) {
00287                 if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) {
00288                         if (numXpdGain >= AR5416_EEP4K_NUM_PD_GAINS)
00289                                 break;
00290                         xpdGainValues[numXpdGain] =
00291                                 (u16)(AR5416_PD_GAINS_IN_MASK - i);
00292                         numXpdGain++;
00293                 }
00294         }
00295 
00296         REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN,
00297                       (numXpdGain - 1) & 0x3);
00298         REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1,
00299                       xpdGainValues[0]);
00300         REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2,
00301                       xpdGainValues[1]);
00302         REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3, 0);
00303 
00304         for (i = 0; i < AR5416_EEP4K_MAX_CHAINS; i++) {
00305                 if (AR_SREV_5416_20_OR_LATER(ah) &&
00306                     (ah->rxchainmask == 5 || ah->txchainmask == 5) &&
00307                     (i != 0)) {
00308                         regChainOffset = (i == 1) ? 0x2000 : 0x1000;
00309                 } else
00310                         regChainOffset = i * 0x1000;
00311 
00312                 if (pEepData->baseEepHeader.txMask & (1 << i)) {
00313                         pRawDataset = pEepData->calPierData2G[i];
00314 
00315                         ath9k_hw_get_gain_boundaries_pdadcs(ah, chan,
00316                                             pRawDataset, pCalBChans,
00317                                             numPiers, pdGainOverlap_t2,
00318                                             gainBoundaries,
00319                                             pdadcValues, numXpdGain);
00320 
00321                         ENABLE_REGWRITE_BUFFER(ah);
00322 
00323                         if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) {
00324                                 REG_WRITE(ah, AR_PHY_TPCRG5 + regChainOffset,
00325                                           SM(pdGainOverlap_t2,
00326                                              AR_PHY_TPCRG5_PD_GAIN_OVERLAP)
00327                                           | SM(gainBoundaries[0],
00328                                                AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1)
00329                                           | SM(gainBoundaries[1],
00330                                                AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2)
00331                                           | SM(gainBoundaries[2],
00332                                                AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3)
00333                                           | SM(gainBoundaries[3],
00334                                        AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4));
00335                         }
00336 
00337                         regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset;
00338                         for (j = 0; j < 32; j++) {
00339                                 reg32 = ((pdadcValues[4 * j + 0] & 0xFF) << 0) |
00340                                         ((pdadcValues[4 * j + 1] & 0xFF) << 8) |
00341                                         ((pdadcValues[4 * j + 2] & 0xFF) << 16)|
00342                                         ((pdadcValues[4 * j + 3] & 0xFF) << 24);
00343                                 REG_WRITE(ah, regOffset, reg32);
00344 
00345                                 DBG2("ath9k: "
00346                                         "PDADC (%d,%4x): %4.4x %8.8x\n",
00347                                         i, regChainOffset, regOffset,
00348                                         reg32);
00349                                 DBG2("ath9k: "
00350                                         "PDADC: Chain %d | "
00351                                         "PDADC %3d Value %3d | "
00352                                         "PDADC %3d Value %3d | "
00353                                         "PDADC %3d Value %3d | "
00354                                         "PDADC %3d Value %3d |\n",
00355                                         i, 4 * j, pdadcValues[4 * j],
00356                                         4 * j + 1, pdadcValues[4 * j + 1],
00357                                         4 * j + 2, pdadcValues[4 * j + 2],
00358                                         4 * j + 3, pdadcValues[4 * j + 3]);
00359 
00360                                 regOffset += 4;
00361                         }
00362 
00363                         REGWRITE_BUFFER_FLUSH(ah);
00364                 }
00365         }
00366 
00367         *pTxPowerIndexOffset = 0;
00368 }
00369 
00370 static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah,
00371                                                  struct ath9k_channel *chan,
00372                                                  int16_t *ratesArray,
00373                                                  u16 cfgCtl,
00374                                                  u16 AntennaReduction,
00375                                                  u16 twiceMaxRegulatoryPower,
00376                                                  u16 powerLimit)
00377 {
00378 #define CMP_TEST_GRP \
00379         (((cfgCtl & ~CTL_MODE_M)| (pCtlMode[ctlMode] & CTL_MODE_M)) ==  \
00380          pEepData->ctlIndex[i])                                         \
00381         || (((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == \
00382             ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL))
00383 
00384         struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
00385         unsigned int i;
00386         int16_t twiceLargestAntenna;
00387         u16 twiceMinEdgePower;
00388         u16 twiceMaxEdgePower = MAX_RATE_POWER;
00389         u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
00390         u16 numCtlModes;
00391         const u16 *pCtlMode;
00392         u16 ctlMode, freq;
00393         struct chan_centers centers;
00394         struct cal_ctl_data_4k *rep;
00395         struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
00396         static const u16 tpScaleReductionTable[5] =
00397                 { 0, 3, 6, 9, MAX_RATE_POWER };
00398         struct cal_target_power_leg targetPowerOfdm, targetPowerCck = {
00399                 0, { 0, 0, 0, 0}
00400         };
00401         struct cal_target_power_leg targetPowerOfdmExt = {
00402                 0, { 0, 0, 0, 0} }, targetPowerCckExt = {
00403                 0, { 0, 0, 0, 0 }
00404         };
00405         struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = {
00406                 0, {0, 0, 0, 0}
00407         };
00408         static const u16 ctlModesFor11g[] = {
00409                 CTL_11B, CTL_11G, CTL_2GHT20,
00410                 CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40
00411         };
00412 
00413         ath9k_hw_get_channel_centers(ah, chan, &centers);
00414 
00415         twiceLargestAntenna = pEepData->modalHeader.antennaGainCh[0];
00416         twiceLargestAntenna = (int16_t)min(AntennaReduction -
00417                                            twiceLargestAntenna, 0);
00418 
00419         maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
00420         if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX) {
00421                 maxRegAllowedPower -=
00422                         (tpScaleReductionTable[(regulatory->tp_scale)] * 2);
00423         }
00424 
00425         scaledPower = min(powerLimit, maxRegAllowedPower);
00426         scaledPower = max((u16)0, scaledPower);
00427 
00428         numCtlModes = ARRAY_SIZE(ctlModesFor11g) - SUB_NUM_CTL_MODES_AT_2G_40;
00429         pCtlMode = ctlModesFor11g;
00430 
00431         ath9k_hw_get_legacy_target_powers(ah, chan,
00432                         pEepData->calTargetPowerCck,
00433                         AR5416_NUM_2G_CCK_TARGET_POWERS,
00434                         &targetPowerCck, 4, 0);
00435         ath9k_hw_get_legacy_target_powers(ah, chan,
00436                         pEepData->calTargetPower2G,
00437                         AR5416_NUM_2G_20_TARGET_POWERS,
00438                         &targetPowerOfdm, 4, 0);
00439         ath9k_hw_get_target_powers(ah, chan,
00440                         pEepData->calTargetPower2GHT20,
00441                         AR5416_NUM_2G_20_TARGET_POWERS,
00442                         &targetPowerHt20, 8, 0);
00443 
00444         if (IS_CHAN_HT40(chan)) {
00445                 numCtlModes = ARRAY_SIZE(ctlModesFor11g);
00446                 ath9k_hw_get_target_powers(ah, chan,
00447                                 pEepData->calTargetPower2GHT40,
00448                                 AR5416_NUM_2G_40_TARGET_POWERS,
00449                                 &targetPowerHt40, 8, 1);
00450                 ath9k_hw_get_legacy_target_powers(ah, chan,
00451                                 pEepData->calTargetPowerCck,
00452                                 AR5416_NUM_2G_CCK_TARGET_POWERS,
00453                                 &targetPowerCckExt, 4, 1);
00454                 ath9k_hw_get_legacy_target_powers(ah, chan,
00455                                 pEepData->calTargetPower2G,
00456                                 AR5416_NUM_2G_20_TARGET_POWERS,
00457                                 &targetPowerOfdmExt, 4, 1);
00458         }
00459 
00460         for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) {
00461                 int isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) ||
00462                         (pCtlMode[ctlMode] == CTL_2GHT40);
00463 
00464                 if (isHt40CtlMode)
00465                         freq = centers.synth_center;
00466                 else if (pCtlMode[ctlMode] & EXT_ADDITIVE)
00467                         freq = centers.ext_center;
00468                 else
00469                         freq = centers.ctl_center;
00470 
00471                 if (ah->eep_ops->get_eeprom_ver(ah) == 14 &&
00472                     ah->eep_ops->get_eeprom_rev(ah) <= 2)
00473                         twiceMaxEdgePower = MAX_RATE_POWER;
00474 
00475                 for (i = 0; (i < AR5416_EEP4K_NUM_CTLS) &&
00476                              pEepData->ctlIndex[i]; i++) {
00477 
00478                         if (CMP_TEST_GRP) {
00479                                 rep = &(pEepData->ctlData[i]);
00480 
00481                                 twiceMinEdgePower = ath9k_hw_get_max_edge_power(
00482                                         freq,
00483                                         rep->ctlEdges[
00484                                         ar5416_get_ntxchains(ah->txchainmask) - 1],
00485                                         IS_CHAN_2GHZ(chan),
00486                                         AR5416_EEP4K_NUM_BAND_EDGES);
00487 
00488                                 if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) {
00489                                         twiceMaxEdgePower =
00490                                                 min(twiceMaxEdgePower,
00491                                                     twiceMinEdgePower);
00492                                 } else {
00493                                         twiceMaxEdgePower = twiceMinEdgePower;
00494                                         break;
00495                                 }
00496                         }
00497                 }
00498 
00499                 minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower);
00500 
00501                 switch (pCtlMode[ctlMode]) {
00502                 case CTL_11B:
00503                         for (i = 0; i < ARRAY_SIZE(targetPowerCck.tPow2x); i++) {
00504                                 targetPowerCck.tPow2x[i] =
00505                                         min((u16)targetPowerCck.tPow2x[i],
00506                                             minCtlPower);
00507                         }
00508                         break;
00509                 case CTL_11G:
00510                         for (i = 0; i < ARRAY_SIZE(targetPowerOfdm.tPow2x); i++) {
00511                                 targetPowerOfdm.tPow2x[i] =
00512                                         min((u16)targetPowerOfdm.tPow2x[i],
00513                                             minCtlPower);
00514                         }
00515                         break;
00516                 case CTL_2GHT20:
00517                         for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++) {
00518                                 targetPowerHt20.tPow2x[i] =
00519                                         min((u16)targetPowerHt20.tPow2x[i],
00520                                             minCtlPower);
00521                         }
00522                         break;
00523                 case CTL_11B_EXT:
00524                         targetPowerCckExt.tPow2x[0] =
00525                                 min((u16)targetPowerCckExt.tPow2x[0],
00526                                     minCtlPower);
00527                         break;
00528                 case CTL_11G_EXT:
00529                         targetPowerOfdmExt.tPow2x[0] =
00530                                 min((u16)targetPowerOfdmExt.tPow2x[0],
00531                                     minCtlPower);
00532                         break;
00533                 case CTL_2GHT40:
00534                         for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {
00535                                 targetPowerHt40.tPow2x[i] =
00536                                         min((u16)targetPowerHt40.tPow2x[i],
00537                                             minCtlPower);
00538                         }
00539                         break;
00540                 default:
00541                         break;
00542                 }
00543         }
00544 
00545         ratesArray[rate6mb] =
00546         ratesArray[rate9mb] =
00547         ratesArray[rate12mb] =
00548         ratesArray[rate18mb] =
00549         ratesArray[rate24mb] =
00550         targetPowerOfdm.tPow2x[0];
00551 
00552         ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1];
00553         ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2];
00554         ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3];
00555         ratesArray[rateXr] = targetPowerOfdm.tPow2x[0];
00556 
00557         for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++)
00558                 ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i];
00559 
00560         ratesArray[rate1l] = targetPowerCck.tPow2x[0];
00561         ratesArray[rate2s] = ratesArray[rate2l] = targetPowerCck.tPow2x[1];
00562         ratesArray[rate5_5s] = ratesArray[rate5_5l] = targetPowerCck.tPow2x[2];
00563         ratesArray[rate11s] = ratesArray[rate11l] = targetPowerCck.tPow2x[3];
00564 
00565         if (IS_CHAN_HT40(chan)) {
00566                 for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {
00567                         ratesArray[rateHt40_0 + i] =
00568                                 targetPowerHt40.tPow2x[i];
00569                 }
00570                 ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0];
00571                 ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0];
00572                 ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0];
00573                 ratesArray[rateExtCck] = targetPowerCckExt.tPow2x[0];
00574         }
00575 
00576 #undef CMP_TEST_GRP
00577 }
00578 
00579 static void ath9k_hw_4k_set_txpower(struct ath_hw *ah,
00580                                     struct ath9k_channel *chan,
00581                                     u16 cfgCtl,
00582                                     u8 twiceAntennaReduction,
00583                                     u8 twiceMaxRegulatoryPower,
00584                                     u8 powerLimit, int test)
00585 {
00586         struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
00587         struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
00588         struct modal_eep_4k_header *pModal = &pEepData->modalHeader;
00589         int16_t ratesArray[Ar5416RateSize];
00590         int16_t txPowerIndexOffset = 0;
00591         u8 ht40PowerIncForPdadc = 2;
00592         unsigned int i;
00593 
00594         memset(ratesArray, 0, sizeof(ratesArray));
00595 
00596         if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
00597             AR5416_EEP_MINOR_VER_2) {
00598                 ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
00599         }
00600 
00601         ath9k_hw_set_4k_power_per_rate_table(ah, chan,
00602                                              &ratesArray[0], cfgCtl,
00603                                              twiceAntennaReduction,
00604                                              twiceMaxRegulatoryPower,
00605                                              powerLimit);
00606 
00607         ath9k_hw_set_4k_power_cal_table(ah, chan, &txPowerIndexOffset);
00608 
00609         regulatory->max_power_level = 0;
00610         for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
00611                 ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
00612                 if (ratesArray[i] > MAX_RATE_POWER)
00613                         ratesArray[i] = MAX_RATE_POWER;
00614 
00615                 if (ratesArray[i] > regulatory->max_power_level)
00616                         regulatory->max_power_level = ratesArray[i];
00617         }
00618 
00619         if (test)
00620             return;
00621 
00622         /* Update regulatory */
00623         i = rate6mb;
00624         if (IS_CHAN_HT40(chan))
00625                 i = rateHt40_0;
00626         else if (IS_CHAN_HT20(chan))
00627                 i = rateHt20_0;
00628 
00629         regulatory->max_power_level = ratesArray[i];
00630 
00631         if (AR_SREV_9280_20_OR_LATER(ah)) {
00632                 for (i = 0; i < Ar5416RateSize; i++)
00633                         ratesArray[i] -= AR5416_PWR_TABLE_OFFSET_DB * 2;
00634         }
00635 
00636         ENABLE_REGWRITE_BUFFER(ah);
00637 
00638         /* OFDM power per rate */
00639         REG_WRITE(ah, AR_PHY_POWER_TX_RATE1,
00640                   ATH9K_POW_SM(ratesArray[rate18mb], 24)
00641                   | ATH9K_POW_SM(ratesArray[rate12mb], 16)
00642                   | ATH9K_POW_SM(ratesArray[rate9mb], 8)
00643                   | ATH9K_POW_SM(ratesArray[rate6mb], 0));
00644         REG_WRITE(ah, AR_PHY_POWER_TX_RATE2,
00645                   ATH9K_POW_SM(ratesArray[rate54mb], 24)
00646                   | ATH9K_POW_SM(ratesArray[rate48mb], 16)
00647                   | ATH9K_POW_SM(ratesArray[rate36mb], 8)
00648                   | ATH9K_POW_SM(ratesArray[rate24mb], 0));
00649 
00650         /* CCK power per rate */
00651         REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
00652                   ATH9K_POW_SM(ratesArray[rate2s], 24)
00653                   | ATH9K_POW_SM(ratesArray[rate2l], 16)
00654                   | ATH9K_POW_SM(ratesArray[rateXr], 8)
00655                   | ATH9K_POW_SM(ratesArray[rate1l], 0));
00656         REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
00657                   ATH9K_POW_SM(ratesArray[rate11s], 24)
00658                   | ATH9K_POW_SM(ratesArray[rate11l], 16)
00659                   | ATH9K_POW_SM(ratesArray[rate5_5s], 8)
00660                   | ATH9K_POW_SM(ratesArray[rate5_5l], 0));
00661 
00662         /* HT20 power per rate */
00663         REG_WRITE(ah, AR_PHY_POWER_TX_RATE5,
00664                   ATH9K_POW_SM(ratesArray[rateHt20_3], 24)
00665                   | ATH9K_POW_SM(ratesArray[rateHt20_2], 16)
00666                   | ATH9K_POW_SM(ratesArray[rateHt20_1], 8)
00667                   | ATH9K_POW_SM(ratesArray[rateHt20_0], 0));
00668         REG_WRITE(ah, AR_PHY_POWER_TX_RATE6,
00669                   ATH9K_POW_SM(ratesArray[rateHt20_7], 24)
00670                   | ATH9K_POW_SM(ratesArray[rateHt20_6], 16)
00671                   | ATH9K_POW_SM(ratesArray[rateHt20_5], 8)
00672                   | ATH9K_POW_SM(ratesArray[rateHt20_4], 0));
00673 
00674         /* HT40 power per rate */
00675         if (IS_CHAN_HT40(chan)) {
00676                 REG_WRITE(ah, AR_PHY_POWER_TX_RATE7,
00677                           ATH9K_POW_SM(ratesArray[rateHt40_3] +
00678                                        ht40PowerIncForPdadc, 24)
00679                           | ATH9K_POW_SM(ratesArray[rateHt40_2] +
00680                                          ht40PowerIncForPdadc, 16)
00681                           | ATH9K_POW_SM(ratesArray[rateHt40_1] +
00682                                          ht40PowerIncForPdadc, 8)
00683                           | ATH9K_POW_SM(ratesArray[rateHt40_0] +
00684                                          ht40PowerIncForPdadc, 0));
00685                 REG_WRITE(ah, AR_PHY_POWER_TX_RATE8,
00686                           ATH9K_POW_SM(ratesArray[rateHt40_7] +
00687                                        ht40PowerIncForPdadc, 24)
00688                           | ATH9K_POW_SM(ratesArray[rateHt40_6] +
00689                                          ht40PowerIncForPdadc, 16)
00690                           | ATH9K_POW_SM(ratesArray[rateHt40_5] +
00691                                          ht40PowerIncForPdadc, 8)
00692                           | ATH9K_POW_SM(ratesArray[rateHt40_4] +
00693                                          ht40PowerIncForPdadc, 0));
00694                 REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
00695                           ATH9K_POW_SM(ratesArray[rateExtOfdm], 24)
00696                           | ATH9K_POW_SM(ratesArray[rateExtCck], 16)
00697                           | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
00698                           | ATH9K_POW_SM(ratesArray[rateDupCck], 0));
00699         }
00700 
00701         REGWRITE_BUFFER_FLUSH(ah);
00702 }
00703 
00704 static void ath9k_hw_4k_set_addac(struct ath_hw *ah,
00705                                   struct ath9k_channel *chan __unused)
00706 {
00707         struct modal_eep_4k_header *pModal;
00708         struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
00709         u8 biaslevel;
00710 
00711         if (ah->hw_version.macVersion != AR_SREV_VERSION_9160)
00712                 return;
00713 
00714         if (ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_MINOR_VER_7)
00715                 return;
00716 
00717         pModal = &eep->modalHeader;
00718 
00719         if (pModal->xpaBiasLvl != 0xff) {
00720                 biaslevel = pModal->xpaBiasLvl;
00721                 INI_RA(&ah->iniAddac, 7, 1) =
00722                   (INI_RA(&ah->iniAddac, 7, 1) & (~0x18)) | biaslevel << 3;
00723         }
00724 }
00725 
00726 static void ath9k_hw_4k_set_gain(struct ath_hw *ah,
00727                                  struct modal_eep_4k_header *pModal,
00728                                  struct ar5416_eeprom_4k *eep,
00729                                  u8 txRxAttenLocal)
00730 {
00731         REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0,
00732                   pModal->antCtrlChain[0]);
00733 
00734         REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0),
00735                   (REG_READ(ah, AR_PHY_TIMING_CTRL4(0)) &
00736                    ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF |
00737                      AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) |
00738                   SM(pModal->iqCalICh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) |
00739                   SM(pModal->iqCalQCh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF));
00740 
00741         if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
00742             AR5416_EEP_MINOR_VER_3) {
00743                 txRxAttenLocal = pModal->txRxAttenCh[0];
00744 
00745                 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ,
00746                               AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, pModal->bswMargin[0]);
00747                 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ,
00748                               AR_PHY_GAIN_2GHZ_XATTEN1_DB, pModal->bswAtten[0]);
00749                 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ,
00750                               AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,
00751                               pModal->xatten2Margin[0]);
00752                 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ,
00753                               AR_PHY_GAIN_2GHZ_XATTEN2_DB, pModal->xatten2Db[0]);
00754 
00755                 /* Set the block 1 value to block 0 value */
00756                 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000,
00757                               AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN,
00758                               pModal->bswMargin[0]);
00759                 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000,
00760                               AR_PHY_GAIN_2GHZ_XATTEN1_DB, pModal->bswAtten[0]);
00761                 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000,
00762                               AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,
00763                               pModal->xatten2Margin[0]);
00764                 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000,
00765                               AR_PHY_GAIN_2GHZ_XATTEN2_DB,
00766                               pModal->xatten2Db[0]);
00767         }
00768 
00769         REG_RMW_FIELD(ah, AR_PHY_RXGAIN,
00770                       AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal);
00771         REG_RMW_FIELD(ah, AR_PHY_RXGAIN,
00772                       AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[0]);
00773 
00774         REG_RMW_FIELD(ah, AR_PHY_RXGAIN + 0x1000,
00775                       AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal);
00776         REG_RMW_FIELD(ah, AR_PHY_RXGAIN + 0x1000,
00777                       AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[0]);
00778 }
00779 
00780 /*
00781  * Read EEPROM header info and program the device for correct operation
00782  * given the channel value.
00783  */
00784 static void ath9k_hw_4k_set_board_values(struct ath_hw *ah,
00785                                          struct ath9k_channel *chan)
00786 {
00787         struct modal_eep_4k_header *pModal;
00788         struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
00789         struct base_eep_header_4k *pBase = &eep->baseEepHeader;
00790         u8 txRxAttenLocal;
00791         u8 ob[5], db1[5], db2[5];
00792         u8 ant_div_control1, ant_div_control2;
00793         u32 regVal;
00794 
00795         pModal = &eep->modalHeader;
00796         txRxAttenLocal = 23;
00797 
00798         REG_WRITE(ah, AR_PHY_SWITCH_COM, pModal->antCtrlCommon);
00799 
00800         /* Single chain for 4K EEPROM*/
00801         ath9k_hw_4k_set_gain(ah, pModal, eep, txRxAttenLocal);
00802 
00803         /* Initialize Ant Diversity settings from EEPROM */
00804         if (pModal->version >= 3) {
00805                 ant_div_control1 = pModal->antdiv_ctl1;
00806                 ant_div_control2 = pModal->antdiv_ctl2;
00807 
00808                 regVal = REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL);
00809                 regVal &= (~(AR_PHY_9285_ANT_DIV_CTL_ALL));
00810 
00811                 regVal |= SM(ant_div_control1,
00812                              AR_PHY_9285_ANT_DIV_CTL);
00813                 regVal |= SM(ant_div_control2,
00814                              AR_PHY_9285_ANT_DIV_ALT_LNACONF);
00815                 regVal |= SM((ant_div_control2 >> 2),
00816                              AR_PHY_9285_ANT_DIV_MAIN_LNACONF);
00817                 regVal |= SM((ant_div_control1 >> 1),
00818                              AR_PHY_9285_ANT_DIV_ALT_GAINTB);
00819                 regVal |= SM((ant_div_control1 >> 2),
00820                              AR_PHY_9285_ANT_DIV_MAIN_GAINTB);
00821 
00822 
00823                 REG_WRITE(ah, AR_PHY_MULTICHAIN_GAIN_CTL, regVal);
00824                 regVal = REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL);
00825                 regVal = REG_READ(ah, AR_PHY_CCK_DETECT);
00826                 regVal &= (~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV);
00827                 regVal |= SM((ant_div_control1 >> 3),
00828                              AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV);
00829 
00830                 REG_WRITE(ah, AR_PHY_CCK_DETECT, regVal);
00831                 regVal = REG_READ(ah, AR_PHY_CCK_DETECT);
00832         }
00833 
00834         if (pModal->version >= 2) {
00835                 ob[0] = pModal->ob_0;
00836                 ob[1] = pModal->ob_1;
00837                 ob[2] = pModal->ob_2;
00838                 ob[3] = pModal->ob_3;
00839                 ob[4] = pModal->ob_4;
00840 
00841                 db1[0] = pModal->db1_0;
00842                 db1[1] = pModal->db1_1;
00843                 db1[2] = pModal->db1_2;
00844                 db1[3] = pModal->db1_3;
00845                 db1[4] = pModal->db1_4;
00846 
00847                 db2[0] = pModal->db2_0;
00848                 db2[1] = pModal->db2_1;
00849                 db2[2] = pModal->db2_2;
00850                 db2[3] = pModal->db2_3;
00851                 db2[4] = pModal->db2_4;
00852         } else if (pModal->version == 1) {
00853                 ob[0] = pModal->ob_0;
00854                 ob[1] = ob[2] = ob[3] = ob[4] = pModal->ob_1;
00855                 db1[0] = pModal->db1_0;
00856                 db1[1] = db1[2] = db1[3] = db1[4] = pModal->db1_1;
00857                 db2[0] = pModal->db2_0;
00858                 db2[1] = db2[2] = db2[3] = db2[4] = pModal->db2_1;
00859         } else {
00860                 int i;
00861 
00862                 for (i = 0; i < 5; i++) {
00863                         ob[i] = pModal->ob_0;
00864                         db1[i] = pModal->db1_0;
00865                         db2[i] = pModal->db1_0;
00866                 }
00867         }
00868 
00869         if (AR_SREV_9271(ah)) {
00870                 ath9k_hw_analog_shift_rmw(ah,
00871                                           AR9285_AN_RF2G3,
00872                                           AR9271_AN_RF2G3_OB_cck,
00873                                           AR9271_AN_RF2G3_OB_cck_S,
00874                                           ob[0]);
00875                 ath9k_hw_analog_shift_rmw(ah,
00876                                           AR9285_AN_RF2G3,
00877                                           AR9271_AN_RF2G3_OB_psk,
00878                                           AR9271_AN_RF2G3_OB_psk_S,
00879                                           ob[1]);
00880                 ath9k_hw_analog_shift_rmw(ah,
00881                                           AR9285_AN_RF2G3,
00882                                           AR9271_AN_RF2G3_OB_qam,
00883                                           AR9271_AN_RF2G3_OB_qam_S,
00884                                           ob[2]);
00885                 ath9k_hw_analog_shift_rmw(ah,
00886                                           AR9285_AN_RF2G3,
00887                                           AR9271_AN_RF2G3_DB_1,
00888                                           AR9271_AN_RF2G3_DB_1_S,
00889                                           db1[0]);
00890                 ath9k_hw_analog_shift_rmw(ah,
00891                                           AR9285_AN_RF2G4,
00892                                           AR9271_AN_RF2G4_DB_2,
00893                                           AR9271_AN_RF2G4_DB_2_S,
00894                                           db2[0]);
00895         } else {
00896                 ath9k_hw_analog_shift_rmw(ah,
00897                                           AR9285_AN_RF2G3,
00898                                           AR9285_AN_RF2G3_OB_0,
00899                                           AR9285_AN_RF2G3_OB_0_S,
00900                                           ob[0]);
00901                 ath9k_hw_analog_shift_rmw(ah,
00902                                           AR9285_AN_RF2G3,
00903                                           AR9285_AN_RF2G3_OB_1,
00904                                           AR9285_AN_RF2G3_OB_1_S,
00905                                           ob[1]);
00906                 ath9k_hw_analog_shift_rmw(ah,
00907                                           AR9285_AN_RF2G3,
00908                                           AR9285_AN_RF2G3_OB_2,
00909                                           AR9285_AN_RF2G3_OB_2_S,
00910                                           ob[2]);
00911                 ath9k_hw_analog_shift_rmw(ah,
00912                                           AR9285_AN_RF2G3,
00913                                           AR9285_AN_RF2G3_OB_3,
00914                                           AR9285_AN_RF2G3_OB_3_S,
00915                                           ob[3]);
00916                 ath9k_hw_analog_shift_rmw(ah,
00917                                           AR9285_AN_RF2G3,
00918                                           AR9285_AN_RF2G3_OB_4,
00919                                           AR9285_AN_RF2G3_OB_4_S,
00920                                           ob[4]);
00921 
00922                 ath9k_hw_analog_shift_rmw(ah,
00923                                           AR9285_AN_RF2G3,
00924                                           AR9285_AN_RF2G3_DB1_0,
00925                                           AR9285_AN_RF2G3_DB1_0_S,
00926                                           db1[0]);
00927                 ath9k_hw_analog_shift_rmw(ah,
00928                                           AR9285_AN_RF2G3,
00929                                           AR9285_AN_RF2G3_DB1_1,
00930                                           AR9285_AN_RF2G3_DB1_1_S,
00931                                           db1[1]);
00932                 ath9k_hw_analog_shift_rmw(ah,
00933                                           AR9285_AN_RF2G3,
00934                                           AR9285_AN_RF2G3_DB1_2,
00935                                           AR9285_AN_RF2G3_DB1_2_S,
00936                                           db1[2]);
00937                 ath9k_hw_analog_shift_rmw(ah,
00938                                           AR9285_AN_RF2G4,
00939                                           AR9285_AN_RF2G4_DB1_3,
00940                                           AR9285_AN_RF2G4_DB1_3_S,
00941                                           db1[3]);
00942                 ath9k_hw_analog_shift_rmw(ah,
00943                                           AR9285_AN_RF2G4,
00944                                           AR9285_AN_RF2G4_DB1_4,
00945                                           AR9285_AN_RF2G4_DB1_4_S, db1[4]);
00946 
00947                 ath9k_hw_analog_shift_rmw(ah,
00948                                           AR9285_AN_RF2G4,
00949                                           AR9285_AN_RF2G4_DB2_0,
00950                                           AR9285_AN_RF2G4_DB2_0_S,
00951                                           db2[0]);
00952                 ath9k_hw_analog_shift_rmw(ah,
00953                                           AR9285_AN_RF2G4,
00954                                           AR9285_AN_RF2G4_DB2_1,
00955                                           AR9285_AN_RF2G4_DB2_1_S,
00956                                           db2[1]);
00957                 ath9k_hw_analog_shift_rmw(ah,
00958                                           AR9285_AN_RF2G4,
00959                                           AR9285_AN_RF2G4_DB2_2,
00960                                           AR9285_AN_RF2G4_DB2_2_S,
00961                                           db2[2]);
00962                 ath9k_hw_analog_shift_rmw(ah,
00963                                           AR9285_AN_RF2G4,
00964                                           AR9285_AN_RF2G4_DB2_3,
00965                                           AR9285_AN_RF2G4_DB2_3_S,
00966                                           db2[3]);
00967                 ath9k_hw_analog_shift_rmw(ah,
00968                                           AR9285_AN_RF2G4,
00969                                           AR9285_AN_RF2G4_DB2_4,
00970                                           AR9285_AN_RF2G4_DB2_4_S,
00971                                           db2[4]);
00972         }
00973 
00974 
00975         REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH,
00976                       pModal->switchSettling);
00977         REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC,
00978                       pModal->adcDesiredSize);
00979 
00980         REG_WRITE(ah, AR_PHY_RF_CTL4,
00981                   SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF) |
00982                   SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAB_OFF) |
00983                   SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAA_ON)  |
00984                   SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAB_ON));
00985 
00986         REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON,
00987                       pModal->txEndToRxOn);
00988 
00989         if (AR_SREV_9271_10(ah))
00990                 REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON,
00991                               pModal->txEndToRxOn);
00992         REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62,
00993                       pModal->thresh62);
00994         REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, AR_PHY_EXT_CCA0_THRESH62,
00995                       pModal->thresh62);
00996 
00997         if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
00998                                                 AR5416_EEP_MINOR_VER_2) {
00999                 REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_DATA_START,
01000                               pModal->txFrameToDataStart);
01001                 REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_PA_ON,
01002                               pModal->txFrameToPaOn);
01003         }
01004 
01005         if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
01006                                                 AR5416_EEP_MINOR_VER_3) {
01007                 if (IS_CHAN_HT40(chan))
01008                         REG_RMW_FIELD(ah, AR_PHY_SETTLING,
01009                                       AR_PHY_SETTLING_SWITCH,
01010                                       pModal->swSettleHt40);
01011         }
01012         if (AR_SREV_9271(ah) || AR_SREV_9285(ah)) {
01013                 u8 bb_desired_scale = (pModal->bb_scale_smrt_antenna &
01014                                 EEP_4K_BB_DESIRED_SCALE_MASK);
01015                 if ((pBase->txGainType == 0) && (bb_desired_scale != 0)) {
01016                         u32 pwrctrl, mask, clr;
01017 
01018                         mask = BIT(0)|BIT(5)|BIT(10)|BIT(15)|BIT(20)|BIT(25);
01019                         pwrctrl = mask * bb_desired_scale;
01020                         clr = mask * 0x1f;
01021                         REG_RMW(ah, AR_PHY_TX_PWRCTRL8, pwrctrl, clr);
01022                         REG_RMW(ah, AR_PHY_TX_PWRCTRL10, pwrctrl, clr);
01023                         REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL12, pwrctrl, clr);
01024 
01025                         mask = BIT(0)|BIT(5)|BIT(15);
01026                         pwrctrl = mask * bb_desired_scale;
01027                         clr = mask * 0x1f;
01028                         REG_RMW(ah, AR_PHY_TX_PWRCTRL9, pwrctrl, clr);
01029 
01030                         mask = BIT(0)|BIT(5);
01031                         pwrctrl = mask * bb_desired_scale;
01032                         clr = mask * 0x1f;
01033                         REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL11, pwrctrl, clr);
01034                         REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL13, pwrctrl, clr);
01035                 }
01036         }
01037 }
01038 
01039 static u16 ath9k_hw_4k_get_spur_channel(struct ath_hw *ah, u16 i, int is2GHz)
01040 {
01041 #define EEP_MAP4K_SPURCHAN \
01042         (ah->eeprom.map4k.modalHeader.spurChans[i].spurChan)
01043 
01044         u16 spur_val = AR_NO_SPUR;
01045 
01046         DBG2("ath9k: "
01047                 "Getting spur idx:%d is2Ghz:%d val:%x\n",
01048                 i, is2GHz, ah->config.spurchans[i][is2GHz]);
01049 
01050         switch (ah->config.spurmode) {
01051         case SPUR_DISABLE:
01052                 break;
01053         case SPUR_ENABLE_IOCTL:
01054                 spur_val = ah->config.spurchans[i][is2GHz];
01055                 DBG2("ath9k: "
01056                         "Getting spur val from new loc. %d\n", spur_val);
01057                 break;
01058         case SPUR_ENABLE_EEPROM:
01059                 spur_val = EEP_MAP4K_SPURCHAN;
01060                 break;
01061         }
01062 
01063         return spur_val;
01064 
01065 #undef EEP_MAP4K_SPURCHAN
01066 }
01067 
01068 const struct eeprom_ops eep_4k_ops = {
01069         .check_eeprom           = ath9k_hw_4k_check_eeprom,
01070         .get_eeprom             = ath9k_hw_4k_get_eeprom,
01071         .fill_eeprom            = ath9k_hw_4k_fill_eeprom,
01072         .get_eeprom_ver         = ath9k_hw_4k_get_eeprom_ver,
01073         .get_eeprom_rev         = ath9k_hw_4k_get_eeprom_rev,
01074         .set_board_values       = ath9k_hw_4k_set_board_values,
01075         .set_addac              = ath9k_hw_4k_set_addac,
01076         .set_txpower            = ath9k_hw_4k_set_txpower,
01077         .get_spur_channel       = ath9k_hw_4k_get_spur_channel
01078 };