1323 lines · c
1/*2 * Copyright (c) 2008-2011 Atheros Communications Inc.3 *4 * Permission to use, copy, modify, and/or distribute this software for any5 * purpose with or without fee is hereby granted, provided that the above6 * copyright notice and this permission notice appear in all copies.7 *8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.15 */16 17#include <linux/unaligned.h>18#include "hw.h"19#include "ar9002_phy.h"20 21static void ath9k_get_txgain_index(struct ath_hw *ah,22 struct ath9k_channel *chan,23 struct calDataPerFreqOpLoop *rawDatasetOpLoop,24 u8 *calChans, u16 availPiers, u8 *pwr, u8 *pcdacIdx)25{26 u8 pcdac, i = 0;27 u16 idxL = 0, idxR = 0, numPiers;28 bool match;29 struct chan_centers centers;30 31 ath9k_hw_get_channel_centers(ah, chan, ¢ers);32 33 for (numPiers = 0; numPiers < availPiers; numPiers++)34 if (calChans[numPiers] == AR5416_BCHAN_UNUSED)35 break;36 37 match = ath9k_hw_get_lower_upper_index(38 (u8)FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan)),39 calChans, numPiers, &idxL, &idxR);40 if (match) {41 pcdac = rawDatasetOpLoop[idxL].pcdac[0][0];42 *pwr = rawDatasetOpLoop[idxL].pwrPdg[0][0];43 } else {44 pcdac = rawDatasetOpLoop[idxR].pcdac[0][0];45 *pwr = (rawDatasetOpLoop[idxL].pwrPdg[0][0] +46 rawDatasetOpLoop[idxR].pwrPdg[0][0])/2;47 }48 49 while (pcdac > ah->originalGain[i] &&50 i < (AR9280_TX_GAIN_TABLE_SIZE - 1))51 i++;52 53 *pcdacIdx = i;54}55 56static void ath9k_olc_get_pdadcs(struct ath_hw *ah,57 u32 initTxGain,58 int txPower,59 u8 *pPDADCValues)60{61 u32 i;62 u32 offset;63 64 REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL6_0,65 AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3);66 REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL6_1,67 AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3);68 69 REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL7,70 AR_PHY_TX_PWRCTRL_INIT_TX_GAIN, initTxGain);71 72 offset = txPower;73 for (i = 0; i < AR5416_NUM_PDADC_VALUES; i++)74 if (i < offset)75 pPDADCValues[i] = 0x0;76 else77 pPDADCValues[i] = 0xFF;78}79 80static int ath9k_hw_def_get_eeprom_ver(struct ath_hw *ah)81{82 u16 version = le16_to_cpu(ah->eeprom.def.baseEepHeader.version);83 84 return (version & AR5416_EEP_VER_MAJOR_MASK) >>85 AR5416_EEP_VER_MAJOR_SHIFT;86}87 88static int ath9k_hw_def_get_eeprom_rev(struct ath_hw *ah)89{90 u16 version = le16_to_cpu(ah->eeprom.def.baseEepHeader.version);91 92 return version & AR5416_EEP_VER_MINOR_MASK;93}94 95#define SIZE_EEPROM_DEF (sizeof(struct ar5416_eeprom_def) / sizeof(u16))96 97static bool __ath9k_hw_def_fill_eeprom(struct ath_hw *ah)98{99 u16 *eep_data = (u16 *)&ah->eeprom.def;100 int addr, ar5416_eep_start_loc = 0x100;101 102 for (addr = 0; addr < SIZE_EEPROM_DEF; addr++) {103 if (!ath9k_hw_nvram_read(ah, addr + ar5416_eep_start_loc,104 eep_data))105 return false;106 eep_data++;107 }108 return true;109}110 111static bool __ath9k_hw_usb_def_fill_eeprom(struct ath_hw *ah)112{113 u16 *eep_data = (u16 *)&ah->eeprom.def;114 115 ath9k_hw_usb_gen_fill_eeprom(ah, eep_data,116 0x100, SIZE_EEPROM_DEF);117 return true;118}119 120static bool ath9k_hw_def_fill_eeprom(struct ath_hw *ah)121{122 struct ath_common *common = ath9k_hw_common(ah);123 124 if (!ath9k_hw_use_flash(ah)) {125 ath_dbg(common, EEPROM, "Reading from EEPROM, not flash\n");126 }127 128 if (common->bus_ops->ath_bus_type == ATH_USB)129 return __ath9k_hw_usb_def_fill_eeprom(ah);130 else131 return __ath9k_hw_def_fill_eeprom(ah);132}133 134#ifdef CONFIG_ATH9K_COMMON_DEBUG135static u32 ath9k_def_dump_modal_eeprom(char *buf, u32 len, u32 size,136 struct modal_eep_header *modal_hdr)137{138 PR_EEP("Chain0 Ant. Control", le32_to_cpu(modal_hdr->antCtrlChain[0]));139 PR_EEP("Chain1 Ant. Control", le32_to_cpu(modal_hdr->antCtrlChain[1]));140 PR_EEP("Chain2 Ant. Control", le32_to_cpu(modal_hdr->antCtrlChain[2]));141 PR_EEP("Ant. Common Control", le32_to_cpu(modal_hdr->antCtrlCommon));142 PR_EEP("Chain0 Ant. Gain", modal_hdr->antennaGainCh[0]);143 PR_EEP("Chain1 Ant. Gain", modal_hdr->antennaGainCh[1]);144 PR_EEP("Chain2 Ant. Gain", modal_hdr->antennaGainCh[2]);145 PR_EEP("Switch Settle", modal_hdr->switchSettling);146 PR_EEP("Chain0 TxRxAtten", modal_hdr->txRxAttenCh[0]);147 PR_EEP("Chain1 TxRxAtten", modal_hdr->txRxAttenCh[1]);148 PR_EEP("Chain2 TxRxAtten", modal_hdr->txRxAttenCh[2]);149 PR_EEP("Chain0 RxTxMargin", modal_hdr->rxTxMarginCh[0]);150 PR_EEP("Chain1 RxTxMargin", modal_hdr->rxTxMarginCh[1]);151 PR_EEP("Chain2 RxTxMargin", modal_hdr->rxTxMarginCh[2]);152 PR_EEP("ADC Desired size", modal_hdr->adcDesiredSize);153 PR_EEP("PGA Desired size", modal_hdr->pgaDesiredSize);154 PR_EEP("Chain0 xlna Gain", modal_hdr->xlnaGainCh[0]);155 PR_EEP("Chain1 xlna Gain", modal_hdr->xlnaGainCh[1]);156 PR_EEP("Chain2 xlna Gain", modal_hdr->xlnaGainCh[2]);157 PR_EEP("txEndToXpaOff", modal_hdr->txEndToXpaOff);158 PR_EEP("txEndToRxOn", modal_hdr->txEndToRxOn);159 PR_EEP("txFrameToXpaOn", modal_hdr->txFrameToXpaOn);160 PR_EEP("CCA Threshold)", modal_hdr->thresh62);161 PR_EEP("Chain0 NF Threshold", modal_hdr->noiseFloorThreshCh[0]);162 PR_EEP("Chain1 NF Threshold", modal_hdr->noiseFloorThreshCh[1]);163 PR_EEP("Chain2 NF Threshold", modal_hdr->noiseFloorThreshCh[2]);164 PR_EEP("xpdGain", modal_hdr->xpdGain);165 PR_EEP("External PD", modal_hdr->xpd);166 PR_EEP("Chain0 I Coefficient", modal_hdr->iqCalICh[0]);167 PR_EEP("Chain1 I Coefficient", modal_hdr->iqCalICh[1]);168 PR_EEP("Chain2 I Coefficient", modal_hdr->iqCalICh[2]);169 PR_EEP("Chain0 Q Coefficient", modal_hdr->iqCalQCh[0]);170 PR_EEP("Chain1 Q Coefficient", modal_hdr->iqCalQCh[1]);171 PR_EEP("Chain2 Q Coefficient", modal_hdr->iqCalQCh[2]);172 PR_EEP("pdGainOverlap", modal_hdr->pdGainOverlap);173 PR_EEP("Chain0 OutputBias", modal_hdr->ob);174 PR_EEP("Chain0 DriverBias", modal_hdr->db);175 PR_EEP("xPA Bias Level", modal_hdr->xpaBiasLvl);176 PR_EEP("2chain pwr decrease", modal_hdr->pwrDecreaseFor2Chain);177 PR_EEP("3chain pwr decrease", modal_hdr->pwrDecreaseFor3Chain);178 PR_EEP("txFrameToDataStart", modal_hdr->txFrameToDataStart);179 PR_EEP("txFrameToPaOn", modal_hdr->txFrameToPaOn);180 PR_EEP("HT40 Power Inc.", modal_hdr->ht40PowerIncForPdadc);181 PR_EEP("Chain0 bswAtten", modal_hdr->bswAtten[0]);182 PR_EEP("Chain1 bswAtten", modal_hdr->bswAtten[1]);183 PR_EEP("Chain2 bswAtten", modal_hdr->bswAtten[2]);184 PR_EEP("Chain0 bswMargin", modal_hdr->bswMargin[0]);185 PR_EEP("Chain1 bswMargin", modal_hdr->bswMargin[1]);186 PR_EEP("Chain2 bswMargin", modal_hdr->bswMargin[2]);187 PR_EEP("HT40 Switch Settle", modal_hdr->swSettleHt40);188 PR_EEP("Chain0 xatten2Db", modal_hdr->xatten2Db[0]);189 PR_EEP("Chain1 xatten2Db", modal_hdr->xatten2Db[1]);190 PR_EEP("Chain2 xatten2Db", modal_hdr->xatten2Db[2]);191 PR_EEP("Chain0 xatten2Margin", modal_hdr->xatten2Margin[0]);192 PR_EEP("Chain1 xatten2Margin", modal_hdr->xatten2Margin[1]);193 PR_EEP("Chain2 xatten2Margin", modal_hdr->xatten2Margin[2]);194 PR_EEP("Chain1 OutputBias", modal_hdr->ob_ch1);195 PR_EEP("Chain1 DriverBias", modal_hdr->db_ch1);196 PR_EEP("LNA Control", modal_hdr->lna_ctl);197 PR_EEP("XPA Bias Freq0", le16_to_cpu(modal_hdr->xpaBiasLvlFreq[0]));198 PR_EEP("XPA Bias Freq1", le16_to_cpu(modal_hdr->xpaBiasLvlFreq[1]));199 PR_EEP("XPA Bias Freq2", le16_to_cpu(modal_hdr->xpaBiasLvlFreq[2]));200 201 return len;202}203 204static u32 ath9k_hw_def_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,205 u8 *buf, u32 len, u32 size)206{207 struct ar5416_eeprom_def *eep = &ah->eeprom.def;208 struct base_eep_header *pBase = &eep->baseEepHeader;209 u32 binBuildNumber = le32_to_cpu(pBase->binBuildNumber);210 211 if (!dump_base_hdr) {212 len += scnprintf(buf + len, size - len,213 "%20s :\n", "2GHz modal Header");214 len = ath9k_def_dump_modal_eeprom(buf, len, size,215 &eep->modalHeader[0]);216 len += scnprintf(buf + len, size - len,217 "%20s :\n", "5GHz modal Header");218 len = ath9k_def_dump_modal_eeprom(buf, len, size,219 &eep->modalHeader[1]);220 goto out;221 }222 223 PR_EEP("Major Version", ath9k_hw_def_get_eeprom_ver(ah));224 PR_EEP("Minor Version", ath9k_hw_def_get_eeprom_rev(ah));225 PR_EEP("Checksum", le16_to_cpu(pBase->checksum));226 PR_EEP("Length", le16_to_cpu(pBase->length));227 PR_EEP("RegDomain1", le16_to_cpu(pBase->regDmn[0]));228 PR_EEP("RegDomain2", le16_to_cpu(pBase->regDmn[1]));229 PR_EEP("TX Mask", pBase->txMask);230 PR_EEP("RX Mask", pBase->rxMask);231 PR_EEP("Allow 5GHz", !!(pBase->opCapFlags & AR5416_OPFLAGS_11A));232 PR_EEP("Allow 2GHz", !!(pBase->opCapFlags & AR5416_OPFLAGS_11G));233 PR_EEP("Disable 2GHz HT20", !!(pBase->opCapFlags &234 AR5416_OPFLAGS_N_2G_HT20));235 PR_EEP("Disable 2GHz HT40", !!(pBase->opCapFlags &236 AR5416_OPFLAGS_N_2G_HT40));237 PR_EEP("Disable 5Ghz HT20", !!(pBase->opCapFlags &238 AR5416_OPFLAGS_N_5G_HT20));239 PR_EEP("Disable 5Ghz HT40", !!(pBase->opCapFlags &240 AR5416_OPFLAGS_N_5G_HT40));241 PR_EEP("Big Endian", !!(pBase->eepMisc & AR5416_EEPMISC_BIG_ENDIAN));242 PR_EEP("Cal Bin Major Ver", (binBuildNumber >> 24) & 0xFF);243 PR_EEP("Cal Bin Minor Ver", (binBuildNumber >> 16) & 0xFF);244 PR_EEP("Cal Bin Build", (binBuildNumber >> 8) & 0xFF);245 PR_EEP("OpenLoop Power Ctrl", pBase->openLoopPwrCntl);246 247 len += scnprintf(buf + len, size - len, "%20s : %pM\n", "MacAddress",248 pBase->macAddr);249 250out:251 if (len > size)252 len = size;253 254 return len;255}256#else257static u32 ath9k_hw_def_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,258 u8 *buf, u32 len, u32 size)259{260 return 0;261}262#endif263 264static int ath9k_hw_def_check_eeprom(struct ath_hw *ah)265{266 struct ar5416_eeprom_def *eep = &ah->eeprom.def;267 struct ath_common *common = ath9k_hw_common(ah);268 u32 el;269 bool need_swap;270 int i, err;271 272 err = ath9k_hw_nvram_swap_data(ah, &need_swap, SIZE_EEPROM_DEF);273 if (err)274 return err;275 276 if (need_swap)277 el = swab16((__force u16)eep->baseEepHeader.length);278 else279 el = le16_to_cpu(eep->baseEepHeader.length);280 281 el = min(el / sizeof(u16), SIZE_EEPROM_DEF);282 if (!ath9k_hw_nvram_validate_checksum(ah, el))283 return -EINVAL;284 285 if (need_swap) {286 u32 j;287 288 EEPROM_FIELD_SWAB16(eep->baseEepHeader.length);289 EEPROM_FIELD_SWAB16(eep->baseEepHeader.checksum);290 EEPROM_FIELD_SWAB16(eep->baseEepHeader.version);291 EEPROM_FIELD_SWAB16(eep->baseEepHeader.regDmn[0]);292 EEPROM_FIELD_SWAB16(eep->baseEepHeader.regDmn[1]);293 EEPROM_FIELD_SWAB16(eep->baseEepHeader.rfSilent);294 EEPROM_FIELD_SWAB16(eep->baseEepHeader.blueToothOptions);295 EEPROM_FIELD_SWAB16(eep->baseEepHeader.deviceCap);296 297 for (j = 0; j < ARRAY_SIZE(eep->modalHeader); j++) {298 struct modal_eep_header *pModal =299 &eep->modalHeader[j];300 EEPROM_FIELD_SWAB32(pModal->antCtrlCommon);301 302 for (i = 0; i < AR5416_MAX_CHAINS; i++)303 EEPROM_FIELD_SWAB32(pModal->antCtrlChain[i]);304 305 for (i = 0; i < 3; i++)306 EEPROM_FIELD_SWAB16(pModal->xpaBiasLvlFreq[i]);307 308 for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++)309 EEPROM_FIELD_SWAB16(310 pModal->spurChans[i].spurChan);311 }312 }313 314 if (!ath9k_hw_nvram_check_version(ah, AR5416_EEP_VER,315 AR5416_EEP_NO_BACK_VER))316 return -EINVAL;317 318 /* Enable fixup for AR_AN_TOP2 if necessary */319 if ((ah->hw_version.devid == AR9280_DEVID_PCI) &&320 ((le16_to_cpu(eep->baseEepHeader.version) & 0xff) > 0x0a) &&321 (eep->baseEepHeader.pwdclkind == 0))322 ah->need_an_top2_fixup = true;323 324 if ((common->bus_ops->ath_bus_type == ATH_USB) &&325 (AR_SREV_9280(ah)))326 eep->modalHeader[0].xpaBiasLvl = 0;327 328 return 0;329}330 331#undef SIZE_EEPROM_DEF332 333static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah,334 enum eeprom_param param)335{336 struct ar5416_eeprom_def *eep = &ah->eeprom.def;337 struct modal_eep_header *pModal = eep->modalHeader;338 struct base_eep_header *pBase = &eep->baseEepHeader;339 int band = 0;340 341 switch (param) {342 case EEP_NFTHRESH_5:343 return pModal[0].noiseFloorThreshCh[0];344 case EEP_NFTHRESH_2:345 return pModal[1].noiseFloorThreshCh[0];346 case EEP_MAC_LSW:347 return get_unaligned_be16(pBase->macAddr);348 case EEP_MAC_MID:349 return get_unaligned_be16(pBase->macAddr + 2);350 case EEP_MAC_MSW:351 return get_unaligned_be16(pBase->macAddr + 4);352 case EEP_REG_0:353 return le16_to_cpu(pBase->regDmn[0]);354 case EEP_OP_CAP:355 return le16_to_cpu(pBase->deviceCap);356 case EEP_OP_MODE:357 return pBase->opCapFlags;358 case EEP_RF_SILENT:359 return le16_to_cpu(pBase->rfSilent);360 case EEP_OB_5:361 return pModal[0].ob;362 case EEP_DB_5:363 return pModal[0].db;364 case EEP_OB_2:365 return pModal[1].ob;366 case EEP_DB_2:367 return pModal[1].db;368 case EEP_TX_MASK:369 return pBase->txMask;370 case EEP_RX_MASK:371 return pBase->rxMask;372 case EEP_FSTCLK_5G:373 return pBase->fastClk5g;374 case EEP_RXGAIN_TYPE:375 return pBase->rxGainType;376 case EEP_TXGAIN_TYPE:377 return pBase->txGainType;378 case EEP_OL_PWRCTRL:379 if (ath9k_hw_def_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_19)380 return pBase->openLoopPwrCntl ? true : false;381 else382 return false;383 case EEP_RC_CHAIN_MASK:384 if (ath9k_hw_def_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_19)385 return pBase->rcChainMask;386 else387 return 0;388 case EEP_DAC_HPWR_5G:389 if (ath9k_hw_def_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_20)390 return pBase->dacHiPwrMode_5G;391 else392 return 0;393 case EEP_FRAC_N_5G:394 if (ath9k_hw_def_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_22)395 return pBase->frac_n_5g;396 else397 return 0;398 case EEP_PWR_TABLE_OFFSET:399 if (ath9k_hw_def_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_21)400 return pBase->pwr_table_offset;401 else402 return AR5416_PWR_TABLE_OFFSET_DB;403 case EEP_ANTENNA_GAIN_2G:404 band = 1;405 fallthrough;406 case EEP_ANTENNA_GAIN_5G:407 return max_t(u8, max_t(u8,408 pModal[band].antennaGainCh[0],409 pModal[band].antennaGainCh[1]),410 pModal[band].antennaGainCh[2]);411 default:412 return 0;413 }414}415 416static void ath9k_hw_def_set_gain(struct ath_hw *ah,417 struct modal_eep_header *pModal,418 struct ar5416_eeprom_def *eep,419 u8 txRxAttenLocal, int regChainOffset, int i)420{421 ENABLE_REG_RMW_BUFFER(ah);422 if (ath9k_hw_def_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_3) {423 txRxAttenLocal = pModal->txRxAttenCh[i];424 425 if (AR_SREV_9280_20_OR_LATER(ah)) {426 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,427 AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN,428 pModal->bswMargin[i]);429 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,430 AR_PHY_GAIN_2GHZ_XATTEN1_DB,431 pModal->bswAtten[i]);432 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,433 AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,434 pModal->xatten2Margin[i]);435 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,436 AR_PHY_GAIN_2GHZ_XATTEN2_DB,437 pModal->xatten2Db[i]);438 } else {439 REG_RMW(ah, AR_PHY_GAIN_2GHZ + regChainOffset,440 SM(pModal-> bswMargin[i], AR_PHY_GAIN_2GHZ_BSW_MARGIN),441 AR_PHY_GAIN_2GHZ_BSW_MARGIN);442 REG_RMW(ah, AR_PHY_GAIN_2GHZ + regChainOffset,443 SM(pModal->bswAtten[i], AR_PHY_GAIN_2GHZ_BSW_ATTEN),444 AR_PHY_GAIN_2GHZ_BSW_ATTEN);445 }446 }447 448 if (AR_SREV_9280_20_OR_LATER(ah)) {449 REG_RMW_FIELD(ah,450 AR_PHY_RXGAIN + regChainOffset,451 AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal);452 REG_RMW_FIELD(ah,453 AR_PHY_RXGAIN + regChainOffset,454 AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[i]);455 } else {456 REG_RMW(ah, AR_PHY_RXGAIN + regChainOffset,457 SM(txRxAttenLocal, AR_PHY_RXGAIN_TXRX_ATTEN),458 AR_PHY_RXGAIN_TXRX_ATTEN);459 REG_RMW(ah, AR_PHY_GAIN_2GHZ + regChainOffset,460 SM(pModal->rxTxMarginCh[i], AR_PHY_GAIN_2GHZ_RXTX_MARGIN),461 AR_PHY_GAIN_2GHZ_RXTX_MARGIN);462 }463 REG_RMW_BUFFER_FLUSH(ah);464}465 466static void ath9k_hw_def_set_board_values(struct ath_hw *ah,467 struct ath9k_channel *chan)468{469 struct modal_eep_header *pModal;470 struct ar5416_eeprom_def *eep = &ah->eeprom.def;471 int i, regChainOffset;472 u8 txRxAttenLocal;473 u32 antCtrlCommon;474 475 pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]);476 txRxAttenLocal = IS_CHAN_2GHZ(chan) ? 23 : 44;477 antCtrlCommon = le32_to_cpu(pModal->antCtrlCommon);478 479 REG_WRITE(ah, AR_PHY_SWITCH_COM, antCtrlCommon & 0xffff);480 481 for (i = 0; i < AR5416_MAX_CHAINS; i++) {482 if (AR_SREV_9280(ah)) {483 if (i >= 2)484 break;485 }486 487 if ((ah->rxchainmask == 5 || ah->txchainmask == 5) && (i != 0))488 regChainOffset = (i == 1) ? 0x2000 : 0x1000;489 else490 regChainOffset = i * 0x1000;491 492 REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset,493 le32_to_cpu(pModal->antCtrlChain[i]));494 495 REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset,496 (REG_READ(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset) &497 ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF |498 AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) |499 SM(pModal->iqCalICh[i],500 AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) |501 SM(pModal->iqCalQCh[i],502 AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF));503 504 ath9k_hw_def_set_gain(ah, pModal, eep, txRxAttenLocal,505 regChainOffset, i);506 }507 508 if (AR_SREV_9280_20_OR_LATER(ah)) {509 if (IS_CHAN_2GHZ(chan)) {510 ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0,511 AR_AN_RF2G1_CH0_OB,512 AR_AN_RF2G1_CH0_OB_S,513 pModal->ob);514 ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0,515 AR_AN_RF2G1_CH0_DB,516 AR_AN_RF2G1_CH0_DB_S,517 pModal->db);518 ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH1,519 AR_AN_RF2G1_CH1_OB,520 AR_AN_RF2G1_CH1_OB_S,521 pModal->ob_ch1);522 ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH1,523 AR_AN_RF2G1_CH1_DB,524 AR_AN_RF2G1_CH1_DB_S,525 pModal->db_ch1);526 } else {527 ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH0,528 AR_AN_RF5G1_CH0_OB5,529 AR_AN_RF5G1_CH0_OB5_S,530 pModal->ob);531 ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH0,532 AR_AN_RF5G1_CH0_DB5,533 AR_AN_RF5G1_CH0_DB5_S,534 pModal->db);535 ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH1,536 AR_AN_RF5G1_CH1_OB5,537 AR_AN_RF5G1_CH1_OB5_S,538 pModal->ob_ch1);539 ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH1,540 AR_AN_RF5G1_CH1_DB5,541 AR_AN_RF5G1_CH1_DB5_S,542 pModal->db_ch1);543 }544 ath9k_hw_analog_shift_rmw(ah, AR_AN_TOP2,545 AR_AN_TOP2_XPABIAS_LVL,546 AR_AN_TOP2_XPABIAS_LVL_S,547 pModal->xpaBiasLvl);548 ath9k_hw_analog_shift_rmw(ah, AR_AN_TOP2,549 AR_AN_TOP2_LOCALBIAS,550 AR_AN_TOP2_LOCALBIAS_S,551 !!(pModal->lna_ctl &552 LNA_CTL_LOCAL_BIAS));553 REG_RMW_FIELD(ah, AR_PHY_XPA_CFG, AR_PHY_FORCE_XPA_CFG,554 !!(pModal->lna_ctl & LNA_CTL_FORCE_XPA));555 }556 557 REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH,558 pModal->switchSettling);559 REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC,560 pModal->adcDesiredSize);561 562 if (!AR_SREV_9280_20_OR_LATER(ah))563 REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,564 AR_PHY_DESIRED_SZ_PGA,565 pModal->pgaDesiredSize);566 567 REG_WRITE(ah, AR_PHY_RF_CTL4,568 SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF)569 | SM(pModal->txEndToXpaOff,570 AR_PHY_RF_CTL4_TX_END_XPAB_OFF)571 | SM(pModal->txFrameToXpaOn,572 AR_PHY_RF_CTL4_FRAME_XPAA_ON)573 | SM(pModal->txFrameToXpaOn,574 AR_PHY_RF_CTL4_FRAME_XPAB_ON));575 576 REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON,577 pModal->txEndToRxOn);578 579 if (AR_SREV_9280_20_OR_LATER(ah)) {580 REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62,581 pModal->thresh62);582 REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0,583 AR_PHY_EXT_CCA0_THRESH62,584 pModal->thresh62);585 } else {586 REG_RMW_FIELD(ah, AR_PHY_CCA, AR_PHY_CCA_THRESH62,587 pModal->thresh62);588 REG_RMW_FIELD(ah, AR_PHY_EXT_CCA,589 AR_PHY_EXT_CCA_THRESH62,590 pModal->thresh62);591 }592 593 if (ath9k_hw_def_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_2) {594 REG_RMW_FIELD(ah, AR_PHY_RF_CTL2,595 AR_PHY_TX_END_DATA_START,596 pModal->txFrameToDataStart);597 REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_PA_ON,598 pModal->txFrameToPaOn);599 }600 601 if (ath9k_hw_def_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_3) {602 if (IS_CHAN_HT40(chan))603 REG_RMW_FIELD(ah, AR_PHY_SETTLING,604 AR_PHY_SETTLING_SWITCH,605 pModal->swSettleHt40);606 }607 608 if (AR_SREV_9280_20_OR_LATER(ah) &&609 ath9k_hw_def_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_19)610 REG_RMW_FIELD(ah, AR_PHY_CCK_TX_CTRL,611 AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK,612 pModal->miscBits);613 614 615 if (AR_SREV_9280_20(ah) &&616 ath9k_hw_def_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_20) {617 if (IS_CHAN_2GHZ(chan))618 REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE,619 eep->baseEepHeader.dacLpMode);620 else if (eep->baseEepHeader.dacHiPwrMode_5G)621 REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE, 0);622 else623 REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE,624 eep->baseEepHeader.dacLpMode);625 626 udelay(100);627 628 REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL, AR_PHY_FRAME_CTL_TX_CLIP,629 pModal->miscBits >> 2);630 631 REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL9,632 AR_PHY_TX_DESIRED_SCALE_CCK,633 eep->baseEepHeader.desiredScaleCCK);634 }635}636 637static void ath9k_hw_def_set_addac(struct ath_hw *ah,638 struct ath9k_channel *chan)639{640#define XPA_LVL_FREQ(cnt) (le16_to_cpu(pModal->xpaBiasLvlFreq[cnt]))641 struct modal_eep_header *pModal;642 struct ar5416_eeprom_def *eep = &ah->eeprom.def;643 u8 biaslevel;644 645 if (ah->hw_version.macVersion != AR_SREV_VERSION_9160)646 return;647 648 if (ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_MINOR_VER_7)649 return;650 651 pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]);652 653 if (pModal->xpaBiasLvl != 0xff) {654 biaslevel = pModal->xpaBiasLvl;655 } else {656 u16 resetFreqBin, freqBin, freqCount = 0;657 struct chan_centers centers;658 659 ath9k_hw_get_channel_centers(ah, chan, ¢ers);660 661 resetFreqBin = FREQ2FBIN(centers.synth_center,662 IS_CHAN_2GHZ(chan));663 freqBin = XPA_LVL_FREQ(0) & 0xff;664 biaslevel = (u8) (XPA_LVL_FREQ(0) >> 14);665 666 freqCount++;667 668 while (freqCount < 3) {669 if (XPA_LVL_FREQ(freqCount) == 0x0)670 break;671 672 freqBin = XPA_LVL_FREQ(freqCount) & 0xff;673 if (resetFreqBin >= freqBin)674 biaslevel = (u8)(XPA_LVL_FREQ(freqCount) >> 14);675 else676 break;677 freqCount++;678 }679 }680 681 if (IS_CHAN_2GHZ(chan)) {682 INI_RA(&ah->iniAddac, 7, 1) = (INI_RA(&ah->iniAddac,683 7, 1) & (~0x18)) | biaslevel << 3;684 } else {685 INI_RA(&ah->iniAddac, 6, 1) = (INI_RA(&ah->iniAddac,686 6, 1) & (~0xc0)) | biaslevel << 6;687 }688#undef XPA_LVL_FREQ689}690 691static int16_t ath9k_change_gain_boundary_setting(struct ath_hw *ah,692 u16 *gb,693 u16 numXpdGain,694 u16 pdGainOverlap_t2,695 int8_t pwr_table_offset,696 int16_t *diff)697 698{699 u16 k;700 701 /* Prior to writing the boundaries or the pdadc vs. power table702 * into the chip registers the default starting point on the pdadc703 * vs. power table needs to be checked and the curve boundaries704 * adjusted accordingly705 */706 if (AR_SREV_9280_20_OR_LATER(ah)) {707 u16 gb_limit;708 709 if (AR5416_PWR_TABLE_OFFSET_DB != pwr_table_offset) {710 /* get the difference in dB */711 *diff = (u16)(pwr_table_offset - AR5416_PWR_TABLE_OFFSET_DB);712 /* get the number of half dB steps */713 *diff *= 2;714 /* change the original gain boundary settings715 * by the number of half dB steps716 */717 for (k = 0; k < numXpdGain; k++)718 gb[k] = (u16)(gb[k] - *diff);719 }720 /* Because of a hardware limitation, ensure the gain boundary721 * is not larger than (63 - overlap)722 */723 gb_limit = (u16)(MAX_RATE_POWER - pdGainOverlap_t2);724 725 for (k = 0; k < numXpdGain; k++)726 gb[k] = (u16)min(gb_limit, gb[k]);727 }728 729 return *diff;730}731 732static void ath9k_adjust_pdadc_values(struct ath_hw *ah,733 int8_t pwr_table_offset,734 int16_t diff,735 u8 *pdadcValues)736{737#define NUM_PDADC(diff) (AR5416_NUM_PDADC_VALUES - diff)738 u16 k;739 740 /* If this is a board that has a pwrTableOffset that differs from741 * the default AR5416_PWR_TABLE_OFFSET_DB then the start of the742 * pdadc vs pwr table needs to be adjusted prior to writing to the743 * chip.744 */745 if (AR_SREV_9280_20_OR_LATER(ah)) {746 if (AR5416_PWR_TABLE_OFFSET_DB != pwr_table_offset) {747 /* shift the table to start at the new offset */748 for (k = 0; k < (u16)NUM_PDADC(diff); k++ ) {749 pdadcValues[k] = pdadcValues[k + diff];750 }751 752 /* fill the back of the table */753 for (k = (u16)NUM_PDADC(diff); k < NUM_PDADC(0); k++) {754 pdadcValues[k] = pdadcValues[NUM_PDADC(diff)];755 }756 }757 }758#undef NUM_PDADC759}760 761static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah,762 struct ath9k_channel *chan)763{764#define SM_PD_GAIN(x) SM(0x38, AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_##x)765#define SM_PDGAIN_B(x, y) \766 SM((gainBoundaries[x]), AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_##y)767 struct ath_common *common = ath9k_hw_common(ah);768 struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;769 struct cal_data_per_freq *pRawDataset;770 u8 *pCalBChans = NULL;771 u16 pdGainOverlap_t2;772 static u8 pdadcValues[AR5416_NUM_PDADC_VALUES];773 u16 gainBoundaries[AR5416_PD_GAINS_IN_MASK];774 u16 numPiers, i, j;775 int16_t diff = 0;776 u16 numXpdGain, xpdMask;777 u16 xpdGainValues[AR5416_NUM_PD_GAINS] = { 0, 0, 0, 0 };778 u32 reg32, regOffset, regChainOffset;779 int16_t modalIdx;780 int8_t pwr_table_offset;781 782 modalIdx = IS_CHAN_2GHZ(chan) ? 1 : 0;783 xpdMask = pEepData->modalHeader[modalIdx].xpdGain;784 785 pwr_table_offset = ah->eep_ops->get_eeprom(ah, EEP_PWR_TABLE_OFFSET);786 787 if (ath9k_hw_def_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_2) {788 pdGainOverlap_t2 =789 pEepData->modalHeader[modalIdx].pdGainOverlap;790 } else {791 pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5),792 AR_PHY_TPCRG5_PD_GAIN_OVERLAP));793 }794 795 if (IS_CHAN_2GHZ(chan)) {796 pCalBChans = pEepData->calFreqPier2G;797 numPiers = AR5416_NUM_2G_CAL_PIERS;798 } else {799 pCalBChans = pEepData->calFreqPier5G;800 numPiers = AR5416_NUM_5G_CAL_PIERS;801 }802 803 if (OLC_FOR_AR9280_20_LATER(ah) && IS_CHAN_2GHZ(chan)) {804 pRawDataset = pEepData->calPierData2G[0];805 ah->initPDADC = ((struct calDataPerFreqOpLoop *)806 pRawDataset)->vpdPdg[0][0];807 }808 809 numXpdGain = 0;810 811 for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) {812 if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) {813 if (numXpdGain >= AR5416_NUM_PD_GAINS)814 break;815 xpdGainValues[numXpdGain] =816 (u16)(AR5416_PD_GAINS_IN_MASK - i);817 numXpdGain++;818 }819 }820 821 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN,822 (numXpdGain - 1) & 0x3);823 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1,824 xpdGainValues[0]);825 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2,826 xpdGainValues[1]);827 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3,828 xpdGainValues[2]);829 830 for (i = 0; i < AR5416_MAX_CHAINS; i++) {831 if ((ah->rxchainmask == 5 || ah->txchainmask == 5) &&832 (i != 0)) {833 regChainOffset = (i == 1) ? 0x2000 : 0x1000;834 } else835 regChainOffset = i * 0x1000;836 837 if (pEepData->baseEepHeader.txMask & (1 << i)) {838 if (IS_CHAN_2GHZ(chan))839 pRawDataset = pEepData->calPierData2G[i];840 else841 pRawDataset = pEepData->calPierData5G[i];842 843 844 if (OLC_FOR_AR9280_20_LATER(ah)) {845 u8 pcdacIdx;846 u8 txPower;847 848 ath9k_get_txgain_index(ah, chan,849 (struct calDataPerFreqOpLoop *)pRawDataset,850 pCalBChans, numPiers, &txPower, &pcdacIdx);851 ath9k_olc_get_pdadcs(ah, pcdacIdx,852 txPower/2, pdadcValues);853 } else {854 ath9k_hw_get_gain_boundaries_pdadcs(ah,855 chan, pRawDataset,856 pCalBChans, numPiers,857 pdGainOverlap_t2,858 gainBoundaries,859 pdadcValues,860 numXpdGain);861 }862 863 diff = ath9k_change_gain_boundary_setting(ah,864 gainBoundaries,865 numXpdGain,866 pdGainOverlap_t2,867 pwr_table_offset,868 &diff);869 870 ENABLE_REGWRITE_BUFFER(ah);871 872 if (OLC_FOR_AR9280_20_LATER(ah)) {873 REG_WRITE(ah,874 AR_PHY_TPCRG5 + regChainOffset,875 SM(0x6,876 AR_PHY_TPCRG5_PD_GAIN_OVERLAP) |877 SM_PD_GAIN(1) | SM_PD_GAIN(2) |878 SM_PD_GAIN(3) | SM_PD_GAIN(4));879 } else {880 REG_WRITE(ah,881 AR_PHY_TPCRG5 + regChainOffset,882 SM(pdGainOverlap_t2,883 AR_PHY_TPCRG5_PD_GAIN_OVERLAP)|884 SM_PDGAIN_B(0, 1) |885 SM_PDGAIN_B(1, 2) |886 SM_PDGAIN_B(2, 3) |887 SM_PDGAIN_B(3, 4));888 }889 890 ath9k_adjust_pdadc_values(ah, pwr_table_offset,891 diff, pdadcValues);892 893 regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset;894 for (j = 0; j < 32; j++) {895 reg32 = get_unaligned_le32(&pdadcValues[4 * j]);896 REG_WRITE(ah, regOffset, reg32);897 898 ath_dbg(common, EEPROM,899 "PDADC (%d,%4x): %4.4x %8.8x\n",900 i, regChainOffset, regOffset,901 reg32);902 ath_dbg(common, EEPROM,903 "PDADC: Chain %d | PDADC %3d Value %3d | PDADC %3d Value %3d | PDADC %3d Value %3d | PDADC %3d Value %3d |\n",904 i, 4 * j, pdadcValues[4 * j],905 4 * j + 1, pdadcValues[4 * j + 1],906 4 * j + 2, pdadcValues[4 * j + 2],907 4 * j + 3, pdadcValues[4 * j + 3]);908 909 regOffset += 4;910 }911 REGWRITE_BUFFER_FLUSH(ah);912 }913 }914 915#undef SM_PD_GAIN916#undef SM_PDGAIN_B917}918 919static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah,920 struct ath9k_channel *chan,921 int16_t *ratesArray,922 u16 cfgCtl,923 u16 antenna_reduction,924 u16 powerLimit)925{926 struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;927 u16 twiceMaxEdgePower;928 int i;929 struct cal_ctl_data *rep;930 struct cal_target_power_leg targetPowerOfdm, targetPowerCck = {931 0, { 0, 0, 0, 0}932 };933 struct cal_target_power_leg targetPowerOfdmExt = {934 0, { 0, 0, 0, 0} }, targetPowerCckExt = {935 0, { 0, 0, 0, 0 }936 };937 struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = {938 0, {0, 0, 0, 0}939 };940 u16 scaledPower = 0, minCtlPower;941 static const u16 ctlModesFor11a[] = {942 CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40943 };944 static const u16 ctlModesFor11g[] = {945 CTL_11B, CTL_11G, CTL_2GHT20,946 CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40947 };948 u16 numCtlModes;949 const u16 *pCtlMode;950 u16 ctlMode, freq;951 struct chan_centers centers;952 int tx_chainmask;953 u16 twiceMinEdgePower;954 955 tx_chainmask = ah->txchainmask;956 957 ath9k_hw_get_channel_centers(ah, chan, ¢ers);958 959 scaledPower = ath9k_hw_get_scaled_power(ah, powerLimit,960 antenna_reduction);961 962 if (IS_CHAN_2GHZ(chan)) {963 numCtlModes = ARRAY_SIZE(ctlModesFor11g) -964 SUB_NUM_CTL_MODES_AT_2G_40;965 pCtlMode = ctlModesFor11g;966 967 ath9k_hw_get_legacy_target_powers(ah, chan,968 pEepData->calTargetPowerCck,969 AR5416_NUM_2G_CCK_TARGET_POWERS,970 &targetPowerCck, 4, false);971 ath9k_hw_get_legacy_target_powers(ah, chan,972 pEepData->calTargetPower2G,973 AR5416_NUM_2G_20_TARGET_POWERS,974 &targetPowerOfdm, 4, false);975 ath9k_hw_get_target_powers(ah, chan,976 pEepData->calTargetPower2GHT20,977 AR5416_NUM_2G_20_TARGET_POWERS,978 &targetPowerHt20, 8, false);979 980 if (IS_CHAN_HT40(chan)) {981 numCtlModes = ARRAY_SIZE(ctlModesFor11g);982 ath9k_hw_get_target_powers(ah, chan,983 pEepData->calTargetPower2GHT40,984 AR5416_NUM_2G_40_TARGET_POWERS,985 &targetPowerHt40, 8, true);986 ath9k_hw_get_legacy_target_powers(ah, chan,987 pEepData->calTargetPowerCck,988 AR5416_NUM_2G_CCK_TARGET_POWERS,989 &targetPowerCckExt, 4, true);990 ath9k_hw_get_legacy_target_powers(ah, chan,991 pEepData->calTargetPower2G,992 AR5416_NUM_2G_20_TARGET_POWERS,993 &targetPowerOfdmExt, 4, true);994 }995 } else {996 numCtlModes = ARRAY_SIZE(ctlModesFor11a) -997 SUB_NUM_CTL_MODES_AT_5G_40;998 pCtlMode = ctlModesFor11a;999 1000 ath9k_hw_get_legacy_target_powers(ah, chan,1001 pEepData->calTargetPower5G,1002 AR5416_NUM_5G_20_TARGET_POWERS,1003 &targetPowerOfdm, 4, false);1004 ath9k_hw_get_target_powers(ah, chan,1005 pEepData->calTargetPower5GHT20,1006 AR5416_NUM_5G_20_TARGET_POWERS,1007 &targetPowerHt20, 8, false);1008 1009 if (IS_CHAN_HT40(chan)) {1010 numCtlModes = ARRAY_SIZE(ctlModesFor11a);1011 ath9k_hw_get_target_powers(ah, chan,1012 pEepData->calTargetPower5GHT40,1013 AR5416_NUM_5G_40_TARGET_POWERS,1014 &targetPowerHt40, 8, true);1015 ath9k_hw_get_legacy_target_powers(ah, chan,1016 pEepData->calTargetPower5G,1017 AR5416_NUM_5G_20_TARGET_POWERS,1018 &targetPowerOfdmExt, 4, true);1019 }1020 }1021 1022 for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) {1023 bool isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) ||1024 (pCtlMode[ctlMode] == CTL_2GHT40);1025 if (isHt40CtlMode)1026 freq = centers.synth_center;1027 else if (pCtlMode[ctlMode] & EXT_ADDITIVE)1028 freq = centers.ext_center;1029 else1030 freq = centers.ctl_center;1031 1032 twiceMaxEdgePower = MAX_RATE_POWER;1033 1034 for (i = 0; (i < AR5416_NUM_CTLS) && pEepData->ctlIndex[i]; i++) {1035 if ((((cfgCtl & ~CTL_MODE_M) |1036 (pCtlMode[ctlMode] & CTL_MODE_M)) ==1037 pEepData->ctlIndex[i]) ||1038 (((cfgCtl & ~CTL_MODE_M) |1039 (pCtlMode[ctlMode] & CTL_MODE_M)) ==1040 ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL))) {1041 rep = &(pEepData->ctlData[i]);1042 1043 twiceMinEdgePower = ath9k_hw_get_max_edge_power(freq,1044 rep->ctlEdges[ar5416_get_ntxchains(tx_chainmask) - 1],1045 IS_CHAN_2GHZ(chan), AR5416_NUM_BAND_EDGES);1046 1047 if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) {1048 twiceMaxEdgePower = min(twiceMaxEdgePower,1049 twiceMinEdgePower);1050 } else {1051 twiceMaxEdgePower = twiceMinEdgePower;1052 break;1053 }1054 }1055 }1056 1057 minCtlPower = min(twiceMaxEdgePower, scaledPower);1058 1059 switch (pCtlMode[ctlMode]) {1060 case CTL_11B:1061 for (i = 0; i < ARRAY_SIZE(targetPowerCck.tPow2x); i++) {1062 targetPowerCck.tPow2x[i] =1063 min((u16)targetPowerCck.tPow2x[i],1064 minCtlPower);1065 }1066 break;1067 case CTL_11A:1068 case CTL_11G:1069 for (i = 0; i < ARRAY_SIZE(targetPowerOfdm.tPow2x); i++) {1070 targetPowerOfdm.tPow2x[i] =1071 min((u16)targetPowerOfdm.tPow2x[i],1072 minCtlPower);1073 }1074 break;1075 case CTL_5GHT20:1076 case CTL_2GHT20:1077 for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++) {1078 targetPowerHt20.tPow2x[i] =1079 min((u16)targetPowerHt20.tPow2x[i],1080 minCtlPower);1081 }1082 break;1083 case CTL_11B_EXT:1084 targetPowerCckExt.tPow2x[0] = min((u16)1085 targetPowerCckExt.tPow2x[0],1086 minCtlPower);1087 break;1088 case CTL_11A_EXT:1089 case CTL_11G_EXT:1090 targetPowerOfdmExt.tPow2x[0] = min((u16)1091 targetPowerOfdmExt.tPow2x[0],1092 minCtlPower);1093 break;1094 case CTL_5GHT40:1095 case CTL_2GHT40:1096 for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {1097 targetPowerHt40.tPow2x[i] =1098 min((u16)targetPowerHt40.tPow2x[i],1099 minCtlPower);1100 }1101 break;1102 default:1103 break;1104 }1105 }1106 1107 ratesArray[rate6mb] = ratesArray[rate9mb] = ratesArray[rate12mb] =1108 ratesArray[rate18mb] = ratesArray[rate24mb] =1109 targetPowerOfdm.tPow2x[0];1110 ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1];1111 ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2];1112 ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3];1113 ratesArray[rateXr] = targetPowerOfdm.tPow2x[0];1114 1115 for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++)1116 ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i];1117 1118 if (IS_CHAN_2GHZ(chan)) {1119 ratesArray[rate1l] = targetPowerCck.tPow2x[0];1120 ratesArray[rate2s] = ratesArray[rate2l] =1121 targetPowerCck.tPow2x[1];1122 ratesArray[rate5_5s] = ratesArray[rate5_5l] =1123 targetPowerCck.tPow2x[2];1124 ratesArray[rate11s] = ratesArray[rate11l] =1125 targetPowerCck.tPow2x[3];1126 }1127 if (IS_CHAN_HT40(chan)) {1128 for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {1129 ratesArray[rateHt40_0 + i] =1130 targetPowerHt40.tPow2x[i];1131 }1132 ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0];1133 ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0];1134 ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0];1135 if (IS_CHAN_2GHZ(chan)) {1136 ratesArray[rateExtCck] =1137 targetPowerCckExt.tPow2x[0];1138 }1139 }1140}1141 1142static void ath9k_hw_def_set_txpower(struct ath_hw *ah,1143 struct ath9k_channel *chan,1144 u16 cfgCtl,1145 u8 twiceAntennaReduction,1146 u8 powerLimit, bool test)1147{1148#define RT_AR_DELTA(x) (ratesArray[x] - cck_ofdm_delta)1149 struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);1150 struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;1151 struct modal_eep_header *pModal =1152 &(pEepData->modalHeader[IS_CHAN_2GHZ(chan)]);1153 int16_t ratesArray[Ar5416RateSize];1154 u8 ht40PowerIncForPdadc = 2;1155 int i, cck_ofdm_delta = 0;1156 1157 memset(ratesArray, 0, sizeof(ratesArray));1158 1159 if (ath9k_hw_def_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_2)1160 ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;1161 1162 ath9k_hw_set_def_power_per_rate_table(ah, chan,1163 &ratesArray[0], cfgCtl,1164 twiceAntennaReduction,1165 powerLimit);1166 1167 ath9k_hw_set_def_power_cal_table(ah, chan);1168 1169 regulatory->max_power_level = 0;1170 for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {1171 if (ratesArray[i] > MAX_RATE_POWER)1172 ratesArray[i] = MAX_RATE_POWER;1173 if (ratesArray[i] > regulatory->max_power_level)1174 regulatory->max_power_level = ratesArray[i];1175 }1176 1177 ath9k_hw_update_regulatory_maxpower(ah);1178 1179 if (test)1180 return;1181 1182 if (AR_SREV_9280_20_OR_LATER(ah)) {1183 for (i = 0; i < Ar5416RateSize; i++) {1184 int8_t pwr_table_offset;1185 1186 pwr_table_offset = ah->eep_ops->get_eeprom(ah,1187 EEP_PWR_TABLE_OFFSET);1188 ratesArray[i] -= pwr_table_offset * 2;1189 }1190 }1191 1192 ENABLE_REGWRITE_BUFFER(ah);1193 1194 REG_WRITE(ah, AR_PHY_POWER_TX_RATE1,1195 ATH9K_POW_SM(ratesArray[rate18mb], 24)1196 | ATH9K_POW_SM(ratesArray[rate12mb], 16)1197 | ATH9K_POW_SM(ratesArray[rate9mb], 8)1198 | ATH9K_POW_SM(ratesArray[rate6mb], 0));1199 REG_WRITE(ah, AR_PHY_POWER_TX_RATE2,1200 ATH9K_POW_SM(ratesArray[rate54mb], 24)1201 | ATH9K_POW_SM(ratesArray[rate48mb], 16)1202 | ATH9K_POW_SM(ratesArray[rate36mb], 8)1203 | ATH9K_POW_SM(ratesArray[rate24mb], 0));1204 1205 if (IS_CHAN_2GHZ(chan)) {1206 if (OLC_FOR_AR9280_20_LATER(ah)) {1207 cck_ofdm_delta = 2;1208 REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,1209 ATH9K_POW_SM(RT_AR_DELTA(rate2s), 24)1210 | ATH9K_POW_SM(RT_AR_DELTA(rate2l), 16)1211 | ATH9K_POW_SM(ratesArray[rateXr], 8)1212 | ATH9K_POW_SM(RT_AR_DELTA(rate1l), 0));1213 REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,1214 ATH9K_POW_SM(RT_AR_DELTA(rate11s), 24)1215 | ATH9K_POW_SM(RT_AR_DELTA(rate11l), 16)1216 | ATH9K_POW_SM(RT_AR_DELTA(rate5_5s), 8)1217 | ATH9K_POW_SM(RT_AR_DELTA(rate5_5l), 0));1218 } else {1219 REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,1220 ATH9K_POW_SM(ratesArray[rate2s], 24)1221 | ATH9K_POW_SM(ratesArray[rate2l], 16)1222 | ATH9K_POW_SM(ratesArray[rateXr], 8)1223 | ATH9K_POW_SM(ratesArray[rate1l], 0));1224 REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,1225 ATH9K_POW_SM(ratesArray[rate11s], 24)1226 | ATH9K_POW_SM(ratesArray[rate11l], 16)1227 | ATH9K_POW_SM(ratesArray[rate5_5s], 8)1228 | ATH9K_POW_SM(ratesArray[rate5_5l], 0));1229 }1230 }1231 1232 REG_WRITE(ah, AR_PHY_POWER_TX_RATE5,1233 ATH9K_POW_SM(ratesArray[rateHt20_3], 24)1234 | ATH9K_POW_SM(ratesArray[rateHt20_2], 16)1235 | ATH9K_POW_SM(ratesArray[rateHt20_1], 8)1236 | ATH9K_POW_SM(ratesArray[rateHt20_0], 0));1237 REG_WRITE(ah, AR_PHY_POWER_TX_RATE6,1238 ATH9K_POW_SM(ratesArray[rateHt20_7], 24)1239 | ATH9K_POW_SM(ratesArray[rateHt20_6], 16)1240 | ATH9K_POW_SM(ratesArray[rateHt20_5], 8)1241 | ATH9K_POW_SM(ratesArray[rateHt20_4], 0));1242 1243 if (IS_CHAN_HT40(chan)) {1244 REG_WRITE(ah, AR_PHY_POWER_TX_RATE7,1245 ATH9K_POW_SM(ratesArray[rateHt40_3] +1246 ht40PowerIncForPdadc, 24)1247 | ATH9K_POW_SM(ratesArray[rateHt40_2] +1248 ht40PowerIncForPdadc, 16)1249 | ATH9K_POW_SM(ratesArray[rateHt40_1] +1250 ht40PowerIncForPdadc, 8)1251 | ATH9K_POW_SM(ratesArray[rateHt40_0] +1252 ht40PowerIncForPdadc, 0));1253 REG_WRITE(ah, AR_PHY_POWER_TX_RATE8,1254 ATH9K_POW_SM(ratesArray[rateHt40_7] +1255 ht40PowerIncForPdadc, 24)1256 | ATH9K_POW_SM(ratesArray[rateHt40_6] +1257 ht40PowerIncForPdadc, 16)1258 | ATH9K_POW_SM(ratesArray[rateHt40_5] +1259 ht40PowerIncForPdadc, 8)1260 | ATH9K_POW_SM(ratesArray[rateHt40_4] +1261 ht40PowerIncForPdadc, 0));1262 if (OLC_FOR_AR9280_20_LATER(ah)) {1263 REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,1264 ATH9K_POW_SM(ratesArray[rateExtOfdm], 24)1265 | ATH9K_POW_SM(RT_AR_DELTA(rateExtCck), 16)1266 | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)1267 | ATH9K_POW_SM(RT_AR_DELTA(rateDupCck), 0));1268 } else {1269 REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,1270 ATH9K_POW_SM(ratesArray[rateExtOfdm], 24)1271 | ATH9K_POW_SM(ratesArray[rateExtCck], 16)1272 | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)1273 | ATH9K_POW_SM(ratesArray[rateDupCck], 0));1274 }1275 }1276 1277 REG_WRITE(ah, AR_PHY_POWER_TX_SUB,1278 ATH9K_POW_SM(pModal->pwrDecreaseFor3Chain, 6)1279 | ATH9K_POW_SM(pModal->pwrDecreaseFor2Chain, 0));1280 1281 /* TPC initializations */1282 if (ah->tpc_enabled) {1283 int ht40_delta;1284 1285 ht40_delta = (IS_CHAN_HT40(chan)) ? ht40PowerIncForPdadc : 0;1286 ar5008_hw_init_rate_txpower(ah, ratesArray, chan, ht40_delta);1287 /* Enable TPC */1288 REG_WRITE(ah, AR_PHY_POWER_TX_RATE_MAX,1289 MAX_RATE_POWER | AR_PHY_POWER_TX_RATE_MAX_TPC_ENABLE);1290 } else {1291 /* Disable TPC */1292 REG_WRITE(ah, AR_PHY_POWER_TX_RATE_MAX, MAX_RATE_POWER);1293 }1294 1295 REGWRITE_BUFFER_FLUSH(ah);1296}1297 1298static u16 ath9k_hw_def_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz)1299{1300 __le16 spch = ah->eeprom.def.modalHeader[is2GHz].spurChans[i].spurChan;1301 1302 return le16_to_cpu(spch);1303}1304 1305static u8 ath9k_hw_def_get_eepmisc(struct ath_hw *ah)1306{1307 return ah->eeprom.def.baseEepHeader.eepMisc;1308}1309 1310const struct eeprom_ops eep_def_ops = {1311 .check_eeprom = ath9k_hw_def_check_eeprom,1312 .get_eeprom = ath9k_hw_def_get_eeprom,1313 .fill_eeprom = ath9k_hw_def_fill_eeprom,1314 .dump_eeprom = ath9k_hw_def_dump_eeprom,1315 .get_eeprom_ver = ath9k_hw_def_get_eeprom_ver,1316 .get_eeprom_rev = ath9k_hw_def_get_eeprom_rev,1317 .set_board_values = ath9k_hw_def_set_board_values,1318 .set_addac = ath9k_hw_def_set_addac,1319 .set_txpower = ath9k_hw_def_set_txpower,1320 .get_spur_channel = ath9k_hw_def_get_spur_channel,1321 .get_eepmisc = ath9k_hw_def_get_eepmisc1322};1323