~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to roms/ipxe/src/drivers/net/ath/ath9k/ath9k_ar9002_calib.c

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
26
enum ar9002_cal_types {
 
27
        ADC_GAIN_CAL = BIT(0),
 
28
        ADC_DC_CAL = BIT(1),
 
29
        IQ_MISMATCH_CAL = BIT(2),
 
30
};
 
31
 
 
32
static int ar9002_hw_is_cal_supported(struct ath_hw *ah,
 
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
 
 
54
static void ar9002_hw_setup_calibration(struct ath_hw *ah,
 
55
                                        struct ath9k_cal_list *currCal)
 
56
{
 
57
        REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(0),
 
58
                      AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX,
 
59
                      currCal->calData->calCountMax);
 
60
 
 
61
        switch (currCal->calData->calType) {
 
62
        case IQ_MISMATCH_CAL:
 
63
                REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ);
 
64
                DBG2("ath9k: "
 
65
                        "starting IQ Mismatch Calibration\n");
 
66
                break;
 
67
        case ADC_GAIN_CAL:
 
68
                REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_GAIN);
 
69
                DBG2("ath9k: "
 
70
                        "starting ADC Gain Calibration\n");
 
71
                break;
 
72
        case ADC_DC_CAL:
 
73
                REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_PER);
 
74
                DBG2("ath9k: "
 
75
                        "starting ADC DC Calibration\n");
 
76
                break;
 
77
        }
 
78
 
 
79
        REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0),
 
80
                    AR_PHY_TIMING_CTRL4_DO_CAL);
 
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)) &
 
93
                      AR_PHY_TIMING_CTRL4_DO_CAL)) {
 
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 {
 
111
                                ar9002_hw_setup_calibration(ah, currCal);
 
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] +=
 
127
                        REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
 
128
                ah->totalPowerMeasQ[i] +=
 
129
                        REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
 
130
                ah->totalIqCorrMeas[i] +=
 
131
                        (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(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
 
 
140
static void ar9002_hw_adc_gaincal_collect(struct ath_hw *ah)
 
141
{
 
142
        int i;
 
143
 
 
144
        for (i = 0; i < AR5416_MAX_CHAINS; i++) {
 
145
                ah->totalAdcIOddPhase[i] +=
 
146
                        REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
 
147
                ah->totalAdcIEvenPhase[i] +=
 
148
                        REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
 
149
                ah->totalAdcQOddPhase[i] +=
 
150
                        REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
 
151
                ah->totalAdcQEvenPhase[i] +=
 
152
                        REG_READ(ah, AR_PHY_CAL_MEAS_3(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
 
 
164
static void ar9002_hw_adc_dccal_collect(struct ath_hw *ah)
 
165
{
 
166
        int i;
 
167
 
 
168
        for (i = 0; i < AR5416_MAX_CHAINS; i++) {
 
169
                ah->totalAdcDcOffsetIOddPhase[i] +=
 
170
                        (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
 
171
                ah->totalAdcDcOffsetIEvenPhase[i] +=
 
172
                        (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
 
173
                ah->totalAdcDcOffsetQOddPhase[i] +=
 
174
                        (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
 
175
                ah->totalAdcDcOffsetQEvenPhase[i] +=
 
176
                        (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_3(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;
 
192
        int32_t qCoff, iCoff;
 
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
 
 
249
                        REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i),
 
250
                                      AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF,
 
251
                                      iCoff);
 
252
                        REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i),
 
253
                                      AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF,
 
254
                                      qCoff);
 
255
                        DBG2("ath9k: "
 
256
                                "IQ Cal and Correction done for Chain %d\n",
 
257
                                i);
 
258
                }
 
259
        }
 
260
 
 
261
        REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0),
 
262
                    AR_PHY_TIMING_CTRL4_IQCORR_ENABLE);
 
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
 
 
307
                        val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
 
308
                        val &= 0xfffff000;
 
309
                        val |= (qGainMismatch) | (iGainMismatch << 6);
 
310
                        REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
 
311
 
 
312
                        DBG2("ath9k: "
 
313
                                "ADC Gain Cal done for Chain %d\n", i);
 
314
                }
 
315
        }
 
316
 
 
317
        REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
 
318
                  REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
 
319
                  AR_PHY_NEW_ADC_GAIN_CORR_ENABLE);
 
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
 
 
365
                val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
 
366
                val &= 0xc0000fff;
 
367
                val |= (qDcMismatch << 12) | (iDcMismatch << 21);
 
368
                REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
 
369
 
 
370
                DBG2("ath9k: "
 
371
                        "ADC DC Offset Cal done for Chain %d\n", i);
 
372
        }
 
373
 
 
374
        REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
 
375
                  REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
 
376
                  AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE);
 
377
}
 
378
 
 
379
static void ar9287_hw_olc_temp_compensation(struct ath_hw *ah)
 
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
                }
 
402
                REG_RMW_FIELD(ah, AR_PHY_CH0_TX_PWRCTRL11,
 
403
                              AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta);
 
404
                REG_RMW_FIELD(ah, AR_PHY_CH1_TX_PWRCTRL11,
 
405
                              AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta);
 
406
        }
 
407
}
 
408
 
 
409
static void ar9280_hw_olc_temp_compensation(struct ath_hw *ah)
 
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
 
 
432
                        REG_RMW_FIELD(ah,
 
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 */
 
465
        REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1);
 
466
        /* 7854, b5,1, pdrxtxbb=1 */
 
467
        REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1);
 
468
        /* 7854, b7,1, pdv2i=1 */
 
469
        REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1);
 
470
        /* 7854, b8,1, pddacinterface=1 */
 
471
        REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1);
 
472
        /* 7824,b12,0, offcal=0 */
 
473
        REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0);
 
474
        /* 7838, b1,0, pwddb=0 */
 
475
        REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0);
 
476
        /* 7820,b11,0, enpacal=0 */
 
477
        REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0);
 
478
        /* 7820,b25,1, pdpadrv1=0 */
 
479
        REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 0);
 
480
        /* 7820,b24,0, pdpadrv2=0 */
 
481
        REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2, 0);
 
482
        /* 7820,b23,0, pdpaout=0 */
 
483
        REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0);
 
484
        /* 783c,b14-16,7, padrvgn2tab_0=7 */
 
485
        REG_RMW_FIELD(ah, AR9285_AN_RF2G8, AR9285_AN_RF2G8_PADRVGN2TAB0, 7);
 
486
        /*
 
487
         * 7838,b29-31,0, padrvgn1tab_0=0
 
488
         * does not matter since we turn it off
 
489
         */
 
490
        REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PADRVGN2TAB0, 0);
 
491
 
 
492
        REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9271_AN_RF2G3_CCOMP, 0xfff);
 
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);
 
500
        REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9271_AN_RF2G6_OFFS, 0);
 
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
 
 
529
        ENABLE_REGWRITE_BUFFER(ah);
 
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
 
 
541
        REGWRITE_BUFFER_FLUSH(ah);
 
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) ==
 
564
            AR5416_EEP_TXGAIN_HIGH_POWER)
 
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
 
 
577
        REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1);
 
578
        REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1);
 
579
        REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1);
 
580
        REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1);
 
581
        REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0);
 
582
        REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0);
 
583
        REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0);
 
584
        REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 0);
 
585
        REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2, 0);
 
586
        REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0);
 
587
        REG_RMW_FIELD(ah, AR9285_AN_RF2G8, AR9285_AN_RF2G8_PADRVGN2TAB0, 7);
 
588
        REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PADRVGN2TAB0, 0);
 
589
        ccomp_org = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_CCOMP);
 
590
        REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, 0xf);
 
591
 
 
592
        REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0);
 
593
        udelay(30);
 
594
        REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, 0);
 
595
        REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 0);
 
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
 
 
609
        REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 1);
 
610
        udelay(1);
 
611
        reg_field = MS(REG_READ(ah, AR9285_AN_RF2G9), AR9285_AN_RXTXBB1_SPARE9);
 
612
        REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, reg_field);
 
613
        offs_6_1 = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_OFFS);
 
614
        offs_0   = MS(REG_READ(ah, AR9285_AN_RF2G3), AR9285_AN_RF2G3_PDVCCOMP);
 
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
 
 
632
        REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, offs_6_1);
 
633
        REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, offs_0);
 
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
 
 
645
        REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, ccomp_org);
 
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
 
 
663
static void ar9002_hw_olc_temp_compensation(struct ath_hw *ah)
 
664
{
 
665
        if (OLC_FOR_AR9287_10_LATER)
 
666
                ar9287_hw_olc_temp_compensation(ah);
 
667
        else if (OLC_FOR_AR9280_20_LATER)
 
668
                ar9280_hw_olc_temp_compensation(ah);
 
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
 
 
680
        nfcal = !!(REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF);
 
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) {
 
716
                        ath9k_hw_start_nfcal(ah, 0);
 
717
                        /* Do periodic PAOffset Cal */
 
718
                        ar9002_hw_pa_cal(ah, 0);
 
719
                        ar9002_hw_olc_temp_compensation(ah);
 
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
{
 
729
        REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
 
730
        if (IS_CHAN_HT20(chan)) {
 
731
                REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE);
 
732
                REG_SET_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN);
 
733
                REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
 
734
                            AR_PHY_AGC_CONTROL_FLTR_CAL);
 
735
                REG_CLR_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE);
 
736
                REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL);
 
737
                if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
 
738
                                  AR_PHY_AGC_CONTROL_CAL, 0, AH_WAIT_TIMEOUT)) {
 
739
                        DBG("ath9k: "
 
740
                                "offset calibration failed to complete in 1ms; noisy environment?\n");
 
741
                        return 0;
 
742
                }
 
743
                REG_CLR_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN);
 
744
                REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE);
 
745
                REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
 
746
        }
 
747
        REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
 
748
        REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL);
 
749
        REG_SET_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE);
 
750
        REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL);
 
751
        if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL,
 
752
                          0, AH_WAIT_TIMEOUT)) {
 
753
                DBG("ath9k: "
 
754
                        "offset calibration failed to complete in 1ms; noisy environment?\n");
 
755
                return 0;
 
756
        }
 
757
 
 
758
        REG_SET_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
 
759
        REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
 
760
        REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL);
 
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),
 
781
                        AR_PHY_TX_PWRCTRL_TX_GAIN_TAB_MAX);
 
782
 
 
783
        for (i = 0; i < (txgain_max+1); i++) {
 
784
                clc_gain = (REG_READ(ah, (AR_PHY_TX_GAIN_TBL1+(i<<2))) &
 
785
                           AR_PHY_TX_GAIN_CLC) >> AR_PHY_TX_GAIN_CLC_S;
 
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)))
 
794
                              & AR_PHY_CLC_I0) >> AR_PHY_CLC_I0_S;
 
795
                reg_clc_Q0 = (REG_READ(ah, (AR_PHY_CLC_TBL1 + (i << 2)))
 
796
                              & AR_PHY_CLC_Q0) >> AR_PHY_CLC_Q0_S;
 
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)) {
 
807
                        REG_WRITE(ah, AR9285_RF2G5,
 
808
                                  (reg_rf2g5_org & AR9285_RF2G5_IC50TX) |
 
809
                                  AR9285_RF2G5_IC50TX_XE_SET);
 
810
                } else {
 
811
                        REG_WRITE(ah, AR9285_RF2G5,
 
812
                                  (reg_rf2g5_org & AR9285_RF2G5_IC50TX) |
 
813
                                  AR9285_RF2G5_IC50TX_SET);
 
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 {
 
830
                if (AR_SREV_9280_20_OR_LATER(ah)) {
 
831
                        if (!AR_SREV_9287_11_OR_LATER(ah))
 
832
                                REG_CLR_BIT(ah, AR_PHY_ADC_CTL,
 
833
                                            AR_PHY_ADC_CTL_OFF_PWDADC);
 
834
                        REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
 
835
                                    AR_PHY_AGC_CONTROL_FLTR_CAL);
 
836
                }
 
837
 
 
838
                /* Calibrate the AGC */
 
839
                REG_WRITE(ah, AR_PHY_AGC_CONTROL,
 
840
                          REG_READ(ah, AR_PHY_AGC_CONTROL) |
 
841
                          AR_PHY_AGC_CONTROL_CAL);
 
842
 
 
843
                /* Poll for offset calibration complete */
 
844
                if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
 
845
                                   AR_PHY_AGC_CONTROL_CAL,
 
846
                                   0, AH_WAIT_TIMEOUT)) {
 
847
                        DBG("ath9k: "
 
848
                                "offset calibration failed to complete in 1ms; noisy environment?\n");
 
849
                        return 0;
 
850
                }
 
851
 
 
852
                if (AR_SREV_9280_20_OR_LATER(ah)) {
 
853
                        if (!AR_SREV_9287_11_OR_LATER(ah))
 
854
                                REG_SET_BIT(ah, AR_PHY_ADC_CTL,
 
855
                                            AR_PHY_ADC_CTL_OFF_PWDADC);
 
856
                        REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
 
857
                                    AR_PHY_AGC_CONTROL_FLTR_CAL);
 
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 */
 
865
        ath9k_hw_start_nfcal(ah, 1);
 
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 */
 
873
        if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) {
 
874
                ah->supp_cals = IQ_MISMATCH_CAL;
 
875
 
 
876
                if (AR_SREV_9160_10_OR_LATER(ah))
 
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
 
 
882
                if (ar9002_hw_is_cal_supported(ah, chan, ADC_GAIN_CAL)) {
 
883
                        INIT_CAL(&ah->adcgain_caldata);
 
884
                        INSERT_CAL(ah, &ah->adcgain_caldata);
 
885
                        DBG2("ath9k: "
 
886
                                        "enabling ADC Gain Calibration.\n");
 
887
                }
 
888
 
 
889
                if (ar9002_hw_is_cal_supported(ah, chan, ADC_DC_CAL)) {
 
890
                        INIT_CAL(&ah->adcdc_caldata);
 
891
                        INSERT_CAL(ah, &ah->adcdc_caldata);
 
892
                        DBG2("ath9k: "
 
893
                                        "enabling ADC DC Calibration.\n");
 
894
                }
 
895
 
 
896
                if (ar9002_hw_is_cal_supported(ah, chan, IQ_MISMATCH_CAL)) {
 
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 = {
 
916
        IQ_MISMATCH_CAL,
 
917
        MAX_CAL_SAMPLES,
 
918
        PER_MIN_LOG_COUNT,
 
919
        ar9002_hw_iqcal_collect,
 
920
        ar9002_hw_iqcalibrate
 
921
};
 
922
static const struct ath9k_percal_data iq_cal_single_sample = {
 
923
        IQ_MISMATCH_CAL,
 
924
        MIN_CAL_SAMPLES,
 
925
        PER_MAX_LOG_COUNT,
 
926
        ar9002_hw_iqcal_collect,
 
927
        ar9002_hw_iqcalibrate
 
928
};
 
929
static const struct ath9k_percal_data adc_gain_cal_multi_sample = {
 
930
        ADC_GAIN_CAL,
 
931
        MAX_CAL_SAMPLES,
 
932
        PER_MIN_LOG_COUNT,
 
933
        ar9002_hw_adc_gaincal_collect,
 
934
        ar9002_hw_adc_gaincal_calibrate
 
935
};
 
936
static const struct ath9k_percal_data adc_gain_cal_single_sample = {
 
937
        ADC_GAIN_CAL,
 
938
        MIN_CAL_SAMPLES,
 
939
        PER_MAX_LOG_COUNT,
 
940
        ar9002_hw_adc_gaincal_collect,
 
941
        ar9002_hw_adc_gaincal_calibrate
 
942
};
 
943
static const struct ath9k_percal_data adc_dc_cal_multi_sample = {
 
944
        ADC_DC_CAL,
 
945
        MAX_CAL_SAMPLES,
 
946
        PER_MIN_LOG_COUNT,
 
947
        ar9002_hw_adc_dccal_collect,
 
948
        ar9002_hw_adc_dccal_calibrate
 
949
};
 
950
static const struct ath9k_percal_data adc_dc_cal_single_sample = {
 
951
        ADC_DC_CAL,
 
952
        MIN_CAL_SAMPLES,
 
953
        PER_MAX_LOG_COUNT,
 
954
        ar9002_hw_adc_dccal_collect,
 
955
        ar9002_hw_adc_dccal_calibrate
 
956
};
 
957
 
 
958
static void ar9002_hw_init_cal_settings(struct ath_hw *ah)
 
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
 
 
966
        if (AR_SREV_9160_10_OR_LATER(ah)) {
 
967
                if (AR_SREV_9280_20_OR_LATER(ah)) {
 
968
                        ah->iq_caldata.calData = &iq_cal_single_sample;
 
969
                        ah->adcgain_caldata.calData =
 
970
                                &adc_gain_cal_single_sample;
 
971
                        ah->adcdc_caldata.calData =
 
972
                                &adc_dc_cal_single_sample;
 
973
                } else {
 
974
                        ah->iq_caldata.calData = &iq_cal_multi_sample;
 
975
                        ah->adcgain_caldata.calData =
 
976
                                &adc_gain_cal_multi_sample;
 
977
                        ah->adcdc_caldata.calData =
 
978
                                &adc_dc_cal_multi_sample;
 
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
 
 
987
void ar9002_hw_attach_calib_ops(struct ath_hw *ah)
 
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
 
 
992
        priv_ops->init_cal_settings = ar9002_hw_init_cal_settings;
 
993
        priv_ops->init_cal = ar9002_hw_init_cal;
 
994
        priv_ops->setup_calibration = ar9002_hw_setup_calibration;
 
995
 
 
996
        ops->calibrate = ar9002_hw_calibrate;
 
997
}