aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuis R. Rodriguez <lrodriguez@atheros.com>2010-04-15 17:39:00 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-04-16 15:43:31 -0400
commit795f5e2ca672727a96bacf97075976cfe1249fcf (patch)
tree194a0f9920377520a1591638eacab205db365dbe
parent0df13da4555320f6dc9b901fd5f22cf54065c708 (diff)
ath9k_hw: split calib code by hardware families
Calibration code touches phy registers and since these change the calibration code needs to be abstracted. Noise floor calibration is the only thing remaining but since the remaining calls only touch the AR_PHY_AGC_CONTROL register we'll just define that register conditionally, that will be done separately. The goal is to remove the dependency of ar9002_phy.h on calib.c This also adds stubs to be filled for AR9003 calibration code. Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/ath/ath9k/Makefile4
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9002_calib.c993
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_calib.c66
-rw-r--r--drivers/net/wireless/ath/ath9k/calib.c928
-rw-r--r--drivers/net/wireless/ath/ath9k/calib.h15
-rw-r--r--drivers/net/wireless/ath/ath9k/hw-ops.h28
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c34
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.h21
8 files changed, 1118 insertions, 971 deletions
diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile
index 96af3d96de5c..d2417ed8ec4c 100644
--- a/drivers/net/wireless/ath/ath9k/Makefile
+++ b/drivers/net/wireless/ath/ath9k/Makefile
@@ -17,11 +17,13 @@ ath9k_hw-y:= hw.o \
17 ar9003_phy.o \ 17 ar9003_phy.o \
18 ar9002_phy.o \ 18 ar9002_phy.o \
19 ar5008_phy.o \ 19 ar5008_phy.o \
20 ar9002_calib.o \
21 ar9003_calib.o \
22 calib.o \
20 eeprom.o \ 23 eeprom.o \
21 eeprom_def.o \ 24 eeprom_def.o \
22 eeprom_4k.o \ 25 eeprom_4k.o \
23 eeprom_9287.o \ 26 eeprom_9287.o \
24 calib.o \
25 ani.o \ 27 ani.o \
26 btcoex.o \ 28 btcoex.o \
27 mac.o \ 29 mac.o \
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_calib.c b/drivers/net/wireless/ath/ath9k/ar9002_calib.c
new file mode 100644
index 000000000000..cd234aafaa4a
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c
@@ -0,0 +1,993 @@
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
23static void ar9002_hw_setup_calibration(struct ath_hw *ah,
24 struct ath9k_cal_list *currCal)
25{
26 struct ath_common *common = ath9k_hw_common(ah);
27
28 REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(0),
29 AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX,
30 currCal->calData->calCountMax);
31
32 switch (currCal->calData->calType) {
33 case IQ_MISMATCH_CAL:
34 REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ);
35 ath_print(common, ATH_DBG_CALIBRATE,
36 "starting IQ Mismatch Calibration\n");
37 break;
38 case ADC_GAIN_CAL:
39 REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_GAIN);
40 ath_print(common, ATH_DBG_CALIBRATE,
41 "starting ADC Gain Calibration\n");
42 break;
43 case ADC_DC_CAL:
44 REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_PER);
45 ath_print(common, ATH_DBG_CALIBRATE,
46 "starting ADC DC Calibration\n");
47 break;
48 case ADC_DC_INIT_CAL:
49 REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_INIT);
50 ath_print(common, ATH_DBG_CALIBRATE,
51 "starting Init ADC DC Calibration\n");
52 break;
53 }
54
55 REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0),
56 AR_PHY_TIMING_CTRL4_DO_CAL);
57}
58
59static bool ar9002_hw_per_calibration(struct ath_hw *ah,
60 struct ath9k_channel *ichan,
61 u8 rxchainmask,
62 struct ath9k_cal_list *currCal)
63{
64 bool iscaldone = false;
65
66 if (currCal->calState == CAL_RUNNING) {
67 if (!(REG_READ(ah, AR_PHY_TIMING_CTRL4(0)) &
68 AR_PHY_TIMING_CTRL4_DO_CAL)) {
69
70 currCal->calData->calCollect(ah);
71 ah->cal_samples++;
72
73 if (ah->cal_samples >=
74 currCal->calData->calNumSamples) {
75 int i, numChains = 0;
76 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
77 if (rxchainmask & (1 << i))
78 numChains++;
79 }
80
81 currCal->calData->calPostProc(ah, numChains);
82 ichan->CalValid |= currCal->calData->calType;
83 currCal->calState = CAL_DONE;
84 iscaldone = true;
85 } else {
86 ar9002_hw_setup_calibration(ah, currCal);
87 }
88 }
89 } else if (!(ichan->CalValid & currCal->calData->calType)) {
90 ath9k_hw_reset_calibration(ah, currCal);
91 }
92
93 return iscaldone;
94}
95
96/* Assumes you are talking about the currently configured channel */
97static bool ar9002_hw_iscal_supported(struct ath_hw *ah,
98 enum ath9k_cal_types calType)
99{
100 struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
101
102 switch (calType & ah->supp_cals) {
103 case IQ_MISMATCH_CAL: /* Both 2 GHz and 5 GHz support OFDM */
104 return true;
105 case ADC_GAIN_CAL:
106 case ADC_DC_CAL:
107 if (!(conf->channel->band == IEEE80211_BAND_2GHZ &&
108 conf_is_ht20(conf)))
109 return true;
110 break;
111 }
112 return false;
113}
114
115static void ar9002_hw_iqcal_collect(struct ath_hw *ah)
116{
117 int i;
118
119 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
120 ah->totalPowerMeasI[i] +=
121 REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
122 ah->totalPowerMeasQ[i] +=
123 REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
124 ah->totalIqCorrMeas[i] +=
125 (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
126 ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
127 "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
128 ah->cal_samples, i, ah->totalPowerMeasI[i],
129 ah->totalPowerMeasQ[i],
130 ah->totalIqCorrMeas[i]);
131 }
132}
133
134static void ar9002_hw_adc_gaincal_collect(struct ath_hw *ah)
135{
136 int i;
137
138 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
139 ah->totalAdcIOddPhase[i] +=
140 REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
141 ah->totalAdcIEvenPhase[i] +=
142 REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
143 ah->totalAdcQOddPhase[i] +=
144 REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
145 ah->totalAdcQEvenPhase[i] +=
146 REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
147
148 ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
149 "%d: Chn %d oddi=0x%08x; eveni=0x%08x; "
150 "oddq=0x%08x; evenq=0x%08x;\n",
151 ah->cal_samples, i,
152 ah->totalAdcIOddPhase[i],
153 ah->totalAdcIEvenPhase[i],
154 ah->totalAdcQOddPhase[i],
155 ah->totalAdcQEvenPhase[i]);
156 }
157}
158
159static void ar9002_hw_adc_dccal_collect(struct ath_hw *ah)
160{
161 int i;
162
163 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
164 ah->totalAdcDcOffsetIOddPhase[i] +=
165 (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
166 ah->totalAdcDcOffsetIEvenPhase[i] +=
167 (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
168 ah->totalAdcDcOffsetQOddPhase[i] +=
169 (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
170 ah->totalAdcDcOffsetQEvenPhase[i] +=
171 (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
172
173 ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
174 "%d: Chn %d oddi=0x%08x; eveni=0x%08x; "
175 "oddq=0x%08x; evenq=0x%08x;\n",
176 ah->cal_samples, i,
177 ah->totalAdcDcOffsetIOddPhase[i],
178 ah->totalAdcDcOffsetIEvenPhase[i],
179 ah->totalAdcDcOffsetQOddPhase[i],
180 ah->totalAdcDcOffsetQEvenPhase[i]);
181 }
182}
183
184static void ar9002_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
185{
186 struct ath_common *common = ath9k_hw_common(ah);
187 u32 powerMeasQ, powerMeasI, iqCorrMeas;
188 u32 qCoffDenom, iCoffDenom;
189 int32_t qCoff, iCoff;
190 int iqCorrNeg, i;
191
192 for (i = 0; i < numChains; i++) {
193 powerMeasI = ah->totalPowerMeasI[i];
194 powerMeasQ = ah->totalPowerMeasQ[i];
195 iqCorrMeas = ah->totalIqCorrMeas[i];
196
197 ath_print(common, ATH_DBG_CALIBRATE,
198 "Starting IQ Cal and Correction for Chain %d\n",
199 i);
200
201 ath_print(common, ATH_DBG_CALIBRATE,
202 "Orignal: Chn %diq_corr_meas = 0x%08x\n",
203 i, ah->totalIqCorrMeas[i]);
204
205 iqCorrNeg = 0;
206
207 if (iqCorrMeas > 0x80000000) {
208 iqCorrMeas = (0xffffffff - iqCorrMeas) + 1;
209 iqCorrNeg = 1;
210 }
211
212 ath_print(common, ATH_DBG_CALIBRATE,
213 "Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI);
214 ath_print(common, ATH_DBG_CALIBRATE,
215 "Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ);
216 ath_print(common, ATH_DBG_CALIBRATE, "iqCorrNeg is 0x%08x\n",
217 iqCorrNeg);
218
219 iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128;
220 qCoffDenom = powerMeasQ / 64;
221
222 if ((powerMeasQ != 0) && (iCoffDenom != 0) &&
223 (qCoffDenom != 0)) {
224 iCoff = iqCorrMeas / iCoffDenom;
225 qCoff = powerMeasI / qCoffDenom - 64;
226 ath_print(common, ATH_DBG_CALIBRATE,
227 "Chn %d iCoff = 0x%08x\n", i, iCoff);
228 ath_print(common, ATH_DBG_CALIBRATE,
229 "Chn %d qCoff = 0x%08x\n", i, qCoff);
230
231 iCoff = iCoff & 0x3f;
232 ath_print(common, ATH_DBG_CALIBRATE,
233 "New: Chn %d iCoff = 0x%08x\n", i, iCoff);
234 if (iqCorrNeg == 0x0)
235 iCoff = 0x40 - iCoff;
236
237 if (qCoff > 15)
238 qCoff = 15;
239 else if (qCoff <= -16)
240 qCoff = 16;
241
242 ath_print(common, ATH_DBG_CALIBRATE,
243 "Chn %d : iCoff = 0x%x qCoff = 0x%x\n",
244 i, iCoff, qCoff);
245
246 REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i),
247 AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF,
248 iCoff);
249 REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i),
250 AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF,
251 qCoff);
252 ath_print(common, ATH_DBG_CALIBRATE,
253 "IQ Cal and Correction done for Chain %d\n",
254 i);
255 }
256 }
257
258 REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0),
259 AR_PHY_TIMING_CTRL4_IQCORR_ENABLE);
260}
261
262static void ar9002_hw_adc_gaincal_calibrate(struct ath_hw *ah, u8 numChains)
263{
264 struct ath_common *common = ath9k_hw_common(ah);
265 u32 iOddMeasOffset, iEvenMeasOffset, qOddMeasOffset, qEvenMeasOffset;
266 u32 qGainMismatch, iGainMismatch, val, i;
267
268 for (i = 0; i < numChains; i++) {
269 iOddMeasOffset = ah->totalAdcIOddPhase[i];
270 iEvenMeasOffset = ah->totalAdcIEvenPhase[i];
271 qOddMeasOffset = ah->totalAdcQOddPhase[i];
272 qEvenMeasOffset = ah->totalAdcQEvenPhase[i];
273
274 ath_print(common, ATH_DBG_CALIBRATE,
275 "Starting ADC Gain Cal for Chain %d\n", i);
276
277 ath_print(common, ATH_DBG_CALIBRATE,
278 "Chn %d pwr_meas_odd_i = 0x%08x\n", i,
279 iOddMeasOffset);
280 ath_print(common, ATH_DBG_CALIBRATE,
281 "Chn %d pwr_meas_even_i = 0x%08x\n", i,
282 iEvenMeasOffset);
283 ath_print(common, ATH_DBG_CALIBRATE,
284 "Chn %d pwr_meas_odd_q = 0x%08x\n", i,
285 qOddMeasOffset);
286 ath_print(common, ATH_DBG_CALIBRATE,
287 "Chn %d pwr_meas_even_q = 0x%08x\n", i,
288 qEvenMeasOffset);
289
290 if (iOddMeasOffset != 0 && qEvenMeasOffset != 0) {
291 iGainMismatch =
292 ((iEvenMeasOffset * 32) /
293 iOddMeasOffset) & 0x3f;
294 qGainMismatch =
295 ((qOddMeasOffset * 32) /
296 qEvenMeasOffset) & 0x3f;
297
298 ath_print(common, ATH_DBG_CALIBRATE,
299 "Chn %d gain_mismatch_i = 0x%08x\n", i,
300 iGainMismatch);
301 ath_print(common, ATH_DBG_CALIBRATE,
302 "Chn %d gain_mismatch_q = 0x%08x\n", i,
303 qGainMismatch);
304
305 val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
306 val &= 0xfffff000;
307 val |= (qGainMismatch) | (iGainMismatch << 6);
308 REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
309
310 ath_print(common, ATH_DBG_CALIBRATE,
311 "ADC Gain Cal done for Chain %d\n", i);
312 }
313 }
314
315 REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
316 REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
317 AR_PHY_NEW_ADC_GAIN_CORR_ENABLE);
318}
319
320static void ar9002_hw_adc_dccal_calibrate(struct ath_hw *ah, u8 numChains)
321{
322 struct ath_common *common = ath9k_hw_common(ah);
323 u32 iOddMeasOffset, iEvenMeasOffset, val, i;
324 int32_t qOddMeasOffset, qEvenMeasOffset, qDcMismatch, iDcMismatch;
325 const struct ath9k_percal_data *calData =
326 ah->cal_list_curr->calData;
327 u32 numSamples =
328 (1 << (calData->calCountMax + 5)) * calData->calNumSamples;
329
330 for (i = 0; i < numChains; i++) {
331 iOddMeasOffset = ah->totalAdcDcOffsetIOddPhase[i];
332 iEvenMeasOffset = ah->totalAdcDcOffsetIEvenPhase[i];
333 qOddMeasOffset = ah->totalAdcDcOffsetQOddPhase[i];
334 qEvenMeasOffset = ah->totalAdcDcOffsetQEvenPhase[i];
335
336 ath_print(common, ATH_DBG_CALIBRATE,
337 "Starting ADC DC Offset Cal for Chain %d\n", i);
338
339 ath_print(common, ATH_DBG_CALIBRATE,
340 "Chn %d pwr_meas_odd_i = %d\n", i,
341 iOddMeasOffset);
342 ath_print(common, ATH_DBG_CALIBRATE,
343 "Chn %d pwr_meas_even_i = %d\n", i,
344 iEvenMeasOffset);
345 ath_print(common, ATH_DBG_CALIBRATE,
346 "Chn %d pwr_meas_odd_q = %d\n", i,
347 qOddMeasOffset);
348 ath_print(common, ATH_DBG_CALIBRATE,
349 "Chn %d pwr_meas_even_q = %d\n", i,
350 qEvenMeasOffset);
351
352 iDcMismatch = (((iEvenMeasOffset - iOddMeasOffset) * 2) /
353 numSamples) & 0x1ff;
354 qDcMismatch = (((qOddMeasOffset - qEvenMeasOffset) * 2) /
355 numSamples) & 0x1ff;
356
357 ath_print(common, ATH_DBG_CALIBRATE,
358 "Chn %d dc_offset_mismatch_i = 0x%08x\n", i,
359 iDcMismatch);
360 ath_print(common, ATH_DBG_CALIBRATE,
361 "Chn %d dc_offset_mismatch_q = 0x%08x\n", i,
362 qDcMismatch);
363
364 val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
365 val &= 0xc0000fff;
366 val |= (qDcMismatch << 12) | (iDcMismatch << 21);
367 REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
368
369 ath_print(common, ATH_DBG_CALIBRATE,
370 "ADC DC Offset Cal done for Chain %d\n", i);
371 }
372
373 REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
374 REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
375 AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE);
376}
377
378static void ar9287_hw_olc_temp_compensation(struct ath_hw *ah)
379{
380 u32 rddata;
381 int32_t delta, currPDADC, slope;
382
383 rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4);
384 currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT);
385
386 if (ah->initPDADC == 0 || currPDADC == 0) {
387 /*
388 * Zero value indicates that no frames have been transmitted
389 * yet, can't do temperature compensation until frames are
390 * transmitted.
391 */
392 return;
393 } else {
394 slope = ah->eep_ops->get_eeprom(ah, EEP_TEMPSENSE_SLOPE);
395
396 if (slope == 0) { /* to avoid divide by zero case */
397 delta = 0;
398 } else {
399 delta = ((currPDADC - ah->initPDADC)*4) / slope;
400 }
401 REG_RMW_FIELD(ah, AR_PHY_CH0_TX_PWRCTRL11,
402 AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta);
403 REG_RMW_FIELD(ah, AR_PHY_CH1_TX_PWRCTRL11,
404 AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta);
405 }
406}
407
408static void ar9280_hw_olc_temp_compensation(struct ath_hw *ah)
409{
410 u32 rddata, i;
411 int delta, currPDADC, regval;
412
413 rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4);
414 currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT);
415
416 if (ah->initPDADC == 0 || currPDADC == 0)
417 return;
418
419 if (ah->eep_ops->get_eeprom(ah, EEP_DAC_HPWR_5G))
420 delta = (currPDADC - ah->initPDADC + 4) / 8;
421 else
422 delta = (currPDADC - ah->initPDADC + 5) / 10;
423
424 if (delta != ah->PDADCdelta) {
425 ah->PDADCdelta = delta;
426 for (i = 1; i < AR9280_TX_GAIN_TABLE_SIZE; i++) {
427 regval = ah->originalGain[i] - delta;
428 if (regval < 0)
429 regval = 0;
430
431 REG_RMW_FIELD(ah,
432 AR_PHY_TX_GAIN_TBL1 + i * 4,
433 AR_PHY_TX_GAIN, regval);
434 }
435 }
436}
437
438static void ar9271_hw_pa_cal(struct ath_hw *ah, bool is_reset)
439{
440 u32 regVal;
441 unsigned int i;
442 u32 regList[][2] = {
443 { 0x786c, 0 },
444 { 0x7854, 0 },
445 { 0x7820, 0 },
446 { 0x7824, 0 },
447 { 0x7868, 0 },
448 { 0x783c, 0 },
449 { 0x7838, 0 } ,
450 { 0x7828, 0 } ,
451 };
452
453 for (i = 0; i < ARRAY_SIZE(regList); i++)
454 regList[i][1] = REG_READ(ah, regList[i][0]);
455
456 regVal = REG_READ(ah, 0x7834);
457 regVal &= (~(0x1));
458 REG_WRITE(ah, 0x7834, regVal);
459 regVal = REG_READ(ah, 0x9808);
460 regVal |= (0x1 << 27);
461 REG_WRITE(ah, 0x9808, regVal);
462
463 /* 786c,b23,1, pwddac=1 */
464 REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1);
465 /* 7854, b5,1, pdrxtxbb=1 */
466 REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1);
467 /* 7854, b7,1, pdv2i=1 */
468 REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1);
469 /* 7854, b8,1, pddacinterface=1 */
470 REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1);
471 /* 7824,b12,0, offcal=0 */
472 REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0);
473 /* 7838, b1,0, pwddb=0 */
474 REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0);
475 /* 7820,b11,0, enpacal=0 */
476 REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0);
477 /* 7820,b25,1, pdpadrv1=0 */
478 REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 0);
479 /* 7820,b24,0, pdpadrv2=0 */
480 REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2, 0);
481 /* 7820,b23,0, pdpaout=0 */
482 REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0);
483 /* 783c,b14-16,7, padrvgn2tab_0=7 */
484 REG_RMW_FIELD(ah, AR9285_AN_RF2G8, AR9285_AN_RF2G8_PADRVGN2TAB0, 7);
485 /*
486 * 7838,b29-31,0, padrvgn1tab_0=0
487 * does not matter since we turn it off
488 */
489 REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PADRVGN2TAB0, 0);
490
491 REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9271_AN_RF2G3_CCOMP, 0xfff);
492
493 /* Set:
494 * localmode=1,bmode=1,bmoderxtx=1,synthon=1,
495 * txon=1,paon=1,oscon=1,synthon_force=1
496 */
497 REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0);
498 udelay(30);
499 REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9271_AN_RF2G6_OFFS, 0);
500
501 /* find off_6_1; */
502 for (i = 6; i > 0; i--) {
503 regVal = REG_READ(ah, 0x7834);
504 regVal |= (1 << (20 + i));
505 REG_WRITE(ah, 0x7834, regVal);
506 udelay(1);
507 /* regVal = REG_READ(ah, 0x7834); */
508 regVal &= (~(0x1 << (20 + i)));
509 regVal |= (MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9)
510 << (20 + i));
511 REG_WRITE(ah, 0x7834, regVal);
512 }
513
514 regVal = (regVal >> 20) & 0x7f;
515
516 /* Update PA cal info */
517 if ((!is_reset) && (ah->pacal_info.prev_offset == regVal)) {
518 if (ah->pacal_info.max_skipcount < MAX_PACAL_SKIPCOUNT)
519 ah->pacal_info.max_skipcount =
520 2 * ah->pacal_info.max_skipcount;
521 ah->pacal_info.skipcount = ah->pacal_info.max_skipcount;
522 } else {
523 ah->pacal_info.max_skipcount = 1;
524 ah->pacal_info.skipcount = 0;
525 ah->pacal_info.prev_offset = regVal;
526 }
527
528 regVal = REG_READ(ah, 0x7834);
529 regVal |= 0x1;
530 REG_WRITE(ah, 0x7834, regVal);
531 regVal = REG_READ(ah, 0x9808);
532 regVal &= (~(0x1 << 27));
533 REG_WRITE(ah, 0x9808, regVal);
534
535 for (i = 0; i < ARRAY_SIZE(regList); i++)
536 REG_WRITE(ah, regList[i][0], regList[i][1]);
537}
538
539static inline void ar9285_hw_pa_cal(struct ath_hw *ah, bool is_reset)
540{
541 struct ath_common *common = ath9k_hw_common(ah);
542 u32 regVal;
543 int i, offset, offs_6_1, offs_0;
544 u32 ccomp_org, reg_field;
545 u32 regList[][2] = {
546 { 0x786c, 0 },
547 { 0x7854, 0 },
548 { 0x7820, 0 },
549 { 0x7824, 0 },
550 { 0x7868, 0 },
551 { 0x783c, 0 },
552 { 0x7838, 0 },
553 };
554
555 ath_print(common, ATH_DBG_CALIBRATE, "Running PA Calibration\n");
556
557 /* PA CAL is not needed for high power solution */
558 if (ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE) ==
559 AR5416_EEP_TXGAIN_HIGH_POWER)
560 return;
561
562 if (AR_SREV_9285_11(ah)) {
563 REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14));
564 udelay(10);
565 }
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 if (AR_SREV_9285_11(ah))
648 REG_WRITE(ah, AR9285_AN_TOP4, AR9285_AN_TOP4_DEFAULT);
649
650}
651
652static void ar9002_hw_pa_cal(struct ath_hw *ah, bool is_reset)
653{
654 if (AR_SREV_9271(ah)) {
655 if (is_reset || !ah->pacal_info.skipcount)
656 ar9271_hw_pa_cal(ah, is_reset);
657 else
658 ah->pacal_info.skipcount--;
659 } else if (AR_SREV_9285_11_OR_LATER(ah)) {
660 if (is_reset || !ah->pacal_info.skipcount)
661 ar9285_hw_pa_cal(ah, is_reset);
662 else
663 ah->pacal_info.skipcount--;
664 }
665}
666
667static void ar9002_hw_olc_temp_compensation(struct ath_hw *ah)
668{
669 if (OLC_FOR_AR9287_10_LATER)
670 ar9287_hw_olc_temp_compensation(ah);
671 else if (OLC_FOR_AR9280_20_LATER)
672 ar9280_hw_olc_temp_compensation(ah);
673}
674
675static bool ar9002_hw_calibrate(struct ath_hw *ah,
676 struct ath9k_channel *chan,
677 u8 rxchainmask,
678 bool longcal)
679{
680 bool iscaldone = true;
681 struct ath9k_cal_list *currCal = ah->cal_list_curr;
682
683 if (currCal &&
684 (currCal->calState == CAL_RUNNING ||
685 currCal->calState == CAL_WAITING)) {
686 iscaldone = ar9002_hw_per_calibration(ah, chan,
687 rxchainmask, currCal);
688 if (iscaldone) {
689 ah->cal_list_curr = currCal = currCal->calNext;
690
691 if (currCal->calState == CAL_WAITING) {
692 iscaldone = false;
693 ath9k_hw_reset_calibration(ah, currCal);
694 }
695 }
696 }
697
698 /* Do NF cal only at longer intervals */
699 if (longcal) {
700 /* Do periodic PAOffset Cal */
701 ar9002_hw_pa_cal(ah, false);
702 ar9002_hw_olc_temp_compensation(ah);
703
704 /*
705 * Get the value from the previous NF cal and update
706 * history buffer.
707 */
708 ath9k_hw_getnf(ah, chan);
709
710 /*
711 * Load the NF from history buffer of the current channel.
712 * NF is slow time-variant, so it is OK to use a historical
713 * value.
714 */
715 ath9k_hw_loadnf(ah, ah->curchan);
716
717 ath9k_hw_start_nfcal(ah);
718 }
719
720 return iscaldone;
721}
722
723/* Carrier leakage Calibration fix */
724static bool ar9285_hw_cl_cal(struct ath_hw *ah, struct ath9k_channel *chan)
725{
726 struct ath_common *common = ath9k_hw_common(ah);
727
728 REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
729 if (IS_CHAN_HT20(chan)) {
730 REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE);
731 REG_SET_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN);
732 REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
733 AR_PHY_AGC_CONTROL_FLTR_CAL);
734 REG_CLR_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE);
735 REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL);
736 if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
737 AR_PHY_AGC_CONTROL_CAL, 0, AH_WAIT_TIMEOUT)) {
738 ath_print(common, ATH_DBG_CALIBRATE, "offset "
739 "calibration failed to complete in "
740 "1ms; noisy ??\n");
741 return false;
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 ath_print(common, ATH_DBG_CALIBRATE, "offset calibration "
754 "failed to complete in 1ms; noisy ??\n");
755 return false;
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 true;
763}
764
765static bool ar9285_hw_clc(struct ath_hw *ah, struct ath9k_channel *chan)
766{
767 int i;
768 u_int32_t txgain_max;
769 u_int32_t clc_gain, gain_mask = 0, clc_num = 0;
770 u_int32_t reg_clc_I0, reg_clc_Q0;
771 u_int32_t i0_num = 0;
772 u_int32_t q0_num = 0;
773 u_int32_t total_num = 0;
774 u_int32_t reg_rf2g5_org;
775 bool retv = true;
776
777 if (!(ar9285_hw_cl_cal(ah, chan)))
778 return false;
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
821static bool ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan)
822{
823 struct ath_common *common = ath9k_hw_common(ah);
824
825 if (AR_SREV_9271(ah) || AR_SREV_9285_12_OR_LATER(ah)) {
826 if (!ar9285_hw_clc(ah, chan))
827 return false;
828 } else {
829 if (AR_SREV_9280_10_OR_LATER(ah)) {
830 if (!AR_SREV_9287_10_OR_LATER(ah))
831 REG_CLR_BIT(ah, AR_PHY_ADC_CTL,
832 AR_PHY_ADC_CTL_OFF_PWDADC);
833 REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
834 AR_PHY_AGC_CONTROL_FLTR_CAL);
835 }
836
837 /* Calibrate the AGC */
838 REG_WRITE(ah, AR_PHY_AGC_CONTROL,
839 REG_READ(ah, AR_PHY_AGC_CONTROL) |
840 AR_PHY_AGC_CONTROL_CAL);
841
842 /* Poll for offset calibration complete */
843 if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
844 AR_PHY_AGC_CONTROL_CAL,
845 0, AH_WAIT_TIMEOUT)) {
846 ath_print(common, ATH_DBG_CALIBRATE,
847 "offset calibration failed to "
848 "complete in 1ms; noisy environment?\n");
849 return false;
850 }
851
852 if (AR_SREV_9280_10_OR_LATER(ah)) {
853 if (!AR_SREV_9287_10_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, true);
863
864 /* Do NF Calibration after DC offset and other calibrations */
865 REG_WRITE(ah, AR_PHY_AGC_CONTROL,
866 REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_NF);
867
868 ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL;
869
870 /* Enable IQ, ADC Gain and ADC DC offset CALs */
871 if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) {
872 if (ar9002_hw_iscal_supported(ah, ADC_GAIN_CAL)) {
873 INIT_CAL(&ah->adcgain_caldata);
874 INSERT_CAL(ah, &ah->adcgain_caldata);
875 ath_print(common, ATH_DBG_CALIBRATE,
876 "enabling ADC Gain Calibration.\n");
877 }
878 if (ar9002_hw_iscal_supported(ah, ADC_DC_CAL)) {
879 INIT_CAL(&ah->adcdc_caldata);
880 INSERT_CAL(ah, &ah->adcdc_caldata);
881 ath_print(common, ATH_DBG_CALIBRATE,
882 "enabling ADC DC Calibration.\n");
883 }
884 if (ar9002_hw_iscal_supported(ah, IQ_MISMATCH_CAL)) {
885 INIT_CAL(&ah->iq_caldata);
886 INSERT_CAL(ah, &ah->iq_caldata);
887 ath_print(common, ATH_DBG_CALIBRATE,
888 "enabling IQ Calibration.\n");
889 }
890
891 ah->cal_list_curr = ah->cal_list;
892
893 if (ah->cal_list_curr)
894 ath9k_hw_reset_calibration(ah, ah->cal_list_curr);
895 }
896
897 chan->CalValid = 0;
898
899 return true;
900}
901
902static const struct ath9k_percal_data iq_cal_multi_sample = {
903 IQ_MISMATCH_CAL,
904 MAX_CAL_SAMPLES,
905 PER_MIN_LOG_COUNT,
906 ar9002_hw_iqcal_collect,
907 ar9002_hw_iqcalibrate
908};
909static const struct ath9k_percal_data iq_cal_single_sample = {
910 IQ_MISMATCH_CAL,
911 MIN_CAL_SAMPLES,
912 PER_MAX_LOG_COUNT,
913 ar9002_hw_iqcal_collect,
914 ar9002_hw_iqcalibrate
915};
916static const struct ath9k_percal_data adc_gain_cal_multi_sample = {
917 ADC_GAIN_CAL,
918 MAX_CAL_SAMPLES,
919 PER_MIN_LOG_COUNT,
920 ar9002_hw_adc_gaincal_collect,
921 ar9002_hw_adc_gaincal_calibrate
922};
923static const struct ath9k_percal_data adc_gain_cal_single_sample = {
924 ADC_GAIN_CAL,
925 MIN_CAL_SAMPLES,
926 PER_MAX_LOG_COUNT,
927 ar9002_hw_adc_gaincal_collect,
928 ar9002_hw_adc_gaincal_calibrate
929};
930static const struct ath9k_percal_data adc_dc_cal_multi_sample = {
931 ADC_DC_CAL,
932 MAX_CAL_SAMPLES,
933 PER_MIN_LOG_COUNT,
934 ar9002_hw_adc_dccal_collect,
935 ar9002_hw_adc_dccal_calibrate
936};
937static const struct ath9k_percal_data adc_dc_cal_single_sample = {
938 ADC_DC_CAL,
939 MIN_CAL_SAMPLES,
940 PER_MAX_LOG_COUNT,
941 ar9002_hw_adc_dccal_collect,
942 ar9002_hw_adc_dccal_calibrate
943};
944static const struct ath9k_percal_data adc_init_dc_cal = {
945 ADC_DC_INIT_CAL,
946 MIN_CAL_SAMPLES,
947 INIT_LOG_COUNT,
948 ar9002_hw_adc_dccal_collect,
949 ar9002_hw_adc_dccal_calibrate
950};
951
952static void ar9002_hw_init_cal_settings(struct ath_hw *ah)
953{
954 if (AR_SREV_9100(ah)) {
955 ah->iq_caldata.calData = &iq_cal_multi_sample;
956 ah->supp_cals = IQ_MISMATCH_CAL;
957 return;
958 }
959
960 if (AR_SREV_9160_10_OR_LATER(ah)) {
961 if (AR_SREV_9280_10_OR_LATER(ah)) {
962 ah->iq_caldata.calData = &iq_cal_single_sample;
963 ah->adcgain_caldata.calData =
964 &adc_gain_cal_single_sample;
965 ah->adcdc_caldata.calData =
966 &adc_dc_cal_single_sample;
967 ah->adcdc_calinitdata.calData =
968 &adc_init_dc_cal;
969 } else {
970 ah->iq_caldata.calData = &iq_cal_multi_sample;
971 ah->adcgain_caldata.calData =
972 &adc_gain_cal_multi_sample;
973 ah->adcdc_caldata.calData =
974 &adc_dc_cal_multi_sample;
975 ah->adcdc_calinitdata.calData =
976 &adc_init_dc_cal;
977 }
978 ah->supp_cals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL;
979 }
980}
981
982void ar9002_hw_attach_calib_ops(struct ath_hw *ah)
983{
984 struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
985 struct ath_hw_ops *ops = ath9k_hw_ops(ah);
986
987 priv_ops->init_cal_settings = ar9002_hw_init_cal_settings;
988 priv_ops->init_cal = ar9002_hw_init_cal;
989 priv_ops->setup_calibration = ar9002_hw_setup_calibration;
990 priv_ops->iscal_supported = ar9002_hw_iscal_supported;
991
992 ops->calibrate = ar9002_hw_calibrate;
993}
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
new file mode 100644
index 000000000000..6a7267764ac9
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
@@ -0,0 +1,66 @@
1/*
2 * Copyright (c) 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 "ar9003_phy.h"
20
21static void ar9003_hw_setup_calibration(struct ath_hw *ah,
22 struct ath9k_cal_list *currCal)
23{
24 /* TODO */
25}
26
27static bool ar9003_hw_calibrate(struct ath_hw *ah,
28 struct ath9k_channel *chan,
29 u8 rxchainmask,
30 bool longcal)
31{
32 /* TODO */
33 return false;
34}
35
36static bool ar9003_hw_init_cal(struct ath_hw *ah,
37 struct ath9k_channel *chan)
38{
39 /* TODO */
40 return false;
41}
42
43static void ar9003_hw_init_cal_settings(struct ath_hw *ah)
44{
45 /* TODO */
46}
47
48static bool ar9003_hw_iscal_supported(struct ath_hw *ah,
49 enum ath9k_cal_types calType)
50{
51 /* TODO */
52 return false;
53}
54
55void ar9003_hw_attach_calib_ops(struct ath_hw *ah)
56{
57 struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
58 struct ath_hw_ops *ops = ath9k_hw_ops(ah);
59
60 priv_ops->init_cal_settings = ar9003_hw_init_cal_settings;
61 priv_ops->init_cal = ar9003_hw_init_cal;
62 priv_ops->setup_calibration = ar9003_hw_setup_calibration;
63 priv_ops->iscal_supported = ar9003_hw_iscal_supported;
64
65 ops->calibrate = ar9003_hw_calibrate;
66}
diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c
index aa724c263404..085e1264fbe0 100644
--- a/drivers/net/wireless/ath/ath9k/calib.c
+++ b/drivers/net/wireless/ath/ath9k/calib.c
@@ -18,9 +18,10 @@
18#include "hw-ops.h" 18#include "hw-ops.h"
19#include "ar9002_phy.h" 19#include "ar9002_phy.h"
20 20
21/* Common calibration code */
22
21/* We can tune this as we go by monitoring really low values */ 23/* We can tune this as we go by monitoring really low values */
22#define ATH9K_NF_TOO_LOW -60 24#define ATH9K_NF_TOO_LOW -60
23#define AR9285_CLCAL_REDO_THRESH 1
24 25
25/* AR5416 may return very high value (like -31 dBm), in those cases the nf 26/* AR5416 may return very high value (like -31 dBm), in those cases the nf
26 * is incorrect and we should use the static NF value. Later we can try to 27 * is incorrect and we should use the static NF value. Later we can try to
@@ -108,44 +109,8 @@ static bool ath9k_hw_get_nf_thresh(struct ath_hw *ah,
108 return true; 109 return true;
109} 110}
110 111
111static void ath9k_hw_setup_calibration(struct ath_hw *ah, 112void ath9k_hw_reset_calibration(struct ath_hw *ah,
112 struct ath9k_cal_list *currCal) 113 struct ath9k_cal_list *currCal)
113{
114 struct ath_common *common = ath9k_hw_common(ah);
115
116 REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(0),
117 AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX,
118 currCal->calData->calCountMax);
119
120 switch (currCal->calData->calType) {
121 case IQ_MISMATCH_CAL:
122 REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ);
123 ath_print(common, ATH_DBG_CALIBRATE,
124 "starting IQ Mismatch Calibration\n");
125 break;
126 case ADC_GAIN_CAL:
127 REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_GAIN);
128 ath_print(common, ATH_DBG_CALIBRATE,
129 "starting ADC Gain Calibration\n");
130 break;
131 case ADC_DC_CAL:
132 REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_PER);
133 ath_print(common, ATH_DBG_CALIBRATE,
134 "starting ADC DC Calibration\n");
135 break;
136 case ADC_DC_INIT_CAL:
137 REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_INIT);
138 ath_print(common, ATH_DBG_CALIBRATE,
139 "starting Init ADC DC Calibration\n");
140 break;
141 }
142
143 REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0),
144 AR_PHY_TIMING_CTRL4_DO_CAL);
145}
146
147static void ath9k_hw_reset_calibration(struct ath_hw *ah,
148 struct ath9k_cal_list *currCal)
149{ 114{
150 int i; 115 int i;
151 116
@@ -163,324 +128,6 @@ static void ath9k_hw_reset_calibration(struct ath_hw *ah,
163 ah->cal_samples = 0; 128 ah->cal_samples = 0;
164} 129}
165 130
166static bool ath9k_hw_per_calibration(struct ath_hw *ah,
167 struct ath9k_channel *ichan,
168 u8 rxchainmask,
169 struct ath9k_cal_list *currCal)
170{
171 bool iscaldone = false;
172
173 if (currCal->calState == CAL_RUNNING) {
174 if (!(REG_READ(ah, AR_PHY_TIMING_CTRL4(0)) &
175 AR_PHY_TIMING_CTRL4_DO_CAL)) {
176
177 currCal->calData->calCollect(ah);
178 ah->cal_samples++;
179
180 if (ah->cal_samples >= currCal->calData->calNumSamples) {
181 int i, numChains = 0;
182 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
183 if (rxchainmask & (1 << i))
184 numChains++;
185 }
186
187 currCal->calData->calPostProc(ah, numChains);
188 ichan->CalValid |= currCal->calData->calType;
189 currCal->calState = CAL_DONE;
190 iscaldone = true;
191 } else {
192 ath9k_hw_setup_calibration(ah, currCal);
193 }
194 }
195 } else if (!(ichan->CalValid & currCal->calData->calType)) {
196 ath9k_hw_reset_calibration(ah, currCal);
197 }
198
199 return iscaldone;
200}
201
202/* Assumes you are talking about the currently configured channel */
203static bool ath9k_hw_iscal_supported(struct ath_hw *ah,
204 enum ath9k_cal_types calType)
205{
206 struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
207
208 switch (calType & ah->supp_cals) {
209 case IQ_MISMATCH_CAL: /* Both 2 GHz and 5 GHz support OFDM */
210 return true;
211 case ADC_GAIN_CAL:
212 case ADC_DC_CAL:
213 if (!(conf->channel->band == IEEE80211_BAND_2GHZ &&
214 conf_is_ht20(conf)))
215 return true;
216 break;
217 }
218 return false;
219}
220
221static void ath9k_hw_iqcal_collect(struct ath_hw *ah)
222{
223 int i;
224
225 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
226 ah->totalPowerMeasI[i] +=
227 REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
228 ah->totalPowerMeasQ[i] +=
229 REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
230 ah->totalIqCorrMeas[i] +=
231 (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
232 ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
233 "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
234 ah->cal_samples, i, ah->totalPowerMeasI[i],
235 ah->totalPowerMeasQ[i],
236 ah->totalIqCorrMeas[i]);
237 }
238}
239
240static void ath9k_hw_adc_gaincal_collect(struct ath_hw *ah)
241{
242 int i;
243
244 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
245 ah->totalAdcIOddPhase[i] +=
246 REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
247 ah->totalAdcIEvenPhase[i] +=
248 REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
249 ah->totalAdcQOddPhase[i] +=
250 REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
251 ah->totalAdcQEvenPhase[i] +=
252 REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
253
254 ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
255 "%d: Chn %d oddi=0x%08x; eveni=0x%08x; "
256 "oddq=0x%08x; evenq=0x%08x;\n",
257 ah->cal_samples, i,
258 ah->totalAdcIOddPhase[i],
259 ah->totalAdcIEvenPhase[i],
260 ah->totalAdcQOddPhase[i],
261 ah->totalAdcQEvenPhase[i]);
262 }
263}
264
265static void ath9k_hw_adc_dccal_collect(struct ath_hw *ah)
266{
267 int i;
268
269 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
270 ah->totalAdcDcOffsetIOddPhase[i] +=
271 (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
272 ah->totalAdcDcOffsetIEvenPhase[i] +=
273 (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
274 ah->totalAdcDcOffsetQOddPhase[i] +=
275 (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
276 ah->totalAdcDcOffsetQEvenPhase[i] +=
277 (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
278
279 ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
280 "%d: Chn %d oddi=0x%08x; eveni=0x%08x; "
281 "oddq=0x%08x; evenq=0x%08x;\n",
282 ah->cal_samples, i,
283 ah->totalAdcDcOffsetIOddPhase[i],
284 ah->totalAdcDcOffsetIEvenPhase[i],
285 ah->totalAdcDcOffsetQOddPhase[i],
286 ah->totalAdcDcOffsetQEvenPhase[i]);
287 }
288}
289
290static void ath9k_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
291{
292 struct ath_common *common = ath9k_hw_common(ah);
293 u32 powerMeasQ, powerMeasI, iqCorrMeas;
294 u32 qCoffDenom, iCoffDenom;
295 int32_t qCoff, iCoff;
296 int iqCorrNeg, i;
297
298 for (i = 0; i < numChains; i++) {
299 powerMeasI = ah->totalPowerMeasI[i];
300 powerMeasQ = ah->totalPowerMeasQ[i];
301 iqCorrMeas = ah->totalIqCorrMeas[i];
302
303 ath_print(common, ATH_DBG_CALIBRATE,
304 "Starting IQ Cal and Correction for Chain %d\n",
305 i);
306
307 ath_print(common, ATH_DBG_CALIBRATE,
308 "Orignal: Chn %diq_corr_meas = 0x%08x\n",
309 i, ah->totalIqCorrMeas[i]);
310
311 iqCorrNeg = 0;
312
313 if (iqCorrMeas > 0x80000000) {
314 iqCorrMeas = (0xffffffff - iqCorrMeas) + 1;
315 iqCorrNeg = 1;
316 }
317
318 ath_print(common, ATH_DBG_CALIBRATE,
319 "Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI);
320 ath_print(common, ATH_DBG_CALIBRATE,
321 "Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ);
322 ath_print(common, ATH_DBG_CALIBRATE, "iqCorrNeg is 0x%08x\n",
323 iqCorrNeg);
324
325 iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128;
326 qCoffDenom = powerMeasQ / 64;
327
328 if ((powerMeasQ != 0) && (iCoffDenom != 0) &&
329 (qCoffDenom != 0)) {
330 iCoff = iqCorrMeas / iCoffDenom;
331 qCoff = powerMeasI / qCoffDenom - 64;
332 ath_print(common, ATH_DBG_CALIBRATE,
333 "Chn %d iCoff = 0x%08x\n", i, iCoff);
334 ath_print(common, ATH_DBG_CALIBRATE,
335 "Chn %d qCoff = 0x%08x\n", i, qCoff);
336
337 iCoff = iCoff & 0x3f;
338 ath_print(common, ATH_DBG_CALIBRATE,
339 "New: Chn %d iCoff = 0x%08x\n", i, iCoff);
340 if (iqCorrNeg == 0x0)
341 iCoff = 0x40 - iCoff;
342
343 if (qCoff > 15)
344 qCoff = 15;
345 else if (qCoff <= -16)
346 qCoff = 16;
347
348 ath_print(common, ATH_DBG_CALIBRATE,
349 "Chn %d : iCoff = 0x%x qCoff = 0x%x\n",
350 i, iCoff, qCoff);
351
352 REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i),
353 AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF,
354 iCoff);
355 REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i),
356 AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF,
357 qCoff);
358 ath_print(common, ATH_DBG_CALIBRATE,
359 "IQ Cal and Correction done for Chain %d\n",
360 i);
361 }
362 }
363
364 REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0),
365 AR_PHY_TIMING_CTRL4_IQCORR_ENABLE);
366}
367
368static void ath9k_hw_adc_gaincal_calibrate(struct ath_hw *ah, u8 numChains)
369{
370 struct ath_common *common = ath9k_hw_common(ah);
371 u32 iOddMeasOffset, iEvenMeasOffset, qOddMeasOffset, qEvenMeasOffset;
372 u32 qGainMismatch, iGainMismatch, val, i;
373
374 for (i = 0; i < numChains; i++) {
375 iOddMeasOffset = ah->totalAdcIOddPhase[i];
376 iEvenMeasOffset = ah->totalAdcIEvenPhase[i];
377 qOddMeasOffset = ah->totalAdcQOddPhase[i];
378 qEvenMeasOffset = ah->totalAdcQEvenPhase[i];
379
380 ath_print(common, ATH_DBG_CALIBRATE,
381 "Starting ADC Gain Cal for Chain %d\n", i);
382
383 ath_print(common, ATH_DBG_CALIBRATE,
384 "Chn %d pwr_meas_odd_i = 0x%08x\n", i,
385 iOddMeasOffset);
386 ath_print(common, ATH_DBG_CALIBRATE,
387 "Chn %d pwr_meas_even_i = 0x%08x\n", i,
388 iEvenMeasOffset);
389 ath_print(common, ATH_DBG_CALIBRATE,
390 "Chn %d pwr_meas_odd_q = 0x%08x\n", i,
391 qOddMeasOffset);
392 ath_print(common, ATH_DBG_CALIBRATE,
393 "Chn %d pwr_meas_even_q = 0x%08x\n", i,
394 qEvenMeasOffset);
395
396 if (iOddMeasOffset != 0 && qEvenMeasOffset != 0) {
397 iGainMismatch =
398 ((iEvenMeasOffset * 32) /
399 iOddMeasOffset) & 0x3f;
400 qGainMismatch =
401 ((qOddMeasOffset * 32) /
402 qEvenMeasOffset) & 0x3f;
403
404 ath_print(common, ATH_DBG_CALIBRATE,
405 "Chn %d gain_mismatch_i = 0x%08x\n", i,
406 iGainMismatch);
407 ath_print(common, ATH_DBG_CALIBRATE,
408 "Chn %d gain_mismatch_q = 0x%08x\n", i,
409 qGainMismatch);
410
411 val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
412 val &= 0xfffff000;
413 val |= (qGainMismatch) | (iGainMismatch << 6);
414 REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
415
416 ath_print(common, ATH_DBG_CALIBRATE,
417 "ADC Gain Cal done for Chain %d\n", i);
418 }
419 }
420
421 REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
422 REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
423 AR_PHY_NEW_ADC_GAIN_CORR_ENABLE);
424}
425
426static void ath9k_hw_adc_dccal_calibrate(struct ath_hw *ah, u8 numChains)
427{
428 struct ath_common *common = ath9k_hw_common(ah);
429 u32 iOddMeasOffset, iEvenMeasOffset, val, i;
430 int32_t qOddMeasOffset, qEvenMeasOffset, qDcMismatch, iDcMismatch;
431 const struct ath9k_percal_data *calData =
432 ah->cal_list_curr->calData;
433 u32 numSamples =
434 (1 << (calData->calCountMax + 5)) * calData->calNumSamples;
435
436 for (i = 0; i < numChains; i++) {
437 iOddMeasOffset = ah->totalAdcDcOffsetIOddPhase[i];
438 iEvenMeasOffset = ah->totalAdcDcOffsetIEvenPhase[i];
439 qOddMeasOffset = ah->totalAdcDcOffsetQOddPhase[i];
440 qEvenMeasOffset = ah->totalAdcDcOffsetQEvenPhase[i];
441
442 ath_print(common, ATH_DBG_CALIBRATE,
443 "Starting ADC DC Offset Cal for Chain %d\n", i);
444
445 ath_print(common, ATH_DBG_CALIBRATE,
446 "Chn %d pwr_meas_odd_i = %d\n", i,
447 iOddMeasOffset);
448 ath_print(common, ATH_DBG_CALIBRATE,
449 "Chn %d pwr_meas_even_i = %d\n", i,
450 iEvenMeasOffset);
451 ath_print(common, ATH_DBG_CALIBRATE,
452 "Chn %d pwr_meas_odd_q = %d\n", i,
453 qOddMeasOffset);
454 ath_print(common, ATH_DBG_CALIBRATE,
455 "Chn %d pwr_meas_even_q = %d\n", i,
456 qEvenMeasOffset);
457
458 iDcMismatch = (((iEvenMeasOffset - iOddMeasOffset) * 2) /
459 numSamples) & 0x1ff;
460 qDcMismatch = (((qOddMeasOffset - qEvenMeasOffset) * 2) /
461 numSamples) & 0x1ff;
462
463 ath_print(common, ATH_DBG_CALIBRATE,
464 "Chn %d dc_offset_mismatch_i = 0x%08x\n", i,
465 iDcMismatch);
466 ath_print(common, ATH_DBG_CALIBRATE,
467 "Chn %d dc_offset_mismatch_q = 0x%08x\n", i,
468 qDcMismatch);
469
470 val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
471 val &= 0xc0000fff;
472 val |= (qDcMismatch << 12) | (iDcMismatch << 21);
473 REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
474
475 ath_print(common, ATH_DBG_CALIBRATE,
476 "ADC DC Offset Cal done for Chain %d\n", i);
477 }
478
479 REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
480 REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
481 AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE);
482}
483
484/* This is done for the currently configured channel */ 131/* This is done for the currently configured channel */
485bool ath9k_hw_reset_calvalid(struct ath_hw *ah) 132bool ath9k_hw_reset_calvalid(struct ath_hw *ah)
486{ 133{
@@ -670,570 +317,3 @@ s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan)
670 return nf; 317 return nf;
671} 318}
672EXPORT_SYMBOL(ath9k_hw_getchan_noise); 319EXPORT_SYMBOL(ath9k_hw_getchan_noise);
673
674static void ar9287_hw_olc_temp_compensation(struct ath_hw *ah)
675{
676 u32 rddata;
677 int32_t delta, currPDADC, slope;
678
679 rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4);
680 currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT);
681
682 if (ah->initPDADC == 0 || currPDADC == 0) {
683 /*
684 * Zero value indicates that no frames have been transmitted yet,
685 * can't do temperature compensation until frames are transmitted.
686 */
687 return;
688 } else {
689 slope = ah->eep_ops->get_eeprom(ah, EEP_TEMPSENSE_SLOPE);
690
691 if (slope == 0) { /* to avoid divide by zero case */
692 delta = 0;
693 } else {
694 delta = ((currPDADC - ah->initPDADC)*4) / slope;
695 }
696 REG_RMW_FIELD(ah, AR_PHY_CH0_TX_PWRCTRL11,
697 AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta);
698 REG_RMW_FIELD(ah, AR_PHY_CH1_TX_PWRCTRL11,
699 AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta);
700 }
701}
702
703static void ar9280_hw_olc_temp_compensation(struct ath_hw *ah)
704{
705 u32 rddata, i;
706 int delta, currPDADC, regval;
707
708 rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4);
709 currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT);
710
711 if (ah->initPDADC == 0 || currPDADC == 0)
712 return;
713
714 if (ah->eep_ops->get_eeprom(ah, EEP_DAC_HPWR_5G))
715 delta = (currPDADC - ah->initPDADC + 4) / 8;
716 else
717 delta = (currPDADC - ah->initPDADC + 5) / 10;
718
719 if (delta != ah->PDADCdelta) {
720 ah->PDADCdelta = delta;
721 for (i = 1; i < AR9280_TX_GAIN_TABLE_SIZE; i++) {
722 regval = ah->originalGain[i] - delta;
723 if (regval < 0)
724 regval = 0;
725
726 REG_RMW_FIELD(ah,
727 AR_PHY_TX_GAIN_TBL1 + i * 4,
728 AR_PHY_TX_GAIN, regval);
729 }
730 }
731}
732
733static void ar9271_hw_pa_cal(struct ath_hw *ah, bool is_reset)
734{
735 u32 regVal;
736 unsigned int i;
737 u32 regList [][2] = {
738 { 0x786c, 0 },
739 { 0x7854, 0 },
740 { 0x7820, 0 },
741 { 0x7824, 0 },
742 { 0x7868, 0 },
743 { 0x783c, 0 },
744 { 0x7838, 0 } ,
745 { 0x7828, 0 } ,
746 };
747
748 for (i = 0; i < ARRAY_SIZE(regList); i++)
749 regList[i][1] = REG_READ(ah, regList[i][0]);
750
751 regVal = REG_READ(ah, 0x7834);
752 regVal &= (~(0x1));
753 REG_WRITE(ah, 0x7834, regVal);
754 regVal = REG_READ(ah, 0x9808);
755 regVal |= (0x1 << 27);
756 REG_WRITE(ah, 0x9808, regVal);
757
758 /* 786c,b23,1, pwddac=1 */
759 REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1);
760 /* 7854, b5,1, pdrxtxbb=1 */
761 REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1);
762 /* 7854, b7,1, pdv2i=1 */
763 REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1);
764 /* 7854, b8,1, pddacinterface=1 */
765 REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1);
766 /* 7824,b12,0, offcal=0 */
767 REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0);
768 /* 7838, b1,0, pwddb=0 */
769 REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0);
770 /* 7820,b11,0, enpacal=0 */
771 REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0);
772 /* 7820,b25,1, pdpadrv1=0 */
773 REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 0);
774 /* 7820,b24,0, pdpadrv2=0 */
775 REG_RMW_FIELD(ah, AR9285_AN_RF2G1,AR9285_AN_RF2G1_PDPADRV2,0);
776 /* 7820,b23,0, pdpaout=0 */
777 REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0);
778 /* 783c,b14-16,7, padrvgn2tab_0=7 */
779 REG_RMW_FIELD(ah, AR9285_AN_RF2G8,AR9285_AN_RF2G8_PADRVGN2TAB0, 7);
780 /*
781 * 7838,b29-31,0, padrvgn1tab_0=0
782 * does not matter since we turn it off
783 */
784 REG_RMW_FIELD(ah, AR9285_AN_RF2G7,AR9285_AN_RF2G7_PADRVGN2TAB0, 0);
785
786 REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9271_AN_RF2G3_CCOMP, 0xfff);
787
788 /* Set:
789 * localmode=1,bmode=1,bmoderxtx=1,synthon=1,
790 * txon=1,paon=1,oscon=1,synthon_force=1
791 */
792 REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0);
793 udelay(30);
794 REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9271_AN_RF2G6_OFFS, 0);
795
796 /* find off_6_1; */
797 for (i = 6; i > 0; i--) {
798 regVal = REG_READ(ah, 0x7834);
799 regVal |= (1 << (20 + i));
800 REG_WRITE(ah, 0x7834, regVal);
801 udelay(1);
802 //regVal = REG_READ(ah, 0x7834);
803 regVal &= (~(0x1 << (20 + i)));
804 regVal |= (MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9)
805 << (20 + i));
806 REG_WRITE(ah, 0x7834, regVal);
807 }
808
809 regVal = (regVal >>20) & 0x7f;
810
811 /* Update PA cal info */
812 if ((!is_reset) && (ah->pacal_info.prev_offset == regVal)) {
813 if (ah->pacal_info.max_skipcount < MAX_PACAL_SKIPCOUNT)
814 ah->pacal_info.max_skipcount =
815 2 * ah->pacal_info.max_skipcount;
816 ah->pacal_info.skipcount = ah->pacal_info.max_skipcount;
817 } else {
818 ah->pacal_info.max_skipcount = 1;
819 ah->pacal_info.skipcount = 0;
820 ah->pacal_info.prev_offset = regVal;
821 }
822
823 regVal = REG_READ(ah, 0x7834);
824 regVal |= 0x1;
825 REG_WRITE(ah, 0x7834, regVal);
826 regVal = REG_READ(ah, 0x9808);
827 regVal &= (~(0x1 << 27));
828 REG_WRITE(ah, 0x9808, regVal);
829
830 for (i = 0; i < ARRAY_SIZE(regList); i++)
831 REG_WRITE(ah, regList[i][0], regList[i][1]);
832}
833
834static inline void ar9285_hw_pa_cal(struct ath_hw *ah, bool is_reset)
835{
836 struct ath_common *common = ath9k_hw_common(ah);
837 u32 regVal;
838 int i, offset, offs_6_1, offs_0;
839 u32 ccomp_org, reg_field;
840 u32 regList[][2] = {
841 { 0x786c, 0 },
842 { 0x7854, 0 },
843 { 0x7820, 0 },
844 { 0x7824, 0 },
845 { 0x7868, 0 },
846 { 0x783c, 0 },
847 { 0x7838, 0 },
848 };
849
850 ath_print(common, ATH_DBG_CALIBRATE, "Running PA Calibration\n");
851
852 /* PA CAL is not needed for high power solution */
853 if (ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE) ==
854 AR5416_EEP_TXGAIN_HIGH_POWER)
855 return;
856
857 if (AR_SREV_9285_11(ah)) {
858 REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14));
859 udelay(10);
860 }
861
862 for (i = 0; i < ARRAY_SIZE(regList); i++)
863 regList[i][1] = REG_READ(ah, regList[i][0]);
864
865 regVal = REG_READ(ah, 0x7834);
866 regVal &= (~(0x1));
867 REG_WRITE(ah, 0x7834, regVal);
868 regVal = REG_READ(ah, 0x9808);
869 regVal |= (0x1 << 27);
870 REG_WRITE(ah, 0x9808, regVal);
871
872 REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1);
873 REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1);
874 REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1);
875 REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1);
876 REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0);
877 REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0);
878 REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0);
879 REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 0);
880 REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2, 0);
881 REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0);
882 REG_RMW_FIELD(ah, AR9285_AN_RF2G8, AR9285_AN_RF2G8_PADRVGN2TAB0, 7);
883 REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PADRVGN2TAB0, 0);
884 ccomp_org = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_CCOMP);
885 REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, 0xf);
886
887 REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0);
888 udelay(30);
889 REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, 0);
890 REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 0);
891
892 for (i = 6; i > 0; i--) {
893 regVal = REG_READ(ah, 0x7834);
894 regVal |= (1 << (19 + i));
895 REG_WRITE(ah, 0x7834, regVal);
896 udelay(1);
897 regVal = REG_READ(ah, 0x7834);
898 regVal &= (~(0x1 << (19 + i)));
899 reg_field = MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9);
900 regVal |= (reg_field << (19 + i));
901 REG_WRITE(ah, 0x7834, regVal);
902 }
903
904 REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 1);
905 udelay(1);
906 reg_field = MS(REG_READ(ah, AR9285_AN_RF2G9), AR9285_AN_RXTXBB1_SPARE9);
907 REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, reg_field);
908 offs_6_1 = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_OFFS);
909 offs_0 = MS(REG_READ(ah, AR9285_AN_RF2G3), AR9285_AN_RF2G3_PDVCCOMP);
910
911 offset = (offs_6_1<<1) | offs_0;
912 offset = offset - 0;
913 offs_6_1 = offset>>1;
914 offs_0 = offset & 1;
915
916 if ((!is_reset) && (ah->pacal_info.prev_offset == offset)) {
917 if (ah->pacal_info.max_skipcount < MAX_PACAL_SKIPCOUNT)
918 ah->pacal_info.max_skipcount =
919 2 * ah->pacal_info.max_skipcount;
920 ah->pacal_info.skipcount = ah->pacal_info.max_skipcount;
921 } else {
922 ah->pacal_info.max_skipcount = 1;
923 ah->pacal_info.skipcount = 0;
924 ah->pacal_info.prev_offset = offset;
925 }
926
927 REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, offs_6_1);
928 REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, offs_0);
929
930 regVal = REG_READ(ah, 0x7834);
931 regVal |= 0x1;
932 REG_WRITE(ah, 0x7834, regVal);
933 regVal = REG_READ(ah, 0x9808);
934 regVal &= (~(0x1 << 27));
935 REG_WRITE(ah, 0x9808, regVal);
936
937 for (i = 0; i < ARRAY_SIZE(regList); i++)
938 REG_WRITE(ah, regList[i][0], regList[i][1]);
939
940 REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, ccomp_org);
941
942 if (AR_SREV_9285_11(ah))
943 REG_WRITE(ah, AR9285_AN_TOP4, AR9285_AN_TOP4_DEFAULT);
944
945}
946
947static void ar9002_hw_pa_cal(struct ath_hw *ah, bool is_reset)
948{
949 if (AR_SREV_9271(ah)) {
950 if (is_reset || !ah->pacal_info.skipcount)
951 ar9271_hw_pa_cal(ah, is_reset);
952 else
953 ah->pacal_info.skipcount--;
954 } else if (AR_SREV_9285_11_OR_LATER(ah)) {
955 if (is_reset || !ah->pacal_info.skipcount)
956 ar9285_hw_pa_cal(ah, is_reset);
957 else
958 ah->pacal_info.skipcount--;
959 }
960}
961
962static void ar9002_hw_olc_temp_compensation(struct ath_hw *ah)
963{
964 if (OLC_FOR_AR9287_10_LATER)
965 ar9287_hw_olc_temp_compensation(ah);
966 else if (OLC_FOR_AR9280_20_LATER)
967 ar9280_hw_olc_temp_compensation(ah);
968}
969
970bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan,
971 u8 rxchainmask, bool longcal)
972{
973 bool iscaldone = true;
974 struct ath9k_cal_list *currCal = ah->cal_list_curr;
975
976 if (currCal &&
977 (currCal->calState == CAL_RUNNING ||
978 currCal->calState == CAL_WAITING)) {
979 iscaldone = ath9k_hw_per_calibration(ah, chan,
980 rxchainmask, currCal);
981 if (iscaldone) {
982 ah->cal_list_curr = currCal = currCal->calNext;
983
984 if (currCal->calState == CAL_WAITING) {
985 iscaldone = false;
986 ath9k_hw_reset_calibration(ah, currCal);
987 }
988 }
989 }
990
991 /* Do NF cal only at longer intervals */
992 if (longcal) {
993 /* Do periodic PAOffset Cal */
994 ar9002_hw_pa_cal(ah, false);
995 ar9002_hw_olc_temp_compensation(ah);
996
997 /* Get the value from the previous NF cal and update history buffer */
998 ath9k_hw_getnf(ah, chan);
999
1000 /*
1001 * Load the NF from history buffer of the current channel.
1002 * NF is slow time-variant, so it is OK to use a historical value.
1003 */
1004 ath9k_hw_loadnf(ah, ah->curchan);
1005
1006 ath9k_hw_start_nfcal(ah);
1007 }
1008
1009 return iscaldone;
1010}
1011EXPORT_SYMBOL(ath9k_hw_calibrate);
1012
1013/* Carrier leakage Calibration fix */
1014static bool ar9285_cl_cal(struct ath_hw *ah, struct ath9k_channel *chan)
1015{
1016 struct ath_common *common = ath9k_hw_common(ah);
1017
1018 REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
1019 if (IS_CHAN_HT20(chan)) {
1020 REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE);
1021 REG_SET_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN);
1022 REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
1023 AR_PHY_AGC_CONTROL_FLTR_CAL);
1024 REG_CLR_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE);
1025 REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL);
1026 if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
1027 AR_PHY_AGC_CONTROL_CAL, 0, AH_WAIT_TIMEOUT)) {
1028 ath_print(common, ATH_DBG_CALIBRATE, "offset "
1029 "calibration failed to complete in "
1030 "1ms; noisy ??\n");
1031 return false;
1032 }
1033 REG_CLR_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN);
1034 REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE);
1035 REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
1036 }
1037 REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
1038 REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL);
1039 REG_SET_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE);
1040 REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL);
1041 if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL,
1042 0, AH_WAIT_TIMEOUT)) {
1043 ath_print(common, ATH_DBG_CALIBRATE, "offset calibration "
1044 "failed to complete in 1ms; noisy ??\n");
1045 return false;
1046 }
1047
1048 REG_SET_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
1049 REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
1050 REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL);
1051
1052 return true;
1053}
1054
1055static bool ar9285_clc(struct ath_hw *ah, struct ath9k_channel *chan)
1056{
1057 int i;
1058 u_int32_t txgain_max;
1059 u_int32_t clc_gain, gain_mask = 0, clc_num = 0;
1060 u_int32_t reg_clc_I0, reg_clc_Q0;
1061 u_int32_t i0_num = 0;
1062 u_int32_t q0_num = 0;
1063 u_int32_t total_num = 0;
1064 u_int32_t reg_rf2g5_org;
1065 bool retv = true;
1066
1067 if (!(ar9285_cl_cal(ah, chan)))
1068 return false;
1069
1070 txgain_max = MS(REG_READ(ah, AR_PHY_TX_PWRCTRL7),
1071 AR_PHY_TX_PWRCTRL_TX_GAIN_TAB_MAX);
1072
1073 for (i = 0; i < (txgain_max+1); i++) {
1074 clc_gain = (REG_READ(ah, (AR_PHY_TX_GAIN_TBL1+(i<<2))) &
1075 AR_PHY_TX_GAIN_CLC) >> AR_PHY_TX_GAIN_CLC_S;
1076 if (!(gain_mask & (1 << clc_gain))) {
1077 gain_mask |= (1 << clc_gain);
1078 clc_num++;
1079 }
1080 }
1081
1082 for (i = 0; i < clc_num; i++) {
1083 reg_clc_I0 = (REG_READ(ah, (AR_PHY_CLC_TBL1 + (i << 2)))
1084 & AR_PHY_CLC_I0) >> AR_PHY_CLC_I0_S;
1085 reg_clc_Q0 = (REG_READ(ah, (AR_PHY_CLC_TBL1 + (i << 2)))
1086 & AR_PHY_CLC_Q0) >> AR_PHY_CLC_Q0_S;
1087 if (reg_clc_I0 == 0)
1088 i0_num++;
1089
1090 if (reg_clc_Q0 == 0)
1091 q0_num++;
1092 }
1093 total_num = i0_num + q0_num;
1094 if (total_num > AR9285_CLCAL_REDO_THRESH) {
1095 reg_rf2g5_org = REG_READ(ah, AR9285_RF2G5);
1096 if (AR_SREV_9285E_20(ah)) {
1097 REG_WRITE(ah, AR9285_RF2G5,
1098 (reg_rf2g5_org & AR9285_RF2G5_IC50TX) |
1099 AR9285_RF2G5_IC50TX_XE_SET);
1100 } else {
1101 REG_WRITE(ah, AR9285_RF2G5,
1102 (reg_rf2g5_org & AR9285_RF2G5_IC50TX) |
1103 AR9285_RF2G5_IC50TX_SET);
1104 }
1105 retv = ar9285_cl_cal(ah, chan);
1106 REG_WRITE(ah, AR9285_RF2G5, reg_rf2g5_org);
1107 }
1108 return retv;
1109}
1110
1111bool ath9k_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan)
1112{
1113 struct ath_common *common = ath9k_hw_common(ah);
1114
1115 if (AR_SREV_9271(ah) || AR_SREV_9285_12_OR_LATER(ah)) {
1116 if (!ar9285_clc(ah, chan))
1117 return false;
1118 } else {
1119 if (AR_SREV_9280_10_OR_LATER(ah)) {
1120 if (!AR_SREV_9287_10_OR_LATER(ah))
1121 REG_CLR_BIT(ah, AR_PHY_ADC_CTL,
1122 AR_PHY_ADC_CTL_OFF_PWDADC);
1123 REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
1124 AR_PHY_AGC_CONTROL_FLTR_CAL);
1125 }
1126
1127 /* Calibrate the AGC */
1128 REG_WRITE(ah, AR_PHY_AGC_CONTROL,
1129 REG_READ(ah, AR_PHY_AGC_CONTROL) |
1130 AR_PHY_AGC_CONTROL_CAL);
1131
1132 /* Poll for offset calibration complete */
1133 if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL,
1134 0, AH_WAIT_TIMEOUT)) {
1135 ath_print(common, ATH_DBG_CALIBRATE,
1136 "offset calibration failed to "
1137 "complete in 1ms; noisy environment?\n");
1138 return false;
1139 }
1140
1141 if (AR_SREV_9280_10_OR_LATER(ah)) {
1142 if (!AR_SREV_9287_10_OR_LATER(ah))
1143 REG_SET_BIT(ah, AR_PHY_ADC_CTL,
1144 AR_PHY_ADC_CTL_OFF_PWDADC);
1145 REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
1146 AR_PHY_AGC_CONTROL_FLTR_CAL);
1147 }
1148 }
1149
1150 /* Do PA Calibration */
1151 ar9002_hw_pa_cal(ah, true);
1152
1153 /* Do NF Calibration after DC offset and other calibrations */
1154 REG_WRITE(ah, AR_PHY_AGC_CONTROL,
1155 REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_NF);
1156
1157 ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL;
1158
1159 /* Enable IQ, ADC Gain and ADC DC offset CALs */
1160 if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) {
1161 if (ath9k_hw_iscal_supported(ah, ADC_GAIN_CAL)) {
1162 INIT_CAL(&ah->adcgain_caldata);
1163 INSERT_CAL(ah, &ah->adcgain_caldata);
1164 ath_print(common, ATH_DBG_CALIBRATE,
1165 "enabling ADC Gain Calibration.\n");
1166 }
1167 if (ath9k_hw_iscal_supported(ah, ADC_DC_CAL)) {
1168 INIT_CAL(&ah->adcdc_caldata);
1169 INSERT_CAL(ah, &ah->adcdc_caldata);
1170 ath_print(common, ATH_DBG_CALIBRATE,
1171 "enabling ADC DC Calibration.\n");
1172 }
1173 if (ath9k_hw_iscal_supported(ah, IQ_MISMATCH_CAL)) {
1174 INIT_CAL(&ah->iq_caldata);
1175 INSERT_CAL(ah, &ah->iq_caldata);
1176 ath_print(common, ATH_DBG_CALIBRATE,
1177 "enabling IQ Calibration.\n");
1178 }
1179
1180 ah->cal_list_curr = ah->cal_list;
1181
1182 if (ah->cal_list_curr)
1183 ath9k_hw_reset_calibration(ah, ah->cal_list_curr);
1184 }
1185
1186 chan->CalValid = 0;
1187
1188 return true;
1189}
1190
1191const struct ath9k_percal_data iq_cal_multi_sample = {
1192 IQ_MISMATCH_CAL,
1193 MAX_CAL_SAMPLES,
1194 PER_MIN_LOG_COUNT,
1195 ath9k_hw_iqcal_collect,
1196 ath9k_hw_iqcalibrate
1197};
1198const struct ath9k_percal_data iq_cal_single_sample = {
1199 IQ_MISMATCH_CAL,
1200 MIN_CAL_SAMPLES,
1201 PER_MAX_LOG_COUNT,
1202 ath9k_hw_iqcal_collect,
1203 ath9k_hw_iqcalibrate
1204};
1205const struct ath9k_percal_data adc_gain_cal_multi_sample = {
1206 ADC_GAIN_CAL,
1207 MAX_CAL_SAMPLES,
1208 PER_MIN_LOG_COUNT,
1209 ath9k_hw_adc_gaincal_collect,
1210 ath9k_hw_adc_gaincal_calibrate
1211};
1212const struct ath9k_percal_data adc_gain_cal_single_sample = {
1213 ADC_GAIN_CAL,
1214 MIN_CAL_SAMPLES,
1215 PER_MAX_LOG_COUNT,
1216 ath9k_hw_adc_gaincal_collect,
1217 ath9k_hw_adc_gaincal_calibrate
1218};
1219const struct ath9k_percal_data adc_dc_cal_multi_sample = {
1220 ADC_DC_CAL,
1221 MAX_CAL_SAMPLES,
1222 PER_MIN_LOG_COUNT,
1223 ath9k_hw_adc_dccal_collect,
1224 ath9k_hw_adc_dccal_calibrate
1225};
1226const struct ath9k_percal_data adc_dc_cal_single_sample = {
1227 ADC_DC_CAL,
1228 MIN_CAL_SAMPLES,
1229 PER_MAX_LOG_COUNT,
1230 ath9k_hw_adc_dccal_collect,
1231 ath9k_hw_adc_dccal_calibrate
1232};
1233const struct ath9k_percal_data adc_init_dc_cal = {
1234 ADC_DC_INIT_CAL,
1235 MIN_CAL_SAMPLES,
1236 INIT_LOG_COUNT,
1237 ath9k_hw_adc_dccal_collect,
1238 ath9k_hw_adc_dccal_calibrate
1239};
diff --git a/drivers/net/wireless/ath/ath9k/calib.h b/drivers/net/wireless/ath/ath9k/calib.h
index b2c873e97485..9f6c21d50f17 100644
--- a/drivers/net/wireless/ath/ath9k/calib.h
+++ b/drivers/net/wireless/ath/ath9k/calib.h
@@ -19,14 +19,6 @@
19 19
20#include "hw.h" 20#include "hw.h"
21 21
22extern const struct ath9k_percal_data iq_cal_multi_sample;
23extern const struct ath9k_percal_data iq_cal_single_sample;
24extern const struct ath9k_percal_data adc_gain_cal_multi_sample;
25extern const struct ath9k_percal_data adc_gain_cal_single_sample;
26extern const struct ath9k_percal_data adc_dc_cal_multi_sample;
27extern const struct ath9k_percal_data adc_dc_cal_single_sample;
28extern const struct ath9k_percal_data adc_init_dc_cal;
29
30#define AR_PHY_CCA_MAX_AR5416_GOOD_VALUE -85 22#define AR_PHY_CCA_MAX_AR5416_GOOD_VALUE -85
31#define AR_PHY_CCA_MAX_AR9280_GOOD_VALUE -112 23#define AR_PHY_CCA_MAX_AR9280_GOOD_VALUE -112
32#define AR_PHY_CCA_MAX_AR9285_GOOD_VALUE -118 24#define AR_PHY_CCA_MAX_AR9285_GOOD_VALUE -118
@@ -127,9 +119,8 @@ int16_t ath9k_hw_getnf(struct ath_hw *ah,
127 struct ath9k_channel *chan); 119 struct ath9k_channel *chan);
128void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah); 120void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah);
129s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan); 121s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan);
130bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, 122void ath9k_hw_reset_calibration(struct ath_hw *ah,
131 u8 rxchainmask, bool longcal); 123 struct ath9k_cal_list *currCal);
132bool ath9k_hw_init_cal(struct ath_hw *ah, 124
133 struct ath9k_channel *chan);
134 125
135#endif /* CALIB_H */ 126#endif /* CALIB_H */
diff --git a/drivers/net/wireless/ath/ath9k/hw-ops.h b/drivers/net/wireless/ath/ath9k/hw-ops.h
index e2b8ad4df904..3848c0d3f99e 100644
--- a/drivers/net/wireless/ath/ath9k/hw-ops.h
+++ b/drivers/net/wireless/ath/ath9k/hw-ops.h
@@ -44,6 +44,14 @@ static inline void ath9k_hw_get_desc_link(struct ath_hw *ah, void *ds,
44{ 44{
45 ath9k_hw_ops(ah)->get_desc_link(ds, link); 45 ath9k_hw_ops(ah)->get_desc_link(ds, link);
46} 46}
47static inline bool ath9k_hw_calibrate(struct ath_hw *ah,
48 struct ath9k_channel *chan,
49 u8 rxchainmask,
50 bool longcal)
51{
52 return ath9k_hw_ops(ah)->calibrate(ah, chan, rxchainmask, longcal);
53}
54
47/* Private hardware call ops */ 55/* Private hardware call ops */
48 56
49/* PHY ops */ 57/* PHY ops */
@@ -166,7 +174,25 @@ static inline bool ath9k_hw_ani_control(struct ath_hw *ah,
166static inline void ath9k_hw_do_getnf(struct ath_hw *ah, 174static inline void ath9k_hw_do_getnf(struct ath_hw *ah,
167 int16_t nfarray[NUM_NF_READINGS]) 175 int16_t nfarray[NUM_NF_READINGS])
168{ 176{
169 return ath9k_hw_private_ops(ah)->do_getnf(ah, nfarray); 177 ath9k_hw_private_ops(ah)->do_getnf(ah, nfarray);
178}
179
180static inline bool ath9k_hw_init_cal(struct ath_hw *ah,
181 struct ath9k_channel *chan)
182{
183 return ath9k_hw_private_ops(ah)->init_cal(ah, chan);
184}
185
186static inline void ath9k_hw_setup_calibration(struct ath_hw *ah,
187 struct ath9k_cal_list *currCal)
188{
189 ath9k_hw_private_ops(ah)->setup_calibration(ah, currCal);
190}
191
192static inline bool ath9k_hw_iscal_supported(struct ath_hw *ah,
193 enum ath9k_cal_types calType)
194{
195 return ath9k_hw_private_ops(ah)->iscal_supported(ah, calType);
170} 196}
171 197
172#endif /* ATH9K_HW_OPS_H */ 198#endif /* ATH9K_HW_OPS_H */
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 67c2becad662..e6d4c4c8a3df 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -600,36 +600,6 @@ static bool ar9003_hw_macversion_supported(u32 macversion)
600 return false; 600 return false;
601} 601}
602 602
603static void ar9002_hw_init_cal_settings(struct ath_hw *ah)
604{
605 if (AR_SREV_9100(ah)) {
606 ah->iq_caldata.calData = &iq_cal_multi_sample;
607 ah->supp_cals = IQ_MISMATCH_CAL;
608 return;
609 }
610
611 if (AR_SREV_9160_10_OR_LATER(ah)) {
612 if (AR_SREV_9280_10_OR_LATER(ah)) {
613 ah->iq_caldata.calData = &iq_cal_single_sample;
614 ah->adcgain_caldata.calData =
615 &adc_gain_cal_single_sample;
616 ah->adcdc_caldata.calData =
617 &adc_dc_cal_single_sample;
618 ah->adcdc_calinitdata.calData =
619 &adc_init_dc_cal;
620 } else {
621 ah->iq_caldata.calData = &iq_cal_multi_sample;
622 ah->adcgain_caldata.calData =
623 &adc_gain_cal_multi_sample;
624 ah->adcdc_caldata.calData =
625 &adc_dc_cal_multi_sample;
626 ah->adcdc_calinitdata.calData =
627 &adc_init_dc_cal;
628 }
629 ah->supp_cals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL;
630 }
631}
632
633static void ar9002_hw_init_mode_regs(struct ath_hw *ah) 603static void ar9002_hw_init_mode_regs(struct ath_hw *ah)
634{ 604{
635 if (AR_SREV_9271(ah)) { 605 if (AR_SREV_9271(ah)) {
@@ -3641,7 +3611,6 @@ static void ar9002_hw_attach_ops(struct ath_hw *ah)
3641 struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); 3611 struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
3642 struct ath_hw_ops *ops = ath9k_hw_ops(ah); 3612 struct ath_hw_ops *ops = ath9k_hw_ops(ah);
3643 3613
3644 priv_ops->init_cal_settings = ar9002_hw_init_cal_settings;
3645 priv_ops->init_mode_regs = ar9002_hw_init_mode_regs; 3614 priv_ops->init_mode_regs = ar9002_hw_init_mode_regs;
3646 priv_ops->macversion_supported = ar9002_hw_macversion_supported; 3615 priv_ops->macversion_supported = ar9002_hw_macversion_supported;
3647 3616
@@ -3651,6 +3620,7 @@ static void ar9002_hw_attach_ops(struct ath_hw *ah)
3651 if (AR_SREV_9280_10_OR_LATER(ah)) 3620 if (AR_SREV_9280_10_OR_LATER(ah))
3652 ar9002_hw_attach_phy_ops(ah); 3621 ar9002_hw_attach_phy_ops(ah);
3653 3622
3623 ar9002_hw_attach_calib_ops(ah);
3654 ar9002_hw_attach_mac_ops(ah); 3624 ar9002_hw_attach_mac_ops(ah);
3655} 3625}
3656 3626
@@ -3663,6 +3633,6 @@ static void ar9003_hw_attach_ops(struct ath_hw *ah)
3663 priv_ops->macversion_supported = ar9003_hw_macversion_supported; 3633 priv_ops->macversion_supported = ar9003_hw_macversion_supported;
3664 3634
3665 ar9003_hw_attach_phy_ops(ah); 3635 ar9003_hw_attach_phy_ops(ah);
3666 3636 ar9003_hw_attach_calib_ops(ah);
3667 ar9003_hw_attach_mac_ops(ah); 3637 ar9003_hw_attach_mac_ops(ah);
3668} 3638}
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index 48fb5ce8294b..7ef93c8df923 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -469,7 +469,9 @@ struct ath_gen_timer_table {
469 * This structure contains private callbacks designed to only be used internally 469 * This structure contains private callbacks designed to only be used internally
470 * by the hardware core. 470 * by the hardware core.
471 * 471 *
472 * @init_cal_settings: Initializes calibration settings 472 * @init_cal_settings: setup types of calibrations supported
473 * @init_cal: starts actual calibration
474 *
473 * @init_mode_regs: Initializes mode registers 475 * @init_mode_regs: Initializes mode registers
474 * @macversion_supported: If this specific mac revision is supported 476 * @macversion_supported: If this specific mac revision is supported
475 * 477 *
@@ -480,11 +482,20 @@ struct ath_gen_timer_table {
480 * @set_rf_regs: 482 * @set_rf_regs:
481 * @compute_pll_control: compute the PLL control value to use for 483 * @compute_pll_control: compute the PLL control value to use for
482 * AR_RTC_PLL_CONTROL for a given channel 484 * AR_RTC_PLL_CONTROL for a given channel
485 * @setup_calibration: set up calibration
486 * @iscal_supported: used to query if a type of calibration is supported
483 */ 487 */
484struct ath_hw_private_ops { 488struct ath_hw_private_ops {
489 /* Calibration ops */
485 void (*init_cal_settings)(struct ath_hw *ah); 490 void (*init_cal_settings)(struct ath_hw *ah);
491 bool (*init_cal)(struct ath_hw *ah, struct ath9k_channel *chan);
492
486 void (*init_mode_regs)(struct ath_hw *ah); 493 void (*init_mode_regs)(struct ath_hw *ah);
487 bool (*macversion_supported)(u32 macversion); 494 bool (*macversion_supported)(u32 macversion);
495 void (*setup_calibration)(struct ath_hw *ah,
496 struct ath9k_cal_list *currCal);
497 bool (*iscal_supported)(struct ath_hw *ah,
498 enum ath9k_cal_types calType);
488 499
489 /* PHY ops */ 500 /* PHY ops */
490 int (*rf_set_freq)(struct ath_hw *ah, 501 int (*rf_set_freq)(struct ath_hw *ah,
@@ -523,6 +534,7 @@ struct ath_hw_private_ops {
523 * hardware code and also by the lower level driver. 534 * hardware code and also by the lower level driver.
524 * 535 *
525 * @config_pci_powersave: 536 * @config_pci_powersave:
537 * @calibrate: periodic calibration for NF, ANI, IQ, ADC gain, ADC-DC
526 */ 538 */
527struct ath_hw_ops { 539struct ath_hw_ops {
528 void (*config_pci_powersave)(struct ath_hw *ah, 540 void (*config_pci_powersave)(struct ath_hw *ah,
@@ -531,6 +543,10 @@ struct ath_hw_ops {
531 void (*rx_enable)(struct ath_hw *ah); 543 void (*rx_enable)(struct ath_hw *ah);
532 void (*set_desc_link)(void *ds, u32 link); 544 void (*set_desc_link)(void *ds, u32 link);
533 void (*get_desc_link)(void *ds, u32 **link); 545 void (*get_desc_link)(void *ds, u32 **link);
546 bool (*calibrate)(struct ath_hw *ah,
547 struct ath9k_channel *chan,
548 u8 rxchainmask,
549 bool longcal);
534}; 550};
535 551
536struct ath_hw { 552struct ath_hw {
@@ -833,6 +849,9 @@ void ar5008_hw_attach_phy_ops(struct ath_hw *ah);
833void ar9002_hw_attach_phy_ops(struct ath_hw *ah); 849void ar9002_hw_attach_phy_ops(struct ath_hw *ah);
834void ar9003_hw_attach_phy_ops(struct ath_hw *ah); 850void ar9003_hw_attach_phy_ops(struct ath_hw *ah);
835 851
852void ar9002_hw_attach_calib_ops(struct ath_hw *ah);
853void ar9003_hw_attach_calib_ops(struct ath_hw *ah);
854
836#define ATH_PCIE_CAP_LINK_CTRL 0x70 855#define ATH_PCIE_CAP_LINK_CTRL 0x70
837#define ATH_PCIE_CAP_LINK_L0S 1 856#define ATH_PCIE_CAP_LINK_L0S 1
838#define ATH_PCIE_CAP_LINK_L1 2 857#define ATH_PCIE_CAP_LINK_L1 2