iPXE
ath9k_eeprom_def.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 void ath9k_get_txgain_index(struct ath_hw *ah,
00026                 struct ath9k_channel *chan,
00027                 struct calDataPerFreqOpLoop *rawDatasetOpLoop,
00028                 u8 *calChans,  u16 availPiers, u8 *pwr, u8 *pcdacIdx)
00029 {
00030         u8 pcdac, i = 0;
00031         u16 idxL = 0, idxR = 0, numPiers;
00032         int match;
00033         struct chan_centers centers;
00034 
00035         ath9k_hw_get_channel_centers(ah, chan, &centers);
00036 
00037         for (numPiers = 0; numPiers < availPiers; numPiers++)
00038                 if (calChans[numPiers] == AR5416_BCHAN_UNUSED)
00039                         break;
00040 
00041         match = ath9k_hw_get_lower_upper_index(
00042                         (u8)FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan)),
00043                         calChans, numPiers, &idxL, &idxR);
00044         if (match) {
00045                 pcdac = rawDatasetOpLoop[idxL].pcdac[0][0];
00046                 *pwr = rawDatasetOpLoop[idxL].pwrPdg[0][0];
00047         } else {
00048                 pcdac = rawDatasetOpLoop[idxR].pcdac[0][0];
00049                 *pwr = (rawDatasetOpLoop[idxL].pwrPdg[0][0] +
00050                                 rawDatasetOpLoop[idxR].pwrPdg[0][0])/2;
00051         }
00052 
00053         while (pcdac > ah->originalGain[i] &&
00054                         i < (AR9280_TX_GAIN_TABLE_SIZE - 1))
00055                 i++;
00056 
00057         *pcdacIdx = i;
00058 }
00059 
00060 static void ath9k_olc_get_pdadcs(struct ath_hw *ah,
00061                                 u32 initTxGain,
00062                                 int txPower,
00063                                 u8 *pPDADCValues)
00064 {
00065         u32 i;
00066         u32 offset;
00067 
00068         REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL6_0,
00069                         AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3);
00070         REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL6_1,
00071                         AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3);
00072 
00073         REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL7,
00074                         AR_PHY_TX_PWRCTRL_INIT_TX_GAIN, initTxGain);
00075 
00076         offset = txPower;
00077         for (i = 0; i < AR5416_NUM_PDADC_VALUES; i++)
00078                 if (i < offset)
00079                         pPDADCValues[i] = 0x0;
00080                 else
00081                         pPDADCValues[i] = 0xFF;
00082 }
00083 
00084 static int ath9k_hw_def_get_eeprom_ver(struct ath_hw *ah)
00085 {
00086         return ((ah->eeprom.def.baseEepHeader.version >> 12) & 0xF);
00087 }
00088 
00089 static int ath9k_hw_def_get_eeprom_rev(struct ath_hw *ah)
00090 {
00091         return ((ah->eeprom.def.baseEepHeader.version) & 0xFFF);
00092 }
00093 
00094 #define SIZE_EEPROM_DEF (sizeof(struct ar5416_eeprom_def) / sizeof(u16))
00095 
00096 static int __ath9k_hw_def_fill_eeprom(struct ath_hw *ah)
00097 {
00098         struct ath_common *common = ath9k_hw_common(ah);
00099         u16 *eep_data = (u16 *)&ah->eeprom.def;
00100         unsigned int addr;
00101         int ar5416_eep_start_loc = 0x100;
00102 
00103         for (addr = 0; addr < SIZE_EEPROM_DEF; addr++) {
00104                 if (!ath9k_hw_nvram_read(common, addr + ar5416_eep_start_loc,
00105                                          eep_data)) {
00106                         DBG("ath9k: "
00107                                 "Unable to read eeprom region\n");
00108                         return 0;
00109                 }
00110                 eep_data++;
00111         }
00112         return 1;
00113 }
00114 
00115 static int __ath9k_hw_usb_def_fill_eeprom(struct ath_hw *ah)
00116 {
00117         u16 *eep_data = (u16 *)&ah->eeprom.def;
00118 
00119         ath9k_hw_usb_gen_fill_eeprom(ah, eep_data,
00120                                      0x100, SIZE_EEPROM_DEF);
00121         return 1;
00122 }
00123 
00124 static int ath9k_hw_def_fill_eeprom(struct ath_hw *ah)
00125 {
00126         struct ath_common *common = ath9k_hw_common(ah);
00127 
00128         if (!ath9k_hw_use_flash(ah)) {
00129                 DBG2("ath9k: "
00130                         "Reading from EEPROM, not flash\n");
00131         }
00132 
00133         if (common->bus_ops->ath_bus_type == ATH_USB)
00134                 return __ath9k_hw_usb_def_fill_eeprom(ah);
00135         else
00136                 return __ath9k_hw_def_fill_eeprom(ah);
00137 }
00138 
00139 #undef SIZE_EEPROM_DEF
00140 
00141 static int ath9k_hw_def_check_eeprom(struct ath_hw *ah)
00142 {
00143         struct ar5416_eeprom_def *eep =
00144                 (struct ar5416_eeprom_def *) &ah->eeprom.def;
00145         struct ath_common *common = ath9k_hw_common(ah);
00146         u16 *eepdata, temp, magic, magic2;
00147         u32 sum = 0, el;
00148         int need_swap = 0;
00149         unsigned int i, addr, size;
00150 
00151         if (!ath9k_hw_nvram_read(common, AR5416_EEPROM_MAGIC_OFFSET, &magic)) {
00152                 DBG("ath9k: Reading Magic # failed\n");
00153                 return 0;
00154         }
00155 
00156         if (!ath9k_hw_use_flash(ah)) {
00157                 DBG2("ath9k: "
00158                         "Read Magic = 0x%04X\n", magic);
00159 
00160                 if (magic != AR5416_EEPROM_MAGIC) {
00161                         magic2 = swab16(magic);
00162 
00163                         if (magic2 == AR5416_EEPROM_MAGIC) {
00164                                 size = sizeof(struct ar5416_eeprom_def);
00165                                 need_swap = 1;
00166                                 eepdata = (u16 *) (&ah->eeprom);
00167 
00168                                 for (addr = 0; addr < size / sizeof(u16); addr++) {
00169                                         temp = swab16(*eepdata);
00170                                         *eepdata = temp;
00171                                         eepdata++;
00172                                 }
00173                         } else {
00174                                 DBG("ath9k: "
00175                                         "Invalid EEPROM Magic. Endianness mismatch.\n");
00176                                 return -EINVAL;
00177                         }
00178                 }
00179         }
00180 
00181         DBG2("ath9k: need_swap = %s.\n",
00182                 need_swap ? "True" : "False");
00183 
00184         if (need_swap)
00185                 el = swab16(ah->eeprom.def.baseEepHeader.length);
00186         else
00187                 el = ah->eeprom.def.baseEepHeader.length;
00188 
00189         if (el > sizeof(struct ar5416_eeprom_def))
00190                 el = sizeof(struct ar5416_eeprom_def) / sizeof(u16);
00191         else
00192                 el = el / sizeof(u16);
00193 
00194         eepdata = (u16 *)(&ah->eeprom);
00195 
00196         for (i = 0; i < el; i++)
00197                 sum ^= *eepdata++;
00198 
00199         if (need_swap) {
00200                 u32 integer, j;
00201                 u16 word;
00202 
00203                 DBG("ath9k: "
00204                         "EEPROM Endianness is not native.. Changing.\n");
00205 
00206                 word = swab16(eep->baseEepHeader.length);
00207                 eep->baseEepHeader.length = word;
00208 
00209                 word = swab16(eep->baseEepHeader.checksum);
00210                 eep->baseEepHeader.checksum = word;
00211 
00212                 word = swab16(eep->baseEepHeader.version);
00213                 eep->baseEepHeader.version = word;
00214 
00215                 word = swab16(eep->baseEepHeader.regDmn[0]);
00216                 eep->baseEepHeader.regDmn[0] = word;
00217 
00218                 word = swab16(eep->baseEepHeader.regDmn[1]);
00219                 eep->baseEepHeader.regDmn[1] = word;
00220 
00221                 word = swab16(eep->baseEepHeader.rfSilent);
00222                 eep->baseEepHeader.rfSilent = word;
00223 
00224                 word = swab16(eep->baseEepHeader.blueToothOptions);
00225                 eep->baseEepHeader.blueToothOptions = word;
00226 
00227                 word = swab16(eep->baseEepHeader.deviceCap);
00228                 eep->baseEepHeader.deviceCap = word;
00229 
00230                 for (j = 0; j < ARRAY_SIZE(eep->modalHeader); j++) {
00231                         struct modal_eep_header *pModal =
00232                                 &eep->modalHeader[j];
00233                         integer = swab32(pModal->antCtrlCommon);
00234                         pModal->antCtrlCommon = integer;
00235 
00236                         for (i = 0; i < AR5416_MAX_CHAINS; i++) {
00237                                 integer = swab32(pModal->antCtrlChain[i]);
00238                                 pModal->antCtrlChain[i] = integer;
00239                         }
00240                         for (i = 0; i < 3; i++) {
00241                                 word = swab16(pModal->xpaBiasLvlFreq[i]);
00242                                 pModal->xpaBiasLvlFreq[i] = word;
00243                         }
00244 
00245                         for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
00246                                 word = swab16(pModal->spurChans[i].spurChan);
00247                                 pModal->spurChans[i].spurChan = word;
00248                         }
00249                 }
00250         }
00251 
00252         if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER ||
00253             ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) {
00254                 DBG("ath9k: Bad EEPROM checksum 0x%x or revision 0x%04x\n",
00255                         sum, ah->eep_ops->get_eeprom_ver(ah));
00256                 return -EINVAL;
00257         }
00258 
00259         /* Enable fixup for AR_AN_TOP2 if necessary */
00260         if ((ah->hw_version.devid == AR9280_DEVID_PCI) &&
00261             ((eep->baseEepHeader.version & 0xff) > 0x0a) &&
00262             (eep->baseEepHeader.pwdclkind == 0))
00263                 ah->need_an_top2_fixup = 1;
00264 
00265         if ((common->bus_ops->ath_bus_type == ATH_USB) &&
00266             (AR_SREV_9280(ah)))
00267                 eep->modalHeader[0].xpaBiasLvl = 0;
00268 
00269         return 0;
00270 }
00271 
00272 static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah,
00273                                    enum eeprom_param param)
00274 {
00275         struct ar5416_eeprom_def *eep = &ah->eeprom.def;
00276         struct modal_eep_header *pModal = eep->modalHeader;
00277         struct base_eep_header *pBase = &eep->baseEepHeader;
00278 
00279         switch (param) {
00280         case EEP_NFTHRESH_5:
00281                 return pModal[0].noiseFloorThreshCh[0];
00282         case EEP_NFTHRESH_2:
00283                 return pModal[1].noiseFloorThreshCh[0];
00284         case EEP_MAC_LSW:
00285                 return pBase->macAddr[0] << 8 | pBase->macAddr[1];
00286         case EEP_MAC_MID:
00287                 return pBase->macAddr[2] << 8 | pBase->macAddr[3];
00288         case EEP_MAC_MSW:
00289                 return pBase->macAddr[4] << 8 | pBase->macAddr[5];
00290         case EEP_REG_0:
00291                 return pBase->regDmn[0];
00292         case EEP_REG_1:
00293                 return pBase->regDmn[1];
00294         case EEP_OP_CAP:
00295                 return pBase->deviceCap;
00296         case EEP_OP_MODE:
00297                 return pBase->opCapFlags;
00298         case EEP_RF_SILENT:
00299                 return pBase->rfSilent;
00300         case EEP_OB_5:
00301                 return pModal[0].ob;
00302         case EEP_DB_5:
00303                 return pModal[0].db;
00304         case EEP_OB_2:
00305                 return pModal[1].ob;
00306         case EEP_DB_2:
00307                 return pModal[1].db;
00308         case EEP_MINOR_REV:
00309                 return AR5416_VER_MASK;
00310         case EEP_TX_MASK:
00311                 return pBase->txMask;
00312         case EEP_RX_MASK:
00313                 return pBase->rxMask;
00314         case EEP_FSTCLK_5G:
00315                 return pBase->fastClk5g;
00316         case EEP_RXGAIN_TYPE:
00317                 return pBase->rxGainType;
00318         case EEP_TXGAIN_TYPE:
00319                 return pBase->txGainType;
00320         case EEP_OL_PWRCTRL:
00321                 if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19)
00322                         return pBase->openLoopPwrCntl ? 1 : 0;
00323                 else
00324                         return 0;
00325         case EEP_RC_CHAIN_MASK:
00326                 if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19)
00327                         return pBase->rcChainMask;
00328                 else
00329                         return 0;
00330         case EEP_DAC_HPWR_5G:
00331                 if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_20)
00332                         return pBase->dacHiPwrMode_5G;
00333                 else
00334                         return 0;
00335         case EEP_FRAC_N_5G:
00336                 if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_22)
00337                         return pBase->frac_n_5g;
00338                 else
00339                         return 0;
00340         case EEP_PWR_TABLE_OFFSET:
00341                 if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_21)
00342                         return pBase->pwr_table_offset;
00343                 else
00344                         return AR5416_PWR_TABLE_OFFSET_DB;
00345         default:
00346                 return 0;
00347         }
00348 }
00349 
00350 static void ath9k_hw_def_set_gain(struct ath_hw *ah,
00351                                   struct modal_eep_header *pModal,
00352                                   struct ar5416_eeprom_def *eep,
00353                                   u8 txRxAttenLocal, int regChainOffset, int i)
00354 {
00355         if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_3) {
00356                 txRxAttenLocal = pModal->txRxAttenCh[i];
00357 
00358                 if (AR_SREV_9280_20_OR_LATER(ah)) {
00359                         REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
00360                               AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN,
00361                               pModal->bswMargin[i]);
00362                         REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
00363                               AR_PHY_GAIN_2GHZ_XATTEN1_DB,
00364                               pModal->bswAtten[i]);
00365                         REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
00366                               AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,
00367                               pModal->xatten2Margin[i]);
00368                         REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
00369                               AR_PHY_GAIN_2GHZ_XATTEN2_DB,
00370                               pModal->xatten2Db[i]);
00371                 } else {
00372                         REG_WRITE(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
00373                           (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) &
00374                            ~AR_PHY_GAIN_2GHZ_BSW_MARGIN)
00375                           | SM(pModal-> bswMargin[i],
00376                                AR_PHY_GAIN_2GHZ_BSW_MARGIN));
00377                         REG_WRITE(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
00378                           (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) &
00379                            ~AR_PHY_GAIN_2GHZ_BSW_ATTEN)
00380                           | SM(pModal->bswAtten[i],
00381                                AR_PHY_GAIN_2GHZ_BSW_ATTEN));
00382                 }
00383         }
00384 
00385         if (AR_SREV_9280_20_OR_LATER(ah)) {
00386                 REG_RMW_FIELD(ah,
00387                       AR_PHY_RXGAIN + regChainOffset,
00388                       AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal);
00389                 REG_RMW_FIELD(ah,
00390                       AR_PHY_RXGAIN + regChainOffset,
00391                       AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[i]);
00392         } else {
00393                 REG_WRITE(ah,
00394                           AR_PHY_RXGAIN + regChainOffset,
00395                           (REG_READ(ah, AR_PHY_RXGAIN + regChainOffset) &
00396                            ~AR_PHY_RXGAIN_TXRX_ATTEN)
00397                           | SM(txRxAttenLocal, AR_PHY_RXGAIN_TXRX_ATTEN));
00398                 REG_WRITE(ah,
00399                           AR_PHY_GAIN_2GHZ + regChainOffset,
00400                           (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) &
00401                            ~AR_PHY_GAIN_2GHZ_RXTX_MARGIN) |
00402                           SM(pModal->rxTxMarginCh[i], AR_PHY_GAIN_2GHZ_RXTX_MARGIN));
00403         }
00404 }
00405 
00406 static void ath9k_hw_def_set_board_values(struct ath_hw *ah,
00407                                           struct ath9k_channel *chan)
00408 {
00409         struct modal_eep_header *pModal;
00410         struct ar5416_eeprom_def *eep = &ah->eeprom.def;
00411         int i, regChainOffset;
00412         u8 txRxAttenLocal;
00413 
00414         pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
00415         txRxAttenLocal = IS_CHAN_2GHZ(chan) ? 23 : 44;
00416 
00417         REG_WRITE(ah, AR_PHY_SWITCH_COM, pModal->antCtrlCommon & 0xffff);
00418 
00419         for (i = 0; i < AR5416_MAX_CHAINS; i++) {
00420                 if (AR_SREV_9280(ah)) {
00421                         if (i >= 2)
00422                                 break;
00423                 }
00424 
00425                 if (AR_SREV_5416_20_OR_LATER(ah) &&
00426                     (ah->rxchainmask == 5 || ah->txchainmask == 5) && (i != 0))
00427                         regChainOffset = (i == 1) ? 0x2000 : 0x1000;
00428                 else
00429                         regChainOffset = i * 0x1000;
00430 
00431                 REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset,
00432                           pModal->antCtrlChain[i]);
00433 
00434                 REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset,
00435                           (REG_READ(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset) &
00436                            ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF |
00437                              AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) |
00438                           SM(pModal->iqCalICh[i],
00439                              AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) |
00440                           SM(pModal->iqCalQCh[i],
00441                              AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF));
00442 
00443                 if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah))
00444                         ath9k_hw_def_set_gain(ah, pModal, eep, txRxAttenLocal,
00445                                               regChainOffset, i);
00446         }
00447 
00448         if (AR_SREV_9280_20_OR_LATER(ah)) {
00449                 if (IS_CHAN_2GHZ(chan)) {
00450                         ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0,
00451                                                   AR_AN_RF2G1_CH0_OB,
00452                                                   AR_AN_RF2G1_CH0_OB_S,
00453                                                   pModal->ob);
00454                         ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0,
00455                                                   AR_AN_RF2G1_CH0_DB,
00456                                                   AR_AN_RF2G1_CH0_DB_S,
00457                                                   pModal->db);
00458                         ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH1,
00459                                                   AR_AN_RF2G1_CH1_OB,
00460                                                   AR_AN_RF2G1_CH1_OB_S,
00461                                                   pModal->ob_ch1);
00462                         ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH1,
00463                                                   AR_AN_RF2G1_CH1_DB,
00464                                                   AR_AN_RF2G1_CH1_DB_S,
00465                                                   pModal->db_ch1);
00466                 } else {
00467                         ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH0,
00468                                                   AR_AN_RF5G1_CH0_OB5,
00469                                                   AR_AN_RF5G1_CH0_OB5_S,
00470                                                   pModal->ob);
00471                         ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH0,
00472                                                   AR_AN_RF5G1_CH0_DB5,
00473                                                   AR_AN_RF5G1_CH0_DB5_S,
00474                                                   pModal->db);
00475                         ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH1,
00476                                                   AR_AN_RF5G1_CH1_OB5,
00477                                                   AR_AN_RF5G1_CH1_OB5_S,
00478                                                   pModal->ob_ch1);
00479                         ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH1,
00480                                                   AR_AN_RF5G1_CH1_DB5,
00481                                                   AR_AN_RF5G1_CH1_DB5_S,
00482                                                   pModal->db_ch1);
00483                 }
00484                 ath9k_hw_analog_shift_rmw(ah, AR_AN_TOP2,
00485                                           AR_AN_TOP2_XPABIAS_LVL,
00486                                           AR_AN_TOP2_XPABIAS_LVL_S,
00487                                           pModal->xpaBiasLvl);
00488                 ath9k_hw_analog_shift_rmw(ah, AR_AN_TOP2,
00489                                           AR_AN_TOP2_LOCALBIAS,
00490                                           AR_AN_TOP2_LOCALBIAS_S,
00491                                           !!(pModal->lna_ctl &
00492                                              LNA_CTL_LOCAL_BIAS));
00493                 REG_RMW_FIELD(ah, AR_PHY_XPA_CFG, AR_PHY_FORCE_XPA_CFG,
00494                               !!(pModal->lna_ctl & LNA_CTL_FORCE_XPA));
00495         }
00496 
00497         REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH,
00498                       pModal->switchSettling);
00499         REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC,
00500                       pModal->adcDesiredSize);
00501 
00502         if (!AR_SREV_9280_20_OR_LATER(ah))
00503                 REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
00504                               AR_PHY_DESIRED_SZ_PGA,
00505                               pModal->pgaDesiredSize);
00506 
00507         REG_WRITE(ah, AR_PHY_RF_CTL4,
00508                   SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF)
00509                   | SM(pModal->txEndToXpaOff,
00510                        AR_PHY_RF_CTL4_TX_END_XPAB_OFF)
00511                   | SM(pModal->txFrameToXpaOn,
00512                        AR_PHY_RF_CTL4_FRAME_XPAA_ON)
00513                   | SM(pModal->txFrameToXpaOn,
00514                        AR_PHY_RF_CTL4_FRAME_XPAB_ON));
00515 
00516         REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON,
00517                       pModal->txEndToRxOn);
00518 
00519         if (AR_SREV_9280_20_OR_LATER(ah)) {
00520                 REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62,
00521                               pModal->thresh62);
00522                 REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0,
00523                               AR_PHY_EXT_CCA0_THRESH62,
00524                               pModal->thresh62);
00525         } else {
00526                 REG_RMW_FIELD(ah, AR_PHY_CCA, AR_PHY_CCA_THRESH62,
00527                               pModal->thresh62);
00528                 REG_RMW_FIELD(ah, AR_PHY_EXT_CCA,
00529                               AR_PHY_EXT_CCA_THRESH62,
00530                               pModal->thresh62);
00531         }
00532 
00533         if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_2) {
00534                 REG_RMW_FIELD(ah, AR_PHY_RF_CTL2,
00535                               AR_PHY_TX_END_DATA_START,
00536                               pModal->txFrameToDataStart);
00537                 REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_PA_ON,
00538                               pModal->txFrameToPaOn);
00539         }
00540 
00541         if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_3) {
00542                 if (IS_CHAN_HT40(chan))
00543                         REG_RMW_FIELD(ah, AR_PHY_SETTLING,
00544                                       AR_PHY_SETTLING_SWITCH,
00545                                       pModal->swSettleHt40);
00546         }
00547 
00548         if (AR_SREV_9280_20_OR_LATER(ah) &&
00549             AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19)
00550                 REG_RMW_FIELD(ah, AR_PHY_CCK_TX_CTRL,
00551                               AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK,
00552                               pModal->miscBits);
00553 
00554 
00555         if (AR_SREV_9280_20(ah) && AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_20) {
00556                 if (IS_CHAN_2GHZ(chan))
00557                         REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE,
00558                                         eep->baseEepHeader.dacLpMode);
00559                 else if (eep->baseEepHeader.dacHiPwrMode_5G)
00560                         REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE, 0);
00561                 else
00562                         REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE,
00563                                       eep->baseEepHeader.dacLpMode);
00564 
00565                 udelay(100);
00566 
00567                 REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL, AR_PHY_FRAME_CTL_TX_CLIP,
00568                               pModal->miscBits >> 2);
00569 
00570                 REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL9,
00571                               AR_PHY_TX_DESIRED_SCALE_CCK,
00572                               eep->baseEepHeader.desiredScaleCCK);
00573         }
00574 }
00575 
00576 static void ath9k_hw_def_set_addac(struct ath_hw *ah,
00577                                    struct ath9k_channel *chan)
00578 {
00579 #define XPA_LVL_FREQ(cnt) (pModal->xpaBiasLvlFreq[cnt])
00580         struct modal_eep_header *pModal;
00581         struct ar5416_eeprom_def *eep = &ah->eeprom.def;
00582         u8 biaslevel;
00583 
00584         if (ah->hw_version.macVersion != AR_SREV_VERSION_9160)
00585                 return;
00586 
00587         if (ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_MINOR_VER_7)
00588                 return;
00589 
00590         pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
00591 
00592         if (pModal->xpaBiasLvl != 0xff) {
00593                 biaslevel = pModal->xpaBiasLvl;
00594         } else {
00595                 u16 resetFreqBin, freqBin, freqCount = 0;
00596                 struct chan_centers centers;
00597 
00598                 ath9k_hw_get_channel_centers(ah, chan, &centers);
00599 
00600                 resetFreqBin = FREQ2FBIN(centers.synth_center,
00601                                          IS_CHAN_2GHZ(chan));
00602                 freqBin = XPA_LVL_FREQ(0) & 0xff;
00603                 biaslevel = (u8) (XPA_LVL_FREQ(0) >> 14);
00604 
00605                 freqCount++;
00606 
00607                 while (freqCount < 3) {
00608                         if (XPA_LVL_FREQ(freqCount) == 0x0)
00609                                 break;
00610 
00611                         freqBin = XPA_LVL_FREQ(freqCount) & 0xff;
00612                         if (resetFreqBin >= freqBin)
00613                                 biaslevel = (u8)(XPA_LVL_FREQ(freqCount) >> 14);
00614                         else
00615                                 break;
00616                         freqCount++;
00617                 }
00618         }
00619 
00620         if (IS_CHAN_2GHZ(chan)) {
00621                 INI_RA(&ah->iniAddac, 7, 1) = (INI_RA(&ah->iniAddac,
00622                                         7, 1) & (~0x18)) | biaslevel << 3;
00623         } else {
00624                 INI_RA(&ah->iniAddac, 6, 1) = (INI_RA(&ah->iniAddac,
00625                                         6, 1) & (~0xc0)) | biaslevel << 6;
00626         }
00627 #undef XPA_LVL_FREQ
00628 }
00629 
00630 static int16_t ath9k_change_gain_boundary_setting(struct ath_hw *ah,
00631                                 u16 *gb,
00632                                 u16 numXpdGain,
00633                                 u16 pdGainOverlap_t2,
00634                                 int8_t pwr_table_offset,
00635                                 int16_t *diff)
00636 
00637 {
00638         u16 k;
00639 
00640         /* Prior to writing the boundaries or the pdadc vs. power table
00641          * into the chip registers the default starting point on the pdadc
00642          * vs. power table needs to be checked and the curve boundaries
00643          * adjusted accordingly
00644          */
00645         if (AR_SREV_9280_20_OR_LATER(ah)) {
00646                 u16 gb_limit;
00647 
00648                 if (AR5416_PWR_TABLE_OFFSET_DB != pwr_table_offset) {
00649                         /* get the difference in dB */
00650                         *diff = (u16)(pwr_table_offset - AR5416_PWR_TABLE_OFFSET_DB);
00651                         /* get the number of half dB steps */
00652                         *diff *= 2;
00653                         /* change the original gain boundary settings
00654                          * by the number of half dB steps
00655                          */
00656                         for (k = 0; k < numXpdGain; k++)
00657                                 gb[k] = (u16)(gb[k] - *diff);
00658                 }
00659                 /* Because of a hardware limitation, ensure the gain boundary
00660                  * is not larger than (63 - overlap)
00661                  */
00662                 gb_limit = (u16)(MAX_RATE_POWER - pdGainOverlap_t2);
00663 
00664                 for (k = 0; k < numXpdGain; k++)
00665                         gb[k] = (u16)min(gb_limit, gb[k]);
00666         }
00667 
00668         return *diff;
00669 }
00670 
00671 static void ath9k_adjust_pdadc_values(struct ath_hw *ah,
00672                                       int8_t pwr_table_offset,
00673                                       int16_t diff,
00674                                       u8 *pdadcValues)
00675 {
00676 #define NUM_PDADC(diff) (AR5416_NUM_PDADC_VALUES - diff)
00677         u16 k;
00678 
00679         /* If this is a board that has a pwrTableOffset that differs from
00680          * the default AR5416_PWR_TABLE_OFFSET_DB then the start of the
00681          * pdadc vs pwr table needs to be adjusted prior to writing to the
00682          * chip.
00683          */
00684         if (AR_SREV_9280_20_OR_LATER(ah)) {
00685                 if (AR5416_PWR_TABLE_OFFSET_DB != pwr_table_offset) {
00686                         /* shift the table to start at the new offset */
00687                         for (k = 0; k < (u16)NUM_PDADC(diff); k++ ) {
00688                                 pdadcValues[k] = pdadcValues[k + diff];
00689                         }
00690 
00691                         /* fill the back of the table */
00692                         for (k = (u16)NUM_PDADC(diff); k < NUM_PDADC(0); k++) {
00693                                 pdadcValues[k] = pdadcValues[NUM_PDADC(diff)];
00694                         }
00695                 }
00696         }
00697 #undef NUM_PDADC
00698 }
00699 
00700 static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah,
00701                                   struct ath9k_channel *chan,
00702                                   int16_t *pTxPowerIndexOffset)
00703 {
00704 #define SM_PD_GAIN(x) SM(0x38, AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_##x)
00705 #define SM_PDGAIN_B(x, y) \
00706                 SM((gainBoundaries[x]), AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_##y)
00707         struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;
00708         struct cal_data_per_freq *pRawDataset;
00709         u8 *pCalBChans = NULL;
00710         u16 pdGainOverlap_t2;
00711         static u8 pdadcValues[AR5416_NUM_PDADC_VALUES];
00712         u16 gainBoundaries[AR5416_PD_GAINS_IN_MASK];
00713         u16 numPiers, i, j;
00714         int16_t diff = 0;
00715         u16 numXpdGain, xpdMask;
00716         u16 xpdGainValues[AR5416_NUM_PD_GAINS] = { 0, 0, 0, 0 };
00717         u32 reg32, regOffset, regChainOffset;
00718         int16_t modalIdx;
00719         int8_t pwr_table_offset;
00720 
00721         modalIdx = IS_CHAN_2GHZ(chan) ? 1 : 0;
00722         xpdMask = pEepData->modalHeader[modalIdx].xpdGain;
00723 
00724         pwr_table_offset = ah->eep_ops->get_eeprom(ah, EEP_PWR_TABLE_OFFSET);
00725 
00726         if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
00727             AR5416_EEP_MINOR_VER_2) {
00728                 pdGainOverlap_t2 =
00729                         pEepData->modalHeader[modalIdx].pdGainOverlap;
00730         } else {
00731                 pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5),
00732                                             AR_PHY_TPCRG5_PD_GAIN_OVERLAP));
00733         }
00734 
00735         if (IS_CHAN_2GHZ(chan)) {
00736                 pCalBChans = pEepData->calFreqPier2G;
00737                 numPiers = AR5416_NUM_2G_CAL_PIERS;
00738         } else {
00739                 pCalBChans = pEepData->calFreqPier5G;
00740                 numPiers = AR5416_NUM_5G_CAL_PIERS;
00741         }
00742 
00743         if (OLC_FOR_AR9280_20_LATER && IS_CHAN_2GHZ(chan)) {
00744                 pRawDataset = pEepData->calPierData2G[0];
00745                 ah->initPDADC = ((struct calDataPerFreqOpLoop *)
00746                                  pRawDataset)->vpdPdg[0][0];
00747         }
00748 
00749         numXpdGain = 0;
00750 
00751         for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) {
00752                 if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) {
00753                         if (numXpdGain >= AR5416_NUM_PD_GAINS)
00754                                 break;
00755                         xpdGainValues[numXpdGain] =
00756                                 (u16)(AR5416_PD_GAINS_IN_MASK - i);
00757                         numXpdGain++;
00758                 }
00759         }
00760 
00761         REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN,
00762                       (numXpdGain - 1) & 0x3);
00763         REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1,
00764                       xpdGainValues[0]);
00765         REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2,
00766                       xpdGainValues[1]);
00767         REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3,
00768                       xpdGainValues[2]);
00769 
00770         for (i = 0; i < AR5416_MAX_CHAINS; i++) {
00771                 if (AR_SREV_5416_20_OR_LATER(ah) &&
00772                     (ah->rxchainmask == 5 || ah->txchainmask == 5) &&
00773                     (i != 0)) {
00774                         regChainOffset = (i == 1) ? 0x2000 : 0x1000;
00775                 } else
00776                         regChainOffset = i * 0x1000;
00777 
00778                 if (pEepData->baseEepHeader.txMask & (1 << i)) {
00779                         if (IS_CHAN_2GHZ(chan))
00780                                 pRawDataset = pEepData->calPierData2G[i];
00781                         else
00782                                 pRawDataset = pEepData->calPierData5G[i];
00783 
00784 
00785                         if (OLC_FOR_AR9280_20_LATER) {
00786                                 u8 pcdacIdx;
00787                                 u8 txPower;
00788 
00789                                 ath9k_get_txgain_index(ah, chan,
00790                                 (struct calDataPerFreqOpLoop *)pRawDataset,
00791                                 pCalBChans, numPiers, &txPower, &pcdacIdx);
00792                                 ath9k_olc_get_pdadcs(ah, pcdacIdx,
00793                                                      txPower/2, pdadcValues);
00794                         } else {
00795                                 ath9k_hw_get_gain_boundaries_pdadcs(ah,
00796                                                         chan, pRawDataset,
00797                                                         pCalBChans, numPiers,
00798                                                         pdGainOverlap_t2,
00799                                                         gainBoundaries,
00800                                                         pdadcValues,
00801                                                         numXpdGain);
00802                         }
00803 
00804                         diff = ath9k_change_gain_boundary_setting(ah,
00805                                                            gainBoundaries,
00806                                                            numXpdGain,
00807                                                            pdGainOverlap_t2,
00808                                                            pwr_table_offset,
00809                                                            &diff);
00810 
00811                         ENABLE_REGWRITE_BUFFER(ah);
00812 
00813                         if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) {
00814                                 if (OLC_FOR_AR9280_20_LATER) {
00815                                         REG_WRITE(ah,
00816                                                 AR_PHY_TPCRG5 + regChainOffset,
00817                                                 SM(0x6,
00818                                                 AR_PHY_TPCRG5_PD_GAIN_OVERLAP) |
00819                                                 SM_PD_GAIN(1) | SM_PD_GAIN(2) |
00820                                                 SM_PD_GAIN(3) | SM_PD_GAIN(4));
00821                                 } else {
00822                                         REG_WRITE(ah,
00823                                                 AR_PHY_TPCRG5 + regChainOffset,
00824                                                 SM(pdGainOverlap_t2,
00825                                                 AR_PHY_TPCRG5_PD_GAIN_OVERLAP)|
00826                                                 SM_PDGAIN_B(0, 1) |
00827                                                 SM_PDGAIN_B(1, 2) |
00828                                                 SM_PDGAIN_B(2, 3) |
00829                                                 SM_PDGAIN_B(3, 4));
00830                                 }
00831                         }
00832 
00833 
00834                         ath9k_adjust_pdadc_values(ah, pwr_table_offset,
00835                                                   diff, pdadcValues);
00836 
00837                         regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset;
00838                         for (j = 0; j < 32; j++) {
00839                                 reg32 = ((pdadcValues[4 * j + 0] & 0xFF) << 0) |
00840                                         ((pdadcValues[4 * j + 1] & 0xFF) << 8) |
00841                                         ((pdadcValues[4 * j + 2] & 0xFF) << 16)|
00842                                         ((pdadcValues[4 * j + 3] & 0xFF) << 24);
00843                                 REG_WRITE(ah, regOffset, reg32);
00844 
00845                                 DBG2("ath9k: "
00846                                         "PDADC (%d,%4x): %4.4x %8.8x\n",
00847                                         i, regChainOffset, regOffset,
00848                                         reg32);
00849                                 DBG2("ath9k: "
00850                                         "PDADC: Chain %d | PDADC %3d "
00851                                         "Value %3d | PDADC %3d Value %3d | "
00852                                         "PDADC %3d Value %3d | PDADC %3d "
00853                                         "Value %3d |\n",
00854                                         i, 4 * j, pdadcValues[4 * j],
00855                                         4 * j + 1, pdadcValues[4 * j + 1],
00856                                         4 * j + 2, pdadcValues[4 * j + 2],
00857                                         4 * j + 3, pdadcValues[4 * j + 3]);
00858 
00859                                 regOffset += 4;
00860                         }
00861                         REGWRITE_BUFFER_FLUSH(ah);
00862                 }
00863         }
00864 
00865         *pTxPowerIndexOffset = 0;
00866 #undef SM_PD_GAIN
00867 #undef SM_PDGAIN_B
00868 }
00869 
00870 static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah,
00871                                                   struct ath9k_channel *chan,
00872                                                   int16_t *ratesArray,
00873                                                   u16 cfgCtl,
00874                                                   u16 AntennaReduction,
00875                                                   u16 twiceMaxRegulatoryPower,
00876                                                   u16 powerLimit)
00877 {
00878 #define REDUCE_SCALED_POWER_BY_TWO_CHAIN     6  /* 10*log10(2)*2 */
00879 #define REDUCE_SCALED_POWER_BY_THREE_CHAIN   9 /* 10*log10(3)*2 */
00880 
00881         struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
00882         struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;
00883         u16 twiceMaxEdgePower = MAX_RATE_POWER;
00884         static const u16 tpScaleReductionTable[5] =
00885                 { 0, 3, 6, 9, MAX_RATE_POWER };
00886 
00887         unsigned int i;
00888         int16_t twiceLargestAntenna;
00889         struct cal_ctl_data *rep;
00890         struct cal_target_power_leg targetPowerOfdm, targetPowerCck = {
00891                 0, { 0, 0, 0, 0}
00892         };
00893         struct cal_target_power_leg targetPowerOfdmExt = {
00894                 0, { 0, 0, 0, 0} }, targetPowerCckExt = {
00895                 0, { 0, 0, 0, 0 }
00896         };
00897         struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = {
00898                 0, {0, 0, 0, 0}
00899         };
00900         u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
00901         static const u16 ctlModesFor11a[] = {
00902                 CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40
00903         };
00904         static const u16 ctlModesFor11g[] = {
00905                 CTL_11B, CTL_11G, CTL_2GHT20,
00906                 CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40
00907         };
00908         u16 numCtlModes;
00909         const u16 *pCtlMode;
00910         u16 ctlMode, freq;
00911         struct chan_centers centers;
00912         int tx_chainmask;
00913         u16 twiceMinEdgePower;
00914 
00915         tx_chainmask = ah->txchainmask;
00916 
00917         ath9k_hw_get_channel_centers(ah, chan, &centers);
00918 
00919         twiceLargestAntenna = max(
00920                 pEepData->modalHeader
00921                         [IS_CHAN_2GHZ(chan)].antennaGainCh[0],
00922                 pEepData->modalHeader
00923                         [IS_CHAN_2GHZ(chan)].antennaGainCh[1]);
00924 
00925         twiceLargestAntenna = max((u8)twiceLargestAntenna,
00926                                   pEepData->modalHeader
00927                                   [IS_CHAN_2GHZ(chan)].antennaGainCh[2]);
00928 
00929         twiceLargestAntenna = (int16_t)min(AntennaReduction -
00930                                            twiceLargestAntenna, 0);
00931 
00932         maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
00933 
00934         if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX) {
00935                 maxRegAllowedPower -=
00936                         (tpScaleReductionTable[(regulatory->tp_scale)] * 2);
00937         }
00938 
00939         scaledPower = min(powerLimit, maxRegAllowedPower);
00940 
00941         switch (ar5416_get_ntxchains(tx_chainmask)) {
00942         case 1:
00943                 break;
00944         case 2:
00945                 if (scaledPower > REDUCE_SCALED_POWER_BY_TWO_CHAIN)
00946                         scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN;
00947                 else
00948                         scaledPower = 0;
00949                 break;
00950         case 3:
00951                 if (scaledPower > REDUCE_SCALED_POWER_BY_THREE_CHAIN)
00952                         scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN;
00953                 else
00954                         scaledPower = 0;
00955                 break;
00956         }
00957 
00958         if (IS_CHAN_2GHZ(chan)) {
00959                 numCtlModes = ARRAY_SIZE(ctlModesFor11g) -
00960                         SUB_NUM_CTL_MODES_AT_2G_40;
00961                 pCtlMode = ctlModesFor11g;
00962 
00963                 ath9k_hw_get_legacy_target_powers(ah, chan,
00964                         pEepData->calTargetPowerCck,
00965                         AR5416_NUM_2G_CCK_TARGET_POWERS,
00966                         &targetPowerCck, 4, 0);
00967                 ath9k_hw_get_legacy_target_powers(ah, chan,
00968                         pEepData->calTargetPower2G,
00969                         AR5416_NUM_2G_20_TARGET_POWERS,
00970                         &targetPowerOfdm, 4, 0);
00971                 ath9k_hw_get_target_powers(ah, chan,
00972                         pEepData->calTargetPower2GHT20,
00973                         AR5416_NUM_2G_20_TARGET_POWERS,
00974                         &targetPowerHt20, 8, 0);
00975 
00976                 if (IS_CHAN_HT40(chan)) {
00977                         numCtlModes = ARRAY_SIZE(ctlModesFor11g);
00978                         ath9k_hw_get_target_powers(ah, chan,
00979                                 pEepData->calTargetPower2GHT40,
00980                                 AR5416_NUM_2G_40_TARGET_POWERS,
00981                                 &targetPowerHt40, 8, 1);
00982                         ath9k_hw_get_legacy_target_powers(ah, chan,
00983                                 pEepData->calTargetPowerCck,
00984                                 AR5416_NUM_2G_CCK_TARGET_POWERS,
00985                                 &targetPowerCckExt, 4, 1);
00986                         ath9k_hw_get_legacy_target_powers(ah, chan,
00987                                 pEepData->calTargetPower2G,
00988                                 AR5416_NUM_2G_20_TARGET_POWERS,
00989                                 &targetPowerOfdmExt, 4, 1);
00990                 }
00991         } else {
00992                 numCtlModes = ARRAY_SIZE(ctlModesFor11a) -
00993                         SUB_NUM_CTL_MODES_AT_5G_40;
00994                 pCtlMode = ctlModesFor11a;
00995 
00996                 ath9k_hw_get_legacy_target_powers(ah, chan,
00997                         pEepData->calTargetPower5G,
00998                         AR5416_NUM_5G_20_TARGET_POWERS,
00999                         &targetPowerOfdm, 4, 0);
01000                 ath9k_hw_get_target_powers(ah, chan,
01001                         pEepData->calTargetPower5GHT20,
01002                         AR5416_NUM_5G_20_TARGET_POWERS,
01003                         &targetPowerHt20, 8, 0);
01004 
01005                 if (IS_CHAN_HT40(chan)) {
01006                         numCtlModes = ARRAY_SIZE(ctlModesFor11a);
01007                         ath9k_hw_get_target_powers(ah, chan,
01008                                 pEepData->calTargetPower5GHT40,
01009                                 AR5416_NUM_5G_40_TARGET_POWERS,
01010                                 &targetPowerHt40, 8, 1);
01011                         ath9k_hw_get_legacy_target_powers(ah, chan,
01012                                 pEepData->calTargetPower5G,
01013                                 AR5416_NUM_5G_20_TARGET_POWERS,
01014                                 &targetPowerOfdmExt, 4, 1);
01015                 }
01016         }
01017 
01018         for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) {
01019                 int isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) ||
01020                         (pCtlMode[ctlMode] == CTL_2GHT40);
01021                 if (isHt40CtlMode)
01022                         freq = centers.synth_center;
01023                 else if (pCtlMode[ctlMode] & EXT_ADDITIVE)
01024                         freq = centers.ext_center;
01025                 else
01026                         freq = centers.ctl_center;
01027 
01028                 if (ah->eep_ops->get_eeprom_ver(ah) == 14 &&
01029                     ah->eep_ops->get_eeprom_rev(ah) <= 2)
01030                         twiceMaxEdgePower = MAX_RATE_POWER;
01031 
01032                 for (i = 0; (i < AR5416_NUM_CTLS) && pEepData->ctlIndex[i]; i++) {
01033                         if ((((cfgCtl & ~CTL_MODE_M) |
01034                               (pCtlMode[ctlMode] & CTL_MODE_M)) ==
01035                              pEepData->ctlIndex[i]) ||
01036                             (((cfgCtl & ~CTL_MODE_M) |
01037                               (pCtlMode[ctlMode] & CTL_MODE_M)) ==
01038                              ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL))) {
01039                                 rep = &(pEepData->ctlData[i]);
01040 
01041                                 twiceMinEdgePower = ath9k_hw_get_max_edge_power(freq,
01042                                 rep->ctlEdges[ar5416_get_ntxchains(tx_chainmask) - 1],
01043                                 IS_CHAN_2GHZ(chan), AR5416_NUM_BAND_EDGES);
01044 
01045                                 if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) {
01046                                         twiceMaxEdgePower = min(twiceMaxEdgePower,
01047                                                                 twiceMinEdgePower);
01048                                 } else {
01049                                         twiceMaxEdgePower = twiceMinEdgePower;
01050                                         break;
01051                                 }
01052                         }
01053                 }
01054 
01055                 minCtlPower = min(twiceMaxEdgePower, scaledPower);
01056 
01057                 switch (pCtlMode[ctlMode]) {
01058                 case CTL_11B:
01059                         for (i = 0; i < ARRAY_SIZE(targetPowerCck.tPow2x); i++) {
01060                                 targetPowerCck.tPow2x[i] =
01061                                         min((u16)targetPowerCck.tPow2x[i],
01062                                             minCtlPower);
01063                         }
01064                         break;
01065                 case CTL_11A:
01066                 case CTL_11G:
01067                         for (i = 0; i < ARRAY_SIZE(targetPowerOfdm.tPow2x); i++) {
01068                                 targetPowerOfdm.tPow2x[i] =
01069                                         min((u16)targetPowerOfdm.tPow2x[i],
01070                                             minCtlPower);
01071                         }
01072                         break;
01073                 case CTL_5GHT20:
01074                 case CTL_2GHT20:
01075                         for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++) {
01076                                 targetPowerHt20.tPow2x[i] =
01077                                         min((u16)targetPowerHt20.tPow2x[i],
01078                                             minCtlPower);
01079                         }
01080                         break;
01081                 case CTL_11B_EXT:
01082                         targetPowerCckExt.tPow2x[0] = min((u16)
01083                                         targetPowerCckExt.tPow2x[0],
01084                                         minCtlPower);
01085                         break;
01086                 case CTL_11A_EXT:
01087                 case CTL_11G_EXT:
01088                         targetPowerOfdmExt.tPow2x[0] = min((u16)
01089                                         targetPowerOfdmExt.tPow2x[0],
01090                                         minCtlPower);
01091                         break;
01092                 case CTL_5GHT40:
01093                 case CTL_2GHT40:
01094                         for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {
01095                                 targetPowerHt40.tPow2x[i] =
01096                                         min((u16)targetPowerHt40.tPow2x[i],
01097                                             minCtlPower);
01098                         }
01099                         break;
01100                 default:
01101                         break;
01102                 }
01103         }
01104 
01105         ratesArray[rate6mb] = ratesArray[rate9mb] = ratesArray[rate12mb] =
01106                 ratesArray[rate18mb] = ratesArray[rate24mb] =
01107                 targetPowerOfdm.tPow2x[0];
01108         ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1];
01109         ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2];
01110         ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3];
01111         ratesArray[rateXr] = targetPowerOfdm.tPow2x[0];
01112 
01113         for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++)
01114                 ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i];
01115 
01116         if (IS_CHAN_2GHZ(chan)) {
01117                 ratesArray[rate1l] = targetPowerCck.tPow2x[0];
01118                 ratesArray[rate2s] = ratesArray[rate2l] =
01119                         targetPowerCck.tPow2x[1];
01120                 ratesArray[rate5_5s] = ratesArray[rate5_5l] =
01121                         targetPowerCck.tPow2x[2];
01122                 ratesArray[rate11s] = ratesArray[rate11l] =
01123                         targetPowerCck.tPow2x[3];
01124         }
01125         if (IS_CHAN_HT40(chan)) {
01126                 for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {
01127                         ratesArray[rateHt40_0 + i] =
01128                                 targetPowerHt40.tPow2x[i];
01129                 }
01130                 ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0];
01131                 ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0];
01132                 ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0];
01133                 if (IS_CHAN_2GHZ(chan)) {
01134                         ratesArray[rateExtCck] =
01135                                 targetPowerCckExt.tPow2x[0];
01136                 }
01137         }
01138 }
01139 
01140 static void ath9k_hw_def_set_txpower(struct ath_hw *ah,
01141                                     struct ath9k_channel *chan,
01142                                     u16 cfgCtl,
01143                                     u8 twiceAntennaReduction,
01144                                     u8 twiceMaxRegulatoryPower,
01145                                     u8 powerLimit, int test)
01146 {
01147 #define RT_AR_DELTA(x) (ratesArray[x] - cck_ofdm_delta)
01148         struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
01149         struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;
01150         struct modal_eep_header *pModal =
01151                 &(pEepData->modalHeader[IS_CHAN_2GHZ(chan)]);
01152         int16_t ratesArray[Ar5416RateSize];
01153         int16_t txPowerIndexOffset = 0;
01154         u8 ht40PowerIncForPdadc = 2;
01155         unsigned int i, cck_ofdm_delta = 0;
01156 
01157         memset(ratesArray, 0, sizeof(ratesArray));
01158 
01159         if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
01160             AR5416_EEP_MINOR_VER_2) {
01161                 ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
01162         }
01163 
01164         ath9k_hw_set_def_power_per_rate_table(ah, chan,
01165                                                &ratesArray[0], cfgCtl,
01166                                                twiceAntennaReduction,
01167                                                twiceMaxRegulatoryPower,
01168                                                powerLimit);
01169 
01170         ath9k_hw_set_def_power_cal_table(ah, chan, &txPowerIndexOffset);
01171 
01172         regulatory->max_power_level = 0;
01173         for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
01174                 ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
01175                 if (ratesArray[i] > MAX_RATE_POWER)
01176                         ratesArray[i] = MAX_RATE_POWER;
01177                 if (ratesArray[i] > regulatory->max_power_level)
01178                         regulatory->max_power_level = ratesArray[i];
01179         }
01180 
01181         if (!test) {
01182                 i = rate6mb;
01183 
01184                 if (IS_CHAN_HT40(chan))
01185                         i = rateHt40_0;
01186                 else if (IS_CHAN_HT20(chan))
01187                         i = rateHt20_0;
01188 
01189                 regulatory->max_power_level = ratesArray[i];
01190         }
01191 
01192         switch(ar5416_get_ntxchains(ah->txchainmask)) {
01193         case 1:
01194                 break;
01195         case 2:
01196                 regulatory->max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN;
01197                 break;
01198         case 3:
01199                 regulatory->max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN;
01200                 break;
01201         default:
01202                 DBG2("ath9k: "
01203                         "Invalid chainmask configuration\n");
01204                 break;
01205         }
01206 
01207         if (test)
01208                 return;
01209 
01210         if (AR_SREV_9280_20_OR_LATER(ah)) {
01211                 for (i = 0; i < Ar5416RateSize; i++) {
01212                         int8_t pwr_table_offset;
01213 
01214                         pwr_table_offset = ah->eep_ops->get_eeprom(ah,
01215                                                         EEP_PWR_TABLE_OFFSET);
01216                         ratesArray[i] -= pwr_table_offset * 2;
01217                 }
01218         }
01219 
01220         ENABLE_REGWRITE_BUFFER(ah);
01221 
01222         REG_WRITE(ah, AR_PHY_POWER_TX_RATE1,
01223                   ATH9K_POW_SM(ratesArray[rate18mb], 24)
01224                   | ATH9K_POW_SM(ratesArray[rate12mb], 16)
01225                   | ATH9K_POW_SM(ratesArray[rate9mb], 8)
01226                   | ATH9K_POW_SM(ratesArray[rate6mb], 0));
01227         REG_WRITE(ah, AR_PHY_POWER_TX_RATE2,
01228                   ATH9K_POW_SM(ratesArray[rate54mb], 24)
01229                   | ATH9K_POW_SM(ratesArray[rate48mb], 16)
01230                   | ATH9K_POW_SM(ratesArray[rate36mb], 8)
01231                   | ATH9K_POW_SM(ratesArray[rate24mb], 0));
01232 
01233         if (IS_CHAN_2GHZ(chan)) {
01234                 if (OLC_FOR_AR9280_20_LATER) {
01235                         cck_ofdm_delta = 2;
01236                         REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
01237                                 ATH9K_POW_SM(RT_AR_DELTA(rate2s), 24)
01238                                 | ATH9K_POW_SM(RT_AR_DELTA(rate2l), 16)
01239                                 | ATH9K_POW_SM(ratesArray[rateXr], 8)
01240                                 | ATH9K_POW_SM(RT_AR_DELTA(rate1l), 0));
01241                         REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
01242                                 ATH9K_POW_SM(RT_AR_DELTA(rate11s), 24)
01243                                 | ATH9K_POW_SM(RT_AR_DELTA(rate11l), 16)
01244                                 | ATH9K_POW_SM(RT_AR_DELTA(rate5_5s), 8)
01245                                 | ATH9K_POW_SM(RT_AR_DELTA(rate5_5l), 0));
01246                 } else {
01247                         REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
01248                                 ATH9K_POW_SM(ratesArray[rate2s], 24)
01249                                 | ATH9K_POW_SM(ratesArray[rate2l], 16)
01250                                 | ATH9K_POW_SM(ratesArray[rateXr], 8)
01251                                 | ATH9K_POW_SM(ratesArray[rate1l], 0));
01252                         REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
01253                                 ATH9K_POW_SM(ratesArray[rate11s], 24)
01254                                 | ATH9K_POW_SM(ratesArray[rate11l], 16)
01255                                 | ATH9K_POW_SM(ratesArray[rate5_5s], 8)
01256                                 | ATH9K_POW_SM(ratesArray[rate5_5l], 0));
01257                 }
01258         }
01259 
01260         REG_WRITE(ah, AR_PHY_POWER_TX_RATE5,
01261                   ATH9K_POW_SM(ratesArray[rateHt20_3], 24)
01262                   | ATH9K_POW_SM(ratesArray[rateHt20_2], 16)
01263                   | ATH9K_POW_SM(ratesArray[rateHt20_1], 8)
01264                   | ATH9K_POW_SM(ratesArray[rateHt20_0], 0));
01265         REG_WRITE(ah, AR_PHY_POWER_TX_RATE6,
01266                   ATH9K_POW_SM(ratesArray[rateHt20_7], 24)
01267                   | ATH9K_POW_SM(ratesArray[rateHt20_6], 16)
01268                   | ATH9K_POW_SM(ratesArray[rateHt20_5], 8)
01269                   | ATH9K_POW_SM(ratesArray[rateHt20_4], 0));
01270 
01271         if (IS_CHAN_HT40(chan)) {
01272                 REG_WRITE(ah, AR_PHY_POWER_TX_RATE7,
01273                           ATH9K_POW_SM(ratesArray[rateHt40_3] +
01274                                        ht40PowerIncForPdadc, 24)
01275                           | ATH9K_POW_SM(ratesArray[rateHt40_2] +
01276                                          ht40PowerIncForPdadc, 16)
01277                           | ATH9K_POW_SM(ratesArray[rateHt40_1] +
01278                                          ht40PowerIncForPdadc, 8)
01279                           | ATH9K_POW_SM(ratesArray[rateHt40_0] +
01280                                          ht40PowerIncForPdadc, 0));
01281                 REG_WRITE(ah, AR_PHY_POWER_TX_RATE8,
01282                           ATH9K_POW_SM(ratesArray[rateHt40_7] +
01283                                        ht40PowerIncForPdadc, 24)
01284                           | ATH9K_POW_SM(ratesArray[rateHt40_6] +
01285                                          ht40PowerIncForPdadc, 16)
01286                           | ATH9K_POW_SM(ratesArray[rateHt40_5] +
01287                                          ht40PowerIncForPdadc, 8)
01288                           | ATH9K_POW_SM(ratesArray[rateHt40_4] +
01289                                          ht40PowerIncForPdadc, 0));
01290                 if (OLC_FOR_AR9280_20_LATER) {
01291                         REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
01292                                 ATH9K_POW_SM(ratesArray[rateExtOfdm], 24)
01293                                 | ATH9K_POW_SM(RT_AR_DELTA(rateExtCck), 16)
01294                                 | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
01295                                 | ATH9K_POW_SM(RT_AR_DELTA(rateDupCck), 0));
01296                 } else {
01297                         REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
01298                                 ATH9K_POW_SM(ratesArray[rateExtOfdm], 24)
01299                                 | ATH9K_POW_SM(ratesArray[rateExtCck], 16)
01300                                 | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
01301                                 | ATH9K_POW_SM(ratesArray[rateDupCck], 0));
01302                 }
01303         }
01304 
01305         REG_WRITE(ah, AR_PHY_POWER_TX_SUB,
01306                   ATH9K_POW_SM(pModal->pwrDecreaseFor3Chain, 6)
01307                   | ATH9K_POW_SM(pModal->pwrDecreaseFor2Chain, 0));
01308 
01309         REGWRITE_BUFFER_FLUSH(ah);
01310 }
01311 
01312 static u16 ath9k_hw_def_get_spur_channel(struct ath_hw *ah, u16 i, int is2GHz)
01313 {
01314 #define EEP_DEF_SPURCHAN \
01315         (ah->eeprom.def.modalHeader[is2GHz].spurChans[i].spurChan)
01316 
01317         u16 spur_val = AR_NO_SPUR;
01318 
01319         DBG2("ath9k: "
01320                 "Getting spur idx:%d is2Ghz:%d val:%x\n",
01321                 i, is2GHz, ah->config.spurchans[i][is2GHz]);
01322 
01323         switch (ah->config.spurmode) {
01324         case SPUR_DISABLE:
01325                 break;
01326         case SPUR_ENABLE_IOCTL:
01327                 spur_val = ah->config.spurchans[i][is2GHz];
01328                 DBG2("ath9k: "
01329                         "Getting spur val from new loc. %d\n", spur_val);
01330                 break;
01331         case SPUR_ENABLE_EEPROM:
01332                 spur_val = EEP_DEF_SPURCHAN;
01333                 break;
01334         }
01335 
01336         return spur_val;
01337 
01338 #undef EEP_DEF_SPURCHAN
01339 }
01340 
01341 const struct eeprom_ops eep_def_ops = {
01342         .check_eeprom           = ath9k_hw_def_check_eeprom,
01343         .get_eeprom             = ath9k_hw_def_get_eeprom,
01344         .fill_eeprom            = ath9k_hw_def_fill_eeprom,
01345         .get_eeprom_ver         = ath9k_hw_def_get_eeprom_ver,
01346         .get_eeprom_rev         = ath9k_hw_def_get_eeprom_rev,
01347         .set_board_values       = ath9k_hw_def_set_board_values,
01348         .set_addac              = ath9k_hw_def_set_addac,
01349         .set_txpower            = ath9k_hw_def_set_txpower,
01350         .get_spur_channel       = ath9k_hw_def_get_spur_channel
01351 };