1 /* 2 * Copyright (c) 2008-2009 Atheros Communications Inc. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 #include "hw.h" 18 #include "ar9002_phy.h" 19 20 #define NUM_EEP_WORDS (sizeof(struct ar9287_eeprom) / sizeof(u16)) 21 22 static int ath9k_hw_ar9287_get_eeprom_ver(struct ath_hw *ah) 23 { 24 return (ah->eeprom.map9287.baseEepHeader.version >> 12) & 0xF; 25 } 26 27 static int ath9k_hw_ar9287_get_eeprom_rev(struct ath_hw *ah) 28 { 29 return (ah->eeprom.map9287.baseEepHeader.version) & 0xFFF; 30 } 31 32 static bool ath9k_hw_ar9287_fill_eeprom(struct ath_hw *ah) 33 { 34 struct ar9287_eeprom *eep = &ah->eeprom.map9287; 35 struct ath_common *common = ath9k_hw_common(ah); 36 u16 *eep_data; 37 int addr, eep_start_loc; 38 eep_data = (u16 *)eep; 39 40 if (common->bus_ops->ath_bus_type == ATH_USB) 41 eep_start_loc = AR9287_HTC_EEP_START_LOC; 42 else 43 eep_start_loc = AR9287_EEP_START_LOC; 44 45 if (!ath9k_hw_use_flash(ah)) { 46 ath_dbg(common, ATH_DBG_EEPROM, 47 "Reading from EEPROM, not flash\n"); 48 } 49 50 for (addr = 0; addr < NUM_EEP_WORDS; addr++) { 51 if (!ath9k_hw_nvram_read(common, addr + eep_start_loc, 52 eep_data)) { 53 ath_dbg(common, ATH_DBG_EEPROM, 54 "Unable to read eeprom region\n"); 55 return false; 56 } 57 eep_data++; 58 } 59 60 return true; 61 } 62 63 static int ath9k_hw_ar9287_check_eeprom(struct ath_hw *ah) 64 { 65 u32 sum = 0, el, integer; 66 u16 temp, word, magic, magic2, *eepdata; 67 int i, addr; 68 bool need_swap = false; 69 struct ar9287_eeprom *eep = &ah->eeprom.map9287; 70 struct ath_common *common = ath9k_hw_common(ah); 71 72 if (!ath9k_hw_use_flash(ah)) { 73 if (!ath9k_hw_nvram_read(common, AR5416_EEPROM_MAGIC_OFFSET, 74 &magic)) { 75 ath_err(common, "Reading Magic # failed\n"); 76 return false; 77 } 78 79 ath_dbg(common, ATH_DBG_EEPROM, 80 "Read Magic = 0x%04X\n", magic); 81 82 if (magic != AR5416_EEPROM_MAGIC) { 83 magic2 = swab16(magic); 84 85 if (magic2 == AR5416_EEPROM_MAGIC) { 86 need_swap = true; 87 eepdata = (u16 *)(&ah->eeprom); 88 89 for (addr = 0; addr < NUM_EEP_WORDS; addr++) { 90 temp = swab16(*eepdata); 91 *eepdata = temp; 92 eepdata++; 93 } 94 } else { 95 ath_err(common, 96 "Invalid EEPROM Magic. Endianness mismatch.\n"); 97 return -EINVAL; 98 } 99 } 100 } 101 102 ath_dbg(common, ATH_DBG_EEPROM, "need_swap = %s.\n", 103 need_swap ? "True" : "False"); 104 105 if (need_swap) 106 el = swab16(ah->eeprom.map9287.baseEepHeader.length); 107 else 108 el = ah->eeprom.map9287.baseEepHeader.length; 109 110 if (el > sizeof(struct ar9287_eeprom)) 111 el = sizeof(struct ar9287_eeprom) / sizeof(u16); 112 else 113 el = el / sizeof(u16); 114 115 eepdata = (u16 *)(&ah->eeprom); 116 117 for (i = 0; i < el; i++) 118 sum ^= *eepdata++; 119 120 if (need_swap) { 121 word = swab16(eep->baseEepHeader.length); 122 eep->baseEepHeader.length = word; 123 124 word = swab16(eep->baseEepHeader.checksum); 125 eep->baseEepHeader.checksum = word; 126 127 word = swab16(eep->baseEepHeader.version); 128 eep->baseEepHeader.version = word; 129 130 word = swab16(eep->baseEepHeader.regDmn[0]); 131 eep->baseEepHeader.regDmn[0] = word; 132 133 word = swab16(eep->baseEepHeader.regDmn[1]); 134 eep->baseEepHeader.regDmn[1] = word; 135 136 word = swab16(eep->baseEepHeader.rfSilent); 137 eep->baseEepHeader.rfSilent = word; 138 139 word = swab16(eep->baseEepHeader.blueToothOptions); 140 eep->baseEepHeader.blueToothOptions = word; 141 142 word = swab16(eep->baseEepHeader.deviceCap); 143 eep->baseEepHeader.deviceCap = word; 144 145 integer = swab32(eep->modalHeader.antCtrlCommon); 146 eep->modalHeader.antCtrlCommon = integer; 147 148 for (i = 0; i < AR9287_MAX_CHAINS; i++) { 149 integer = swab32(eep->modalHeader.antCtrlChain[i]); 150 eep->modalHeader.antCtrlChain[i] = integer; 151 } 152 153 for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { 154 word = swab16(eep->modalHeader.spurChans[i].spurChan); 155 eep->modalHeader.spurChans[i].spurChan = word; 156 } 157 } 158 159 if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR9287_EEP_VER 160 || ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) { 161 ath_err(common, "Bad EEPROM checksum 0x%x or revision 0x%04x\n", 162 sum, ah->eep_ops->get_eeprom_ver(ah)); 163 return -EINVAL; 164 } 165 166 return 0; 167 } 168 169 static u32 ath9k_hw_ar9287_get_eeprom(struct ath_hw *ah, 170 enum eeprom_param param) 171 { 172 struct ar9287_eeprom *eep = &ah->eeprom.map9287; 173 struct modal_eep_ar9287_header *pModal = &eep->modalHeader; 174 struct base_eep_ar9287_header *pBase = &eep->baseEepHeader; 175 u16 ver_minor; 176 177 ver_minor = pBase->version & AR9287_EEP_VER_MINOR_MASK; 178 179 switch (param) { 180 case EEP_NFTHRESH_2: 181 return pModal->noiseFloorThreshCh[0]; 182 case EEP_MAC_LSW: 183 return pBase->macAddr[0] << 8 | pBase->macAddr[1]; 184 case EEP_MAC_MID: 185 return pBase->macAddr[2] << 8 | pBase->macAddr[3]; 186 case EEP_MAC_MSW: 187 return pBase->macAddr[4] << 8 | pBase->macAddr[5]; 188 case EEP_REG_0: 189 return pBase->regDmn[0]; 190 case EEP_REG_1: 191 return pBase->regDmn[1]; 192 case EEP_OP_CAP: 193 return pBase->deviceCap; 194 case EEP_OP_MODE: 195 return pBase->opCapFlags; 196 case EEP_RF_SILENT: 197 return pBase->rfSilent; 198 case EEP_MINOR_REV: 199 return ver_minor; 200 case EEP_TX_MASK: 201 return pBase->txMask; 202 case EEP_RX_MASK: 203 return pBase->rxMask; 204 case EEP_DEV_TYPE: 205 return pBase->deviceType; 206 case EEP_OL_PWRCTRL: 207 return pBase->openLoopPwrCntl; 208 case EEP_TEMPSENSE_SLOPE: 209 if (ver_minor >= AR9287_EEP_MINOR_VER_2) 210 return pBase->tempSensSlope; 211 else 212 return 0; 213 case EEP_TEMPSENSE_SLOPE_PAL_ON: 214 if (ver_minor >= AR9287_EEP_MINOR_VER_3) 215 return pBase->tempSensSlopePalOn; 216 else 217 return 0; 218 default: 219 return 0; 220 } 221 } 222 223 static void ar9287_eeprom_get_tx_gain_index(struct ath_hw *ah, 224 struct ath9k_channel *chan, 225 struct cal_data_op_loop_ar9287 *pRawDatasetOpLoop, 226 u8 *pCalChans, u16 availPiers, int8_t *pPwr) 227 { 228 u16 idxL = 0, idxR = 0, numPiers; 229 bool match; 230 struct chan_centers centers; 231 232 ath9k_hw_get_channel_centers(ah, chan, ¢ers); 233 234 for (numPiers = 0; numPiers < availPiers; numPiers++) { 235 if (pCalChans[numPiers] == AR5416_BCHAN_UNUSED) 236 break; 237 } 238 239 match = ath9k_hw_get_lower_upper_index( 240 (u8)FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan)), 241 pCalChans, numPiers, &idxL, &idxR); 242 243 if (match) { 244 *pPwr = (int8_t) pRawDatasetOpLoop[idxL].pwrPdg[0][0]; 245 } else { 246 *pPwr = ((int8_t) pRawDatasetOpLoop[idxL].pwrPdg[0][0] + 247 (int8_t) pRawDatasetOpLoop[idxR].pwrPdg[0][0])/2; 248 } 249 250 } 251 252 static void ar9287_eeprom_olpc_set_pdadcs(struct ath_hw *ah, 253 int32_t txPower, u16 chain) 254 { 255 u32 tmpVal; 256 u32 a; 257 258 /* Enable OLPC for chain 0 */ 259 260 tmpVal = REG_READ(ah, 0xa270); 261 tmpVal = tmpVal & 0xFCFFFFFF; 262 tmpVal = tmpVal | (0x3 << 24); 263 REG_WRITE(ah, 0xa270, tmpVal); 264 265 /* Enable OLPC for chain 1 */ 266 267 tmpVal = REG_READ(ah, 0xb270); 268 tmpVal = tmpVal & 0xFCFFFFFF; 269 tmpVal = tmpVal | (0x3 << 24); 270 REG_WRITE(ah, 0xb270, tmpVal); 271 272 /* Write the OLPC ref power for chain 0 */ 273 274 if (chain == 0) { 275 tmpVal = REG_READ(ah, 0xa398); 276 tmpVal = tmpVal & 0xff00ffff; 277 a = (txPower)&0xff; 278 tmpVal = tmpVal | (a << 16); 279 REG_WRITE(ah, 0xa398, tmpVal); 280 } 281 282 /* Write the OLPC ref power for chain 1 */ 283 284 if (chain == 1) { 285 tmpVal = REG_READ(ah, 0xb398); 286 tmpVal = tmpVal & 0xff00ffff; 287 a = (txPower)&0xff; 288 tmpVal = tmpVal | (a << 16); 289 REG_WRITE(ah, 0xb398, tmpVal); 290 } 291 } 292 293 static void ath9k_hw_set_ar9287_power_cal_table(struct ath_hw *ah, 294 struct ath9k_channel *chan, 295 int16_t *pTxPowerIndexOffset) 296 { 297 struct cal_data_per_freq_ar9287 *pRawDataset; 298 struct cal_data_op_loop_ar9287 *pRawDatasetOpenLoop; 299 u8 *pCalBChans = NULL; 300 u16 pdGainOverlap_t2; 301 u8 pdadcValues[AR5416_NUM_PDADC_VALUES]; 302 u16 gainBoundaries[AR5416_PD_GAINS_IN_MASK]; 303 u16 numPiers = 0, i, j; 304 u16 numXpdGain, xpdMask; 305 u16 xpdGainValues[AR5416_NUM_PD_GAINS] = {0, 0, 0, 0}; 306 u32 reg32, regOffset, regChainOffset, regval; 307 int16_t modalIdx, diff = 0; 308 struct ar9287_eeprom *pEepData = &ah->eeprom.map9287; 309 310 modalIdx = IS_CHAN_2GHZ(chan) ? 1 : 0; 311 xpdMask = pEepData->modalHeader.xpdGain; 312 313 if ((pEepData->baseEepHeader.version & AR9287_EEP_VER_MINOR_MASK) >= 314 AR9287_EEP_MINOR_VER_2) 315 pdGainOverlap_t2 = pEepData->modalHeader.pdGainOverlap; 316 else 317 pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5), 318 AR_PHY_TPCRG5_PD_GAIN_OVERLAP)); 319 320 if (IS_CHAN_2GHZ(chan)) { 321 pCalBChans = pEepData->calFreqPier2G; 322 numPiers = AR9287_NUM_2G_CAL_PIERS; 323 if (ath9k_hw_ar9287_get_eeprom(ah, EEP_OL_PWRCTRL)) { 324 pRawDatasetOpenLoop = 325 (struct cal_data_op_loop_ar9287 *)pEepData->calPierData2G[0]; 326 ah->initPDADC = pRawDatasetOpenLoop->vpdPdg[0][0]; 327 } 328 } 329 330 numXpdGain = 0; 331 332 /* Calculate the value of xpdgains from the xpdGain Mask */ 333 for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) { 334 if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) { 335 if (numXpdGain >= AR5416_NUM_PD_GAINS) 336 break; 337 xpdGainValues[numXpdGain] = 338 (u16)(AR5416_PD_GAINS_IN_MASK-i); 339 numXpdGain++; 340 } 341 } 342 343 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN, 344 (numXpdGain - 1) & 0x3); 345 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1, 346 xpdGainValues[0]); 347 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2, 348 xpdGainValues[1]); 349 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3, 350 xpdGainValues[2]); 351 352 for (i = 0; i < AR9287_MAX_CHAINS; i++) { 353 regChainOffset = i * 0x1000; 354 355 if (pEepData->baseEepHeader.txMask & (1 << i)) { 356 pRawDatasetOpenLoop = 357 (struct cal_data_op_loop_ar9287 *)pEepData->calPierData2G[i]; 358 359 if (ath9k_hw_ar9287_get_eeprom(ah, EEP_OL_PWRCTRL)) { 360 int8_t txPower; 361 ar9287_eeprom_get_tx_gain_index(ah, chan, 362 pRawDatasetOpenLoop, 363 pCalBChans, numPiers, 364 &txPower); 365 ar9287_eeprom_olpc_set_pdadcs(ah, txPower, i); 366 } else { 367 pRawDataset = 368 (struct cal_data_per_freq_ar9287 *) 369 pEepData->calPierData2G[i]; 370 371 ath9k_hw_get_gain_boundaries_pdadcs(ah, chan, 372 pRawDataset, 373 pCalBChans, numPiers, 374 pdGainOverlap_t2, 375 gainBoundaries, 376 pdadcValues, 377 numXpdGain); 378 } 379 380 if (i == 0) { 381 if (!ath9k_hw_ar9287_get_eeprom(ah, 382 EEP_OL_PWRCTRL)) { 383 384 regval = SM(pdGainOverlap_t2, 385 AR_PHY_TPCRG5_PD_GAIN_OVERLAP) 386 | SM(gainBoundaries[0], 387 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1) 388 | SM(gainBoundaries[1], 389 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2) 390 | SM(gainBoundaries[2], 391 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3) 392 | SM(gainBoundaries[3], 393 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4); 394 395 REG_WRITE(ah, 396 AR_PHY_TPCRG5 + regChainOffset, 397 regval); 398 } 399 } 400 401 if ((int32_t)AR9287_PWR_TABLE_OFFSET_DB != 402 pEepData->baseEepHeader.pwrTableOffset) { 403 diff = (u16)(pEepData->baseEepHeader.pwrTableOffset - 404 (int32_t)AR9287_PWR_TABLE_OFFSET_DB); 405 diff *= 2; 406 407 for (j = 0; j < ((u16)AR5416_NUM_PDADC_VALUES-diff); j++) 408 pdadcValues[j] = pdadcValues[j+diff]; 409 410 for (j = (u16)(AR5416_NUM_PDADC_VALUES-diff); 411 j < AR5416_NUM_PDADC_VALUES; j++) 412 pdadcValues[j] = 413 pdadcValues[AR5416_NUM_PDADC_VALUES-diff]; 414 } 415 416 if (!ath9k_hw_ar9287_get_eeprom(ah, EEP_OL_PWRCTRL)) { 417 regOffset = AR_PHY_BASE + 418 (672 << 2) + regChainOffset; 419 420 for (j = 0; j < 32; j++) { 421 reg32 = ((pdadcValues[4*j + 0] & 0xFF) << 0) 422 | ((pdadcValues[4*j + 1] & 0xFF) << 8) 423 | ((pdadcValues[4*j + 2] & 0xFF) << 16) 424 | ((pdadcValues[4*j + 3] & 0xFF) << 24); 425 426 REG_WRITE(ah, regOffset, reg32); 427 regOffset += 4; 428 } 429 } 430 } 431 } 432 433 *pTxPowerIndexOffset = 0; 434 } 435 436 static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah, 437 struct ath9k_channel *chan, 438 int16_t *ratesArray, 439 u16 cfgCtl, 440 u16 AntennaReduction, 441 u16 twiceMaxRegulatoryPower, 442 u16 powerLimit) 443 { 444 #define CMP_CTL \ 445 (((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == \ 446 pEepData->ctlIndex[i]) 447 448 #define CMP_NO_CTL \ 449 (((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == \ 450 ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL)) 451 452 #define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 453 #define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10 454 455 struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); 456 u16 twiceMaxEdgePower = MAX_RATE_POWER; 457 static const u16 tpScaleReductionTable[5] = 458 { 0, 3, 6, 9, MAX_RATE_POWER }; 459 int i; 460 int16_t twiceLargestAntenna; 461 struct cal_ctl_data_ar9287 *rep; 462 struct cal_target_power_leg targetPowerOfdm = {0, {0, 0, 0, 0} }, 463 targetPowerCck = {0, {0, 0, 0, 0} }; 464 struct cal_target_power_leg targetPowerOfdmExt = {0, {0, 0, 0, 0} }, 465 targetPowerCckExt = {0, {0, 0, 0, 0} }; 466 struct cal_target_power_ht targetPowerHt20, 467 targetPowerHt40 = {0, {0, 0, 0, 0} }; 468 u16 scaledPower = 0, minCtlPower, maxRegAllowedPower; 469 static const u16 ctlModesFor11g[] = { 470 CTL_11B, CTL_11G, CTL_2GHT20, 471 CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40 472 }; 473 u16 numCtlModes = 0; 474 const u16 *pCtlMode = NULL; 475 u16 ctlMode, freq; 476 struct chan_centers centers; 477 int tx_chainmask; 478 u16 twiceMinEdgePower; 479 struct ar9287_eeprom *pEepData = &ah->eeprom.map9287; 480 tx_chainmask = ah->txchainmask; 481 482 ath9k_hw_get_channel_centers(ah, chan, ¢ers); 483 484 /* Compute TxPower reduction due to Antenna Gain */ 485 twiceLargestAntenna = max(pEepData->modalHeader.antennaGainCh[0], 486 pEepData->modalHeader.antennaGainCh[1]); 487 twiceLargestAntenna = (int16_t)min((AntennaReduction) - 488 twiceLargestAntenna, 0); 489 490 /* 491 * scaledPower is the minimum of the user input power level 492 * and the regulatory allowed power level. 493 */ 494 maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna; 495 496 if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX) 497 maxRegAllowedPower -= 498 (tpScaleReductionTable[(regulatory->tp_scale)] * 2); 499 500 scaledPower = min(powerLimit, maxRegAllowedPower); 501 502 /* 503 * Reduce scaled Power by number of chains active 504 * to get the per chain tx power level. 505 */ 506 switch (ar5416_get_ntxchains(tx_chainmask)) { 507 case 1: 508 break; 509 case 2: 510 scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN; 511 break; 512 case 3: 513 scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN; 514 break; 515 } 516 scaledPower = max((u16)0, scaledPower); 517 518 /* 519 * Get TX power from EEPROM. 520 */ 521 if (IS_CHAN_2GHZ(chan)) { 522 /* CTL_11B, CTL_11G, CTL_2GHT20 */ 523 numCtlModes = 524 ARRAY_SIZE(ctlModesFor11g) - SUB_NUM_CTL_MODES_AT_2G_40; 525 526 pCtlMode = ctlModesFor11g; 527 528 ath9k_hw_get_legacy_target_powers(ah, chan, 529 pEepData->calTargetPowerCck, 530 AR9287_NUM_2G_CCK_TARGET_POWERS, 531 &targetPowerCck, 4, false); 532 ath9k_hw_get_legacy_target_powers(ah, chan, 533 pEepData->calTargetPower2G, 534 AR9287_NUM_2G_20_TARGET_POWERS, 535 &targetPowerOfdm, 4, false); 536 ath9k_hw_get_target_powers(ah, chan, 537 pEepData->calTargetPower2GHT20, 538 AR9287_NUM_2G_20_TARGET_POWERS, 539 &targetPowerHt20, 8, false); 540 541 if (IS_CHAN_HT40(chan)) { 542 /* All 2G CTLs */ 543 numCtlModes = ARRAY_SIZE(ctlModesFor11g); 544 ath9k_hw_get_target_powers(ah, chan, 545 pEepData->calTargetPower2GHT40, 546 AR9287_NUM_2G_40_TARGET_POWERS, 547 &targetPowerHt40, 8, true); 548 ath9k_hw_get_legacy_target_powers(ah, chan, 549 pEepData->calTargetPowerCck, 550 AR9287_NUM_2G_CCK_TARGET_POWERS, 551 &targetPowerCckExt, 4, true); 552 ath9k_hw_get_legacy_target_powers(ah, chan, 553 pEepData->calTargetPower2G, 554 AR9287_NUM_2G_20_TARGET_POWERS, 555 &targetPowerOfdmExt, 4, true); 556 } 557 } 558 559 for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) { 560 bool isHt40CtlMode = 561 (pCtlMode[ctlMode] == CTL_2GHT40) ? true : false; 562 563 if (isHt40CtlMode) 564 freq = centers.synth_center; 565 else if (pCtlMode[ctlMode] & EXT_ADDITIVE) 566 freq = centers.ext_center; 567 else 568 freq = centers.ctl_center; 569 570 /* Walk through the CTL indices stored in EEPROM */ 571 for (i = 0; (i < AR9287_NUM_CTLS) && pEepData->ctlIndex[i]; i++) { 572 struct cal_ctl_edges *pRdEdgesPower; 573 574 /* 575 * Compare test group from regulatory channel list 576 * with test mode from pCtlMode list 577 */ 578 if (CMP_CTL || CMP_NO_CTL) { 579 rep = &(pEepData->ctlData[i]); 580 pRdEdgesPower = 581 rep->ctlEdges[ar5416_get_ntxchains(tx_chainmask) - 1]; 582 583 twiceMinEdgePower = ath9k_hw_get_max_edge_power(freq, 584 pRdEdgesPower, 585 IS_CHAN_2GHZ(chan), 586 AR5416_NUM_BAND_EDGES); 587 588 if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) { 589 twiceMaxEdgePower = min(twiceMaxEdgePower, 590 twiceMinEdgePower); 591 } else { 592 twiceMaxEdgePower = twiceMinEdgePower; 593 break; 594 } 595 } 596 } 597 598 minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower); 599 600 /* Apply ctl mode to correct target power set */ 601 switch (pCtlMode[ctlMode]) { 602 case CTL_11B: 603 for (i = 0; i < ARRAY_SIZE(targetPowerCck.tPow2x); i++) { 604 targetPowerCck.tPow2x[i] = 605 (u8)min((u16)targetPowerCck.tPow2x[i], 606 minCtlPower); 607 } 608 break; 609 case CTL_11A: 610 case CTL_11G: 611 for (i = 0; i < ARRAY_SIZE(targetPowerOfdm.tPow2x); i++) { 612 targetPowerOfdm.tPow2x[i] = 613 (u8)min((u16)targetPowerOfdm.tPow2x[i], 614 minCtlPower); 615 } 616 break; 617 case CTL_5GHT20: 618 case CTL_2GHT20: 619 for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++) { 620 targetPowerHt20.tPow2x[i] = 621 (u8)min((u16)targetPowerHt20.tPow2x[i], 622 minCtlPower); 623 } 624 break; 625 case CTL_11B_EXT: 626 targetPowerCckExt.tPow2x[0] = 627 (u8)min((u16)targetPowerCckExt.tPow2x[0], 628 minCtlPower); 629 break; 630 case CTL_11A_EXT: 631 case CTL_11G_EXT: 632 targetPowerOfdmExt.tPow2x[0] = 633 (u8)min((u16)targetPowerOfdmExt.tPow2x[0], 634 minCtlPower); 635 break; 636 case CTL_5GHT40: 637 case CTL_2GHT40: 638 for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) { 639 targetPowerHt40.tPow2x[i] = 640 (u8)min((u16)targetPowerHt40.tPow2x[i], 641 minCtlPower); 642 } 643 break; 644 default: 645 break; 646 } 647 } 648 649 /* Now set the rates array */ 650 651 ratesArray[rate6mb] = 652 ratesArray[rate9mb] = 653 ratesArray[rate12mb] = 654 ratesArray[rate18mb] = 655 ratesArray[rate24mb] = targetPowerOfdm.tPow2x[0]; 656 657 ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1]; 658 ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2]; 659 ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3]; 660 ratesArray[rateXr] = targetPowerOfdm.tPow2x[0]; 661 662 for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++) 663 ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i]; 664 665 if (IS_CHAN_2GHZ(chan)) { 666 ratesArray[rate1l] = targetPowerCck.tPow2x[0]; 667 ratesArray[rate2s] = 668 ratesArray[rate2l] = targetPowerCck.tPow2x[1]; 669 ratesArray[rate5_5s] = 670 ratesArray[rate5_5l] = targetPowerCck.tPow2x[2]; 671 ratesArray[rate11s] = 672 ratesArray[rate11l] = targetPowerCck.tPow2x[3]; 673 } 674 if (IS_CHAN_HT40(chan)) { 675 for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) 676 ratesArray[rateHt40_0 + i] = targetPowerHt40.tPow2x[i]; 677 678 ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0]; 679 ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0]; 680 ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0]; 681 682 if (IS_CHAN_2GHZ(chan)) 683 ratesArray[rateExtCck] = targetPowerCckExt.tPow2x[0]; 684 } 685 686 #undef CMP_CTL 687 #undef CMP_NO_CTL 688 #undef REDUCE_SCALED_POWER_BY_TWO_CHAIN 689 #undef REDUCE_SCALED_POWER_BY_THREE_CHAIN 690 } 691 692 static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah, 693 struct ath9k_channel *chan, u16 cfgCtl, 694 u8 twiceAntennaReduction, 695 u8 twiceMaxRegulatoryPower, 696 u8 powerLimit, bool test) 697 { 698 struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); 699 struct ar9287_eeprom *pEepData = &ah->eeprom.map9287; 700 struct modal_eep_ar9287_header *pModal = &pEepData->modalHeader; 701 int16_t ratesArray[Ar5416RateSize]; 702 int16_t txPowerIndexOffset = 0; 703 u8 ht40PowerIncForPdadc = 2; 704 int i; 705 706 memset(ratesArray, 0, sizeof(ratesArray)); 707 708 if ((pEepData->baseEepHeader.version & AR9287_EEP_VER_MINOR_MASK) >= 709 AR9287_EEP_MINOR_VER_2) 710 ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc; 711 712 ath9k_hw_set_ar9287_power_per_rate_table(ah, chan, 713 &ratesArray[0], cfgCtl, 714 twiceAntennaReduction, 715 twiceMaxRegulatoryPower, 716 powerLimit); 717 718 ath9k_hw_set_ar9287_power_cal_table(ah, chan, &txPowerIndexOffset); 719 720 regulatory->max_power_level = 0; 721 for (i = 0; i < ARRAY_SIZE(ratesArray); i++) { 722 ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]); 723 if (ratesArray[i] > MAX_RATE_POWER) 724 ratesArray[i] = MAX_RATE_POWER; 725 726 if (ratesArray[i] > regulatory->max_power_level) 727 regulatory->max_power_level = ratesArray[i]; 728 } 729 730 if (test) 731 return; 732 733 if (IS_CHAN_2GHZ(chan)) 734 i = rate1l; 735 else 736 i = rate6mb; 737 738 regulatory->max_power_level = ratesArray[i]; 739 740 if (AR_SREV_9280_20_OR_LATER(ah)) { 741 for (i = 0; i < Ar5416RateSize; i++) 742 ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2; 743 } 744 745 /* OFDM power per rate */ 746 REG_WRITE(ah, AR_PHY_POWER_TX_RATE1, 747 ATH9K_POW_SM(ratesArray[rate18mb], 24) 748 | ATH9K_POW_SM(ratesArray[rate12mb], 16) 749 | ATH9K_POW_SM(ratesArray[rate9mb], 8) 750 | ATH9K_POW_SM(ratesArray[rate6mb], 0)); 751 752 REG_WRITE(ah, AR_PHY_POWER_TX_RATE2, 753 ATH9K_POW_SM(ratesArray[rate54mb], 24) 754 | ATH9K_POW_SM(ratesArray[rate48mb], 16) 755 | ATH9K_POW_SM(ratesArray[rate36mb], 8) 756 | ATH9K_POW_SM(ratesArray[rate24mb], 0)); 757 758 /* CCK power per rate */ 759 if (IS_CHAN_2GHZ(chan)) { 760 REG_WRITE(ah, AR_PHY_POWER_TX_RATE3, 761 ATH9K_POW_SM(ratesArray[rate2s], 24) 762 | ATH9K_POW_SM(ratesArray[rate2l], 16) 763 | ATH9K_POW_SM(ratesArray[rateXr], 8) 764 | ATH9K_POW_SM(ratesArray[rate1l], 0)); 765 REG_WRITE(ah, AR_PHY_POWER_TX_RATE4, 766 ATH9K_POW_SM(ratesArray[rate11s], 24) 767 | ATH9K_POW_SM(ratesArray[rate11l], 16) 768 | ATH9K_POW_SM(ratesArray[rate5_5s], 8) 769 | ATH9K_POW_SM(ratesArray[rate5_5l], 0)); 770 } 771 772 /* HT20 power per rate */ 773 REG_WRITE(ah, AR_PHY_POWER_TX_RATE5, 774 ATH9K_POW_SM(ratesArray[rateHt20_3], 24) 775 | ATH9K_POW_SM(ratesArray[rateHt20_2], 16) 776 | ATH9K_POW_SM(ratesArray[rateHt20_1], 8) 777 | ATH9K_POW_SM(ratesArray[rateHt20_0], 0)); 778 779 REG_WRITE(ah, AR_PHY_POWER_TX_RATE6, 780 ATH9K_POW_SM(ratesArray[rateHt20_7], 24) 781 | ATH9K_POW_SM(ratesArray[rateHt20_6], 16) 782 | ATH9K_POW_SM(ratesArray[rateHt20_5], 8) 783 | ATH9K_POW_SM(ratesArray[rateHt20_4], 0)); 784 785 /* HT40 power per rate */ 786 if (IS_CHAN_HT40(chan)) { 787 if (ath9k_hw_ar9287_get_eeprom(ah, EEP_OL_PWRCTRL)) { 788 REG_WRITE(ah, AR_PHY_POWER_TX_RATE7, 789 ATH9K_POW_SM(ratesArray[rateHt40_3], 24) 790 | ATH9K_POW_SM(ratesArray[rateHt40_2], 16) 791 | ATH9K_POW_SM(ratesArray[rateHt40_1], 8) 792 | ATH9K_POW_SM(ratesArray[rateHt40_0], 0)); 793 794 REG_WRITE(ah, AR_PHY_POWER_TX_RATE8, 795 ATH9K_POW_SM(ratesArray[rateHt40_7], 24) 796 | ATH9K_POW_SM(ratesArray[rateHt40_6], 16) 797 | ATH9K_POW_SM(ratesArray[rateHt40_5], 8) 798 | ATH9K_POW_SM(ratesArray[rateHt40_4], 0)); 799 } else { 800 REG_WRITE(ah, AR_PHY_POWER_TX_RATE7, 801 ATH9K_POW_SM(ratesArray[rateHt40_3] + 802 ht40PowerIncForPdadc, 24) 803 | ATH9K_POW_SM(ratesArray[rateHt40_2] + 804 ht40PowerIncForPdadc, 16) 805 | ATH9K_POW_SM(ratesArray[rateHt40_1] + 806 ht40PowerIncForPdadc, 8) 807 | ATH9K_POW_SM(ratesArray[rateHt40_0] + 808 ht40PowerIncForPdadc, 0)); 809 810 REG_WRITE(ah, AR_PHY_POWER_TX_RATE8, 811 ATH9K_POW_SM(ratesArray[rateHt40_7] + 812 ht40PowerIncForPdadc, 24) 813 | ATH9K_POW_SM(ratesArray[rateHt40_6] + 814 ht40PowerIncForPdadc, 16) 815 | ATH9K_POW_SM(ratesArray[rateHt40_5] + 816 ht40PowerIncForPdadc, 8) 817 | ATH9K_POW_SM(ratesArray[rateHt40_4] + 818 ht40PowerIncForPdadc, 0)); 819 } 820 821 /* Dup/Ext power per rate */ 822 REG_WRITE(ah, AR_PHY_POWER_TX_RATE9, 823 ATH9K_POW_SM(ratesArray[rateExtOfdm], 24) 824 | ATH9K_POW_SM(ratesArray[rateExtCck], 16) 825 | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8) 826 | ATH9K_POW_SM(ratesArray[rateDupCck], 0)); 827 } 828 } 829 830 static void ath9k_hw_ar9287_set_addac(struct ath_hw *ah, 831 struct ath9k_channel *chan) 832 { 833 } 834 835 static void ath9k_hw_ar9287_set_board_values(struct ath_hw *ah, 836 struct ath9k_channel *chan) 837 { 838 struct ar9287_eeprom *eep = &ah->eeprom.map9287; 839 struct modal_eep_ar9287_header *pModal = &eep->modalHeader; 840 u16 antWrites[AR9287_ANT_16S]; 841 u32 regChainOffset, regval; 842 u8 txRxAttenLocal; 843 int i, j, offset_num; 844 845 pModal = &eep->modalHeader; 846 847 antWrites[0] = (u16)((pModal->antCtrlCommon >> 28) & 0xF); 848 antWrites[1] = (u16)((pModal->antCtrlCommon >> 24) & 0xF); 849 antWrites[2] = (u16)((pModal->antCtrlCommon >> 20) & 0xF); 850 antWrites[3] = (u16)((pModal->antCtrlCommon >> 16) & 0xF); 851 antWrites[4] = (u16)((pModal->antCtrlCommon >> 12) & 0xF); 852 antWrites[5] = (u16)((pModal->antCtrlCommon >> 8) & 0xF); 853 antWrites[6] = (u16)((pModal->antCtrlCommon >> 4) & 0xF); 854 antWrites[7] = (u16)(pModal->antCtrlCommon & 0xF); 855 856 offset_num = 8; 857 858 for (i = 0, j = offset_num; i < AR9287_MAX_CHAINS; i++) { 859 antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 28) & 0xf); 860 antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 10) & 0x3); 861 antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 8) & 0x3); 862 antWrites[j++] = 0; 863 antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 6) & 0x3); 864 antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 4) & 0x3); 865 antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 2) & 0x3); 866 antWrites[j++] = (u16)(pModal->antCtrlChain[i] & 0x3); 867 } 868 869 REG_WRITE(ah, AR_PHY_SWITCH_COM, pModal->antCtrlCommon); 870 871 for (i = 0; i < AR9287_MAX_CHAINS; i++) { 872 regChainOffset = i * 0x1000; 873 874 REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset, 875 pModal->antCtrlChain[i]); 876 877 REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset, 878 (REG_READ(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset) 879 & ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF | 880 AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) | 881 SM(pModal->iqCalICh[i], 882 AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) | 883 SM(pModal->iqCalQCh[i], 884 AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF)); 885 886 txRxAttenLocal = pModal->txRxAttenCh[i]; 887 888 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, 889 AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, 890 pModal->bswMargin[i]); 891 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, 892 AR_PHY_GAIN_2GHZ_XATTEN1_DB, 893 pModal->bswAtten[i]); 894 REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset, 895 AR9280_PHY_RXGAIN_TXRX_ATTEN, 896 txRxAttenLocal); 897 REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset, 898 AR9280_PHY_RXGAIN_TXRX_MARGIN, 899 pModal->rxTxMarginCh[i]); 900 } 901 902 903 if (IS_CHAN_HT40(chan)) 904 REG_RMW_FIELD(ah, AR_PHY_SETTLING, 905 AR_PHY_SETTLING_SWITCH, pModal->swSettleHt40); 906 else 907 REG_RMW_FIELD(ah, AR_PHY_SETTLING, 908 AR_PHY_SETTLING_SWITCH, pModal->switchSettling); 909 910 REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, 911 AR_PHY_DESIRED_SZ_ADC, pModal->adcDesiredSize); 912 913 REG_WRITE(ah, AR_PHY_RF_CTL4, 914 SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF) 915 | SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAB_OFF) 916 | SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAA_ON) 917 | SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAB_ON)); 918 919 REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, 920 AR_PHY_TX_END_TO_A2_RX_ON, pModal->txEndToRxOn); 921 922 REG_RMW_FIELD(ah, AR_PHY_CCA, 923 AR9280_PHY_CCA_THRESH62, pModal->thresh62); 924 REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, 925 AR_PHY_EXT_CCA0_THRESH62, pModal->thresh62); 926 927 regval = REG_READ(ah, AR9287_AN_RF2G3_CH0); 928 regval &= ~(AR9287_AN_RF2G3_DB1 | 929 AR9287_AN_RF2G3_DB2 | 930 AR9287_AN_RF2G3_OB_CCK | 931 AR9287_AN_RF2G3_OB_PSK | 932 AR9287_AN_RF2G3_OB_QAM | 933 AR9287_AN_RF2G3_OB_PAL_OFF); 934 regval |= (SM(pModal->db1, AR9287_AN_RF2G3_DB1) | 935 SM(pModal->db2, AR9287_AN_RF2G3_DB2) | 936 SM(pModal->ob_cck, AR9287_AN_RF2G3_OB_CCK) | 937 SM(pModal->ob_psk, AR9287_AN_RF2G3_OB_PSK) | 938 SM(pModal->ob_qam, AR9287_AN_RF2G3_OB_QAM) | 939 SM(pModal->ob_pal_off, AR9287_AN_RF2G3_OB_PAL_OFF)); 940 941 ath9k_hw_analog_shift_regwrite(ah, AR9287_AN_RF2G3_CH0, regval); 942 943 regval = REG_READ(ah, AR9287_AN_RF2G3_CH1); 944 regval &= ~(AR9287_AN_RF2G3_DB1 | 945 AR9287_AN_RF2G3_DB2 | 946 AR9287_AN_RF2G3_OB_CCK | 947 AR9287_AN_RF2G3_OB_PSK | 948 AR9287_AN_RF2G3_OB_QAM | 949 AR9287_AN_RF2G3_OB_PAL_OFF); 950 regval |= (SM(pModal->db1, AR9287_AN_RF2G3_DB1) | 951 SM(pModal->db2, AR9287_AN_RF2G3_DB2) | 952 SM(pModal->ob_cck, AR9287_AN_RF2G3_OB_CCK) | 953 SM(pModal->ob_psk, AR9287_AN_RF2G3_OB_PSK) | 954 SM(pModal->ob_qam, AR9287_AN_RF2G3_OB_QAM) | 955 SM(pModal->ob_pal_off, AR9287_AN_RF2G3_OB_PAL_OFF)); 956 957 ath9k_hw_analog_shift_regwrite(ah, AR9287_AN_RF2G3_CH1, regval); 958 959 REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, 960 AR_PHY_TX_END_DATA_START, pModal->txFrameToDataStart); 961 REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, 962 AR_PHY_TX_END_PA_ON, pModal->txFrameToPaOn); 963 964 ath9k_hw_analog_shift_rmw(ah, AR9287_AN_TOP2, 965 AR9287_AN_TOP2_XPABIAS_LVL, 966 AR9287_AN_TOP2_XPABIAS_LVL_S, 967 pModal->xpaBiasLvl); 968 } 969 970 static u16 ath9k_hw_ar9287_get_spur_channel(struct ath_hw *ah, 971 u16 i, bool is2GHz) 972 { 973 #define EEP_MAP9287_SPURCHAN \ 974 (ah->eeprom.map9287.modalHeader.spurChans[i].spurChan) 975 976 struct ath_common *common = ath9k_hw_common(ah); 977 u16 spur_val = AR_NO_SPUR; 978 979 ath_dbg(common, ATH_DBG_ANI, 980 "Getting spur idx:%d is2Ghz:%d val:%x\n", 981 i, is2GHz, ah->config.spurchans[i][is2GHz]); 982 983 switch (ah->config.spurmode) { 984 case SPUR_DISABLE: 985 break; 986 case SPUR_ENABLE_IOCTL: 987 spur_val = ah->config.spurchans[i][is2GHz]; 988 ath_dbg(common, ATH_DBG_ANI, 989 "Getting spur val from new loc. %d\n", spur_val); 990 break; 991 case SPUR_ENABLE_EEPROM: 992 spur_val = EEP_MAP9287_SPURCHAN; 993 break; 994 } 995 996 return spur_val; 997 998 #undef EEP_MAP9287_SPURCHAN 999 } 1000 1001 const struct eeprom_ops eep_ar9287_ops = { 1002 .check_eeprom = ath9k_hw_ar9287_check_eeprom, 1003 .get_eeprom = ath9k_hw_ar9287_get_eeprom, 1004 .fill_eeprom = ath9k_hw_ar9287_fill_eeprom, 1005 .get_eeprom_ver = ath9k_hw_ar9287_get_eeprom_ver, 1006 .get_eeprom_rev = ath9k_hw_ar9287_get_eeprom_rev, 1007 .set_board_values = ath9k_hw_ar9287_set_board_values, 1008 .set_addac = ath9k_hw_ar9287_set_addac, 1009 .set_txpower = ath9k_hw_ar9287_set_txpower, 1010 .get_spur_channel = ath9k_hw_ar9287_get_spur_channel 1011 }; 1012