ar9285_reset.c revision 221806
1/* 2 * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting 3 * Copyright (c) 2002-2008 Atheros Communications, Inc. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 * 17 * $FreeBSD: head/sys/dev/ath/ath_hal/ar9002/ar9285_reset.c 221806 2011-05-12 10:11:24Z adrian $ 18 */ 19 20/* 21 * This is almost the same as ar5416_reset.c but uses the v4k EEPROM and 22 * supports only 2Ghz operation. 23 */ 24 25#include "opt_ah.h" 26 27#include "ah.h" 28#include "ah_internal.h" 29#include "ah_devid.h" 30 31#include "ah_eeprom_v14.h" 32#include "ah_eeprom_v4k.h" 33 34#include "ar9002/ar9285.h" 35#include "ar5416/ar5416.h" 36#include "ar5416/ar5416reg.h" 37#include "ar5416/ar5416phy.h" 38#include "ar9002/ar9002phy.h" 39#include "ar9002/ar9285phy.h" 40#include "ar9002/ar9285an.h" 41 42/* Eeprom versioning macros. Returns true if the version is equal or newer than the ver specified */ 43#define EEP_MINOR(_ah) \ 44 (AH_PRIVATE(_ah)->ah_eeversion & AR5416_EEP_VER_MINOR_MASK) 45#define IS_EEP_MINOR_V2(_ah) (EEP_MINOR(_ah) >= AR5416_EEP_MINOR_VER_2) 46#define IS_EEP_MINOR_V3(_ah) (EEP_MINOR(_ah) >= AR5416_EEP_MINOR_VER_3) 47 48/* Additional Time delay to wait after activiting the Base band */ 49#define BASE_ACTIVATE_DELAY 100 /* 100 usec */ 50#define PLL_SETTLE_DELAY 300 /* 300 usec */ 51#define RTC_PLL_SETTLE_DELAY 1000 /* 1 ms */ 52 53static HAL_BOOL ar9285SetPowerPerRateTable(struct ath_hal *ah, 54 struct ar5416eeprom_4k *pEepData, 55 const struct ieee80211_channel *chan, int16_t *ratesArray, 56 uint16_t cfgCtl, uint16_t AntennaReduction, 57 uint16_t twiceMaxRegulatoryPower, 58 uint16_t powerLimit); 59static HAL_BOOL ar9285SetPowerCalTable(struct ath_hal *ah, 60 struct ar5416eeprom_4k *pEepData, 61 const struct ieee80211_channel *chan, 62 int16_t *pTxPowerIndexOffset); 63static void ar9285GetGainBoundariesAndPdadcs(struct ath_hal *ah, 64 const struct ieee80211_channel *chan, CAL_DATA_PER_FREQ_4K *pRawDataSet, 65 uint8_t * bChans, uint16_t availPiers, 66 uint16_t tPdGainOverlap, int16_t *pMinCalPower, 67 uint16_t * pPdGainBoundaries, uint8_t * pPDADCValues, 68 uint16_t numXpdGains); 69 70HAL_BOOL 71ar9285SetTransmitPower(struct ath_hal *ah, 72 const struct ieee80211_channel *chan, uint16_t *rfXpdGain) 73{ 74#define POW_SM(_r, _s) (((_r) & 0x3f) << (_s)) 75#define N(a) (sizeof (a) / sizeof (a[0])) 76 77 MODAL_EEP4K_HEADER *pModal; 78 struct ath_hal_5212 *ahp = AH5212(ah); 79 int16_t ratesArray[Ar5416RateSize]; 80 int16_t txPowerIndexOffset = 0; 81 uint8_t ht40PowerIncForPdadc = 2; 82 int i; 83 84 uint16_t cfgCtl; 85 uint16_t powerLimit; 86 uint16_t twiceAntennaReduction; 87 uint16_t twiceMaxRegulatoryPower; 88 int16_t maxPower; 89 HAL_EEPROM_v4k *ee = AH_PRIVATE(ah)->ah_eeprom; 90 struct ar5416eeprom_4k *pEepData = &ee->ee_base; 91 92 HALASSERT(AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER14_1); 93 94 /* Setup info for the actual eeprom */ 95 OS_MEMZERO(ratesArray, sizeof(ratesArray)); 96 cfgCtl = ath_hal_getctl(ah, chan); 97 powerLimit = chan->ic_maxregpower * 2; 98 twiceAntennaReduction = chan->ic_maxantgain; 99 twiceMaxRegulatoryPower = AH_MIN(MAX_RATE_POWER, AH_PRIVATE(ah)->ah_powerLimit); 100 pModal = &pEepData->modalHeader; 101 HALDEBUG(ah, HAL_DEBUG_RESET, "%s Channel=%u CfgCtl=%u\n", 102 __func__,chan->ic_freq, cfgCtl ); 103 104 if (IS_EEP_MINOR_V2(ah)) { 105 ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc; 106 } 107 108 if (!ar9285SetPowerPerRateTable(ah, pEepData, chan, 109 &ratesArray[0],cfgCtl, 110 twiceAntennaReduction, 111 twiceMaxRegulatoryPower, powerLimit)) { 112 HALDEBUG(ah, HAL_DEBUG_ANY, 113 "%s: unable to set tx power per rate table\n", __func__); 114 return AH_FALSE; 115 } 116 117 if (!ar9285SetPowerCalTable(ah, pEepData, chan, &txPowerIndexOffset)) { 118 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unable to set power table\n", 119 __func__); 120 return AH_FALSE; 121 } 122 123 maxPower = AH_MAX(ratesArray[rate6mb], ratesArray[rateHt20_0]); 124 maxPower = AH_MAX(maxPower, ratesArray[rate1l]); 125 126 if (IEEE80211_IS_CHAN_HT40(chan)) { 127 maxPower = AH_MAX(maxPower, ratesArray[rateHt40_0]); 128 } 129 130 ahp->ah_tx6PowerInHalfDbm = maxPower; 131 AH_PRIVATE(ah)->ah_maxPowerLevel = maxPower; 132 ahp->ah_txPowerIndexOffset = txPowerIndexOffset; 133 134 /* 135 * txPowerIndexOffset is set by the SetPowerTable() call - 136 * adjust the rate table (0 offset if rates EEPROM not loaded) 137 */ 138 for (i = 0; i < N(ratesArray); i++) { 139 ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]); 140 /* -5 dBm offset for Merlin and later; this includes Kite */ 141 ratesArray[i] -= AR5416_PWR_TABLE_OFFSET_DB * 2; 142 if (ratesArray[i] > AR5416_MAX_RATE_POWER) 143 ratesArray[i] = AR5416_MAX_RATE_POWER; 144 if (ratesArray[i] < 0) 145 ratesArray[i] = 0; 146 } 147 148#ifdef AH_EEPROM_DUMP 149 ar5416PrintPowerPerRate(ah, ratesArray); 150#endif 151 152 /* 153 * Adjust the HT40 power to meet the correct target TX power 154 * for 40MHz mode, based on TX power curves that are established 155 * for 20MHz mode. 156 * 157 * XXX handle overflow/too high power level? 158 */ 159 if (IEEE80211_IS_CHAN_HT40(chan)) { 160 ratesArray[rateHt40_0] += ht40PowerIncForPdadc; 161 ratesArray[rateHt40_1] += ht40PowerIncForPdadc; 162 ratesArray[rateHt40_2] += ht40PowerIncForPdadc; 163 ratesArray[rateHt40_3] += ht40PowerIncForPdadc; 164 ratesArray[rateHt40_4] += ht40PowerIncForPdadc; 165 ratesArray[rateHt40_5] += ht40PowerIncForPdadc; 166 ratesArray[rateHt40_6] += ht40PowerIncForPdadc; 167 ratesArray[rateHt40_7] += ht40PowerIncForPdadc; 168 } 169 170 /* Write the TX power rate registers */ 171 ar5416WriteTxPowerRateRegisters(ah, chan, ratesArray); 172 173 return AH_TRUE; 174#undef POW_SM 175#undef N 176} 177 178static void 179ar9285SetBoardGain(struct ath_hal *ah, const MODAL_EEP4K_HEADER *pModal, 180 const struct ar5416eeprom_4k *eep, uint8_t txRxAttenLocal) 181{ 182 OS_REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0, 183 pModal->antCtrlChain[0]); 184 185 OS_REG_WRITE(ah, AR_PHY_TIMING_CTRL4_CHAIN(0), 186 (OS_REG_READ(ah, AR_PHY_TIMING_CTRL4_CHAIN(0)) & 187 ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF | 188 AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) | 189 SM(pModal->iqCalICh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) | 190 SM(pModal->iqCalQCh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF)); 191 192 if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= 193 AR5416_EEP_MINOR_VER_3) { 194 txRxAttenLocal = pModal->txRxAttenCh[0]; 195 196 OS_REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ, 197 AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, pModal->bswMargin[0]); 198 OS_REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ, 199 AR_PHY_GAIN_2GHZ_XATTEN1_DB, pModal->bswAtten[0]); 200 OS_REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ, 201 AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN, pModal->xatten2Margin[0]); 202 OS_REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ, 203 AR_PHY_GAIN_2GHZ_XATTEN2_DB, pModal->xatten2Db[0]); 204 205 /* Set the block 1 value to block 0 value */ 206 OS_REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000, 207 AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, 208 pModal->bswMargin[0]); 209 OS_REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000, 210 AR_PHY_GAIN_2GHZ_XATTEN1_DB, pModal->bswAtten[0]); 211 OS_REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000, 212 AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN, 213 pModal->xatten2Margin[0]); 214 OS_REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000, 215 AR_PHY_GAIN_2GHZ_XATTEN2_DB, pModal->xatten2Db[0]); 216 } 217 218 OS_REG_RMW_FIELD(ah, AR_PHY_RXGAIN, 219 AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal); 220 OS_REG_RMW_FIELD(ah, AR_PHY_RXGAIN, 221 AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[0]); 222 223 OS_REG_RMW_FIELD(ah, AR_PHY_RXGAIN + 0x1000, 224 AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal); 225 OS_REG_RMW_FIELD(ah, AR_PHY_RXGAIN + 0x1000, 226 AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[0]); 227} 228 229/* 230 * Read EEPROM header info and program the device for correct operation 231 * given the channel value. 232 */ 233HAL_BOOL 234ar9285SetBoardValues(struct ath_hal *ah, const struct ieee80211_channel *chan) 235{ 236 const HAL_EEPROM_v4k *ee = AH_PRIVATE(ah)->ah_eeprom; 237 const struct ar5416eeprom_4k *eep = &ee->ee_base; 238 const MODAL_EEP4K_HEADER *pModal; 239 uint8_t txRxAttenLocal; 240 uint8_t ob[5], db1[5], db2[5]; 241 242 pModal = &eep->modalHeader; 243 txRxAttenLocal = 23; 244 245 OS_REG_WRITE(ah, AR_PHY_SWITCH_COM, pModal->antCtrlCommon); 246 247 /* Single chain for 4K EEPROM*/ 248 ar9285SetBoardGain(ah, pModal, eep, txRxAttenLocal); 249 250 /* Initialize Ant Diversity settings if supported */ 251 (void) ar9285SetAntennaSwitch(ah, AH5212(ah)->ah_antControl); 252 253 /* Configure TX power calibration */ 254 if (pModal->version >= 2) { 255 ob[0] = pModal->ob_0; 256 ob[1] = pModal->ob_1; 257 ob[2] = pModal->ob_2; 258 ob[3] = pModal->ob_3; 259 ob[4] = pModal->ob_4; 260 261 db1[0] = pModal->db1_0; 262 db1[1] = pModal->db1_1; 263 db1[2] = pModal->db1_2; 264 db1[3] = pModal->db1_3; 265 db1[4] = pModal->db1_4; 266 267 db2[0] = pModal->db2_0; 268 db2[1] = pModal->db2_1; 269 db2[2] = pModal->db2_2; 270 db2[3] = pModal->db2_3; 271 db2[4] = pModal->db2_4; 272 } else if (pModal->version == 1) { 273 ob[0] = pModal->ob_0; 274 ob[1] = ob[2] = ob[3] = ob[4] = pModal->ob_1; 275 db1[0] = pModal->db1_0; 276 db1[1] = db1[2] = db1[3] = db1[4] = pModal->db1_1; 277 db2[0] = pModal->db2_0; 278 db2[1] = db2[2] = db2[3] = db2[4] = pModal->db2_1; 279 } else { 280 int i; 281 282 for (i = 0; i < 5; i++) { 283 ob[i] = pModal->ob_0; 284 db1[i] = pModal->db1_0; 285 db2[i] = pModal->db1_0; 286 } 287 } 288 289 OS_A_REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_OB_0, ob[0]); 290 OS_A_REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_OB_1, ob[1]); 291 OS_A_REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_OB_2, ob[2]); 292 OS_A_REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_OB_3, ob[3]); 293 OS_A_REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_OB_4, ob[4]); 294 295 OS_A_REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_DB1_0, db1[0]); 296 OS_A_REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_DB1_1, db1[1]); 297 OS_A_REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_DB1_2, db1[2]); 298 OS_A_REG_RMW_FIELD(ah, AR9285_AN_RF2G4, AR9285_AN_RF2G4_DB1_3, db1[3]); 299 OS_A_REG_RMW_FIELD(ah, AR9285_AN_RF2G4, AR9285_AN_RF2G4_DB1_4, db1[4]); 300 301 OS_A_REG_RMW_FIELD(ah, AR9285_AN_RF2G4, AR9285_AN_RF2G4_DB2_0, db2[0]); 302 OS_A_REG_RMW_FIELD(ah, AR9285_AN_RF2G4, AR9285_AN_RF2G4_DB2_1, db2[1]); 303 OS_A_REG_RMW_FIELD(ah, AR9285_AN_RF2G4, AR9285_AN_RF2G4_DB2_2, db2[2]); 304 OS_A_REG_RMW_FIELD(ah, AR9285_AN_RF2G4, AR9285_AN_RF2G4_DB2_3, db2[3]); 305 OS_A_REG_RMW_FIELD(ah, AR9285_AN_RF2G4, AR9285_AN_RF2G4_DB2_4, db2[4]); 306 307 OS_REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH, 308 pModal->switchSettling); 309 OS_REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC, 310 pModal->adcDesiredSize); 311 312 OS_REG_WRITE(ah, AR_PHY_RF_CTL4, 313 SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF) | 314 SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAB_OFF) | 315 SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAA_ON) | 316 SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAB_ON)); 317 318 OS_REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON, 319 pModal->txEndToRxOn); 320 321 OS_REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62, 322 pModal->thresh62); 323 OS_REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, AR_PHY_EXT_CCA0_THRESH62, 324 pModal->thresh62); 325 326 if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= 327 AR5416_EEP_MINOR_VER_2) { 328 OS_REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_FRAME_TO_DATA_START, 329 pModal->txFrameToDataStart); 330 OS_REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_FRAME_TO_PA_ON, 331 pModal->txFrameToPaOn); 332 } 333 334 if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= 335 AR5416_EEP_MINOR_VER_3) { 336 if (IEEE80211_IS_CHAN_HT40(chan)) 337 OS_REG_RMW_FIELD(ah, AR_PHY_SETTLING, 338 AR_PHY_SETTLING_SWITCH, pModal->swSettleHt40); 339 } 340 341 /* 342 * Program the CCK TX gain factor appropriately if needed. 343 * The AR9285/AR9271 has a non-constant PA tx gain behaviour 344 * for CCK versus OFDM rates; other chips deal with this 345 * differently. 346 * 347 * The mask/shift/multiply hackery is done so place the same 348 * value (bb_desired_scale) into multiple 5-bit fields. 349 * For example, AR_PHY_TX_PWRCTRL9 has bb_desired_scale written 350 * to three fields: (0..4), (5..9) and (10..14). 351 */ 352 if (AR_SREV_9271(ah) || AR_SREV_KITE(ah)) { 353 uint8_t bb_desired_scale = (pModal->bb_scale_smrt_antenna & EEP_4K_BB_DESIRED_SCALE_MASK); 354 if ((eep->baseEepHeader.txGainType == 0) && (bb_desired_scale != 0)) { 355 ath_hal_printf(ah, "[ath]: adjusting cck tx gain factor\n"); 356 uint32_t pwrctrl, mask, clr; 357 358 mask = (1<<0) | (1<<5) | (1<<10) | (1<<15) | (1<<20) | (1<<25); 359 pwrctrl = mask * bb_desired_scale; 360 clr = mask * 0x1f; 361 OS_REG_RMW(ah, AR_PHY_TX_PWRCTRL8, pwrctrl, clr); 362 OS_REG_RMW(ah, AR_PHY_TX_PWRCTRL10, pwrctrl, clr); 363 OS_REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL12, pwrctrl, clr); 364 365 mask = (1<<0) | (1<<5) | (1<<15); 366 pwrctrl = mask * bb_desired_scale; 367 clr = mask * 0x1f; 368 OS_REG_RMW(ah, AR_PHY_TX_PWRCTRL9, pwrctrl, clr); 369 370 mask = (1<<0) | (1<<5); 371 pwrctrl = mask * bb_desired_scale; 372 clr = mask * 0x1f; 373 OS_REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL11, pwrctrl, clr); 374 OS_REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL13, pwrctrl, clr); 375 } 376 } 377 378 return AH_TRUE; 379} 380 381/* 382 * Helper functions common for AP/CB/XB 383 */ 384 385static HAL_BOOL 386ar9285SetPowerPerRateTable(struct ath_hal *ah, struct ar5416eeprom_4k *pEepData, 387 const struct ieee80211_channel *chan, 388 int16_t *ratesArray, uint16_t cfgCtl, 389 uint16_t AntennaReduction, 390 uint16_t twiceMaxRegulatoryPower, 391 uint16_t powerLimit) 392{ 393#define N(a) (sizeof(a)/sizeof(a[0])) 394/* Local defines to distinguish between extension and control CTL's */ 395#define EXT_ADDITIVE (0x8000) 396#define CTL_11G_EXT (CTL_11G | EXT_ADDITIVE) 397#define CTL_11B_EXT (CTL_11B | EXT_ADDITIVE) 398 399 uint16_t twiceMaxEdgePower = AR5416_MAX_RATE_POWER; 400 int i; 401 int16_t twiceLargestAntenna; 402 CAL_CTL_DATA_4K *rep; 403 CAL_TARGET_POWER_LEG targetPowerOfdm, targetPowerCck = {0, {0, 0, 0, 0}}; 404 CAL_TARGET_POWER_LEG targetPowerOfdmExt = {0, {0, 0, 0, 0}}, targetPowerCckExt = {0, {0, 0, 0, 0}}; 405 CAL_TARGET_POWER_HT targetPowerHt20, targetPowerHt40 = {0, {0, 0, 0, 0}}; 406 int16_t scaledPower, minCtlPower; 407 408#define SUB_NUM_CTL_MODES_AT_2G_40 3 /* excluding HT40, EXT-OFDM, EXT-CCK */ 409 static const uint16_t ctlModesFor11g[] = { 410 CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40 411 }; 412 const uint16_t *pCtlMode; 413 uint16_t numCtlModes, ctlMode, freq; 414 CHAN_CENTERS centers; 415 416 ar5416GetChannelCenters(ah, chan, ¢ers); 417 418 /* Compute TxPower reduction due to Antenna Gain */ 419 420 twiceLargestAntenna = pEepData->modalHeader.antennaGainCh[0]; 421 twiceLargestAntenna = (int16_t)AH_MIN((AntennaReduction) - twiceLargestAntenna, 0); 422 423 /* XXX setup for 5212 use (really used?) */ 424 ath_hal_eepromSet(ah, AR_EEP_ANTGAINMAX_2, twiceLargestAntenna); 425 426 /* 427 * scaledPower is the minimum of the user input power level and 428 * the regulatory allowed power level 429 */ 430 scaledPower = AH_MIN(powerLimit, twiceMaxRegulatoryPower + twiceLargestAntenna); 431 432 /* Get target powers from EEPROM - our baseline for TX Power */ 433 /* Setup for CTL modes */ 434 numCtlModes = N(ctlModesFor11g) - SUB_NUM_CTL_MODES_AT_2G_40; /* CTL_11B, CTL_11G, CTL_2GHT20 */ 435 pCtlMode = ctlModesFor11g; 436 437 ar5416GetTargetPowersLeg(ah, chan, pEepData->calTargetPowerCck, 438 AR5416_4K_NUM_2G_CCK_TARGET_POWERS, &targetPowerCck, 4, AH_FALSE); 439 ar5416GetTargetPowersLeg(ah, chan, pEepData->calTargetPower2G, 440 AR5416_4K_NUM_2G_20_TARGET_POWERS, &targetPowerOfdm, 4, AH_FALSE); 441 ar5416GetTargetPowers(ah, chan, pEepData->calTargetPower2GHT20, 442 AR5416_4K_NUM_2G_20_TARGET_POWERS, &targetPowerHt20, 8, AH_FALSE); 443 444 if (IEEE80211_IS_CHAN_HT40(chan)) { 445 numCtlModes = N(ctlModesFor11g); /* All 2G CTL's */ 446 447 ar5416GetTargetPowers(ah, chan, pEepData->calTargetPower2GHT40, 448 AR5416_4K_NUM_2G_40_TARGET_POWERS, &targetPowerHt40, 8, AH_TRUE); 449 /* Get target powers for extension channels */ 450 ar5416GetTargetPowersLeg(ah, chan, pEepData->calTargetPowerCck, 451 AR5416_4K_NUM_2G_CCK_TARGET_POWERS, &targetPowerCckExt, 4, AH_TRUE); 452 ar5416GetTargetPowersLeg(ah, chan, pEepData->calTargetPower2G, 453 AR5416_4K_NUM_2G_20_TARGET_POWERS, &targetPowerOfdmExt, 4, AH_TRUE); 454 } 455 456 /* 457 * For MIMO, need to apply regulatory caps individually across dynamically 458 * running modes: CCK, OFDM, HT20, HT40 459 * 460 * The outer loop walks through each possible applicable runtime mode. 461 * The inner loop walks through each ctlIndex entry in EEPROM. 462 * The ctl value is encoded as [7:4] == test group, [3:0] == test mode. 463 * 464 */ 465 for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) { 466 HAL_BOOL isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) || 467 (pCtlMode[ctlMode] == CTL_2GHT40); 468 if (isHt40CtlMode) { 469 freq = centers.ctl_center; 470 } else if (pCtlMode[ctlMode] & EXT_ADDITIVE) { 471 freq = centers.ext_center; 472 } else { 473 freq = centers.ctl_center; 474 } 475 476 /* walk through each CTL index stored in EEPROM */ 477 for (i = 0; (i < AR5416_4K_NUM_CTLS) && pEepData->ctlIndex[i]; i++) { 478 uint16_t twiceMinEdgePower; 479 480 /* compare test group from regulatory channel list with test mode from pCtlMode list */ 481 if ((((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == pEepData->ctlIndex[i]) || 482 (((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == 483 ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL))) { 484 rep = &(pEepData->ctlData[i]); 485 twiceMinEdgePower = ar5416GetMaxEdgePower(freq, 486 rep->ctlEdges[ 487 owl_get_ntxchains(AH5416(ah)->ah_tx_chainmask) - 1], AH_TRUE); 488 if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) { 489 /* Find the minimum of all CTL edge powers that apply to this channel */ 490 twiceMaxEdgePower = AH_MIN(twiceMaxEdgePower, twiceMinEdgePower); 491 } else { 492 /* specific */ 493 twiceMaxEdgePower = twiceMinEdgePower; 494 break; 495 } 496 } 497 } 498 minCtlPower = (uint8_t)AH_MIN(twiceMaxEdgePower, scaledPower); 499 /* Apply ctl mode to correct target power set */ 500 switch(pCtlMode[ctlMode]) { 501 case CTL_11B: 502 for (i = 0; i < N(targetPowerCck.tPow2x); i++) { 503 targetPowerCck.tPow2x[i] = (uint8_t)AH_MIN(targetPowerCck.tPow2x[i], minCtlPower); 504 } 505 break; 506 case CTL_11A: 507 case CTL_11G: 508 for (i = 0; i < N(targetPowerOfdm.tPow2x); i++) { 509 targetPowerOfdm.tPow2x[i] = (uint8_t)AH_MIN(targetPowerOfdm.tPow2x[i], minCtlPower); 510 } 511 break; 512 case CTL_5GHT20: 513 case CTL_2GHT20: 514 for (i = 0; i < N(targetPowerHt20.tPow2x); i++) { 515 targetPowerHt20.tPow2x[i] = (uint8_t)AH_MIN(targetPowerHt20.tPow2x[i], minCtlPower); 516 } 517 break; 518 case CTL_11B_EXT: 519 targetPowerCckExt.tPow2x[0] = (uint8_t)AH_MIN(targetPowerCckExt.tPow2x[0], minCtlPower); 520 break; 521 case CTL_11G_EXT: 522 targetPowerOfdmExt.tPow2x[0] = (uint8_t)AH_MIN(targetPowerOfdmExt.tPow2x[0], minCtlPower); 523 break; 524 case CTL_5GHT40: 525 case CTL_2GHT40: 526 for (i = 0; i < N(targetPowerHt40.tPow2x); i++) { 527 targetPowerHt40.tPow2x[i] = (uint8_t)AH_MIN(targetPowerHt40.tPow2x[i], minCtlPower); 528 } 529 break; 530 default: 531 return AH_FALSE; 532 break; 533 } 534 } /* end ctl mode checking */ 535 536 /* Set rates Array from collected data */ 537 ratesArray[rate6mb] = ratesArray[rate9mb] = ratesArray[rate12mb] = ratesArray[rate18mb] = ratesArray[rate24mb] = targetPowerOfdm.tPow2x[0]; 538 ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1]; 539 ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2]; 540 ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3]; 541 ratesArray[rateXr] = targetPowerOfdm.tPow2x[0]; 542 543 for (i = 0; i < N(targetPowerHt20.tPow2x); i++) { 544 ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i]; 545 } 546 547 ratesArray[rate1l] = targetPowerCck.tPow2x[0]; 548 ratesArray[rate2s] = ratesArray[rate2l] = targetPowerCck.tPow2x[1]; 549 ratesArray[rate5_5s] = ratesArray[rate5_5l] = targetPowerCck.tPow2x[2]; 550 ratesArray[rate11s] = ratesArray[rate11l] = targetPowerCck.tPow2x[3]; 551 if (IEEE80211_IS_CHAN_HT40(chan)) { 552 for (i = 0; i < N(targetPowerHt40.tPow2x); i++) { 553 ratesArray[rateHt40_0 + i] = targetPowerHt40.tPow2x[i]; 554 } 555 ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0]; 556 ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0]; 557 ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0]; 558 if (IEEE80211_IS_CHAN_2GHZ(chan)) { 559 ratesArray[rateExtCck] = targetPowerCckExt.tPow2x[0]; 560 } 561 } 562 return AH_TRUE; 563#undef EXT_ADDITIVE 564#undef CTL_11G_EXT 565#undef CTL_11B_EXT 566#undef SUB_NUM_CTL_MODES_AT_2G_40 567#undef N 568} 569 570static HAL_BOOL 571ar9285SetPowerCalTable(struct ath_hal *ah, struct ar5416eeprom_4k *pEepData, 572 const struct ieee80211_channel *chan, int16_t *pTxPowerIndexOffset) 573{ 574 CAL_DATA_PER_FREQ_4K *pRawDataset; 575 uint8_t *pCalBChans = AH_NULL; 576 uint16_t pdGainOverlap_t2; 577 static uint8_t pdadcValues[AR5416_NUM_PDADC_VALUES]; 578 uint16_t gainBoundaries[AR5416_PD_GAINS_IN_MASK]; 579 uint16_t numPiers, i; 580 int16_t tMinCalPower; 581 uint16_t numXpdGain, xpdMask; 582 uint16_t xpdGainValues[4]; /* v4k eeprom has 2; the other two stay 0 */ 583 uint32_t regChainOffset; 584 585 OS_MEMZERO(xpdGainValues, sizeof(xpdGainValues)); 586 587 xpdMask = pEepData->modalHeader.xpdGain; 588 589 if (IS_EEP_MINOR_V2(ah)) { 590 pdGainOverlap_t2 = pEepData->modalHeader.pdGainOverlap; 591 } else { 592 pdGainOverlap_t2 = (uint16_t)(MS(OS_REG_READ(ah, AR_PHY_TPCRG5), AR_PHY_TPCRG5_PD_GAIN_OVERLAP)); 593 } 594 595 pCalBChans = pEepData->calFreqPier2G; 596 numPiers = AR5416_4K_NUM_2G_CAL_PIERS; 597 numXpdGain = 0; 598 599 /* Calculate the value of xpdgains from the xpdGain Mask */ 600 for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) { 601 if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) { 602 if (numXpdGain >= AR5416_4K_NUM_PD_GAINS) { 603 HALASSERT(0); 604 break; 605 } 606 xpdGainValues[numXpdGain] = (uint16_t)(AR5416_PD_GAINS_IN_MASK - i); 607 numXpdGain++; 608 } 609 } 610 611 /* Write the detector gain biases and their number */ 612 ar5416WriteDetectorGainBiases(ah, numXpdGain, xpdGainValues); 613 614 for (i = 0; i < AR5416_MAX_CHAINS; i++) { 615 regChainOffset = ar5416GetRegChainOffset(ah, i); 616 if (pEepData->baseEepHeader.txMask & (1 << i)) { 617 pRawDataset = pEepData->calPierData2G[i]; 618 619 ar9285GetGainBoundariesAndPdadcs(ah, chan, pRawDataset, 620 pCalBChans, numPiers, 621 pdGainOverlap_t2, 622 &tMinCalPower, gainBoundaries, 623 pdadcValues, numXpdGain); 624 625 if ((i == 0) || AR_SREV_5416_V20_OR_LATER(ah)) { 626 /* 627 * Note the pdadc table may not start at 0 dBm power, could be 628 * negative or greater than 0. Need to offset the power 629 * values by the amount of minPower for griffin 630 */ 631 ar5416SetGainBoundariesClosedLoop(ah, i, pdGainOverlap_t2, gainBoundaries); 632 } 633 634 /* Write the power values into the baseband power table */ 635 ar5416WritePdadcValues(ah, i, pdadcValues); 636 } 637 } 638 *pTxPowerIndexOffset = 0; 639 640 return AH_TRUE; 641} 642 643static void 644ar9285GetGainBoundariesAndPdadcs(struct ath_hal *ah, 645 const struct ieee80211_channel *chan, 646 CAL_DATA_PER_FREQ_4K *pRawDataSet, 647 uint8_t * bChans, uint16_t availPiers, 648 uint16_t tPdGainOverlap, int16_t *pMinCalPower, uint16_t * pPdGainBoundaries, 649 uint8_t * pPDADCValues, uint16_t numXpdGains) 650{ 651 652 int i, j, k; 653 int16_t ss; /* potentially -ve index for taking care of pdGainOverlap */ 654 uint16_t idxL, idxR, numPiers; /* Pier indexes */ 655 656 /* filled out Vpd table for all pdGains (chanL) */ 657 static uint8_t vpdTableL[AR5416_4K_NUM_PD_GAINS][AR5416_MAX_PWR_RANGE_IN_HALF_DB]; 658 659 /* filled out Vpd table for all pdGains (chanR) */ 660 static uint8_t vpdTableR[AR5416_4K_NUM_PD_GAINS][AR5416_MAX_PWR_RANGE_IN_HALF_DB]; 661 662 /* filled out Vpd table for all pdGains (interpolated) */ 663 static uint8_t vpdTableI[AR5416_4K_NUM_PD_GAINS][AR5416_MAX_PWR_RANGE_IN_HALF_DB]; 664 665 uint8_t *pVpdL, *pVpdR, *pPwrL, *pPwrR; 666 uint8_t minPwrT4[AR5416_4K_NUM_PD_GAINS]; 667 uint8_t maxPwrT4[AR5416_4K_NUM_PD_GAINS]; 668 int16_t vpdStep; 669 int16_t tmpVal; 670 uint16_t sizeCurrVpdTable, maxIndex, tgtIndex; 671 HAL_BOOL match; 672 int16_t minDelta = 0; 673 CHAN_CENTERS centers; 674 675 ar5416GetChannelCenters(ah, chan, ¢ers); 676 677 /* Trim numPiers for the number of populated channel Piers */ 678 for (numPiers = 0; numPiers < availPiers; numPiers++) { 679 if (bChans[numPiers] == AR5416_BCHAN_UNUSED) { 680 break; 681 } 682 } 683 684 /* Find pier indexes around the current channel */ 685 match = ath_ee_getLowerUpperIndex((uint8_t)FREQ2FBIN(centers.synth_center, 686 IEEE80211_IS_CHAN_2GHZ(chan)), bChans, numPiers, &idxL, &idxR); 687 688 if (match) { 689 /* Directly fill both vpd tables from the matching index */ 690 for (i = 0; i < numXpdGains; i++) { 691 minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0]; 692 maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4]; 693 ath_ee_FillVpdTable(minPwrT4[i], maxPwrT4[i], 694 pRawDataSet[idxL].pwrPdg[i], 695 pRawDataSet[idxL].vpdPdg[i], 696 AR5416_PD_GAIN_ICEPTS, vpdTableI[i]); 697 } 698 } else { 699 for (i = 0; i < numXpdGains; i++) { 700 pVpdL = pRawDataSet[idxL].vpdPdg[i]; 701 pPwrL = pRawDataSet[idxL].pwrPdg[i]; 702 pVpdR = pRawDataSet[idxR].vpdPdg[i]; 703 pPwrR = pRawDataSet[idxR].pwrPdg[i]; 704 705 /* Start Vpd interpolation from the max of the minimum powers */ 706 minPwrT4[i] = AH_MAX(pPwrL[0], pPwrR[0]); 707 708 /* End Vpd interpolation from the min of the max powers */ 709 maxPwrT4[i] = AH_MIN(pPwrL[AR5416_PD_GAIN_ICEPTS - 1], pPwrR[AR5416_PD_GAIN_ICEPTS - 1]); 710 HALASSERT(maxPwrT4[i] > minPwrT4[i]); 711 712 /* Fill pier Vpds */ 713 ath_ee_FillVpdTable(minPwrT4[i], maxPwrT4[i], pPwrL, pVpdL, 714 AR5416_PD_GAIN_ICEPTS, vpdTableL[i]); 715 ath_ee_FillVpdTable(minPwrT4[i], maxPwrT4[i], pPwrR, pVpdR, 716 AR5416_PD_GAIN_ICEPTS, vpdTableR[i]); 717 718 /* Interpolate the final vpd */ 719 for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) { 720 vpdTableI[i][j] = (uint8_t)(ath_ee_interpolate((uint16_t)FREQ2FBIN(centers.synth_center, 721 IEEE80211_IS_CHAN_2GHZ(chan)), 722 bChans[idxL], bChans[idxR], vpdTableL[i][j], vpdTableR[i][j])); 723 } 724 } 725 } 726 *pMinCalPower = (int16_t)(minPwrT4[0] / 2); 727 728 k = 0; /* index for the final table */ 729 for (i = 0; i < numXpdGains; i++) { 730 if (i == (numXpdGains - 1)) { 731 pPdGainBoundaries[i] = (uint16_t)(maxPwrT4[i] / 2); 732 } else { 733 pPdGainBoundaries[i] = (uint16_t)((maxPwrT4[i] + minPwrT4[i+1]) / 4); 734 } 735 736 pPdGainBoundaries[i] = (uint16_t)AH_MIN(AR5416_MAX_RATE_POWER, pPdGainBoundaries[i]); 737 738 /* NB: only applies to owl 1.0 */ 739 if ((i == 0) && !AR_SREV_5416_V20_OR_LATER(ah) ) { 740 /* 741 * fix the gain delta, but get a delta that can be applied to min to 742 * keep the upper power values accurate, don't think max needs to 743 * be adjusted because should not be at that area of the table? 744 */ 745 minDelta = pPdGainBoundaries[0] - 23; 746 pPdGainBoundaries[0] = 23; 747 } 748 else { 749 minDelta = 0; 750 } 751 752 /* Find starting index for this pdGain */ 753 if (i == 0) { 754 if (AR_SREV_MERLIN_20_OR_LATER(ah)) 755 ss = (int16_t)(0 - (minPwrT4[i] / 2)); 756 else 757 ss = 0; /* for the first pdGain, start from index 0 */ 758 } else { 759 /* need overlap entries extrapolated below. */ 760 ss = (int16_t)((pPdGainBoundaries[i-1] - (minPwrT4[i] / 2)) - tPdGainOverlap + 1 + minDelta); 761 } 762 vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]); 763 vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep); 764 /* 765 *-ve ss indicates need to extrapolate data below for this pdGain 766 */ 767 while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) { 768 tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep); 769 pPDADCValues[k++] = (uint8_t)((tmpVal < 0) ? 0 : tmpVal); 770 ss++; 771 } 772 773 sizeCurrVpdTable = (uint8_t)((maxPwrT4[i] - minPwrT4[i]) / 2 +1); 774 tgtIndex = (uint8_t)(pPdGainBoundaries[i] + tPdGainOverlap - (minPwrT4[i] / 2)); 775 maxIndex = (tgtIndex < sizeCurrVpdTable) ? tgtIndex : sizeCurrVpdTable; 776 777 while ((ss < maxIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1))) { 778 pPDADCValues[k++] = vpdTableI[i][ss++]; 779 } 780 781 vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] - vpdTableI[i][sizeCurrVpdTable - 2]); 782 vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep); 783 /* 784 * for last gain, pdGainBoundary == Pmax_t2, so will 785 * have to extrapolate 786 */ 787 if (tgtIndex >= maxIndex) { /* need to extrapolate above */ 788 while ((ss <= tgtIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1))) { 789 tmpVal = (int16_t)((vpdTableI[i][sizeCurrVpdTable - 1] + 790 (ss - maxIndex +1) * vpdStep)); 791 pPDADCValues[k++] = (uint8_t)((tmpVal > 255) ? 255 : tmpVal); 792 ss++; 793 } 794 } /* extrapolated above */ 795 } /* for all pdGainUsed */ 796 797 /* Fill out pdGainBoundaries - only up to 2 allowed here, but hardware allows up to 4 */ 798 while (i < AR5416_PD_GAINS_IN_MASK) { 799 pPdGainBoundaries[i] = AR5416_4K_EEP_PD_GAIN_BOUNDARY_DEFAULT; 800 i++; 801 } 802 803 while (k < AR5416_NUM_PDADC_VALUES) { 804 pPDADCValues[k] = pPDADCValues[k-1]; 805 k++; 806 } 807 return; 808} 809