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 
20 FILE_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 
32 };
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 
85 static int ar9002_hw_per_calibration(struct ath_hw *ah,
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) {
94  if (!(REG_READ(ah, AR_PHY_TIMING_CTRL4(0)) &
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)) {
117  ath9k_hw_reset_calibration(ah, currCal);
118  }
119 
120  return iscaldone;
121 }
122 
123 static void ar9002_hw_iqcal_collect(struct ath_hw *ah)
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 
190 static 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 
267 static 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 
324 static 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 
441 static 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 
546 static 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 
650 static 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 
666 {
669  else if (OLC_FOR_AR9280_20_LATER)
671 }
672 
673 static 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;
696  ath9k_hw_reset_calibration(ah, currCal);
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 */
720  ar9002_hw_pa_cal(ah, 0);
722  }
723  }
724 
725  return iscaldone;
726 }
727 
728 /* Carrier leakage Calibration fix */
729 static 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 
767 static 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 
823 static 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 */
864  ar9002_hw_pa_cal(ah, 1);
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 
917 static const struct ath9k_percal_data iq_cal_multi_sample = {
923 };
930 };
932  ADC_GAIN_CAL,
937 };
939  ADC_GAIN_CAL,
944 };
946  ADC_DC_CAL,
951 };
953  ADC_DC_CAL,
958 };
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 
990 {
991  struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
992  struct ath_hw_ops *ops = ath9k_hw_ops(ah);
993 
995  priv_ops->init_cal = ar9002_hw_init_cal;
997 
999 }
static const struct ath9k_percal_data iq_cal_multi_sample
#define AR_PHY_CAL_MEAS_3(_i)
Definition: ar9002_phy.h:384
static void ar9271_hw_pa_cal(struct ath_hw *ah, int is_reset)
#define AR9285_AN_RF2G2_OFFCAL
Definition: reg.h:1294
#define AR_SREV_9287_11_OR_LATER(_ah)
Definition: reg.h:837
#define AR_PHY_TIMING_CTRL4_IQCORR_ENABLE
Definition: ar9002_phy.h:193
Definition: hw.h:657
#define AR9285_AN_RF2G1_ENPACAL
Definition: reg.h:1283
static void ar9280_hw_olc_temp_compensation(struct ath_hw *ah)
#define AR_PHY_CALMODE_ADC_DC_PER
Definition: ar9002_phy.h:378
#define AR9285_RF2G5_IC50TX_SET
Definition: reg.h:1336
#define AR_SREV_9280_20_OR_LATER(_ah)
Definition: reg.h:825
#define AR_PHY_TX_PWRCTRL4
Definition: ar9002_phy.h:474
#define AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF
Definition: ar9002_phy.h:191
#define AR_PHY_ADC_CTL
Definition: ar9002_phy.h:67
static int ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan)
void __asmcall int val
Definition: setjmp.h:12
static const struct ath9k_percal_data adc_gain_cal_multi_sample
#define AR9285_RF2G5_IC50TX
Definition: reg.h:1335
#define AR_PHY_PARALLEL_CAL_ENABLE
Definition: ar9002_phy.h:554
#define AR9285_AN_RF2G8_PADRVGN2TAB0
Definition: reg.h:1374
#define IS_CHAN_B(_c)
Definition: ath5k.h:660
#define AR9280_TX_GAIN_TABLE_SIZE
Definition: eeprom.h:183
static void ar9285_hw_pa_cal(struct ath_hw *ah, int is_reset)
static void ar9002_hw_adc_gaincal_collect(struct ath_hw *ah)
#define AR_PHY_TX_GAIN_TBL1
Definition: ar9002_phy.h:499
#define AR9285_AN_RF2G1_PDPADRV1
Definition: reg.h:1285
void(* calPostProc)(struct ath_hw *, u8)
Definition: calib.h:85
void ath9k_hw_start_nfcal(struct ath_hw *ah, int update)
Definition: ath9k_calib.c:208
#define IS_CHAN_2GHZ(_c)
Definition: hw.h:362
#define AR_PHY_CL_CAL_CTL
Definition: ar9002_phy.h:552
#define AR9285_AN_RF2G1_PDPADRV2
Definition: reg.h:1287
#define MS(_v, _f)
Definition: hw.h:103
#define AR_PHY_TX_GAIN_CLC
Definition: phy.h:32
#define AR9285_AN_RF2G1_PDPAOUT
Definition: reg.h:1289
#define REG_CLR_BIT(_a, _r, _f)
Definition: hw.h:110
#define AR_PHY_CLC_I0_S
Definition: phy.h:39
void(* init_cal_settings)(struct ath_hw *ah)
Definition: hw.h:553
static void ar9002_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
#define REGWRITE_BUFFER_FLUSH(_ah)
Definition: hw.h:96
FILE_SECBOOT(FORBIDDEN)
int32_t CalValid
Definition: hw.h:336
static void ar9002_hw_adc_gaincal_calibrate(struct ath_hw *ah, u8 numChains)
#define AR_PHY_TURBO
Definition: ar9002_phy.h:26
struct ath9k_cal_list * calNext
Definition: calib.h:91
#define AR9285_RF2G5
Definition: reg.h:1334
#define AR_PHY_CLC_Q0
Definition: phy.h:40
#define AR_PHY_CALMODE
Definition: ar9002_phy.h:374
struct ath_hw_private_ops - callbacks used internally by hardware code
Definition: hw.h:551
#define AR9285_AN_RF2G7_PADRVGN2TAB0
Definition: reg.h:1370
#define AR_SREV_9100(ah)
Definition: reg.h:811
static void ar9002_hw_setup_calibration(struct ath_hw *ah, struct ath9k_cal_list *currCal)
#define AR_SREV_9285(_ah)
Definition: reg.h:830
void(* setup_calibration)(struct ath_hw *ah, struct ath9k_cal_list *currCal)
Definition: hw.h:558
#define AR9285_AN_RF2G3_PDVCCOMP
Definition: reg.h:1298
#define AR5416_EEP_TXGAIN_HIGH_POWER
Definition: eeprom.h:171
#define AR_PHY_CLC_TBL1
Definition: phy.h:37
#define OLC_FOR_AR9287_10_LATER
Definition: eeprom.h:109
static int ar9002_hw_per_calibration(struct ath_hw *ah, struct ath9k_channel *ichan __unused, u8 rxchainmask, struct ath9k_cal_list *currCal)
void ar9002_hw_attach_calib_ops(struct ath_hw *ah)
#define AR_PHY_AGC_CONTROL_CAL
Definition: reg.h:1911
#define REG_RMW_FIELD(_a, _r, _f, _v)
Definition: hw.h:104
#define AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE
Definition: ar9002_phy.h:305
static void ar9002_hw_adc_dccal_collect(struct ath_hw *ah)
u32 calNumSamples
Definition: calib.h:82
#define AR_PHY_CLC_Q0_S
Definition: phy.h:41
Definition: calib.h:71
#define AR_SREV_9287(_ah)
Definition: reg.h:835
static void ar9002_hw_olc_temp_compensation(struct ath_hw *ah)
#define AR_PHY_ADC_CTL_OFF_PWDADC
Definition: ar9002_phy.h:72
static int ar9285_hw_cl_cal(struct ath_hw *ah, struct ath9k_channel *chan)
#define AR9285_AN_RF2G9
Definition: reg.h:1378
#define AR9285_RF2G5_IC50TX_XE_SET
Definition: reg.h:1337
#define AR_PHY_CLC_I0
Definition: phy.h:38
#define INIT_CAL(_perCal)
Definition: calib.h:49
#define MIN_CAL_SAMPLES
Definition: calib.h:74
#define AR_PHY_TIMING_CTRL4(_i)
Definition: ar9002_phy.h:188
#define __unused
Declare a variable or data structure as unused.
Definition: compiler.h:573
#define AR9271_AN_RF2G3_CCOMP
Definition: reg.h:1352
void udelay(unsigned long usecs)
Delay for a fixed number of microseconds.
Definition: timer.c:61
void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan)
Definition: ath9k_calib.c:226
#define AR_PHY_AGC_CONTROL
Definition: reg.h:1910
static int ar9002_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, u8 rxchainmask, int longcal)
int8_t iCoff
Definition: hw.h:337
static const struct ath9k_percal_data adc_dc_cal_multi_sample
void(* calCollect)(struct ath_hw *)
Definition: calib.h:84
#define AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP
Definition: ar9002_phy.h:507
static void ar9002_hw_pa_cal(struct ath_hw *ah, int is_reset)
#define AR9285_AN_TOP3_PWDDAC
Definition: reg.h:1394
#define AR_PHY_TPCRG1_PD_CAL_ENABLE
Definition: ar9002_phy.h:471
#define AR_PHY_CH1_TX_PWRCTRL11
Definition: ar9002_phy.h:504
#define AR_PHY_CAL_MEAS_2(_i)
Definition: ar9002_phy.h:383
#define MAX_CAL_SAMPLES
Definition: calib.h:75
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
#define INSERT_CAL(_ahp, _perCal)
Definition: calib.h:54
#define AR_PHY_TPCRG1
Definition: ar9002_phy.h:460
#define ARRAY_SIZE(x)
Definition: efx_common.h:43
#define OLC_FOR_AR9280_20_LATER
Definition: eeprom.h:107
const struct ath9k_percal_data * calData
Definition: calib.h:89
#define AR_SREV_9285_12_OR_LATER(_ah)
Definition: reg.h:832
#define AR9285_AN_RF2G2
Definition: reg.h:1293
#define AR9285_AN_RXTXBB1_PDV2I
Definition: reg.h:1382
#define AR_PHY_AGC_CONTROL_NF
Definition: reg.h:1912
#define AR9285_AN_RXTXBB1_SPARE9
Definition: reg.h:1386
#define AR_PHY_CL_CAL_ENABLE
Definition: ar9002_phy.h:553
#define PER_MAX_LOG_COUNT
Definition: calib.h:78
#define AR_PHY_CALMODE_ADC_GAIN
Definition: ar9002_phy.h:377
unsigned int uint32_t
Definition: stdint.h:12
#define AR_PHY_CH0_TX_PWRCTRL11
Definition: ar9002_phy.h:503
#define REG_READ(_ah, _reg)
Definition: hw.h:81
#define AR9285_AN_RF2G3
Definition: reg.h:1297
#define AR9271_AN_RF2G6_OFFS
Definition: reg.h:1364
#define PER_MIN_LOG_COUNT
Definition: calib.h:77
#define AR_SREV_9285E_20(_ah)
Definition: reg.h:882
#define AR_PHY_NEW_ADC_GAIN_CORR_ENABLE
Definition: ar9002_phy.h:304
#define AR5416_MAX_CHAINS
Definition: eeprom.h:160
static void ar9002_hw_init_cal_settings(struct ath_hw *ah)
#define REG_SET_BIT(_a, _r, _f)
Definition: hw.h:108
static struct ath_hw_ops * ath9k_hw_ops(struct ath_hw *ah)
Definition: hw.h:885
#define AR9285_AN_RF2G6_CCOMP
Definition: reg.h:1359
#define AR_PHY_FC_DYN2040_EN
Definition: ar9002_phy.h:29
#define AR9285_AN_TOP3
Definition: reg.h:1391
#define BIT(nr)
Definition: ath.h:34
signed int int32_t
Definition: stdint.h:17
u32 calCountMax
Definition: calib.h:83
#define AR9285_AN_RXTXBB1_PDRXTXBB1
Definition: reg.h:1380
#define AR9285_CLCAL_REDO_THRESH
#define AR_PHY_TX_PWRCTRL_TX_GAIN_TAB_MAX
Definition: phy.h:30
int ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout)
Definition: ath9k_hw.c:95
#define AR9285_AN_RF2G7
Definition: reg.h:1367
#define REG_WRITE(_ah, _reg, _val)
Definition: hw.h:78
#define AR9285_AN_RF2G7_PWDDB
Definition: reg.h:1368
int8_t qCoff
Definition: hw.h:338
static const struct ath9k_percal_data iq_cal_single_sample
#define AR9285_AN_RXTXBB1_PDDACIF
Definition: reg.h:1384
#define AR_SREV_9271(_ah)
Definition: reg.h:854
#define AH_WAIT_TIMEOUT
Definition: hw.h:146
#define AR9285_AN_RF2G6
Definition: reg.h:1358
#define AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX
Definition: ar9002_phy.h:194
ar9002_cal_types
#define AR_PHY_NEW_ADC_DC_GAIN_CORR(_i)
Definition: ar9002_phy.h:303
static const struct ath9k_percal_data adc_dc_cal_single_sample
#define AR9285_AN_RXTXBB1
Definition: reg.h:1379
static int ar9285_hw_clc(struct ath_hw *ah, struct ath9k_channel *chan)
#define AR_PHY_CAL_MEAS_1(_i)
Definition: ar9002_phy.h:382
#define AR9285_AN_RF2G6_OFFS
Definition: reg.h:1361
#define AR_PHY_TX_PWRCTRL_PD_AVG_OUT
Definition: ar9002_phy.h:477
#define AR_PHY_TX_GAIN_CLC_S
Definition: phy.h:33
#define AR9285_AN_RF2G8
Definition: reg.h:1373
int ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan)
Definition: ath9k_calib.c:348
uint8_t ah
Definition: registers.h:85
static void ar9002_hw_adc_dccal_calibrate(struct ath_hw *ah, u8 numChains)
#define AR_PHY_TX_GAIN
Definition: ar9002_phy.h:500
#define AR_SREV_9160_10_OR_LATER(_ah)
Definition: reg.h:818
#define AR_PHY_TX_PWRCTRL7
Definition: ar9002_phy.h:485
#define AR9285_AN_TOP2
Definition: reg.h:1389
#define IS_CHAN_HT20(_c)
Definition: hw.h:371
static struct ath_hw_private_ops * ath9k_hw_private_ops(struct ath_hw *ah)
Definition: hw.h:880
#define AR_PHY_TIMING_CTRL4_DO_CAL
Definition: ar9002_phy.h:196
uint16_t offset
Offset to command line.
Definition: bzimage.h:8
#define AR9285_AN_RF2G1
Definition: reg.h:1282
#define DBG(...)
Print a debugging message.
Definition: compiler.h:498
uint16_t supported
Bitmask of supported option values.
Definition: ena.h:12
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)
void ath9k_hw_reset_calibration(struct ath_hw *ah, struct ath9k_cal_list *currCal)
Definition: ath9k_calib.c:155
static const struct ath9k_percal_data adc_gain_cal_single_sample
static void ar9002_hw_iqcal_collect(struct ath_hw *ah)
#define NULL
NULL pointer (VOID *)
Definition: Base.h:322
#define AR_PHY_CAL_MEAS_0(_i)
Definition: ar9002_phy.h:381
enum ath9k_cal_state calState
Definition: calib.h:90
uint8_t u8
Definition: stdint.h:20
uint32_t u32
Definition: stdint.h:24
#define MAX_PACAL_SKIPCOUNT
Definition: calib.h:101
int(* init_cal)(struct ath_hw *ah, struct ath9k_channel *chan)
Definition: hw.h:554
#define ENABLE_REGWRITE_BUFFER(_ah)
Definition: hw.h:90
#define DBG2(...)
Definition: compiler.h:515
#define AR_PHY_CALMODE_IQ
Definition: ar9002_phy.h:376
#define AR_PHY_AGC_CONTROL_FLTR_CAL
Definition: reg.h:1915
#define AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF
Definition: ar9002_phy.h:189