ea2e7d714bdad0888e070dc61faf5acfba26ff15
[linux-2.6.git] / drivers / net / wireless / ath / ath9k / ar9002_calib.c
1 /*
2  * Copyright (c) 2008-2010 Atheros Communications Inc.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16
17 #include "hw.h"
18 #include "hw-ops.h"
19 #include "ar9002_phy.h"
20
21 #define AR9285_CLCAL_REDO_THRESH    1
22
23 enum ar9002_cal_types {
24         ADC_GAIN_CAL = BIT(0),
25         ADC_DC_CAL = BIT(1),
26         IQ_MISMATCH_CAL = BIT(2),
27 };
28
29
30 static void ar9002_hw_setup_calibration(struct ath_hw *ah,
31                                         struct ath9k_cal_list *currCal)
32 {
33         struct ath_common *common = ath9k_hw_common(ah);
34
35         REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(0),
36                       AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX,
37                       currCal->calData->calCountMax);
38
39         switch (currCal->calData->calType) {
40         case IQ_MISMATCH_CAL:
41                 REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ);
42                 ath_dbg(common, ATH_DBG_CALIBRATE,
43                         "starting IQ Mismatch Calibration\n");
44                 break;
45         case ADC_GAIN_CAL:
46                 REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_GAIN);
47                 ath_dbg(common, ATH_DBG_CALIBRATE,
48                         "starting ADC Gain Calibration\n");
49                 break;
50         case ADC_DC_CAL:
51                 REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_PER);
52                 ath_dbg(common, ATH_DBG_CALIBRATE,
53                         "starting ADC DC Calibration\n");
54                 break;
55         }
56
57         REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0),
58                     AR_PHY_TIMING_CTRL4_DO_CAL);
59 }
60
61 static bool ar9002_hw_per_calibration(struct ath_hw *ah,
62                                       struct ath9k_channel *ichan,
63                                       u8 rxchainmask,
64                                       struct ath9k_cal_list *currCal)
65 {
66         struct ath9k_hw_cal_data *caldata = ah->caldata;
67         bool iscaldone = false;
68
69         if (currCal->calState == CAL_RUNNING) {
70                 if (!(REG_READ(ah, AR_PHY_TIMING_CTRL4(0)) &
71                       AR_PHY_TIMING_CTRL4_DO_CAL)) {
72
73                         currCal->calData->calCollect(ah);
74                         ah->cal_samples++;
75
76                         if (ah->cal_samples >=
77                             currCal->calData->calNumSamples) {
78                                 int i, numChains = 0;
79                                 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
80                                         if (rxchainmask & (1 << i))
81                                                 numChains++;
82                                 }
83
84                                 currCal->calData->calPostProc(ah, numChains);
85                                 caldata->CalValid |= currCal->calData->calType;
86                                 currCal->calState = CAL_DONE;
87                                 iscaldone = true;
88                         } else {
89                                 ar9002_hw_setup_calibration(ah, currCal);
90                         }
91                 }
92         } else if (!(caldata->CalValid & currCal->calData->calType)) {
93                 ath9k_hw_reset_calibration(ah, currCal);
94         }
95
96         return iscaldone;
97 }
98
99 static void ar9002_hw_iqcal_collect(struct ath_hw *ah)
100 {
101         int i;
102
103         for (i = 0; i < AR5416_MAX_CHAINS; i++) {
104                 ah->totalPowerMeasI[i] +=
105                         REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
106                 ah->totalPowerMeasQ[i] +=
107                         REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
108                 ah->totalIqCorrMeas[i] +=
109                         (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
110                 ath_dbg(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
111                         "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
112                         ah->cal_samples, i, ah->totalPowerMeasI[i],
113                         ah->totalPowerMeasQ[i],
114                         ah->totalIqCorrMeas[i]);
115         }
116 }
117
118 static void ar9002_hw_adc_gaincal_collect(struct ath_hw *ah)
119 {
120         int i;
121
122         for (i = 0; i < AR5416_MAX_CHAINS; i++) {
123                 ah->totalAdcIOddPhase[i] +=
124                         REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
125                 ah->totalAdcIEvenPhase[i] +=
126                         REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
127                 ah->totalAdcQOddPhase[i] +=
128                         REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
129                 ah->totalAdcQEvenPhase[i] +=
130                         REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
131
132                 ath_dbg(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
133                         "%d: Chn %d oddi=0x%08x; eveni=0x%08x; oddq=0x%08x; evenq=0x%08x;\n",
134                         ah->cal_samples, i,
135                         ah->totalAdcIOddPhase[i],
136                         ah->totalAdcIEvenPhase[i],
137                         ah->totalAdcQOddPhase[i],
138                         ah->totalAdcQEvenPhase[i]);
139         }
140 }
141
142 static void ar9002_hw_adc_dccal_collect(struct ath_hw *ah)
143 {
144         int i;
145
146         for (i = 0; i < AR5416_MAX_CHAINS; i++) {
147                 ah->totalAdcDcOffsetIOddPhase[i] +=
148                         (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
149                 ah->totalAdcDcOffsetIEvenPhase[i] +=
150                         (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
151                 ah->totalAdcDcOffsetQOddPhase[i] +=
152                         (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
153                 ah->totalAdcDcOffsetQEvenPhase[i] +=
154                         (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
155
156                 ath_dbg(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
157                         "%d: Chn %d oddi=0x%08x; eveni=0x%08x; oddq=0x%08x; evenq=0x%08x;\n",
158                         ah->cal_samples, i,
159                         ah->totalAdcDcOffsetIOddPhase[i],
160                         ah->totalAdcDcOffsetIEvenPhase[i],
161                         ah->totalAdcDcOffsetQOddPhase[i],
162                         ah->totalAdcDcOffsetQEvenPhase[i]);
163         }
164 }
165
166 static void ar9002_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
167 {
168         struct ath_common *common = ath9k_hw_common(ah);
169         u32 powerMeasQ, powerMeasI, iqCorrMeas;
170         u32 qCoffDenom, iCoffDenom;
171         int32_t qCoff, iCoff;
172         int iqCorrNeg, i;
173
174         for (i = 0; i < numChains; i++) {
175                 powerMeasI = ah->totalPowerMeasI[i];
176                 powerMeasQ = ah->totalPowerMeasQ[i];
177                 iqCorrMeas = ah->totalIqCorrMeas[i];
178
179                 ath_dbg(common, ATH_DBG_CALIBRATE,
180                         "Starting IQ Cal and Correction for Chain %d\n",
181                         i);
182
183                 ath_dbg(common, ATH_DBG_CALIBRATE,
184                         "Orignal: Chn %diq_corr_meas = 0x%08x\n",
185                         i, ah->totalIqCorrMeas[i]);
186
187                 iqCorrNeg = 0;
188
189                 if (iqCorrMeas > 0x80000000) {
190                         iqCorrMeas = (0xffffffff - iqCorrMeas) + 1;
191                         iqCorrNeg = 1;
192                 }
193
194                 ath_dbg(common, ATH_DBG_CALIBRATE,
195                         "Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI);
196                 ath_dbg(common, ATH_DBG_CALIBRATE,
197                         "Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ);
198                 ath_dbg(common, ATH_DBG_CALIBRATE, "iqCorrNeg is 0x%08x\n",
199                         iqCorrNeg);
200
201                 iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128;
202                 qCoffDenom = powerMeasQ / 64;
203
204                 if ((powerMeasQ != 0) && (iCoffDenom != 0) &&
205                     (qCoffDenom != 0)) {
206                         iCoff = iqCorrMeas / iCoffDenom;
207                         qCoff = powerMeasI / qCoffDenom - 64;
208                         ath_dbg(common, ATH_DBG_CALIBRATE,
209                                 "Chn %d iCoff = 0x%08x\n", i, iCoff);
210                         ath_dbg(common, ATH_DBG_CALIBRATE,
211                                 "Chn %d qCoff = 0x%08x\n", i, qCoff);
212
213                         iCoff = iCoff & 0x3f;
214                         ath_dbg(common, ATH_DBG_CALIBRATE,
215                                 "New: Chn %d iCoff = 0x%08x\n", i, iCoff);
216                         if (iqCorrNeg == 0x0)
217                                 iCoff = 0x40 - iCoff;
218
219                         if (qCoff > 15)
220                                 qCoff = 15;
221                         else if (qCoff <= -16)
222                                 qCoff = -16;
223
224                         ath_dbg(common, ATH_DBG_CALIBRATE,
225                                 "Chn %d : iCoff = 0x%x  qCoff = 0x%x\n",
226                                 i, iCoff, qCoff);
227
228                         REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i),
229                                       AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF,
230                                       iCoff);
231                         REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i),
232                                       AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF,
233                                       qCoff);
234                         ath_dbg(common, ATH_DBG_CALIBRATE,
235                                 "IQ Cal and Correction done for Chain %d\n",
236                                 i);
237                 }
238         }
239
240         REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0),
241                     AR_PHY_TIMING_CTRL4_IQCORR_ENABLE);
242 }
243
244 static void ar9002_hw_adc_gaincal_calibrate(struct ath_hw *ah, u8 numChains)
245 {
246         struct ath_common *common = ath9k_hw_common(ah);
247         u32 iOddMeasOffset, iEvenMeasOffset, qOddMeasOffset, qEvenMeasOffset;
248         u32 qGainMismatch, iGainMismatch, val, i;
249
250         for (i = 0; i < numChains; i++) {
251                 iOddMeasOffset = ah->totalAdcIOddPhase[i];
252                 iEvenMeasOffset = ah->totalAdcIEvenPhase[i];
253                 qOddMeasOffset = ah->totalAdcQOddPhase[i];
254                 qEvenMeasOffset = ah->totalAdcQEvenPhase[i];
255
256                 ath_dbg(common, ATH_DBG_CALIBRATE,
257                         "Starting ADC Gain Cal for Chain %d\n", i);
258
259                 ath_dbg(common, ATH_DBG_CALIBRATE,
260                         "Chn %d pwr_meas_odd_i = 0x%08x\n", i,
261                         iOddMeasOffset);
262                 ath_dbg(common, ATH_DBG_CALIBRATE,
263                         "Chn %d pwr_meas_even_i = 0x%08x\n", i,
264                         iEvenMeasOffset);
265                 ath_dbg(common, ATH_DBG_CALIBRATE,
266                         "Chn %d pwr_meas_odd_q = 0x%08x\n", i,
267                         qOddMeasOffset);
268                 ath_dbg(common, ATH_DBG_CALIBRATE,
269                         "Chn %d pwr_meas_even_q = 0x%08x\n", i,
270                         qEvenMeasOffset);
271
272                 if (iOddMeasOffset != 0 && qEvenMeasOffset != 0) {
273                         iGainMismatch =
274                                 ((iEvenMeasOffset * 32) /
275                                  iOddMeasOffset) & 0x3f;
276                         qGainMismatch =
277                                 ((qOddMeasOffset * 32) /
278                                  qEvenMeasOffset) & 0x3f;
279
280                         ath_dbg(common, ATH_DBG_CALIBRATE,
281                                 "Chn %d gain_mismatch_i = 0x%08x\n", i,
282                                 iGainMismatch);
283                         ath_dbg(common, ATH_DBG_CALIBRATE,
284                                 "Chn %d gain_mismatch_q = 0x%08x\n", i,
285                                 qGainMismatch);
286
287                         val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
288                         val &= 0xfffff000;
289                         val |= (qGainMismatch) | (iGainMismatch << 6);
290                         REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
291
292                         ath_dbg(common, ATH_DBG_CALIBRATE,
293                                 "ADC Gain Cal done for Chain %d\n", i);
294                 }
295         }
296
297         REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
298                   REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
299                   AR_PHY_NEW_ADC_GAIN_CORR_ENABLE);
300 }
301
302 static void ar9002_hw_adc_dccal_calibrate(struct ath_hw *ah, u8 numChains)
303 {
304         struct ath_common *common = ath9k_hw_common(ah);
305         u32 iOddMeasOffset, iEvenMeasOffset, val, i;
306         int32_t qOddMeasOffset, qEvenMeasOffset, qDcMismatch, iDcMismatch;
307         const struct ath9k_percal_data *calData =
308                 ah->cal_list_curr->calData;
309         u32 numSamples =
310                 (1 << (calData->calCountMax + 5)) * calData->calNumSamples;
311
312         for (i = 0; i < numChains; i++) {
313                 iOddMeasOffset = ah->totalAdcDcOffsetIOddPhase[i];
314                 iEvenMeasOffset = ah->totalAdcDcOffsetIEvenPhase[i];
315                 qOddMeasOffset = ah->totalAdcDcOffsetQOddPhase[i];
316                 qEvenMeasOffset = ah->totalAdcDcOffsetQEvenPhase[i];
317
318                 ath_dbg(common, ATH_DBG_CALIBRATE,
319                         "Starting ADC DC Offset Cal for Chain %d\n", i);
320
321                 ath_dbg(common, ATH_DBG_CALIBRATE,
322                         "Chn %d pwr_meas_odd_i = %d\n", i,
323                         iOddMeasOffset);
324                 ath_dbg(common, ATH_DBG_CALIBRATE,
325                         "Chn %d pwr_meas_even_i = %d\n", i,
326                         iEvenMeasOffset);
327                 ath_dbg(common, ATH_DBG_CALIBRATE,
328                         "Chn %d pwr_meas_odd_q = %d\n", i,
329                         qOddMeasOffset);
330                 ath_dbg(common, ATH_DBG_CALIBRATE,
331                         "Chn %d pwr_meas_even_q = %d\n", i,
332                         qEvenMeasOffset);
333
334                 iDcMismatch = (((iEvenMeasOffset - iOddMeasOffset) * 2) /
335                                numSamples) & 0x1ff;
336                 qDcMismatch = (((qOddMeasOffset - qEvenMeasOffset) * 2) /
337                                numSamples) & 0x1ff;
338
339                 ath_dbg(common, ATH_DBG_CALIBRATE,
340                         "Chn %d dc_offset_mismatch_i = 0x%08x\n", i,
341                         iDcMismatch);
342                 ath_dbg(common, ATH_DBG_CALIBRATE,
343                         "Chn %d dc_offset_mismatch_q = 0x%08x\n", i,
344                         qDcMismatch);
345
346                 val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
347                 val &= 0xc0000fff;
348                 val |= (qDcMismatch << 12) | (iDcMismatch << 21);
349                 REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
350
351                 ath_dbg(common, ATH_DBG_CALIBRATE,
352                         "ADC DC Offset Cal done for Chain %d\n", i);
353         }
354
355         REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
356                   REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
357                   AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE);
358 }
359
360 static void ar9287_hw_olc_temp_compensation(struct ath_hw *ah)
361 {
362         u32 rddata;
363         int32_t delta, currPDADC, slope;
364
365         rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4);
366         currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT);
367
368         if (ah->initPDADC == 0 || currPDADC == 0) {
369                 /*
370                  * Zero value indicates that no frames have been transmitted
371                  * yet, can't do temperature compensation until frames are
372                  * transmitted.
373                  */
374                 return;
375         } else {
376                 slope = ah->eep_ops->get_eeprom(ah, EEP_TEMPSENSE_SLOPE);
377
378                 if (slope == 0) { /* to avoid divide by zero case */
379                         delta = 0;
380                 } else {
381                         delta = ((currPDADC - ah->initPDADC)*4) / slope;
382                 }
383                 REG_RMW_FIELD(ah, AR_PHY_CH0_TX_PWRCTRL11,
384                               AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta);
385                 REG_RMW_FIELD(ah, AR_PHY_CH1_TX_PWRCTRL11,
386                               AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta);
387         }
388 }
389
390 static void ar9280_hw_olc_temp_compensation(struct ath_hw *ah)
391 {
392         u32 rddata, i;
393         int delta, currPDADC, regval;
394
395         rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4);
396         currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT);
397
398         if (ah->initPDADC == 0 || currPDADC == 0)
399                 return;
400
401         if (ah->eep_ops->get_eeprom(ah, EEP_DAC_HPWR_5G))
402                 delta = (currPDADC - ah->initPDADC + 4) / 8;
403         else
404                 delta = (currPDADC - ah->initPDADC + 5) / 10;
405
406         if (delta != ah->PDADCdelta) {
407                 ah->PDADCdelta = delta;
408                 for (i = 1; i < AR9280_TX_GAIN_TABLE_SIZE; i++) {
409                         regval = ah->originalGain[i] - delta;
410                         if (regval < 0)
411                                 regval = 0;
412
413                         REG_RMW_FIELD(ah,
414                                       AR_PHY_TX_GAIN_TBL1 + i * 4,
415                                       AR_PHY_TX_GAIN, regval);
416                 }
417         }
418 }
419
420 static void ar9271_hw_pa_cal(struct ath_hw *ah, bool is_reset)
421 {
422         u32 regVal;
423         unsigned int i;
424         u32 regList[][2] = {
425                 { 0x786c, 0 },
426                 { 0x7854, 0 },
427                 { 0x7820, 0 },
428                 { 0x7824, 0 },
429                 { 0x7868, 0 },
430                 { 0x783c, 0 },
431                 { 0x7838, 0 } ,
432                 { 0x7828, 0 } ,
433         };
434
435         for (i = 0; i < ARRAY_SIZE(regList); i++)
436                 regList[i][1] = REG_READ(ah, regList[i][0]);
437
438         regVal = REG_READ(ah, 0x7834);
439         regVal &= (~(0x1));
440         REG_WRITE(ah, 0x7834, regVal);
441         regVal = REG_READ(ah, 0x9808);
442         regVal |= (0x1 << 27);
443         REG_WRITE(ah, 0x9808, regVal);
444
445         /* 786c,b23,1, pwddac=1 */
446         REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1);
447         /* 7854, b5,1, pdrxtxbb=1 */
448         REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1);
449         /* 7854, b7,1, pdv2i=1 */
450         REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1);
451         /* 7854, b8,1, pddacinterface=1 */
452         REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1);
453         /* 7824,b12,0, offcal=0 */
454         REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0);
455         /* 7838, b1,0, pwddb=0 */
456         REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0);
457         /* 7820,b11,0, enpacal=0 */
458         REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0);
459         /* 7820,b25,1, pdpadrv1=0 */
460         REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 0);
461         /* 7820,b24,0, pdpadrv2=0 */
462         REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2, 0);
463         /* 7820,b23,0, pdpaout=0 */
464         REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0);
465         /* 783c,b14-16,7, padrvgn2tab_0=7 */
466         REG_RMW_FIELD(ah, AR9285_AN_RF2G8, AR9285_AN_RF2G8_PADRVGN2TAB0, 7);
467         /*
468          * 7838,b29-31,0, padrvgn1tab_0=0
469          * does not matter since we turn it off
470          */
471         REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PADRVGN2TAB0, 0);
472
473         REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9271_AN_RF2G3_CCOMP, 0xfff);
474
475         /* Set:
476          * localmode=1,bmode=1,bmoderxtx=1,synthon=1,
477          * txon=1,paon=1,oscon=1,synthon_force=1
478          */
479         REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0);
480         udelay(30);
481         REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9271_AN_RF2G6_OFFS, 0);
482
483         /* find off_6_1; */
484         for (i = 6; i > 0; i--) {
485                 regVal = REG_READ(ah, 0x7834);
486                 regVal |= (1 << (20 + i));
487                 REG_WRITE(ah, 0x7834, regVal);
488                 udelay(1);
489                 /* regVal = REG_READ(ah, 0x7834); */
490                 regVal &= (~(0x1 << (20 + i)));
491                 regVal |= (MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9)
492                             << (20 + i));
493                 REG_WRITE(ah, 0x7834, regVal);
494         }
495
496         regVal = (regVal >> 20) & 0x7f;
497
498         /* Update PA cal info */
499         if ((!is_reset) && (ah->pacal_info.prev_offset == regVal)) {
500                 if (ah->pacal_info.max_skipcount < MAX_PACAL_SKIPCOUNT)
501                         ah->pacal_info.max_skipcount =
502                                 2 * ah->pacal_info.max_skipcount;
503                 ah->pacal_info.skipcount = ah->pacal_info.max_skipcount;
504         } else {
505                 ah->pacal_info.max_skipcount = 1;
506                 ah->pacal_info.skipcount = 0;
507                 ah->pacal_info.prev_offset = regVal;
508         }
509
510         ENABLE_REGWRITE_BUFFER(ah);
511
512         regVal = REG_READ(ah, 0x7834);
513         regVal |= 0x1;
514         REG_WRITE(ah, 0x7834, regVal);
515         regVal = REG_READ(ah, 0x9808);
516         regVal &= (~(0x1 << 27));
517         REG_WRITE(ah, 0x9808, regVal);
518
519         for (i = 0; i < ARRAY_SIZE(regList); i++)
520                 REG_WRITE(ah, regList[i][0], regList[i][1]);
521
522         REGWRITE_BUFFER_FLUSH(ah);
523 }
524
525 static inline void ar9285_hw_pa_cal(struct ath_hw *ah, bool is_reset)
526 {
527         struct ath_common *common = ath9k_hw_common(ah);
528         u32 regVal;
529         int i, offset, offs_6_1, offs_0;
530         u32 ccomp_org, reg_field;
531         u32 regList[][2] = {
532                 { 0x786c, 0 },
533                 { 0x7854, 0 },
534                 { 0x7820, 0 },
535                 { 0x7824, 0 },
536                 { 0x7868, 0 },
537                 { 0x783c, 0 },
538                 { 0x7838, 0 },
539         };
540
541         ath_dbg(common, ATH_DBG_CALIBRATE, "Running PA Calibration\n");
542
543         /* PA CAL is not needed for high power solution */
544         if (ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE) ==
545             AR5416_EEP_TXGAIN_HIGH_POWER)
546                 return;
547
548         for (i = 0; i < ARRAY_SIZE(regList); i++)
549                 regList[i][1] = REG_READ(ah, regList[i][0]);
550
551         regVal = REG_READ(ah, 0x7834);
552         regVal &= (~(0x1));
553         REG_WRITE(ah, 0x7834, regVal);
554         regVal = REG_READ(ah, 0x9808);
555         regVal |= (0x1 << 27);
556         REG_WRITE(ah, 0x9808, regVal);
557
558         REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1);
559         REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1);
560         REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1);
561         REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1);
562         REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0);
563         REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0);
564         REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0);
565         REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 0);
566         REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2, 0);
567         REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0);
568         REG_RMW_FIELD(ah, AR9285_AN_RF2G8, AR9285_AN_RF2G8_PADRVGN2TAB0, 7);
569         REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PADRVGN2TAB0, 0);
570         ccomp_org = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_CCOMP);
571         REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, 0xf);
572
573         REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0);
574         udelay(30);
575         REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, 0);
576         REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 0);
577
578         for (i = 6; i > 0; i--) {
579                 regVal = REG_READ(ah, 0x7834);
580                 regVal |= (1 << (19 + i));
581                 REG_WRITE(ah, 0x7834, regVal);
582                 udelay(1);
583                 regVal = REG_READ(ah, 0x7834);
584                 regVal &= (~(0x1 << (19 + i)));
585                 reg_field = MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9);
586                 regVal |= (reg_field << (19 + i));
587                 REG_WRITE(ah, 0x7834, regVal);
588         }
589
590         REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 1);
591         udelay(1);
592         reg_field = MS(REG_READ(ah, AR9285_AN_RF2G9), AR9285_AN_RXTXBB1_SPARE9);
593         REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, reg_field);
594         offs_6_1 = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_OFFS);
595         offs_0   = MS(REG_READ(ah, AR9285_AN_RF2G3), AR9285_AN_RF2G3_PDVCCOMP);
596
597         offset = (offs_6_1<<1) | offs_0;
598         offset = offset - 0;
599         offs_6_1 = offset>>1;
600         offs_0 = offset & 1;
601
602         if ((!is_reset) && (ah->pacal_info.prev_offset == offset)) {
603                 if (ah->pacal_info.max_skipcount < MAX_PACAL_SKIPCOUNT)
604                         ah->pacal_info.max_skipcount =
605                                 2 * ah->pacal_info.max_skipcount;
606                 ah->pacal_info.skipcount = ah->pacal_info.max_skipcount;
607         } else {
608                 ah->pacal_info.max_skipcount = 1;
609                 ah->pacal_info.skipcount = 0;
610                 ah->pacal_info.prev_offset = offset;
611         }
612
613         REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, offs_6_1);
614         REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, offs_0);
615
616         regVal = REG_READ(ah, 0x7834);
617         regVal |= 0x1;
618         REG_WRITE(ah, 0x7834, regVal);
619         regVal = REG_READ(ah, 0x9808);
620         regVal &= (~(0x1 << 27));
621         REG_WRITE(ah, 0x9808, regVal);
622
623         for (i = 0; i < ARRAY_SIZE(regList); i++)
624                 REG_WRITE(ah, regList[i][0], regList[i][1]);
625
626         REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, ccomp_org);
627 }
628
629 static void ar9002_hw_pa_cal(struct ath_hw *ah, bool is_reset)
630 {
631         if (AR_SREV_9271(ah)) {
632                 if (is_reset || !ah->pacal_info.skipcount)
633                         ar9271_hw_pa_cal(ah, is_reset);
634                 else
635                         ah->pacal_info.skipcount--;
636         } else if (AR_SREV_9285_12_OR_LATER(ah)) {
637                 if (is_reset || !ah->pacal_info.skipcount)
638                         ar9285_hw_pa_cal(ah, is_reset);
639                 else
640                         ah->pacal_info.skipcount--;
641         }
642 }
643
644 static void ar9002_hw_olc_temp_compensation(struct ath_hw *ah)
645 {
646         if (OLC_FOR_AR9287_10_LATER)
647                 ar9287_hw_olc_temp_compensation(ah);
648         else if (OLC_FOR_AR9280_20_LATER)
649                 ar9280_hw_olc_temp_compensation(ah);
650 }
651
652 static bool ar9002_hw_calibrate(struct ath_hw *ah,
653                                 struct ath9k_channel *chan,
654                                 u8 rxchainmask,
655                                 bool longcal)
656 {
657         bool iscaldone = true;
658         struct ath9k_cal_list *currCal = ah->cal_list_curr;
659         bool nfcal, nfcal_pending = false;
660
661         nfcal = !!(REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF);
662         if (ah->caldata)
663                 nfcal_pending = ah->caldata->nfcal_pending;
664
665         if (currCal && !nfcal &&
666             (currCal->calState == CAL_RUNNING ||
667              currCal->calState == CAL_WAITING)) {
668                 iscaldone = ar9002_hw_per_calibration(ah, chan,
669                                                       rxchainmask, currCal);
670                 if (iscaldone) {
671                         ah->cal_list_curr = currCal = currCal->calNext;
672
673                         if (currCal->calState == CAL_WAITING) {
674                                 iscaldone = false;
675                                 ath9k_hw_reset_calibration(ah, currCal);
676                         }
677                 }
678         }
679
680         /* Do NF cal only at longer intervals */
681         if (longcal || nfcal_pending) {
682                 /* Do periodic PAOffset Cal */
683                 ar9002_hw_pa_cal(ah, false);
684                 ar9002_hw_olc_temp_compensation(ah);
685
686                 /*
687                  * Get the value from the previous NF cal and update
688                  * history buffer.
689                  */
690                 if (ath9k_hw_getnf(ah, chan)) {
691                         /*
692                          * Load the NF from history buffer of the current
693                          * channel.
694                          * NF is slow time-variant, so it is OK to use a
695                          * historical value.
696                          */
697                         ath9k_hw_loadnf(ah, ah->curchan);
698                 }
699
700                 if (longcal)
701                         ath9k_hw_start_nfcal(ah, false);
702         }
703
704         return iscaldone;
705 }
706
707 /* Carrier leakage Calibration fix */
708 static bool ar9285_hw_cl_cal(struct ath_hw *ah, struct ath9k_channel *chan)
709 {
710         struct ath_common *common = ath9k_hw_common(ah);
711
712         REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
713         if (IS_CHAN_HT20(chan)) {
714                 REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE);
715                 REG_SET_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN);
716                 REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
717                             AR_PHY_AGC_CONTROL_FLTR_CAL);
718                 REG_CLR_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE);
719                 REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL);
720                 if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
721                                   AR_PHY_AGC_CONTROL_CAL, 0, AH_WAIT_TIMEOUT)) {
722                         ath_dbg(common, ATH_DBG_CALIBRATE,
723                                 "offset calibration failed to complete in 1ms; noisy environment?\n");
724                         return false;
725                 }
726                 REG_CLR_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN);
727                 REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE);
728                 REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
729         }
730         REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
731         REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL);
732         REG_SET_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE);
733         REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL);
734         if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL,
735                           0, AH_WAIT_TIMEOUT)) {
736                 ath_dbg(common, ATH_DBG_CALIBRATE,
737                         "offset calibration failed to complete in 1ms; noisy environment?\n");
738                 return false;
739         }
740
741         REG_SET_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
742         REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
743         REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL);
744
745         return true;
746 }
747
748 static bool ar9285_hw_clc(struct ath_hw *ah, struct ath9k_channel *chan)
749 {
750         int i;
751         u_int32_t txgain_max;
752         u_int32_t clc_gain, gain_mask = 0, clc_num = 0;
753         u_int32_t reg_clc_I0, reg_clc_Q0;
754         u_int32_t i0_num = 0;
755         u_int32_t q0_num = 0;
756         u_int32_t total_num = 0;
757         u_int32_t reg_rf2g5_org;
758         bool retv = true;
759
760         if (!(ar9285_hw_cl_cal(ah, chan)))
761                 return false;
762
763         txgain_max = MS(REG_READ(ah, AR_PHY_TX_PWRCTRL7),
764                         AR_PHY_TX_PWRCTRL_TX_GAIN_TAB_MAX);
765
766         for (i = 0; i < (txgain_max+1); i++) {
767                 clc_gain = (REG_READ(ah, (AR_PHY_TX_GAIN_TBL1+(i<<2))) &
768                            AR_PHY_TX_GAIN_CLC) >> AR_PHY_TX_GAIN_CLC_S;
769                 if (!(gain_mask & (1 << clc_gain))) {
770                         gain_mask |= (1 << clc_gain);
771                         clc_num++;
772                 }
773         }
774
775         for (i = 0; i < clc_num; i++) {
776                 reg_clc_I0 = (REG_READ(ah, (AR_PHY_CLC_TBL1 + (i << 2)))
777                               & AR_PHY_CLC_I0) >> AR_PHY_CLC_I0_S;
778                 reg_clc_Q0 = (REG_READ(ah, (AR_PHY_CLC_TBL1 + (i << 2)))
779                               & AR_PHY_CLC_Q0) >> AR_PHY_CLC_Q0_S;
780                 if (reg_clc_I0 == 0)
781                         i0_num++;
782
783                 if (reg_clc_Q0 == 0)
784                         q0_num++;
785         }
786         total_num = i0_num + q0_num;
787         if (total_num > AR9285_CLCAL_REDO_THRESH) {
788                 reg_rf2g5_org = REG_READ(ah, AR9285_RF2G5);
789                 if (AR_SREV_9285E_20(ah)) {
790                         REG_WRITE(ah, AR9285_RF2G5,
791                                   (reg_rf2g5_org & AR9285_RF2G5_IC50TX) |
792                                   AR9285_RF2G5_IC50TX_XE_SET);
793                 } else {
794                         REG_WRITE(ah, AR9285_RF2G5,
795                                   (reg_rf2g5_org & AR9285_RF2G5_IC50TX) |
796                                   AR9285_RF2G5_IC50TX_SET);
797                 }
798                 retv = ar9285_hw_cl_cal(ah, chan);
799                 REG_WRITE(ah, AR9285_RF2G5, reg_rf2g5_org);
800         }
801         return retv;
802 }
803
804 static bool ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan)
805 {
806         struct ath_common *common = ath9k_hw_common(ah);
807
808         if (AR_SREV_9271(ah) || AR_SREV_9285_12_OR_LATER(ah)) {
809                 if (!ar9285_hw_clc(ah, chan))
810                         return false;
811         } else {
812                 if (AR_SREV_9280_20_OR_LATER(ah)) {
813                         if (!AR_SREV_9287_11_OR_LATER(ah))
814                                 REG_CLR_BIT(ah, AR_PHY_ADC_CTL,
815                                             AR_PHY_ADC_CTL_OFF_PWDADC);
816                         REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
817                                     AR_PHY_AGC_CONTROL_FLTR_CAL);
818                 }
819
820                 /* Calibrate the AGC */
821                 REG_WRITE(ah, AR_PHY_AGC_CONTROL,
822                           REG_READ(ah, AR_PHY_AGC_CONTROL) |
823                           AR_PHY_AGC_CONTROL_CAL);
824
825                 /* Poll for offset calibration complete */
826                 if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
827                                    AR_PHY_AGC_CONTROL_CAL,
828                                    0, AH_WAIT_TIMEOUT)) {
829                         ath_dbg(common, ATH_DBG_CALIBRATE,
830                                 "offset calibration failed to complete in 1ms; noisy environment?\n");
831                         return false;
832                 }
833
834                 if (AR_SREV_9280_20_OR_LATER(ah)) {
835                         if (!AR_SREV_9287_11_OR_LATER(ah))
836                                 REG_SET_BIT(ah, AR_PHY_ADC_CTL,
837                                             AR_PHY_ADC_CTL_OFF_PWDADC);
838                         REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
839                                     AR_PHY_AGC_CONTROL_FLTR_CAL);
840                 }
841         }
842
843         /* Do PA Calibration */
844         ar9002_hw_pa_cal(ah, true);
845
846         /* Do NF Calibration after DC offset and other calibrations */
847         ath9k_hw_start_nfcal(ah, true);
848
849         if (ah->caldata)
850                 ah->caldata->nfcal_pending = true;
851
852         ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL;
853
854         /* Enable IQ, ADC Gain and ADC DC offset CALs */
855         if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) {
856                 ah->supp_cals = IQ_MISMATCH_CAL;
857
858                 if (AR_SREV_9160_10_OR_LATER(ah) &&
859                     !(IS_CHAN_2GHZ(chan) && IS_CHAN_HT20(chan))) {
860                         ah->supp_cals |= ADC_GAIN_CAL | ADC_DC_CAL;
861
862
863                         INIT_CAL(&ah->adcgain_caldata);
864                         INSERT_CAL(ah, &ah->adcgain_caldata);
865                         ath_dbg(common, ATH_DBG_CALIBRATE,
866                                 "enabling ADC Gain Calibration.\n");
867
868                         INIT_CAL(&ah->adcdc_caldata);
869                         INSERT_CAL(ah, &ah->adcdc_caldata);
870                         ath_dbg(common, ATH_DBG_CALIBRATE,
871                                 "enabling ADC DC Calibration.\n");
872                 }
873
874                 INIT_CAL(&ah->iq_caldata);
875                 INSERT_CAL(ah, &ah->iq_caldata);
876                 ath_dbg(common, ATH_DBG_CALIBRATE,
877                         "enabling IQ Calibration.\n");
878
879                 ah->cal_list_curr = ah->cal_list;
880
881                 if (ah->cal_list_curr)
882                         ath9k_hw_reset_calibration(ah, ah->cal_list_curr);
883         }
884
885         if (ah->caldata)
886                 ah->caldata->CalValid = 0;
887
888         return true;
889 }
890
891 static const struct ath9k_percal_data iq_cal_multi_sample = {
892         IQ_MISMATCH_CAL,
893         MAX_CAL_SAMPLES,
894         PER_MIN_LOG_COUNT,
895         ar9002_hw_iqcal_collect,
896         ar9002_hw_iqcalibrate
897 };
898 static const struct ath9k_percal_data iq_cal_single_sample = {
899         IQ_MISMATCH_CAL,
900         MIN_CAL_SAMPLES,
901         PER_MAX_LOG_COUNT,
902         ar9002_hw_iqcal_collect,
903         ar9002_hw_iqcalibrate
904 };
905 static const struct ath9k_percal_data adc_gain_cal_multi_sample = {
906         ADC_GAIN_CAL,
907         MAX_CAL_SAMPLES,
908         PER_MIN_LOG_COUNT,
909         ar9002_hw_adc_gaincal_collect,
910         ar9002_hw_adc_gaincal_calibrate
911 };
912 static const struct ath9k_percal_data adc_gain_cal_single_sample = {
913         ADC_GAIN_CAL,
914         MIN_CAL_SAMPLES,
915         PER_MAX_LOG_COUNT,
916         ar9002_hw_adc_gaincal_collect,
917         ar9002_hw_adc_gaincal_calibrate
918 };
919 static const struct ath9k_percal_data adc_dc_cal_multi_sample = {
920         ADC_DC_CAL,
921         MAX_CAL_SAMPLES,
922         PER_MIN_LOG_COUNT,
923         ar9002_hw_adc_dccal_collect,
924         ar9002_hw_adc_dccal_calibrate
925 };
926 static const struct ath9k_percal_data adc_dc_cal_single_sample = {
927         ADC_DC_CAL,
928         MIN_CAL_SAMPLES,
929         PER_MAX_LOG_COUNT,
930         ar9002_hw_adc_dccal_collect,
931         ar9002_hw_adc_dccal_calibrate
932 };
933
934 static void ar9002_hw_init_cal_settings(struct ath_hw *ah)
935 {
936         if (AR_SREV_9100(ah)) {
937                 ah->iq_caldata.calData = &iq_cal_multi_sample;
938                 ah->supp_cals = IQ_MISMATCH_CAL;
939                 return;
940         }
941
942         if (AR_SREV_9160_10_OR_LATER(ah)) {
943                 if (AR_SREV_9280_20_OR_LATER(ah)) {
944                         ah->iq_caldata.calData = &iq_cal_single_sample;
945                         ah->adcgain_caldata.calData =
946                                 &adc_gain_cal_single_sample;
947                         ah->adcdc_caldata.calData =
948                                 &adc_dc_cal_single_sample;
949                 } else {
950                         ah->iq_caldata.calData = &iq_cal_multi_sample;
951                         ah->adcgain_caldata.calData =
952                                 &adc_gain_cal_multi_sample;
953                         ah->adcdc_caldata.calData =
954                                 &adc_dc_cal_multi_sample;
955                 }
956                 ah->supp_cals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL;
957
958                 if (AR_SREV_9287(ah))
959                         ah->supp_cals &= ~ADC_GAIN_CAL;
960         }
961 }
962
963 void ar9002_hw_attach_calib_ops(struct ath_hw *ah)
964 {
965         struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
966         struct ath_hw_ops *ops = ath9k_hw_ops(ah);
967
968         priv_ops->init_cal_settings = ar9002_hw_init_cal_settings;
969         priv_ops->init_cal = ar9002_hw_init_cal;
970         priv_ops->setup_calibration = ar9002_hw_setup_calibration;
971
972         ops->calibrate = ar9002_hw_calibrate;
973 }