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