iPXE
ath9k_ar9002_calib.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2008-2011 Atheros Communications Inc.
3 *
4 * Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
5 * Original from Linux kernel 3.0.1
6 *
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20FILE_SECBOOT ( FORBIDDEN );
21
22#include "hw.h"
23#include "hw-ops.h"
24#include "ar9002_phy.h"
25
26#define AR9285_CLCAL_REDO_THRESH 1
27
33
35 struct ath9k_channel *chan,
36 enum ar9002_cal_types cal_type)
37{
38 int supported = 0;
39 switch (ah->supp_cals & cal_type) {
40 case IQ_MISMATCH_CAL:
41 /* Run IQ Mismatch for non-CCK only */
42 if (!IS_CHAN_B(chan))
43 supported = 1;
44 break;
45 case ADC_GAIN_CAL:
46 case ADC_DC_CAL:
47 /* Run ADC Gain Cal for non-CCK & non 2GHz-HT20 only */
48 if (!IS_CHAN_B(chan) &&
49 !(IS_CHAN_2GHZ(chan) && IS_CHAN_HT20(chan)))
50 supported = 1;
51 break;
52 }
53 return supported;
54}
55
57 struct ath9k_cal_list *currCal)
58{
61 currCal->calData->calCountMax);
62
63 switch (currCal->calData->calType) {
64 case IQ_MISMATCH_CAL:
66 DBG2("ath9k: "
67 "starting IQ Mismatch Calibration\n");
68 break;
69 case ADC_GAIN_CAL:
71 DBG2("ath9k: "
72 "starting ADC Gain Calibration\n");
73 break;
74 case ADC_DC_CAL:
76 DBG2("ath9k: "
77 "starting ADC DC Calibration\n");
78 break;
79 }
80
83}
84
86 struct ath9k_channel *ichan __unused,
87 u8 rxchainmask,
88 struct ath9k_cal_list *currCal)
89{
90 struct ath9k_hw_cal_data *caldata = ah->caldata;
91 int iscaldone = 0;
92
93 if (currCal->calState == CAL_RUNNING) {
96
97 currCal->calData->calCollect(ah);
98 ah->cal_samples++;
99
100 if (ah->cal_samples >=
101 currCal->calData->calNumSamples) {
102 int i, numChains = 0;
103 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
104 if (rxchainmask & (1 << i))
105 numChains++;
106 }
107
108 currCal->calData->calPostProc(ah, numChains);
109 caldata->CalValid |= currCal->calData->calType;
110 currCal->calState = CAL_DONE;
111 iscaldone = 1;
112 } else {
114 }
115 }
116 } else if (!(caldata->CalValid & currCal->calData->calType)) {
118 }
119
120 return iscaldone;
121}
122
124{
125 int i;
126
127 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
128 ah->totalPowerMeasI[i] +=
130 ah->totalPowerMeasQ[i] +=
132 ah->totalIqCorrMeas[i] +=
134 DBG2("ath9k: "
135 "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
136 ah->cal_samples, i, ah->totalPowerMeasI[i],
137 ah->totalPowerMeasQ[i],
138 ah->totalIqCorrMeas[i]);
139 }
140}
141
143{
144 int i;
145
146 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
147 ah->totalAdcIOddPhase[i] +=
149 ah->totalAdcIEvenPhase[i] +=
151 ah->totalAdcQOddPhase[i] +=
153 ah->totalAdcQEvenPhase[i] +=
155
156 DBG2("ath9k: "
157 "%d: Chn %d oddi=0x%08x; eveni=0x%08x; oddq=0x%08x; evenq=0x%08x;\n",
158 ah->cal_samples, i,
159 ah->totalAdcIOddPhase[i],
160 ah->totalAdcIEvenPhase[i],
161 ah->totalAdcQOddPhase[i],
162 ah->totalAdcQEvenPhase[i]);
163 }
164}
165
167{
168 int i;
169
170 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
171 ah->totalAdcDcOffsetIOddPhase[i] +=
173 ah->totalAdcDcOffsetIEvenPhase[i] +=
175 ah->totalAdcDcOffsetQOddPhase[i] +=
177 ah->totalAdcDcOffsetQEvenPhase[i] +=
179
180 DBG2("ath9k: "
181 "%d: Chn %d oddi=0x%08x; eveni=0x%08x; oddq=0x%08x; evenq=0x%08x;\n",
182 ah->cal_samples, i,
183 ah->totalAdcDcOffsetIOddPhase[i],
184 ah->totalAdcDcOffsetIEvenPhase[i],
185 ah->totalAdcDcOffsetQOddPhase[i],
186 ah->totalAdcDcOffsetQEvenPhase[i]);
187 }
188}
189
190static void ar9002_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
191{
192 u32 powerMeasQ, powerMeasI, iqCorrMeas;
193 u32 qCoffDenom, iCoffDenom;
195 int iqCorrNeg, i;
196
197 for (i = 0; i < numChains; i++) {
198 powerMeasI = ah->totalPowerMeasI[i];
199 powerMeasQ = ah->totalPowerMeasQ[i];
200 iqCorrMeas = ah->totalIqCorrMeas[i];
201
202 DBG2("ath9k: "
203 "Starting IQ Cal and Correction for Chain %d\n",
204 i);
205
206 DBG2("ath9k: "
207 "Orignal: Chn %diq_corr_meas = 0x%08x\n",
208 i, ah->totalIqCorrMeas[i]);
209
210 iqCorrNeg = 0;
211
212 if (iqCorrMeas > 0x80000000) {
213 iqCorrMeas = (0xffffffff - iqCorrMeas) + 1;
214 iqCorrNeg = 1;
215 }
216
217 DBG2("ath9k: "
218 "Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI);
219 DBG2("ath9k: "
220 "Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ);
221 DBG2("ath9k: iqCorrNeg is 0x%08x\n",
222 iqCorrNeg);
223
224 iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128;
225 qCoffDenom = powerMeasQ / 64;
226
227 if ((powerMeasQ != 0) && (iCoffDenom != 0) &&
228 (qCoffDenom != 0)) {
229 iCoff = iqCorrMeas / iCoffDenom;
230 qCoff = powerMeasI / qCoffDenom - 64;
231 DBG2("ath9k: "
232 "Chn %d iCoff = 0x%08x\n", i, iCoff);
233 DBG2("ath9k: "
234 "Chn %d qCoff = 0x%08x\n", i, qCoff);
235
236 iCoff = iCoff & 0x3f;
237 DBG2("ath9k: "
238 "New: Chn %d iCoff = 0x%08x\n", i, iCoff);
239 if (iqCorrNeg == 0x0)
240 iCoff = 0x40 - iCoff;
241
242 if (qCoff > 15)
243 qCoff = 15;
244 else if (qCoff <= -16)
245 qCoff = -16;
246
247 DBG2("ath9k: "
248 "Chn %d : iCoff = 0x%x qCoff = 0x%x\n",
249 i, iCoff, qCoff);
250
253 iCoff);
256 qCoff);
257 DBG2("ath9k: "
258 "IQ Cal and Correction done for Chain %d\n",
259 i);
260 }
261 }
262
265}
266
267static void ar9002_hw_adc_gaincal_calibrate(struct ath_hw *ah, u8 numChains)
268{
269 u32 iOddMeasOffset, iEvenMeasOffset, qOddMeasOffset, qEvenMeasOffset;
270 u32 qGainMismatch, iGainMismatch, val, i;
271
272 for (i = 0; i < numChains; i++) {
273 iOddMeasOffset = ah->totalAdcIOddPhase[i];
274 iEvenMeasOffset = ah->totalAdcIEvenPhase[i];
275 qOddMeasOffset = ah->totalAdcQOddPhase[i];
276 qEvenMeasOffset = ah->totalAdcQEvenPhase[i];
277
278 DBG2("ath9k: "
279 "Starting ADC Gain Cal for Chain %d\n", i);
280
281 DBG2("ath9k: "
282 "Chn %d pwr_meas_odd_i = 0x%08x\n", i,
283 iOddMeasOffset);
284 DBG2("ath9k: "
285 "Chn %d pwr_meas_even_i = 0x%08x\n", i,
286 iEvenMeasOffset);
287 DBG2("ath9k: "
288 "Chn %d pwr_meas_odd_q = 0x%08x\n", i,
289 qOddMeasOffset);
290 DBG2("ath9k: "
291 "Chn %d pwr_meas_even_q = 0x%08x\n", i,
292 qEvenMeasOffset);
293
294 if (iOddMeasOffset != 0 && qEvenMeasOffset != 0) {
295 iGainMismatch =
296 ((iEvenMeasOffset * 32) /
297 iOddMeasOffset) & 0x3f;
298 qGainMismatch =
299 ((qOddMeasOffset * 32) /
300 qEvenMeasOffset) & 0x3f;
301
302 DBG2("ath9k: "
303 "Chn %d gain_mismatch_i = 0x%08x\n", i,
304 iGainMismatch);
305 DBG2("ath9k: "
306 "Chn %d gain_mismatch_q = 0x%08x\n", i,
307 qGainMismatch);
308
310 val &= 0xfffff000;
311 val |= (qGainMismatch) | (iGainMismatch << 6);
313
314 DBG2("ath9k: "
315 "ADC Gain Cal done for Chain %d\n", i);
316 }
317 }
318
322}
323
324static void ar9002_hw_adc_dccal_calibrate(struct ath_hw *ah, u8 numChains)
325{
326 u32 iOddMeasOffset, iEvenMeasOffset, val, i;
327 int32_t qOddMeasOffset, qEvenMeasOffset, qDcMismatch, iDcMismatch;
328 const struct ath9k_percal_data *calData =
329 ah->cal_list_curr->calData;
330 u32 numSamples =
331 (1 << (calData->calCountMax + 5)) * calData->calNumSamples;
332
333 for (i = 0; i < numChains; i++) {
334 iOddMeasOffset = ah->totalAdcDcOffsetIOddPhase[i];
335 iEvenMeasOffset = ah->totalAdcDcOffsetIEvenPhase[i];
336 qOddMeasOffset = ah->totalAdcDcOffsetQOddPhase[i];
337 qEvenMeasOffset = ah->totalAdcDcOffsetQEvenPhase[i];
338
339 DBG2("ath9k: "
340 "Starting ADC DC Offset Cal for Chain %d\n", i);
341
342 DBG2("ath9k: "
343 "Chn %d pwr_meas_odd_i = %d\n", i,
344 iOddMeasOffset);
345 DBG2("ath9k: "
346 "Chn %d pwr_meas_even_i = %d\n", i,
347 iEvenMeasOffset);
348 DBG2("ath9k: "
349 "Chn %d pwr_meas_odd_q = %d\n", i,
350 qOddMeasOffset);
351 DBG2("ath9k: "
352 "Chn %d pwr_meas_even_q = %d\n", i,
353 qEvenMeasOffset);
354
355 iDcMismatch = (((iEvenMeasOffset - iOddMeasOffset) * 2) /
356 numSamples) & 0x1ff;
357 qDcMismatch = (((qOddMeasOffset - qEvenMeasOffset) * 2) /
358 numSamples) & 0x1ff;
359
360 DBG2("ath9k: "
361 "Chn %d dc_offset_mismatch_i = 0x%08x\n", i,
362 iDcMismatch);
363 DBG2("ath9k: "
364 "Chn %d dc_offset_mismatch_q = 0x%08x\n", i,
365 qDcMismatch);
366
368 val &= 0xc0000fff;
369 val |= (qDcMismatch << 12) | (iDcMismatch << 21);
371
372 DBG2("ath9k: "
373 "ADC DC Offset Cal done for Chain %d\n", i);
374 }
375
379}
380
382{
383 u32 rddata;
384 int32_t delta, currPDADC, slope;
385
386 rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4);
387 currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT);
388
389 if (ah->initPDADC == 0 || currPDADC == 0) {
390 /*
391 * Zero value indicates that no frames have been transmitted
392 * yet, can't do temperature compensation until frames are
393 * transmitted.
394 */
395 return;
396 } else {
397 slope = ah->eep_ops->get_eeprom(ah, EEP_TEMPSENSE_SLOPE);
398
399 if (slope == 0) { /* to avoid divide by zero case */
400 delta = 0;
401 } else {
402 delta = ((currPDADC - ah->initPDADC)*4) / slope;
403 }
408 }
409}
410
412{
413 u32 rddata, i;
414 int delta, currPDADC, regval;
415
416 rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4);
417 currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT);
418
419 if (ah->initPDADC == 0 || currPDADC == 0)
420 return;
421
422 if (ah->eep_ops->get_eeprom(ah, EEP_DAC_HPWR_5G))
423 delta = (currPDADC - ah->initPDADC + 4) / 8;
424 else
425 delta = (currPDADC - ah->initPDADC + 5) / 10;
426
427 if (delta != ah->PDADCdelta) {
428 ah->PDADCdelta = delta;
429 for (i = 1; i < AR9280_TX_GAIN_TABLE_SIZE; i++) {
430 regval = ah->originalGain[i] - delta;
431 if (regval < 0)
432 regval = 0;
433
435 AR_PHY_TX_GAIN_TBL1 + i * 4,
436 AR_PHY_TX_GAIN, regval);
437 }
438 }
439}
440
441static void ar9271_hw_pa_cal(struct ath_hw *ah, int is_reset)
442{
443 u32 regVal;
444 unsigned int i;
445 u32 regList[][2] = {
446 { 0x786c, 0 },
447 { 0x7854, 0 },
448 { 0x7820, 0 },
449 { 0x7824, 0 },
450 { 0x7868, 0 },
451 { 0x783c, 0 },
452 { 0x7838, 0 } ,
453 { 0x7828, 0 } ,
454 };
455
456 for (i = 0; i < ARRAY_SIZE(regList); i++)
457 regList[i][1] = REG_READ(ah, regList[i][0]);
458
459 regVal = REG_READ(ah, 0x7834);
460 regVal &= (~(0x1));
461 REG_WRITE(ah, 0x7834, regVal);
462 regVal = REG_READ(ah, 0x9808);
463 regVal |= (0x1 << 27);
464 REG_WRITE(ah, 0x9808, regVal);
465
466 /* 786c,b23,1, pwddac=1 */
468 /* 7854, b5,1, pdrxtxbb=1 */
470 /* 7854, b7,1, pdv2i=1 */
472 /* 7854, b8,1, pddacinterface=1 */
474 /* 7824,b12,0, offcal=0 */
476 /* 7838, b1,0, pwddb=0 */
478 /* 7820,b11,0, enpacal=0 */
480 /* 7820,b25,1, pdpadrv1=0 */
482 /* 7820,b24,0, pdpadrv2=0 */
484 /* 7820,b23,0, pdpaout=0 */
486 /* 783c,b14-16,7, padrvgn2tab_0=7 */
488 /*
489 * 7838,b29-31,0, padrvgn1tab_0=0
490 * does not matter since we turn it off
491 */
493
495
496 /* Set:
497 * localmode=1,bmode=1,bmoderxtx=1,synthon=1,
498 * txon=1,paon=1,oscon=1,synthon_force=1
499 */
500 REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0);
501 udelay(30);
503
504 /* find off_6_1; */
505 for (i = 6; i > 0; i--) {
506 regVal = REG_READ(ah, 0x7834);
507 regVal |= (1 << (20 + i));
508 REG_WRITE(ah, 0x7834, regVal);
509 udelay(1);
510 /* regVal = REG_READ(ah, 0x7834); */
511 regVal &= (~(0x1 << (20 + i)));
512 regVal |= (MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9)
513 << (20 + i));
514 REG_WRITE(ah, 0x7834, regVal);
515 }
516
517 regVal = (regVal >> 20) & 0x7f;
518
519 /* Update PA cal info */
520 if ((!is_reset) && ((unsigned int)ah->pacal_info.prev_offset == regVal)) {
521 if (ah->pacal_info.max_skipcount < MAX_PACAL_SKIPCOUNT)
522 ah->pacal_info.max_skipcount =
523 2 * ah->pacal_info.max_skipcount;
524 ah->pacal_info.skipcount = ah->pacal_info.max_skipcount;
525 } else {
526 ah->pacal_info.max_skipcount = 1;
527 ah->pacal_info.skipcount = 0;
528 ah->pacal_info.prev_offset = regVal;
529 }
530
532
533 regVal = REG_READ(ah, 0x7834);
534 regVal |= 0x1;
535 REG_WRITE(ah, 0x7834, regVal);
536 regVal = REG_READ(ah, 0x9808);
537 regVal &= (~(0x1 << 27));
538 REG_WRITE(ah, 0x9808, regVal);
539
540 for (i = 0; i < ARRAY_SIZE(regList); i++)
541 REG_WRITE(ah, regList[i][0], regList[i][1]);
542
544}
545
546static inline void ar9285_hw_pa_cal(struct ath_hw *ah, int is_reset)
547{
548 u32 regVal;
549 unsigned int i;
550 int offset, offs_6_1, offs_0;
551 u32 ccomp_org, reg_field;
552 u32 regList[][2] = {
553 { 0x786c, 0 },
554 { 0x7854, 0 },
555 { 0x7820, 0 },
556 { 0x7824, 0 },
557 { 0x7868, 0 },
558 { 0x783c, 0 },
559 { 0x7838, 0 },
560 };
561
562 DBG2("ath9k: Running PA Calibration\n");
563
564 /* PA CAL is not needed for high power solution */
565 if (ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE) ==
567 return;
568
569 for (i = 0; i < ARRAY_SIZE(regList); i++)
570 regList[i][1] = REG_READ(ah, regList[i][0]);
571
572 regVal = REG_READ(ah, 0x7834);
573 regVal &= (~(0x1));
574 REG_WRITE(ah, 0x7834, regVal);
575 regVal = REG_READ(ah, 0x9808);
576 regVal |= (0x1 << 27);
577 REG_WRITE(ah, 0x9808, regVal);
578
593
594 REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0);
595 udelay(30);
598
599 for (i = 6; i > 0; i--) {
600 regVal = REG_READ(ah, 0x7834);
601 regVal |= (1 << (19 + i));
602 REG_WRITE(ah, 0x7834, regVal);
603 udelay(1);
604 regVal = REG_READ(ah, 0x7834);
605 regVal &= (~(0x1 << (19 + i)));
606 reg_field = MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9);
607 regVal |= (reg_field << (19 + i));
608 REG_WRITE(ah, 0x7834, regVal);
609 }
610
612 udelay(1);
617
618 offset = (offs_6_1<<1) | offs_0;
619 offset = offset - 0;
620 offs_6_1 = offset>>1;
621 offs_0 = offset & 1;
622
623 if ((!is_reset) && (ah->pacal_info.prev_offset == offset)) {
624 if (ah->pacal_info.max_skipcount < MAX_PACAL_SKIPCOUNT)
625 ah->pacal_info.max_skipcount =
626 2 * ah->pacal_info.max_skipcount;
627 ah->pacal_info.skipcount = ah->pacal_info.max_skipcount;
628 } else {
629 ah->pacal_info.max_skipcount = 1;
630 ah->pacal_info.skipcount = 0;
631 ah->pacal_info.prev_offset = offset;
632 }
633
636
637 regVal = REG_READ(ah, 0x7834);
638 regVal |= 0x1;
639 REG_WRITE(ah, 0x7834, regVal);
640 regVal = REG_READ(ah, 0x9808);
641 regVal &= (~(0x1 << 27));
642 REG_WRITE(ah, 0x9808, regVal);
643
644 for (i = 0; i < ARRAY_SIZE(regList); i++)
645 REG_WRITE(ah, regList[i][0], regList[i][1]);
646
648}
649
650static void ar9002_hw_pa_cal(struct ath_hw *ah, int is_reset)
651{
652 if (AR_SREV_9271(ah)) {
653 if (is_reset || !ah->pacal_info.skipcount)
654 ar9271_hw_pa_cal(ah, is_reset);
655 else
656 ah->pacal_info.skipcount--;
657 } else if (AR_SREV_9285_12_OR_LATER(ah)) {
658 if (is_reset || !ah->pacal_info.skipcount)
659 ar9285_hw_pa_cal(ah, is_reset);
660 else
661 ah->pacal_info.skipcount--;
662 }
663}
664
672
673static int ar9002_hw_calibrate(struct ath_hw *ah,
674 struct ath9k_channel *chan,
675 u8 rxchainmask,
676 int longcal)
677{
678 int iscaldone = 1;
679 struct ath9k_cal_list *currCal = ah->cal_list_curr;
680 int nfcal, nfcal_pending = 0;
681
683 if (ah->caldata)
684 nfcal_pending = ah->caldata->nfcal_pending;
685
686 if (currCal && !nfcal &&
687 (currCal->calState == CAL_RUNNING ||
688 currCal->calState == CAL_WAITING)) {
689 iscaldone = ar9002_hw_per_calibration(ah, chan,
690 rxchainmask, currCal);
691 if (iscaldone) {
692 ah->cal_list_curr = currCal = currCal->calNext;
693
694 if (currCal->calState == CAL_WAITING) {
695 iscaldone = 0;
697 }
698 }
699 }
700
701 /* Do NF cal only at longer intervals */
702 if (longcal || nfcal_pending) {
703 /*
704 * Get the value from the previous NF cal and update
705 * history buffer.
706 */
707 if (ath9k_hw_getnf(ah, chan)) {
708 /*
709 * Load the NF from history buffer of the current
710 * channel.
711 * NF is slow time-variant, so it is OK to use a
712 * historical value.
713 */
714 ath9k_hw_loadnf(ah, ah->curchan);
715 }
716
717 if (longcal) {
719 /* Do periodic PAOffset Cal */
722 }
723 }
724
725 return iscaldone;
726}
727
728/* Carrier leakage Calibration fix */
729static int ar9285_hw_cl_cal(struct ath_hw *ah, struct ath9k_channel *chan)
730{
732 if (IS_CHAN_HT20(chan)) {
741 DBG("ath9k: "
742 "offset calibration failed to complete in 1ms; noisy environment?\n");
743 return 0;
744 }
748 }
754 0, AH_WAIT_TIMEOUT)) {
755 DBG("ath9k: "
756 "offset calibration failed to complete in 1ms; noisy environment?\n");
757 return 0;
758 }
759
763
764 return 1;
765}
766
767static int ar9285_hw_clc(struct ath_hw *ah, struct ath9k_channel *chan)
768{
769 unsigned int i;
770 uint32_t txgain_max;
771 uint32_t clc_gain, gain_mask = 0, clc_num = 0;
772 uint32_t reg_clc_I0, reg_clc_Q0;
773 uint32_t i0_num = 0;
774 uint32_t q0_num = 0;
775 uint32_t total_num = 0;
776 uint32_t reg_rf2g5_org;
777 int retv = 1;
778
779 if (!(ar9285_hw_cl_cal(ah, chan)))
780 return 0;
781
782 txgain_max = MS(REG_READ(ah, AR_PHY_TX_PWRCTRL7),
784
785 for (i = 0; i < (txgain_max+1); i++) {
786 clc_gain = (REG_READ(ah, (AR_PHY_TX_GAIN_TBL1+(i<<2))) &
788 if (!(gain_mask & (1 << clc_gain))) {
789 gain_mask |= (1 << clc_gain);
790 clc_num++;
791 }
792 }
793
794 for (i = 0; i < clc_num; i++) {
795 reg_clc_I0 = (REG_READ(ah, (AR_PHY_CLC_TBL1 + (i << 2)))
797 reg_clc_Q0 = (REG_READ(ah, (AR_PHY_CLC_TBL1 + (i << 2)))
799 if (reg_clc_I0 == 0)
800 i0_num++;
801
802 if (reg_clc_Q0 == 0)
803 q0_num++;
804 }
805 total_num = i0_num + q0_num;
806 if (total_num > AR9285_CLCAL_REDO_THRESH) {
807 reg_rf2g5_org = REG_READ(ah, AR9285_RF2G5);
808 if (AR_SREV_9285E_20(ah)) {
810 (reg_rf2g5_org & AR9285_RF2G5_IC50TX) |
812 } else {
814 (reg_rf2g5_org & AR9285_RF2G5_IC50TX) |
816 }
817 retv = ar9285_hw_cl_cal(ah, chan);
818 REG_WRITE(ah, AR9285_RF2G5, reg_rf2g5_org);
819 }
820 return retv;
821}
822
823static int ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan)
824{
825 if (AR_SREV_9271(ah)) {
826 if (!ar9285_hw_cl_cal(ah, chan))
827 return 0;
828 } else if (AR_SREV_9285(ah) && AR_SREV_9285_12_OR_LATER(ah)) {
829 if (!ar9285_hw_clc(ah, chan))
830 return 0;
831 } else {
838 }
839
840 /* Calibrate the AGC */
844
845 /* Poll for offset calibration complete */
848 0, AH_WAIT_TIMEOUT)) {
849 DBG("ath9k: "
850 "offset calibration failed to complete in 1ms; noisy environment?\n");
851 return 0;
852 }
853
860 }
861 }
862
863 /* Do PA Calibration */
865
866 /* Do NF Calibration after DC offset and other calibrations */
868
869 if (ah->caldata)
870 ah->caldata->nfcal_pending = 1;
871
872 ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL;
873
874 /* Enable IQ, ADC Gain and ADC DC offset CALs */
876 ah->supp_cals = IQ_MISMATCH_CAL;
877
879 ah->supp_cals |= ADC_GAIN_CAL | ADC_DC_CAL;
880
881 if (AR_SREV_9287(ah))
882 ah->supp_cals &= ~ADC_GAIN_CAL;
883
885 INIT_CAL(&ah->adcgain_caldata);
886 INSERT_CAL(ah, &ah->adcgain_caldata);
887 DBG2("ath9k: "
888 "enabling ADC Gain Calibration.\n");
889 }
890
892 INIT_CAL(&ah->adcdc_caldata);
893 INSERT_CAL(ah, &ah->adcdc_caldata);
894 DBG2("ath9k: "
895 "enabling ADC DC Calibration.\n");
896 }
897
899 INIT_CAL(&ah->iq_caldata);
900 INSERT_CAL(ah, &ah->iq_caldata);
901 DBG2("ath9k: "
902 "enabling IQ Calibration.\n");
903 }
904
905 ah->cal_list_curr = ah->cal_list;
906
907 if (ah->cal_list_curr)
908 ath9k_hw_reset_calibration(ah, ah->cal_list_curr);
909 }
910
911 if (ah->caldata)
912 ah->caldata->CalValid = 0;
913
914 return 1;
915}
916
959
961{
962 if (AR_SREV_9100(ah)) {
963 ah->iq_caldata.calData = &iq_cal_multi_sample;
964 ah->supp_cals = IQ_MISMATCH_CAL;
965 return;
966 }
967
970 ah->iq_caldata.calData = &iq_cal_single_sample;
971 ah->adcgain_caldata.calData =
973 ah->adcdc_caldata.calData =
975 } else {
976 ah->iq_caldata.calData = &iq_cal_multi_sample;
977 ah->adcgain_caldata.calData =
979 ah->adcdc_caldata.calData =
981 }
982 ah->supp_cals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL;
983
984 if (AR_SREV_9287(ah))
985 ah->supp_cals &= ~ADC_GAIN_CAL;
986 }
987}
988
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
#define AR_PHY_TX_PWRCTRL4
Definition ar9002_phy.h:474
#define AR_PHY_CALMODE_IQ
Definition ar9002_phy.h:376
#define AR_PHY_FC_DYN2040_EN
Definition ar9002_phy.h:29
#define AR_PHY_TIMING_CTRL4_DO_CAL
Definition ar9002_phy.h:196
#define AR_PHY_TPCRG1
Definition ar9002_phy.h:460
#define AR_PHY_ADC_CTL_OFF_PWDADC
Definition ar9002_phy.h:72
#define AR_PHY_CALMODE_ADC_DC_PER
Definition ar9002_phy.h:378
#define AR_PHY_TX_PWRCTRL7
Definition ar9002_phy.h:485
#define AR_PHY_CAL_MEAS_2(_i)
Definition ar9002_phy.h:383
#define AR_PHY_CALMODE
Definition ar9002_phy.h:374
#define AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF
Definition ar9002_phy.h:191
#define AR_PHY_CL_CAL_ENABLE
Definition ar9002_phy.h:553
#define AR_PHY_CAL_MEAS_1(_i)
Definition ar9002_phy.h:382
#define AR_PHY_CL_CAL_CTL
Definition ar9002_phy.h:552
#define AR_PHY_TX_GAIN_TBL1
Definition ar9002_phy.h:499
#define AR_PHY_TX_GAIN
Definition ar9002_phy.h:500
#define AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF
Definition ar9002_phy.h:189
#define AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP
Definition ar9002_phy.h:507
#define AR_PHY_TX_PWRCTRL_PD_AVG_OUT
Definition ar9002_phy.h:477
#define AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE
Definition ar9002_phy.h:305
#define AR_PHY_TIMING_CTRL4(_i)
Definition ar9002_phy.h:188
#define AR_PHY_TURBO
Definition ar9002_phy.h:26
#define AR_PHY_NEW_ADC_DC_GAIN_CORR(_i)
Definition ar9002_phy.h:303
#define AR_PHY_NEW_ADC_GAIN_CORR_ENABLE
Definition ar9002_phy.h:304
#define AR_PHY_CAL_MEAS_3(_i)
Definition ar9002_phy.h:384
#define AR_PHY_CAL_MEAS_0(_i)
Definition ar9002_phy.h:381
#define AR_PHY_CH0_TX_PWRCTRL11
Definition ar9002_phy.h:503
#define AR_PHY_ADC_CTL
Definition ar9002_phy.h:67
#define AR_PHY_CH1_TX_PWRCTRL11
Definition ar9002_phy.h:504
#define AR_PHY_TPCRG1_PD_CAL_ENABLE
Definition ar9002_phy.h:471
#define AR_PHY_PARALLEL_CAL_ENABLE
Definition ar9002_phy.h:554
#define AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX
Definition ar9002_phy.h:194
#define AR_PHY_TIMING_CTRL4_IQCORR_ENABLE
Definition ar9002_phy.h:193
#define AR_PHY_CALMODE_ADC_GAIN
Definition ar9002_phy.h:377
unsigned int uint32_t
Definition stdint.h:12
signed int int32_t
Definition stdint.h:17
#define IS_CHAN_B(_c)
Definition ath5k.h:660
#define OLC_FOR_AR9280_20_LATER
Definition eeprom.h:107
#define AR9280_TX_GAIN_TABLE_SIZE
Definition eeprom.h:183
@ EEP_TXGAIN_TYPE
Definition eeprom.h:247
@ EEP_DAC_HPWR_5G
Definition eeprom.h:249
@ EEP_TEMPSENSE_SLOPE
Definition eeprom.h:252
#define OLC_FOR_AR9287_10_LATER
Definition eeprom.h:109
#define AR5416_MAX_CHAINS
Definition eeprom.h:160
#define AR5416_EEP_TXGAIN_HIGH_POWER
Definition eeprom.h:171
#define AR9285_AN_TOP2
Definition reg.h:1389
#define AR9285_AN_TOP3
Definition reg.h:1391
#define AR_SREV_9287(_ah)
Definition reg.h:835
#define AR9285_AN_RF2G1_PDPADRV1
Definition reg.h:1285
#define AR9285_AN_RF2G8
Definition reg.h:1373
#define AR9285_RF2G5
Definition reg.h:1334
#define AR9285_AN_RF2G3_PDVCCOMP
Definition reg.h:1298
#define AR_SREV_9285_12_OR_LATER(_ah)
Definition reg.h:832
#define AR9285_RF2G5_IC50TX_SET
Definition reg.h:1336
#define AR_PHY_AGC_CONTROL_FLTR_CAL
Definition reg.h:1906
#define AR_PHY_AGC_CONTROL_CAL
Definition reg.h:1902
#define AR9285_AN_RF2G3
Definition reg.h:1297
#define AR_SREV_9287_11_OR_LATER(_ah)
Definition reg.h:837
#define AR9285_AN_RF2G2
Definition reg.h:1293
#define AR9285_AN_RF2G1_PDPADRV2
Definition reg.h:1287
#define AR_SREV_9285(_ah)
Definition reg.h:830
#define AR_SREV_9285E_20(_ah)
Definition reg.h:882
#define AR9285_AN_RF2G7
Definition reg.h:1367
#define AR9285_AN_RF2G9
Definition reg.h:1378
#define AR_PHY_AGC_CONTROL_NF
Definition reg.h:1903
#define AR_SREV_9280_20_OR_LATER(_ah)
Definition reg.h:825
#define AR_SREV_9100(ah)
Definition reg.h:811
#define AR9271_AN_RF2G3_CCOMP
Definition reg.h:1352
#define AR9285_AN_RF2G6_OFFS
Definition reg.h:1361
#define AR9271_AN_RF2G6_OFFS
Definition reg.h:1364
#define AR9285_AN_RXTXBB1_SPARE9
Definition reg.h:1386
#define AR9285_AN_RXTXBB1
Definition reg.h:1379
#define AR9285_RF2G5_IC50TX
Definition reg.h:1335
#define AR9285_AN_RF2G8_PADRVGN2TAB0
Definition reg.h:1374
#define AR9285_AN_RF2G1
Definition reg.h:1282
#define AR9285_AN_RF2G1_PDPAOUT
Definition reg.h:1289
#define AR9285_AN_RXTXBB1_PDRXTXBB1
Definition reg.h:1380
#define AR9285_AN_RF2G2_OFFCAL
Definition reg.h:1294
#define AR9285_AN_RXTXBB1_PDV2I
Definition reg.h:1382
#define AR_SREV_9271(_ah)
Definition reg.h:854
#define AR9285_AN_TOP3_PWDDAC
Definition reg.h:1394
#define AR9285_AN_RF2G7_PADRVGN2TAB0
Definition reg.h:1370
#define AR9285_AN_RXTXBB1_PDDACIF
Definition reg.h:1384
#define AR_SREV_9160_10_OR_LATER(_ah)
Definition reg.h:818
#define AR9285_RF2G5_IC50TX_XE_SET
Definition reg.h:1337
#define AR9285_AN_RF2G6_CCOMP
Definition reg.h:1359
#define AR9285_AN_RF2G7_PWDDB
Definition reg.h:1368
#define AR9285_AN_RF2G1_ENPACAL
Definition reg.h:1283
#define AR_PHY_AGC_CONTROL
Definition reg.h:1901
#define AR9285_AN_RF2G6
Definition reg.h:1358
static const struct ath9k_percal_data iq_cal_multi_sample
static void ar9285_hw_pa_cal(struct ath_hw *ah, int is_reset)
static void ar9002_hw_setup_calibration(struct ath_hw *ah, struct ath9k_cal_list *currCal)
static const struct ath9k_percal_data adc_dc_cal_multi_sample
static int ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan)
static int ar9002_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, u8 rxchainmask, int longcal)
static int ar9285_hw_cl_cal(struct ath_hw *ah, struct ath9k_channel *chan)
static const struct ath9k_percal_data adc_gain_cal_single_sample
static void ar9002_hw_iqcal_collect(struct ath_hw *ah)
static const struct ath9k_percal_data adc_dc_cal_single_sample
static int ar9285_hw_clc(struct ath_hw *ah, struct ath9k_channel *chan)
static const struct ath9k_percal_data iq_cal_single_sample
static void ar9280_hw_olc_temp_compensation(struct ath_hw *ah)
void ar9002_hw_attach_calib_ops(struct ath_hw *ah)
ar9002_cal_types
@ ADC_DC_CAL
@ IQ_MISMATCH_CAL
@ ADC_GAIN_CAL
static void ar9002_hw_adc_dccal_collect(struct ath_hw *ah)
static int ar9002_hw_per_calibration(struct ath_hw *ah, struct ath9k_channel *ichan __unused, u8 rxchainmask, struct ath9k_cal_list *currCal)
static void ar9002_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
static void ar9002_hw_adc_gaincal_collect(struct ath_hw *ah)
static void ar9002_hw_adc_dccal_calibrate(struct ath_hw *ah, u8 numChains)
static void ar9002_hw_pa_cal(struct ath_hw *ah, int is_reset)
#define AR9285_CLCAL_REDO_THRESH
static int ar9002_hw_is_cal_supported(struct ath_hw *ah, struct ath9k_channel *chan, enum ar9002_cal_types cal_type)
static void ar9287_hw_olc_temp_compensation(struct ath_hw *ah)
static void ar9271_hw_pa_cal(struct ath_hw *ah, int is_reset)
static const struct ath9k_percal_data adc_gain_cal_multi_sample
static void ar9002_hw_init_cal_settings(struct ath_hw *ah)
static void ar9002_hw_olc_temp_compensation(struct ath_hw *ah)
static void ar9002_hw_adc_gaincal_calibrate(struct ath_hw *ah, u8 numChains)
void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan)
void ath9k_hw_start_nfcal(struct ath_hw *ah, int update)
void ath9k_hw_reset_calibration(struct ath_hw *ah, struct ath9k_cal_list *currCal)
int ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan)
int ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout)
Definition ath9k_hw.c:95
#define BIT(nr)
Definition ath.h:34
uint16_t offset
Offset to command line.
Definition bzimage.h:3
#define PER_MAX_LOG_COUNT
Definition calib.h:78
@ CAL_DONE
Definition calib.h:71
@ CAL_RUNNING
Definition calib.h:70
@ CAL_WAITING
Definition calib.h:69
#define MAX_PACAL_SKIPCOUNT
Definition calib.h:101
#define INSERT_CAL(_ahp, _perCal)
Definition calib.h:54
#define MIN_CAL_SAMPLES
Definition calib.h:74
#define INIT_CAL(_perCal)
Definition calib.h:49
#define MAX_CAL_SAMPLES
Definition calib.h:75
#define PER_MIN_LOG_COUNT
Definition calib.h:77
#define ARRAY_SIZE(x)
Definition efx_common.h:43
uint16_t supported
Bitmask of supported option values.
Definition ena.h:1
#define __unused
Declare a variable or data structure as unused.
Definition compiler.h:573
#define DBG2(...)
Definition compiler.h:515
#define DBG(...)
Print a debugging message.
Definition compiler.h:498
#define FILE_SECBOOT(_status)
Declare a file's UEFI Secure Boot permission status.
Definition compiler.h:926
#define REGWRITE_BUFFER_FLUSH(_ah)
Definition hw.h:96
#define REG_WRITE(_ah, _reg, _val)
Definition hw.h:78
#define MS(_v, _f)
Definition hw.h:103
#define REG_READ(_ah, _reg)
Definition hw.h:81
static struct ath_hw_private_ops * ath9k_hw_private_ops(struct ath_hw *ah)
Definition hw.h:880
static struct ath_hw_ops * ath9k_hw_ops(struct ath_hw *ah)
Definition hw.h:885
#define AH_WAIT_TIMEOUT
Definition hw.h:146
#define REG_RMW_FIELD(_a, _r, _f, _v)
Definition hw.h:104
#define ENABLE_REGWRITE_BUFFER(_ah)
Definition hw.h:90
#define IS_CHAN_HT20(_c)
Definition hw.h:371
#define REG_CLR_BIT(_a, _r, _f)
Definition hw.h:110
#define IS_CHAN_2GHZ(_c)
Definition hw.h:362
#define REG_SET_BIT(_a, _r, _f)
Definition hw.h:108
#define u8
Definition igbvf_osdep.h:40
void __asmcall int val
Definition setjmp.h:12
#define AR_PHY_TX_GAIN_CLC_S
Definition phy.h:33
#define AR_PHY_CLC_TBL1
Definition phy.h:37
#define AR_PHY_CLC_I0_S
Definition phy.h:39
#define AR_PHY_CLC_I0
Definition phy.h:38
#define AR_PHY_TX_GAIN_CLC
Definition phy.h:32
#define AR_PHY_TX_PWRCTRL_TX_GAIN_TAB_MAX
Definition phy.h:30
#define AR_PHY_CLC_Q0
Definition phy.h:40
#define AR_PHY_CLC_Q0_S
Definition phy.h:41
uint8_t ah
Definition registers.h:1
enum ath9k_cal_state calState
Definition calib.h:90
const struct ath9k_percal_data * calData
Definition calib.h:89
struct ath9k_cal_list * calNext
Definition calib.h:91
int32_t CalValid
Definition hw.h:336
int8_t iCoff
Definition hw.h:337
int8_t qCoff
Definition hw.h:338
void(* calCollect)(struct ath_hw *)
Definition calib.h:84
u32 calNumSamples
Definition calib.h:82
void(* calPostProc)(struct ath_hw *, u8)
Definition calib.h:85
struct ath_hw_ops - callbacks used by hardware code and driver code
Definition hw.h:604
int(* calibrate)(struct ath_hw *ah, struct ath9k_channel *chan, u8 rxchainmask, int longcal)
Definition hw.h:611
struct ath_hw_private_ops - callbacks used internally by hardware code
Definition hw.h:551
void(* setup_calibration)(struct ath_hw *ah, struct ath9k_cal_list *currCal)
Definition hw.h:558
void(* init_cal_settings)(struct ath_hw *ah)
Definition hw.h:553
int(* init_cal)(struct ath_hw *ah, struct ath9k_channel *chan)
Definition hw.h:554
Definition hw.h:657
void udelay(unsigned long usecs)
Delay for a fixed number of microseconds.
Definition timer.c:61
#define u32
Definition vga.h:21