1 /* 2 * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 /* 7 * Copyright (c) 2008 Atheros Communications Inc. 8 * 9 * Permission to use, copy, modify, and/or distribute this software for any 10 * purpose with or without fee is hereby granted, provided that the above 11 * copyright notice and this permission notice appear in all copies. 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 19 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 20 */ 21 22 #include "arn_core.h" 23 #include "arn_hw.h" 24 #include "arn_reg.h" 25 #include "arn_phy.h" 26 27 static const int16_t NOISE_FLOOR[] = { -96, -93, -98, -96, -93, -96 }; 28 29 /* We can tune this as we go by monitoring really low values */ 30 #define ATH9K_NF_TOO_LOW -60 31 32 /* 33 * AR5416 may return very high value (like -31 dBm), in those cases the nf 34 * is incorrect and we should use the static NF value. Later we can try to 35 * find out why they are reporting these values 36 */ 37 38 /* ARGSUSED */ 39 static boolean_t 40 ath9k_hw_nf_in_range(struct ath_hal *ah, signed short nf) 41 { 42 if (nf > ATH9K_NF_TOO_LOW) { 43 ARN_DBG((ARN_DBG_CALIBRATE, 44 "%s: noise floor value detected (%d) is " 45 "lower than what we think is a " 46 "reasonable value (%d)\n", 47 __func__, nf, ATH9K_NF_TOO_LOW)); 48 49 return (B_FALSE); 50 } 51 return (B_TRUE); 52 } 53 54 static int16_t 55 ath9k_hw_get_nf_hist_mid(int16_t *nfCalBuffer) 56 { 57 int16_t nfval; 58 int16_t sort[ATH9K_NF_CAL_HIST_MAX]; 59 int i, j; 60 61 for (i = 0; i < ATH9K_NF_CAL_HIST_MAX; i++) 62 sort[i] = nfCalBuffer[i]; 63 64 for (i = 0; i < ATH9K_NF_CAL_HIST_MAX - 1; i++) { 65 for (j = 1; j < ATH9K_NF_CAL_HIST_MAX - i; j++) { 66 if (sort[j] > sort[j - 1]) { 67 nfval = sort[j]; 68 sort[j] = sort[j - 1]; 69 sort[j - 1] = nfval; 70 } 71 } 72 } 73 nfval = sort[(ATH9K_NF_CAL_HIST_MAX - 1) >> 1]; 74 75 return (nfval); 76 } 77 78 static void 79 ath9k_hw_update_nfcal_hist_buffer(struct ath9k_nfcal_hist *h, 80 int16_t *nfarray) 81 { 82 int i; 83 84 for (i = 0; i < NUM_NF_READINGS; i++) { 85 h[i].nfCalBuffer[h[i].currIndex] = nfarray[i]; 86 87 if (++h[i].currIndex >= ATH9K_NF_CAL_HIST_MAX) 88 h[i].currIndex = 0; 89 90 if (h[i].invalidNFcount > 0) { 91 if (nfarray[i] < AR_PHY_CCA_MIN_BAD_VALUE || 92 nfarray[i] > AR_PHY_CCA_MAX_HIGH_VALUE) { 93 h[i].invalidNFcount = ATH9K_NF_CAL_HIST_MAX; 94 } else { 95 h[i].invalidNFcount--; 96 h[i].privNF = nfarray[i]; 97 } 98 } else { 99 h[i].privNF = 100 ath9k_hw_get_nf_hist_mid(h[i].nfCalBuffer); 101 } 102 } 103 } 104 105 static void 106 ath9k_hw_do_getnf(struct ath_hal *ah, 107 int16_t nfarray[NUM_NF_READINGS]) 108 { 109 int16_t nf; 110 111 if (AR_SREV_9280_10_OR_LATER(ah)) 112 nf = MS(REG_READ(ah, AR_PHY_CCA), AR9280_PHY_MINCCA_PWR); 113 else 114 nf = MS(REG_READ(ah, AR_PHY_CCA), AR_PHY_MINCCA_PWR); 115 116 if (nf & 0x100) 117 nf = 0 - ((nf ^ 0x1ff) + 1); 118 ARN_DBG((ARN_DBG_CALIBRATE, 119 "NF calibrated [ctl] [chain 0] is %d\n", nf)); 120 nfarray[0] = nf; 121 122 if (AR_SREV_9280_10_OR_LATER(ah)) 123 nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), 124 AR9280_PHY_CH1_MINCCA_PWR); 125 else 126 nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), 127 AR_PHY_CH1_MINCCA_PWR); 128 129 if (nf & 0x100) 130 nf = 0 - ((nf ^ 0x1ff) + 1); 131 ARN_DBG((ARN_DBG_CALIBRATE, 132 "NF calibrated [ctl] [chain 1] is %d\n", nf)); 133 nfarray[1] = nf; 134 135 if (!AR_SREV_9280(ah)) { 136 nf = MS(REG_READ(ah, AR_PHY_CH2_CCA), 137 AR_PHY_CH2_MINCCA_PWR); 138 if (nf & 0x100) 139 nf = 0 - ((nf ^ 0x1ff) + 1); 140 ARN_DBG((ARN_DBG_CALIBRATE, 141 "NF calibrated [ctl] [chain 2] is %d\n", nf)); 142 nfarray[2] = nf; 143 } 144 145 if (AR_SREV_9280_10_OR_LATER(ah)) 146 nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), 147 AR9280_PHY_EXT_MINCCA_PWR); 148 else 149 nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), 150 AR_PHY_EXT_MINCCA_PWR); 151 152 if (nf & 0x100) 153 nf = 0 - ((nf ^ 0x1ff) + 1); 154 ARN_DBG((ARN_DBG_CALIBRATE, 155 "NF calibrated [ext] [chain 0] is %d\n", nf)); 156 nfarray[3] = nf; 157 158 if (AR_SREV_9280_10_OR_LATER(ah)) 159 nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), 160 AR9280_PHY_CH1_EXT_MINCCA_PWR); 161 else 162 nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), 163 AR_PHY_CH1_EXT_MINCCA_PWR); 164 165 if (nf & 0x100) 166 nf = 0 - ((nf ^ 0x1ff) + 1); 167 ARN_DBG((ARN_DBG_CALIBRATE, 168 "NF calibrated [ext] [chain 1] is %d\n", nf)); 169 nfarray[4] = nf; 170 171 if (!AR_SREV_9280(ah)) { 172 nf = MS(REG_READ(ah, AR_PHY_CH2_EXT_CCA), 173 AR_PHY_CH2_EXT_MINCCA_PWR); 174 if (nf & 0x100) 175 nf = 0 - ((nf ^ 0x1ff) + 1); 176 ARN_DBG((ARN_DBG_CALIBRATE, 177 "NF calibrated [ext] [chain 2] is %d\n", nf)); 178 nfarray[5] = nf; 179 } 180 } 181 182 static boolean_t 183 getNoiseFloorThresh(struct ath_hal *ah, 184 const struct ath9k_channel *chan, 185 int16_t *nft) 186 { 187 switch (chan->chanmode) { 188 case CHANNEL_A: 189 case CHANNEL_A_HT20: 190 case CHANNEL_A_HT40PLUS: 191 case CHANNEL_A_HT40MINUS: 192 *nft = (int8_t)ath9k_hw_get_eeprom(ah, EEP_NFTHRESH_5); 193 break; 194 case CHANNEL_B: 195 case CHANNEL_G: 196 case CHANNEL_G_HT20: 197 case CHANNEL_G_HT40PLUS: 198 case CHANNEL_G_HT40MINUS: 199 *nft = (int8_t)ath9k_hw_get_eeprom(ah, EEP_NFTHRESH_2); 200 break; 201 default: 202 ARN_DBG((ARN_DBG_CHANNEL, 203 "%s: invalid channel flags 0x%x\n", __func__, 204 chan->channelFlags)); 205 return (B_FALSE); 206 } 207 208 return (B_TRUE); 209 } 210 211 static void 212 ath9k_hw_setup_calibration(struct ath_hal *ah, 213 struct hal_cal_list *currCal) 214 { 215 REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(0), 216 AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX, 217 currCal->calData->calCountMax); 218 219 switch (currCal->calData->calType) { 220 case IQ_MISMATCH_CAL: 221 REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ); 222 ARN_DBG((ARN_DBG_CALIBRATE, 223 "%s: starting IQ Mismatch Calibration\n", 224 __func__)); 225 break; 226 case ADC_GAIN_CAL: 227 REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_GAIN); 228 ARN_DBG((ARN_DBG_CALIBRATE, 229 "%s: starting ADC Gain Calibration\n", __func__)); 230 break; 231 case ADC_DC_CAL: 232 REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_PER); 233 ARN_DBG((ARN_DBG_CALIBRATE, 234 "%s: starting ADC DC Calibration\n", __func__)); 235 break; 236 case ADC_DC_INIT_CAL: 237 REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_INIT); 238 ARN_DBG((ARN_DBG_CALIBRATE, 239 "%s: starting Init ADC DC Calibration\n", 240 __func__)); 241 break; 242 } 243 244 REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0), 245 AR_PHY_TIMING_CTRL4_DO_CAL); 246 } 247 248 static void 249 ath9k_hw_reset_calibration(struct ath_hal *ah, 250 struct hal_cal_list *currCal) 251 { 252 struct ath_hal_5416 *ahp = AH5416(ah); 253 int i; 254 255 ath9k_hw_setup_calibration(ah, currCal); 256 257 currCal->calState = CAL_RUNNING; 258 259 for (i = 0; i < AR5416_MAX_CHAINS; i++) { 260 ahp->ah_Meas0.sign[i] = 0; 261 ahp->ah_Meas1.sign[i] = 0; 262 ahp->ah_Meas2.sign[i] = 0; 263 ahp->ah_Meas3.sign[i] = 0; 264 } 265 266 ahp->ah_CalSamples = 0; 267 } 268 269 static void 270 ath9k_hw_per_calibration(struct ath_hal *ah, 271 struct ath9k_channel *ichan, 272 uint8_t rxchainmask, 273 struct hal_cal_list *currCal, 274 boolean_t *isCalDone) 275 { 276 struct ath_hal_5416 *ahp = AH5416(ah); 277 278 *isCalDone = B_FALSE; 279 280 if (currCal->calState == CAL_RUNNING) { 281 if (!(REG_READ(ah, AR_PHY_TIMING_CTRL4(0)) & 282 AR_PHY_TIMING_CTRL4_DO_CAL)) { 283 284 currCal->calData->calCollect(ah); 285 ahp->ah_CalSamples++; 286 287 if (ahp->ah_CalSamples >= 288 currCal->calData->calNumSamples) { 289 int i, numChains = 0; 290 for (i = 0; i < AR5416_MAX_CHAINS; i++) { 291 if (rxchainmask & (1 << i)) 292 numChains++; 293 } 294 295 currCal->calData->calPostProc(ah, numChains); 296 ichan->CalValid |= currCal->calData->calType; 297 currCal->calState = CAL_DONE; 298 *isCalDone = B_TRUE; 299 } else { 300 ath9k_hw_setup_calibration(ah, currCal); 301 } 302 } 303 } else if (!(ichan->CalValid & currCal->calData->calType)) { 304 ath9k_hw_reset_calibration(ah, currCal); 305 } 306 } 307 308 static boolean_t 309 ath9k_hw_iscal_supported(struct ath_hal *ah, 310 struct ath9k_channel *chan, 311 enum hal_cal_types calType) 312 { 313 struct ath_hal_5416 *ahp = AH5416(ah); 314 boolean_t retval = B_FALSE; 315 316 switch (calType & ahp->ah_suppCals) { 317 case IQ_MISMATCH_CAL: 318 if (!IS_CHAN_B(chan)) 319 retval = B_TRUE; 320 break; 321 case ADC_GAIN_CAL: 322 case ADC_DC_CAL: 323 if (!IS_CHAN_B(chan) && 324 !(IS_CHAN_2GHZ(chan) && IS_CHAN_HT20(chan))) 325 retval = B_TRUE; 326 break; 327 } 328 329 return (retval); 330 } 331 332 static void 333 ath9k_hw_iqcal_collect(struct ath_hal *ah) 334 { 335 struct ath_hal_5416 *ahp = AH5416(ah); 336 int i; 337 338 for (i = 0; i < AR5416_MAX_CHAINS; i++) { 339 ahp->ah_totalPowerMeasI[i] += 340 REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); 341 ahp->ah_totalPowerMeasQ[i] += 342 REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); 343 ahp->ah_totalIqCorrMeas[i] += 344 (int32_t)REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); 345 ARN_DBG((ARN_DBG_CALIBRATE, 346 "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n", 347 ahp->ah_CalSamples, i, ahp->ah_totalPowerMeasI[i], 348 ahp->ah_totalPowerMeasQ[i], 349 ahp->ah_totalIqCorrMeas[i])); 350 } 351 } 352 353 static void 354 ath9k_hw_adc_gaincal_collect(struct ath_hal *ah) 355 { 356 struct ath_hal_5416 *ahp = AH5416(ah); 357 int i; 358 359 for (i = 0; i < AR5416_MAX_CHAINS; i++) { 360 ahp->ah_totalAdcIOddPhase[i] += 361 REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); 362 ahp->ah_totalAdcIEvenPhase[i] += 363 REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); 364 ahp->ah_totalAdcQOddPhase[i] += 365 REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); 366 ahp->ah_totalAdcQEvenPhase[i] += 367 REG_READ(ah, AR_PHY_CAL_MEAS_3(i)); 368 ARN_DBG((ARN_DBG_CALIBRATE, 369 "%d: Chn %d oddi=0x%08x; eveni=0x%08x; " 370 "oddq=0x%08x; evenq=0x%08x;\n", 371 ahp->ah_CalSamples, i, 372 ahp->ah_totalAdcIOddPhase[i], 373 ahp->ah_totalAdcIEvenPhase[i], 374 ahp->ah_totalAdcQOddPhase[i], 375 ahp->ah_totalAdcQEvenPhase[i])); 376 } 377 } 378 379 static void 380 ath9k_hw_adc_dccal_collect(struct ath_hal *ah) 381 { 382 struct ath_hal_5416 *ahp = AH5416(ah); 383 int i; 384 385 for (i = 0; i < AR5416_MAX_CHAINS; i++) { 386 ahp->ah_totalAdcDcOffsetIOddPhase[i] += 387 (int32_t)REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); 388 ahp->ah_totalAdcDcOffsetIEvenPhase[i] += 389 (int32_t)REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); 390 ahp->ah_totalAdcDcOffsetQOddPhase[i] += 391 (int32_t)REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); 392 ahp->ah_totalAdcDcOffsetQEvenPhase[i] += 393 (int32_t)REG_READ(ah, AR_PHY_CAL_MEAS_3(i)); 394 ARN_DBG((ARN_DBG_CALIBRATE, 395 "%d: Chn %d oddi=0x%08x; eveni=0x%08x; " 396 "oddq=0x%08x; evenq=0x%08x;\n", 397 ahp->ah_CalSamples, i, 398 ahp->ah_totalAdcDcOffsetIOddPhase[i], 399 ahp->ah_totalAdcDcOffsetIEvenPhase[i], 400 ahp->ah_totalAdcDcOffsetQOddPhase[i], 401 ahp->ah_totalAdcDcOffsetQEvenPhase[i])); 402 } 403 } 404 405 static void 406 ath9k_hw_iqcalibrate(struct ath_hal *ah, uint8_t numChains) 407 { 408 struct ath_hal_5416 *ahp = AH5416(ah); 409 uint32_t powerMeasQ, powerMeasI, iqCorrMeas; 410 uint32_t qCoffDenom, iCoffDenom; 411 int32_t qCoff, iCoff; 412 int iqCorrNeg, i; 413 414 for (i = 0; i < numChains; i++) { 415 powerMeasI = ahp->ah_totalPowerMeasI[i]; 416 powerMeasQ = ahp->ah_totalPowerMeasQ[i]; 417 iqCorrMeas = ahp->ah_totalIqCorrMeas[i]; 418 ARN_DBG((ARN_DBG_CALIBRATE, 419 "Starting IQ Cal and Correction for Chain %d\n", 420 i)); 421 422 ARN_DBG((ARN_DBG_CALIBRATE, 423 "Orignal: Chn %diq_corr_meas = 0x%08x\n", 424 i, ahp->ah_totalIqCorrMeas[i])); 425 426 iqCorrNeg = 0; 427 428 if (iqCorrMeas > 0x80000000) { 429 iqCorrMeas = (0xffffffff - iqCorrMeas) + 1; 430 iqCorrNeg = 1; 431 } 432 433 ARN_DBG((ARN_DBG_CALIBRATE, 434 "Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI)); 435 ARN_DBG((ARN_DBG_CALIBRATE, 436 "Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ)); 437 ARN_DBG((ARN_DBG_CALIBRATE, "iqCorrNeg is 0x%08x\n", 438 iqCorrNeg)); 439 440 iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128; 441 qCoffDenom = powerMeasQ / 64; 442 443 if (powerMeasQ != 0) { 444 iCoff = iqCorrMeas / iCoffDenom; 445 qCoff = powerMeasI / qCoffDenom - 64; 446 447 ARN_DBG((ARN_DBG_CALIBRATE, 448 "Chn %d iCoff = 0x%08x\n", i, iCoff)); 449 ARN_DBG((ARN_DBG_CALIBRATE, 450 "Chn %d qCoff = 0x%08x\n", i, qCoff)); 451 452 iCoff = iCoff & 0x3f; 453 454 ARN_DBG((ARN_DBG_CALIBRATE, 455 "New: Chn %d iCoff = 0x%08x\n", i, iCoff)); 456 457 if (iqCorrNeg == 0x0) 458 iCoff = 0x40 - iCoff; 459 460 if (qCoff > 15) 461 qCoff = 15; 462 else if (qCoff <= -16) 463 qCoff = 16; 464 465 ARN_DBG((ARN_DBG_CALIBRATE, 466 "Chn %d : iCoff = 0x%x qCoff = 0x%x\n", 467 i, iCoff, qCoff)); 468 469 REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i), 470 AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF, 471 iCoff); 472 REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i), 473 AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF, 474 qCoff); 475 476 ARN_DBG((ARN_DBG_CALIBRATE, 477 "IQ Cal and Correction done for Chain %d\n", 478 i)); 479 } 480 } 481 482 REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0), 483 AR_PHY_TIMING_CTRL4_IQCORR_ENABLE); 484 } 485 486 static void 487 ath9k_hw_adc_gaincal_calibrate(struct ath_hal *ah, uint8_t numChains) 488 { 489 struct ath_hal_5416 *ahp = AH5416(ah); 490 uint32_t iOddMeasOffset, iEvenMeasOffset, qOddMeasOffset, 491 qEvenMeasOffset; 492 uint32_t qGainMismatch, iGainMismatch, val, i; 493 494 for (i = 0; i < numChains; i++) { 495 iOddMeasOffset = ahp->ah_totalAdcIOddPhase[i]; 496 iEvenMeasOffset = ahp->ah_totalAdcIEvenPhase[i]; 497 qOddMeasOffset = ahp->ah_totalAdcQOddPhase[i]; 498 qEvenMeasOffset = ahp->ah_totalAdcQEvenPhase[i]; 499 500 ARN_DBG((ARN_DBG_CALIBRATE, 501 "Starting ADC Gain Cal for Chain %d\n", i)); 502 503 ARN_DBG((ARN_DBG_CALIBRATE, 504 "Chn %d pwr_meas_odd_i = 0x%08x\n", i, 505 iOddMeasOffset)); 506 ARN_DBG((ARN_DBG_CALIBRATE, 507 "Chn %d pwr_meas_even_i = 0x%08x\n", i, 508 iEvenMeasOffset)); 509 ARN_DBG((ARN_DBG_CALIBRATE, 510 "Chn %d pwr_meas_odd_q = 0x%08x\n", i, 511 qOddMeasOffset)); 512 ARN_DBG((ARN_DBG_CALIBRATE, 513 "Chn %d pwr_meas_even_q = 0x%08x\n", i, 514 qEvenMeasOffset)); 515 516 if (iOddMeasOffset != 0 && qEvenMeasOffset != 0) { 517 iGainMismatch = 518 ((iEvenMeasOffset * 32) / 519 iOddMeasOffset) & 0x3f; 520 qGainMismatch = 521 ((qOddMeasOffset * 32) / 522 qEvenMeasOffset) & 0x3f; 523 524 ARN_DBG((ARN_DBG_CALIBRATE, 525 "Chn %d gain_mismatch_i = 0x%08x\n", i, 526 iGainMismatch)); 527 ARN_DBG((ARN_DBG_CALIBRATE, 528 "Chn %d gain_mismatch_q = 0x%08x\n", i, 529 qGainMismatch)); 530 531 val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i)); 532 val &= 0xfffff000; 533 val |= (qGainMismatch) | (iGainMismatch << 6); 534 REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val); 535 536 ARN_DBG((ARN_DBG_CALIBRATE, 537 "ADC Gain Cal done for Chain %d\n", i)); 538 } 539 } 540 541 REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0), 542 REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) | 543 AR_PHY_NEW_ADC_GAIN_CORR_ENABLE); 544 } 545 546 static void 547 ath9k_hw_adc_dccal_calibrate(struct ath_hal *ah, uint8_t numChains) 548 { 549 struct ath_hal_5416 *ahp = AH5416(ah); 550 uint32_t iOddMeasOffset, iEvenMeasOffset, val, i; 551 int32_t qOddMeasOffset, qEvenMeasOffset, qDcMismatch, iDcMismatch; 552 const struct hal_percal_data *calData = 553 ahp->ah_cal_list_curr->calData; 554 uint32_t numSamples = 555 (1 << (calData->calCountMax + 5)) * calData->calNumSamples; 556 557 for (i = 0; i < numChains; i++) { 558 iOddMeasOffset = ahp->ah_totalAdcDcOffsetIOddPhase[i]; 559 iEvenMeasOffset = ahp->ah_totalAdcDcOffsetIEvenPhase[i]; 560 qOddMeasOffset = ahp->ah_totalAdcDcOffsetQOddPhase[i]; 561 qEvenMeasOffset = ahp->ah_totalAdcDcOffsetQEvenPhase[i]; 562 563 ARN_DBG((ARN_DBG_CALIBRATE, 564 "Starting ADC DC Offset Cal for Chain %d\n", i)); 565 566 ARN_DBG((ARN_DBG_CALIBRATE, 567 "Chn %d pwr_meas_odd_i = %d\n", i, 568 iOddMeasOffset)); 569 ARN_DBG((ARN_DBG_CALIBRATE, 570 "Chn %d pwr_meas_even_i = %d\n", i, 571 iEvenMeasOffset)); 572 ARN_DBG((ARN_DBG_CALIBRATE, 573 "Chn %d pwr_meas_odd_q = %d\n", i, 574 qOddMeasOffset)); 575 ARN_DBG((ARN_DBG_CALIBRATE, 576 "Chn %d pwr_meas_even_q = %d\n", i, 577 qEvenMeasOffset)); 578 579 iDcMismatch = (((iEvenMeasOffset - iOddMeasOffset) * 2) / 580 numSamples) & 0x1ff; 581 qDcMismatch = (((qOddMeasOffset - qEvenMeasOffset) * 2) / 582 numSamples) & 0x1ff; 583 584 ARN_DBG((ARN_DBG_CALIBRATE, 585 "Chn %d dc_offset_mismatch_i = 0x%08x\n", i, 586 iDcMismatch)); 587 ARN_DBG((ARN_DBG_CALIBRATE, 588 "Chn %d dc_offset_mismatch_q = 0x%08x\n", i, 589 qDcMismatch)); 590 591 val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i)); 592 val &= 0xc0000fff; 593 val |= (qDcMismatch << 12) | (iDcMismatch << 21); 594 REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val); 595 596 ARN_DBG((ARN_DBG_CALIBRATE, 597 "ADC DC Offset Cal done for Chain %d\n", i)); 598 } 599 600 REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0), 601 REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) | 602 AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE); 603 } 604 605 void 606 ath9k_hw_reset_calvalid(struct ath_hal *ah, struct ath9k_channel *chan, 607 boolean_t *isCalDone) 608 { 609 struct ath_hal_5416 *ahp = AH5416(ah); 610 struct ath9k_channel *ichan = 611 ath9k_regd_check_channel(ah, chan); 612 struct hal_cal_list *currCal = ahp->ah_cal_list_curr; 613 614 *isCalDone = B_TRUE; 615 616 if (!AR_SREV_9100(ah) && !AR_SREV_9160_10_OR_LATER(ah)) 617 return; 618 619 if (currCal == NULL) 620 return; 621 622 if (ichan == NULL) { 623 ARN_DBG((ARN_DBG_CALIBRATE, 624 "%s: invalid channel %u/0x%x; no mapping\n", 625 __func__, chan->channel, chan->channelFlags)); 626 return; 627 } 628 629 630 if (currCal->calState != CAL_DONE) { 631 ARN_DBG((ARN_DBG_CALIBRATE, 632 "%s: Calibration state incorrect, %d\n", 633 __func__, currCal->calState)); 634 return; 635 } 636 637 638 if (!ath9k_hw_iscal_supported(ah, chan, currCal->calData->calType)) 639 return; 640 ARN_DBG((ARN_DBG_CALIBRATE, 641 "%s: Resetting Cal %d state for channel %u/0x%x\n", 642 __func__, currCal->calData->calType, chan->channel, 643 chan->channelFlags)); 644 645 ichan->CalValid &= ~currCal->calData->calType; 646 currCal->calState = CAL_WAITING; 647 648 *isCalDone = B_FALSE; 649 } 650 651 void 652 ath9k_hw_start_nfcal(struct ath_hal *ah) 653 { 654 REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, 655 AR_PHY_AGC_CONTROL_ENABLE_NF); 656 REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, 657 AR_PHY_AGC_CONTROL_NO_UPDATE_NF); 658 REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); 659 } 660 661 /* ARGSUSED */ 662 void 663 ath9k_hw_loadnf(struct ath_hal *ah, struct ath9k_channel *chan) 664 { 665 struct ath9k_nfcal_hist *h; 666 int i, j; 667 int32_t val; 668 const uint32_t ar5416_cca_regs[6] = { 669 AR_PHY_CCA, 670 AR_PHY_CH1_CCA, 671 AR_PHY_CH2_CCA, 672 AR_PHY_EXT_CCA, 673 AR_PHY_CH1_EXT_CCA, 674 AR_PHY_CH2_EXT_CCA 675 }; 676 uint8_t chainmask; 677 678 if (AR_SREV_9280(ah)) 679 chainmask = 0x1B; 680 else 681 chainmask = 0x3F; 682 683 #ifdef ARN_NF_PER_CHAN 684 h = chan->nfCalHist; 685 #else 686 h = ah->nfCalHist; 687 #endif 688 689 for (i = 0; i < NUM_NF_READINGS; i++) { 690 if (chainmask & (1 << i)) { 691 val = REG_READ(ah, ar5416_cca_regs[i]); 692 val &= 0xFFFFFE00; 693 val |= (((uint32_t)(h[i].privNF) << 1) & 0x1ff); 694 REG_WRITE(ah, ar5416_cca_regs[i], val); 695 } 696 } 697 698 REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, 699 AR_PHY_AGC_CONTROL_ENABLE_NF); 700 REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, 701 AR_PHY_AGC_CONTROL_NO_UPDATE_NF); 702 REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); 703 704 for (j = 0; j < 1000; j++) { 705 if ((REG_READ(ah, AR_PHY_AGC_CONTROL) & 706 AR_PHY_AGC_CONTROL_NF) == 0) 707 break; 708 drv_usecwait(10); 709 } 710 711 for (i = 0; i < NUM_NF_READINGS; i++) { 712 if (chainmask & (1 << i)) { 713 val = REG_READ(ah, ar5416_cca_regs[i]); 714 val &= 0xFFFFFE00; 715 val |= (((uint32_t)(-50) << 1) & 0x1ff); 716 REG_WRITE(ah, ar5416_cca_regs[i], val); 717 } 718 } 719 } 720 721 int16_t 722 ath9k_hw_getnf(struct ath_hal *ah, struct ath9k_channel *chan) 723 { 724 int16_t nf, nfThresh; 725 int16_t nfarray[NUM_NF_READINGS] = { 0 }; 726 struct ath9k_nfcal_hist *h; 727 /* LINTED E_FUNC_SET_NOT_USED */ 728 uint8_t chainmask; 729 730 if (AR_SREV_9280(ah)) 731 chainmask = 0x1B; 732 else 733 chainmask = 0x3F; 734 735 chan->channelFlags &= (~CHANNEL_CW_INT); 736 if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) { 737 ARN_DBG((ARN_DBG_CALIBRATE, "arn: " 738 "%s: NF did not complete in calibration window\n", 739 __func__)); 740 nf = 0; 741 chan->rawNoiseFloor = nf; 742 return (chan->rawNoiseFloor); 743 } else { 744 ath9k_hw_do_getnf(ah, nfarray); 745 nf = nfarray[0]; 746 if (getNoiseFloorThresh(ah, chan, &nfThresh) && 747 nf > nfThresh) { 748 ARN_DBG((ARN_DBG_CALIBRATE, "arn: " 749 "%s: noise floor failed detected; " 750 "detected %d, threshold %d\n", __func__, 751 nf, nfThresh)); 752 chan->channelFlags |= CHANNEL_CW_INT; 753 } 754 } 755 756 #ifdef ARN_NF_PER_CHAN 757 h = chan->nfCalHist; 758 #else 759 h = ah->nfCalHist; 760 #endif 761 762 ath9k_hw_update_nfcal_hist_buffer(h, nfarray); 763 chan->rawNoiseFloor = h[0].privNF; 764 765 return (chan->rawNoiseFloor); 766 } 767 768 void 769 ath9k_init_nfcal_hist_buffer(struct ath_hal *ah) 770 { 771 int i, j; 772 int16_t noise_floor; 773 774 if (AR_SREV_9280(ah)) 775 noise_floor = AR_PHY_CCA_MAX_AR9280_GOOD_VALUE; 776 else if (AR_SREV_9285(ah)) 777 noise_floor = AR_PHY_CCA_MAX_AR9285_GOOD_VALUE; 778 else 779 noise_floor = AR_PHY_CCA_MAX_AR5416_GOOD_VALUE; 780 781 for (i = 0; i < NUM_NF_READINGS; i++) { 782 ah->nfCalHist[i].currIndex = 0; 783 ah->nfCalHist[i].privNF = noise_floor; 784 ah->nfCalHist[i].invalidNFcount = 785 AR_PHY_CCA_FILTERWINDOW_LENGTH; 786 for (j = 0; j < ATH9K_NF_CAL_HIST_MAX; j++) { 787 ah->nfCalHist[i].nfCalBuffer[j] = noise_floor; 788 } 789 } 790 } 791 792 signed short 793 ath9k_hw_getchan_noise(struct ath_hal *ah, struct ath9k_channel *chan) 794 { 795 struct ath9k_channel *ichan; 796 signed short nf; 797 798 ichan = ath9k_regd_check_channel(ah, chan); 799 if (ichan == NULL) { 800 ARN_DBG((ARN_DBG_CALIBRATE, 801 "%s: invalid channel %u/0x%x; no mapping\n", 802 __func__, chan->channel, chan->channelFlags)); 803 return (ATH_DEFAULT_NOISE_FLOOR); 804 } 805 if (ichan->rawNoiseFloor == 0) { 806 enum wireless_mode mode = ath9k_hw_chan2wmode(ah, chan); 807 nf = NOISE_FLOOR[mode]; 808 } else 809 nf = ichan->rawNoiseFloor; 810 811 if (!ath9k_hw_nf_in_range(ah, nf)) 812 nf = ATH_DEFAULT_NOISE_FLOOR; 813 814 return (nf); 815 } 816 817 boolean_t 818 ath9k_hw_calibrate(struct ath_hal *ah, struct ath9k_channel *chan, 819 uint8_t rxchainmask, boolean_t longcal, 820 boolean_t *isCalDone) 821 { 822 struct ath_hal_5416 *ahp = AH5416(ah); 823 struct hal_cal_list *currCal = ahp->ah_cal_list_curr; 824 struct ath9k_channel *ichan = ath9k_regd_check_channel(ah, chan); 825 826 *isCalDone = B_TRUE; 827 828 if (ichan == NULL) { 829 ARN_DBG((ARN_DBG_CHANNEL, 830 "%s: invalid channel %u/0x%x; no mapping\n", 831 __func__, chan->channel, chan->channelFlags)); 832 return (B_FALSE); 833 } 834 835 if (currCal && 836 (currCal->calState == CAL_RUNNING || 837 currCal->calState == CAL_WAITING)) { 838 ath9k_hw_per_calibration(ah, ichan, rxchainmask, currCal, 839 isCalDone); 840 if (*isCalDone) { 841 ahp->ah_cal_list_curr = currCal = currCal->calNext; 842 843 if (currCal->calState == CAL_WAITING) { 844 *isCalDone = B_FALSE; 845 ath9k_hw_reset_calibration(ah, currCal); 846 } 847 } 848 } 849 850 if (longcal) { 851 (void) ath9k_hw_getnf(ah, ichan); 852 ath9k_hw_loadnf(ah, ah->ah_curchan); 853 ath9k_hw_start_nfcal(ah); 854 855 if ((ichan->channelFlags & CHANNEL_CW_INT) != 0) { 856 chan->channelFlags |= CHANNEL_CW_INT; 857 ichan->channelFlags &= ~CHANNEL_CW_INT; 858 } 859 } 860 861 return (B_TRUE); 862 } 863 864 /* AR9285 */ 865 static inline void 866 ath9k_hw_9285_pa_cal(struct ath_hal *ah) 867 { 868 869 uint32_t regVal; 870 int i, offset, offs_6_1, offs_0; 871 uint32_t ccomp_org, reg_field; 872 uint32_t regList[][2] = { 873 { 0x786c, 0 }, 874 { 0x7854, 0 }, 875 { 0x7820, 0 }, 876 { 0x7824, 0 }, 877 { 0x7868, 0 }, 878 { 0x783c, 0 }, 879 { 0x7838, 0 }, 880 }; 881 882 if (AR_SREV_9285_11(ah)) { 883 REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14)); 884 drv_usecwait(10); 885 } 886 887 for (i = 0; i < ARRAY_SIZE(regList); i++) 888 regList[i][1] = REG_READ(ah, regList[i][0]); 889 890 regVal = REG_READ(ah, 0x7834); 891 regVal &= (~(0x1)); 892 REG_WRITE(ah, 0x7834, regVal); 893 regVal = REG_READ(ah, 0x9808); 894 regVal |= (0x1 << 27); 895 REG_WRITE(ah, 0x9808, regVal); 896 897 REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1); 898 REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1); 899 REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1); 900 REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1); 901 REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0); 902 REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0); 903 REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0); 904 REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 1); 905 REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2, 0); 906 REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0); 907 REG_RMW_FIELD(ah, AR9285_AN_RF2G8, AR9285_AN_RF2G8_PADRVGN2TAB0, 7); 908 REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PADRVGN2TAB0, 0); 909 ccomp_org = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_CCOMP); 910 REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, 7); 911 912 REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0); 913 drv_usecwait(30); 914 REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, 0); 915 REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 0); 916 917 for (i = 6; i > 0; i--) { 918 regVal = REG_READ(ah, 0x7834); 919 regVal |= (1 << (19 + i)); 920 REG_WRITE(ah, 0x7834, regVal); 921 drv_usecwait(1); 922 regVal = REG_READ(ah, 0x7834); 923 regVal &= (~(0x1 << (19 + i))); 924 reg_field = MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9); 925 regVal |= (reg_field << (19 + i)); 926 REG_WRITE(ah, 0x7834, regVal); 927 } 928 929 REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 1); 930 drv_usecwait(1); 931 reg_field = MS(REG_READ(ah, AR9285_AN_RF2G9), AR9285_AN_RXTXBB1_SPARE9); 932 REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, reg_field); 933 offs_6_1 = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_OFFS); 934 offs_0 = MS(REG_READ(ah, AR9285_AN_RF2G3), AR9285_AN_RF2G3_PDVCCOMP); 935 936 offset = (offs_6_1<<1) | offs_0; 937 offset = offset - 0; 938 offs_6_1 = offset>>1; 939 offs_0 = offset & 1; 940 941 REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, offs_6_1); 942 REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, offs_0); 943 944 regVal = REG_READ(ah, 0x7834); 945 regVal |= 0x1; 946 REG_WRITE(ah, 0x7834, regVal); 947 regVal = REG_READ(ah, 0x9808); 948 regVal &= (~(0x1 << 27)); 949 REG_WRITE(ah, 0x9808, regVal); 950 951 for (i = 0; i < ARRAY_SIZE(regList); i++) 952 REG_WRITE(ah, regList[i][0], regList[i][1]); 953 954 REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, ccomp_org); 955 956 if (AR_SREV_9285_11(ah)) 957 REG_WRITE(ah, AR9285_AN_TOP4, AR9285_AN_TOP4_DEFAULT); 958 959 } 960 961 boolean_t 962 ath9k_hw_init_cal(struct ath_hal *ah, 963 struct ath9k_channel *chan) 964 { 965 struct ath_hal_5416 *ahp = AH5416(ah); 966 struct ath9k_channel *ichan = ath9k_regd_check_channel(ah, chan); 967 968 REG_WRITE(ah, AR_PHY_AGC_CONTROL, 969 REG_READ(ah, AR_PHY_AGC_CONTROL) | 970 AR_PHY_AGC_CONTROL_CAL); 971 972 if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0)) { 973 ARN_DBG((ARN_DBG_CALIBRATE, 974 "%s: offset calibration failed to complete in 1ms; " 975 "noisy environment?\n", __func__)); 976 return (B_FALSE); 977 } 978 979 if (AR_SREV_9285(ah) && AR_SREV_9285_11_OR_LATER(ah)) 980 ath9k_hw_9285_pa_cal(ah); 981 982 REG_WRITE(ah, AR_PHY_AGC_CONTROL, 983 REG_READ(ah, AR_PHY_AGC_CONTROL) | 984 AR_PHY_AGC_CONTROL_NF); 985 986 ahp->ah_cal_list = ahp->ah_cal_list_last = ahp->ah_cal_list_curr = NULL; 987 988 if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) { 989 if (ath9k_hw_iscal_supported(ah, chan, ADC_GAIN_CAL)) { 990 /* LINTED: E_CONSTANT_CONDITION */ 991 INIT_CAL(&ahp->ah_adcGainCalData); 992 /* LINTED: E_CONSTANT_CONDITION */ 993 INSERT_CAL(ahp, &ahp->ah_adcGainCalData); 994 ARN_DBG((ARN_DBG_CALIBRATE, 995 "%s: enabling ADC Gain Calibration.\n", 996 __func__)); 997 } 998 if (ath9k_hw_iscal_supported(ah, chan, ADC_DC_CAL)) { 999 /* LINTED: E_CONSTANT_CONDITION */ 1000 INIT_CAL(&ahp->ah_adcDcCalData); 1001 /* LINTED: E_CONSTANT_CONDITION */ 1002 INSERT_CAL(ahp, &ahp->ah_adcDcCalData); 1003 ARN_DBG((ARN_DBG_CALIBRATE, 1004 "%s: enabling ADC DC Calibration.\n", 1005 __func__)); 1006 } 1007 if (ath9k_hw_iscal_supported(ah, chan, IQ_MISMATCH_CAL)) { 1008 /* LINTED: E_CONSTANT_CONDITION */ 1009 INIT_CAL(&ahp->ah_iqCalData); 1010 /* LINTED: E_CONSTANT_CONDITION */ 1011 INSERT_CAL(ahp, &ahp->ah_iqCalData); 1012 ARN_DBG((ARN_DBG_CALIBRATE, 1013 "%s: enabling IQ Calibration.\n", 1014 __func__)); 1015 } 1016 1017 ahp->ah_cal_list_curr = ahp->ah_cal_list; 1018 1019 if (ahp->ah_cal_list_curr) 1020 ath9k_hw_reset_calibration(ah, ahp->ah_cal_list_curr); 1021 } 1022 1023 ichan->CalValid = 0; 1024 1025 return (B_TRUE); 1026 } 1027 1028 const struct hal_percal_data iq_cal_multi_sample = { 1029 IQ_MISMATCH_CAL, 1030 MAX_CAL_SAMPLES, 1031 PER_MIN_LOG_COUNT, 1032 ath9k_hw_iqcal_collect, 1033 ath9k_hw_iqcalibrate 1034 }; 1035 const struct hal_percal_data iq_cal_single_sample = { 1036 IQ_MISMATCH_CAL, 1037 MIN_CAL_SAMPLES, 1038 PER_MAX_LOG_COUNT, 1039 ath9k_hw_iqcal_collect, 1040 ath9k_hw_iqcalibrate 1041 }; 1042 const struct hal_percal_data adc_gain_cal_multi_sample = { 1043 ADC_GAIN_CAL, 1044 MAX_CAL_SAMPLES, 1045 PER_MIN_LOG_COUNT, 1046 ath9k_hw_adc_gaincal_collect, 1047 ath9k_hw_adc_gaincal_calibrate 1048 }; 1049 const struct hal_percal_data adc_gain_cal_single_sample = { 1050 ADC_GAIN_CAL, 1051 MIN_CAL_SAMPLES, 1052 PER_MAX_LOG_COUNT, 1053 ath9k_hw_adc_gaincal_collect, 1054 ath9k_hw_adc_gaincal_calibrate 1055 }; 1056 const struct hal_percal_data adc_dc_cal_multi_sample = { 1057 ADC_DC_CAL, 1058 MAX_CAL_SAMPLES, 1059 PER_MIN_LOG_COUNT, 1060 ath9k_hw_adc_dccal_collect, 1061 ath9k_hw_adc_dccal_calibrate 1062 }; 1063 const struct hal_percal_data adc_dc_cal_single_sample = { 1064 ADC_DC_CAL, 1065 MIN_CAL_SAMPLES, 1066 PER_MAX_LOG_COUNT, 1067 ath9k_hw_adc_dccal_collect, 1068 ath9k_hw_adc_dccal_calibrate 1069 }; 1070 const struct hal_percal_data adc_init_dc_cal = { 1071 ADC_DC_INIT_CAL, 1072 MIN_CAL_SAMPLES, 1073 INIT_LOG_COUNT, 1074 ath9k_hw_adc_dccal_collect, 1075 ath9k_hw_adc_dccal_calibrate 1076 };