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$ 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 53 static 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); 59 static HAL_BOOL ar9285SetPowerCalTable(struct ath_hal *ah, 60 struct ar5416eeprom_4k *pEepData, 61 const struct ieee80211_channel *chan, 62 int16_t *pTxPowerIndexOffset); 63 static 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 70 HAL_BOOL 71 ar9285SetTransmitPower(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 178 static void 179 ar9285SetBoardGain(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 */ 233 HAL_BOOL 234 ar9285SetBoardValues(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 385 static HAL_BOOL 386 ar9285SetPowerPerRateTable(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 ar5416SetRatesArrayFromTargetPower(ah, chan, ratesArray, 538 &targetPowerCck, 539 &targetPowerCckExt, 540 &targetPowerOfdm, 541 &targetPowerOfdmExt, 542 &targetPowerHt20, 543 &targetPowerHt40); 544 545 return AH_TRUE; 546 #undef EXT_ADDITIVE 547 #undef CTL_11G_EXT 548 #undef CTL_11B_EXT 549 #undef SUB_NUM_CTL_MODES_AT_2G_40 550 #undef N 551 } 552 553 static HAL_BOOL 554 ar9285SetPowerCalTable(struct ath_hal *ah, struct ar5416eeprom_4k *pEepData, 555 const struct ieee80211_channel *chan, int16_t *pTxPowerIndexOffset) 556 { 557 CAL_DATA_PER_FREQ_4K *pRawDataset; 558 uint8_t *pCalBChans = AH_NULL; 559 uint16_t pdGainOverlap_t2; 560 static uint8_t pdadcValues[AR5416_NUM_PDADC_VALUES]; 561 uint16_t gainBoundaries[AR5416_PD_GAINS_IN_MASK]; 562 uint16_t numPiers, i; 563 int16_t tMinCalPower; 564 uint16_t numXpdGain, xpdMask; 565 uint16_t xpdGainValues[4]; /* v4k eeprom has 2; the other two stay 0 */ 566 uint32_t regChainOffset; 567 568 OS_MEMZERO(xpdGainValues, sizeof(xpdGainValues)); 569 570 xpdMask = pEepData->modalHeader.xpdGain; 571 572 if (IS_EEP_MINOR_V2(ah)) { 573 pdGainOverlap_t2 = pEepData->modalHeader.pdGainOverlap; 574 } else { 575 pdGainOverlap_t2 = (uint16_t)(MS(OS_REG_READ(ah, AR_PHY_TPCRG5), AR_PHY_TPCRG5_PD_GAIN_OVERLAP)); 576 } 577 578 pCalBChans = pEepData->calFreqPier2G; 579 numPiers = AR5416_4K_NUM_2G_CAL_PIERS; 580 numXpdGain = 0; 581 582 /* Calculate the value of xpdgains from the xpdGain Mask */ 583 for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) { 584 if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) { 585 if (numXpdGain >= AR5416_4K_NUM_PD_GAINS) { 586 HALASSERT(0); 587 break; 588 } 589 xpdGainValues[numXpdGain] = (uint16_t)(AR5416_PD_GAINS_IN_MASK - i); 590 numXpdGain++; 591 } 592 } 593 594 /* Write the detector gain biases and their number */ 595 ar5416WriteDetectorGainBiases(ah, numXpdGain, xpdGainValues); 596 597 for (i = 0; i < AR5416_MAX_CHAINS; i++) { 598 regChainOffset = ar5416GetRegChainOffset(ah, i); 599 if (pEepData->baseEepHeader.txMask & (1 << i)) { 600 pRawDataset = pEepData->calPierData2G[i]; 601 602 ar9285GetGainBoundariesAndPdadcs(ah, chan, pRawDataset, 603 pCalBChans, numPiers, 604 pdGainOverlap_t2, 605 &tMinCalPower, gainBoundaries, 606 pdadcValues, numXpdGain); 607 608 if ((i == 0) || AR_SREV_5416_V20_OR_LATER(ah)) { 609 /* 610 * Note the pdadc table may not start at 0 dBm power, could be 611 * negative or greater than 0. Need to offset the power 612 * values by the amount of minPower for griffin 613 */ 614 ar5416SetGainBoundariesClosedLoop(ah, i, pdGainOverlap_t2, gainBoundaries); 615 } 616 617 /* Write the power values into the baseband power table */ 618 ar5416WritePdadcValues(ah, i, pdadcValues); 619 } 620 } 621 *pTxPowerIndexOffset = 0; 622 623 return AH_TRUE; 624 } 625 626 static void 627 ar9285GetGainBoundariesAndPdadcs(struct ath_hal *ah, 628 const struct ieee80211_channel *chan, 629 CAL_DATA_PER_FREQ_4K *pRawDataSet, 630 uint8_t * bChans, uint16_t availPiers, 631 uint16_t tPdGainOverlap, int16_t *pMinCalPower, uint16_t * pPdGainBoundaries, 632 uint8_t * pPDADCValues, uint16_t numXpdGains) 633 { 634 635 int i, j, k; 636 int16_t ss; /* potentially -ve index for taking care of pdGainOverlap */ 637 uint16_t idxL, idxR, numPiers; /* Pier indexes */ 638 639 /* filled out Vpd table for all pdGains (chanL) */ 640 static uint8_t vpdTableL[AR5416_4K_NUM_PD_GAINS][AR5416_MAX_PWR_RANGE_IN_HALF_DB]; 641 642 /* filled out Vpd table for all pdGains (chanR) */ 643 static uint8_t vpdTableR[AR5416_4K_NUM_PD_GAINS][AR5416_MAX_PWR_RANGE_IN_HALF_DB]; 644 645 /* filled out Vpd table for all pdGains (interpolated) */ 646 static uint8_t vpdTableI[AR5416_4K_NUM_PD_GAINS][AR5416_MAX_PWR_RANGE_IN_HALF_DB]; 647 648 uint8_t *pVpdL, *pVpdR, *pPwrL, *pPwrR; 649 uint8_t minPwrT4[AR5416_4K_NUM_PD_GAINS]; 650 uint8_t maxPwrT4[AR5416_4K_NUM_PD_GAINS]; 651 int16_t vpdStep; 652 int16_t tmpVal; 653 uint16_t sizeCurrVpdTable, maxIndex, tgtIndex; 654 HAL_BOOL match; 655 int16_t minDelta = 0; 656 CHAN_CENTERS centers; 657 658 ar5416GetChannelCenters(ah, chan, ¢ers); 659 660 /* Trim numPiers for the number of populated channel Piers */ 661 for (numPiers = 0; numPiers < availPiers; numPiers++) { 662 if (bChans[numPiers] == AR5416_BCHAN_UNUSED) { 663 break; 664 } 665 } 666 667 /* Find pier indexes around the current channel */ 668 match = ath_ee_getLowerUpperIndex((uint8_t)FREQ2FBIN(centers.synth_center, 669 IEEE80211_IS_CHAN_2GHZ(chan)), bChans, numPiers, &idxL, &idxR); 670 671 if (match) { 672 /* Directly fill both vpd tables from the matching index */ 673 for (i = 0; i < numXpdGains; i++) { 674 minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0]; 675 maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4]; 676 ath_ee_FillVpdTable(minPwrT4[i], maxPwrT4[i], 677 pRawDataSet[idxL].pwrPdg[i], 678 pRawDataSet[idxL].vpdPdg[i], 679 AR5416_PD_GAIN_ICEPTS, vpdTableI[i]); 680 } 681 } else { 682 for (i = 0; i < numXpdGains; i++) { 683 pVpdL = pRawDataSet[idxL].vpdPdg[i]; 684 pPwrL = pRawDataSet[idxL].pwrPdg[i]; 685 pVpdR = pRawDataSet[idxR].vpdPdg[i]; 686 pPwrR = pRawDataSet[idxR].pwrPdg[i]; 687 688 /* Start Vpd interpolation from the max of the minimum powers */ 689 minPwrT4[i] = AH_MAX(pPwrL[0], pPwrR[0]); 690 691 /* End Vpd interpolation from the min of the max powers */ 692 maxPwrT4[i] = AH_MIN(pPwrL[AR5416_PD_GAIN_ICEPTS - 1], pPwrR[AR5416_PD_GAIN_ICEPTS - 1]); 693 HALASSERT(maxPwrT4[i] > minPwrT4[i]); 694 695 /* Fill pier Vpds */ 696 ath_ee_FillVpdTable(minPwrT4[i], maxPwrT4[i], pPwrL, pVpdL, 697 AR5416_PD_GAIN_ICEPTS, vpdTableL[i]); 698 ath_ee_FillVpdTable(minPwrT4[i], maxPwrT4[i], pPwrR, pVpdR, 699 AR5416_PD_GAIN_ICEPTS, vpdTableR[i]); 700 701 /* Interpolate the final vpd */ 702 for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) { 703 vpdTableI[i][j] = (uint8_t)(ath_ee_interpolate((uint16_t)FREQ2FBIN(centers.synth_center, 704 IEEE80211_IS_CHAN_2GHZ(chan)), 705 bChans[idxL], bChans[idxR], vpdTableL[i][j], vpdTableR[i][j])); 706 } 707 } 708 } 709 *pMinCalPower = (int16_t)(minPwrT4[0] / 2); 710 711 k = 0; /* index for the final table */ 712 for (i = 0; i < numXpdGains; i++) { 713 if (i == (numXpdGains - 1)) { 714 pPdGainBoundaries[i] = (uint16_t)(maxPwrT4[i] / 2); 715 } else { 716 pPdGainBoundaries[i] = (uint16_t)((maxPwrT4[i] + minPwrT4[i+1]) / 4); 717 } 718 719 pPdGainBoundaries[i] = (uint16_t)AH_MIN(AR5416_MAX_RATE_POWER, pPdGainBoundaries[i]); 720 721 /* NB: only applies to owl 1.0 */ 722 if ((i == 0) && !AR_SREV_5416_V20_OR_LATER(ah) ) { 723 /* 724 * fix the gain delta, but get a delta that can be applied to min to 725 * keep the upper power values accurate, don't think max needs to 726 * be adjusted because should not be at that area of the table? 727 */ 728 minDelta = pPdGainBoundaries[0] - 23; 729 pPdGainBoundaries[0] = 23; 730 } 731 else { 732 minDelta = 0; 733 } 734 735 /* Find starting index for this pdGain */ 736 if (i == 0) { 737 if (AR_SREV_MERLIN_20_OR_LATER(ah)) 738 ss = (int16_t)(0 - (minPwrT4[i] / 2)); 739 else 740 ss = 0; /* for the first pdGain, start from index 0 */ 741 } else { 742 /* need overlap entries extrapolated below. */ 743 ss = (int16_t)((pPdGainBoundaries[i-1] - (minPwrT4[i] / 2)) - tPdGainOverlap + 1 + minDelta); 744 } 745 vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]); 746 vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep); 747 /* 748 *-ve ss indicates need to extrapolate data below for this pdGain 749 */ 750 while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) { 751 tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep); 752 pPDADCValues[k++] = (uint8_t)((tmpVal < 0) ? 0 : tmpVal); 753 ss++; 754 } 755 756 sizeCurrVpdTable = (uint8_t)((maxPwrT4[i] - minPwrT4[i]) / 2 +1); 757 tgtIndex = (uint8_t)(pPdGainBoundaries[i] + tPdGainOverlap - (minPwrT4[i] / 2)); 758 maxIndex = (tgtIndex < sizeCurrVpdTable) ? tgtIndex : sizeCurrVpdTable; 759 760 while ((ss < maxIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1))) { 761 pPDADCValues[k++] = vpdTableI[i][ss++]; 762 } 763 764 vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] - vpdTableI[i][sizeCurrVpdTable - 2]); 765 vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep); 766 /* 767 * for last gain, pdGainBoundary == Pmax_t2, so will 768 * have to extrapolate 769 */ 770 if (tgtIndex >= maxIndex) { /* need to extrapolate above */ 771 while ((ss <= tgtIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1))) { 772 tmpVal = (int16_t)((vpdTableI[i][sizeCurrVpdTable - 1] + 773 (ss - maxIndex +1) * vpdStep)); 774 pPDADCValues[k++] = (uint8_t)((tmpVal > 255) ? 255 : tmpVal); 775 ss++; 776 } 777 } /* extrapolated above */ 778 } /* for all pdGainUsed */ 779 780 /* Fill out pdGainBoundaries - only up to 2 allowed here, but hardware allows up to 4 */ 781 while (i < AR5416_PD_GAINS_IN_MASK) { 782 pPdGainBoundaries[i] = AR5416_4K_EEP_PD_GAIN_BOUNDARY_DEFAULT; 783 i++; 784 } 785 786 while (k < AR5416_NUM_PDADC_VALUES) { 787 pPDADCValues[k] = pPDADCValues[k-1]; 788 k++; 789 } 790 return; 791 } 792