1 /* 2 * Copyright (c) 2008-2009 Atheros Communications Inc. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 #include "ath9k.h" 18 19 /* We can tune this as we go by monitoring really low values */ 20 #define ATH9K_NF_TOO_LOW -60 21 22 /* AR5416 may return very high value (like -31 dBm), in those cases the nf 23 * is incorrect and we should use the static NF value. Later we can try to 24 * find out why they are reporting these values */ 25 26 static bool ath9k_hw_nf_in_range(struct ath_hw *ah, s16 nf) 27 { 28 if (nf > ATH9K_NF_TOO_LOW) { 29 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, 30 "noise floor value detected (%d) is " 31 "lower than what we think is a " 32 "reasonable value (%d)\n", 33 nf, ATH9K_NF_TOO_LOW); 34 return false; 35 } 36 return true; 37 } 38 39 static int16_t ath9k_hw_get_nf_hist_mid(int16_t *nfCalBuffer) 40 { 41 int16_t nfval; 42 int16_t sort[ATH9K_NF_CAL_HIST_MAX]; 43 int i, j; 44 45 for (i = 0; i < ATH9K_NF_CAL_HIST_MAX; i++) 46 sort[i] = nfCalBuffer[i]; 47 48 for (i = 0; i < ATH9K_NF_CAL_HIST_MAX - 1; i++) { 49 for (j = 1; j < ATH9K_NF_CAL_HIST_MAX - i; j++) { 50 if (sort[j] > sort[j - 1]) { 51 nfval = sort[j]; 52 sort[j] = sort[j - 1]; 53 sort[j - 1] = nfval; 54 } 55 } 56 } 57 nfval = sort[(ATH9K_NF_CAL_HIST_MAX - 1) >> 1]; 58 59 return nfval; 60 } 61 62 static void ath9k_hw_update_nfcal_hist_buffer(struct ath9k_nfcal_hist *h, 63 int16_t *nfarray) 64 { 65 int i; 66 67 for (i = 0; i < NUM_NF_READINGS; i++) { 68 h[i].nfCalBuffer[h[i].currIndex] = nfarray[i]; 69 70 if (++h[i].currIndex >= ATH9K_NF_CAL_HIST_MAX) 71 h[i].currIndex = 0; 72 73 if (h[i].invalidNFcount > 0) { 74 if (nfarray[i] < AR_PHY_CCA_MIN_BAD_VALUE || 75 nfarray[i] > AR_PHY_CCA_MAX_HIGH_VALUE) { 76 h[i].invalidNFcount = ATH9K_NF_CAL_HIST_MAX; 77 } else { 78 h[i].invalidNFcount--; 79 h[i].privNF = nfarray[i]; 80 } 81 } else { 82 h[i].privNF = 83 ath9k_hw_get_nf_hist_mid(h[i].nfCalBuffer); 84 } 85 } 86 return; 87 } 88 89 static void ath9k_hw_do_getnf(struct ath_hw *ah, 90 int16_t nfarray[NUM_NF_READINGS]) 91 { 92 int16_t nf; 93 94 if (AR_SREV_9280_10_OR_LATER(ah)) 95 nf = MS(REG_READ(ah, AR_PHY_CCA), AR9280_PHY_MINCCA_PWR); 96 else 97 nf = MS(REG_READ(ah, AR_PHY_CCA), AR_PHY_MINCCA_PWR); 98 99 if (nf & 0x100) 100 nf = 0 - ((nf ^ 0x1ff) + 1); 101 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, 102 "NF calibrated [ctl] [chain 0] is %d\n", nf); 103 nfarray[0] = nf; 104 105 if (!AR_SREV_9285(ah)) { 106 if (AR_SREV_9280_10_OR_LATER(ah)) 107 nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), 108 AR9280_PHY_CH1_MINCCA_PWR); 109 else 110 nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), 111 AR_PHY_CH1_MINCCA_PWR); 112 113 if (nf & 0x100) 114 nf = 0 - ((nf ^ 0x1ff) + 1); 115 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, 116 "NF calibrated [ctl] [chain 1] is %d\n", nf); 117 nfarray[1] = nf; 118 119 if (!AR_SREV_9280(ah) && !AR_SREV_9287(ah)) { 120 nf = MS(REG_READ(ah, AR_PHY_CH2_CCA), 121 AR_PHY_CH2_MINCCA_PWR); 122 if (nf & 0x100) 123 nf = 0 - ((nf ^ 0x1ff) + 1); 124 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, 125 "NF calibrated [ctl] [chain 2] is %d\n", nf); 126 nfarray[2] = nf; 127 } 128 } 129 130 if (AR_SREV_9280_10_OR_LATER(ah)) 131 nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), 132 AR9280_PHY_EXT_MINCCA_PWR); 133 else 134 nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), 135 AR_PHY_EXT_MINCCA_PWR); 136 137 if (nf & 0x100) 138 nf = 0 - ((nf ^ 0x1ff) + 1); 139 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, 140 "NF calibrated [ext] [chain 0] is %d\n", nf); 141 nfarray[3] = nf; 142 143 if (!AR_SREV_9285(ah)) { 144 if (AR_SREV_9280_10_OR_LATER(ah)) 145 nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), 146 AR9280_PHY_CH1_EXT_MINCCA_PWR); 147 else 148 nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), 149 AR_PHY_CH1_EXT_MINCCA_PWR); 150 151 if (nf & 0x100) 152 nf = 0 - ((nf ^ 0x1ff) + 1); 153 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, 154 "NF calibrated [ext] [chain 1] is %d\n", nf); 155 nfarray[4] = nf; 156 157 if (!AR_SREV_9280(ah) && !AR_SREV_9287(ah)) { 158 nf = MS(REG_READ(ah, AR_PHY_CH2_EXT_CCA), 159 AR_PHY_CH2_EXT_MINCCA_PWR); 160 if (nf & 0x100) 161 nf = 0 - ((nf ^ 0x1ff) + 1); 162 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, 163 "NF calibrated [ext] [chain 2] is %d\n", nf); 164 nfarray[5] = nf; 165 } 166 } 167 } 168 169 static bool getNoiseFloorThresh(struct ath_hw *ah, 170 enum ieee80211_band band, 171 int16_t *nft) 172 { 173 switch (band) { 174 case IEEE80211_BAND_5GHZ: 175 *nft = (int8_t)ah->eep_ops->get_eeprom(ah, EEP_NFTHRESH_5); 176 break; 177 case IEEE80211_BAND_2GHZ: 178 *nft = (int8_t)ah->eep_ops->get_eeprom(ah, EEP_NFTHRESH_2); 179 break; 180 default: 181 BUG_ON(1); 182 return false; 183 } 184 185 return true; 186 } 187 188 static void ath9k_hw_setup_calibration(struct ath_hw *ah, 189 struct ath9k_cal_list *currCal) 190 { 191 REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(0), 192 AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX, 193 currCal->calData->calCountMax); 194 195 switch (currCal->calData->calType) { 196 case IQ_MISMATCH_CAL: 197 REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ); 198 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, 199 "starting IQ Mismatch Calibration\n"); 200 break; 201 case ADC_GAIN_CAL: 202 REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_GAIN); 203 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, 204 "starting ADC Gain Calibration\n"); 205 break; 206 case ADC_DC_CAL: 207 REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_PER); 208 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, 209 "starting ADC DC Calibration\n"); 210 break; 211 case ADC_DC_INIT_CAL: 212 REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_INIT); 213 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, 214 "starting Init ADC DC Calibration\n"); 215 break; 216 } 217 218 REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0), 219 AR_PHY_TIMING_CTRL4_DO_CAL); 220 } 221 222 static void ath9k_hw_reset_calibration(struct ath_hw *ah, 223 struct ath9k_cal_list *currCal) 224 { 225 int i; 226 227 ath9k_hw_setup_calibration(ah, currCal); 228 229 currCal->calState = CAL_RUNNING; 230 231 for (i = 0; i < AR5416_MAX_CHAINS; i++) { 232 ah->meas0.sign[i] = 0; 233 ah->meas1.sign[i] = 0; 234 ah->meas2.sign[i] = 0; 235 ah->meas3.sign[i] = 0; 236 } 237 238 ah->cal_samples = 0; 239 } 240 241 static bool ath9k_hw_per_calibration(struct ath_hw *ah, 242 struct ath9k_channel *ichan, 243 u8 rxchainmask, 244 struct ath9k_cal_list *currCal) 245 { 246 bool iscaldone = false; 247 248 if (currCal->calState == CAL_RUNNING) { 249 if (!(REG_READ(ah, AR_PHY_TIMING_CTRL4(0)) & 250 AR_PHY_TIMING_CTRL4_DO_CAL)) { 251 252 currCal->calData->calCollect(ah); 253 ah->cal_samples++; 254 255 if (ah->cal_samples >= currCal->calData->calNumSamples) { 256 int i, numChains = 0; 257 for (i = 0; i < AR5416_MAX_CHAINS; i++) { 258 if (rxchainmask & (1 << i)) 259 numChains++; 260 } 261 262 currCal->calData->calPostProc(ah, numChains); 263 ichan->CalValid |= currCal->calData->calType; 264 currCal->calState = CAL_DONE; 265 iscaldone = true; 266 } else { 267 ath9k_hw_setup_calibration(ah, currCal); 268 } 269 } 270 } else if (!(ichan->CalValid & currCal->calData->calType)) { 271 ath9k_hw_reset_calibration(ah, currCal); 272 } 273 274 return iscaldone; 275 } 276 277 /* Assumes you are talking about the currently configured channel */ 278 static bool ath9k_hw_iscal_supported(struct ath_hw *ah, 279 enum ath9k_cal_types calType) 280 { 281 struct ieee80211_conf *conf = &ah->ah_sc->hw->conf; 282 283 switch (calType & ah->supp_cals) { 284 case IQ_MISMATCH_CAL: /* Both 2 GHz and 5 GHz support OFDM */ 285 return true; 286 case ADC_GAIN_CAL: 287 case ADC_DC_CAL: 288 if (!(conf->channel->band == IEEE80211_BAND_2GHZ && 289 conf_is_ht20(conf))) 290 return true; 291 break; 292 } 293 return false; 294 } 295 296 static void ath9k_hw_iqcal_collect(struct ath_hw *ah) 297 { 298 int i; 299 300 for (i = 0; i < AR5416_MAX_CHAINS; i++) { 301 ah->totalPowerMeasI[i] += 302 REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); 303 ah->totalPowerMeasQ[i] += 304 REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); 305 ah->totalIqCorrMeas[i] += 306 (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); 307 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, 308 "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n", 309 ah->cal_samples, i, ah->totalPowerMeasI[i], 310 ah->totalPowerMeasQ[i], 311 ah->totalIqCorrMeas[i]); 312 } 313 } 314 315 static void ath9k_hw_adc_gaincal_collect(struct ath_hw *ah) 316 { 317 int i; 318 319 for (i = 0; i < AR5416_MAX_CHAINS; i++) { 320 ah->totalAdcIOddPhase[i] += 321 REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); 322 ah->totalAdcIEvenPhase[i] += 323 REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); 324 ah->totalAdcQOddPhase[i] += 325 REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); 326 ah->totalAdcQEvenPhase[i] += 327 REG_READ(ah, AR_PHY_CAL_MEAS_3(i)); 328 329 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, 330 "%d: Chn %d oddi=0x%08x; eveni=0x%08x; " 331 "oddq=0x%08x; evenq=0x%08x;\n", 332 ah->cal_samples, i, 333 ah->totalAdcIOddPhase[i], 334 ah->totalAdcIEvenPhase[i], 335 ah->totalAdcQOddPhase[i], 336 ah->totalAdcQEvenPhase[i]); 337 } 338 } 339 340 static void ath9k_hw_adc_dccal_collect(struct ath_hw *ah) 341 { 342 int i; 343 344 for (i = 0; i < AR5416_MAX_CHAINS; i++) { 345 ah->totalAdcDcOffsetIOddPhase[i] += 346 (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); 347 ah->totalAdcDcOffsetIEvenPhase[i] += 348 (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); 349 ah->totalAdcDcOffsetQOddPhase[i] += 350 (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); 351 ah->totalAdcDcOffsetQEvenPhase[i] += 352 (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_3(i)); 353 354 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, 355 "%d: Chn %d oddi=0x%08x; eveni=0x%08x; " 356 "oddq=0x%08x; evenq=0x%08x;\n", 357 ah->cal_samples, i, 358 ah->totalAdcDcOffsetIOddPhase[i], 359 ah->totalAdcDcOffsetIEvenPhase[i], 360 ah->totalAdcDcOffsetQOddPhase[i], 361 ah->totalAdcDcOffsetQEvenPhase[i]); 362 } 363 } 364 365 static void ath9k_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) 366 { 367 u32 powerMeasQ, powerMeasI, iqCorrMeas; 368 u32 qCoffDenom, iCoffDenom; 369 int32_t qCoff, iCoff; 370 int iqCorrNeg, i; 371 372 for (i = 0; i < numChains; i++) { 373 powerMeasI = ah->totalPowerMeasI[i]; 374 powerMeasQ = ah->totalPowerMeasQ[i]; 375 iqCorrMeas = ah->totalIqCorrMeas[i]; 376 377 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, 378 "Starting IQ Cal and Correction for Chain %d\n", 379 i); 380 381 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, 382 "Orignal: Chn %diq_corr_meas = 0x%08x\n", 383 i, ah->totalIqCorrMeas[i]); 384 385 iqCorrNeg = 0; 386 387 if (iqCorrMeas > 0x80000000) { 388 iqCorrMeas = (0xffffffff - iqCorrMeas) + 1; 389 iqCorrNeg = 1; 390 } 391 392 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, 393 "Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI); 394 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, 395 "Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ); 396 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "iqCorrNeg is 0x%08x\n", 397 iqCorrNeg); 398 399 iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128; 400 qCoffDenom = powerMeasQ / 64; 401 402 if (powerMeasQ != 0) { 403 iCoff = iqCorrMeas / iCoffDenom; 404 qCoff = powerMeasI / qCoffDenom - 64; 405 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, 406 "Chn %d iCoff = 0x%08x\n", i, iCoff); 407 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, 408 "Chn %d qCoff = 0x%08x\n", i, qCoff); 409 410 iCoff = iCoff & 0x3f; 411 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, 412 "New: Chn %d iCoff = 0x%08x\n", i, iCoff); 413 if (iqCorrNeg == 0x0) 414 iCoff = 0x40 - iCoff; 415 416 if (qCoff > 15) 417 qCoff = 15; 418 else if (qCoff <= -16) 419 qCoff = 16; 420 421 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, 422 "Chn %d : iCoff = 0x%x qCoff = 0x%x\n", 423 i, iCoff, qCoff); 424 425 REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i), 426 AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF, 427 iCoff); 428 REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i), 429 AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF, 430 qCoff); 431 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, 432 "IQ Cal and Correction done for Chain %d\n", 433 i); 434 } 435 } 436 437 REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0), 438 AR_PHY_TIMING_CTRL4_IQCORR_ENABLE); 439 } 440 441 static void ath9k_hw_adc_gaincal_calibrate(struct ath_hw *ah, u8 numChains) 442 { 443 u32 iOddMeasOffset, iEvenMeasOffset, qOddMeasOffset, qEvenMeasOffset; 444 u32 qGainMismatch, iGainMismatch, val, i; 445 446 for (i = 0; i < numChains; i++) { 447 iOddMeasOffset = ah->totalAdcIOddPhase[i]; 448 iEvenMeasOffset = ah->totalAdcIEvenPhase[i]; 449 qOddMeasOffset = ah->totalAdcQOddPhase[i]; 450 qEvenMeasOffset = ah->totalAdcQEvenPhase[i]; 451 452 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, 453 "Starting ADC Gain Cal for Chain %d\n", i); 454 455 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, 456 "Chn %d pwr_meas_odd_i = 0x%08x\n", i, 457 iOddMeasOffset); 458 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, 459 "Chn %d pwr_meas_even_i = 0x%08x\n", i, 460 iEvenMeasOffset); 461 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, 462 "Chn %d pwr_meas_odd_q = 0x%08x\n", i, 463 qOddMeasOffset); 464 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, 465 "Chn %d pwr_meas_even_q = 0x%08x\n", i, 466 qEvenMeasOffset); 467 468 if (iOddMeasOffset != 0 && qEvenMeasOffset != 0) { 469 iGainMismatch = 470 ((iEvenMeasOffset * 32) / 471 iOddMeasOffset) & 0x3f; 472 qGainMismatch = 473 ((qOddMeasOffset * 32) / 474 qEvenMeasOffset) & 0x3f; 475 476 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, 477 "Chn %d gain_mismatch_i = 0x%08x\n", i, 478 iGainMismatch); 479 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, 480 "Chn %d gain_mismatch_q = 0x%08x\n", i, 481 qGainMismatch); 482 483 val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i)); 484 val &= 0xfffff000; 485 val |= (qGainMismatch) | (iGainMismatch << 6); 486 REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val); 487 488 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, 489 "ADC Gain Cal done for Chain %d\n", i); 490 } 491 } 492 493 REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0), 494 REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) | 495 AR_PHY_NEW_ADC_GAIN_CORR_ENABLE); 496 } 497 498 static void ath9k_hw_adc_dccal_calibrate(struct ath_hw *ah, u8 numChains) 499 { 500 u32 iOddMeasOffset, iEvenMeasOffset, val, i; 501 int32_t qOddMeasOffset, qEvenMeasOffset, qDcMismatch, iDcMismatch; 502 const struct ath9k_percal_data *calData = 503 ah->cal_list_curr->calData; 504 u32 numSamples = 505 (1 << (calData->calCountMax + 5)) * calData->calNumSamples; 506 507 for (i = 0; i < numChains; i++) { 508 iOddMeasOffset = ah->totalAdcDcOffsetIOddPhase[i]; 509 iEvenMeasOffset = ah->totalAdcDcOffsetIEvenPhase[i]; 510 qOddMeasOffset = ah->totalAdcDcOffsetQOddPhase[i]; 511 qEvenMeasOffset = ah->totalAdcDcOffsetQEvenPhase[i]; 512 513 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, 514 "Starting ADC DC Offset Cal for Chain %d\n", i); 515 516 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, 517 "Chn %d pwr_meas_odd_i = %d\n", i, 518 iOddMeasOffset); 519 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, 520 "Chn %d pwr_meas_even_i = %d\n", i, 521 iEvenMeasOffset); 522 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, 523 "Chn %d pwr_meas_odd_q = %d\n", i, 524 qOddMeasOffset); 525 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, 526 "Chn %d pwr_meas_even_q = %d\n", i, 527 qEvenMeasOffset); 528 529 iDcMismatch = (((iEvenMeasOffset - iOddMeasOffset) * 2) / 530 numSamples) & 0x1ff; 531 qDcMismatch = (((qOddMeasOffset - qEvenMeasOffset) * 2) / 532 numSamples) & 0x1ff; 533 534 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, 535 "Chn %d dc_offset_mismatch_i = 0x%08x\n", i, 536 iDcMismatch); 537 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, 538 "Chn %d dc_offset_mismatch_q = 0x%08x\n", i, 539 qDcMismatch); 540 541 val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i)); 542 val &= 0xc0000fff; 543 val |= (qDcMismatch << 12) | (iDcMismatch << 21); 544 REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val); 545 546 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, 547 "ADC DC Offset Cal done for Chain %d\n", i); 548 } 549 550 REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0), 551 REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) | 552 AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE); 553 } 554 555 /* This is done for the currently configured channel */ 556 bool ath9k_hw_reset_calvalid(struct ath_hw *ah) 557 { 558 struct ieee80211_conf *conf = &ah->ah_sc->hw->conf; 559 struct ath9k_cal_list *currCal = ah->cal_list_curr; 560 561 if (!ah->curchan) 562 return true; 563 564 if (!AR_SREV_9100(ah) && !AR_SREV_9160_10_OR_LATER(ah)) 565 return true; 566 567 if (currCal == NULL) 568 return true; 569 570 if (currCal->calState != CAL_DONE) { 571 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, 572 "Calibration state incorrect, %d\n", 573 currCal->calState); 574 return true; 575 } 576 577 if (!ath9k_hw_iscal_supported(ah, currCal->calData->calType)) 578 return true; 579 580 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, 581 "Resetting Cal %d state for channel %u\n", 582 currCal->calData->calType, conf->channel->center_freq); 583 584 ah->curchan->CalValid &= ~currCal->calData->calType; 585 currCal->calState = CAL_WAITING; 586 587 return false; 588 } 589 590 void ath9k_hw_start_nfcal(struct ath_hw *ah) 591 { 592 REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, 593 AR_PHY_AGC_CONTROL_ENABLE_NF); 594 REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, 595 AR_PHY_AGC_CONTROL_NO_UPDATE_NF); 596 REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); 597 } 598 599 void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) 600 { 601 struct ath9k_nfcal_hist *h; 602 int i, j; 603 int32_t val; 604 const u32 ar5416_cca_regs[6] = { 605 AR_PHY_CCA, 606 AR_PHY_CH1_CCA, 607 AR_PHY_CH2_CCA, 608 AR_PHY_EXT_CCA, 609 AR_PHY_CH1_EXT_CCA, 610 AR_PHY_CH2_EXT_CCA 611 }; 612 u8 chainmask; 613 614 if (AR_SREV_9285(ah)) 615 chainmask = 0x9; 616 else if (AR_SREV_9280(ah) || AR_SREV_9287(ah)) 617 chainmask = 0x1B; 618 else 619 chainmask = 0x3F; 620 621 h = ah->nfCalHist; 622 623 for (i = 0; i < NUM_NF_READINGS; i++) { 624 if (chainmask & (1 << i)) { 625 val = REG_READ(ah, ar5416_cca_regs[i]); 626 val &= 0xFFFFFE00; 627 val |= (((u32) (h[i].privNF) << 1) & 0x1ff); 628 REG_WRITE(ah, ar5416_cca_regs[i], val); 629 } 630 } 631 632 REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, 633 AR_PHY_AGC_CONTROL_ENABLE_NF); 634 REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, 635 AR_PHY_AGC_CONTROL_NO_UPDATE_NF); 636 REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); 637 638 for (j = 0; j < 1000; j++) { 639 if ((REG_READ(ah, AR_PHY_AGC_CONTROL) & 640 AR_PHY_AGC_CONTROL_NF) == 0) 641 break; 642 udelay(10); 643 } 644 645 for (i = 0; i < NUM_NF_READINGS; i++) { 646 if (chainmask & (1 << i)) { 647 val = REG_READ(ah, ar5416_cca_regs[i]); 648 val &= 0xFFFFFE00; 649 val |= (((u32) (-50) << 1) & 0x1ff); 650 REG_WRITE(ah, ar5416_cca_regs[i], val); 651 } 652 } 653 } 654 655 int16_t ath9k_hw_getnf(struct ath_hw *ah, 656 struct ath9k_channel *chan) 657 { 658 int16_t nf, nfThresh; 659 int16_t nfarray[NUM_NF_READINGS] = { 0 }; 660 struct ath9k_nfcal_hist *h; 661 struct ieee80211_channel *c = chan->chan; 662 663 chan->channelFlags &= (~CHANNEL_CW_INT); 664 if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) { 665 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, 666 "NF did not complete in calibration window\n"); 667 nf = 0; 668 chan->rawNoiseFloor = nf; 669 return chan->rawNoiseFloor; 670 } else { 671 ath9k_hw_do_getnf(ah, nfarray); 672 nf = nfarray[0]; 673 if (getNoiseFloorThresh(ah, c->band, &nfThresh) 674 && nf > nfThresh) { 675 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, 676 "noise floor failed detected; " 677 "detected %d, threshold %d\n", 678 nf, nfThresh); 679 chan->channelFlags |= CHANNEL_CW_INT; 680 } 681 } 682 683 h = ah->nfCalHist; 684 685 ath9k_hw_update_nfcal_hist_buffer(h, nfarray); 686 chan->rawNoiseFloor = h[0].privNF; 687 688 return chan->rawNoiseFloor; 689 } 690 691 void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah) 692 { 693 int i, j; 694 s16 noise_floor; 695 696 if (AR_SREV_9280(ah)) 697 noise_floor = AR_PHY_CCA_MAX_AR9280_GOOD_VALUE; 698 else if (AR_SREV_9285(ah)) 699 noise_floor = AR_PHY_CCA_MAX_AR9285_GOOD_VALUE; 700 else 701 noise_floor = AR_PHY_CCA_MAX_AR5416_GOOD_VALUE; 702 703 for (i = 0; i < NUM_NF_READINGS; i++) { 704 ah->nfCalHist[i].currIndex = 0; 705 ah->nfCalHist[i].privNF = noise_floor; 706 ah->nfCalHist[i].invalidNFcount = 707 AR_PHY_CCA_FILTERWINDOW_LENGTH; 708 for (j = 0; j < ATH9K_NF_CAL_HIST_MAX; j++) { 709 ah->nfCalHist[i].nfCalBuffer[j] = noise_floor; 710 } 711 } 712 } 713 714 s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan) 715 { 716 s16 nf; 717 718 if (chan->rawNoiseFloor == 0) 719 nf = -96; 720 else 721 nf = chan->rawNoiseFloor; 722 723 if (!ath9k_hw_nf_in_range(ah, nf)) 724 nf = ATH_DEFAULT_NOISE_FLOOR; 725 726 return nf; 727 } 728 729 static void ath9k_olc_temp_compensation(struct ath_hw *ah) 730 { 731 u32 rddata, i; 732 int delta, currPDADC, regval, slope; 733 734 rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4); 735 currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT); 736 737 738 if (OLC_FOR_AR9287_10_LATER) { 739 if (ah->initPDADC == 0 || currPDADC == 0) { 740 return; 741 } else { 742 slope = ah->eep_ops->get_eeprom(ah, EEP_TEMPSENSE_SLOPE); 743 if (slope == 0) 744 delta = 0; 745 else 746 delta = ((currPDADC - ah->initPDADC)*4) / slope; 747 REG_RMW_FIELD(ah, AR_PHY_CH0_TX_PWRCTRL11, 748 AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta); 749 REG_RMW_FIELD(ah, AR_PHY_CH1_TX_PWRCTRL11, 750 AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta); 751 } 752 } else { 753 if (ah->eep_ops->get_eeprom(ah, EEP_DAC_HPWR_5G)) 754 delta = (currPDADC - ah->initPDADC + 4) / 8; 755 else 756 delta = (currPDADC - ah->initPDADC + 5) / 10; 757 758 if (delta != ah->PDADCdelta) { 759 ah->PDADCdelta = delta; 760 for (i = 1; i < AR9280_TX_GAIN_TABLE_SIZE; i++) { 761 regval = ah->originalGain[i] - delta; 762 if (regval < 0) 763 regval = 0; 764 765 REG_RMW_FIELD(ah, AR_PHY_TX_GAIN_TBL1 + i * 4, 766 AR_PHY_TX_GAIN, regval); 767 } 768 } 769 } 770 } 771 772 static void ath9k_hw_9271_pa_cal(struct ath_hw *ah) 773 { 774 u32 regVal; 775 unsigned int i; 776 u32 regList [][2] = { 777 { 0x786c, 0 }, 778 { 0x7854, 0 }, 779 { 0x7820, 0 }, 780 { 0x7824, 0 }, 781 { 0x7868, 0 }, 782 { 0x783c, 0 }, 783 { 0x7838, 0 } , 784 { 0x7828, 0 } , 785 }; 786 787 for (i = 0; i < ARRAY_SIZE(regList); i++) 788 regList[i][1] = REG_READ(ah, regList[i][0]); 789 790 regVal = REG_READ(ah, 0x7834); 791 regVal &= (~(0x1)); 792 REG_WRITE(ah, 0x7834, regVal); 793 regVal = REG_READ(ah, 0x9808); 794 regVal |= (0x1 << 27); 795 REG_WRITE(ah, 0x9808, regVal); 796 797 /* 786c,b23,1, pwddac=1 */ 798 REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1); 799 /* 7854, b5,1, pdrxtxbb=1 */ 800 REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1); 801 /* 7854, b7,1, pdv2i=1 */ 802 REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1); 803 /* 7854, b8,1, pddacinterface=1 */ 804 REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1); 805 /* 7824,b12,0, offcal=0 */ 806 REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0); 807 /* 7838, b1,0, pwddb=0 */ 808 REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0); 809 /* 7820,b11,0, enpacal=0 */ 810 REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0); 811 /* 7820,b25,1, pdpadrv1=0 */ 812 REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 0); 813 /* 7820,b24,0, pdpadrv2=0 */ 814 REG_RMW_FIELD(ah, AR9285_AN_RF2G1,AR9285_AN_RF2G1_PDPADRV2,0); 815 /* 7820,b23,0, pdpaout=0 */ 816 REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0); 817 /* 783c,b14-16,7, padrvgn2tab_0=7 */ 818 REG_RMW_FIELD(ah, AR9285_AN_RF2G8,AR9285_AN_RF2G8_PADRVGN2TAB0, 7); 819 /* 820 * 7838,b29-31,0, padrvgn1tab_0=0 821 * does not matter since we turn it off 822 */ 823 REG_RMW_FIELD(ah, AR9285_AN_RF2G7,AR9285_AN_RF2G7_PADRVGN2TAB0, 0); 824 825 REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9271_AN_RF2G3_CCOMP, 0xfff); 826 827 /* Set: 828 * localmode=1,bmode=1,bmoderxtx=1,synthon=1, 829 * txon=1,paon=1,oscon=1,synthon_force=1 830 */ 831 REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0); 832 udelay(30); 833 REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9271_AN_RF2G6_OFFS, 0); 834 835 /* find off_6_1; */ 836 for (i = 6; i >= 0; i--) { 837 regVal = REG_READ(ah, 0x7834); 838 regVal |= (1 << (20 + i)); 839 REG_WRITE(ah, 0x7834, regVal); 840 udelay(1); 841 //regVal = REG_READ(ah, 0x7834); 842 regVal &= (~(0x1 << (20 + i))); 843 regVal |= (MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9) 844 << (20 + i)); 845 REG_WRITE(ah, 0x7834, regVal); 846 } 847 848 /* Empirical offset correction */ 849 #if 0 850 REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9271_AN_RF2G6_OFFS, 0x20); 851 #endif 852 853 regVal = REG_READ(ah, 0x7834); 854 regVal |= 0x1; 855 REG_WRITE(ah, 0x7834, regVal); 856 regVal = REG_READ(ah, 0x9808); 857 regVal &= (~(0x1 << 27)); 858 REG_WRITE(ah, 0x9808, regVal); 859 860 for (i = 0; i < ARRAY_SIZE(regList); i++) 861 REG_WRITE(ah, regList[i][0], regList[i][1]); 862 } 863 864 static inline void ath9k_hw_9285_pa_cal(struct ath_hw *ah, bool is_reset) 865 { 866 867 u32 regVal; 868 int i, offset, offs_6_1, offs_0; 869 u32 ccomp_org, reg_field; 870 u32 regList[][2] = { 871 { 0x786c, 0 }, 872 { 0x7854, 0 }, 873 { 0x7820, 0 }, 874 { 0x7824, 0 }, 875 { 0x7868, 0 }, 876 { 0x783c, 0 }, 877 { 0x7838, 0 }, 878 }; 879 880 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "Running PA Calibration\n"); 881 882 /* PA CAL is not needed for high power solution */ 883 if (ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE) == 884 AR5416_EEP_TXGAIN_HIGH_POWER) 885 return; 886 887 if (AR_SREV_9285_11(ah)) { 888 REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14)); 889 udelay(10); 890 } 891 892 for (i = 0; i < ARRAY_SIZE(regList); i++) 893 regList[i][1] = REG_READ(ah, regList[i][0]); 894 895 regVal = REG_READ(ah, 0x7834); 896 regVal &= (~(0x1)); 897 REG_WRITE(ah, 0x7834, regVal); 898 regVal = REG_READ(ah, 0x9808); 899 regVal |= (0x1 << 27); 900 REG_WRITE(ah, 0x9808, regVal); 901 902 REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1); 903 REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1); 904 REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1); 905 REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1); 906 REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0); 907 REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0); 908 REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0); 909 REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 0); 910 REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2, 0); 911 REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0); 912 REG_RMW_FIELD(ah, AR9285_AN_RF2G8, AR9285_AN_RF2G8_PADRVGN2TAB0, 7); 913 REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PADRVGN2TAB0, 0); 914 ccomp_org = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_CCOMP); 915 REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, 0xf); 916 917 REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0); 918 udelay(30); 919 REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, 0); 920 REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 0); 921 922 for (i = 6; i > 0; i--) { 923 regVal = REG_READ(ah, 0x7834); 924 regVal |= (1 << (19 + i)); 925 REG_WRITE(ah, 0x7834, regVal); 926 udelay(1); 927 regVal &= (~(0x1 << (19 + i))); 928 reg_field = MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9); 929 regVal |= (reg_field << (19 + i)); 930 REG_WRITE(ah, 0x7834, regVal); 931 } 932 933 REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 1); 934 udelay(1); 935 reg_field = MS(REG_READ(ah, AR9285_AN_RF2G9), AR9285_AN_RXTXBB1_SPARE9); 936 REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, reg_field); 937 offs_6_1 = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_OFFS); 938 offs_0 = MS(REG_READ(ah, AR9285_AN_RF2G3), AR9285_AN_RF2G3_PDVCCOMP); 939 940 offset = (offs_6_1<<1) | offs_0; 941 offset = offset - 0; 942 offs_6_1 = offset>>1; 943 offs_0 = offset & 1; 944 945 if ((!is_reset) && (ah->pacal_info.prev_offset == offset)) { 946 if (ah->pacal_info.max_skipcount < MAX_PACAL_SKIPCOUNT) 947 ah->pacal_info.max_skipcount = 948 2 * ah->pacal_info.max_skipcount; 949 ah->pacal_info.skipcount = ah->pacal_info.max_skipcount; 950 } else { 951 ah->pacal_info.max_skipcount = 1; 952 ah->pacal_info.skipcount = 0; 953 ah->pacal_info.prev_offset = offset; 954 } 955 956 REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, offs_6_1); 957 REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, offs_0); 958 959 regVal = REG_READ(ah, 0x7834); 960 regVal |= 0x1; 961 REG_WRITE(ah, 0x7834, regVal); 962 regVal = REG_READ(ah, 0x9808); 963 regVal &= (~(0x1 << 27)); 964 REG_WRITE(ah, 0x9808, regVal); 965 966 for (i = 0; i < ARRAY_SIZE(regList); i++) 967 REG_WRITE(ah, regList[i][0], regList[i][1]); 968 969 REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, ccomp_org); 970 971 if (AR_SREV_9285_11(ah)) 972 REG_WRITE(ah, AR9285_AN_TOP4, AR9285_AN_TOP4_DEFAULT); 973 974 } 975 976 bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, 977 u8 rxchainmask, bool longcal) 978 { 979 bool iscaldone = true; 980 struct ath9k_cal_list *currCal = ah->cal_list_curr; 981 982 if (currCal && 983 (currCal->calState == CAL_RUNNING || 984 currCal->calState == CAL_WAITING)) { 985 iscaldone = ath9k_hw_per_calibration(ah, chan, 986 rxchainmask, currCal); 987 if (iscaldone) { 988 ah->cal_list_curr = currCal = currCal->calNext; 989 990 if (currCal->calState == CAL_WAITING) { 991 iscaldone = false; 992 ath9k_hw_reset_calibration(ah, currCal); 993 } 994 } 995 } 996 997 /* Do NF cal only at longer intervals */ 998 if (longcal) { 999 /* Do periodic PAOffset Cal */ 1000 if (AR_SREV_9271(ah)) 1001 ath9k_hw_9271_pa_cal(ah); 1002 else if (AR_SREV_9285_11_OR_LATER(ah)) { 1003 if (!ah->pacal_info.skipcount) 1004 ath9k_hw_9285_pa_cal(ah, false); 1005 else 1006 ah->pacal_info.skipcount--; 1007 } 1008 1009 if (OLC_FOR_AR9280_20_LATER || OLC_FOR_AR9287_10_LATER) 1010 ath9k_olc_temp_compensation(ah); 1011 1012 /* Get the value from the previous NF cal and update history buffer */ 1013 ath9k_hw_getnf(ah, chan); 1014 1015 /* 1016 * Load the NF from history buffer of the current channel. 1017 * NF is slow time-variant, so it is OK to use a historical value. 1018 */ 1019 ath9k_hw_loadnf(ah, ah->curchan); 1020 1021 ath9k_hw_start_nfcal(ah); 1022 } 1023 1024 return iscaldone; 1025 } 1026 1027 static bool ar9285_clc(struct ath_hw *ah, struct ath9k_channel *chan) 1028 { 1029 REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); 1030 if (IS_CHAN_HT20(chan)) { 1031 REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE); 1032 REG_SET_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN); 1033 REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, 1034 AR_PHY_AGC_CONTROL_FLTR_CAL); 1035 REG_CLR_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE); 1036 REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL); 1037 if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, 1038 AR_PHY_AGC_CONTROL_CAL, 0, AH_WAIT_TIMEOUT)) { 1039 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "offset " 1040 "calibration failed to complete in " 1041 "1ms; noisy ??\n"); 1042 return false; 1043 } 1044 REG_CLR_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN); 1045 REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE); 1046 REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); 1047 } 1048 REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); 1049 REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); 1050 REG_SET_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE); 1051 REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL); 1052 if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 1053 0, AH_WAIT_TIMEOUT)) { 1054 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "offset calibration " 1055 "failed to complete in 1ms; noisy ??\n"); 1056 return false; 1057 } 1058 1059 REG_SET_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); 1060 REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); 1061 REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); 1062 1063 return true; 1064 } 1065 1066 bool ath9k_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) 1067 { 1068 if (AR_SREV_9285_12_OR_LATER(ah)) { 1069 if (!ar9285_clc(ah, chan)) 1070 return false; 1071 } else { 1072 if (AR_SREV_9280_10_OR_LATER(ah)) { 1073 if (!AR_SREV_9287_10_OR_LATER(ah)) 1074 REG_CLR_BIT(ah, AR_PHY_ADC_CTL, 1075 AR_PHY_ADC_CTL_OFF_PWDADC); 1076 REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, 1077 AR_PHY_AGC_CONTROL_FLTR_CAL); 1078 } 1079 1080 /* Calibrate the AGC */ 1081 REG_WRITE(ah, AR_PHY_AGC_CONTROL, 1082 REG_READ(ah, AR_PHY_AGC_CONTROL) | 1083 AR_PHY_AGC_CONTROL_CAL); 1084 1085 /* Poll for offset calibration complete */ 1086 if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 1087 0, AH_WAIT_TIMEOUT)) { 1088 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, 1089 "offset calibration failed to complete in 1ms; " 1090 "noisy environment?\n"); 1091 return false; 1092 } 1093 1094 if (AR_SREV_9280_10_OR_LATER(ah)) { 1095 if (!AR_SREV_9287_10_OR_LATER(ah)) 1096 REG_SET_BIT(ah, AR_PHY_ADC_CTL, 1097 AR_PHY_ADC_CTL_OFF_PWDADC); 1098 REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, 1099 AR_PHY_AGC_CONTROL_FLTR_CAL); 1100 } 1101 } 1102 1103 /* Do PA Calibration */ 1104 if (AR_SREV_9285_11_OR_LATER(ah)) 1105 ath9k_hw_9285_pa_cal(ah, true); 1106 1107 /* Do NF Calibration after DC offset and other calibrations */ 1108 REG_WRITE(ah, AR_PHY_AGC_CONTROL, 1109 REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_NF); 1110 1111 ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL; 1112 1113 /* Enable IQ, ADC Gain and ADC DC offset CALs */ 1114 if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) { 1115 if (ath9k_hw_iscal_supported(ah, ADC_GAIN_CAL)) { 1116 INIT_CAL(&ah->adcgain_caldata); 1117 INSERT_CAL(ah, &ah->adcgain_caldata); 1118 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, 1119 "enabling ADC Gain Calibration.\n"); 1120 } 1121 if (ath9k_hw_iscal_supported(ah, ADC_DC_CAL)) { 1122 INIT_CAL(&ah->adcdc_caldata); 1123 INSERT_CAL(ah, &ah->adcdc_caldata); 1124 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, 1125 "enabling ADC DC Calibration.\n"); 1126 } 1127 if (ath9k_hw_iscal_supported(ah, IQ_MISMATCH_CAL)) { 1128 INIT_CAL(&ah->iq_caldata); 1129 INSERT_CAL(ah, &ah->iq_caldata); 1130 DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, 1131 "enabling IQ Calibration.\n"); 1132 } 1133 1134 ah->cal_list_curr = ah->cal_list; 1135 1136 if (ah->cal_list_curr) 1137 ath9k_hw_reset_calibration(ah, ah->cal_list_curr); 1138 } 1139 1140 chan->CalValid = 0; 1141 1142 return true; 1143 } 1144 1145 const struct ath9k_percal_data iq_cal_multi_sample = { 1146 IQ_MISMATCH_CAL, 1147 MAX_CAL_SAMPLES, 1148 PER_MIN_LOG_COUNT, 1149 ath9k_hw_iqcal_collect, 1150 ath9k_hw_iqcalibrate 1151 }; 1152 const struct ath9k_percal_data iq_cal_single_sample = { 1153 IQ_MISMATCH_CAL, 1154 MIN_CAL_SAMPLES, 1155 PER_MAX_LOG_COUNT, 1156 ath9k_hw_iqcal_collect, 1157 ath9k_hw_iqcalibrate 1158 }; 1159 const struct ath9k_percal_data adc_gain_cal_multi_sample = { 1160 ADC_GAIN_CAL, 1161 MAX_CAL_SAMPLES, 1162 PER_MIN_LOG_COUNT, 1163 ath9k_hw_adc_gaincal_collect, 1164 ath9k_hw_adc_gaincal_calibrate 1165 }; 1166 const struct ath9k_percal_data adc_gain_cal_single_sample = { 1167 ADC_GAIN_CAL, 1168 MIN_CAL_SAMPLES, 1169 PER_MAX_LOG_COUNT, 1170 ath9k_hw_adc_gaincal_collect, 1171 ath9k_hw_adc_gaincal_calibrate 1172 }; 1173 const struct ath9k_percal_data adc_dc_cal_multi_sample = { 1174 ADC_DC_CAL, 1175 MAX_CAL_SAMPLES, 1176 PER_MIN_LOG_COUNT, 1177 ath9k_hw_adc_dccal_collect, 1178 ath9k_hw_adc_dccal_calibrate 1179 }; 1180 const struct ath9k_percal_data adc_dc_cal_single_sample = { 1181 ADC_DC_CAL, 1182 MIN_CAL_SAMPLES, 1183 PER_MAX_LOG_COUNT, 1184 ath9k_hw_adc_dccal_collect, 1185 ath9k_hw_adc_dccal_calibrate 1186 }; 1187 const struct ath9k_percal_data adc_init_dc_cal = { 1188 ADC_DC_INIT_CAL, 1189 MIN_CAL_SAMPLES, 1190 INIT_LOG_COUNT, 1191 ath9k_hw_adc_dccal_collect, 1192 ath9k_hw_adc_dccal_calibrate 1193 }; 1194