2 * Copyright (c) 2008-2010 Atheros Communications Inc.
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.
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.
19 #include "ar9002_phy.h"
21 #define AR9285_CLCAL_REDO_THRESH 1
23 enum ar9002_cal_types
{
24 ADC_GAIN_CAL
= BIT(0),
26 IQ_MISMATCH_CAL
= BIT(2),
30 static void ar9002_hw_setup_calibration(struct ath_hw
*ah
,
31 struct ath9k_cal_list
*currCal
)
33 struct ath_common
*common
= ath9k_hw_common(ah
);
35 REG_RMW_FIELD(ah
, AR_PHY_TIMING_CTRL4(0),
36 AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX
,
37 currCal
->calData
->calCountMax
);
39 switch (currCal
->calData
->calType
) {
41 REG_WRITE(ah
, AR_PHY_CALMODE
, AR_PHY_CALMODE_IQ
);
42 ath_dbg(common
, ATH_DBG_CALIBRATE
,
43 "starting IQ Mismatch Calibration\n");
46 REG_WRITE(ah
, AR_PHY_CALMODE
, AR_PHY_CALMODE_ADC_GAIN
);
47 ath_dbg(common
, ATH_DBG_CALIBRATE
,
48 "starting ADC Gain Calibration\n");
51 REG_WRITE(ah
, AR_PHY_CALMODE
, AR_PHY_CALMODE_ADC_DC_PER
);
52 ath_dbg(common
, ATH_DBG_CALIBRATE
,
53 "starting ADC DC Calibration\n");
57 REG_SET_BIT(ah
, AR_PHY_TIMING_CTRL4(0),
58 AR_PHY_TIMING_CTRL4_DO_CAL
);
61 static bool ar9002_hw_per_calibration(struct ath_hw
*ah
,
62 struct ath9k_channel
*ichan
,
64 struct ath9k_cal_list
*currCal
)
66 struct ath9k_hw_cal_data
*caldata
= ah
->caldata
;
67 bool iscaldone
= false;
69 if (currCal
->calState
== CAL_RUNNING
) {
70 if (!(REG_READ(ah
, AR_PHY_TIMING_CTRL4(0)) &
71 AR_PHY_TIMING_CTRL4_DO_CAL
)) {
73 currCal
->calData
->calCollect(ah
);
76 if (ah
->cal_samples
>=
77 currCal
->calData
->calNumSamples
) {
79 for (i
= 0; i
< AR5416_MAX_CHAINS
; i
++) {
80 if (rxchainmask
& (1 << i
))
84 currCal
->calData
->calPostProc(ah
, numChains
);
85 caldata
->CalValid
|= currCal
->calData
->calType
;
86 currCal
->calState
= CAL_DONE
;
89 ar9002_hw_setup_calibration(ah
, currCal
);
92 } else if (!(caldata
->CalValid
& currCal
->calData
->calType
)) {
93 ath9k_hw_reset_calibration(ah
, currCal
);
99 static void ar9002_hw_iqcal_collect(struct ath_hw
*ah
)
103 for (i
= 0; i
< AR5416_MAX_CHAINS
; i
++) {
104 ah
->totalPowerMeasI
[i
] +=
105 REG_READ(ah
, AR_PHY_CAL_MEAS_0(i
));
106 ah
->totalPowerMeasQ
[i
] +=
107 REG_READ(ah
, AR_PHY_CAL_MEAS_1(i
));
108 ah
->totalIqCorrMeas
[i
] +=
109 (int32_t) REG_READ(ah
, AR_PHY_CAL_MEAS_2(i
));
110 ath_dbg(ath9k_hw_common(ah
), ATH_DBG_CALIBRATE
,
111 "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
112 ah
->cal_samples
, i
, ah
->totalPowerMeasI
[i
],
113 ah
->totalPowerMeasQ
[i
],
114 ah
->totalIqCorrMeas
[i
]);
118 static void ar9002_hw_adc_gaincal_collect(struct ath_hw
*ah
)
122 for (i
= 0; i
< AR5416_MAX_CHAINS
; i
++) {
123 ah
->totalAdcIOddPhase
[i
] +=
124 REG_READ(ah
, AR_PHY_CAL_MEAS_0(i
));
125 ah
->totalAdcIEvenPhase
[i
] +=
126 REG_READ(ah
, AR_PHY_CAL_MEAS_1(i
));
127 ah
->totalAdcQOddPhase
[i
] +=
128 REG_READ(ah
, AR_PHY_CAL_MEAS_2(i
));
129 ah
->totalAdcQEvenPhase
[i
] +=
130 REG_READ(ah
, AR_PHY_CAL_MEAS_3(i
));
132 ath_dbg(ath9k_hw_common(ah
), ATH_DBG_CALIBRATE
,
133 "%d: Chn %d oddi=0x%08x; eveni=0x%08x; oddq=0x%08x; evenq=0x%08x;\n",
135 ah
->totalAdcIOddPhase
[i
],
136 ah
->totalAdcIEvenPhase
[i
],
137 ah
->totalAdcQOddPhase
[i
],
138 ah
->totalAdcQEvenPhase
[i
]);
142 static void ar9002_hw_adc_dccal_collect(struct ath_hw
*ah
)
146 for (i
= 0; i
< AR5416_MAX_CHAINS
; i
++) {
147 ah
->totalAdcDcOffsetIOddPhase
[i
] +=
148 (int32_t) REG_READ(ah
, AR_PHY_CAL_MEAS_0(i
));
149 ah
->totalAdcDcOffsetIEvenPhase
[i
] +=
150 (int32_t) REG_READ(ah
, AR_PHY_CAL_MEAS_1(i
));
151 ah
->totalAdcDcOffsetQOddPhase
[i
] +=
152 (int32_t) REG_READ(ah
, AR_PHY_CAL_MEAS_2(i
));
153 ah
->totalAdcDcOffsetQEvenPhase
[i
] +=
154 (int32_t) REG_READ(ah
, AR_PHY_CAL_MEAS_3(i
));
156 ath_dbg(ath9k_hw_common(ah
), ATH_DBG_CALIBRATE
,
157 "%d: Chn %d oddi=0x%08x; eveni=0x%08x; oddq=0x%08x; evenq=0x%08x;\n",
159 ah
->totalAdcDcOffsetIOddPhase
[i
],
160 ah
->totalAdcDcOffsetIEvenPhase
[i
],
161 ah
->totalAdcDcOffsetQOddPhase
[i
],
162 ah
->totalAdcDcOffsetQEvenPhase
[i
]);
166 static void ar9002_hw_iqcalibrate(struct ath_hw
*ah
, u8 numChains
)
168 struct ath_common
*common
= ath9k_hw_common(ah
);
169 u32 powerMeasQ
, powerMeasI
, iqCorrMeas
;
170 u32 qCoffDenom
, iCoffDenom
;
171 int32_t qCoff
, iCoff
;
174 for (i
= 0; i
< numChains
; i
++) {
175 powerMeasI
= ah
->totalPowerMeasI
[i
];
176 powerMeasQ
= ah
->totalPowerMeasQ
[i
];
177 iqCorrMeas
= ah
->totalIqCorrMeas
[i
];
179 ath_dbg(common
, ATH_DBG_CALIBRATE
,
180 "Starting IQ Cal and Correction for Chain %d\n",
183 ath_dbg(common
, ATH_DBG_CALIBRATE
,
184 "Orignal: Chn %diq_corr_meas = 0x%08x\n",
185 i
, ah
->totalIqCorrMeas
[i
]);
189 if (iqCorrMeas
> 0x80000000) {
190 iqCorrMeas
= (0xffffffff - iqCorrMeas
) + 1;
194 ath_dbg(common
, ATH_DBG_CALIBRATE
,
195 "Chn %d pwr_meas_i = 0x%08x\n", i
, powerMeasI
);
196 ath_dbg(common
, ATH_DBG_CALIBRATE
,
197 "Chn %d pwr_meas_q = 0x%08x\n", i
, powerMeasQ
);
198 ath_dbg(common
, ATH_DBG_CALIBRATE
, "iqCorrNeg is 0x%08x\n",
201 iCoffDenom
= (powerMeasI
/ 2 + powerMeasQ
/ 2) / 128;
202 qCoffDenom
= powerMeasQ
/ 64;
204 if ((powerMeasQ
!= 0) && (iCoffDenom
!= 0) &&
206 iCoff
= iqCorrMeas
/ iCoffDenom
;
207 qCoff
= powerMeasI
/ qCoffDenom
- 64;
208 ath_dbg(common
, ATH_DBG_CALIBRATE
,
209 "Chn %d iCoff = 0x%08x\n", i
, iCoff
);
210 ath_dbg(common
, ATH_DBG_CALIBRATE
,
211 "Chn %d qCoff = 0x%08x\n", i
, qCoff
);
213 iCoff
= iCoff
& 0x3f;
214 ath_dbg(common
, ATH_DBG_CALIBRATE
,
215 "New: Chn %d iCoff = 0x%08x\n", i
, iCoff
);
216 if (iqCorrNeg
== 0x0)
217 iCoff
= 0x40 - iCoff
;
221 else if (qCoff
<= -16)
224 ath_dbg(common
, ATH_DBG_CALIBRATE
,
225 "Chn %d : iCoff = 0x%x qCoff = 0x%x\n",
228 REG_RMW_FIELD(ah
, AR_PHY_TIMING_CTRL4(i
),
229 AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF
,
231 REG_RMW_FIELD(ah
, AR_PHY_TIMING_CTRL4(i
),
232 AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF
,
234 ath_dbg(common
, ATH_DBG_CALIBRATE
,
235 "IQ Cal and Correction done for Chain %d\n",
240 REG_SET_BIT(ah
, AR_PHY_TIMING_CTRL4(0),
241 AR_PHY_TIMING_CTRL4_IQCORR_ENABLE
);
244 static void ar9002_hw_adc_gaincal_calibrate(struct ath_hw
*ah
, u8 numChains
)
246 struct ath_common
*common
= ath9k_hw_common(ah
);
247 u32 iOddMeasOffset
, iEvenMeasOffset
, qOddMeasOffset
, qEvenMeasOffset
;
248 u32 qGainMismatch
, iGainMismatch
, val
, i
;
250 for (i
= 0; i
< numChains
; i
++) {
251 iOddMeasOffset
= ah
->totalAdcIOddPhase
[i
];
252 iEvenMeasOffset
= ah
->totalAdcIEvenPhase
[i
];
253 qOddMeasOffset
= ah
->totalAdcQOddPhase
[i
];
254 qEvenMeasOffset
= ah
->totalAdcQEvenPhase
[i
];
256 ath_dbg(common
, ATH_DBG_CALIBRATE
,
257 "Starting ADC Gain Cal for Chain %d\n", i
);
259 ath_dbg(common
, ATH_DBG_CALIBRATE
,
260 "Chn %d pwr_meas_odd_i = 0x%08x\n", i
,
262 ath_dbg(common
, ATH_DBG_CALIBRATE
,
263 "Chn %d pwr_meas_even_i = 0x%08x\n", i
,
265 ath_dbg(common
, ATH_DBG_CALIBRATE
,
266 "Chn %d pwr_meas_odd_q = 0x%08x\n", i
,
268 ath_dbg(common
, ATH_DBG_CALIBRATE
,
269 "Chn %d pwr_meas_even_q = 0x%08x\n", i
,
272 if (iOddMeasOffset
!= 0 && qEvenMeasOffset
!= 0) {
274 ((iEvenMeasOffset
* 32) /
275 iOddMeasOffset
) & 0x3f;
277 ((qOddMeasOffset
* 32) /
278 qEvenMeasOffset
) & 0x3f;
280 ath_dbg(common
, ATH_DBG_CALIBRATE
,
281 "Chn %d gain_mismatch_i = 0x%08x\n", i
,
283 ath_dbg(common
, ATH_DBG_CALIBRATE
,
284 "Chn %d gain_mismatch_q = 0x%08x\n", i
,
287 val
= REG_READ(ah
, AR_PHY_NEW_ADC_DC_GAIN_CORR(i
));
289 val
|= (qGainMismatch
) | (iGainMismatch
<< 6);
290 REG_WRITE(ah
, AR_PHY_NEW_ADC_DC_GAIN_CORR(i
), val
);
292 ath_dbg(common
, ATH_DBG_CALIBRATE
,
293 "ADC Gain Cal done for Chain %d\n", i
);
297 REG_WRITE(ah
, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
298 REG_READ(ah
, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
299 AR_PHY_NEW_ADC_GAIN_CORR_ENABLE
);
302 static void ar9002_hw_adc_dccal_calibrate(struct ath_hw
*ah
, u8 numChains
)
304 struct ath_common
*common
= ath9k_hw_common(ah
);
305 u32 iOddMeasOffset
, iEvenMeasOffset
, val
, i
;
306 int32_t qOddMeasOffset
, qEvenMeasOffset
, qDcMismatch
, iDcMismatch
;
307 const struct ath9k_percal_data
*calData
=
308 ah
->cal_list_curr
->calData
;
310 (1 << (calData
->calCountMax
+ 5)) * calData
->calNumSamples
;
312 for (i
= 0; i
< numChains
; i
++) {
313 iOddMeasOffset
= ah
->totalAdcDcOffsetIOddPhase
[i
];
314 iEvenMeasOffset
= ah
->totalAdcDcOffsetIEvenPhase
[i
];
315 qOddMeasOffset
= ah
->totalAdcDcOffsetQOddPhase
[i
];
316 qEvenMeasOffset
= ah
->totalAdcDcOffsetQEvenPhase
[i
];
318 ath_dbg(common
, ATH_DBG_CALIBRATE
,
319 "Starting ADC DC Offset Cal for Chain %d\n", i
);
321 ath_dbg(common
, ATH_DBG_CALIBRATE
,
322 "Chn %d pwr_meas_odd_i = %d\n", i
,
324 ath_dbg(common
, ATH_DBG_CALIBRATE
,
325 "Chn %d pwr_meas_even_i = %d\n", i
,
327 ath_dbg(common
, ATH_DBG_CALIBRATE
,
328 "Chn %d pwr_meas_odd_q = %d\n", i
,
330 ath_dbg(common
, ATH_DBG_CALIBRATE
,
331 "Chn %d pwr_meas_even_q = %d\n", i
,
334 iDcMismatch
= (((iEvenMeasOffset
- iOddMeasOffset
) * 2) /
336 qDcMismatch
= (((qOddMeasOffset
- qEvenMeasOffset
) * 2) /
339 ath_dbg(common
, ATH_DBG_CALIBRATE
,
340 "Chn %d dc_offset_mismatch_i = 0x%08x\n", i
,
342 ath_dbg(common
, ATH_DBG_CALIBRATE
,
343 "Chn %d dc_offset_mismatch_q = 0x%08x\n", i
,
346 val
= REG_READ(ah
, AR_PHY_NEW_ADC_DC_GAIN_CORR(i
));
348 val
|= (qDcMismatch
<< 12) | (iDcMismatch
<< 21);
349 REG_WRITE(ah
, AR_PHY_NEW_ADC_DC_GAIN_CORR(i
), val
);
351 ath_dbg(common
, ATH_DBG_CALIBRATE
,
352 "ADC DC Offset Cal done for Chain %d\n", i
);
355 REG_WRITE(ah
, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
356 REG_READ(ah
, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
357 AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE
);
360 static void ar9287_hw_olc_temp_compensation(struct ath_hw
*ah
)
363 int32_t delta
, currPDADC
, slope
;
365 rddata
= REG_READ(ah
, AR_PHY_TX_PWRCTRL4
);
366 currPDADC
= MS(rddata
, AR_PHY_TX_PWRCTRL_PD_AVG_OUT
);
368 if (ah
->initPDADC
== 0 || currPDADC
== 0) {
370 * Zero value indicates that no frames have been transmitted
371 * yet, can't do temperature compensation until frames are
376 slope
= ah
->eep_ops
->get_eeprom(ah
, EEP_TEMPSENSE_SLOPE
);
378 if (slope
== 0) { /* to avoid divide by zero case */
381 delta
= ((currPDADC
- ah
->initPDADC
)*4) / slope
;
383 REG_RMW_FIELD(ah
, AR_PHY_CH0_TX_PWRCTRL11
,
384 AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP
, delta
);
385 REG_RMW_FIELD(ah
, AR_PHY_CH1_TX_PWRCTRL11
,
386 AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP
, delta
);
390 static void ar9280_hw_olc_temp_compensation(struct ath_hw
*ah
)
393 int delta
, currPDADC
, regval
;
395 rddata
= REG_READ(ah
, AR_PHY_TX_PWRCTRL4
);
396 currPDADC
= MS(rddata
, AR_PHY_TX_PWRCTRL_PD_AVG_OUT
);
398 if (ah
->initPDADC
== 0 || currPDADC
== 0)
401 if (ah
->eep_ops
->get_eeprom(ah
, EEP_DAC_HPWR_5G
))
402 delta
= (currPDADC
- ah
->initPDADC
+ 4) / 8;
404 delta
= (currPDADC
- ah
->initPDADC
+ 5) / 10;
406 if (delta
!= ah
->PDADCdelta
) {
407 ah
->PDADCdelta
= delta
;
408 for (i
= 1; i
< AR9280_TX_GAIN_TABLE_SIZE
; i
++) {
409 regval
= ah
->originalGain
[i
] - delta
;
414 AR_PHY_TX_GAIN_TBL1
+ i
* 4,
415 AR_PHY_TX_GAIN
, regval
);
420 static void ar9271_hw_pa_cal(struct ath_hw
*ah
, bool is_reset
)
435 for (i
= 0; i
< ARRAY_SIZE(regList
); i
++)
436 regList
[i
][1] = REG_READ(ah
, regList
[i
][0]);
438 regVal
= REG_READ(ah
, 0x7834);
440 REG_WRITE(ah
, 0x7834, regVal
);
441 regVal
= REG_READ(ah
, 0x9808);
442 regVal
|= (0x1 << 27);
443 REG_WRITE(ah
, 0x9808, regVal
);
445 /* 786c,b23,1, pwddac=1 */
446 REG_RMW_FIELD(ah
, AR9285_AN_TOP3
, AR9285_AN_TOP3_PWDDAC
, 1);
447 /* 7854, b5,1, pdrxtxbb=1 */
448 REG_RMW_FIELD(ah
, AR9285_AN_RXTXBB1
, AR9285_AN_RXTXBB1_PDRXTXBB1
, 1);
449 /* 7854, b7,1, pdv2i=1 */
450 REG_RMW_FIELD(ah
, AR9285_AN_RXTXBB1
, AR9285_AN_RXTXBB1_PDV2I
, 1);
451 /* 7854, b8,1, pddacinterface=1 */
452 REG_RMW_FIELD(ah
, AR9285_AN_RXTXBB1
, AR9285_AN_RXTXBB1_PDDACIF
, 1);
453 /* 7824,b12,0, offcal=0 */
454 REG_RMW_FIELD(ah
, AR9285_AN_RF2G2
, AR9285_AN_RF2G2_OFFCAL
, 0);
455 /* 7838, b1,0, pwddb=0 */
456 REG_RMW_FIELD(ah
, AR9285_AN_RF2G7
, AR9285_AN_RF2G7_PWDDB
, 0);
457 /* 7820,b11,0, enpacal=0 */
458 REG_RMW_FIELD(ah
, AR9285_AN_RF2G1
, AR9285_AN_RF2G1_ENPACAL
, 0);
459 /* 7820,b25,1, pdpadrv1=0 */
460 REG_RMW_FIELD(ah
, AR9285_AN_RF2G1
, AR9285_AN_RF2G1_PDPADRV1
, 0);
461 /* 7820,b24,0, pdpadrv2=0 */
462 REG_RMW_FIELD(ah
, AR9285_AN_RF2G1
, AR9285_AN_RF2G1_PDPADRV2
, 0);
463 /* 7820,b23,0, pdpaout=0 */
464 REG_RMW_FIELD(ah
, AR9285_AN_RF2G1
, AR9285_AN_RF2G1_PDPAOUT
, 0);
465 /* 783c,b14-16,7, padrvgn2tab_0=7 */
466 REG_RMW_FIELD(ah
, AR9285_AN_RF2G8
, AR9285_AN_RF2G8_PADRVGN2TAB0
, 7);
468 * 7838,b29-31,0, padrvgn1tab_0=0
469 * does not matter since we turn it off
471 REG_RMW_FIELD(ah
, AR9285_AN_RF2G7
, AR9285_AN_RF2G7_PADRVGN2TAB0
, 0);
473 REG_RMW_FIELD(ah
, AR9285_AN_RF2G3
, AR9271_AN_RF2G3_CCOMP
, 0xfff);
476 * localmode=1,bmode=1,bmoderxtx=1,synthon=1,
477 * txon=1,paon=1,oscon=1,synthon_force=1
479 REG_WRITE(ah
, AR9285_AN_TOP2
, 0xca0358a0);
481 REG_RMW_FIELD(ah
, AR9285_AN_RF2G6
, AR9271_AN_RF2G6_OFFS
, 0);
484 for (i
= 6; i
> 0; i
--) {
485 regVal
= REG_READ(ah
, 0x7834);
486 regVal
|= (1 << (20 + i
));
487 REG_WRITE(ah
, 0x7834, regVal
);
489 /* regVal = REG_READ(ah, 0x7834); */
490 regVal
&= (~(0x1 << (20 + i
)));
491 regVal
|= (MS(REG_READ(ah
, 0x7840), AR9285_AN_RXTXBB1_SPARE9
)
493 REG_WRITE(ah
, 0x7834, regVal
);
496 regVal
= (regVal
>> 20) & 0x7f;
498 /* Update PA cal info */
499 if ((!is_reset
) && (ah
->pacal_info
.prev_offset
== regVal
)) {
500 if (ah
->pacal_info
.max_skipcount
< MAX_PACAL_SKIPCOUNT
)
501 ah
->pacal_info
.max_skipcount
=
502 2 * ah
->pacal_info
.max_skipcount
;
503 ah
->pacal_info
.skipcount
= ah
->pacal_info
.max_skipcount
;
505 ah
->pacal_info
.max_skipcount
= 1;
506 ah
->pacal_info
.skipcount
= 0;
507 ah
->pacal_info
.prev_offset
= regVal
;
510 ENABLE_REGWRITE_BUFFER(ah
);
512 regVal
= REG_READ(ah
, 0x7834);
514 REG_WRITE(ah
, 0x7834, regVal
);
515 regVal
= REG_READ(ah
, 0x9808);
516 regVal
&= (~(0x1 << 27));
517 REG_WRITE(ah
, 0x9808, regVal
);
519 for (i
= 0; i
< ARRAY_SIZE(regList
); i
++)
520 REG_WRITE(ah
, regList
[i
][0], regList
[i
][1]);
522 REGWRITE_BUFFER_FLUSH(ah
);
525 static inline void ar9285_hw_pa_cal(struct ath_hw
*ah
, bool is_reset
)
527 struct ath_common
*common
= ath9k_hw_common(ah
);
529 int i
, offset
, offs_6_1
, offs_0
;
530 u32 ccomp_org
, reg_field
;
541 ath_dbg(common
, ATH_DBG_CALIBRATE
, "Running PA Calibration\n");
543 /* PA CAL is not needed for high power solution */
544 if (ah
->eep_ops
->get_eeprom(ah
, EEP_TXGAIN_TYPE
) ==
545 AR5416_EEP_TXGAIN_HIGH_POWER
)
548 for (i
= 0; i
< ARRAY_SIZE(regList
); i
++)
549 regList
[i
][1] = REG_READ(ah
, regList
[i
][0]);
551 regVal
= REG_READ(ah
, 0x7834);
553 REG_WRITE(ah
, 0x7834, regVal
);
554 regVal
= REG_READ(ah
, 0x9808);
555 regVal
|= (0x1 << 27);
556 REG_WRITE(ah
, 0x9808, regVal
);
558 REG_RMW_FIELD(ah
, AR9285_AN_TOP3
, AR9285_AN_TOP3_PWDDAC
, 1);
559 REG_RMW_FIELD(ah
, AR9285_AN_RXTXBB1
, AR9285_AN_RXTXBB1_PDRXTXBB1
, 1);
560 REG_RMW_FIELD(ah
, AR9285_AN_RXTXBB1
, AR9285_AN_RXTXBB1_PDV2I
, 1);
561 REG_RMW_FIELD(ah
, AR9285_AN_RXTXBB1
, AR9285_AN_RXTXBB1_PDDACIF
, 1);
562 REG_RMW_FIELD(ah
, AR9285_AN_RF2G2
, AR9285_AN_RF2G2_OFFCAL
, 0);
563 REG_RMW_FIELD(ah
, AR9285_AN_RF2G7
, AR9285_AN_RF2G7_PWDDB
, 0);
564 REG_RMW_FIELD(ah
, AR9285_AN_RF2G1
, AR9285_AN_RF2G1_ENPACAL
, 0);
565 REG_RMW_FIELD(ah
, AR9285_AN_RF2G1
, AR9285_AN_RF2G1_PDPADRV1
, 0);
566 REG_RMW_FIELD(ah
, AR9285_AN_RF2G1
, AR9285_AN_RF2G1_PDPADRV2
, 0);
567 REG_RMW_FIELD(ah
, AR9285_AN_RF2G1
, AR9285_AN_RF2G1_PDPAOUT
, 0);
568 REG_RMW_FIELD(ah
, AR9285_AN_RF2G8
, AR9285_AN_RF2G8_PADRVGN2TAB0
, 7);
569 REG_RMW_FIELD(ah
, AR9285_AN_RF2G7
, AR9285_AN_RF2G7_PADRVGN2TAB0
, 0);
570 ccomp_org
= MS(REG_READ(ah
, AR9285_AN_RF2G6
), AR9285_AN_RF2G6_CCOMP
);
571 REG_RMW_FIELD(ah
, AR9285_AN_RF2G6
, AR9285_AN_RF2G6_CCOMP
, 0xf);
573 REG_WRITE(ah
, AR9285_AN_TOP2
, 0xca0358a0);
575 REG_RMW_FIELD(ah
, AR9285_AN_RF2G6
, AR9285_AN_RF2G6_OFFS
, 0);
576 REG_RMW_FIELD(ah
, AR9285_AN_RF2G3
, AR9285_AN_RF2G3_PDVCCOMP
, 0);
578 for (i
= 6; i
> 0; i
--) {
579 regVal
= REG_READ(ah
, 0x7834);
580 regVal
|= (1 << (19 + i
));
581 REG_WRITE(ah
, 0x7834, regVal
);
583 regVal
= REG_READ(ah
, 0x7834);
584 regVal
&= (~(0x1 << (19 + i
)));
585 reg_field
= MS(REG_READ(ah
, 0x7840), AR9285_AN_RXTXBB1_SPARE9
);
586 regVal
|= (reg_field
<< (19 + i
));
587 REG_WRITE(ah
, 0x7834, regVal
);
590 REG_RMW_FIELD(ah
, AR9285_AN_RF2G3
, AR9285_AN_RF2G3_PDVCCOMP
, 1);
592 reg_field
= MS(REG_READ(ah
, AR9285_AN_RF2G9
), AR9285_AN_RXTXBB1_SPARE9
);
593 REG_RMW_FIELD(ah
, AR9285_AN_RF2G3
, AR9285_AN_RF2G3_PDVCCOMP
, reg_field
);
594 offs_6_1
= MS(REG_READ(ah
, AR9285_AN_RF2G6
), AR9285_AN_RF2G6_OFFS
);
595 offs_0
= MS(REG_READ(ah
, AR9285_AN_RF2G3
), AR9285_AN_RF2G3_PDVCCOMP
);
597 offset
= (offs_6_1
<<1) | offs_0
;
599 offs_6_1
= offset
>>1;
602 if ((!is_reset
) && (ah
->pacal_info
.prev_offset
== offset
)) {
603 if (ah
->pacal_info
.max_skipcount
< MAX_PACAL_SKIPCOUNT
)
604 ah
->pacal_info
.max_skipcount
=
605 2 * ah
->pacal_info
.max_skipcount
;
606 ah
->pacal_info
.skipcount
= ah
->pacal_info
.max_skipcount
;
608 ah
->pacal_info
.max_skipcount
= 1;
609 ah
->pacal_info
.skipcount
= 0;
610 ah
->pacal_info
.prev_offset
= offset
;
613 REG_RMW_FIELD(ah
, AR9285_AN_RF2G6
, AR9285_AN_RF2G6_OFFS
, offs_6_1
);
614 REG_RMW_FIELD(ah
, AR9285_AN_RF2G3
, AR9285_AN_RF2G3_PDVCCOMP
, offs_0
);
616 regVal
= REG_READ(ah
, 0x7834);
618 REG_WRITE(ah
, 0x7834, regVal
);
619 regVal
= REG_READ(ah
, 0x9808);
620 regVal
&= (~(0x1 << 27));
621 REG_WRITE(ah
, 0x9808, regVal
);
623 for (i
= 0; i
< ARRAY_SIZE(regList
); i
++)
624 REG_WRITE(ah
, regList
[i
][0], regList
[i
][1]);
626 REG_RMW_FIELD(ah
, AR9285_AN_RF2G6
, AR9285_AN_RF2G6_CCOMP
, ccomp_org
);
629 static void ar9002_hw_pa_cal(struct ath_hw
*ah
, bool is_reset
)
631 if (AR_SREV_9271(ah
)) {
632 if (is_reset
|| !ah
->pacal_info
.skipcount
)
633 ar9271_hw_pa_cal(ah
, is_reset
);
635 ah
->pacal_info
.skipcount
--;
636 } else if (AR_SREV_9285_12_OR_LATER(ah
)) {
637 if (is_reset
|| !ah
->pacal_info
.skipcount
)
638 ar9285_hw_pa_cal(ah
, is_reset
);
640 ah
->pacal_info
.skipcount
--;
644 static void ar9002_hw_olc_temp_compensation(struct ath_hw
*ah
)
646 if (OLC_FOR_AR9287_10_LATER
)
647 ar9287_hw_olc_temp_compensation(ah
);
648 else if (OLC_FOR_AR9280_20_LATER
)
649 ar9280_hw_olc_temp_compensation(ah
);
652 static bool ar9002_hw_calibrate(struct ath_hw
*ah
,
653 struct ath9k_channel
*chan
,
657 bool iscaldone
= true;
658 struct ath9k_cal_list
*currCal
= ah
->cal_list_curr
;
659 bool nfcal
, nfcal_pending
= false;
661 nfcal
= !!(REG_READ(ah
, AR_PHY_AGC_CONTROL
) & AR_PHY_AGC_CONTROL_NF
);
663 nfcal_pending
= ah
->caldata
->nfcal_pending
;
665 if (currCal
&& !nfcal
&&
666 (currCal
->calState
== CAL_RUNNING
||
667 currCal
->calState
== CAL_WAITING
)) {
668 iscaldone
= ar9002_hw_per_calibration(ah
, chan
,
669 rxchainmask
, currCal
);
671 ah
->cal_list_curr
= currCal
= currCal
->calNext
;
673 if (currCal
->calState
== CAL_WAITING
) {
675 ath9k_hw_reset_calibration(ah
, currCal
);
680 /* Do NF cal only at longer intervals */
681 if (longcal
|| nfcal_pending
) {
683 * Get the value from the previous NF cal and update
686 if (ath9k_hw_getnf(ah
, chan
)) {
688 * Load the NF from history buffer of the current
690 * NF is slow time-variant, so it is OK to use a
693 ath9k_hw_loadnf(ah
, ah
->curchan
);
697 ath9k_hw_start_nfcal(ah
, false);
698 /* Do periodic PAOffset Cal */
699 ar9002_hw_pa_cal(ah
, false);
700 ar9002_hw_olc_temp_compensation(ah
);
707 /* Carrier leakage Calibration fix */
708 static bool ar9285_hw_cl_cal(struct ath_hw
*ah
, struct ath9k_channel
*chan
)
710 struct ath_common
*common
= ath9k_hw_common(ah
);
712 REG_SET_BIT(ah
, AR_PHY_CL_CAL_CTL
, AR_PHY_CL_CAL_ENABLE
);
713 if (IS_CHAN_HT20(chan
)) {
714 REG_SET_BIT(ah
, AR_PHY_CL_CAL_CTL
, AR_PHY_PARALLEL_CAL_ENABLE
);
715 REG_SET_BIT(ah
, AR_PHY_TURBO
, AR_PHY_FC_DYN2040_EN
);
716 REG_CLR_BIT(ah
, AR_PHY_AGC_CONTROL
,
717 AR_PHY_AGC_CONTROL_FLTR_CAL
);
718 REG_CLR_BIT(ah
, AR_PHY_TPCRG1
, AR_PHY_TPCRG1_PD_CAL_ENABLE
);
719 REG_SET_BIT(ah
, AR_PHY_AGC_CONTROL
, AR_PHY_AGC_CONTROL_CAL
);
720 if (!ath9k_hw_wait(ah
, AR_PHY_AGC_CONTROL
,
721 AR_PHY_AGC_CONTROL_CAL
, 0, AH_WAIT_TIMEOUT
)) {
722 ath_dbg(common
, ATH_DBG_CALIBRATE
,
723 "offset calibration failed to complete in 1ms; noisy environment?\n");
726 REG_CLR_BIT(ah
, AR_PHY_TURBO
, AR_PHY_FC_DYN2040_EN
);
727 REG_CLR_BIT(ah
, AR_PHY_CL_CAL_CTL
, AR_PHY_PARALLEL_CAL_ENABLE
);
728 REG_CLR_BIT(ah
, AR_PHY_CL_CAL_CTL
, AR_PHY_CL_CAL_ENABLE
);
730 REG_CLR_BIT(ah
, AR_PHY_ADC_CTL
, AR_PHY_ADC_CTL_OFF_PWDADC
);
731 REG_SET_BIT(ah
, AR_PHY_AGC_CONTROL
, AR_PHY_AGC_CONTROL_FLTR_CAL
);
732 REG_SET_BIT(ah
, AR_PHY_TPCRG1
, AR_PHY_TPCRG1_PD_CAL_ENABLE
);
733 REG_SET_BIT(ah
, AR_PHY_AGC_CONTROL
, AR_PHY_AGC_CONTROL_CAL
);
734 if (!ath9k_hw_wait(ah
, AR_PHY_AGC_CONTROL
, AR_PHY_AGC_CONTROL_CAL
,
735 0, AH_WAIT_TIMEOUT
)) {
736 ath_dbg(common
, ATH_DBG_CALIBRATE
,
737 "offset calibration failed to complete in 1ms; noisy environment?\n");
741 REG_SET_BIT(ah
, AR_PHY_ADC_CTL
, AR_PHY_ADC_CTL_OFF_PWDADC
);
742 REG_CLR_BIT(ah
, AR_PHY_CL_CAL_CTL
, AR_PHY_CL_CAL_ENABLE
);
743 REG_CLR_BIT(ah
, AR_PHY_AGC_CONTROL
, AR_PHY_AGC_CONTROL_FLTR_CAL
);
748 static bool ar9285_hw_clc(struct ath_hw
*ah
, struct ath9k_channel
*chan
)
751 u_int32_t txgain_max
;
752 u_int32_t clc_gain
, gain_mask
= 0, clc_num
= 0;
753 u_int32_t reg_clc_I0
, reg_clc_Q0
;
754 u_int32_t i0_num
= 0;
755 u_int32_t q0_num
= 0;
756 u_int32_t total_num
= 0;
757 u_int32_t reg_rf2g5_org
;
760 if (!(ar9285_hw_cl_cal(ah
, chan
)))
763 txgain_max
= MS(REG_READ(ah
, AR_PHY_TX_PWRCTRL7
),
764 AR_PHY_TX_PWRCTRL_TX_GAIN_TAB_MAX
);
766 for (i
= 0; i
< (txgain_max
+1); i
++) {
767 clc_gain
= (REG_READ(ah
, (AR_PHY_TX_GAIN_TBL1
+(i
<<2))) &
768 AR_PHY_TX_GAIN_CLC
) >> AR_PHY_TX_GAIN_CLC_S
;
769 if (!(gain_mask
& (1 << clc_gain
))) {
770 gain_mask
|= (1 << clc_gain
);
775 for (i
= 0; i
< clc_num
; i
++) {
776 reg_clc_I0
= (REG_READ(ah
, (AR_PHY_CLC_TBL1
+ (i
<< 2)))
777 & AR_PHY_CLC_I0
) >> AR_PHY_CLC_I0_S
;
778 reg_clc_Q0
= (REG_READ(ah
, (AR_PHY_CLC_TBL1
+ (i
<< 2)))
779 & AR_PHY_CLC_Q0
) >> AR_PHY_CLC_Q0_S
;
786 total_num
= i0_num
+ q0_num
;
787 if (total_num
> AR9285_CLCAL_REDO_THRESH
) {
788 reg_rf2g5_org
= REG_READ(ah
, AR9285_RF2G5
);
789 if (AR_SREV_9285E_20(ah
)) {
790 REG_WRITE(ah
, AR9285_RF2G5
,
791 (reg_rf2g5_org
& AR9285_RF2G5_IC50TX
) |
792 AR9285_RF2G5_IC50TX_XE_SET
);
794 REG_WRITE(ah
, AR9285_RF2G5
,
795 (reg_rf2g5_org
& AR9285_RF2G5_IC50TX
) |
796 AR9285_RF2G5_IC50TX_SET
);
798 retv
= ar9285_hw_cl_cal(ah
, chan
);
799 REG_WRITE(ah
, AR9285_RF2G5
, reg_rf2g5_org
);
804 static bool ar9002_hw_init_cal(struct ath_hw
*ah
, struct ath9k_channel
*chan
)
806 struct ath_common
*common
= ath9k_hw_common(ah
);
808 if (AR_SREV_9271(ah
)) {
809 if (!ar9285_hw_cl_cal(ah
, chan
))
811 } else if (AR_SREV_9285_12_OR_LATER(ah
)) {
812 if (!ar9285_hw_clc(ah
, chan
))
815 if (AR_SREV_9280_20_OR_LATER(ah
)) {
816 if (!AR_SREV_9287_11_OR_LATER(ah
))
817 REG_CLR_BIT(ah
, AR_PHY_ADC_CTL
,
818 AR_PHY_ADC_CTL_OFF_PWDADC
);
819 REG_SET_BIT(ah
, AR_PHY_AGC_CONTROL
,
820 AR_PHY_AGC_CONTROL_FLTR_CAL
);
823 /* Calibrate the AGC */
824 REG_WRITE(ah
, AR_PHY_AGC_CONTROL
,
825 REG_READ(ah
, AR_PHY_AGC_CONTROL
) |
826 AR_PHY_AGC_CONTROL_CAL
);
828 /* Poll for offset calibration complete */
829 if (!ath9k_hw_wait(ah
, AR_PHY_AGC_CONTROL
,
830 AR_PHY_AGC_CONTROL_CAL
,
831 0, AH_WAIT_TIMEOUT
)) {
832 ath_dbg(common
, ATH_DBG_CALIBRATE
,
833 "offset calibration failed to complete in 1ms; noisy environment?\n");
837 if (AR_SREV_9280_20_OR_LATER(ah
)) {
838 if (!AR_SREV_9287_11_OR_LATER(ah
))
839 REG_SET_BIT(ah
, AR_PHY_ADC_CTL
,
840 AR_PHY_ADC_CTL_OFF_PWDADC
);
841 REG_CLR_BIT(ah
, AR_PHY_AGC_CONTROL
,
842 AR_PHY_AGC_CONTROL_FLTR_CAL
);
846 /* Do PA Calibration */
847 ar9002_hw_pa_cal(ah
, true);
849 /* Do NF Calibration after DC offset and other calibrations */
850 ath9k_hw_start_nfcal(ah
, true);
853 ah
->caldata
->nfcal_pending
= true;
855 ah
->cal_list
= ah
->cal_list_last
= ah
->cal_list_curr
= NULL
;
857 /* Enable IQ, ADC Gain and ADC DC offset CALs */
858 if (AR_SREV_9100(ah
) || AR_SREV_9160_10_OR_LATER(ah
)) {
859 ah
->supp_cals
= IQ_MISMATCH_CAL
;
861 if (AR_SREV_9160_10_OR_LATER(ah
) &&
862 !(IS_CHAN_2GHZ(chan
) && IS_CHAN_HT20(chan
))) {
863 ah
->supp_cals
|= ADC_GAIN_CAL
| ADC_DC_CAL
;
866 INIT_CAL(&ah
->adcgain_caldata
);
867 INSERT_CAL(ah
, &ah
->adcgain_caldata
);
868 ath_dbg(common
, ATH_DBG_CALIBRATE
,
869 "enabling ADC Gain Calibration.\n");
871 INIT_CAL(&ah
->adcdc_caldata
);
872 INSERT_CAL(ah
, &ah
->adcdc_caldata
);
873 ath_dbg(common
, ATH_DBG_CALIBRATE
,
874 "enabling ADC DC Calibration.\n");
877 INIT_CAL(&ah
->iq_caldata
);
878 INSERT_CAL(ah
, &ah
->iq_caldata
);
879 ath_dbg(common
, ATH_DBG_CALIBRATE
,
880 "enabling IQ Calibration.\n");
882 ah
->cal_list_curr
= ah
->cal_list
;
884 if (ah
->cal_list_curr
)
885 ath9k_hw_reset_calibration(ah
, ah
->cal_list_curr
);
889 ah
->caldata
->CalValid
= 0;
894 static const struct ath9k_percal_data iq_cal_multi_sample
= {
898 ar9002_hw_iqcal_collect
,
899 ar9002_hw_iqcalibrate
901 static const struct ath9k_percal_data iq_cal_single_sample
= {
905 ar9002_hw_iqcal_collect
,
906 ar9002_hw_iqcalibrate
908 static const struct ath9k_percal_data adc_gain_cal_multi_sample
= {
912 ar9002_hw_adc_gaincal_collect
,
913 ar9002_hw_adc_gaincal_calibrate
915 static const struct ath9k_percal_data adc_gain_cal_single_sample
= {
919 ar9002_hw_adc_gaincal_collect
,
920 ar9002_hw_adc_gaincal_calibrate
922 static const struct ath9k_percal_data adc_dc_cal_multi_sample
= {
926 ar9002_hw_adc_dccal_collect
,
927 ar9002_hw_adc_dccal_calibrate
929 static const struct ath9k_percal_data adc_dc_cal_single_sample
= {
933 ar9002_hw_adc_dccal_collect
,
934 ar9002_hw_adc_dccal_calibrate
937 static void ar9002_hw_init_cal_settings(struct ath_hw
*ah
)
939 if (AR_SREV_9100(ah
)) {
940 ah
->iq_caldata
.calData
= &iq_cal_multi_sample
;
941 ah
->supp_cals
= IQ_MISMATCH_CAL
;
945 if (AR_SREV_9160_10_OR_LATER(ah
)) {
946 if (AR_SREV_9280_20_OR_LATER(ah
)) {
947 ah
->iq_caldata
.calData
= &iq_cal_single_sample
;
948 ah
->adcgain_caldata
.calData
=
949 &adc_gain_cal_single_sample
;
950 ah
->adcdc_caldata
.calData
=
951 &adc_dc_cal_single_sample
;
953 ah
->iq_caldata
.calData
= &iq_cal_multi_sample
;
954 ah
->adcgain_caldata
.calData
=
955 &adc_gain_cal_multi_sample
;
956 ah
->adcdc_caldata
.calData
=
957 &adc_dc_cal_multi_sample
;
959 ah
->supp_cals
= ADC_GAIN_CAL
| ADC_DC_CAL
| IQ_MISMATCH_CAL
;
961 if (AR_SREV_9287(ah
))
962 ah
->supp_cals
&= ~ADC_GAIN_CAL
;
966 void ar9002_hw_attach_calib_ops(struct ath_hw
*ah
)
968 struct ath_hw_private_ops
*priv_ops
= ath9k_hw_private_ops(ah
);
969 struct ath_hw_ops
*ops
= ath9k_hw_ops(ah
);
971 priv_ops
->init_cal_settings
= ar9002_hw_init_cal_settings
;
972 priv_ops
->init_cal
= ar9002_hw_init_cal
;
973 priv_ops
->setup_calibration
= ar9002_hw_setup_calibration
;
975 ops
->calibrate
= ar9002_hw_calibrate
;