iPXE
|
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, ¢ers); 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, ¢ers); 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, ¢ers); 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 };