diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/calib.c')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/calib.c | 1024 |
1 files changed, 10 insertions, 1014 deletions
diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index 238a5744d8e9..07b8fa6fb62f 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c | |||
@@ -15,6 +15,9 @@ | |||
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include "hw.h" | 17 | #include "hw.h" |
18 | #include "hw-ops.h" | ||
19 | |||
20 | /* Common calibration code */ | ||
18 | 21 | ||
19 | /* We can tune this as we go by monitoring really low values */ | 22 | /* We can tune this as we go by monitoring really low values */ |
20 | #define ATH9K_NF_TOO_LOW -60 | 23 | #define ATH9K_NF_TOO_LOW -60 |
@@ -83,93 +86,11 @@ static void ath9k_hw_update_nfcal_hist_buffer(struct ath9k_nfcal_hist *h, | |||
83 | ath9k_hw_get_nf_hist_mid(h[i].nfCalBuffer); | 86 | ath9k_hw_get_nf_hist_mid(h[i].nfCalBuffer); |
84 | } | 87 | } |
85 | } | 88 | } |
86 | return; | ||
87 | } | 89 | } |
88 | 90 | ||
89 | static void ath9k_hw_do_getnf(struct ath_hw *ah, | 91 | static bool ath9k_hw_get_nf_thresh(struct ath_hw *ah, |
90 | int16_t nfarray[NUM_NF_READINGS]) | 92 | enum ieee80211_band band, |
91 | { | 93 | int16_t *nft) |
92 | struct ath_common *common = ath9k_hw_common(ah); | ||
93 | int16_t nf; | ||
94 | |||
95 | if (AR_SREV_9280_10_OR_LATER(ah)) | ||
96 | nf = MS(REG_READ(ah, AR_PHY_CCA), AR9280_PHY_MINCCA_PWR); | ||
97 | else | ||
98 | nf = MS(REG_READ(ah, AR_PHY_CCA), AR_PHY_MINCCA_PWR); | ||
99 | |||
100 | if (nf & 0x100) | ||
101 | nf = 0 - ((nf ^ 0x1ff) + 1); | ||
102 | ath_print(common, ATH_DBG_CALIBRATE, | ||
103 | "NF calibrated [ctl] [chain 0] is %d\n", nf); | ||
104 | nfarray[0] = nf; | ||
105 | |||
106 | if (!AR_SREV_9285(ah)) { | ||
107 | if (AR_SREV_9280_10_OR_LATER(ah)) | ||
108 | nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), | ||
109 | AR9280_PHY_CH1_MINCCA_PWR); | ||
110 | else | ||
111 | nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), | ||
112 | AR_PHY_CH1_MINCCA_PWR); | ||
113 | |||
114 | if (nf & 0x100) | ||
115 | nf = 0 - ((nf ^ 0x1ff) + 1); | ||
116 | ath_print(common, ATH_DBG_CALIBRATE, | ||
117 | "NF calibrated [ctl] [chain 1] is %d\n", nf); | ||
118 | nfarray[1] = nf; | ||
119 | |||
120 | if (!AR_SREV_9280(ah) && !AR_SREV_9287(ah)) { | ||
121 | nf = MS(REG_READ(ah, AR_PHY_CH2_CCA), | ||
122 | AR_PHY_CH2_MINCCA_PWR); | ||
123 | if (nf & 0x100) | ||
124 | nf = 0 - ((nf ^ 0x1ff) + 1); | ||
125 | ath_print(common, ATH_DBG_CALIBRATE, | ||
126 | "NF calibrated [ctl] [chain 2] is %d\n", nf); | ||
127 | nfarray[2] = nf; | ||
128 | } | ||
129 | } | ||
130 | |||
131 | if (AR_SREV_9280_10_OR_LATER(ah)) | ||
132 | nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), | ||
133 | AR9280_PHY_EXT_MINCCA_PWR); | ||
134 | else | ||
135 | nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), | ||
136 | AR_PHY_EXT_MINCCA_PWR); | ||
137 | |||
138 | if (nf & 0x100) | ||
139 | nf = 0 - ((nf ^ 0x1ff) + 1); | ||
140 | ath_print(common, ATH_DBG_CALIBRATE, | ||
141 | "NF calibrated [ext] [chain 0] is %d\n", nf); | ||
142 | nfarray[3] = nf; | ||
143 | |||
144 | if (!AR_SREV_9285(ah)) { | ||
145 | if (AR_SREV_9280_10_OR_LATER(ah)) | ||
146 | nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), | ||
147 | AR9280_PHY_CH1_EXT_MINCCA_PWR); | ||
148 | else | ||
149 | nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), | ||
150 | AR_PHY_CH1_EXT_MINCCA_PWR); | ||
151 | |||
152 | if (nf & 0x100) | ||
153 | nf = 0 - ((nf ^ 0x1ff) + 1); | ||
154 | ath_print(common, ATH_DBG_CALIBRATE, | ||
155 | "NF calibrated [ext] [chain 1] is %d\n", nf); | ||
156 | nfarray[4] = nf; | ||
157 | |||
158 | if (!AR_SREV_9280(ah) && !AR_SREV_9287(ah)) { | ||
159 | nf = MS(REG_READ(ah, AR_PHY_CH2_EXT_CCA), | ||
160 | AR_PHY_CH2_EXT_MINCCA_PWR); | ||
161 | if (nf & 0x100) | ||
162 | nf = 0 - ((nf ^ 0x1ff) + 1); | ||
163 | ath_print(common, ATH_DBG_CALIBRATE, | ||
164 | "NF calibrated [ext] [chain 2] is %d\n", nf); | ||
165 | nfarray[5] = nf; | ||
166 | } | ||
167 | } | ||
168 | } | ||
169 | |||
170 | static bool getNoiseFloorThresh(struct ath_hw *ah, | ||
171 | enum ieee80211_band band, | ||
172 | int16_t *nft) | ||
173 | { | 94 | { |
174 | switch (band) { | 95 | switch (band) { |
175 | case IEEE80211_BAND_5GHZ: | 96 | case IEEE80211_BAND_5GHZ: |
@@ -186,44 +107,8 @@ static bool getNoiseFloorThresh(struct ath_hw *ah, | |||
186 | return true; | 107 | return true; |
187 | } | 108 | } |
188 | 109 | ||
189 | static void ath9k_hw_setup_calibration(struct ath_hw *ah, | 110 | void ath9k_hw_reset_calibration(struct ath_hw *ah, |
190 | struct ath9k_cal_list *currCal) | 111 | struct ath9k_cal_list *currCal) |
191 | { | ||
192 | struct ath_common *common = ath9k_hw_common(ah); | ||
193 | |||
194 | REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(0), | ||
195 | AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX, | ||
196 | currCal->calData->calCountMax); | ||
197 | |||
198 | switch (currCal->calData->calType) { | ||
199 | case IQ_MISMATCH_CAL: | ||
200 | REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ); | ||
201 | ath_print(common, ATH_DBG_CALIBRATE, | ||
202 | "starting IQ Mismatch Calibration\n"); | ||
203 | break; | ||
204 | case ADC_GAIN_CAL: | ||
205 | REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_GAIN); | ||
206 | ath_print(common, ATH_DBG_CALIBRATE, | ||
207 | "starting ADC Gain Calibration\n"); | ||
208 | break; | ||
209 | case ADC_DC_CAL: | ||
210 | REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_PER); | ||
211 | ath_print(common, ATH_DBG_CALIBRATE, | ||
212 | "starting ADC DC Calibration\n"); | ||
213 | break; | ||
214 | case ADC_DC_INIT_CAL: | ||
215 | REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_INIT); | ||
216 | ath_print(common, ATH_DBG_CALIBRATE, | ||
217 | "starting Init ADC DC Calibration\n"); | ||
218 | break; | ||
219 | } | ||
220 | |||
221 | REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0), | ||
222 | AR_PHY_TIMING_CTRL4_DO_CAL); | ||
223 | } | ||
224 | |||
225 | static void ath9k_hw_reset_calibration(struct ath_hw *ah, | ||
226 | struct ath9k_cal_list *currCal) | ||
227 | { | 112 | { |
228 | int i; | 113 | int i; |
229 | 114 | ||
@@ -241,324 +126,6 @@ static void ath9k_hw_reset_calibration(struct ath_hw *ah, | |||
241 | ah->cal_samples = 0; | 126 | ah->cal_samples = 0; |
242 | } | 127 | } |
243 | 128 | ||
244 | static bool ath9k_hw_per_calibration(struct ath_hw *ah, | ||
245 | struct ath9k_channel *ichan, | ||
246 | u8 rxchainmask, | ||
247 | struct ath9k_cal_list *currCal) | ||
248 | { | ||
249 | bool iscaldone = false; | ||
250 | |||
251 | if (currCal->calState == CAL_RUNNING) { | ||
252 | if (!(REG_READ(ah, AR_PHY_TIMING_CTRL4(0)) & | ||
253 | AR_PHY_TIMING_CTRL4_DO_CAL)) { | ||
254 | |||
255 | currCal->calData->calCollect(ah); | ||
256 | ah->cal_samples++; | ||
257 | |||
258 | if (ah->cal_samples >= currCal->calData->calNumSamples) { | ||
259 | int i, numChains = 0; | ||
260 | for (i = 0; i < AR5416_MAX_CHAINS; i++) { | ||
261 | if (rxchainmask & (1 << i)) | ||
262 | numChains++; | ||
263 | } | ||
264 | |||
265 | currCal->calData->calPostProc(ah, numChains); | ||
266 | ichan->CalValid |= currCal->calData->calType; | ||
267 | currCal->calState = CAL_DONE; | ||
268 | iscaldone = true; | ||
269 | } else { | ||
270 | ath9k_hw_setup_calibration(ah, currCal); | ||
271 | } | ||
272 | } | ||
273 | } else if (!(ichan->CalValid & currCal->calData->calType)) { | ||
274 | ath9k_hw_reset_calibration(ah, currCal); | ||
275 | } | ||
276 | |||
277 | return iscaldone; | ||
278 | } | ||
279 | |||
280 | /* Assumes you are talking about the currently configured channel */ | ||
281 | static bool ath9k_hw_iscal_supported(struct ath_hw *ah, | ||
282 | enum ath9k_cal_types calType) | ||
283 | { | ||
284 | struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; | ||
285 | |||
286 | switch (calType & ah->supp_cals) { | ||
287 | case IQ_MISMATCH_CAL: /* Both 2 GHz and 5 GHz support OFDM */ | ||
288 | return true; | ||
289 | case ADC_GAIN_CAL: | ||
290 | case ADC_DC_CAL: | ||
291 | if (!(conf->channel->band == IEEE80211_BAND_2GHZ && | ||
292 | conf_is_ht20(conf))) | ||
293 | return true; | ||
294 | break; | ||
295 | } | ||
296 | return false; | ||
297 | } | ||
298 | |||
299 | static void ath9k_hw_iqcal_collect(struct ath_hw *ah) | ||
300 | { | ||
301 | int i; | ||
302 | |||
303 | for (i = 0; i < AR5416_MAX_CHAINS; i++) { | ||
304 | ah->totalPowerMeasI[i] += | ||
305 | REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); | ||
306 | ah->totalPowerMeasQ[i] += | ||
307 | REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); | ||
308 | ah->totalIqCorrMeas[i] += | ||
309 | (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); | ||
310 | ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, | ||
311 | "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n", | ||
312 | ah->cal_samples, i, ah->totalPowerMeasI[i], | ||
313 | ah->totalPowerMeasQ[i], | ||
314 | ah->totalIqCorrMeas[i]); | ||
315 | } | ||
316 | } | ||
317 | |||
318 | static void ath9k_hw_adc_gaincal_collect(struct ath_hw *ah) | ||
319 | { | ||
320 | int i; | ||
321 | |||
322 | for (i = 0; i < AR5416_MAX_CHAINS; i++) { | ||
323 | ah->totalAdcIOddPhase[i] += | ||
324 | REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); | ||
325 | ah->totalAdcIEvenPhase[i] += | ||
326 | REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); | ||
327 | ah->totalAdcQOddPhase[i] += | ||
328 | REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); | ||
329 | ah->totalAdcQEvenPhase[i] += | ||
330 | REG_READ(ah, AR_PHY_CAL_MEAS_3(i)); | ||
331 | |||
332 | ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, | ||
333 | "%d: Chn %d oddi=0x%08x; eveni=0x%08x; " | ||
334 | "oddq=0x%08x; evenq=0x%08x;\n", | ||
335 | ah->cal_samples, i, | ||
336 | ah->totalAdcIOddPhase[i], | ||
337 | ah->totalAdcIEvenPhase[i], | ||
338 | ah->totalAdcQOddPhase[i], | ||
339 | ah->totalAdcQEvenPhase[i]); | ||
340 | } | ||
341 | } | ||
342 | |||
343 | static void ath9k_hw_adc_dccal_collect(struct ath_hw *ah) | ||
344 | { | ||
345 | int i; | ||
346 | |||
347 | for (i = 0; i < AR5416_MAX_CHAINS; i++) { | ||
348 | ah->totalAdcDcOffsetIOddPhase[i] += | ||
349 | (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); | ||
350 | ah->totalAdcDcOffsetIEvenPhase[i] += | ||
351 | (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); | ||
352 | ah->totalAdcDcOffsetQOddPhase[i] += | ||
353 | (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); | ||
354 | ah->totalAdcDcOffsetQEvenPhase[i] += | ||
355 | (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_3(i)); | ||
356 | |||
357 | ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, | ||
358 | "%d: Chn %d oddi=0x%08x; eveni=0x%08x; " | ||
359 | "oddq=0x%08x; evenq=0x%08x;\n", | ||
360 | ah->cal_samples, i, | ||
361 | ah->totalAdcDcOffsetIOddPhase[i], | ||
362 | ah->totalAdcDcOffsetIEvenPhase[i], | ||
363 | ah->totalAdcDcOffsetQOddPhase[i], | ||
364 | ah->totalAdcDcOffsetQEvenPhase[i]); | ||
365 | } | ||
366 | } | ||
367 | |||
368 | static void ath9k_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) | ||
369 | { | ||
370 | struct ath_common *common = ath9k_hw_common(ah); | ||
371 | u32 powerMeasQ, powerMeasI, iqCorrMeas; | ||
372 | u32 qCoffDenom, iCoffDenom; | ||
373 | int32_t qCoff, iCoff; | ||
374 | int iqCorrNeg, i; | ||
375 | |||
376 | for (i = 0; i < numChains; i++) { | ||
377 | powerMeasI = ah->totalPowerMeasI[i]; | ||
378 | powerMeasQ = ah->totalPowerMeasQ[i]; | ||
379 | iqCorrMeas = ah->totalIqCorrMeas[i]; | ||
380 | |||
381 | ath_print(common, ATH_DBG_CALIBRATE, | ||
382 | "Starting IQ Cal and Correction for Chain %d\n", | ||
383 | i); | ||
384 | |||
385 | ath_print(common, ATH_DBG_CALIBRATE, | ||
386 | "Orignal: Chn %diq_corr_meas = 0x%08x\n", | ||
387 | i, ah->totalIqCorrMeas[i]); | ||
388 | |||
389 | iqCorrNeg = 0; | ||
390 | |||
391 | if (iqCorrMeas > 0x80000000) { | ||
392 | iqCorrMeas = (0xffffffff - iqCorrMeas) + 1; | ||
393 | iqCorrNeg = 1; | ||
394 | } | ||
395 | |||
396 | ath_print(common, ATH_DBG_CALIBRATE, | ||
397 | "Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI); | ||
398 | ath_print(common, ATH_DBG_CALIBRATE, | ||
399 | "Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ); | ||
400 | ath_print(common, ATH_DBG_CALIBRATE, "iqCorrNeg is 0x%08x\n", | ||
401 | iqCorrNeg); | ||
402 | |||
403 | iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128; | ||
404 | qCoffDenom = powerMeasQ / 64; | ||
405 | |||
406 | if ((powerMeasQ != 0) && (iCoffDenom != 0) && | ||
407 | (qCoffDenom != 0)) { | ||
408 | iCoff = iqCorrMeas / iCoffDenom; | ||
409 | qCoff = powerMeasI / qCoffDenom - 64; | ||
410 | ath_print(common, ATH_DBG_CALIBRATE, | ||
411 | "Chn %d iCoff = 0x%08x\n", i, iCoff); | ||
412 | ath_print(common, ATH_DBG_CALIBRATE, | ||
413 | "Chn %d qCoff = 0x%08x\n", i, qCoff); | ||
414 | |||
415 | iCoff = iCoff & 0x3f; | ||
416 | ath_print(common, ATH_DBG_CALIBRATE, | ||
417 | "New: Chn %d iCoff = 0x%08x\n", i, iCoff); | ||
418 | if (iqCorrNeg == 0x0) | ||
419 | iCoff = 0x40 - iCoff; | ||
420 | |||
421 | if (qCoff > 15) | ||
422 | qCoff = 15; | ||
423 | else if (qCoff <= -16) | ||
424 | qCoff = 16; | ||
425 | |||
426 | ath_print(common, ATH_DBG_CALIBRATE, | ||
427 | "Chn %d : iCoff = 0x%x qCoff = 0x%x\n", | ||
428 | i, iCoff, qCoff); | ||
429 | |||
430 | REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i), | ||
431 | AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF, | ||
432 | iCoff); | ||
433 | REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i), | ||
434 | AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF, | ||
435 | qCoff); | ||
436 | ath_print(common, ATH_DBG_CALIBRATE, | ||
437 | "IQ Cal and Correction done for Chain %d\n", | ||
438 | i); | ||
439 | } | ||
440 | } | ||
441 | |||
442 | REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0), | ||
443 | AR_PHY_TIMING_CTRL4_IQCORR_ENABLE); | ||
444 | } | ||
445 | |||
446 | static void ath9k_hw_adc_gaincal_calibrate(struct ath_hw *ah, u8 numChains) | ||
447 | { | ||
448 | struct ath_common *common = ath9k_hw_common(ah); | ||
449 | u32 iOddMeasOffset, iEvenMeasOffset, qOddMeasOffset, qEvenMeasOffset; | ||
450 | u32 qGainMismatch, iGainMismatch, val, i; | ||
451 | |||
452 | for (i = 0; i < numChains; i++) { | ||
453 | iOddMeasOffset = ah->totalAdcIOddPhase[i]; | ||
454 | iEvenMeasOffset = ah->totalAdcIEvenPhase[i]; | ||
455 | qOddMeasOffset = ah->totalAdcQOddPhase[i]; | ||
456 | qEvenMeasOffset = ah->totalAdcQEvenPhase[i]; | ||
457 | |||
458 | ath_print(common, ATH_DBG_CALIBRATE, | ||
459 | "Starting ADC Gain Cal for Chain %d\n", i); | ||
460 | |||
461 | ath_print(common, ATH_DBG_CALIBRATE, | ||
462 | "Chn %d pwr_meas_odd_i = 0x%08x\n", i, | ||
463 | iOddMeasOffset); | ||
464 | ath_print(common, ATH_DBG_CALIBRATE, | ||
465 | "Chn %d pwr_meas_even_i = 0x%08x\n", i, | ||
466 | iEvenMeasOffset); | ||
467 | ath_print(common, ATH_DBG_CALIBRATE, | ||
468 | "Chn %d pwr_meas_odd_q = 0x%08x\n", i, | ||
469 | qOddMeasOffset); | ||
470 | ath_print(common, ATH_DBG_CALIBRATE, | ||
471 | "Chn %d pwr_meas_even_q = 0x%08x\n", i, | ||
472 | qEvenMeasOffset); | ||
473 | |||
474 | if (iOddMeasOffset != 0 && qEvenMeasOffset != 0) { | ||
475 | iGainMismatch = | ||
476 | ((iEvenMeasOffset * 32) / | ||
477 | iOddMeasOffset) & 0x3f; | ||
478 | qGainMismatch = | ||
479 | ((qOddMeasOffset * 32) / | ||
480 | qEvenMeasOffset) & 0x3f; | ||
481 | |||
482 | ath_print(common, ATH_DBG_CALIBRATE, | ||
483 | "Chn %d gain_mismatch_i = 0x%08x\n", i, | ||
484 | iGainMismatch); | ||
485 | ath_print(common, ATH_DBG_CALIBRATE, | ||
486 | "Chn %d gain_mismatch_q = 0x%08x\n", i, | ||
487 | qGainMismatch); | ||
488 | |||
489 | val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i)); | ||
490 | val &= 0xfffff000; | ||
491 | val |= (qGainMismatch) | (iGainMismatch << 6); | ||
492 | REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val); | ||
493 | |||
494 | ath_print(common, ATH_DBG_CALIBRATE, | ||
495 | "ADC Gain Cal done for Chain %d\n", i); | ||
496 | } | ||
497 | } | ||
498 | |||
499 | REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0), | ||
500 | REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) | | ||
501 | AR_PHY_NEW_ADC_GAIN_CORR_ENABLE); | ||
502 | } | ||
503 | |||
504 | static void ath9k_hw_adc_dccal_calibrate(struct ath_hw *ah, u8 numChains) | ||
505 | { | ||
506 | struct ath_common *common = ath9k_hw_common(ah); | ||
507 | u32 iOddMeasOffset, iEvenMeasOffset, val, i; | ||
508 | int32_t qOddMeasOffset, qEvenMeasOffset, qDcMismatch, iDcMismatch; | ||
509 | const struct ath9k_percal_data *calData = | ||
510 | ah->cal_list_curr->calData; | ||
511 | u32 numSamples = | ||
512 | (1 << (calData->calCountMax + 5)) * calData->calNumSamples; | ||
513 | |||
514 | for (i = 0; i < numChains; i++) { | ||
515 | iOddMeasOffset = ah->totalAdcDcOffsetIOddPhase[i]; | ||
516 | iEvenMeasOffset = ah->totalAdcDcOffsetIEvenPhase[i]; | ||
517 | qOddMeasOffset = ah->totalAdcDcOffsetQOddPhase[i]; | ||
518 | qEvenMeasOffset = ah->totalAdcDcOffsetQEvenPhase[i]; | ||
519 | |||
520 | ath_print(common, ATH_DBG_CALIBRATE, | ||
521 | "Starting ADC DC Offset Cal for Chain %d\n", i); | ||
522 | |||
523 | ath_print(common, ATH_DBG_CALIBRATE, | ||
524 | "Chn %d pwr_meas_odd_i = %d\n", i, | ||
525 | iOddMeasOffset); | ||
526 | ath_print(common, ATH_DBG_CALIBRATE, | ||
527 | "Chn %d pwr_meas_even_i = %d\n", i, | ||
528 | iEvenMeasOffset); | ||
529 | ath_print(common, ATH_DBG_CALIBRATE, | ||
530 | "Chn %d pwr_meas_odd_q = %d\n", i, | ||
531 | qOddMeasOffset); | ||
532 | ath_print(common, ATH_DBG_CALIBRATE, | ||
533 | "Chn %d pwr_meas_even_q = %d\n", i, | ||
534 | qEvenMeasOffset); | ||
535 | |||
536 | iDcMismatch = (((iEvenMeasOffset - iOddMeasOffset) * 2) / | ||
537 | numSamples) & 0x1ff; | ||
538 | qDcMismatch = (((qOddMeasOffset - qEvenMeasOffset) * 2) / | ||
539 | numSamples) & 0x1ff; | ||
540 | |||
541 | ath_print(common, ATH_DBG_CALIBRATE, | ||
542 | "Chn %d dc_offset_mismatch_i = 0x%08x\n", i, | ||
543 | iDcMismatch); | ||
544 | ath_print(common, ATH_DBG_CALIBRATE, | ||
545 | "Chn %d dc_offset_mismatch_q = 0x%08x\n", i, | ||
546 | qDcMismatch); | ||
547 | |||
548 | val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i)); | ||
549 | val &= 0xc0000fff; | ||
550 | val |= (qDcMismatch << 12) | (iDcMismatch << 21); | ||
551 | REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val); | ||
552 | |||
553 | ath_print(common, ATH_DBG_CALIBRATE, | ||
554 | "ADC DC Offset Cal done for Chain %d\n", i); | ||
555 | } | ||
556 | |||
557 | REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0), | ||
558 | REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) | | ||
559 | AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE); | ||
560 | } | ||
561 | |||
562 | /* This is done for the currently configured channel */ | 129 | /* This is done for the currently configured channel */ |
563 | bool ath9k_hw_reset_calvalid(struct ath_hw *ah) | 130 | bool ath9k_hw_reset_calvalid(struct ath_hw *ah) |
564 | { | 131 | { |
@@ -605,72 +172,6 @@ void ath9k_hw_start_nfcal(struct ath_hw *ah) | |||
605 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); | 172 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); |
606 | } | 173 | } |
607 | 174 | ||
608 | void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) | ||
609 | { | ||
610 | struct ath9k_nfcal_hist *h; | ||
611 | int i, j; | ||
612 | int32_t val; | ||
613 | const u32 ar5416_cca_regs[6] = { | ||
614 | AR_PHY_CCA, | ||
615 | AR_PHY_CH1_CCA, | ||
616 | AR_PHY_CH2_CCA, | ||
617 | AR_PHY_EXT_CCA, | ||
618 | AR_PHY_CH1_EXT_CCA, | ||
619 | AR_PHY_CH2_EXT_CCA | ||
620 | }; | ||
621 | u8 chainmask, rx_chain_status; | ||
622 | |||
623 | rx_chain_status = REG_READ(ah, AR_PHY_RX_CHAINMASK); | ||
624 | if (AR_SREV_9285(ah)) | ||
625 | chainmask = 0x9; | ||
626 | else if (AR_SREV_9280(ah) || AR_SREV_9287(ah)) { | ||
627 | if ((rx_chain_status & 0x2) || (rx_chain_status & 0x4)) | ||
628 | chainmask = 0x1B; | ||
629 | else | ||
630 | chainmask = 0x09; | ||
631 | } else { | ||
632 | if (rx_chain_status & 0x4) | ||
633 | chainmask = 0x3F; | ||
634 | else if (rx_chain_status & 0x2) | ||
635 | chainmask = 0x1B; | ||
636 | else | ||
637 | chainmask = 0x09; | ||
638 | } | ||
639 | |||
640 | h = ah->nfCalHist; | ||
641 | |||
642 | for (i = 0; i < NUM_NF_READINGS; i++) { | ||
643 | if (chainmask & (1 << i)) { | ||
644 | val = REG_READ(ah, ar5416_cca_regs[i]); | ||
645 | val &= 0xFFFFFE00; | ||
646 | val |= (((u32) (h[i].privNF) << 1) & 0x1ff); | ||
647 | REG_WRITE(ah, ar5416_cca_regs[i], val); | ||
648 | } | ||
649 | } | ||
650 | |||
651 | REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, | ||
652 | AR_PHY_AGC_CONTROL_ENABLE_NF); | ||
653 | REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, | ||
654 | AR_PHY_AGC_CONTROL_NO_UPDATE_NF); | ||
655 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); | ||
656 | |||
657 | for (j = 0; j < 5; j++) { | ||
658 | if ((REG_READ(ah, AR_PHY_AGC_CONTROL) & | ||
659 | AR_PHY_AGC_CONTROL_NF) == 0) | ||
660 | break; | ||
661 | udelay(50); | ||
662 | } | ||
663 | |||
664 | for (i = 0; i < NUM_NF_READINGS; i++) { | ||
665 | if (chainmask & (1 << i)) { | ||
666 | val = REG_READ(ah, ar5416_cca_regs[i]); | ||
667 | val &= 0xFFFFFE00; | ||
668 | val |= (((u32) (-50) << 1) & 0x1ff); | ||
669 | REG_WRITE(ah, ar5416_cca_regs[i], val); | ||
670 | } | ||
671 | } | ||
672 | } | ||
673 | |||
674 | int16_t ath9k_hw_getnf(struct ath_hw *ah, | 175 | int16_t ath9k_hw_getnf(struct ath_hw *ah, |
675 | struct ath9k_channel *chan) | 176 | struct ath9k_channel *chan) |
676 | { | 177 | { |
@@ -690,7 +191,7 @@ int16_t ath9k_hw_getnf(struct ath_hw *ah, | |||
690 | } else { | 191 | } else { |
691 | ath9k_hw_do_getnf(ah, nfarray); | 192 | ath9k_hw_do_getnf(ah, nfarray); |
692 | nf = nfarray[0]; | 193 | nf = nfarray[0]; |
693 | if (getNoiseFloorThresh(ah, c->band, &nfThresh) | 194 | if (ath9k_hw_get_nf_thresh(ah, c->band, &nfThresh) |
694 | && nf > nfThresh) { | 195 | && nf > nfThresh) { |
695 | ath_print(common, ATH_DBG_CALIBRATE, | 196 | ath_print(common, ATH_DBG_CALIBRATE, |
696 | "noise floor failed detected; " | 197 | "noise floor failed detected; " |
@@ -715,7 +216,7 @@ void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah) | |||
715 | 216 | ||
716 | if (AR_SREV_9280(ah)) | 217 | if (AR_SREV_9280(ah)) |
717 | noise_floor = AR_PHY_CCA_MAX_AR9280_GOOD_VALUE; | 218 | noise_floor = AR_PHY_CCA_MAX_AR9280_GOOD_VALUE; |
718 | else if (AR_SREV_9285(ah)) | 219 | else if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) |
719 | noise_floor = AR_PHY_CCA_MAX_AR9285_GOOD_VALUE; | 220 | noise_floor = AR_PHY_CCA_MAX_AR9285_GOOD_VALUE; |
720 | else if (AR_SREV_9287(ah)) | 221 | else if (AR_SREV_9287(ah)) |
721 | noise_floor = AR_PHY_CCA_MAX_AR9287_GOOD_VALUE; | 222 | noise_floor = AR_PHY_CCA_MAX_AR9287_GOOD_VALUE; |
@@ -748,508 +249,3 @@ s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan) | |||
748 | return nf; | 249 | return nf; |
749 | } | 250 | } |
750 | EXPORT_SYMBOL(ath9k_hw_getchan_noise); | 251 | EXPORT_SYMBOL(ath9k_hw_getchan_noise); |
751 | |||
752 | static void ath9k_olc_temp_compensation_9287(struct ath_hw *ah) | ||
753 | { | ||
754 | u32 rddata; | ||
755 | int32_t delta, currPDADC, slope; | ||
756 | |||
757 | rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4); | ||
758 | currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT); | ||
759 | |||
760 | if (ah->initPDADC == 0 || currPDADC == 0) { | ||
761 | /* | ||
762 | * Zero value indicates that no frames have been transmitted yet, | ||
763 | * can't do temperature compensation until frames are transmitted. | ||
764 | */ | ||
765 | return; | ||
766 | } else { | ||
767 | slope = ah->eep_ops->get_eeprom(ah, EEP_TEMPSENSE_SLOPE); | ||
768 | |||
769 | if (slope == 0) { /* to avoid divide by zero case */ | ||
770 | delta = 0; | ||
771 | } else { | ||
772 | delta = ((currPDADC - ah->initPDADC)*4) / slope; | ||
773 | } | ||
774 | REG_RMW_FIELD(ah, AR_PHY_CH0_TX_PWRCTRL11, | ||
775 | AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta); | ||
776 | REG_RMW_FIELD(ah, AR_PHY_CH1_TX_PWRCTRL11, | ||
777 | AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta); | ||
778 | } | ||
779 | } | ||
780 | |||
781 | static void ath9k_olc_temp_compensation(struct ath_hw *ah) | ||
782 | { | ||
783 | u32 rddata, i; | ||
784 | int delta, currPDADC, regval; | ||
785 | |||
786 | if (OLC_FOR_AR9287_10_LATER) { | ||
787 | ath9k_olc_temp_compensation_9287(ah); | ||
788 | } else { | ||
789 | rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4); | ||
790 | currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT); | ||
791 | |||
792 | if (ah->initPDADC == 0 || currPDADC == 0) { | ||
793 | return; | ||
794 | } else { | ||
795 | if (ah->eep_ops->get_eeprom(ah, EEP_DAC_HPWR_5G)) | ||
796 | delta = (currPDADC - ah->initPDADC + 4) / 8; | ||
797 | else | ||
798 | delta = (currPDADC - ah->initPDADC + 5) / 10; | ||
799 | |||
800 | if (delta != ah->PDADCdelta) { | ||
801 | ah->PDADCdelta = delta; | ||
802 | for (i = 1; i < AR9280_TX_GAIN_TABLE_SIZE; i++) { | ||
803 | regval = ah->originalGain[i] - delta; | ||
804 | if (regval < 0) | ||
805 | regval = 0; | ||
806 | |||
807 | REG_RMW_FIELD(ah, | ||
808 | AR_PHY_TX_GAIN_TBL1 + i * 4, | ||
809 | AR_PHY_TX_GAIN, regval); | ||
810 | } | ||
811 | } | ||
812 | } | ||
813 | } | ||
814 | } | ||
815 | |||
816 | static void ath9k_hw_9271_pa_cal(struct ath_hw *ah, bool is_reset) | ||
817 | { | ||
818 | u32 regVal; | ||
819 | unsigned int i; | ||
820 | u32 regList [][2] = { | ||
821 | { 0x786c, 0 }, | ||
822 | { 0x7854, 0 }, | ||
823 | { 0x7820, 0 }, | ||
824 | { 0x7824, 0 }, | ||
825 | { 0x7868, 0 }, | ||
826 | { 0x783c, 0 }, | ||
827 | { 0x7838, 0 } , | ||
828 | { 0x7828, 0 } , | ||
829 | }; | ||
830 | |||
831 | for (i = 0; i < ARRAY_SIZE(regList); i++) | ||
832 | regList[i][1] = REG_READ(ah, regList[i][0]); | ||
833 | |||
834 | regVal = REG_READ(ah, 0x7834); | ||
835 | regVal &= (~(0x1)); | ||
836 | REG_WRITE(ah, 0x7834, regVal); | ||
837 | regVal = REG_READ(ah, 0x9808); | ||
838 | regVal |= (0x1 << 27); | ||
839 | REG_WRITE(ah, 0x9808, regVal); | ||
840 | |||
841 | /* 786c,b23,1, pwddac=1 */ | ||
842 | REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1); | ||
843 | /* 7854, b5,1, pdrxtxbb=1 */ | ||
844 | REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1); | ||
845 | /* 7854, b7,1, pdv2i=1 */ | ||
846 | REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1); | ||
847 | /* 7854, b8,1, pddacinterface=1 */ | ||
848 | REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1); | ||
849 | /* 7824,b12,0, offcal=0 */ | ||
850 | REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0); | ||
851 | /* 7838, b1,0, pwddb=0 */ | ||
852 | REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0); | ||
853 | /* 7820,b11,0, enpacal=0 */ | ||
854 | REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0); | ||
855 | /* 7820,b25,1, pdpadrv1=0 */ | ||
856 | REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 0); | ||
857 | /* 7820,b24,0, pdpadrv2=0 */ | ||
858 | REG_RMW_FIELD(ah, AR9285_AN_RF2G1,AR9285_AN_RF2G1_PDPADRV2,0); | ||
859 | /* 7820,b23,0, pdpaout=0 */ | ||
860 | REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0); | ||
861 | /* 783c,b14-16,7, padrvgn2tab_0=7 */ | ||
862 | REG_RMW_FIELD(ah, AR9285_AN_RF2G8,AR9285_AN_RF2G8_PADRVGN2TAB0, 7); | ||
863 | /* | ||
864 | * 7838,b29-31,0, padrvgn1tab_0=0 | ||
865 | * does not matter since we turn it off | ||
866 | */ | ||
867 | REG_RMW_FIELD(ah, AR9285_AN_RF2G7,AR9285_AN_RF2G7_PADRVGN2TAB0, 0); | ||
868 | |||
869 | REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9271_AN_RF2G3_CCOMP, 0xfff); | ||
870 | |||
871 | /* Set: | ||
872 | * localmode=1,bmode=1,bmoderxtx=1,synthon=1, | ||
873 | * txon=1,paon=1,oscon=1,synthon_force=1 | ||
874 | */ | ||
875 | REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0); | ||
876 | udelay(30); | ||
877 | REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9271_AN_RF2G6_OFFS, 0); | ||
878 | |||
879 | /* find off_6_1; */ | ||
880 | for (i = 6; i > 0; i--) { | ||
881 | regVal = REG_READ(ah, 0x7834); | ||
882 | regVal |= (1 << (20 + i)); | ||
883 | REG_WRITE(ah, 0x7834, regVal); | ||
884 | udelay(1); | ||
885 | //regVal = REG_READ(ah, 0x7834); | ||
886 | regVal &= (~(0x1 << (20 + i))); | ||
887 | regVal |= (MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9) | ||
888 | << (20 + i)); | ||
889 | REG_WRITE(ah, 0x7834, regVal); | ||
890 | } | ||
891 | |||
892 | regVal = (regVal >>20) & 0x7f; | ||
893 | |||
894 | /* Update PA cal info */ | ||
895 | if ((!is_reset) && (ah->pacal_info.prev_offset == regVal)) { | ||
896 | if (ah->pacal_info.max_skipcount < MAX_PACAL_SKIPCOUNT) | ||
897 | ah->pacal_info.max_skipcount = | ||
898 | 2 * ah->pacal_info.max_skipcount; | ||
899 | ah->pacal_info.skipcount = ah->pacal_info.max_skipcount; | ||
900 | } else { | ||
901 | ah->pacal_info.max_skipcount = 1; | ||
902 | ah->pacal_info.skipcount = 0; | ||
903 | ah->pacal_info.prev_offset = regVal; | ||
904 | } | ||
905 | |||
906 | regVal = REG_READ(ah, 0x7834); | ||
907 | regVal |= 0x1; | ||
908 | REG_WRITE(ah, 0x7834, regVal); | ||
909 | regVal = REG_READ(ah, 0x9808); | ||
910 | regVal &= (~(0x1 << 27)); | ||
911 | REG_WRITE(ah, 0x9808, regVal); | ||
912 | |||
913 | for (i = 0; i < ARRAY_SIZE(regList); i++) | ||
914 | REG_WRITE(ah, regList[i][0], regList[i][1]); | ||
915 | } | ||
916 | |||
917 | static inline void ath9k_hw_9285_pa_cal(struct ath_hw *ah, bool is_reset) | ||
918 | { | ||
919 | struct ath_common *common = ath9k_hw_common(ah); | ||
920 | u32 regVal; | ||
921 | int i, offset, offs_6_1, offs_0; | ||
922 | u32 ccomp_org, reg_field; | ||
923 | u32 regList[][2] = { | ||
924 | { 0x786c, 0 }, | ||
925 | { 0x7854, 0 }, | ||
926 | { 0x7820, 0 }, | ||
927 | { 0x7824, 0 }, | ||
928 | { 0x7868, 0 }, | ||
929 | { 0x783c, 0 }, | ||
930 | { 0x7838, 0 }, | ||
931 | }; | ||
932 | |||
933 | ath_print(common, ATH_DBG_CALIBRATE, "Running PA Calibration\n"); | ||
934 | |||
935 | /* PA CAL is not needed for high power solution */ | ||
936 | if (ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE) == | ||
937 | AR5416_EEP_TXGAIN_HIGH_POWER) | ||
938 | return; | ||
939 | |||
940 | if (AR_SREV_9285_11(ah)) { | ||
941 | REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14)); | ||
942 | udelay(10); | ||
943 | } | ||
944 | |||
945 | for (i = 0; i < ARRAY_SIZE(regList); i++) | ||
946 | regList[i][1] = REG_READ(ah, regList[i][0]); | ||
947 | |||
948 | regVal = REG_READ(ah, 0x7834); | ||
949 | regVal &= (~(0x1)); | ||
950 | REG_WRITE(ah, 0x7834, regVal); | ||
951 | regVal = REG_READ(ah, 0x9808); | ||
952 | regVal |= (0x1 << 27); | ||
953 | REG_WRITE(ah, 0x9808, regVal); | ||
954 | |||
955 | REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1); | ||
956 | REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1); | ||
957 | REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1); | ||
958 | REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1); | ||
959 | REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0); | ||
960 | REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0); | ||
961 | REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0); | ||
962 | REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 0); | ||
963 | REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2, 0); | ||
964 | REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0); | ||
965 | REG_RMW_FIELD(ah, AR9285_AN_RF2G8, AR9285_AN_RF2G8_PADRVGN2TAB0, 7); | ||
966 | REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PADRVGN2TAB0, 0); | ||
967 | ccomp_org = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_CCOMP); | ||
968 | REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, 0xf); | ||
969 | |||
970 | REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0); | ||
971 | udelay(30); | ||
972 | REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, 0); | ||
973 | REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 0); | ||
974 | |||
975 | for (i = 6; i > 0; i--) { | ||
976 | regVal = REG_READ(ah, 0x7834); | ||
977 | regVal |= (1 << (19 + i)); | ||
978 | REG_WRITE(ah, 0x7834, regVal); | ||
979 | udelay(1); | ||
980 | regVal = REG_READ(ah, 0x7834); | ||
981 | regVal &= (~(0x1 << (19 + i))); | ||
982 | reg_field = MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9); | ||
983 | regVal |= (reg_field << (19 + i)); | ||
984 | REG_WRITE(ah, 0x7834, regVal); | ||
985 | } | ||
986 | |||
987 | REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 1); | ||
988 | udelay(1); | ||
989 | reg_field = MS(REG_READ(ah, AR9285_AN_RF2G9), AR9285_AN_RXTXBB1_SPARE9); | ||
990 | REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, reg_field); | ||
991 | offs_6_1 = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_OFFS); | ||
992 | offs_0 = MS(REG_READ(ah, AR9285_AN_RF2G3), AR9285_AN_RF2G3_PDVCCOMP); | ||
993 | |||
994 | offset = (offs_6_1<<1) | offs_0; | ||
995 | offset = offset - 0; | ||
996 | offs_6_1 = offset>>1; | ||
997 | offs_0 = offset & 1; | ||
998 | |||
999 | if ((!is_reset) && (ah->pacal_info.prev_offset == offset)) { | ||
1000 | if (ah->pacal_info.max_skipcount < MAX_PACAL_SKIPCOUNT) | ||
1001 | ah->pacal_info.max_skipcount = | ||
1002 | 2 * ah->pacal_info.max_skipcount; | ||
1003 | ah->pacal_info.skipcount = ah->pacal_info.max_skipcount; | ||
1004 | } else { | ||
1005 | ah->pacal_info.max_skipcount = 1; | ||
1006 | ah->pacal_info.skipcount = 0; | ||
1007 | ah->pacal_info.prev_offset = offset; | ||
1008 | } | ||
1009 | |||
1010 | REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, offs_6_1); | ||
1011 | REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, offs_0); | ||
1012 | |||
1013 | regVal = REG_READ(ah, 0x7834); | ||
1014 | regVal |= 0x1; | ||
1015 | REG_WRITE(ah, 0x7834, regVal); | ||
1016 | regVal = REG_READ(ah, 0x9808); | ||
1017 | regVal &= (~(0x1 << 27)); | ||
1018 | REG_WRITE(ah, 0x9808, regVal); | ||
1019 | |||
1020 | for (i = 0; i < ARRAY_SIZE(regList); i++) | ||
1021 | REG_WRITE(ah, regList[i][0], regList[i][1]); | ||
1022 | |||
1023 | REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, ccomp_org); | ||
1024 | |||
1025 | if (AR_SREV_9285_11(ah)) | ||
1026 | REG_WRITE(ah, AR9285_AN_TOP4, AR9285_AN_TOP4_DEFAULT); | ||
1027 | |||
1028 | } | ||
1029 | |||
1030 | bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, | ||
1031 | u8 rxchainmask, bool longcal) | ||
1032 | { | ||
1033 | bool iscaldone = true; | ||
1034 | struct ath9k_cal_list *currCal = ah->cal_list_curr; | ||
1035 | |||
1036 | if (currCal && | ||
1037 | (currCal->calState == CAL_RUNNING || | ||
1038 | currCal->calState == CAL_WAITING)) { | ||
1039 | iscaldone = ath9k_hw_per_calibration(ah, chan, | ||
1040 | rxchainmask, currCal); | ||
1041 | if (iscaldone) { | ||
1042 | ah->cal_list_curr = currCal = currCal->calNext; | ||
1043 | |||
1044 | if (currCal->calState == CAL_WAITING) { | ||
1045 | iscaldone = false; | ||
1046 | ath9k_hw_reset_calibration(ah, currCal); | ||
1047 | } | ||
1048 | } | ||
1049 | } | ||
1050 | |||
1051 | /* Do NF cal only at longer intervals */ | ||
1052 | if (longcal) { | ||
1053 | /* Do periodic PAOffset Cal */ | ||
1054 | if (AR_SREV_9271(ah)) | ||
1055 | ath9k_hw_9271_pa_cal(ah, false); | ||
1056 | else if (AR_SREV_9285_11_OR_LATER(ah)) { | ||
1057 | if (!ah->pacal_info.skipcount) | ||
1058 | ath9k_hw_9285_pa_cal(ah, false); | ||
1059 | else | ||
1060 | ah->pacal_info.skipcount--; | ||
1061 | } | ||
1062 | |||
1063 | if (OLC_FOR_AR9280_20_LATER || OLC_FOR_AR9287_10_LATER) | ||
1064 | ath9k_olc_temp_compensation(ah); | ||
1065 | |||
1066 | /* Get the value from the previous NF cal and update history buffer */ | ||
1067 | ath9k_hw_getnf(ah, chan); | ||
1068 | |||
1069 | /* | ||
1070 | * Load the NF from history buffer of the current channel. | ||
1071 | * NF is slow time-variant, so it is OK to use a historical value. | ||
1072 | */ | ||
1073 | ath9k_hw_loadnf(ah, ah->curchan); | ||
1074 | |||
1075 | ath9k_hw_start_nfcal(ah); | ||
1076 | } | ||
1077 | |||
1078 | return iscaldone; | ||
1079 | } | ||
1080 | EXPORT_SYMBOL(ath9k_hw_calibrate); | ||
1081 | |||
1082 | /* Carrier leakage Calibration fix */ | ||
1083 | static bool ar9285_clc(struct ath_hw *ah, struct ath9k_channel *chan) | ||
1084 | { | ||
1085 | struct ath_common *common = ath9k_hw_common(ah); | ||
1086 | |||
1087 | REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); | ||
1088 | if (IS_CHAN_HT20(chan)) { | ||
1089 | REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE); | ||
1090 | REG_SET_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN); | ||
1091 | REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, | ||
1092 | AR_PHY_AGC_CONTROL_FLTR_CAL); | ||
1093 | REG_CLR_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE); | ||
1094 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL); | ||
1095 | if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, | ||
1096 | AR_PHY_AGC_CONTROL_CAL, 0, AH_WAIT_TIMEOUT)) { | ||
1097 | ath_print(common, ATH_DBG_CALIBRATE, "offset " | ||
1098 | "calibration failed to complete in " | ||
1099 | "1ms; noisy ??\n"); | ||
1100 | return false; | ||
1101 | } | ||
1102 | REG_CLR_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN); | ||
1103 | REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE); | ||
1104 | REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); | ||
1105 | } | ||
1106 | REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); | ||
1107 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); | ||
1108 | REG_SET_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE); | ||
1109 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL); | ||
1110 | if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, | ||
1111 | 0, AH_WAIT_TIMEOUT)) { | ||
1112 | ath_print(common, ATH_DBG_CALIBRATE, "offset calibration " | ||
1113 | "failed to complete in 1ms; noisy ??\n"); | ||
1114 | return false; | ||
1115 | } | ||
1116 | |||
1117 | REG_SET_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); | ||
1118 | REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); | ||
1119 | REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); | ||
1120 | |||
1121 | return true; | ||
1122 | } | ||
1123 | |||
1124 | bool ath9k_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) | ||
1125 | { | ||
1126 | struct ath_common *common = ath9k_hw_common(ah); | ||
1127 | |||
1128 | if (AR_SREV_9271(ah) || AR_SREV_9285_12_OR_LATER(ah)) { | ||
1129 | if (!ar9285_clc(ah, chan)) | ||
1130 | return false; | ||
1131 | } else { | ||
1132 | if (AR_SREV_9280_10_OR_LATER(ah)) { | ||
1133 | if (!AR_SREV_9287_10_OR_LATER(ah)) | ||
1134 | REG_CLR_BIT(ah, AR_PHY_ADC_CTL, | ||
1135 | AR_PHY_ADC_CTL_OFF_PWDADC); | ||
1136 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, | ||
1137 | AR_PHY_AGC_CONTROL_FLTR_CAL); | ||
1138 | } | ||
1139 | |||
1140 | /* Calibrate the AGC */ | ||
1141 | REG_WRITE(ah, AR_PHY_AGC_CONTROL, | ||
1142 | REG_READ(ah, AR_PHY_AGC_CONTROL) | | ||
1143 | AR_PHY_AGC_CONTROL_CAL); | ||
1144 | |||
1145 | /* Poll for offset calibration complete */ | ||
1146 | if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, | ||
1147 | 0, AH_WAIT_TIMEOUT)) { | ||
1148 | ath_print(common, ATH_DBG_CALIBRATE, | ||
1149 | "offset calibration failed to " | ||
1150 | "complete in 1ms; noisy environment?\n"); | ||
1151 | return false; | ||
1152 | } | ||
1153 | |||
1154 | if (AR_SREV_9280_10_OR_LATER(ah)) { | ||
1155 | if (!AR_SREV_9287_10_OR_LATER(ah)) | ||
1156 | REG_SET_BIT(ah, AR_PHY_ADC_CTL, | ||
1157 | AR_PHY_ADC_CTL_OFF_PWDADC); | ||
1158 | REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, | ||
1159 | AR_PHY_AGC_CONTROL_FLTR_CAL); | ||
1160 | } | ||
1161 | } | ||
1162 | |||
1163 | /* Do PA Calibration */ | ||
1164 | if (AR_SREV_9271(ah)) | ||
1165 | ath9k_hw_9271_pa_cal(ah, true); | ||
1166 | else if (AR_SREV_9285_11_OR_LATER(ah)) | ||
1167 | ath9k_hw_9285_pa_cal(ah, true); | ||
1168 | |||
1169 | /* Do NF Calibration after DC offset and other calibrations */ | ||
1170 | REG_WRITE(ah, AR_PHY_AGC_CONTROL, | ||
1171 | REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_NF); | ||
1172 | |||
1173 | ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL; | ||
1174 | |||
1175 | /* Enable IQ, ADC Gain and ADC DC offset CALs */ | ||
1176 | if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) { | ||
1177 | if (ath9k_hw_iscal_supported(ah, ADC_GAIN_CAL)) { | ||
1178 | INIT_CAL(&ah->adcgain_caldata); | ||
1179 | INSERT_CAL(ah, &ah->adcgain_caldata); | ||
1180 | ath_print(common, ATH_DBG_CALIBRATE, | ||
1181 | "enabling ADC Gain Calibration.\n"); | ||
1182 | } | ||
1183 | if (ath9k_hw_iscal_supported(ah, ADC_DC_CAL)) { | ||
1184 | INIT_CAL(&ah->adcdc_caldata); | ||
1185 | INSERT_CAL(ah, &ah->adcdc_caldata); | ||
1186 | ath_print(common, ATH_DBG_CALIBRATE, | ||
1187 | "enabling ADC DC Calibration.\n"); | ||
1188 | } | ||
1189 | if (ath9k_hw_iscal_supported(ah, IQ_MISMATCH_CAL)) { | ||
1190 | INIT_CAL(&ah->iq_caldata); | ||
1191 | INSERT_CAL(ah, &ah->iq_caldata); | ||
1192 | ath_print(common, ATH_DBG_CALIBRATE, | ||
1193 | "enabling IQ Calibration.\n"); | ||
1194 | } | ||
1195 | |||
1196 | ah->cal_list_curr = ah->cal_list; | ||
1197 | |||
1198 | if (ah->cal_list_curr) | ||
1199 | ath9k_hw_reset_calibration(ah, ah->cal_list_curr); | ||
1200 | } | ||
1201 | |||
1202 | chan->CalValid = 0; | ||
1203 | |||
1204 | return true; | ||
1205 | } | ||
1206 | |||
1207 | const struct ath9k_percal_data iq_cal_multi_sample = { | ||
1208 | IQ_MISMATCH_CAL, | ||
1209 | MAX_CAL_SAMPLES, | ||
1210 | PER_MIN_LOG_COUNT, | ||
1211 | ath9k_hw_iqcal_collect, | ||
1212 | ath9k_hw_iqcalibrate | ||
1213 | }; | ||
1214 | const struct ath9k_percal_data iq_cal_single_sample = { | ||
1215 | IQ_MISMATCH_CAL, | ||
1216 | MIN_CAL_SAMPLES, | ||
1217 | PER_MAX_LOG_COUNT, | ||
1218 | ath9k_hw_iqcal_collect, | ||
1219 | ath9k_hw_iqcalibrate | ||
1220 | }; | ||
1221 | const struct ath9k_percal_data adc_gain_cal_multi_sample = { | ||
1222 | ADC_GAIN_CAL, | ||
1223 | MAX_CAL_SAMPLES, | ||
1224 | PER_MIN_LOG_COUNT, | ||
1225 | ath9k_hw_adc_gaincal_collect, | ||
1226 | ath9k_hw_adc_gaincal_calibrate | ||
1227 | }; | ||
1228 | const struct ath9k_percal_data adc_gain_cal_single_sample = { | ||
1229 | ADC_GAIN_CAL, | ||
1230 | MIN_CAL_SAMPLES, | ||
1231 | PER_MAX_LOG_COUNT, | ||
1232 | ath9k_hw_adc_gaincal_collect, | ||
1233 | ath9k_hw_adc_gaincal_calibrate | ||
1234 | }; | ||
1235 | const struct ath9k_percal_data adc_dc_cal_multi_sample = { | ||
1236 | ADC_DC_CAL, | ||
1237 | MAX_CAL_SAMPLES, | ||
1238 | PER_MIN_LOG_COUNT, | ||
1239 | ath9k_hw_adc_dccal_collect, | ||
1240 | ath9k_hw_adc_dccal_calibrate | ||
1241 | }; | ||
1242 | const struct ath9k_percal_data adc_dc_cal_single_sample = { | ||
1243 | ADC_DC_CAL, | ||
1244 | MIN_CAL_SAMPLES, | ||
1245 | PER_MAX_LOG_COUNT, | ||
1246 | ath9k_hw_adc_dccal_collect, | ||
1247 | ath9k_hw_adc_dccal_calibrate | ||
1248 | }; | ||
1249 | const struct ath9k_percal_data adc_init_dc_cal = { | ||
1250 | ADC_DC_INIT_CAL, | ||
1251 | MIN_CAL_SAMPLES, | ||
1252 | INIT_LOG_COUNT, | ||
1253 | ath9k_hw_adc_dccal_collect, | ||
1254 | ath9k_hw_adc_dccal_calibrate | ||
1255 | }; | ||