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 static void ar9002_hw_setup_calibration(struct ath_hw
*ah
,
24 struct ath9k_cal_list
*currCal
)
26 struct ath_common
*common
= ath9k_hw_common(ah
);
28 REG_RMW_FIELD(ah
, AR_PHY_TIMING_CTRL4(0),
29 AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX
,
30 currCal
->calData
->calCountMax
);
32 switch (currCal
->calData
->calType
) {
34 REG_WRITE(ah
, AR_PHY_CALMODE
, AR_PHY_CALMODE_IQ
);
35 ath_print(common
, ATH_DBG_CALIBRATE
,
36 "starting IQ Mismatch Calibration\n");
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");
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");
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");
54 break; /* Not supported */
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 bool iscaldone
= false;
68 if (currCal
->calState
== CAL_RUNNING
) {
69 if (!(REG_READ(ah
, AR_PHY_TIMING_CTRL4(0)) &
70 AR_PHY_TIMING_CTRL4_DO_CAL
)) {
72 currCal
->calData
->calCollect(ah
);
75 if (ah
->cal_samples
>=
76 currCal
->calData
->calNumSamples
) {
78 for (i
= 0; i
< AR5416_MAX_CHAINS
; i
++) {
79 if (rxchainmask
& (1 << i
))
83 currCal
->calData
->calPostProc(ah
, numChains
);
84 ichan
->CalValid
|= currCal
->calData
->calType
;
85 currCal
->calState
= CAL_DONE
;
88 ar9002_hw_setup_calibration(ah
, currCal
);
91 } else if (!(ichan
->CalValid
& currCal
->calData
->calType
)) {
92 ath9k_hw_reset_calibration(ah
, currCal
);
98 /* Assumes you are talking about the currently configured channel */
99 static bool ar9002_hw_iscal_supported(struct ath_hw
*ah
,
100 enum ath9k_cal_types calType
)
102 struct ieee80211_conf
*conf
= &ath9k_hw_common(ah
)->hw
->conf
;
104 switch (calType
& ah
->supp_cals
) {
105 case IQ_MISMATCH_CAL
: /* Both 2 GHz and 5 GHz support OFDM */
109 if (!(conf
->channel
->band
== IEEE80211_BAND_2GHZ
&&
117 static void ar9002_hw_iqcal_collect(struct ath_hw
*ah
)
121 for (i
= 0; i
< AR5416_MAX_CHAINS
; i
++) {
122 ah
->totalPowerMeasI
[i
] +=
123 REG_READ(ah
, AR_PHY_CAL_MEAS_0(i
));
124 ah
->totalPowerMeasQ
[i
] +=
125 REG_READ(ah
, AR_PHY_CAL_MEAS_1(i
));
126 ah
->totalIqCorrMeas
[i
] +=
127 (int32_t) REG_READ(ah
, AR_PHY_CAL_MEAS_2(i
));
128 ath_print(ath9k_hw_common(ah
), ATH_DBG_CALIBRATE
,
129 "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
130 ah
->cal_samples
, i
, ah
->totalPowerMeasI
[i
],
131 ah
->totalPowerMeasQ
[i
],
132 ah
->totalIqCorrMeas
[i
]);
136 static void ar9002_hw_adc_gaincal_collect(struct ath_hw
*ah
)
140 for (i
= 0; i
< AR5416_MAX_CHAINS
; i
++) {
141 ah
->totalAdcIOddPhase
[i
] +=
142 REG_READ(ah
, AR_PHY_CAL_MEAS_0(i
));
143 ah
->totalAdcIEvenPhase
[i
] +=
144 REG_READ(ah
, AR_PHY_CAL_MEAS_1(i
));
145 ah
->totalAdcQOddPhase
[i
] +=
146 REG_READ(ah
, AR_PHY_CAL_MEAS_2(i
));
147 ah
->totalAdcQEvenPhase
[i
] +=
148 REG_READ(ah
, AR_PHY_CAL_MEAS_3(i
));
150 ath_print(ath9k_hw_common(ah
), ATH_DBG_CALIBRATE
,
151 "%d: Chn %d oddi=0x%08x; eveni=0x%08x; "
152 "oddq=0x%08x; evenq=0x%08x;\n",
154 ah
->totalAdcIOddPhase
[i
],
155 ah
->totalAdcIEvenPhase
[i
],
156 ah
->totalAdcQOddPhase
[i
],
157 ah
->totalAdcQEvenPhase
[i
]);
161 static void ar9002_hw_adc_dccal_collect(struct ath_hw
*ah
)
165 for (i
= 0; i
< AR5416_MAX_CHAINS
; i
++) {
166 ah
->totalAdcDcOffsetIOddPhase
[i
] +=
167 (int32_t) REG_READ(ah
, AR_PHY_CAL_MEAS_0(i
));
168 ah
->totalAdcDcOffsetIEvenPhase
[i
] +=
169 (int32_t) REG_READ(ah
, AR_PHY_CAL_MEAS_1(i
));
170 ah
->totalAdcDcOffsetQOddPhase
[i
] +=
171 (int32_t) REG_READ(ah
, AR_PHY_CAL_MEAS_2(i
));
172 ah
->totalAdcDcOffsetQEvenPhase
[i
] +=
173 (int32_t) REG_READ(ah
, AR_PHY_CAL_MEAS_3(i
));
175 ath_print(ath9k_hw_common(ah
), ATH_DBG_CALIBRATE
,
176 "%d: Chn %d oddi=0x%08x; eveni=0x%08x; "
177 "oddq=0x%08x; evenq=0x%08x;\n",
179 ah
->totalAdcDcOffsetIOddPhase
[i
],
180 ah
->totalAdcDcOffsetIEvenPhase
[i
],
181 ah
->totalAdcDcOffsetQOddPhase
[i
],
182 ah
->totalAdcDcOffsetQEvenPhase
[i
]);
186 static void ar9002_hw_iqcalibrate(struct ath_hw
*ah
, u8 numChains
)
188 struct ath_common
*common
= ath9k_hw_common(ah
);
189 u32 powerMeasQ
, powerMeasI
, iqCorrMeas
;
190 u32 qCoffDenom
, iCoffDenom
;
191 int32_t qCoff
, iCoff
;
194 for (i
= 0; i
< numChains
; i
++) {
195 powerMeasI
= ah
->totalPowerMeasI
[i
];
196 powerMeasQ
= ah
->totalPowerMeasQ
[i
];
197 iqCorrMeas
= ah
->totalIqCorrMeas
[i
];
199 ath_print(common
, ATH_DBG_CALIBRATE
,
200 "Starting IQ Cal and Correction for Chain %d\n",
203 ath_print(common
, ATH_DBG_CALIBRATE
,
204 "Orignal: Chn %diq_corr_meas = 0x%08x\n",
205 i
, ah
->totalIqCorrMeas
[i
]);
209 if (iqCorrMeas
> 0x80000000) {
210 iqCorrMeas
= (0xffffffff - iqCorrMeas
) + 1;
214 ath_print(common
, ATH_DBG_CALIBRATE
,
215 "Chn %d pwr_meas_i = 0x%08x\n", i
, powerMeasI
);
216 ath_print(common
, ATH_DBG_CALIBRATE
,
217 "Chn %d pwr_meas_q = 0x%08x\n", i
, powerMeasQ
);
218 ath_print(common
, ATH_DBG_CALIBRATE
, "iqCorrNeg is 0x%08x\n",
221 iCoffDenom
= (powerMeasI
/ 2 + powerMeasQ
/ 2) / 128;
222 qCoffDenom
= powerMeasQ
/ 64;
224 if ((powerMeasQ
!= 0) && (iCoffDenom
!= 0) &&
226 iCoff
= iqCorrMeas
/ iCoffDenom
;
227 qCoff
= powerMeasI
/ qCoffDenom
- 64;
228 ath_print(common
, ATH_DBG_CALIBRATE
,
229 "Chn %d iCoff = 0x%08x\n", i
, iCoff
);
230 ath_print(common
, ATH_DBG_CALIBRATE
,
231 "Chn %d qCoff = 0x%08x\n", i
, qCoff
);
233 iCoff
= iCoff
& 0x3f;
234 ath_print(common
, ATH_DBG_CALIBRATE
,
235 "New: Chn %d iCoff = 0x%08x\n", i
, iCoff
);
236 if (iqCorrNeg
== 0x0)
237 iCoff
= 0x40 - iCoff
;
241 else if (qCoff
<= -16)
244 ath_print(common
, ATH_DBG_CALIBRATE
,
245 "Chn %d : iCoff = 0x%x qCoff = 0x%x\n",
248 REG_RMW_FIELD(ah
, AR_PHY_TIMING_CTRL4(i
),
249 AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF
,
251 REG_RMW_FIELD(ah
, AR_PHY_TIMING_CTRL4(i
),
252 AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF
,
254 ath_print(common
, ATH_DBG_CALIBRATE
,
255 "IQ Cal and Correction done for Chain %d\n",
260 REG_SET_BIT(ah
, AR_PHY_TIMING_CTRL4(0),
261 AR_PHY_TIMING_CTRL4_IQCORR_ENABLE
);
264 static void ar9002_hw_adc_gaincal_calibrate(struct ath_hw
*ah
, u8 numChains
)
266 struct ath_common
*common
= ath9k_hw_common(ah
);
267 u32 iOddMeasOffset
, iEvenMeasOffset
, qOddMeasOffset
, qEvenMeasOffset
;
268 u32 qGainMismatch
, iGainMismatch
, val
, i
;
270 for (i
= 0; i
< numChains
; i
++) {
271 iOddMeasOffset
= ah
->totalAdcIOddPhase
[i
];
272 iEvenMeasOffset
= ah
->totalAdcIEvenPhase
[i
];
273 qOddMeasOffset
= ah
->totalAdcQOddPhase
[i
];
274 qEvenMeasOffset
= ah
->totalAdcQEvenPhase
[i
];
276 ath_print(common
, ATH_DBG_CALIBRATE
,
277 "Starting ADC Gain Cal for Chain %d\n", i
);
279 ath_print(common
, ATH_DBG_CALIBRATE
,
280 "Chn %d pwr_meas_odd_i = 0x%08x\n", i
,
282 ath_print(common
, ATH_DBG_CALIBRATE
,
283 "Chn %d pwr_meas_even_i = 0x%08x\n", i
,
285 ath_print(common
, ATH_DBG_CALIBRATE
,
286 "Chn %d pwr_meas_odd_q = 0x%08x\n", i
,
288 ath_print(common
, ATH_DBG_CALIBRATE
,
289 "Chn %d pwr_meas_even_q = 0x%08x\n", i
,
292 if (iOddMeasOffset
!= 0 && qEvenMeasOffset
!= 0) {
294 ((iEvenMeasOffset
* 32) /
295 iOddMeasOffset
) & 0x3f;
297 ((qOddMeasOffset
* 32) /
298 qEvenMeasOffset
) & 0x3f;
300 ath_print(common
, ATH_DBG_CALIBRATE
,
301 "Chn %d gain_mismatch_i = 0x%08x\n", i
,
303 ath_print(common
, ATH_DBG_CALIBRATE
,
304 "Chn %d gain_mismatch_q = 0x%08x\n", i
,
307 val
= REG_READ(ah
, AR_PHY_NEW_ADC_DC_GAIN_CORR(i
));
309 val
|= (qGainMismatch
) | (iGainMismatch
<< 6);
310 REG_WRITE(ah
, AR_PHY_NEW_ADC_DC_GAIN_CORR(i
), val
);
312 ath_print(common
, ATH_DBG_CALIBRATE
,
313 "ADC Gain Cal done for Chain %d\n", i
);
317 REG_WRITE(ah
, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
318 REG_READ(ah
, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
319 AR_PHY_NEW_ADC_GAIN_CORR_ENABLE
);
322 static void ar9002_hw_adc_dccal_calibrate(struct ath_hw
*ah
, u8 numChains
)
324 struct ath_common
*common
= ath9k_hw_common(ah
);
325 u32 iOddMeasOffset
, iEvenMeasOffset
, val
, i
;
326 int32_t qOddMeasOffset
, qEvenMeasOffset
, qDcMismatch
, iDcMismatch
;
327 const struct ath9k_percal_data
*calData
=
328 ah
->cal_list_curr
->calData
;
330 (1 << (calData
->calCountMax
+ 5)) * calData
->calNumSamples
;
332 for (i
= 0; i
< numChains
; i
++) {
333 iOddMeasOffset
= ah
->totalAdcDcOffsetIOddPhase
[i
];
334 iEvenMeasOffset
= ah
->totalAdcDcOffsetIEvenPhase
[i
];
335 qOddMeasOffset
= ah
->totalAdcDcOffsetQOddPhase
[i
];
336 qEvenMeasOffset
= ah
->totalAdcDcOffsetQEvenPhase
[i
];
338 ath_print(common
, ATH_DBG_CALIBRATE
,
339 "Starting ADC DC Offset Cal for Chain %d\n", i
);
341 ath_print(common
, ATH_DBG_CALIBRATE
,
342 "Chn %d pwr_meas_odd_i = %d\n", i
,
344 ath_print(common
, ATH_DBG_CALIBRATE
,
345 "Chn %d pwr_meas_even_i = %d\n", i
,
347 ath_print(common
, ATH_DBG_CALIBRATE
,
348 "Chn %d pwr_meas_odd_q = %d\n", i
,
350 ath_print(common
, ATH_DBG_CALIBRATE
,
351 "Chn %d pwr_meas_even_q = %d\n", i
,
354 iDcMismatch
= (((iEvenMeasOffset
- iOddMeasOffset
) * 2) /
356 qDcMismatch
= (((qOddMeasOffset
- qEvenMeasOffset
) * 2) /
359 ath_print(common
, ATH_DBG_CALIBRATE
,
360 "Chn %d dc_offset_mismatch_i = 0x%08x\n", i
,
362 ath_print(common
, ATH_DBG_CALIBRATE
,
363 "Chn %d dc_offset_mismatch_q = 0x%08x\n", i
,
366 val
= REG_READ(ah
, AR_PHY_NEW_ADC_DC_GAIN_CORR(i
));
368 val
|= (qDcMismatch
<< 12) | (iDcMismatch
<< 21);
369 REG_WRITE(ah
, AR_PHY_NEW_ADC_DC_GAIN_CORR(i
), val
);
371 ath_print(common
, ATH_DBG_CALIBRATE
,
372 "ADC DC Offset Cal done for Chain %d\n", i
);
375 REG_WRITE(ah
, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
376 REG_READ(ah
, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
377 AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE
);
380 static void ar9287_hw_olc_temp_compensation(struct ath_hw
*ah
)
383 int32_t delta
, currPDADC
, slope
;
385 rddata
= REG_READ(ah
, AR_PHY_TX_PWRCTRL4
);
386 currPDADC
= MS(rddata
, AR_PHY_TX_PWRCTRL_PD_AVG_OUT
);
388 if (ah
->initPDADC
== 0 || currPDADC
== 0) {
390 * Zero value indicates that no frames have been transmitted
391 * yet, can't do temperature compensation until frames are
396 slope
= ah
->eep_ops
->get_eeprom(ah
, EEP_TEMPSENSE_SLOPE
);
398 if (slope
== 0) { /* to avoid divide by zero case */
401 delta
= ((currPDADC
- ah
->initPDADC
)*4) / slope
;
403 REG_RMW_FIELD(ah
, AR_PHY_CH0_TX_PWRCTRL11
,
404 AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP
, delta
);
405 REG_RMW_FIELD(ah
, AR_PHY_CH1_TX_PWRCTRL11
,
406 AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP
, delta
);
410 static void ar9280_hw_olc_temp_compensation(struct ath_hw
*ah
)
413 int delta
, currPDADC
, regval
;
415 rddata
= REG_READ(ah
, AR_PHY_TX_PWRCTRL4
);
416 currPDADC
= MS(rddata
, AR_PHY_TX_PWRCTRL_PD_AVG_OUT
);
418 if (ah
->initPDADC
== 0 || currPDADC
== 0)
421 if (ah
->eep_ops
->get_eeprom(ah
, EEP_DAC_HPWR_5G
))
422 delta
= (currPDADC
- ah
->initPDADC
+ 4) / 8;
424 delta
= (currPDADC
- ah
->initPDADC
+ 5) / 10;
426 if (delta
!= ah
->PDADCdelta
) {
427 ah
->PDADCdelta
= delta
;
428 for (i
= 1; i
< AR9280_TX_GAIN_TABLE_SIZE
; i
++) {
429 regval
= ah
->originalGain
[i
] - delta
;
434 AR_PHY_TX_GAIN_TBL1
+ i
* 4,
435 AR_PHY_TX_GAIN
, regval
);
440 static void ar9271_hw_pa_cal(struct ath_hw
*ah
, bool is_reset
)
455 for (i
= 0; i
< ARRAY_SIZE(regList
); i
++)
456 regList
[i
][1] = REG_READ(ah
, regList
[i
][0]);
458 regVal
= REG_READ(ah
, 0x7834);
460 REG_WRITE(ah
, 0x7834, regVal
);
461 regVal
= REG_READ(ah
, 0x9808);
462 regVal
|= (0x1 << 27);
463 REG_WRITE(ah
, 0x9808, regVal
);
465 /* 786c,b23,1, pwddac=1 */
466 REG_RMW_FIELD(ah
, AR9285_AN_TOP3
, AR9285_AN_TOP3_PWDDAC
, 1);
467 /* 7854, b5,1, pdrxtxbb=1 */
468 REG_RMW_FIELD(ah
, AR9285_AN_RXTXBB1
, AR9285_AN_RXTXBB1_PDRXTXBB1
, 1);
469 /* 7854, b7,1, pdv2i=1 */
470 REG_RMW_FIELD(ah
, AR9285_AN_RXTXBB1
, AR9285_AN_RXTXBB1_PDV2I
, 1);
471 /* 7854, b8,1, pddacinterface=1 */
472 REG_RMW_FIELD(ah
, AR9285_AN_RXTXBB1
, AR9285_AN_RXTXBB1_PDDACIF
, 1);
473 /* 7824,b12,0, offcal=0 */
474 REG_RMW_FIELD(ah
, AR9285_AN_RF2G2
, AR9285_AN_RF2G2_OFFCAL
, 0);
475 /* 7838, b1,0, pwddb=0 */
476 REG_RMW_FIELD(ah
, AR9285_AN_RF2G7
, AR9285_AN_RF2G7_PWDDB
, 0);
477 /* 7820,b11,0, enpacal=0 */
478 REG_RMW_FIELD(ah
, AR9285_AN_RF2G1
, AR9285_AN_RF2G1_ENPACAL
, 0);
479 /* 7820,b25,1, pdpadrv1=0 */
480 REG_RMW_FIELD(ah
, AR9285_AN_RF2G1
, AR9285_AN_RF2G1_PDPADRV1
, 0);
481 /* 7820,b24,0, pdpadrv2=0 */
482 REG_RMW_FIELD(ah
, AR9285_AN_RF2G1
, AR9285_AN_RF2G1_PDPADRV2
, 0);
483 /* 7820,b23,0, pdpaout=0 */
484 REG_RMW_FIELD(ah
, AR9285_AN_RF2G1
, AR9285_AN_RF2G1_PDPAOUT
, 0);
485 /* 783c,b14-16,7, padrvgn2tab_0=7 */
486 REG_RMW_FIELD(ah
, AR9285_AN_RF2G8
, AR9285_AN_RF2G8_PADRVGN2TAB0
, 7);
488 * 7838,b29-31,0, padrvgn1tab_0=0
489 * does not matter since we turn it off
491 REG_RMW_FIELD(ah
, AR9285_AN_RF2G7
, AR9285_AN_RF2G7_PADRVGN2TAB0
, 0);
493 REG_RMW_FIELD(ah
, AR9285_AN_RF2G3
, AR9271_AN_RF2G3_CCOMP
, 0xfff);
496 * localmode=1,bmode=1,bmoderxtx=1,synthon=1,
497 * txon=1,paon=1,oscon=1,synthon_force=1
499 REG_WRITE(ah
, AR9285_AN_TOP2
, 0xca0358a0);
501 REG_RMW_FIELD(ah
, AR9285_AN_RF2G6
, AR9271_AN_RF2G6_OFFS
, 0);
504 for (i
= 6; i
> 0; i
--) {
505 regVal
= REG_READ(ah
, 0x7834);
506 regVal
|= (1 << (20 + i
));
507 REG_WRITE(ah
, 0x7834, regVal
);
509 /* regVal = REG_READ(ah, 0x7834); */
510 regVal
&= (~(0x1 << (20 + i
)));
511 regVal
|= (MS(REG_READ(ah
, 0x7840), AR9285_AN_RXTXBB1_SPARE9
)
513 REG_WRITE(ah
, 0x7834, regVal
);
516 regVal
= (regVal
>> 20) & 0x7f;
518 /* Update PA cal info */
519 if ((!is_reset
) && (ah
->pacal_info
.prev_offset
== regVal
)) {
520 if (ah
->pacal_info
.max_skipcount
< MAX_PACAL_SKIPCOUNT
)
521 ah
->pacal_info
.max_skipcount
=
522 2 * ah
->pacal_info
.max_skipcount
;
523 ah
->pacal_info
.skipcount
= ah
->pacal_info
.max_skipcount
;
525 ah
->pacal_info
.max_skipcount
= 1;
526 ah
->pacal_info
.skipcount
= 0;
527 ah
->pacal_info
.prev_offset
= regVal
;
530 ENABLE_REGWRITE_BUFFER(ah
);
532 regVal
= REG_READ(ah
, 0x7834);
534 REG_WRITE(ah
, 0x7834, regVal
);
535 regVal
= REG_READ(ah
, 0x9808);
536 regVal
&= (~(0x1 << 27));
537 REG_WRITE(ah
, 0x9808, regVal
);
539 for (i
= 0; i
< ARRAY_SIZE(regList
); i
++)
540 REG_WRITE(ah
, regList
[i
][0], regList
[i
][1]);
542 REGWRITE_BUFFER_FLUSH(ah
);
543 DISABLE_REGWRITE_BUFFER(ah
);
546 static inline void ar9285_hw_pa_cal(struct ath_hw
*ah
, bool is_reset
)
548 struct ath_common
*common
= ath9k_hw_common(ah
);
550 int i
, offset
, offs_6_1
, offs_0
;
551 u32 ccomp_org
, reg_field
;
562 ath_print(common
, ATH_DBG_CALIBRATE
, "Running PA Calibration\n");
564 /* PA CAL is not needed for high power solution */
565 if (ah
->eep_ops
->get_eeprom(ah
, EEP_TXGAIN_TYPE
) ==
566 AR5416_EEP_TXGAIN_HIGH_POWER
)
569 if (AR_SREV_9285_11(ah
)) {
570 REG_WRITE(ah
, AR9285_AN_TOP4
, (AR9285_AN_TOP4_DEFAULT
| 0x14));
574 for (i
= 0; i
< ARRAY_SIZE(regList
); i
++)
575 regList
[i
][1] = REG_READ(ah
, regList
[i
][0]);
577 regVal
= REG_READ(ah
, 0x7834);
579 REG_WRITE(ah
, 0x7834, regVal
);
580 regVal
= REG_READ(ah
, 0x9808);
581 regVal
|= (0x1 << 27);
582 REG_WRITE(ah
, 0x9808, regVal
);
584 REG_RMW_FIELD(ah
, AR9285_AN_TOP3
, AR9285_AN_TOP3_PWDDAC
, 1);
585 REG_RMW_FIELD(ah
, AR9285_AN_RXTXBB1
, AR9285_AN_RXTXBB1_PDRXTXBB1
, 1);
586 REG_RMW_FIELD(ah
, AR9285_AN_RXTXBB1
, AR9285_AN_RXTXBB1_PDV2I
, 1);
587 REG_RMW_FIELD(ah
, AR9285_AN_RXTXBB1
, AR9285_AN_RXTXBB1_PDDACIF
, 1);
588 REG_RMW_FIELD(ah
, AR9285_AN_RF2G2
, AR9285_AN_RF2G2_OFFCAL
, 0);
589 REG_RMW_FIELD(ah
, AR9285_AN_RF2G7
, AR9285_AN_RF2G7_PWDDB
, 0);
590 REG_RMW_FIELD(ah
, AR9285_AN_RF2G1
, AR9285_AN_RF2G1_ENPACAL
, 0);
591 REG_RMW_FIELD(ah
, AR9285_AN_RF2G1
, AR9285_AN_RF2G1_PDPADRV1
, 0);
592 REG_RMW_FIELD(ah
, AR9285_AN_RF2G1
, AR9285_AN_RF2G1_PDPADRV2
, 0);
593 REG_RMW_FIELD(ah
, AR9285_AN_RF2G1
, AR9285_AN_RF2G1_PDPAOUT
, 0);
594 REG_RMW_FIELD(ah
, AR9285_AN_RF2G8
, AR9285_AN_RF2G8_PADRVGN2TAB0
, 7);
595 REG_RMW_FIELD(ah
, AR9285_AN_RF2G7
, AR9285_AN_RF2G7_PADRVGN2TAB0
, 0);
596 ccomp_org
= MS(REG_READ(ah
, AR9285_AN_RF2G6
), AR9285_AN_RF2G6_CCOMP
);
597 REG_RMW_FIELD(ah
, AR9285_AN_RF2G6
, AR9285_AN_RF2G6_CCOMP
, 0xf);
599 REG_WRITE(ah
, AR9285_AN_TOP2
, 0xca0358a0);
601 REG_RMW_FIELD(ah
, AR9285_AN_RF2G6
, AR9285_AN_RF2G6_OFFS
, 0);
602 REG_RMW_FIELD(ah
, AR9285_AN_RF2G3
, AR9285_AN_RF2G3_PDVCCOMP
, 0);
604 for (i
= 6; i
> 0; i
--) {
605 regVal
= REG_READ(ah
, 0x7834);
606 regVal
|= (1 << (19 + i
));
607 REG_WRITE(ah
, 0x7834, regVal
);
609 regVal
= REG_READ(ah
, 0x7834);
610 regVal
&= (~(0x1 << (19 + i
)));
611 reg_field
= MS(REG_READ(ah
, 0x7840), AR9285_AN_RXTXBB1_SPARE9
);
612 regVal
|= (reg_field
<< (19 + i
));
613 REG_WRITE(ah
, 0x7834, regVal
);
616 REG_RMW_FIELD(ah
, AR9285_AN_RF2G3
, AR9285_AN_RF2G3_PDVCCOMP
, 1);
618 reg_field
= MS(REG_READ(ah
, AR9285_AN_RF2G9
), AR9285_AN_RXTXBB1_SPARE9
);
619 REG_RMW_FIELD(ah
, AR9285_AN_RF2G3
, AR9285_AN_RF2G3_PDVCCOMP
, reg_field
);
620 offs_6_1
= MS(REG_READ(ah
, AR9285_AN_RF2G6
), AR9285_AN_RF2G6_OFFS
);
621 offs_0
= MS(REG_READ(ah
, AR9285_AN_RF2G3
), AR9285_AN_RF2G3_PDVCCOMP
);
623 offset
= (offs_6_1
<<1) | offs_0
;
625 offs_6_1
= offset
>>1;
628 if ((!is_reset
) && (ah
->pacal_info
.prev_offset
== offset
)) {
629 if (ah
->pacal_info
.max_skipcount
< MAX_PACAL_SKIPCOUNT
)
630 ah
->pacal_info
.max_skipcount
=
631 2 * ah
->pacal_info
.max_skipcount
;
632 ah
->pacal_info
.skipcount
= ah
->pacal_info
.max_skipcount
;
634 ah
->pacal_info
.max_skipcount
= 1;
635 ah
->pacal_info
.skipcount
= 0;
636 ah
->pacal_info
.prev_offset
= offset
;
639 REG_RMW_FIELD(ah
, AR9285_AN_RF2G6
, AR9285_AN_RF2G6_OFFS
, offs_6_1
);
640 REG_RMW_FIELD(ah
, AR9285_AN_RF2G3
, AR9285_AN_RF2G3_PDVCCOMP
, offs_0
);
642 regVal
= REG_READ(ah
, 0x7834);
644 REG_WRITE(ah
, 0x7834, regVal
);
645 regVal
= REG_READ(ah
, 0x9808);
646 regVal
&= (~(0x1 << 27));
647 REG_WRITE(ah
, 0x9808, regVal
);
649 for (i
= 0; i
< ARRAY_SIZE(regList
); i
++)
650 REG_WRITE(ah
, regList
[i
][0], regList
[i
][1]);
652 REG_RMW_FIELD(ah
, AR9285_AN_RF2G6
, AR9285_AN_RF2G6_CCOMP
, ccomp_org
);
654 if (AR_SREV_9285_11(ah
))
655 REG_WRITE(ah
, AR9285_AN_TOP4
, AR9285_AN_TOP4_DEFAULT
);
659 static void ar9002_hw_pa_cal(struct ath_hw
*ah
, bool is_reset
)
661 if (AR_SREV_9271(ah
)) {
662 if (is_reset
|| !ah
->pacal_info
.skipcount
)
663 ar9271_hw_pa_cal(ah
, is_reset
);
665 ah
->pacal_info
.skipcount
--;
666 } else if (AR_SREV_9285_11_OR_LATER(ah
)) {
667 if (is_reset
|| !ah
->pacal_info
.skipcount
)
668 ar9285_hw_pa_cal(ah
, is_reset
);
670 ah
->pacal_info
.skipcount
--;
674 static void ar9002_hw_olc_temp_compensation(struct ath_hw
*ah
)
676 if (OLC_FOR_AR9287_10_LATER
)
677 ar9287_hw_olc_temp_compensation(ah
);
678 else if (OLC_FOR_AR9280_20_LATER
)
679 ar9280_hw_olc_temp_compensation(ah
);
682 static bool ar9002_hw_calibrate(struct ath_hw
*ah
,
683 struct ath9k_channel
*chan
,
687 bool iscaldone
= true;
688 struct ath9k_cal_list
*currCal
= ah
->cal_list_curr
;
691 (currCal
->calState
== CAL_RUNNING
||
692 currCal
->calState
== CAL_WAITING
)) {
693 iscaldone
= ar9002_hw_per_calibration(ah
, chan
,
694 rxchainmask
, currCal
);
696 ah
->cal_list_curr
= currCal
= currCal
->calNext
;
698 if (currCal
->calState
== CAL_WAITING
) {
700 ath9k_hw_reset_calibration(ah
, currCal
);
705 /* Do NF cal only at longer intervals */
707 /* Do periodic PAOffset Cal */
708 ar9002_hw_pa_cal(ah
, false);
709 ar9002_hw_olc_temp_compensation(ah
);
712 * Get the value from the previous NF cal and update
715 ath9k_hw_getnf(ah
, chan
);
718 * Load the NF from history buffer of the current channel.
719 * NF is slow time-variant, so it is OK to use a historical
722 ath9k_hw_loadnf(ah
, ah
->curchan
);
724 ath9k_hw_start_nfcal(ah
);
730 /* Carrier leakage Calibration fix */
731 static bool ar9285_hw_cl_cal(struct ath_hw
*ah
, struct ath9k_channel
*chan
)
733 struct ath_common
*common
= ath9k_hw_common(ah
);
735 REG_SET_BIT(ah
, AR_PHY_CL_CAL_CTL
, AR_PHY_CL_CAL_ENABLE
);
736 if (IS_CHAN_HT20(chan
)) {
737 REG_SET_BIT(ah
, AR_PHY_CL_CAL_CTL
, AR_PHY_PARALLEL_CAL_ENABLE
);
738 REG_SET_BIT(ah
, AR_PHY_TURBO
, AR_PHY_FC_DYN2040_EN
);
739 REG_CLR_BIT(ah
, AR_PHY_AGC_CONTROL
,
740 AR_PHY_AGC_CONTROL_FLTR_CAL
);
741 REG_CLR_BIT(ah
, AR_PHY_TPCRG1
, AR_PHY_TPCRG1_PD_CAL_ENABLE
);
742 REG_SET_BIT(ah
, AR_PHY_AGC_CONTROL
, AR_PHY_AGC_CONTROL_CAL
);
743 if (!ath9k_hw_wait(ah
, AR_PHY_AGC_CONTROL
,
744 AR_PHY_AGC_CONTROL_CAL
, 0, AH_WAIT_TIMEOUT
)) {
745 ath_print(common
, ATH_DBG_CALIBRATE
, "offset "
746 "calibration failed to complete in "
750 REG_CLR_BIT(ah
, AR_PHY_TURBO
, AR_PHY_FC_DYN2040_EN
);
751 REG_CLR_BIT(ah
, AR_PHY_CL_CAL_CTL
, AR_PHY_PARALLEL_CAL_ENABLE
);
752 REG_CLR_BIT(ah
, AR_PHY_CL_CAL_CTL
, AR_PHY_CL_CAL_ENABLE
);
754 REG_CLR_BIT(ah
, AR_PHY_ADC_CTL
, AR_PHY_ADC_CTL_OFF_PWDADC
);
755 REG_SET_BIT(ah
, AR_PHY_AGC_CONTROL
, AR_PHY_AGC_CONTROL_FLTR_CAL
);
756 REG_SET_BIT(ah
, AR_PHY_TPCRG1
, AR_PHY_TPCRG1_PD_CAL_ENABLE
);
757 REG_SET_BIT(ah
, AR_PHY_AGC_CONTROL
, AR_PHY_AGC_CONTROL_CAL
);
758 if (!ath9k_hw_wait(ah
, AR_PHY_AGC_CONTROL
, AR_PHY_AGC_CONTROL_CAL
,
759 0, AH_WAIT_TIMEOUT
)) {
760 ath_print(common
, ATH_DBG_CALIBRATE
, "offset calibration "
761 "failed to complete in 1ms; noisy ??\n");
765 REG_SET_BIT(ah
, AR_PHY_ADC_CTL
, AR_PHY_ADC_CTL_OFF_PWDADC
);
766 REG_CLR_BIT(ah
, AR_PHY_CL_CAL_CTL
, AR_PHY_CL_CAL_ENABLE
);
767 REG_CLR_BIT(ah
, AR_PHY_AGC_CONTROL
, AR_PHY_AGC_CONTROL_FLTR_CAL
);
772 static bool ar9285_hw_clc(struct ath_hw
*ah
, struct ath9k_channel
*chan
)
775 u_int32_t txgain_max
;
776 u_int32_t clc_gain
, gain_mask
= 0, clc_num
= 0;
777 u_int32_t reg_clc_I0
, reg_clc_Q0
;
778 u_int32_t i0_num
= 0;
779 u_int32_t q0_num
= 0;
780 u_int32_t total_num
= 0;
781 u_int32_t reg_rf2g5_org
;
784 if (!(ar9285_hw_cl_cal(ah
, chan
)))
787 txgain_max
= MS(REG_READ(ah
, AR_PHY_TX_PWRCTRL7
),
788 AR_PHY_TX_PWRCTRL_TX_GAIN_TAB_MAX
);
790 for (i
= 0; i
< (txgain_max
+1); i
++) {
791 clc_gain
= (REG_READ(ah
, (AR_PHY_TX_GAIN_TBL1
+(i
<<2))) &
792 AR_PHY_TX_GAIN_CLC
) >> AR_PHY_TX_GAIN_CLC_S
;
793 if (!(gain_mask
& (1 << clc_gain
))) {
794 gain_mask
|= (1 << clc_gain
);
799 for (i
= 0; i
< clc_num
; i
++) {
800 reg_clc_I0
= (REG_READ(ah
, (AR_PHY_CLC_TBL1
+ (i
<< 2)))
801 & AR_PHY_CLC_I0
) >> AR_PHY_CLC_I0_S
;
802 reg_clc_Q0
= (REG_READ(ah
, (AR_PHY_CLC_TBL1
+ (i
<< 2)))
803 & AR_PHY_CLC_Q0
) >> AR_PHY_CLC_Q0_S
;
810 total_num
= i0_num
+ q0_num
;
811 if (total_num
> AR9285_CLCAL_REDO_THRESH
) {
812 reg_rf2g5_org
= REG_READ(ah
, AR9285_RF2G5
);
813 if (AR_SREV_9285E_20(ah
)) {
814 REG_WRITE(ah
, AR9285_RF2G5
,
815 (reg_rf2g5_org
& AR9285_RF2G5_IC50TX
) |
816 AR9285_RF2G5_IC50TX_XE_SET
);
818 REG_WRITE(ah
, AR9285_RF2G5
,
819 (reg_rf2g5_org
& AR9285_RF2G5_IC50TX
) |
820 AR9285_RF2G5_IC50TX_SET
);
822 retv
= ar9285_hw_cl_cal(ah
, chan
);
823 REG_WRITE(ah
, AR9285_RF2G5
, reg_rf2g5_org
);
828 static bool ar9002_hw_init_cal(struct ath_hw
*ah
, struct ath9k_channel
*chan
)
830 struct ath_common
*common
= ath9k_hw_common(ah
);
832 if (AR_SREV_9271(ah
) || AR_SREV_9285_12_OR_LATER(ah
)) {
833 if (!ar9285_hw_clc(ah
, chan
))
836 if (AR_SREV_9280_10_OR_LATER(ah
)) {
837 if (!AR_SREV_9287_10_OR_LATER(ah
))
838 REG_CLR_BIT(ah
, AR_PHY_ADC_CTL
,
839 AR_PHY_ADC_CTL_OFF_PWDADC
);
840 REG_SET_BIT(ah
, AR_PHY_AGC_CONTROL
,
841 AR_PHY_AGC_CONTROL_FLTR_CAL
);
844 /* Calibrate the AGC */
845 REG_WRITE(ah
, AR_PHY_AGC_CONTROL
,
846 REG_READ(ah
, AR_PHY_AGC_CONTROL
) |
847 AR_PHY_AGC_CONTROL_CAL
);
849 /* Poll for offset calibration complete */
850 if (!ath9k_hw_wait(ah
, AR_PHY_AGC_CONTROL
,
851 AR_PHY_AGC_CONTROL_CAL
,
852 0, AH_WAIT_TIMEOUT
)) {
853 ath_print(common
, ATH_DBG_CALIBRATE
,
854 "offset calibration failed to "
855 "complete in 1ms; noisy environment?\n");
859 if (AR_SREV_9280_10_OR_LATER(ah
)) {
860 if (!AR_SREV_9287_10_OR_LATER(ah
))
861 REG_SET_BIT(ah
, AR_PHY_ADC_CTL
,
862 AR_PHY_ADC_CTL_OFF_PWDADC
);
863 REG_CLR_BIT(ah
, AR_PHY_AGC_CONTROL
,
864 AR_PHY_AGC_CONTROL_FLTR_CAL
);
868 /* Do PA Calibration */
869 ar9002_hw_pa_cal(ah
, true);
871 /* Do NF Calibration after DC offset and other calibrations */
872 REG_WRITE(ah
, AR_PHY_AGC_CONTROL
,
873 REG_READ(ah
, AR_PHY_AGC_CONTROL
) | AR_PHY_AGC_CONTROL_NF
);
875 ah
->cal_list
= ah
->cal_list_last
= ah
->cal_list_curr
= NULL
;
877 /* Enable IQ, ADC Gain and ADC DC offset CALs */
878 if (AR_SREV_9100(ah
) || AR_SREV_9160_10_OR_LATER(ah
)) {
879 if (ar9002_hw_iscal_supported(ah
, ADC_GAIN_CAL
)) {
880 INIT_CAL(&ah
->adcgain_caldata
);
881 INSERT_CAL(ah
, &ah
->adcgain_caldata
);
882 ath_print(common
, ATH_DBG_CALIBRATE
,
883 "enabling ADC Gain Calibration.\n");
885 if (ar9002_hw_iscal_supported(ah
, ADC_DC_CAL
)) {
886 INIT_CAL(&ah
->adcdc_caldata
);
887 INSERT_CAL(ah
, &ah
->adcdc_caldata
);
888 ath_print(common
, ATH_DBG_CALIBRATE
,
889 "enabling ADC DC Calibration.\n");
891 if (ar9002_hw_iscal_supported(ah
, IQ_MISMATCH_CAL
)) {
892 INIT_CAL(&ah
->iq_caldata
);
893 INSERT_CAL(ah
, &ah
->iq_caldata
);
894 ath_print(common
, ATH_DBG_CALIBRATE
,
895 "enabling IQ Calibration.\n");
898 ah
->cal_list_curr
= ah
->cal_list
;
900 if (ah
->cal_list_curr
)
901 ath9k_hw_reset_calibration(ah
, ah
->cal_list_curr
);
909 static const struct ath9k_percal_data iq_cal_multi_sample
= {
913 ar9002_hw_iqcal_collect
,
914 ar9002_hw_iqcalibrate
916 static const struct ath9k_percal_data iq_cal_single_sample
= {
920 ar9002_hw_iqcal_collect
,
921 ar9002_hw_iqcalibrate
923 static const struct ath9k_percal_data adc_gain_cal_multi_sample
= {
927 ar9002_hw_adc_gaincal_collect
,
928 ar9002_hw_adc_gaincal_calibrate
930 static const struct ath9k_percal_data adc_gain_cal_single_sample
= {
934 ar9002_hw_adc_gaincal_collect
,
935 ar9002_hw_adc_gaincal_calibrate
937 static const struct ath9k_percal_data adc_dc_cal_multi_sample
= {
941 ar9002_hw_adc_dccal_collect
,
942 ar9002_hw_adc_dccal_calibrate
944 static const struct ath9k_percal_data adc_dc_cal_single_sample
= {
948 ar9002_hw_adc_dccal_collect
,
949 ar9002_hw_adc_dccal_calibrate
951 static const struct ath9k_percal_data adc_init_dc_cal
= {
955 ar9002_hw_adc_dccal_collect
,
956 ar9002_hw_adc_dccal_calibrate
959 static void ar9002_hw_init_cal_settings(struct ath_hw
*ah
)
961 if (AR_SREV_9100(ah
)) {
962 ah
->iq_caldata
.calData
= &iq_cal_multi_sample
;
963 ah
->supp_cals
= IQ_MISMATCH_CAL
;
967 if (AR_SREV_9160_10_OR_LATER(ah
)) {
968 if (AR_SREV_9280_10_OR_LATER(ah
)) {
969 ah
->iq_caldata
.calData
= &iq_cal_single_sample
;
970 ah
->adcgain_caldata
.calData
=
971 &adc_gain_cal_single_sample
;
972 ah
->adcdc_caldata
.calData
=
973 &adc_dc_cal_single_sample
;
974 ah
->adcdc_calinitdata
.calData
=
977 ah
->iq_caldata
.calData
= &iq_cal_multi_sample
;
978 ah
->adcgain_caldata
.calData
=
979 &adc_gain_cal_multi_sample
;
980 ah
->adcdc_caldata
.calData
=
981 &adc_dc_cal_multi_sample
;
982 ah
->adcdc_calinitdata
.calData
=
985 ah
->supp_cals
= ADC_GAIN_CAL
| ADC_DC_CAL
| IQ_MISMATCH_CAL
;
989 void ar9002_hw_attach_calib_ops(struct ath_hw
*ah
)
991 struct ath_hw_private_ops
*priv_ops
= ath9k_hw_private_ops(ah
);
992 struct ath_hw_ops
*ops
= ath9k_hw_ops(ah
);
994 priv_ops
->init_cal_settings
= ar9002_hw_init_cal_settings
;
995 priv_ops
->init_cal
= ar9002_hw_init_cal
;
996 priv_ops
->setup_calibration
= ar9002_hw_setup_calibration
;
997 priv_ops
->iscal_supported
= ar9002_hw_iscal_supported
;
999 ops
->calibrate
= ar9002_hw_calibrate
;