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 "hw.h" 18 #include "hw-ops.h" 19 #include "ar9002_phy.h" 20 21 #define AR9285_CLCAL_REDO_THRESH 1 22 23 enum ar9002_cal_types { 24 ADC_GAIN_CAL = BIT(0), 25 ADC_DC_CAL = BIT(1), 26 IQ_MISMATCH_CAL = BIT(2), 27 }; 28 29 static bool ar9002_hw_is_cal_supported(struct ath_hw *ah, 30 struct ath9k_channel *chan, 31 enum ar9002_cal_types cal_type) 32 { 33 bool supported = false; 34 switch (ah->supp_cals & cal_type) { 35 case IQ_MISMATCH_CAL: 36 /* Run IQ Mismatch for non-CCK only */ 37 if (!IS_CHAN_B(chan)) 38 supported = true; 39 break; 40 case ADC_GAIN_CAL: 41 case ADC_DC_CAL: 42 /* Run ADC Gain Cal for non-CCK & non 2GHz-HT20 only */ 43 if (!IS_CHAN_B(chan) && 44 !((IS_CHAN_2GHZ(chan) || IS_CHAN_A_FAST_CLOCK(ah, chan)) && 45 IS_CHAN_HT20(chan))) 46 supported = true; 47 break; 48 } 49 return supported; 50 } 51 52 static void ar9002_hw_setup_calibration(struct ath_hw *ah, 53 struct ath9k_cal_list *currCal) 54 { 55 struct ath_common *common = ath9k_hw_common(ah); 56 57 REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(0), 58 AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX, 59 currCal->calData->calCountMax); 60 61 switch (currCal->calData->calType) { 62 case IQ_MISMATCH_CAL: 63 REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ); 64 ath_dbg(common, ATH_DBG_CALIBRATE, 65 "starting IQ Mismatch Calibration\n"); 66 break; 67 case ADC_GAIN_CAL: 68 REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_GAIN); 69 ath_dbg(common, ATH_DBG_CALIBRATE, 70 "starting ADC Gain Calibration\n"); 71 break; 72 case ADC_DC_CAL: 73 REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_PER); 74 ath_dbg(common, ATH_DBG_CALIBRATE, 75 "starting ADC DC Calibration\n"); 76 break; 77 } 78 79 REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0), 80 AR_PHY_TIMING_CTRL4_DO_CAL); 81 } 82 83 static bool ar9002_hw_per_calibration(struct ath_hw *ah, 84 struct ath9k_channel *ichan, 85 u8 rxchainmask, 86 struct ath9k_cal_list *currCal) 87 { 88 struct ath9k_hw_cal_data *caldata = ah->caldata; 89 bool iscaldone = false; 90 91 if (currCal->calState == CAL_RUNNING) { 92 if (!(REG_READ(ah, AR_PHY_TIMING_CTRL4(0)) & 93 AR_PHY_TIMING_CTRL4_DO_CAL)) { 94 95 currCal->calData->calCollect(ah); 96 ah->cal_samples++; 97 98 if (ah->cal_samples >= 99 currCal->calData->calNumSamples) { 100 int i, numChains = 0; 101 for (i = 0; i < AR5416_MAX_CHAINS; i++) { 102 if (rxchainmask & (1 << i)) 103 numChains++; 104 } 105 106 currCal->calData->calPostProc(ah, numChains); 107 caldata->CalValid |= currCal->calData->calType; 108 currCal->calState = CAL_DONE; 109 iscaldone = true; 110 } else { 111 ar9002_hw_setup_calibration(ah, currCal); 112 } 113 } 114 } else if (!(caldata->CalValid & currCal->calData->calType)) { 115 ath9k_hw_reset_calibration(ah, currCal); 116 } 117 118 return iscaldone; 119 } 120 121 static void ar9002_hw_iqcal_collect(struct ath_hw *ah) 122 { 123 int i; 124 125 for (i = 0; i < AR5416_MAX_CHAINS; i++) { 126 ah->totalPowerMeasI[i] += 127 REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); 128 ah->totalPowerMeasQ[i] += 129 REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); 130 ah->totalIqCorrMeas[i] += 131 (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); 132 ath_dbg(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, 133 "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n", 134 ah->cal_samples, i, ah->totalPowerMeasI[i], 135 ah->totalPowerMeasQ[i], 136 ah->totalIqCorrMeas[i]); 137 } 138 } 139 140 static void ar9002_hw_adc_gaincal_collect(struct ath_hw *ah) 141 { 142 int i; 143 144 for (i = 0; i < AR5416_MAX_CHAINS; i++) { 145 ah->totalAdcIOddPhase[i] += 146 REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); 147 ah->totalAdcIEvenPhase[i] += 148 REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); 149 ah->totalAdcQOddPhase[i] += 150 REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); 151 ah->totalAdcQEvenPhase[i] += 152 REG_READ(ah, AR_PHY_CAL_MEAS_3(i)); 153 154 ath_dbg(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, 155 "%d: Chn %d oddi=0x%08x; eveni=0x%08x; oddq=0x%08x; evenq=0x%08x;\n", 156 ah->cal_samples, i, 157 ah->totalAdcIOddPhase[i], 158 ah->totalAdcIEvenPhase[i], 159 ah->totalAdcQOddPhase[i], 160 ah->totalAdcQEvenPhase[i]); 161 } 162 } 163 164 static void ar9002_hw_adc_dccal_collect(struct ath_hw *ah) 165 { 166 int i; 167 168 for (i = 0; i < AR5416_MAX_CHAINS; i++) { 169 ah->totalAdcDcOffsetIOddPhase[i] += 170 (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); 171 ah->totalAdcDcOffsetIEvenPhase[i] += 172 (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); 173 ah->totalAdcDcOffsetQOddPhase[i] += 174 (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); 175 ah->totalAdcDcOffsetQEvenPhase[i] += 176 (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_3(i)); 177 178 ath_dbg(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, 179 "%d: Chn %d oddi=0x%08x; eveni=0x%08x; oddq=0x%08x; evenq=0x%08x;\n", 180 ah->cal_samples, i, 181 ah->totalAdcDcOffsetIOddPhase[i], 182 ah->totalAdcDcOffsetIEvenPhase[i], 183 ah->totalAdcDcOffsetQOddPhase[i], 184 ah->totalAdcDcOffsetQEvenPhase[i]); 185 } 186 } 187 188 static void ar9002_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) 189 { 190 struct ath_common *common = ath9k_hw_common(ah); 191 u32 powerMeasQ, powerMeasI, iqCorrMeas; 192 u32 qCoffDenom, iCoffDenom; 193 int32_t qCoff, iCoff; 194 int iqCorrNeg, i; 195 196 for (i = 0; i < numChains; i++) { 197 powerMeasI = ah->totalPowerMeasI[i]; 198 powerMeasQ = ah->totalPowerMeasQ[i]; 199 iqCorrMeas = ah->totalIqCorrMeas[i]; 200 201 ath_dbg(common, ATH_DBG_CALIBRATE, 202 "Starting IQ Cal and Correction for Chain %d\n", 203 i); 204 205 ath_dbg(common, ATH_DBG_CALIBRATE, 206 "Orignal: Chn %diq_corr_meas = 0x%08x\n", 207 i, ah->totalIqCorrMeas[i]); 208 209 iqCorrNeg = 0; 210 211 if (iqCorrMeas > 0x80000000) { 212 iqCorrMeas = (0xffffffff - iqCorrMeas) + 1; 213 iqCorrNeg = 1; 214 } 215 216 ath_dbg(common, ATH_DBG_CALIBRATE, 217 "Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI); 218 ath_dbg(common, ATH_DBG_CALIBRATE, 219 "Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ); 220 ath_dbg(common, ATH_DBG_CALIBRATE, "iqCorrNeg is 0x%08x\n", 221 iqCorrNeg); 222 223 iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128; 224 qCoffDenom = powerMeasQ / 64; 225 226 if ((powerMeasQ != 0) && (iCoffDenom != 0) && 227 (qCoffDenom != 0)) { 228 iCoff = iqCorrMeas / iCoffDenom; 229 qCoff = powerMeasI / qCoffDenom - 64; 230 ath_dbg(common, ATH_DBG_CALIBRATE, 231 "Chn %d iCoff = 0x%08x\n", i, iCoff); 232 ath_dbg(common, ATH_DBG_CALIBRATE, 233 "Chn %d qCoff = 0x%08x\n", i, qCoff); 234 235 iCoff = iCoff & 0x3f; 236 ath_dbg(common, ATH_DBG_CALIBRATE, 237 "New: Chn %d iCoff = 0x%08x\n", i, iCoff); 238 if (iqCorrNeg == 0x0) 239 iCoff = 0x40 - iCoff; 240 241 if (qCoff > 15) 242 qCoff = 15; 243 else if (qCoff <= -16) 244 qCoff = -16; 245 246 ath_dbg(common, ATH_DBG_CALIBRATE, 247 "Chn %d : iCoff = 0x%x qCoff = 0x%x\n", 248 i, iCoff, qCoff); 249 250 REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i), 251 AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF, 252 iCoff); 253 REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i), 254 AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF, 255 qCoff); 256 ath_dbg(common, ATH_DBG_CALIBRATE, 257 "IQ Cal and Correction done for Chain %d\n", 258 i); 259 } 260 } 261 262 REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0), 263 AR_PHY_TIMING_CTRL4_IQCORR_ENABLE); 264 } 265 266 static void ar9002_hw_adc_gaincal_calibrate(struct ath_hw *ah, u8 numChains) 267 { 268 struct ath_common *common = ath9k_hw_common(ah); 269 u32 iOddMeasOffset, iEvenMeasOffset, qOddMeasOffset, qEvenMeasOffset; 270 u32 qGainMismatch, iGainMismatch, val, i; 271 272 for (i = 0; i < numChains; i++) { 273 iOddMeasOffset = ah->totalAdcIOddPhase[i]; 274 iEvenMeasOffset = ah->totalAdcIEvenPhase[i]; 275 qOddMeasOffset = ah->totalAdcQOddPhase[i]; 276 qEvenMeasOffset = ah->totalAdcQEvenPhase[i]; 277 278 ath_dbg(common, ATH_DBG_CALIBRATE, 279 "Starting ADC Gain Cal for Chain %d\n", i); 280 281 ath_dbg(common, ATH_DBG_CALIBRATE, 282 "Chn %d pwr_meas_odd_i = 0x%08x\n", i, 283 iOddMeasOffset); 284 ath_dbg(common, ATH_DBG_CALIBRATE, 285 "Chn %d pwr_meas_even_i = 0x%08x\n", i, 286 iEvenMeasOffset); 287 ath_dbg(common, ATH_DBG_CALIBRATE, 288 "Chn %d pwr_meas_odd_q = 0x%08x\n", i, 289 qOddMeasOffset); 290 ath_dbg(common, ATH_DBG_CALIBRATE, 291 "Chn %d pwr_meas_even_q = 0x%08x\n", i, 292 qEvenMeasOffset); 293 294 if (iOddMeasOffset != 0 && qEvenMeasOffset != 0) { 295 iGainMismatch = 296 ((iEvenMeasOffset * 32) / 297 iOddMeasOffset) & 0x3f; 298 qGainMismatch = 299 ((qOddMeasOffset * 32) / 300 qEvenMeasOffset) & 0x3f; 301 302 ath_dbg(common, ATH_DBG_CALIBRATE, 303 "Chn %d gain_mismatch_i = 0x%08x\n", i, 304 iGainMismatch); 305 ath_dbg(common, ATH_DBG_CALIBRATE, 306 "Chn %d gain_mismatch_q = 0x%08x\n", i, 307 qGainMismatch); 308 309 val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i)); 310 val &= 0xfffff000; 311 val |= (qGainMismatch) | (iGainMismatch << 6); 312 REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val); 313 314 ath_dbg(common, ATH_DBG_CALIBRATE, 315 "ADC Gain Cal done for Chain %d\n", i); 316 } 317 } 318 319 REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0), 320 REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) | 321 AR_PHY_NEW_ADC_GAIN_CORR_ENABLE); 322 } 323 324 static void ar9002_hw_adc_dccal_calibrate(struct ath_hw *ah, u8 numChains) 325 { 326 struct ath_common *common = ath9k_hw_common(ah); 327 u32 iOddMeasOffset, iEvenMeasOffset, val, i; 328 int32_t qOddMeasOffset, qEvenMeasOffset, qDcMismatch, iDcMismatch; 329 const struct ath9k_percal_data *calData = 330 ah->cal_list_curr->calData; 331 u32 numSamples = 332 (1 << (calData->calCountMax + 5)) * calData->calNumSamples; 333 334 for (i = 0; i < numChains; i++) { 335 iOddMeasOffset = ah->totalAdcDcOffsetIOddPhase[i]; 336 iEvenMeasOffset = ah->totalAdcDcOffsetIEvenPhase[i]; 337 qOddMeasOffset = ah->totalAdcDcOffsetQOddPhase[i]; 338 qEvenMeasOffset = ah->totalAdcDcOffsetQEvenPhase[i]; 339 340 ath_dbg(common, ATH_DBG_CALIBRATE, 341 "Starting ADC DC Offset Cal for Chain %d\n", i); 342 343 ath_dbg(common, ATH_DBG_CALIBRATE, 344 "Chn %d pwr_meas_odd_i = %d\n", i, 345 iOddMeasOffset); 346 ath_dbg(common, ATH_DBG_CALIBRATE, 347 "Chn %d pwr_meas_even_i = %d\n", i, 348 iEvenMeasOffset); 349 ath_dbg(common, ATH_DBG_CALIBRATE, 350 "Chn %d pwr_meas_odd_q = %d\n", i, 351 qOddMeasOffset); 352 ath_dbg(common, ATH_DBG_CALIBRATE, 353 "Chn %d pwr_meas_even_q = %d\n", i, 354 qEvenMeasOffset); 355 356 iDcMismatch = (((iEvenMeasOffset - iOddMeasOffset) * 2) / 357 numSamples) & 0x1ff; 358 qDcMismatch = (((qOddMeasOffset - qEvenMeasOffset) * 2) / 359 numSamples) & 0x1ff; 360 361 ath_dbg(common, ATH_DBG_CALIBRATE, 362 "Chn %d dc_offset_mismatch_i = 0x%08x\n", i, 363 iDcMismatch); 364 ath_dbg(common, ATH_DBG_CALIBRATE, 365 "Chn %d dc_offset_mismatch_q = 0x%08x\n", i, 366 qDcMismatch); 367 368 val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i)); 369 val &= 0xc0000fff; 370 val |= (qDcMismatch << 12) | (iDcMismatch << 21); 371 REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val); 372 373 ath_dbg(common, ATH_DBG_CALIBRATE, 374 "ADC DC Offset Cal done for Chain %d\n", i); 375 } 376 377 REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0), 378 REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) | 379 AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE); 380 } 381 382 static void ar9287_hw_olc_temp_compensation(struct ath_hw *ah) 383 { 384 u32 rddata; 385 int32_t delta, currPDADC, slope; 386 387 rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4); 388 currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT); 389 390 if (ah->initPDADC == 0 || currPDADC == 0) { 391 /* 392 * Zero value indicates that no frames have been transmitted 393 * yet, can't do temperature compensation until frames are 394 * transmitted. 395 */ 396 return; 397 } else { 398 slope = ah->eep_ops->get_eeprom(ah, EEP_TEMPSENSE_SLOPE); 399 400 if (slope == 0) { /* to avoid divide by zero case */ 401 delta = 0; 402 } else { 403 delta = ((currPDADC - ah->initPDADC)*4) / slope; 404 } 405 REG_RMW_FIELD(ah, AR_PHY_CH0_TX_PWRCTRL11, 406 AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta); 407 REG_RMW_FIELD(ah, AR_PHY_CH1_TX_PWRCTRL11, 408 AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta); 409 } 410 } 411 412 static void ar9280_hw_olc_temp_compensation(struct ath_hw *ah) 413 { 414 u32 rddata, i; 415 int delta, currPDADC, regval; 416 417 rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4); 418 currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT); 419 420 if (ah->initPDADC == 0 || currPDADC == 0) 421 return; 422 423 if (ah->eep_ops->get_eeprom(ah, EEP_DAC_HPWR_5G)) 424 delta = (currPDADC - ah->initPDADC + 4) / 8; 425 else 426 delta = (currPDADC - ah->initPDADC + 5) / 10; 427 428 if (delta != ah->PDADCdelta) { 429 ah->PDADCdelta = delta; 430 for (i = 1; i < AR9280_TX_GAIN_TABLE_SIZE; i++) { 431 regval = ah->originalGain[i] - delta; 432 if (regval < 0) 433 regval = 0; 434 435 REG_RMW_FIELD(ah, 436 AR_PHY_TX_GAIN_TBL1 + i * 4, 437 AR_PHY_TX_GAIN, regval); 438 } 439 } 440 } 441 442 static void ar9271_hw_pa_cal(struct ath_hw *ah, bool is_reset) 443 { 444 u32 regVal; 445 unsigned int i; 446 u32 regList[][2] = { 447 { 0x786c, 0 }, 448 { 0x7854, 0 }, 449 { 0x7820, 0 }, 450 { 0x7824, 0 }, 451 { 0x7868, 0 }, 452 { 0x783c, 0 }, 453 { 0x7838, 0 } , 454 { 0x7828, 0 } , 455 }; 456 457 for (i = 0; i < ARRAY_SIZE(regList); i++) 458 regList[i][1] = REG_READ(ah, regList[i][0]); 459 460 regVal = REG_READ(ah, 0x7834); 461 regVal &= (~(0x1)); 462 REG_WRITE(ah, 0x7834, regVal); 463 regVal = REG_READ(ah, 0x9808); 464 regVal |= (0x1 << 27); 465 REG_WRITE(ah, 0x9808, regVal); 466 467 /* 786c,b23,1, pwddac=1 */ 468 REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1); 469 /* 7854, b5,1, pdrxtxbb=1 */ 470 REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1); 471 /* 7854, b7,1, pdv2i=1 */ 472 REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1); 473 /* 7854, b8,1, pddacinterface=1 */ 474 REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1); 475 /* 7824,b12,0, offcal=0 */ 476 REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0); 477 /* 7838, b1,0, pwddb=0 */ 478 REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0); 479 /* 7820,b11,0, enpacal=0 */ 480 REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0); 481 /* 7820,b25,1, pdpadrv1=0 */ 482 REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 0); 483 /* 7820,b24,0, pdpadrv2=0 */ 484 REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2, 0); 485 /* 7820,b23,0, pdpaout=0 */ 486 REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0); 487 /* 783c,b14-16,7, padrvgn2tab_0=7 */ 488 REG_RMW_FIELD(ah, AR9285_AN_RF2G8, AR9285_AN_RF2G8_PADRVGN2TAB0, 7); 489 /* 490 * 7838,b29-31,0, padrvgn1tab_0=0 491 * does not matter since we turn it off 492 */ 493 REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PADRVGN2TAB0, 0); 494 495 REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9271_AN_RF2G3_CCOMP, 0xfff); 496 497 /* Set: 498 * localmode=1,bmode=1,bmoderxtx=1,synthon=1, 499 * txon=1,paon=1,oscon=1,synthon_force=1 500 */ 501 REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0); 502 udelay(30); 503 REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9271_AN_RF2G6_OFFS, 0); 504 505 /* find off_6_1; */ 506 for (i = 6; i > 0; i--) { 507 regVal = REG_READ(ah, 0x7834); 508 regVal |= (1 << (20 + i)); 509 REG_WRITE(ah, 0x7834, regVal); 510 udelay(1); 511 /* regVal = REG_READ(ah, 0x7834); */ 512 regVal &= (~(0x1 << (20 + i))); 513 regVal |= (MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9) 514 << (20 + i)); 515 REG_WRITE(ah, 0x7834, regVal); 516 } 517 518 regVal = (regVal >> 20) & 0x7f; 519 520 /* Update PA cal info */ 521 if ((!is_reset) && (ah->pacal_info.prev_offset == regVal)) { 522 if (ah->pacal_info.max_skipcount < MAX_PACAL_SKIPCOUNT) 523 ah->pacal_info.max_skipcount = 524 2 * ah->pacal_info.max_skipcount; 525 ah->pacal_info.skipcount = ah->pacal_info.max_skipcount; 526 } else { 527 ah->pacal_info.max_skipcount = 1; 528 ah->pacal_info.skipcount = 0; 529 ah->pacal_info.prev_offset = regVal; 530 } 531 532 ENABLE_REGWRITE_BUFFER(ah); 533 534 regVal = REG_READ(ah, 0x7834); 535 regVal |= 0x1; 536 REG_WRITE(ah, 0x7834, regVal); 537 regVal = REG_READ(ah, 0x9808); 538 regVal &= (~(0x1 << 27)); 539 REG_WRITE(ah, 0x9808, regVal); 540 541 for (i = 0; i < ARRAY_SIZE(regList); i++) 542 REG_WRITE(ah, regList[i][0], regList[i][1]); 543 544 REGWRITE_BUFFER_FLUSH(ah); 545 } 546 547 static inline void ar9285_hw_pa_cal(struct ath_hw *ah, bool is_reset) 548 { 549 struct ath_common *common = ath9k_hw_common(ah); 550 u32 regVal; 551 int i, offset, offs_6_1, offs_0; 552 u32 ccomp_org, reg_field; 553 u32 regList[][2] = { 554 { 0x786c, 0 }, 555 { 0x7854, 0 }, 556 { 0x7820, 0 }, 557 { 0x7824, 0 }, 558 { 0x7868, 0 }, 559 { 0x783c, 0 }, 560 { 0x7838, 0 }, 561 }; 562 563 ath_dbg(common, ATH_DBG_CALIBRATE, "Running PA Calibration\n"); 564 565 /* PA CAL is not needed for high power solution */ 566 if (ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE) == 567 AR5416_EEP_TXGAIN_HIGH_POWER) 568 return; 569 570 for (i = 0; i < ARRAY_SIZE(regList); i++) 571 regList[i][1] = REG_READ(ah, regList[i][0]); 572 573 regVal = REG_READ(ah, 0x7834); 574 regVal &= (~(0x1)); 575 REG_WRITE(ah, 0x7834, regVal); 576 regVal = REG_READ(ah, 0x9808); 577 regVal |= (0x1 << 27); 578 REG_WRITE(ah, 0x9808, regVal); 579 580 REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1); 581 REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1); 582 REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1); 583 REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1); 584 REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0); 585 REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0); 586 REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0); 587 REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 0); 588 REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2, 0); 589 REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0); 590 REG_RMW_FIELD(ah, AR9285_AN_RF2G8, AR9285_AN_RF2G8_PADRVGN2TAB0, 7); 591 REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PADRVGN2TAB0, 0); 592 ccomp_org = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_CCOMP); 593 REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, 0xf); 594 595 REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0); 596 udelay(30); 597 REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, 0); 598 REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 0); 599 600 for (i = 6; i > 0; i--) { 601 regVal = REG_READ(ah, 0x7834); 602 regVal |= (1 << (19 + i)); 603 REG_WRITE(ah, 0x7834, regVal); 604 udelay(1); 605 regVal = REG_READ(ah, 0x7834); 606 regVal &= (~(0x1 << (19 + i))); 607 reg_field = MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9); 608 regVal |= (reg_field << (19 + i)); 609 REG_WRITE(ah, 0x7834, regVal); 610 } 611 612 REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 1); 613 udelay(1); 614 reg_field = MS(REG_READ(ah, AR9285_AN_RF2G9), AR9285_AN_RXTXBB1_SPARE9); 615 REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, reg_field); 616 offs_6_1 = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_OFFS); 617 offs_0 = MS(REG_READ(ah, AR9285_AN_RF2G3), AR9285_AN_RF2G3_PDVCCOMP); 618 619 offset = (offs_6_1<<1) | offs_0; 620 offset = offset - 0; 621 offs_6_1 = offset>>1; 622 offs_0 = offset & 1; 623 624 if ((!is_reset) && (ah->pacal_info.prev_offset == offset)) { 625 if (ah->pacal_info.max_skipcount < MAX_PACAL_SKIPCOUNT) 626 ah->pacal_info.max_skipcount = 627 2 * ah->pacal_info.max_skipcount; 628 ah->pacal_info.skipcount = ah->pacal_info.max_skipcount; 629 } else { 630 ah->pacal_info.max_skipcount = 1; 631 ah->pacal_info.skipcount = 0; 632 ah->pacal_info.prev_offset = offset; 633 } 634 635 REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, offs_6_1); 636 REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, offs_0); 637 638 regVal = REG_READ(ah, 0x7834); 639 regVal |= 0x1; 640 REG_WRITE(ah, 0x7834, regVal); 641 regVal = REG_READ(ah, 0x9808); 642 regVal &= (~(0x1 << 27)); 643 REG_WRITE(ah, 0x9808, regVal); 644 645 for (i = 0; i < ARRAY_SIZE(regList); i++) 646 REG_WRITE(ah, regList[i][0], regList[i][1]); 647 648 REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, ccomp_org); 649 } 650 651 static void ar9002_hw_pa_cal(struct ath_hw *ah, bool is_reset) 652 { 653 if (AR_SREV_9271(ah)) { 654 if (is_reset || !ah->pacal_info.skipcount) 655 ar9271_hw_pa_cal(ah, is_reset); 656 else 657 ah->pacal_info.skipcount--; 658 } else if (AR_SREV_9285_12_OR_LATER(ah)) { 659 if (is_reset || !ah->pacal_info.skipcount) 660 ar9285_hw_pa_cal(ah, is_reset); 661 else 662 ah->pacal_info.skipcount--; 663 } 664 } 665 666 static void ar9002_hw_olc_temp_compensation(struct ath_hw *ah) 667 { 668 if (OLC_FOR_AR9287_10_LATER) 669 ar9287_hw_olc_temp_compensation(ah); 670 else if (OLC_FOR_AR9280_20_LATER) 671 ar9280_hw_olc_temp_compensation(ah); 672 } 673 674 static bool ar9002_hw_calibrate(struct ath_hw *ah, 675 struct ath9k_channel *chan, 676 u8 rxchainmask, 677 bool longcal) 678 { 679 bool iscaldone = true; 680 struct ath9k_cal_list *currCal = ah->cal_list_curr; 681 bool nfcal, nfcal_pending = false; 682 683 nfcal = !!(REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF); 684 if (ah->caldata) 685 nfcal_pending = ah->caldata->nfcal_pending; 686 687 if (currCal && !nfcal && 688 (currCal->calState == CAL_RUNNING || 689 currCal->calState == CAL_WAITING)) { 690 iscaldone = ar9002_hw_per_calibration(ah, chan, 691 rxchainmask, currCal); 692 if (iscaldone) { 693 ah->cal_list_curr = currCal = currCal->calNext; 694 695 if (currCal->calState == CAL_WAITING) { 696 iscaldone = false; 697 ath9k_hw_reset_calibration(ah, currCal); 698 } 699 } 700 } 701 702 /* Do NF cal only at longer intervals */ 703 if (longcal || nfcal_pending) { 704 /* 705 * Get the value from the previous NF cal and update 706 * history buffer. 707 */ 708 if (ath9k_hw_getnf(ah, chan)) { 709 /* 710 * Load the NF from history buffer of the current 711 * channel. 712 * NF is slow time-variant, so it is OK to use a 713 * historical value. 714 */ 715 ath9k_hw_loadnf(ah, ah->curchan); 716 } 717 718 if (longcal) { 719 ath9k_hw_start_nfcal(ah, false); 720 /* Do periodic PAOffset Cal */ 721 ar9002_hw_pa_cal(ah, false); 722 ar9002_hw_olc_temp_compensation(ah); 723 } 724 } 725 726 return iscaldone; 727 } 728 729 /* Carrier leakage Calibration fix */ 730 static bool ar9285_hw_cl_cal(struct ath_hw *ah, struct ath9k_channel *chan) 731 { 732 struct ath_common *common = ath9k_hw_common(ah); 733 734 REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); 735 if (IS_CHAN_HT20(chan)) { 736 REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE); 737 REG_SET_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN); 738 REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, 739 AR_PHY_AGC_CONTROL_FLTR_CAL); 740 REG_CLR_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE); 741 REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL); 742 if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, 743 AR_PHY_AGC_CONTROL_CAL, 0, AH_WAIT_TIMEOUT)) { 744 ath_dbg(common, ATH_DBG_CALIBRATE, 745 "offset calibration failed to complete in 1ms; noisy environment?\n"); 746 return false; 747 } 748 REG_CLR_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN); 749 REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE); 750 REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); 751 } 752 REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); 753 REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); 754 REG_SET_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE); 755 REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL); 756 if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 757 0, AH_WAIT_TIMEOUT)) { 758 ath_dbg(common, ATH_DBG_CALIBRATE, 759 "offset calibration failed to complete in 1ms; noisy environment?\n"); 760 return false; 761 } 762 763 REG_SET_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); 764 REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); 765 REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); 766 767 return true; 768 } 769 770 static bool ar9285_hw_clc(struct ath_hw *ah, struct ath9k_channel *chan) 771 { 772 int i; 773 u_int32_t txgain_max; 774 u_int32_t clc_gain, gain_mask = 0, clc_num = 0; 775 u_int32_t reg_clc_I0, reg_clc_Q0; 776 u_int32_t i0_num = 0; 777 u_int32_t q0_num = 0; 778 u_int32_t total_num = 0; 779 u_int32_t reg_rf2g5_org; 780 bool retv = true; 781 782 if (!(ar9285_hw_cl_cal(ah, chan))) 783 return false; 784 785 txgain_max = MS(REG_READ(ah, AR_PHY_TX_PWRCTRL7), 786 AR_PHY_TX_PWRCTRL_TX_GAIN_TAB_MAX); 787 788 for (i = 0; i < (txgain_max+1); i++) { 789 clc_gain = (REG_READ(ah, (AR_PHY_TX_GAIN_TBL1+(i<<2))) & 790 AR_PHY_TX_GAIN_CLC) >> AR_PHY_TX_GAIN_CLC_S; 791 if (!(gain_mask & (1 << clc_gain))) { 792 gain_mask |= (1 << clc_gain); 793 clc_num++; 794 } 795 } 796 797 for (i = 0; i < clc_num; i++) { 798 reg_clc_I0 = (REG_READ(ah, (AR_PHY_CLC_TBL1 + (i << 2))) 799 & AR_PHY_CLC_I0) >> AR_PHY_CLC_I0_S; 800 reg_clc_Q0 = (REG_READ(ah, (AR_PHY_CLC_TBL1 + (i << 2))) 801 & AR_PHY_CLC_Q0) >> AR_PHY_CLC_Q0_S; 802 if (reg_clc_I0 == 0) 803 i0_num++; 804 805 if (reg_clc_Q0 == 0) 806 q0_num++; 807 } 808 total_num = i0_num + q0_num; 809 if (total_num > AR9285_CLCAL_REDO_THRESH) { 810 reg_rf2g5_org = REG_READ(ah, AR9285_RF2G5); 811 if (AR_SREV_9285E_20(ah)) { 812 REG_WRITE(ah, AR9285_RF2G5, 813 (reg_rf2g5_org & AR9285_RF2G5_IC50TX) | 814 AR9285_RF2G5_IC50TX_XE_SET); 815 } else { 816 REG_WRITE(ah, AR9285_RF2G5, 817 (reg_rf2g5_org & AR9285_RF2G5_IC50TX) | 818 AR9285_RF2G5_IC50TX_SET); 819 } 820 retv = ar9285_hw_cl_cal(ah, chan); 821 REG_WRITE(ah, AR9285_RF2G5, reg_rf2g5_org); 822 } 823 return retv; 824 } 825 826 static bool ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) 827 { 828 struct ath_common *common = ath9k_hw_common(ah); 829 830 if (AR_SREV_9271(ah)) { 831 if (!ar9285_hw_cl_cal(ah, chan)) 832 return false; 833 } else if (AR_SREV_9285(ah) && AR_SREV_9285_12_OR_LATER(ah)) { 834 if (!ar9285_hw_clc(ah, chan)) 835 return false; 836 } else { 837 if (AR_SREV_9280_20_OR_LATER(ah)) { 838 if (!AR_SREV_9287_11_OR_LATER(ah)) 839 REG_CLR_BIT(ah, AR_PHY_ADC_CTL, 840 AR_PHY_ADC_CTL_OFF_PWDADC); 841 REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, 842 AR_PHY_AGC_CONTROL_FLTR_CAL); 843 } 844 845 /* Calibrate the AGC */ 846 REG_WRITE(ah, AR_PHY_AGC_CONTROL, 847 REG_READ(ah, AR_PHY_AGC_CONTROL) | 848 AR_PHY_AGC_CONTROL_CAL); 849 850 /* Poll for offset calibration complete */ 851 if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, 852 AR_PHY_AGC_CONTROL_CAL, 853 0, AH_WAIT_TIMEOUT)) { 854 ath_dbg(common, ATH_DBG_CALIBRATE, 855 "offset calibration failed to complete in 1ms; noisy environment?\n"); 856 return false; 857 } 858 859 if (AR_SREV_9280_20_OR_LATER(ah)) { 860 if (!AR_SREV_9287_11_OR_LATER(ah)) 861 REG_SET_BIT(ah, AR_PHY_ADC_CTL, 862 AR_PHY_ADC_CTL_OFF_PWDADC); 863 REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, 864 AR_PHY_AGC_CONTROL_FLTR_CAL); 865 } 866 } 867 868 /* Do PA Calibration */ 869 ar9002_hw_pa_cal(ah, true); 870 871 if (ah->caldata) 872 ah->caldata->nfcal_pending = true; 873 874 ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL; 875 876 /* Enable IQ, ADC Gain and ADC DC offset CALs */ 877 if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) { 878 ah->supp_cals = IQ_MISMATCH_CAL; 879 880 if (AR_SREV_9160_10_OR_LATER(ah)) 881 ah->supp_cals |= ADC_GAIN_CAL | ADC_DC_CAL; 882 883 if (AR_SREV_9287(ah)) 884 ah->supp_cals &= ~ADC_GAIN_CAL; 885 886 if (ar9002_hw_is_cal_supported(ah, chan, ADC_GAIN_CAL)) { 887 INIT_CAL(&ah->adcgain_caldata); 888 INSERT_CAL(ah, &ah->adcgain_caldata); 889 ath_dbg(common, ATH_DBG_CALIBRATE, 890 "enabling ADC Gain Calibration.\n"); 891 } 892 893 if (ar9002_hw_is_cal_supported(ah, chan, ADC_DC_CAL)) { 894 INIT_CAL(&ah->adcdc_caldata); 895 INSERT_CAL(ah, &ah->adcdc_caldata); 896 ath_dbg(common, ATH_DBG_CALIBRATE, 897 "enabling ADC DC Calibration.\n"); 898 } 899 900 if (ar9002_hw_is_cal_supported(ah, chan, IQ_MISMATCH_CAL)) { 901 INIT_CAL(&ah->iq_caldata); 902 INSERT_CAL(ah, &ah->iq_caldata); 903 ath_dbg(common, ATH_DBG_CALIBRATE, 904 "enabling IQ Calibration.\n"); 905 } 906 907 ah->cal_list_curr = ah->cal_list; 908 909 if (ah->cal_list_curr) 910 ath9k_hw_reset_calibration(ah, ah->cal_list_curr); 911 } 912 913 if (ah->caldata) 914 ah->caldata->CalValid = 0; 915 916 return true; 917 } 918 919 static const struct ath9k_percal_data iq_cal_multi_sample = { 920 IQ_MISMATCH_CAL, 921 MAX_CAL_SAMPLES, 922 PER_MIN_LOG_COUNT, 923 ar9002_hw_iqcal_collect, 924 ar9002_hw_iqcalibrate 925 }; 926 static const struct ath9k_percal_data iq_cal_single_sample = { 927 IQ_MISMATCH_CAL, 928 MIN_CAL_SAMPLES, 929 PER_MAX_LOG_COUNT, 930 ar9002_hw_iqcal_collect, 931 ar9002_hw_iqcalibrate 932 }; 933 static const struct ath9k_percal_data adc_gain_cal_multi_sample = { 934 ADC_GAIN_CAL, 935 MAX_CAL_SAMPLES, 936 PER_MIN_LOG_COUNT, 937 ar9002_hw_adc_gaincal_collect, 938 ar9002_hw_adc_gaincal_calibrate 939 }; 940 static const struct ath9k_percal_data adc_gain_cal_single_sample = { 941 ADC_GAIN_CAL, 942 MIN_CAL_SAMPLES, 943 PER_MAX_LOG_COUNT, 944 ar9002_hw_adc_gaincal_collect, 945 ar9002_hw_adc_gaincal_calibrate 946 }; 947 static const struct ath9k_percal_data adc_dc_cal_multi_sample = { 948 ADC_DC_CAL, 949 MAX_CAL_SAMPLES, 950 PER_MIN_LOG_COUNT, 951 ar9002_hw_adc_dccal_collect, 952 ar9002_hw_adc_dccal_calibrate 953 }; 954 static const struct ath9k_percal_data adc_dc_cal_single_sample = { 955 ADC_DC_CAL, 956 MIN_CAL_SAMPLES, 957 PER_MAX_LOG_COUNT, 958 ar9002_hw_adc_dccal_collect, 959 ar9002_hw_adc_dccal_calibrate 960 }; 961 962 static void ar9002_hw_init_cal_settings(struct ath_hw *ah) 963 { 964 if (AR_SREV_9100(ah)) { 965 ah->iq_caldata.calData = &iq_cal_multi_sample; 966 ah->supp_cals = IQ_MISMATCH_CAL; 967 return; 968 } 969 970 if (AR_SREV_9160_10_OR_LATER(ah)) { 971 if (AR_SREV_9280_20_OR_LATER(ah)) { 972 ah->iq_caldata.calData = &iq_cal_single_sample; 973 ah->adcgain_caldata.calData = 974 &adc_gain_cal_single_sample; 975 ah->adcdc_caldata.calData = 976 &adc_dc_cal_single_sample; 977 } else { 978 ah->iq_caldata.calData = &iq_cal_multi_sample; 979 ah->adcgain_caldata.calData = 980 &adc_gain_cal_multi_sample; 981 ah->adcdc_caldata.calData = 982 &adc_dc_cal_multi_sample; 983 } 984 ah->supp_cals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL; 985 986 if (AR_SREV_9287(ah)) 987 ah->supp_cals &= ~ADC_GAIN_CAL; 988 } 989 } 990 991 void ar9002_hw_attach_calib_ops(struct ath_hw *ah) 992 { 993 struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); 994 struct ath_hw_ops *ops = ath9k_hw_ops(ah); 995 996 priv_ops->init_cal_settings = ar9002_hw_init_cal_settings; 997 priv_ops->init_cal = ar9002_hw_init_cal; 998 priv_ops->setup_calibration = ar9002_hw_setup_calibration; 999 1000 ops->calibrate = ar9002_hw_calibrate; 1001 } 1002