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