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