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