1056 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 int ath9k_hw_4k_get_eeprom_ver(struct ath_hw *ah)22{23 u16 version = le16_to_cpu(ah->eeprom.map4k.baseEepHeader.version);24 25 return (version & AR5416_EEP_VER_MAJOR_MASK) >>26 AR5416_EEP_VER_MAJOR_SHIFT;27}28 29static int ath9k_hw_4k_get_eeprom_rev(struct ath_hw *ah)30{31 u16 version = le16_to_cpu(ah->eeprom.map4k.baseEepHeader.version);32 33 return version & AR5416_EEP_VER_MINOR_MASK;34}35 36#define SIZE_EEPROM_4K (sizeof(struct ar5416_eeprom_4k) / sizeof(u16))37 38static bool __ath9k_hw_4k_fill_eeprom(struct ath_hw *ah)39{40 u16 *eep_data = (u16 *)&ah->eeprom.map4k;41 int addr, eep_start_loc = 64;42 43 for (addr = 0; addr < SIZE_EEPROM_4K; addr++) {44 if (!ath9k_hw_nvram_read(ah, addr + eep_start_loc, eep_data))45 return false;46 eep_data++;47 }48 49 return true;50}51 52static bool __ath9k_hw_usb_4k_fill_eeprom(struct ath_hw *ah)53{54 u16 *eep_data = (u16 *)&ah->eeprom.map4k;55 56 ath9k_hw_usb_gen_fill_eeprom(ah, eep_data, 64, SIZE_EEPROM_4K);57 58 return true;59}60 61static bool ath9k_hw_4k_fill_eeprom(struct ath_hw *ah)62{63 struct ath_common *common = ath9k_hw_common(ah);64 65 if (!ath9k_hw_use_flash(ah)) {66 ath_dbg(common, EEPROM, "Reading from EEPROM, not flash\n");67 }68 69 if (common->bus_ops->ath_bus_type == ATH_USB)70 return __ath9k_hw_usb_4k_fill_eeprom(ah);71 else72 return __ath9k_hw_4k_fill_eeprom(ah);73}74 75#ifdef CONFIG_ATH9K_COMMON_DEBUG76static u32 ath9k_dump_4k_modal_eeprom(char *buf, u32 len, u32 size,77 struct modal_eep_4k_header *modal_hdr)78{79 PR_EEP("Chain0 Ant. Control", le32_to_cpu(modal_hdr->antCtrlChain[0]));80 PR_EEP("Ant. Common Control", le32_to_cpu(modal_hdr->antCtrlCommon));81 PR_EEP("Chain0 Ant. Gain", modal_hdr->antennaGainCh[0]);82 PR_EEP("Switch Settle", modal_hdr->switchSettling);83 PR_EEP("Chain0 TxRxAtten", modal_hdr->txRxAttenCh[0]);84 PR_EEP("Chain0 RxTxMargin", modal_hdr->rxTxMarginCh[0]);85 PR_EEP("ADC Desired size", modal_hdr->adcDesiredSize);86 PR_EEP("PGA Desired size", modal_hdr->pgaDesiredSize);87 PR_EEP("Chain0 xlna Gain", modal_hdr->xlnaGainCh[0]);88 PR_EEP("txEndToXpaOff", modal_hdr->txEndToXpaOff);89 PR_EEP("txEndToRxOn", modal_hdr->txEndToRxOn);90 PR_EEP("txFrameToXpaOn", modal_hdr->txFrameToXpaOn);91 PR_EEP("CCA Threshold)", modal_hdr->thresh62);92 PR_EEP("Chain0 NF Threshold", modal_hdr->noiseFloorThreshCh[0]);93 PR_EEP("xpdGain", modal_hdr->xpdGain);94 PR_EEP("External PD", modal_hdr->xpd);95 PR_EEP("Chain0 I Coefficient", modal_hdr->iqCalICh[0]);96 PR_EEP("Chain0 Q Coefficient", modal_hdr->iqCalQCh[0]);97 PR_EEP("pdGainOverlap", modal_hdr->pdGainOverlap);98 PR_EEP("O/D Bias Version", modal_hdr->version);99 PR_EEP("CCK OutputBias", modal_hdr->ob_0);100 PR_EEP("BPSK OutputBias", modal_hdr->ob_1);101 PR_EEP("QPSK OutputBias", modal_hdr->ob_2);102 PR_EEP("16QAM OutputBias", modal_hdr->ob_3);103 PR_EEP("64QAM OutputBias", modal_hdr->ob_4);104 PR_EEP("CCK Driver1_Bias", modal_hdr->db1_0);105 PR_EEP("BPSK Driver1_Bias", modal_hdr->db1_1);106 PR_EEP("QPSK Driver1_Bias", modal_hdr->db1_2);107 PR_EEP("16QAM Driver1_Bias", modal_hdr->db1_3);108 PR_EEP("64QAM Driver1_Bias", modal_hdr->db1_4);109 PR_EEP("CCK Driver2_Bias", modal_hdr->db2_0);110 PR_EEP("BPSK Driver2_Bias", modal_hdr->db2_1);111 PR_EEP("QPSK Driver2_Bias", modal_hdr->db2_2);112 PR_EEP("16QAM Driver2_Bias", modal_hdr->db2_3);113 PR_EEP("64QAM Driver2_Bias", modal_hdr->db2_4);114 PR_EEP("xPA Bias Level", modal_hdr->xpaBiasLvl);115 PR_EEP("txFrameToDataStart", modal_hdr->txFrameToDataStart);116 PR_EEP("txFrameToPaOn", modal_hdr->txFrameToPaOn);117 PR_EEP("HT40 Power Inc.", modal_hdr->ht40PowerIncForPdadc);118 PR_EEP("Chain0 bswAtten", modal_hdr->bswAtten[0]);119 PR_EEP("Chain0 bswMargin", modal_hdr->bswMargin[0]);120 PR_EEP("HT40 Switch Settle", modal_hdr->swSettleHt40);121 PR_EEP("Chain0 xatten2Db", modal_hdr->xatten2Db[0]);122 PR_EEP("Chain0 xatten2Margin", modal_hdr->xatten2Margin[0]);123 PR_EEP("Ant. Diversity ctl1", modal_hdr->antdiv_ctl1);124 PR_EEP("Ant. Diversity ctl2", modal_hdr->antdiv_ctl2);125 PR_EEP("TX Diversity", modal_hdr->tx_diversity);126 127 return len;128}129 130static u32 ath9k_hw_4k_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,131 u8 *buf, u32 len, u32 size)132{133 struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;134 struct base_eep_header_4k *pBase = &eep->baseEepHeader;135 u32 binBuildNumber = le32_to_cpu(pBase->binBuildNumber);136 137 if (!dump_base_hdr) {138 len += scnprintf(buf + len, size - len,139 "%20s :\n", "2GHz modal Header");140 len = ath9k_dump_4k_modal_eeprom(buf, len, size,141 &eep->modalHeader);142 goto out;143 }144 145 PR_EEP("Major Version", ath9k_hw_4k_get_eeprom_ver(ah));146 PR_EEP("Minor Version", ath9k_hw_4k_get_eeprom_rev(ah));147 PR_EEP("Checksum", le16_to_cpu(pBase->checksum));148 PR_EEP("Length", le16_to_cpu(pBase->length));149 PR_EEP("RegDomain1", le16_to_cpu(pBase->regDmn[0]));150 PR_EEP("RegDomain2", le16_to_cpu(pBase->regDmn[1]));151 PR_EEP("TX Mask", pBase->txMask);152 PR_EEP("RX Mask", pBase->rxMask);153 PR_EEP("Allow 5GHz", !!(pBase->opCapFlags & AR5416_OPFLAGS_11A));154 PR_EEP("Allow 2GHz", !!(pBase->opCapFlags & AR5416_OPFLAGS_11G));155 PR_EEP("Disable 2GHz HT20", !!(pBase->opCapFlags &156 AR5416_OPFLAGS_N_2G_HT20));157 PR_EEP("Disable 2GHz HT40", !!(pBase->opCapFlags &158 AR5416_OPFLAGS_N_2G_HT40));159 PR_EEP("Disable 5Ghz HT20", !!(pBase->opCapFlags &160 AR5416_OPFLAGS_N_5G_HT20));161 PR_EEP("Disable 5Ghz HT40", !!(pBase->opCapFlags &162 AR5416_OPFLAGS_N_5G_HT40));163 PR_EEP("Big Endian", !!(pBase->eepMisc & AR5416_EEPMISC_BIG_ENDIAN));164 PR_EEP("Cal Bin Major Ver", (binBuildNumber >> 24) & 0xFF);165 PR_EEP("Cal Bin Minor Ver", (binBuildNumber >> 16) & 0xFF);166 PR_EEP("Cal Bin Build", (binBuildNumber >> 8) & 0xFF);167 PR_EEP("TX Gain type", pBase->txGainType);168 169 len += scnprintf(buf + len, size - len, "%20s : %pM\n", "MacAddress",170 pBase->macAddr);171 172out:173 if (len > size)174 len = size;175 176 return len;177}178#else179static u32 ath9k_hw_4k_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,180 u8 *buf, u32 len, u32 size)181{182 return 0;183}184#endif185 186static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah)187{188 struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;189 u32 el;190 bool need_swap;191 int i, err;192 193 err = ath9k_hw_nvram_swap_data(ah, &need_swap, SIZE_EEPROM_4K);194 if (err)195 return err;196 197 if (need_swap)198 el = swab16((__force u16)eep->baseEepHeader.length);199 else200 el = le16_to_cpu(eep->baseEepHeader.length);201 202 el = min(el / sizeof(u16), SIZE_EEPROM_4K);203 if (!ath9k_hw_nvram_validate_checksum(ah, el))204 return -EINVAL;205 206 if (need_swap) {207 EEPROM_FIELD_SWAB16(eep->baseEepHeader.length);208 EEPROM_FIELD_SWAB16(eep->baseEepHeader.checksum);209 EEPROM_FIELD_SWAB16(eep->baseEepHeader.version);210 EEPROM_FIELD_SWAB16(eep->baseEepHeader.regDmn[0]);211 EEPROM_FIELD_SWAB16(eep->baseEepHeader.regDmn[1]);212 EEPROM_FIELD_SWAB16(eep->baseEepHeader.rfSilent);213 EEPROM_FIELD_SWAB16(eep->baseEepHeader.blueToothOptions);214 EEPROM_FIELD_SWAB16(eep->baseEepHeader.deviceCap);215 EEPROM_FIELD_SWAB32(eep->modalHeader.antCtrlCommon);216 217 for (i = 0; i < AR5416_EEP4K_MAX_CHAINS; i++)218 EEPROM_FIELD_SWAB32(eep->modalHeader.antCtrlChain[i]);219 220 for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++)221 EEPROM_FIELD_SWAB16(222 eep->modalHeader.spurChans[i].spurChan);223 }224 225 if (!ath9k_hw_nvram_check_version(ah, AR5416_EEP_VER,226 AR5416_EEP_NO_BACK_VER))227 return -EINVAL;228 229 return 0;230}231 232#undef SIZE_EEPROM_4K233 234static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah,235 enum eeprom_param param)236{237 struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;238 struct modal_eep_4k_header *pModal = &eep->modalHeader;239 struct base_eep_header_4k *pBase = &eep->baseEepHeader;240 241 switch (param) {242 case EEP_NFTHRESH_2:243 return pModal->noiseFloorThreshCh[0];244 case EEP_MAC_LSW:245 return get_unaligned_be16(pBase->macAddr);246 case EEP_MAC_MID:247 return get_unaligned_be16(pBase->macAddr + 2);248 case EEP_MAC_MSW:249 return get_unaligned_be16(pBase->macAddr + 4);250 case EEP_REG_0:251 return le16_to_cpu(pBase->regDmn[0]);252 case EEP_OP_CAP:253 return le16_to_cpu(pBase->deviceCap);254 case EEP_OP_MODE:255 return pBase->opCapFlags;256 case EEP_RF_SILENT:257 return le16_to_cpu(pBase->rfSilent);258 case EEP_OB_2:259 return pModal->ob_0;260 case EEP_DB_2:261 return pModal->db1_1;262 case EEP_TX_MASK:263 return pBase->txMask;264 case EEP_RX_MASK:265 return pBase->rxMask;266 case EEP_FRAC_N_5G:267 return 0;268 case EEP_PWR_TABLE_OFFSET:269 return AR5416_PWR_TABLE_OFFSET_DB;270 case EEP_MODAL_VER:271 return pModal->version;272 case EEP_ANT_DIV_CTL1:273 return pModal->antdiv_ctl1;274 case EEP_TXGAIN_TYPE:275 return pBase->txGainType;276 case EEP_ANTENNA_GAIN_2G:277 return pModal->antennaGainCh[0];278 default:279 return 0;280 }281}282 283static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah,284 struct ath9k_channel *chan)285{286 struct ath_common *common = ath9k_hw_common(ah);287 struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;288 struct cal_data_per_freq_4k *pRawDataset;289 u8 *pCalBChans = NULL;290 u16 pdGainOverlap_t2;291 static u8 pdadcValues[AR5416_NUM_PDADC_VALUES];292 u16 gainBoundaries[AR5416_PD_GAINS_IN_MASK];293 u16 numPiers, i, j;294 u16 numXpdGain, xpdMask;295 u16 xpdGainValues[AR5416_EEP4K_NUM_PD_GAINS] = { 0, 0 };296 u32 reg32, regOffset, regChainOffset;297 298 xpdMask = pEepData->modalHeader.xpdGain;299 300 if (ath9k_hw_4k_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_2)301 pdGainOverlap_t2 =302 pEepData->modalHeader.pdGainOverlap;303 else304 pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5),305 AR_PHY_TPCRG5_PD_GAIN_OVERLAP));306 307 pCalBChans = pEepData->calFreqPier2G;308 numPiers = AR5416_EEP4K_NUM_2G_CAL_PIERS;309 310 numXpdGain = 0;311 312 for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) {313 if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) {314 if (numXpdGain >= AR5416_EEP4K_NUM_PD_GAINS)315 break;316 xpdGainValues[numXpdGain] =317 (u16)(AR5416_PD_GAINS_IN_MASK - i);318 numXpdGain++;319 }320 }321 322 ENABLE_REG_RMW_BUFFER(ah);323 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN,324 (numXpdGain - 1) & 0x3);325 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1,326 xpdGainValues[0]);327 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2,328 xpdGainValues[1]);329 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3, 0);330 REG_RMW_BUFFER_FLUSH(ah);331 332 for (i = 0; i < AR5416_EEP4K_MAX_CHAINS; i++) {333 regChainOffset = i * 0x1000;334 335 if (pEepData->baseEepHeader.txMask & (1 << i)) {336 pRawDataset = pEepData->calPierData2G[i];337 338 ath9k_hw_get_gain_boundaries_pdadcs(ah, chan,339 pRawDataset, pCalBChans,340 numPiers, pdGainOverlap_t2,341 gainBoundaries,342 pdadcValues, numXpdGain);343 344 ENABLE_REGWRITE_BUFFER(ah);345 346 REG_WRITE(ah, AR_PHY_TPCRG5 + regChainOffset,347 SM(pdGainOverlap_t2,348 AR_PHY_TPCRG5_PD_GAIN_OVERLAP)349 | SM(gainBoundaries[0],350 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1)351 | SM(gainBoundaries[1],352 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2)353 | SM(gainBoundaries[2],354 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3)355 | SM(gainBoundaries[3],356 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4));357 358 regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset;359 for (j = 0; j < 32; j++) {360 reg32 = get_unaligned_le32(&pdadcValues[4 * j]);361 REG_WRITE(ah, regOffset, reg32);362 363 ath_dbg(common, EEPROM,364 "PDADC (%d,%4x): %4.4x %8.8x\n",365 i, regChainOffset, regOffset,366 reg32);367 ath_dbg(common, EEPROM,368 "PDADC: Chain %d | "369 "PDADC %3d Value %3d | "370 "PDADC %3d Value %3d | "371 "PDADC %3d Value %3d | "372 "PDADC %3d Value %3d |\n",373 i, 4 * j, pdadcValues[4 * j],374 4 * j + 1, pdadcValues[4 * j + 1],375 4 * j + 2, pdadcValues[4 * j + 2],376 4 * j + 3, pdadcValues[4 * j + 3]);377 378 regOffset += 4;379 }380 381 REGWRITE_BUFFER_FLUSH(ah);382 }383 }384}385 386static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah,387 struct ath9k_channel *chan,388 int16_t *ratesArray,389 u16 cfgCtl,390 u16 antenna_reduction,391 u16 powerLimit)392{393#define CMP_TEST_GRP \394 (((cfgCtl & ~CTL_MODE_M)| (pCtlMode[ctlMode] & CTL_MODE_M)) == \395 pEepData->ctlIndex[i]) \396 || (((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == \397 ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL))398 399 int i;400 u16 twiceMinEdgePower;401 u16 twiceMaxEdgePower;402 u16 scaledPower = 0, minCtlPower;403 u16 numCtlModes;404 const u16 *pCtlMode;405 u16 ctlMode, freq;406 struct chan_centers centers;407 struct cal_ctl_data_4k *rep;408 struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;409 struct cal_target_power_leg targetPowerOfdm, targetPowerCck = {410 0, { 0, 0, 0, 0}411 };412 struct cal_target_power_leg targetPowerOfdmExt = {413 0, { 0, 0, 0, 0} }, targetPowerCckExt = {414 0, { 0, 0, 0, 0 }415 };416 struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = {417 0, {0, 0, 0, 0}418 };419 static const u16 ctlModesFor11g[] = {420 CTL_11B, CTL_11G, CTL_2GHT20,421 CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40422 };423 424 ath9k_hw_get_channel_centers(ah, chan, ¢ers);425 426 scaledPower = powerLimit - antenna_reduction;427 scaledPower = min_t(u16, scaledPower, MAX_RATE_POWER);428 numCtlModes = ARRAY_SIZE(ctlModesFor11g) - SUB_NUM_CTL_MODES_AT_2G_40;429 pCtlMode = ctlModesFor11g;430 431 ath9k_hw_get_legacy_target_powers(ah, chan,432 pEepData->calTargetPowerCck,433 AR5416_NUM_2G_CCK_TARGET_POWERS,434 &targetPowerCck, 4, false);435 ath9k_hw_get_legacy_target_powers(ah, chan,436 pEepData->calTargetPower2G,437 AR5416_NUM_2G_20_TARGET_POWERS,438 &targetPowerOfdm, 4, false);439 ath9k_hw_get_target_powers(ah, chan,440 pEepData->calTargetPower2GHT20,441 AR5416_NUM_2G_20_TARGET_POWERS,442 &targetPowerHt20, 8, false);443 444 if (IS_CHAN_HT40(chan)) {445 numCtlModes = ARRAY_SIZE(ctlModesFor11g);446 ath9k_hw_get_target_powers(ah, chan,447 pEepData->calTargetPower2GHT40,448 AR5416_NUM_2G_40_TARGET_POWERS,449 &targetPowerHt40, 8, true);450 ath9k_hw_get_legacy_target_powers(ah, chan,451 pEepData->calTargetPowerCck,452 AR5416_NUM_2G_CCK_TARGET_POWERS,453 &targetPowerCckExt, 4, true);454 ath9k_hw_get_legacy_target_powers(ah, chan,455 pEepData->calTargetPower2G,456 AR5416_NUM_2G_20_TARGET_POWERS,457 &targetPowerOfdmExt, 4, true);458 }459 460 for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) {461 bool isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) ||462 (pCtlMode[ctlMode] == CTL_2GHT40);463 464 if (isHt40CtlMode)465 freq = centers.synth_center;466 else if (pCtlMode[ctlMode] & EXT_ADDITIVE)467 freq = centers.ext_center;468 else469 freq = centers.ctl_center;470 471 twiceMaxEdgePower = MAX_RATE_POWER;472 473 for (i = 0; (i < AR5416_EEP4K_NUM_CTLS) &&474 pEepData->ctlIndex[i]; i++) {475 476 if (CMP_TEST_GRP) {477 rep = &(pEepData->ctlData[i]);478 479 twiceMinEdgePower = ath9k_hw_get_max_edge_power(480 freq,481 rep->ctlEdges[482 ar5416_get_ntxchains(ah->txchainmask) - 1],483 IS_CHAN_2GHZ(chan),484 AR5416_EEP4K_NUM_BAND_EDGES);485 486 if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) {487 twiceMaxEdgePower =488 min(twiceMaxEdgePower,489 twiceMinEdgePower);490 } else {491 twiceMaxEdgePower = twiceMinEdgePower;492 break;493 }494 }495 }496 497 minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower);498 499 switch (pCtlMode[ctlMode]) {500 case CTL_11B:501 for (i = 0; i < ARRAY_SIZE(targetPowerCck.tPow2x); i++) {502 targetPowerCck.tPow2x[i] =503 min((u16)targetPowerCck.tPow2x[i],504 minCtlPower);505 }506 break;507 case CTL_11G:508 for (i = 0; i < ARRAY_SIZE(targetPowerOfdm.tPow2x); i++) {509 targetPowerOfdm.tPow2x[i] =510 min((u16)targetPowerOfdm.tPow2x[i],511 minCtlPower);512 }513 break;514 case CTL_2GHT20:515 for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++) {516 targetPowerHt20.tPow2x[i] =517 min((u16)targetPowerHt20.tPow2x[i],518 minCtlPower);519 }520 break;521 case CTL_11B_EXT:522 targetPowerCckExt.tPow2x[0] =523 min((u16)targetPowerCckExt.tPow2x[0],524 minCtlPower);525 break;526 case CTL_11G_EXT:527 targetPowerOfdmExt.tPow2x[0] =528 min((u16)targetPowerOfdmExt.tPow2x[0],529 minCtlPower);530 break;531 case CTL_2GHT40:532 for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {533 targetPowerHt40.tPow2x[i] =534 min((u16)targetPowerHt40.tPow2x[i],535 minCtlPower);536 }537 break;538 default:539 break;540 }541 }542 543 ratesArray[rate6mb] =544 ratesArray[rate9mb] =545 ratesArray[rate12mb] =546 ratesArray[rate18mb] =547 ratesArray[rate24mb] =548 targetPowerOfdm.tPow2x[0];549 550 ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1];551 ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2];552 ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3];553 ratesArray[rateXr] = targetPowerOfdm.tPow2x[0];554 555 for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++)556 ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i];557 558 ratesArray[rate1l] = targetPowerCck.tPow2x[0];559 ratesArray[rate2s] = ratesArray[rate2l] = targetPowerCck.tPow2x[1];560 ratesArray[rate5_5s] = ratesArray[rate5_5l] = targetPowerCck.tPow2x[2];561 ratesArray[rate11s] = ratesArray[rate11l] = targetPowerCck.tPow2x[3];562 563 if (IS_CHAN_HT40(chan)) {564 for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {565 ratesArray[rateHt40_0 + i] =566 targetPowerHt40.tPow2x[i];567 }568 ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0];569 ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0];570 ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0];571 ratesArray[rateExtCck] = targetPowerCckExt.tPow2x[0];572 }573 574#undef CMP_TEST_GRP575}576 577static void ath9k_hw_4k_set_txpower(struct ath_hw *ah,578 struct ath9k_channel *chan,579 u16 cfgCtl,580 u8 twiceAntennaReduction,581 u8 powerLimit, bool test)582{583 struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);584 struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;585 struct modal_eep_4k_header *pModal = &pEepData->modalHeader;586 int16_t ratesArray[Ar5416RateSize];587 u8 ht40PowerIncForPdadc = 2;588 int i;589 590 memset(ratesArray, 0, sizeof(ratesArray));591 592 if (ath9k_hw_4k_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_2)593 ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;594 595 ath9k_hw_set_4k_power_per_rate_table(ah, chan,596 &ratesArray[0], cfgCtl,597 twiceAntennaReduction,598 powerLimit);599 600 ath9k_hw_set_4k_power_cal_table(ah, chan);601 602 regulatory->max_power_level = 0;603 for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {604 if (ratesArray[i] > MAX_RATE_POWER)605 ratesArray[i] = MAX_RATE_POWER;606 607 if (ratesArray[i] > regulatory->max_power_level)608 regulatory->max_power_level = ratesArray[i];609 }610 611 if (test)612 return;613 614 for (i = 0; i < Ar5416RateSize; i++)615 ratesArray[i] -= AR5416_PWR_TABLE_OFFSET_DB * 2;616 617 ENABLE_REGWRITE_BUFFER(ah);618 619 /* OFDM power per rate */620 REG_WRITE(ah, AR_PHY_POWER_TX_RATE1,621 ATH9K_POW_SM(ratesArray[rate18mb], 24)622 | ATH9K_POW_SM(ratesArray[rate12mb], 16)623 | ATH9K_POW_SM(ratesArray[rate9mb], 8)624 | ATH9K_POW_SM(ratesArray[rate6mb], 0));625 REG_WRITE(ah, AR_PHY_POWER_TX_RATE2,626 ATH9K_POW_SM(ratesArray[rate54mb], 24)627 | ATH9K_POW_SM(ratesArray[rate48mb], 16)628 | ATH9K_POW_SM(ratesArray[rate36mb], 8)629 | ATH9K_POW_SM(ratesArray[rate24mb], 0));630 631 /* CCK power per rate */632 REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,633 ATH9K_POW_SM(ratesArray[rate2s], 24)634 | ATH9K_POW_SM(ratesArray[rate2l], 16)635 | ATH9K_POW_SM(ratesArray[rateXr], 8)636 | ATH9K_POW_SM(ratesArray[rate1l], 0));637 REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,638 ATH9K_POW_SM(ratesArray[rate11s], 24)639 | ATH9K_POW_SM(ratesArray[rate11l], 16)640 | ATH9K_POW_SM(ratesArray[rate5_5s], 8)641 | ATH9K_POW_SM(ratesArray[rate5_5l], 0));642 643 /* HT20 power per rate */644 REG_WRITE(ah, AR_PHY_POWER_TX_RATE5,645 ATH9K_POW_SM(ratesArray[rateHt20_3], 24)646 | ATH9K_POW_SM(ratesArray[rateHt20_2], 16)647 | ATH9K_POW_SM(ratesArray[rateHt20_1], 8)648 | ATH9K_POW_SM(ratesArray[rateHt20_0], 0));649 REG_WRITE(ah, AR_PHY_POWER_TX_RATE6,650 ATH9K_POW_SM(ratesArray[rateHt20_7], 24)651 | ATH9K_POW_SM(ratesArray[rateHt20_6], 16)652 | ATH9K_POW_SM(ratesArray[rateHt20_5], 8)653 | ATH9K_POW_SM(ratesArray[rateHt20_4], 0));654 655 /* HT40 power per rate */656 if (IS_CHAN_HT40(chan)) {657 REG_WRITE(ah, AR_PHY_POWER_TX_RATE7,658 ATH9K_POW_SM(ratesArray[rateHt40_3] +659 ht40PowerIncForPdadc, 24)660 | ATH9K_POW_SM(ratesArray[rateHt40_2] +661 ht40PowerIncForPdadc, 16)662 | ATH9K_POW_SM(ratesArray[rateHt40_1] +663 ht40PowerIncForPdadc, 8)664 | ATH9K_POW_SM(ratesArray[rateHt40_0] +665 ht40PowerIncForPdadc, 0));666 REG_WRITE(ah, AR_PHY_POWER_TX_RATE8,667 ATH9K_POW_SM(ratesArray[rateHt40_7] +668 ht40PowerIncForPdadc, 24)669 | ATH9K_POW_SM(ratesArray[rateHt40_6] +670 ht40PowerIncForPdadc, 16)671 | ATH9K_POW_SM(ratesArray[rateHt40_5] +672 ht40PowerIncForPdadc, 8)673 | ATH9K_POW_SM(ratesArray[rateHt40_4] +674 ht40PowerIncForPdadc, 0));675 REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,676 ATH9K_POW_SM(ratesArray[rateExtOfdm], 24)677 | ATH9K_POW_SM(ratesArray[rateExtCck], 16)678 | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)679 | ATH9K_POW_SM(ratesArray[rateDupCck], 0));680 }681 682 /* TPC initializations */683 if (ah->tpc_enabled) {684 int ht40_delta;685 686 ht40_delta = (IS_CHAN_HT40(chan)) ? ht40PowerIncForPdadc : 0;687 ar5008_hw_init_rate_txpower(ah, ratesArray, chan, ht40_delta);688 /* Enable TPC */689 REG_WRITE(ah, AR_PHY_POWER_TX_RATE_MAX,690 MAX_RATE_POWER | AR_PHY_POWER_TX_RATE_MAX_TPC_ENABLE);691 } else {692 /* Disable TPC */693 REG_WRITE(ah, AR_PHY_POWER_TX_RATE_MAX, MAX_RATE_POWER);694 }695 696 REGWRITE_BUFFER_FLUSH(ah);697}698 699static void ath9k_hw_4k_set_gain(struct ath_hw *ah,700 struct modal_eep_4k_header *pModal,701 struct ar5416_eeprom_4k *eep,702 u8 txRxAttenLocal)703{704 ENABLE_REG_RMW_BUFFER(ah);705 REG_RMW(ah, AR_PHY_SWITCH_CHAIN_0,706 le32_to_cpu(pModal->antCtrlChain[0]), 0);707 708 REG_RMW(ah, AR_PHY_TIMING_CTRL4(0),709 SM(pModal->iqCalICh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) |710 SM(pModal->iqCalQCh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF),711 AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF | AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF);712 713 if (ath9k_hw_4k_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_3) {714 txRxAttenLocal = pModal->txRxAttenCh[0];715 716 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ,717 AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, pModal->bswMargin[0]);718 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ,719 AR_PHY_GAIN_2GHZ_XATTEN1_DB, pModal->bswAtten[0]);720 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ,721 AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,722 pModal->xatten2Margin[0]);723 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ,724 AR_PHY_GAIN_2GHZ_XATTEN2_DB, pModal->xatten2Db[0]);725 726 /* Set the block 1 value to block 0 value */727 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000,728 AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN,729 pModal->bswMargin[0]);730 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000,731 AR_PHY_GAIN_2GHZ_XATTEN1_DB, pModal->bswAtten[0]);732 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000,733 AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,734 pModal->xatten2Margin[0]);735 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000,736 AR_PHY_GAIN_2GHZ_XATTEN2_DB,737 pModal->xatten2Db[0]);738 }739 740 REG_RMW_FIELD(ah, AR_PHY_RXGAIN,741 AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal);742 REG_RMW_FIELD(ah, AR_PHY_RXGAIN,743 AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[0]);744 745 REG_RMW_FIELD(ah, AR_PHY_RXGAIN + 0x1000,746 AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal);747 REG_RMW_FIELD(ah, AR_PHY_RXGAIN + 0x1000,748 AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[0]);749 REG_RMW_BUFFER_FLUSH(ah);750}751 752/*753 * Read EEPROM header info and program the device for correct operation754 * given the channel value.755 */756static void ath9k_hw_4k_set_board_values(struct ath_hw *ah,757 struct ath9k_channel *chan)758{759 struct ath9k_hw_capabilities *pCap = &ah->caps;760 struct modal_eep_4k_header *pModal;761 struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;762 struct base_eep_header_4k *pBase = &eep->baseEepHeader;763 u8 txRxAttenLocal;764 u8 ob[5], db1[5], db2[5];765 u8 ant_div_control1, ant_div_control2;766 u8 bb_desired_scale;767 u32 regVal;768 769 pModal = &eep->modalHeader;770 txRxAttenLocal = 23;771 772 REG_WRITE(ah, AR_PHY_SWITCH_COM, le32_to_cpu(pModal->antCtrlCommon));773 774 /* Single chain for 4K EEPROM*/775 ath9k_hw_4k_set_gain(ah, pModal, eep, txRxAttenLocal);776 777 /* Initialize Ant Diversity settings from EEPROM */778 if (pModal->version >= 3) {779 ant_div_control1 = pModal->antdiv_ctl1;780 ant_div_control2 = pModal->antdiv_ctl2;781 782 regVal = REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL);783 regVal &= (~(AR_PHY_9285_ANT_DIV_CTL_ALL));784 785 regVal |= SM(ant_div_control1,786 AR_PHY_9285_ANT_DIV_CTL);787 regVal |= SM(ant_div_control2,788 AR_PHY_9285_ANT_DIV_ALT_LNACONF);789 regVal |= SM((ant_div_control2 >> 2),790 AR_PHY_9285_ANT_DIV_MAIN_LNACONF);791 regVal |= SM((ant_div_control1 >> 1),792 AR_PHY_9285_ANT_DIV_ALT_GAINTB);793 regVal |= SM((ant_div_control1 >> 2),794 AR_PHY_9285_ANT_DIV_MAIN_GAINTB);795 796 797 REG_WRITE(ah, AR_PHY_MULTICHAIN_GAIN_CTL, regVal);798 regVal = REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL);799 regVal = REG_READ(ah, AR_PHY_CCK_DETECT);800 regVal &= (~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV);801 regVal |= SM((ant_div_control1 >> 3),802 AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV);803 804 REG_WRITE(ah, AR_PHY_CCK_DETECT, regVal);805 regVal = REG_READ(ah, AR_PHY_CCK_DETECT);806 807 if (pCap->hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) {808 /*809 * If diversity combining is enabled,810 * set MAIN to LNA1 and ALT to LNA2 initially.811 */812 regVal = REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL);813 regVal &= (~(AR_PHY_9285_ANT_DIV_MAIN_LNACONF |814 AR_PHY_9285_ANT_DIV_ALT_LNACONF));815 816 regVal |= (ATH_ANT_DIV_COMB_LNA1 <<817 AR_PHY_9285_ANT_DIV_MAIN_LNACONF_S);818 regVal |= (ATH_ANT_DIV_COMB_LNA2 <<819 AR_PHY_9285_ANT_DIV_ALT_LNACONF_S);820 regVal &= (~(AR_PHY_9285_FAST_DIV_BIAS));821 regVal |= (0 << AR_PHY_9285_FAST_DIV_BIAS_S);822 REG_WRITE(ah, AR_PHY_MULTICHAIN_GAIN_CTL, regVal);823 }824 }825 826 if (pModal->version >= 2) {827 ob[0] = pModal->ob_0;828 ob[1] = pModal->ob_1;829 ob[2] = pModal->ob_2;830 ob[3] = pModal->ob_3;831 ob[4] = pModal->ob_4;832 833 db1[0] = pModal->db1_0;834 db1[1] = pModal->db1_1;835 db1[2] = pModal->db1_2;836 db1[3] = pModal->db1_3;837 db1[4] = pModal->db1_4;838 839 db2[0] = pModal->db2_0;840 db2[1] = pModal->db2_1;841 db2[2] = pModal->db2_2;842 db2[3] = pModal->db2_3;843 db2[4] = pModal->db2_4;844 } else if (pModal->version == 1) {845 ob[0] = pModal->ob_0;846 ob[1] = ob[2] = ob[3] = ob[4] = pModal->ob_1;847 db1[0] = pModal->db1_0;848 db1[1] = db1[2] = db1[3] = db1[4] = pModal->db1_1;849 db2[0] = pModal->db2_0;850 db2[1] = db2[2] = db2[3] = db2[4] = pModal->db2_1;851 } else {852 int i;853 854 for (i = 0; i < 5; i++) {855 ob[i] = pModal->ob_0;856 db1[i] = pModal->db1_0;857 db2[i] = pModal->db1_0;858 }859 }860 861 ENABLE_REG_RMW_BUFFER(ah);862 if (AR_SREV_9271(ah)) {863 ath9k_hw_analog_shift_rmw(ah,864 AR9285_AN_RF2G3,865 AR9271_AN_RF2G3_OB_cck,866 AR9271_AN_RF2G3_OB_cck_S,867 ob[0]);868 ath9k_hw_analog_shift_rmw(ah,869 AR9285_AN_RF2G3,870 AR9271_AN_RF2G3_OB_psk,871 AR9271_AN_RF2G3_OB_psk_S,872 ob[1]);873 ath9k_hw_analog_shift_rmw(ah,874 AR9285_AN_RF2G3,875 AR9271_AN_RF2G3_OB_qam,876 AR9271_AN_RF2G3_OB_qam_S,877 ob[2]);878 ath9k_hw_analog_shift_rmw(ah,879 AR9285_AN_RF2G3,880 AR9271_AN_RF2G3_DB_1,881 AR9271_AN_RF2G3_DB_1_S,882 db1[0]);883 ath9k_hw_analog_shift_rmw(ah,884 AR9285_AN_RF2G4,885 AR9271_AN_RF2G4_DB_2,886 AR9271_AN_RF2G4_DB_2_S,887 db2[0]);888 } else {889 ath9k_hw_analog_shift_rmw(ah,890 AR9285_AN_RF2G3,891 AR9285_AN_RF2G3_OB_0,892 AR9285_AN_RF2G3_OB_0_S,893 ob[0]);894 ath9k_hw_analog_shift_rmw(ah,895 AR9285_AN_RF2G3,896 AR9285_AN_RF2G3_OB_1,897 AR9285_AN_RF2G3_OB_1_S,898 ob[1]);899 ath9k_hw_analog_shift_rmw(ah,900 AR9285_AN_RF2G3,901 AR9285_AN_RF2G3_OB_2,902 AR9285_AN_RF2G3_OB_2_S,903 ob[2]);904 ath9k_hw_analog_shift_rmw(ah,905 AR9285_AN_RF2G3,906 AR9285_AN_RF2G3_OB_3,907 AR9285_AN_RF2G3_OB_3_S,908 ob[3]);909 ath9k_hw_analog_shift_rmw(ah,910 AR9285_AN_RF2G3,911 AR9285_AN_RF2G3_OB_4,912 AR9285_AN_RF2G3_OB_4_S,913 ob[4]);914 915 ath9k_hw_analog_shift_rmw(ah,916 AR9285_AN_RF2G3,917 AR9285_AN_RF2G3_DB1_0,918 AR9285_AN_RF2G3_DB1_0_S,919 db1[0]);920 ath9k_hw_analog_shift_rmw(ah,921 AR9285_AN_RF2G3,922 AR9285_AN_RF2G3_DB1_1,923 AR9285_AN_RF2G3_DB1_1_S,924 db1[1]);925 ath9k_hw_analog_shift_rmw(ah,926 AR9285_AN_RF2G3,927 AR9285_AN_RF2G3_DB1_2,928 AR9285_AN_RF2G3_DB1_2_S,929 db1[2]);930 ath9k_hw_analog_shift_rmw(ah,931 AR9285_AN_RF2G4,932 AR9285_AN_RF2G4_DB1_3,933 AR9285_AN_RF2G4_DB1_3_S,934 db1[3]);935 ath9k_hw_analog_shift_rmw(ah,936 AR9285_AN_RF2G4,937 AR9285_AN_RF2G4_DB1_4,938 AR9285_AN_RF2G4_DB1_4_S, db1[4]);939 940 ath9k_hw_analog_shift_rmw(ah,941 AR9285_AN_RF2G4,942 AR9285_AN_RF2G4_DB2_0,943 AR9285_AN_RF2G4_DB2_0_S,944 db2[0]);945 ath9k_hw_analog_shift_rmw(ah,946 AR9285_AN_RF2G4,947 AR9285_AN_RF2G4_DB2_1,948 AR9285_AN_RF2G4_DB2_1_S,949 db2[1]);950 ath9k_hw_analog_shift_rmw(ah,951 AR9285_AN_RF2G4,952 AR9285_AN_RF2G4_DB2_2,953 AR9285_AN_RF2G4_DB2_2_S,954 db2[2]);955 ath9k_hw_analog_shift_rmw(ah,956 AR9285_AN_RF2G4,957 AR9285_AN_RF2G4_DB2_3,958 AR9285_AN_RF2G4_DB2_3_S,959 db2[3]);960 ath9k_hw_analog_shift_rmw(ah,961 AR9285_AN_RF2G4,962 AR9285_AN_RF2G4_DB2_4,963 AR9285_AN_RF2G4_DB2_4_S,964 db2[4]);965 }966 REG_RMW_BUFFER_FLUSH(ah);967 968 ENABLE_REG_RMW_BUFFER(ah);969 REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH,970 pModal->switchSettling);971 REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC,972 pModal->adcDesiredSize);973 974 REG_RMW(ah, AR_PHY_RF_CTL4,975 SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF) |976 SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAB_OFF) |977 SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAA_ON) |978 SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAB_ON), 0);979 980 REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON,981 pModal->txEndToRxOn);982 983 if (AR_SREV_9271_10(ah))984 REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON,985 pModal->txEndToRxOn);986 REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62,987 pModal->thresh62);988 REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, AR_PHY_EXT_CCA0_THRESH62,989 pModal->thresh62);990 991 if (ath9k_hw_4k_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_2) {992 REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_DATA_START,993 pModal->txFrameToDataStart);994 REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_PA_ON,995 pModal->txFrameToPaOn);996 }997 998 if (ath9k_hw_4k_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_3) {999 if (IS_CHAN_HT40(chan))1000 REG_RMW_FIELD(ah, AR_PHY_SETTLING,1001 AR_PHY_SETTLING_SWITCH,1002 pModal->swSettleHt40);1003 }1004 1005 REG_RMW_BUFFER_FLUSH(ah);1006 1007 bb_desired_scale = (pModal->bb_scale_smrt_antenna &1008 EEP_4K_BB_DESIRED_SCALE_MASK);1009 if ((pBase->txGainType == 0) && (bb_desired_scale != 0)) {1010 u32 pwrctrl, mask, clr;1011 1012 mask = BIT(0)|BIT(5)|BIT(10)|BIT(15)|BIT(20)|BIT(25);1013 pwrctrl = mask * bb_desired_scale;1014 clr = mask * 0x1f;1015 ENABLE_REG_RMW_BUFFER(ah);1016 REG_RMW(ah, AR_PHY_TX_PWRCTRL8, pwrctrl, clr);1017 REG_RMW(ah, AR_PHY_TX_PWRCTRL10, pwrctrl, clr);1018 REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL12, pwrctrl, clr);1019 1020 mask = BIT(0)|BIT(5)|BIT(15);1021 pwrctrl = mask * bb_desired_scale;1022 clr = mask * 0x1f;1023 REG_RMW(ah, AR_PHY_TX_PWRCTRL9, pwrctrl, clr);1024 1025 mask = BIT(0)|BIT(5);1026 pwrctrl = mask * bb_desired_scale;1027 clr = mask * 0x1f;1028 REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL11, pwrctrl, clr);1029 REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL13, pwrctrl, clr);1030 REG_RMW_BUFFER_FLUSH(ah);1031 }1032}1033 1034static u16 ath9k_hw_4k_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz)1035{1036 return le16_to_cpu(ah->eeprom.map4k.modalHeader.spurChans[i].spurChan);1037}1038 1039static u8 ath9k_hw_4k_get_eepmisc(struct ath_hw *ah)1040{1041 return ah->eeprom.map4k.baseEepHeader.eepMisc;1042}1043 1044const struct eeprom_ops eep_4k_ops = {1045 .check_eeprom = ath9k_hw_4k_check_eeprom,1046 .get_eeprom = ath9k_hw_4k_get_eeprom,1047 .fill_eeprom = ath9k_hw_4k_fill_eeprom,1048 .dump_eeprom = ath9k_hw_4k_dump_eeprom,1049 .get_eeprom_ver = ath9k_hw_4k_get_eeprom_ver,1050 .get_eeprom_rev = ath9k_hw_4k_get_eeprom_rev,1051 .set_board_values = ath9k_hw_4k_set_board_values,1052 .set_txpower = ath9k_hw_4k_set_txpower,1053 .get_spur_channel = ath9k_hw_4k_get_spur_channel,1054 .get_eepmisc = ath9k_hw_4k_get_eepmisc1055};1056