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 #include "hw.h"
21 #include "hw-ops.h"
22 #include "ar9002_phy.h"
23 
24 #define AR9285_CLCAL_REDO_THRESH 1
25 
30 };
31 
33  struct ath9k_channel *chan,
34  enum ar9002_cal_types cal_type)
35 {
36  int supported = 0;
37  switch (ah->supp_cals & cal_type) {
38  case IQ_MISMATCH_CAL:
39  /* Run IQ Mismatch for non-CCK only */
40  if (!IS_CHAN_B(chan))
41  supported = 1;
42  break;
43  case ADC_GAIN_CAL:
44  case ADC_DC_CAL:
45  /* Run ADC Gain Cal for non-CCK & non 2GHz-HT20 only */
46  if (!IS_CHAN_B(chan) &&
47  !(IS_CHAN_2GHZ(chan) && IS_CHAN_HT20(chan)))
48  supported = 1;
49  break;
50  }
51  return supported;
52 }
53 
55  struct ath9k_cal_list *currCal)
56 {
59  currCal->calData->calCountMax);
60 
61  switch (currCal->calData->calType) {
62  case IQ_MISMATCH_CAL:
64  DBG2("ath9k: "
65  "starting IQ Mismatch Calibration\n");
66  break;
67  case ADC_GAIN_CAL:
69  DBG2("ath9k: "
70  "starting ADC Gain Calibration\n");
71  break;
72  case ADC_DC_CAL:
74  DBG2("ath9k: "
75  "starting ADC DC Calibration\n");
76  break;
77  }
78 
81 }
82 
83 static int ar9002_hw_per_calibration(struct ath_hw *ah,
84  struct ath9k_channel *ichan __unused,
85  u8 rxchainmask,
86  struct ath9k_cal_list *currCal)
87 {
88  struct ath9k_hw_cal_data *caldata = ah->caldata;
89  int iscaldone = 0;
90 
91  if (currCal->calState == CAL_RUNNING) {
92  if (!(REG_READ(ah, AR_PHY_TIMING_CTRL4(0)) &
94 
95  currCal->calData->calCollect(ah);
96  ah->cal_samples++;
97 
98  if (ah->cal_samples >=
99  currCal->calData->calNumSamples) {
100  int i, numChains = 0;
101  for (i = 0; i < AR5416_MAX_CHAINS; i++) {
102  if (rxchainmask & (1 << i))
103  numChains++;
104  }
105 
106  currCal->calData->calPostProc(ah, numChains);
107  caldata->CalValid |= currCal->calData->calType;
108  currCal->calState = CAL_DONE;
109  iscaldone = 1;
110  } else {
112  }
113  }
114  } else if (!(caldata->CalValid & currCal->calData->calType)) {
115  ath9k_hw_reset_calibration(ah, currCal);
116  }
117 
118  return iscaldone;
119 }
120 
121 static void ar9002_hw_iqcal_collect(struct ath_hw *ah)
122 {
123  int i;
124 
125  for (i = 0; i < AR5416_MAX_CHAINS; i++) {
126  ah->totalPowerMeasI[i] +=
128  ah->totalPowerMeasQ[i] +=
130  ah->totalIqCorrMeas[i] +=
132  DBG2("ath9k: "
133  "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
134  ah->cal_samples, i, ah->totalPowerMeasI[i],
135  ah->totalPowerMeasQ[i],
136  ah->totalIqCorrMeas[i]);
137  }
138 }
139 
141 {
142  int i;
143 
144  for (i = 0; i < AR5416_MAX_CHAINS; i++) {
145  ah->totalAdcIOddPhase[i] +=
147  ah->totalAdcIEvenPhase[i] +=
149  ah->totalAdcQOddPhase[i] +=
151  ah->totalAdcQEvenPhase[i] +=
153 
154  DBG2("ath9k: "
155  "%d: Chn %d oddi=0x%08x; eveni=0x%08x; oddq=0x%08x; evenq=0x%08x;\n",
156  ah->cal_samples, i,
157  ah->totalAdcIOddPhase[i],
158  ah->totalAdcIEvenPhase[i],
159  ah->totalAdcQOddPhase[i],
160  ah->totalAdcQEvenPhase[i]);
161  }
162 }
163 
165 {
166  int i;
167 
168  for (i = 0; i < AR5416_MAX_CHAINS; i++) {
169  ah->totalAdcDcOffsetIOddPhase[i] +=
171  ah->totalAdcDcOffsetIEvenPhase[i] +=
173  ah->totalAdcDcOffsetQOddPhase[i] +=
175  ah->totalAdcDcOffsetQEvenPhase[i] +=
177 
178  DBG2("ath9k: "
179  "%d: Chn %d oddi=0x%08x; eveni=0x%08x; oddq=0x%08x; evenq=0x%08x;\n",
180  ah->cal_samples, i,
181  ah->totalAdcDcOffsetIOddPhase[i],
182  ah->totalAdcDcOffsetIEvenPhase[i],
183  ah->totalAdcDcOffsetQOddPhase[i],
184  ah->totalAdcDcOffsetQEvenPhase[i]);
185  }
186 }
187 
188 static void ar9002_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
189 {
190  u32 powerMeasQ, powerMeasI, iqCorrMeas;
191  u32 qCoffDenom, iCoffDenom;
193  int iqCorrNeg, i;
194 
195  for (i = 0; i < numChains; i++) {
196  powerMeasI = ah->totalPowerMeasI[i];
197  powerMeasQ = ah->totalPowerMeasQ[i];
198  iqCorrMeas = ah->totalIqCorrMeas[i];
199 
200  DBG2("ath9k: "
201  "Starting IQ Cal and Correction for Chain %d\n",
202  i);
203 
204  DBG2("ath9k: "
205  "Orignal: Chn %diq_corr_meas = 0x%08x\n",
206  i, ah->totalIqCorrMeas[i]);
207 
208  iqCorrNeg = 0;
209 
210  if (iqCorrMeas > 0x80000000) {
211  iqCorrMeas = (0xffffffff - iqCorrMeas) + 1;
212  iqCorrNeg = 1;
213  }
214 
215  DBG2("ath9k: "
216  "Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI);
217  DBG2("ath9k: "
218  "Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ);
219  DBG2("ath9k: iqCorrNeg is 0x%08x\n",
220  iqCorrNeg);
221 
222  iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128;
223  qCoffDenom = powerMeasQ / 64;
224 
225  if ((powerMeasQ != 0) && (iCoffDenom != 0) &&
226  (qCoffDenom != 0)) {
227  iCoff = iqCorrMeas / iCoffDenom;
228  qCoff = powerMeasI / qCoffDenom - 64;
229  DBG2("ath9k: "
230  "Chn %d iCoff = 0x%08x\n", i, iCoff);
231  DBG2("ath9k: "
232  "Chn %d qCoff = 0x%08x\n", i, qCoff);
233 
234  iCoff = iCoff & 0x3f;
235  DBG2("ath9k: "
236  "New: Chn %d iCoff = 0x%08x\n", i, iCoff);
237  if (iqCorrNeg == 0x0)
238  iCoff = 0x40 - iCoff;
239 
240  if (qCoff > 15)
241  qCoff = 15;
242  else if (qCoff <= -16)
243  qCoff = -16;
244 
245  DBG2("ath9k: "
246  "Chn %d : iCoff = 0x%x qCoff = 0x%x\n",
247  i, iCoff, qCoff);
248 
251  iCoff);
254  qCoff);
255  DBG2("ath9k: "
256  "IQ Cal and Correction done for Chain %d\n",
257  i);
258  }
259  }
260 
263 }
264 
265 static void ar9002_hw_adc_gaincal_calibrate(struct ath_hw *ah, u8 numChains)
266 {
267  u32 iOddMeasOffset, iEvenMeasOffset, qOddMeasOffset, qEvenMeasOffset;
268  u32 qGainMismatch, iGainMismatch, val, i;
269 
270  for (i = 0; i < numChains; i++) {
271  iOddMeasOffset = ah->totalAdcIOddPhase[i];
272  iEvenMeasOffset = ah->totalAdcIEvenPhase[i];
273  qOddMeasOffset = ah->totalAdcQOddPhase[i];
274  qEvenMeasOffset = ah->totalAdcQEvenPhase[i];
275 
276  DBG2("ath9k: "
277  "Starting ADC Gain Cal for Chain %d\n", i);
278 
279  DBG2("ath9k: "
280  "Chn %d pwr_meas_odd_i = 0x%08x\n", i,
281  iOddMeasOffset);
282  DBG2("ath9k: "
283  "Chn %d pwr_meas_even_i = 0x%08x\n", i,
284  iEvenMeasOffset);
285  DBG2("ath9k: "
286  "Chn %d pwr_meas_odd_q = 0x%08x\n", i,
287  qOddMeasOffset);
288  DBG2("ath9k: "
289  "Chn %d pwr_meas_even_q = 0x%08x\n", i,
290  qEvenMeasOffset);
291 
292  if (iOddMeasOffset != 0 && qEvenMeasOffset != 0) {
293  iGainMismatch =
294  ((iEvenMeasOffset * 32) /
295  iOddMeasOffset) & 0x3f;
296  qGainMismatch =
297  ((qOddMeasOffset * 32) /
298  qEvenMeasOffset) & 0x3f;
299 
300  DBG2("ath9k: "
301  "Chn %d gain_mismatch_i = 0x%08x\n", i,
302  iGainMismatch);
303  DBG2("ath9k: "
304  "Chn %d gain_mismatch_q = 0x%08x\n", i,
305  qGainMismatch);
306 
308  val &= 0xfffff000;
309  val |= (qGainMismatch) | (iGainMismatch << 6);
311 
312  DBG2("ath9k: "
313  "ADC Gain Cal done for Chain %d\n", i);
314  }
315  }
316 
320 }
321 
322 static void ar9002_hw_adc_dccal_calibrate(struct ath_hw *ah, u8 numChains)
323 {
324  u32 iOddMeasOffset, iEvenMeasOffset, val, i;
325  int32_t qOddMeasOffset, qEvenMeasOffset, qDcMismatch, iDcMismatch;
326  const struct ath9k_percal_data *calData =
327  ah->cal_list_curr->calData;
328  u32 numSamples =
329  (1 << (calData->calCountMax + 5)) * calData->calNumSamples;
330 
331  for (i = 0; i < numChains; i++) {
332  iOddMeasOffset = ah->totalAdcDcOffsetIOddPhase[i];
333  iEvenMeasOffset = ah->totalAdcDcOffsetIEvenPhase[i];
334  qOddMeasOffset = ah->totalAdcDcOffsetQOddPhase[i];
335  qEvenMeasOffset = ah->totalAdcDcOffsetQEvenPhase[i];
336 
337  DBG2("ath9k: "
338  "Starting ADC DC Offset Cal for Chain %d\n", i);
339 
340  DBG2("ath9k: "
341  "Chn %d pwr_meas_odd_i = %d\n", i,
342  iOddMeasOffset);
343  DBG2("ath9k: "
344  "Chn %d pwr_meas_even_i = %d\n", i,
345  iEvenMeasOffset);
346  DBG2("ath9k: "
347  "Chn %d pwr_meas_odd_q = %d\n", i,
348  qOddMeasOffset);
349  DBG2("ath9k: "
350  "Chn %d pwr_meas_even_q = %d\n", i,
351  qEvenMeasOffset);
352 
353  iDcMismatch = (((iEvenMeasOffset - iOddMeasOffset) * 2) /
354  numSamples) & 0x1ff;
355  qDcMismatch = (((qOddMeasOffset - qEvenMeasOffset) * 2) /
356  numSamples) & 0x1ff;
357 
358  DBG2("ath9k: "
359  "Chn %d dc_offset_mismatch_i = 0x%08x\n", i,
360  iDcMismatch);
361  DBG2("ath9k: "
362  "Chn %d dc_offset_mismatch_q = 0x%08x\n", i,
363  qDcMismatch);
364 
366  val &= 0xc0000fff;
367  val |= (qDcMismatch << 12) | (iDcMismatch << 21);
369 
370  DBG2("ath9k: "
371  "ADC DC Offset Cal done for Chain %d\n", i);
372  }
373 
377 }
378 
380 {
381  u32 rddata;
382  int32_t delta, currPDADC, slope;
383 
384  rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4);
385  currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT);
386 
387  if (ah->initPDADC == 0 || currPDADC == 0) {
388  /*
389  * Zero value indicates that no frames have been transmitted
390  * yet, can't do temperature compensation until frames are
391  * transmitted.
392  */
393  return;
394  } else {
395  slope = ah->eep_ops->get_eeprom(ah, EEP_TEMPSENSE_SLOPE);
396 
397  if (slope == 0) { /* to avoid divide by zero case */
398  delta = 0;
399  } else {
400  delta = ((currPDADC - ah->initPDADC)*4) / slope;
401  }
406  }
407 }
408 
410 {
411  u32 rddata, i;
412  int delta, currPDADC, regval;
413 
414  rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4);
415  currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT);
416 
417  if (ah->initPDADC == 0 || currPDADC == 0)
418  return;
419 
420  if (ah->eep_ops->get_eeprom(ah, EEP_DAC_HPWR_5G))
421  delta = (currPDADC - ah->initPDADC + 4) / 8;
422  else
423  delta = (currPDADC - ah->initPDADC + 5) / 10;
424 
425  if (delta != ah->PDADCdelta) {
426  ah->PDADCdelta = delta;
427  for (i = 1; i < AR9280_TX_GAIN_TABLE_SIZE; i++) {
428  regval = ah->originalGain[i] - delta;
429  if (regval < 0)
430  regval = 0;
431 
433  AR_PHY_TX_GAIN_TBL1 + i * 4,
434  AR_PHY_TX_GAIN, regval);
435  }
436  }
437 }
438 
439 static void ar9271_hw_pa_cal(struct ath_hw *ah, int is_reset)
440 {
441  u32 regVal;
442  unsigned int i;
443  u32 regList[][2] = {
444  { 0x786c, 0 },
445  { 0x7854, 0 },
446  { 0x7820, 0 },
447  { 0x7824, 0 },
448  { 0x7868, 0 },
449  { 0x783c, 0 },
450  { 0x7838, 0 } ,
451  { 0x7828, 0 } ,
452  };
453 
454  for (i = 0; i < ARRAY_SIZE(regList); i++)
455  regList[i][1] = REG_READ(ah, regList[i][0]);
456 
457  regVal = REG_READ(ah, 0x7834);
458  regVal &= (~(0x1));
459  REG_WRITE(ah, 0x7834, regVal);
460  regVal = REG_READ(ah, 0x9808);
461  regVal |= (0x1 << 27);
462  REG_WRITE(ah, 0x9808, regVal);
463 
464  /* 786c,b23,1, pwddac=1 */
466  /* 7854, b5,1, pdrxtxbb=1 */
468  /* 7854, b7,1, pdv2i=1 */
470  /* 7854, b8,1, pddacinterface=1 */
472  /* 7824,b12,0, offcal=0 */
474  /* 7838, b1,0, pwddb=0 */
476  /* 7820,b11,0, enpacal=0 */
478  /* 7820,b25,1, pdpadrv1=0 */
480  /* 7820,b24,0, pdpadrv2=0 */
482  /* 7820,b23,0, pdpaout=0 */
484  /* 783c,b14-16,7, padrvgn2tab_0=7 */
486  /*
487  * 7838,b29-31,0, padrvgn1tab_0=0
488  * does not matter since we turn it off
489  */
491 
493 
494  /* Set:
495  * localmode=1,bmode=1,bmoderxtx=1,synthon=1,
496  * txon=1,paon=1,oscon=1,synthon_force=1
497  */
498  REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0);
499  udelay(30);
501 
502  /* find off_6_1; */
503  for (i = 6; i > 0; i--) {
504  regVal = REG_READ(ah, 0x7834);
505  regVal |= (1 << (20 + i));
506  REG_WRITE(ah, 0x7834, regVal);
507  udelay(1);
508  /* regVal = REG_READ(ah, 0x7834); */
509  regVal &= (~(0x1 << (20 + i)));
510  regVal |= (MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9)
511  << (20 + i));
512  REG_WRITE(ah, 0x7834, regVal);
513  }
514 
515  regVal = (regVal >> 20) & 0x7f;
516 
517  /* Update PA cal info */
518  if ((!is_reset) && ((unsigned int)ah->pacal_info.prev_offset == regVal)) {
519  if (ah->pacal_info.max_skipcount < MAX_PACAL_SKIPCOUNT)
520  ah->pacal_info.max_skipcount =
521  2 * ah->pacal_info.max_skipcount;
522  ah->pacal_info.skipcount = ah->pacal_info.max_skipcount;
523  } else {
524  ah->pacal_info.max_skipcount = 1;
525  ah->pacal_info.skipcount = 0;
526  ah->pacal_info.prev_offset = regVal;
527  }
528 
530 
531  regVal = REG_READ(ah, 0x7834);
532  regVal |= 0x1;
533  REG_WRITE(ah, 0x7834, regVal);
534  regVal = REG_READ(ah, 0x9808);
535  regVal &= (~(0x1 << 27));
536  REG_WRITE(ah, 0x9808, regVal);
537 
538  for (i = 0; i < ARRAY_SIZE(regList); i++)
539  REG_WRITE(ah, regList[i][0], regList[i][1]);
540 
542 }
543 
544 static inline void ar9285_hw_pa_cal(struct ath_hw *ah, int is_reset)
545 {
546  u32 regVal;
547  unsigned int i;
548  int offset, offs_6_1, offs_0;
549  u32 ccomp_org, reg_field;
550  u32 regList[][2] = {
551  { 0x786c, 0 },
552  { 0x7854, 0 },
553  { 0x7820, 0 },
554  { 0x7824, 0 },
555  { 0x7868, 0 },
556  { 0x783c, 0 },
557  { 0x7838, 0 },
558  };
559 
560  DBG2("ath9k: Running PA Calibration\n");
561 
562  /* PA CAL is not needed for high power solution */
563  if (ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE) ==
565  return;
566 
567  for (i = 0; i < ARRAY_SIZE(regList); i++)
568  regList[i][1] = REG_READ(ah, regList[i][0]);
569 
570  regVal = REG_READ(ah, 0x7834);
571  regVal &= (~(0x1));
572  REG_WRITE(ah, 0x7834, regVal);
573  regVal = REG_READ(ah, 0x9808);
574  regVal |= (0x1 << 27);
575  REG_WRITE(ah, 0x9808, regVal);
576 
591 
592  REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0);
593  udelay(30);
596 
597  for (i = 6; i > 0; i--) {
598  regVal = REG_READ(ah, 0x7834);
599  regVal |= (1 << (19 + i));
600  REG_WRITE(ah, 0x7834, regVal);
601  udelay(1);
602  regVal = REG_READ(ah, 0x7834);
603  regVal &= (~(0x1 << (19 + i)));
604  reg_field = MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9);
605  regVal |= (reg_field << (19 + i));
606  REG_WRITE(ah, 0x7834, regVal);
607  }
608 
610  udelay(1);
615 
616  offset = (offs_6_1<<1) | offs_0;
617  offset = offset - 0;
618  offs_6_1 = offset>>1;
619  offs_0 = offset & 1;
620 
621  if ((!is_reset) && (ah->pacal_info.prev_offset == offset)) {
622  if (ah->pacal_info.max_skipcount < MAX_PACAL_SKIPCOUNT)
623  ah->pacal_info.max_skipcount =
624  2 * ah->pacal_info.max_skipcount;
625  ah->pacal_info.skipcount = ah->pacal_info.max_skipcount;
626  } else {
627  ah->pacal_info.max_skipcount = 1;
628  ah->pacal_info.skipcount = 0;
629  ah->pacal_info.prev_offset = offset;
630  }
631 
634 
635  regVal = REG_READ(ah, 0x7834);
636  regVal |= 0x1;
637  REG_WRITE(ah, 0x7834, regVal);
638  regVal = REG_READ(ah, 0x9808);
639  regVal &= (~(0x1 << 27));
640  REG_WRITE(ah, 0x9808, regVal);
641 
642  for (i = 0; i < ARRAY_SIZE(regList); i++)
643  REG_WRITE(ah, regList[i][0], regList[i][1]);
644 
646 }
647 
648 static void ar9002_hw_pa_cal(struct ath_hw *ah, int is_reset)
649 {
650  if (AR_SREV_9271(ah)) {
651  if (is_reset || !ah->pacal_info.skipcount)
652  ar9271_hw_pa_cal(ah, is_reset);
653  else
654  ah->pacal_info.skipcount--;
655  } else if (AR_SREV_9285_12_OR_LATER(ah)) {
656  if (is_reset || !ah->pacal_info.skipcount)
657  ar9285_hw_pa_cal(ah, is_reset);
658  else
659  ah->pacal_info.skipcount--;
660  }
661 }
662 
664 {
667  else if (OLC_FOR_AR9280_20_LATER)
669 }
670 
671 static int ar9002_hw_calibrate(struct ath_hw *ah,
672  struct ath9k_channel *chan,
673  u8 rxchainmask,
674  int longcal)
675 {
676  int iscaldone = 1;
677  struct ath9k_cal_list *currCal = ah->cal_list_curr;
678  int nfcal, nfcal_pending = 0;
679 
681  if (ah->caldata)
682  nfcal_pending = ah->caldata->nfcal_pending;
683 
684  if (currCal && !nfcal &&
685  (currCal->calState == CAL_RUNNING ||
686  currCal->calState == CAL_WAITING)) {
687  iscaldone = ar9002_hw_per_calibration(ah, chan,
688  rxchainmask, currCal);
689  if (iscaldone) {
690  ah->cal_list_curr = currCal = currCal->calNext;
691 
692  if (currCal->calState == CAL_WAITING) {
693  iscaldone = 0;
694  ath9k_hw_reset_calibration(ah, currCal);
695  }
696  }
697  }
698 
699  /* Do NF cal only at longer intervals */
700  if (longcal || nfcal_pending) {
701  /*
702  * Get the value from the previous NF cal and update
703  * history buffer.
704  */
705  if (ath9k_hw_getnf(ah, chan)) {
706  /*
707  * Load the NF from history buffer of the current
708  * channel.
709  * NF is slow time-variant, so it is OK to use a
710  * historical value.
711  */
712  ath9k_hw_loadnf(ah, ah->curchan);
713  }
714 
715  if (longcal) {
717  /* Do periodic PAOffset Cal */
718  ar9002_hw_pa_cal(ah, 0);
720  }
721  }
722 
723  return iscaldone;
724 }
725 
726 /* Carrier leakage Calibration fix */
727 static int ar9285_hw_cl_cal(struct ath_hw *ah, struct ath9k_channel *chan)
728 {
730  if (IS_CHAN_HT20(chan)) {
739  DBG("ath9k: "
740  "offset calibration failed to complete in 1ms; noisy environment?\n");
741  return 0;
742  }
746  }
752  0, AH_WAIT_TIMEOUT)) {
753  DBG("ath9k: "
754  "offset calibration failed to complete in 1ms; noisy environment?\n");
755  return 0;
756  }
757 
761 
762  return 1;
763 }
764 
765 static int ar9285_hw_clc(struct ath_hw *ah, struct ath9k_channel *chan)
766 {
767  unsigned int i;
768  uint32_t txgain_max;
769  uint32_t clc_gain, gain_mask = 0, clc_num = 0;
770  uint32_t reg_clc_I0, reg_clc_Q0;
771  uint32_t i0_num = 0;
772  uint32_t q0_num = 0;
773  uint32_t total_num = 0;
774  uint32_t reg_rf2g5_org;
775  int retv = 1;
776 
777  if (!(ar9285_hw_cl_cal(ah, chan)))
778  return 0;
779 
780  txgain_max = MS(REG_READ(ah, AR_PHY_TX_PWRCTRL7),
782 
783  for (i = 0; i < (txgain_max+1); i++) {
784  clc_gain = (REG_READ(ah, (AR_PHY_TX_GAIN_TBL1+(i<<2))) &
786  if (!(gain_mask & (1 << clc_gain))) {
787  gain_mask |= (1 << clc_gain);
788  clc_num++;
789  }
790  }
791 
792  for (i = 0; i < clc_num; i++) {
793  reg_clc_I0 = (REG_READ(ah, (AR_PHY_CLC_TBL1 + (i << 2)))
795  reg_clc_Q0 = (REG_READ(ah, (AR_PHY_CLC_TBL1 + (i << 2)))
797  if (reg_clc_I0 == 0)
798  i0_num++;
799 
800  if (reg_clc_Q0 == 0)
801  q0_num++;
802  }
803  total_num = i0_num + q0_num;
804  if (total_num > AR9285_CLCAL_REDO_THRESH) {
805  reg_rf2g5_org = REG_READ(ah, AR9285_RF2G5);
806  if (AR_SREV_9285E_20(ah)) {
808  (reg_rf2g5_org & AR9285_RF2G5_IC50TX) |
810  } else {
812  (reg_rf2g5_org & AR9285_RF2G5_IC50TX) |
814  }
815  retv = ar9285_hw_cl_cal(ah, chan);
816  REG_WRITE(ah, AR9285_RF2G5, reg_rf2g5_org);
817  }
818  return retv;
819 }
820 
821 static int ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan)
822 {
823  if (AR_SREV_9271(ah)) {
824  if (!ar9285_hw_cl_cal(ah, chan))
825  return 0;
826  } else if (AR_SREV_9285(ah) && AR_SREV_9285_12_OR_LATER(ah)) {
827  if (!ar9285_hw_clc(ah, chan))
828  return 0;
829  } else {
836  }
837 
838  /* Calibrate the AGC */
842 
843  /* Poll for offset calibration complete */
846  0, AH_WAIT_TIMEOUT)) {
847  DBG("ath9k: "
848  "offset calibration failed to complete in 1ms; noisy environment?\n");
849  return 0;
850  }
851 
858  }
859  }
860 
861  /* Do PA Calibration */
862  ar9002_hw_pa_cal(ah, 1);
863 
864  /* Do NF Calibration after DC offset and other calibrations */
866 
867  if (ah->caldata)
868  ah->caldata->nfcal_pending = 1;
869 
870  ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL;
871 
872  /* Enable IQ, ADC Gain and ADC DC offset CALs */
874  ah->supp_cals = IQ_MISMATCH_CAL;
875 
877  ah->supp_cals |= ADC_GAIN_CAL | ADC_DC_CAL;
878 
879  if (AR_SREV_9287(ah))
880  ah->supp_cals &= ~ADC_GAIN_CAL;
881 
883  INIT_CAL(&ah->adcgain_caldata);
884  INSERT_CAL(ah, &ah->adcgain_caldata);
885  DBG2("ath9k: "
886  "enabling ADC Gain Calibration.\n");
887  }
888 
890  INIT_CAL(&ah->adcdc_caldata);
891  INSERT_CAL(ah, &ah->adcdc_caldata);
892  DBG2("ath9k: "
893  "enabling ADC DC Calibration.\n");
894  }
895 
897  INIT_CAL(&ah->iq_caldata);
898  INSERT_CAL(ah, &ah->iq_caldata);
899  DBG2("ath9k: "
900  "enabling IQ Calibration.\n");
901  }
902 
903  ah->cal_list_curr = ah->cal_list;
904 
905  if (ah->cal_list_curr)
906  ath9k_hw_reset_calibration(ah, ah->cal_list_curr);
907  }
908 
909  if (ah->caldata)
910  ah->caldata->CalValid = 0;
911 
912  return 1;
913 }
914 
915 static const struct ath9k_percal_data iq_cal_multi_sample = {
921 };
928 };
930  ADC_GAIN_CAL,
935 };
937  ADC_GAIN_CAL,
942 };
944  ADC_DC_CAL,
949 };
951  ADC_DC_CAL,
956 };
957 
959 {
960  if (AR_SREV_9100(ah)) {
961  ah->iq_caldata.calData = &iq_cal_multi_sample;
962  ah->supp_cals = IQ_MISMATCH_CAL;
963  return;
964  }
965 
968  ah->iq_caldata.calData = &iq_cal_single_sample;
969  ah->adcgain_caldata.calData =
971  ah->adcdc_caldata.calData =
973  } else {
974  ah->iq_caldata.calData = &iq_cal_multi_sample;
975  ah->adcgain_caldata.calData =
977  ah->adcdc_caldata.calData =
979  }
980  ah->supp_cals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL;
981 
982  if (AR_SREV_9287(ah))
983  ah->supp_cals &= ~ADC_GAIN_CAL;
984  }
985 }
986 
988 {
989  struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
990  struct ath_hw_ops *ops = ath9k_hw_ops(ah);
991 
993  priv_ops->init_cal = ar9002_hw_init_cal;
995 
997 }
static const struct ath9k_percal_data iq_cal_multi_sample
#define AR_PHY_CAL_MEAS_3(_i)
Definition: ar9002_phy.h:383
static void ar9271_hw_pa_cal(struct ath_hw *ah, int is_reset)
#define AR9285_AN_RF2G2_OFFCAL
Definition: reg.h:1293
#define AR_SREV_9287_11_OR_LATER(_ah)
Definition: reg.h:836
#define AR_PHY_TIMING_CTRL4_IQCORR_ENABLE
Definition: ar9002_phy.h:192
Definition: hw.h:656
#define AR9285_AN_RF2G1_ENPACAL
Definition: reg.h:1282
static void ar9280_hw_olc_temp_compensation(struct ath_hw *ah)
#define AR_PHY_CALMODE_ADC_DC_PER
Definition: ar9002_phy.h:377
#define AR9285_RF2G5_IC50TX_SET
Definition: reg.h:1335
#define AR_SREV_9280_20_OR_LATER(_ah)
Definition: reg.h:824
#define AR_PHY_TX_PWRCTRL4
Definition: ar9002_phy.h:473
#define AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF
Definition: ar9002_phy.h:190
#define AR_PHY_ADC_CTL
Definition: ar9002_phy.h:66
static int ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan)
static const struct ath9k_percal_data adc_gain_cal_multi_sample
#define AR9285_RF2G5_IC50TX
Definition: reg.h:1334
#define AR_PHY_PARALLEL_CAL_ENABLE
Definition: ar9002_phy.h:553
#define AR9285_AN_RF2G8_PADRVGN2TAB0
Definition: reg.h:1373
#define IS_CHAN_B(_c)
Definition: ath5k.h:658
#define AR9280_TX_GAIN_TABLE_SIZE
Definition: eeprom.h:182
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:498
#define AR9285_AN_RF2G1_PDPADRV1
Definition: reg.h:1284
void(* calPostProc)(struct ath_hw *, u8)
Definition: calib.h:84
void ath9k_hw_start_nfcal(struct ath_hw *ah, int update)
Definition: ath9k_calib.c:206
#define IS_CHAN_2GHZ(_c)
Definition: hw.h:361
#define AR_PHY_CL_CAL_CTL
Definition: ar9002_phy.h:551
#define AR9285_AN_RF2G1_PDPADRV2
Definition: reg.h:1286
#define MS(_v, _f)
Definition: hw.h:102
#define AR_PHY_TX_GAIN_CLC
Definition: phy.h:31
#define AR9285_AN_RF2G1_PDPAOUT
Definition: reg.h:1288
#define REG_CLR_BIT(_a, _r, _f)
Definition: hw.h:109
#define AR_PHY_CLC_I0_S
Definition: phy.h:38
void(* init_cal_settings)(struct ath_hw *ah)
Definition: hw.h:552
static void ar9002_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
#define REGWRITE_BUFFER_FLUSH(_ah)
Definition: hw.h:95
int32_t CalValid
Definition: hw.h:335
static void ar9002_hw_adc_gaincal_calibrate(struct ath_hw *ah, u8 numChains)
#define AR_PHY_TURBO
Definition: ar9002_phy.h:25
struct ath9k_cal_list * calNext
Definition: calib.h:90
#define AR9285_RF2G5
Definition: reg.h:1333
#define AR_PHY_CLC_Q0
Definition: phy.h:39
#define AR_PHY_CALMODE
Definition: ar9002_phy.h:373
struct ath_hw_private_ops - callbacks used internally by hardware code
Definition: hw.h:550
#define AR9285_AN_RF2G7_PADRVGN2TAB0
Definition: reg.h:1369
#define AR_SREV_9100(ah)
Definition: reg.h:810
static void ar9002_hw_setup_calibration(struct ath_hw *ah, struct ath9k_cal_list *currCal)
#define AR_SREV_9285(_ah)
Definition: reg.h:829
void(* setup_calibration)(struct ath_hw *ah, struct ath9k_cal_list *currCal)
Definition: hw.h:557
#define AR9285_AN_RF2G3_PDVCCOMP
Definition: reg.h:1297
#define AR5416_EEP_TXGAIN_HIGH_POWER
Definition: eeprom.h:170
#define AR_PHY_CLC_TBL1
Definition: phy.h:36
#define OLC_FOR_AR9287_10_LATER
Definition: eeprom.h:108
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:1910
#define REG_RMW_FIELD(_a, _r, _f, _v)
Definition: hw.h:103
#define AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE
Definition: ar9002_phy.h:304
static void ar9002_hw_adc_dccal_collect(struct ath_hw *ah)
u32 calNumSamples
Definition: calib.h:81
#define AR_PHY_CLC_Q0_S
Definition: phy.h:40
Definition: calib.h:70
#define AR_SREV_9287(_ah)
Definition: reg.h:834
static void ar9002_hw_olc_temp_compensation(struct ath_hw *ah)
#define AR_PHY_ADC_CTL_OFF_PWDADC
Definition: ar9002_phy.h:71
static int ar9285_hw_cl_cal(struct ath_hw *ah, struct ath9k_channel *chan)
#define AR9285_AN_RF2G9
Definition: reg.h:1377
#define AR9285_RF2G5_IC50TX_XE_SET
Definition: reg.h:1336
#define AR_PHY_CLC_I0
Definition: phy.h:37
#define INIT_CAL(_perCal)
Definition: calib.h:48
#define MIN_CAL_SAMPLES
Definition: calib.h:73
#define AR_PHY_TIMING_CTRL4(_i)
Definition: ar9002_phy.h:187
#define AR9271_AN_RF2G3_CCOMP
Definition: reg.h:1351
void udelay(unsigned long usecs)
Delay for a fixed number of microseconds.
Definition: timer.c:60
void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan)
Definition: ath9k_calib.c:224
#define AR_PHY_AGC_CONTROL
Definition: reg.h:1909
static userptr_t size_t offset
Offset of the first segment within the content.
Definition: deflate.h:259
static int ar9002_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, u8 rxchainmask, int longcal)
int8_t iCoff
Definition: hw.h:336
static const struct ath9k_percal_data adc_dc_cal_multi_sample
void(* calCollect)(struct ath_hw *)
Definition: calib.h:83
#define AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP
Definition: ar9002_phy.h:506
static void ar9002_hw_pa_cal(struct ath_hw *ah, int is_reset)
#define AR9285_AN_TOP3_PWDDAC
Definition: reg.h:1393
#define AR_PHY_TPCRG1_PD_CAL_ENABLE
Definition: ar9002_phy.h:470
#define AR_PHY_CH1_TX_PWRCTRL11
Definition: ar9002_phy.h:503
#define AR_PHY_CAL_MEAS_2(_i)
Definition: ar9002_phy.h:382
#define MAX_CAL_SAMPLES
Definition: calib.h:74
struct ath_hw_ops - callbacks used by hardware code and driver code
Definition: hw.h:603
int(* calibrate)(struct ath_hw *ah, struct ath9k_channel *chan, u8 rxchainmask, int longcal)
Definition: hw.h:610
#define INSERT_CAL(_ahp, _perCal)
Definition: calib.h:53
#define AR_PHY_TPCRG1
Definition: ar9002_phy.h:459
#define ARRAY_SIZE(x)
Definition: efx_common.h:43
#define OLC_FOR_AR9280_20_LATER
Definition: eeprom.h:106
const struct ath9k_percal_data * calData
Definition: calib.h:88
#define AR_SREV_9285_12_OR_LATER(_ah)
Definition: reg.h:831
#define AR9285_AN_RF2G2
Definition: reg.h:1292
#define AR9285_AN_RXTXBB1_PDV2I
Definition: reg.h:1381
#define AR_PHY_AGC_CONTROL_NF
Definition: reg.h:1911
#define AR9285_AN_RXTXBB1_SPARE9
Definition: reg.h:1385
#define AR_PHY_CL_CAL_ENABLE
Definition: ar9002_phy.h:552
#define PER_MAX_LOG_COUNT
Definition: calib.h:77
#define AR_PHY_CALMODE_ADC_GAIN
Definition: ar9002_phy.h:376
unsigned int uint32_t
Definition: stdint.h:12
#define AR_PHY_CH0_TX_PWRCTRL11
Definition: ar9002_phy.h:502
#define REG_READ(_ah, _reg)
Definition: hw.h:80
#define AR9285_AN_RF2G3
Definition: reg.h:1296
void __asmcall int val
Definition: setjmp.h:28
#define AR9271_AN_RF2G6_OFFS
Definition: reg.h:1363
#define PER_MIN_LOG_COUNT
Definition: calib.h:76
#define AR_SREV_9285E_20(_ah)
Definition: reg.h:881
#define AR_PHY_NEW_ADC_GAIN_CORR_ENABLE
Definition: ar9002_phy.h:303
#define AR5416_MAX_CHAINS
Definition: eeprom.h:159
static void ar9002_hw_init_cal_settings(struct ath_hw *ah)
#define REG_SET_BIT(_a, _r, _f)
Definition: hw.h:107
#define __unused
Declare a variable or data structure as unused.
Definition: compiler.h:573
static struct ath_hw_ops * ath9k_hw_ops(struct ath_hw *ah)
Definition: hw.h:884
#define AR9285_AN_RF2G6_CCOMP
Definition: reg.h:1358
#define AR_PHY_FC_DYN2040_EN
Definition: ar9002_phy.h:28
#define AR9285_AN_TOP3
Definition: reg.h:1390
#define BIT(nr)
Definition: ath.h:32
signed int int32_t
Definition: stdint.h:17
u32 calCountMax
Definition: calib.h:82
#define AR9285_AN_RXTXBB1_PDRXTXBB1
Definition: reg.h:1379
#define AR9285_CLCAL_REDO_THRESH
#define AR_PHY_TX_PWRCTRL_TX_GAIN_TAB_MAX
Definition: phy.h:29
int ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout)
Definition: ath9k_hw.c:93
#define AR9285_AN_RF2G7
Definition: reg.h:1366
#define REG_WRITE(_ah, _reg, _val)
Definition: hw.h:77
#define AR9285_AN_RF2G7_PWDDB
Definition: reg.h:1367
int8_t qCoff
Definition: hw.h:337
static const struct ath9k_percal_data iq_cal_single_sample
#define AR9285_AN_RXTXBB1_PDDACIF
Definition: reg.h:1383
#define AR_SREV_9271(_ah)
Definition: reg.h:853
#define AH_WAIT_TIMEOUT
Definition: hw.h:145
#define AR9285_AN_RF2G6
Definition: reg.h:1357
#define AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX
Definition: ar9002_phy.h:193
ar9002_cal_types
#define AR_PHY_NEW_ADC_DC_GAIN_CORR(_i)
Definition: ar9002_phy.h:302
static const struct ath9k_percal_data adc_dc_cal_single_sample
#define AR9285_AN_RXTXBB1
Definition: reg.h:1378
static int ar9285_hw_clc(struct ath_hw *ah, struct ath9k_channel *chan)
#define AR_PHY_CAL_MEAS_1(_i)
Definition: ar9002_phy.h:381
#define AR9285_AN_RF2G6_OFFS
Definition: reg.h:1360
#define AR_PHY_TX_PWRCTRL_PD_AVG_OUT
Definition: ar9002_phy.h:476
#define AR_PHY_TX_GAIN_CLC_S
Definition: phy.h:32
#define AR9285_AN_RF2G8
Definition: reg.h:1372
int ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan)
Definition: ath9k_calib.c:346
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:499
#define AR_SREV_9160_10_OR_LATER(_ah)
Definition: reg.h:817
#define AR_PHY_TX_PWRCTRL7
Definition: ar9002_phy.h:484
#define AR9285_AN_TOP2
Definition: reg.h:1388
#define IS_CHAN_HT20(_c)
Definition: hw.h:370
static struct ath_hw_private_ops * ath9k_hw_private_ops(struct ath_hw *ah)
Definition: hw.h:879
#define AR_PHY_TIMING_CTRL4_DO_CAL
Definition: ar9002_phy.h:195
#define AR9285_AN_RF2G1
Definition: reg.h:1281
#define DBG(...)
Print a debugging message.
Definition: compiler.h:498
uint32_t supported
Bitmask of supported AENQ groups (device -> host)
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:153
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:321
#define AR_PHY_CAL_MEAS_0(_i)
Definition: ar9002_phy.h:380
enum ath9k_cal_state calState
Definition: calib.h:89
uint8_t u8
Definition: stdint.h:19
uint32_t u32
Definition: stdint.h:23
#define MAX_PACAL_SKIPCOUNT
Definition: calib.h:100
int(* init_cal)(struct ath_hw *ah, struct ath9k_channel *chan)
Definition: hw.h:553
#define ENABLE_REGWRITE_BUFFER(_ah)
Definition: hw.h:89
#define DBG2(...)
Definition: compiler.h:515
#define AR_PHY_CALMODE_IQ
Definition: ar9002_phy.h:375
#define AR_PHY_AGC_CONTROL_FLTR_CAL
Definition: reg.h:1914
#define AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF
Definition: ar9002_phy.h:188