2 * Copyright (c) 2008-2011 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),
29 static bool ar9002_hw_is_cal_supported(struct ath_hw
*ah
,
30 struct ath9k_channel
*chan
,
31 enum ar9002_cal_types cal_type
)
33 bool supported
= false;
34 switch (ah
->supp_cals
& cal_type
) {
40 /* Run ADC Gain Cal for non-CCK & non 2GHz-HT20 only */
41 if (!((IS_CHAN_2GHZ(chan
) || IS_CHAN_A_FAST_CLOCK(ah
, chan
)) &&
49 static void ar9002_hw_setup_calibration(struct ath_hw
*ah
,
50 struct ath9k_cal_list
*currCal
)
52 struct ath_common
*common
= ath9k_hw_common(ah
);
54 REG_RMW_FIELD(ah
, AR_PHY_TIMING_CTRL4(0),
55 AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX
,
56 currCal
->calData
->calCountMax
);
58 switch (currCal
->calData
->calType
) {
60 REG_WRITE(ah
, AR_PHY_CALMODE
, AR_PHY_CALMODE_IQ
);
61 ath_dbg(common
, CALIBRATE
,
62 "starting IQ Mismatch Calibration\n");
65 REG_WRITE(ah
, AR_PHY_CALMODE
, AR_PHY_CALMODE_ADC_GAIN
);
66 ath_dbg(common
, CALIBRATE
, "starting ADC Gain Calibration\n");
69 REG_WRITE(ah
, AR_PHY_CALMODE
, AR_PHY_CALMODE_ADC_DC_PER
);
70 ath_dbg(common
, CALIBRATE
, "starting ADC DC Calibration\n");
74 REG_SET_BIT(ah
, AR_PHY_TIMING_CTRL4(0),
75 AR_PHY_TIMING_CTRL4_DO_CAL
);
78 static bool ar9002_hw_per_calibration(struct ath_hw
*ah
,
79 struct ath9k_channel
*ichan
,
81 struct ath9k_cal_list
*currCal
)
83 struct ath9k_hw_cal_data
*caldata
= ah
->caldata
;
84 bool iscaldone
= false;
86 if (currCal
->calState
== CAL_RUNNING
) {
87 if (!(REG_READ(ah
, AR_PHY_TIMING_CTRL4(0)) &
88 AR_PHY_TIMING_CTRL4_DO_CAL
)) {
90 currCal
->calData
->calCollect(ah
);
93 if (ah
->cal_samples
>=
94 currCal
->calData
->calNumSamples
) {
96 for (i
= 0; i
< AR5416_MAX_CHAINS
; i
++) {
97 if (rxchainmask
& (1 << i
))
101 currCal
->calData
->calPostProc(ah
, numChains
);
102 caldata
->CalValid
|= currCal
->calData
->calType
;
103 currCal
->calState
= CAL_DONE
;
106 ar9002_hw_setup_calibration(ah
, currCal
);
109 } else if (!(caldata
->CalValid
& currCal
->calData
->calType
)) {
110 ath9k_hw_reset_calibration(ah
, currCal
);
116 static void ar9002_hw_iqcal_collect(struct ath_hw
*ah
)
120 for (i
= 0; i
< AR5416_MAX_CHAINS
; i
++) {
121 ah
->totalPowerMeasI
[i
] +=
122 REG_READ(ah
, AR_PHY_CAL_MEAS_0(i
));
123 ah
->totalPowerMeasQ
[i
] +=
124 REG_READ(ah
, AR_PHY_CAL_MEAS_1(i
));
125 ah
->totalIqCorrMeas
[i
] +=
126 (int32_t) REG_READ(ah
, AR_PHY_CAL_MEAS_2(i
));
127 ath_dbg(ath9k_hw_common(ah
), CALIBRATE
,
128 "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
129 ah
->cal_samples
, i
, ah
->totalPowerMeasI
[i
],
130 ah
->totalPowerMeasQ
[i
],
131 ah
->totalIqCorrMeas
[i
]);
135 static void ar9002_hw_adc_gaincal_collect(struct ath_hw
*ah
)
139 for (i
= 0; i
< AR5416_MAX_CHAINS
; i
++) {
140 ah
->totalAdcIOddPhase
[i
] +=
141 REG_READ(ah
, AR_PHY_CAL_MEAS_0(i
));
142 ah
->totalAdcIEvenPhase
[i
] +=
143 REG_READ(ah
, AR_PHY_CAL_MEAS_1(i
));
144 ah
->totalAdcQOddPhase
[i
] +=
145 REG_READ(ah
, AR_PHY_CAL_MEAS_2(i
));
146 ah
->totalAdcQEvenPhase
[i
] +=
147 REG_READ(ah
, AR_PHY_CAL_MEAS_3(i
));
149 ath_dbg(ath9k_hw_common(ah
), CALIBRATE
,
150 "%d: Chn %d oddi=0x%08x; eveni=0x%08x; oddq=0x%08x; evenq=0x%08x;\n",
152 ah
->totalAdcIOddPhase
[i
],
153 ah
->totalAdcIEvenPhase
[i
],
154 ah
->totalAdcQOddPhase
[i
],
155 ah
->totalAdcQEvenPhase
[i
]);
159 static void ar9002_hw_adc_dccal_collect(struct ath_hw
*ah
)
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
));
173 ath_dbg(ath9k_hw_common(ah
), CALIBRATE
,
174 "%d: Chn %d oddi=0x%08x; eveni=0x%08x; oddq=0x%08x; evenq=0x%08x;\n",
176 ah
->totalAdcDcOffsetIOddPhase
[i
],
177 ah
->totalAdcDcOffsetIEvenPhase
[i
],
178 ah
->totalAdcDcOffsetQOddPhase
[i
],
179 ah
->totalAdcDcOffsetQEvenPhase
[i
]);
183 static void ar9002_hw_iqcalibrate(struct ath_hw
*ah
, u8 numChains
)
185 struct ath_common
*common
= ath9k_hw_common(ah
);
186 u32 powerMeasQ
, powerMeasI
, iqCorrMeas
;
187 u32 qCoffDenom
, iCoffDenom
;
188 int32_t qCoff
, iCoff
;
191 for (i
= 0; i
< numChains
; i
++) {
192 powerMeasI
= ah
->totalPowerMeasI
[i
];
193 powerMeasQ
= ah
->totalPowerMeasQ
[i
];
194 iqCorrMeas
= ah
->totalIqCorrMeas
[i
];
196 ath_dbg(common
, CALIBRATE
,
197 "Starting IQ Cal and Correction for Chain %d\n",
200 ath_dbg(common
, CALIBRATE
,
201 "Original: Chn %d iq_corr_meas = 0x%08x\n",
202 i
, ah
->totalIqCorrMeas
[i
]);
206 if (iqCorrMeas
> 0x80000000) {
207 iqCorrMeas
= (0xffffffff - iqCorrMeas
) + 1;
211 ath_dbg(common
, CALIBRATE
, "Chn %d pwr_meas_i = 0x%08x\n",
213 ath_dbg(common
, CALIBRATE
, "Chn %d pwr_meas_q = 0x%08x\n",
215 ath_dbg(common
, CALIBRATE
, "iqCorrNeg is 0x%08x\n", iqCorrNeg
);
217 iCoffDenom
= (powerMeasI
/ 2 + powerMeasQ
/ 2) / 128;
218 qCoffDenom
= powerMeasQ
/ 64;
220 if ((powerMeasQ
!= 0) && (iCoffDenom
!= 0) &&
222 iCoff
= iqCorrMeas
/ iCoffDenom
;
223 qCoff
= powerMeasI
/ qCoffDenom
- 64;
224 ath_dbg(common
, CALIBRATE
, "Chn %d iCoff = 0x%08x\n",
226 ath_dbg(common
, CALIBRATE
, "Chn %d qCoff = 0x%08x\n",
229 iCoff
= iCoff
& 0x3f;
230 ath_dbg(common
, CALIBRATE
,
231 "New: Chn %d iCoff = 0x%08x\n", i
, iCoff
);
232 if (iqCorrNeg
== 0x0)
233 iCoff
= 0x40 - iCoff
;
237 else if (qCoff
<= -16)
240 ath_dbg(common
, CALIBRATE
,
241 "Chn %d : iCoff = 0x%x qCoff = 0x%x\n",
244 REG_RMW_FIELD(ah
, AR_PHY_TIMING_CTRL4(i
),
245 AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF
,
247 REG_RMW_FIELD(ah
, AR_PHY_TIMING_CTRL4(i
),
248 AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF
,
250 ath_dbg(common
, CALIBRATE
,
251 "IQ Cal and Correction done for Chain %d\n",
256 REG_SET_BIT(ah
, AR_PHY_TIMING_CTRL4(0),
257 AR_PHY_TIMING_CTRL4_IQCORR_ENABLE
);
260 static void ar9002_hw_adc_gaincal_calibrate(struct ath_hw
*ah
, u8 numChains
)
262 struct ath_common
*common
= ath9k_hw_common(ah
);
263 u32 iOddMeasOffset
, iEvenMeasOffset
, qOddMeasOffset
, qEvenMeasOffset
;
264 u32 qGainMismatch
, iGainMismatch
, val
, i
;
266 for (i
= 0; i
< numChains
; i
++) {
267 iOddMeasOffset
= ah
->totalAdcIOddPhase
[i
];
268 iEvenMeasOffset
= ah
->totalAdcIEvenPhase
[i
];
269 qOddMeasOffset
= ah
->totalAdcQOddPhase
[i
];
270 qEvenMeasOffset
= ah
->totalAdcQEvenPhase
[i
];
272 ath_dbg(common
, CALIBRATE
,
273 "Starting ADC Gain Cal for Chain %d\n", i
);
275 ath_dbg(common
, CALIBRATE
, "Chn %d pwr_meas_odd_i = 0x%08x\n",
277 ath_dbg(common
, CALIBRATE
, "Chn %d pwr_meas_even_i = 0x%08x\n",
279 ath_dbg(common
, CALIBRATE
, "Chn %d pwr_meas_odd_q = 0x%08x\n",
281 ath_dbg(common
, CALIBRATE
, "Chn %d pwr_meas_even_q = 0x%08x\n",
284 if (iOddMeasOffset
!= 0 && qEvenMeasOffset
!= 0) {
286 ((iEvenMeasOffset
* 32) /
287 iOddMeasOffset
) & 0x3f;
289 ((qOddMeasOffset
* 32) /
290 qEvenMeasOffset
) & 0x3f;
292 ath_dbg(common
, CALIBRATE
,
293 "Chn %d gain_mismatch_i = 0x%08x\n",
295 ath_dbg(common
, CALIBRATE
,
296 "Chn %d gain_mismatch_q = 0x%08x\n",
299 val
= REG_READ(ah
, AR_PHY_NEW_ADC_DC_GAIN_CORR(i
));
301 val
|= (qGainMismatch
) | (iGainMismatch
<< 6);
302 REG_WRITE(ah
, AR_PHY_NEW_ADC_DC_GAIN_CORR(i
), val
);
304 ath_dbg(common
, CALIBRATE
,
305 "ADC Gain Cal done for Chain %d\n", i
);
309 REG_WRITE(ah
, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
310 REG_READ(ah
, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
311 AR_PHY_NEW_ADC_GAIN_CORR_ENABLE
);
314 static void ar9002_hw_adc_dccal_calibrate(struct ath_hw
*ah
, u8 numChains
)
316 struct ath_common
*common
= ath9k_hw_common(ah
);
317 u32 iOddMeasOffset
, iEvenMeasOffset
, val
, i
;
318 int32_t qOddMeasOffset
, qEvenMeasOffset
, qDcMismatch
, iDcMismatch
;
319 const struct ath9k_percal_data
*calData
=
320 ah
->cal_list_curr
->calData
;
322 (1 << (calData
->calCountMax
+ 5)) * calData
->calNumSamples
;
324 for (i
= 0; i
< numChains
; i
++) {
325 iOddMeasOffset
= ah
->totalAdcDcOffsetIOddPhase
[i
];
326 iEvenMeasOffset
= ah
->totalAdcDcOffsetIEvenPhase
[i
];
327 qOddMeasOffset
= ah
->totalAdcDcOffsetQOddPhase
[i
];
328 qEvenMeasOffset
= ah
->totalAdcDcOffsetQEvenPhase
[i
];
330 ath_dbg(common
, CALIBRATE
,
331 "Starting ADC DC Offset Cal for Chain %d\n", i
);
333 ath_dbg(common
, CALIBRATE
, "Chn %d pwr_meas_odd_i = %d\n",
335 ath_dbg(common
, CALIBRATE
, "Chn %d pwr_meas_even_i = %d\n",
337 ath_dbg(common
, CALIBRATE
, "Chn %d pwr_meas_odd_q = %d\n",
339 ath_dbg(common
, CALIBRATE
, "Chn %d pwr_meas_even_q = %d\n",
342 iDcMismatch
= (((iEvenMeasOffset
- iOddMeasOffset
) * 2) /
344 qDcMismatch
= (((qOddMeasOffset
- qEvenMeasOffset
) * 2) /
347 ath_dbg(common
, CALIBRATE
,
348 "Chn %d dc_offset_mismatch_i = 0x%08x\n",
350 ath_dbg(common
, CALIBRATE
,
351 "Chn %d dc_offset_mismatch_q = 0x%08x\n",
354 val
= REG_READ(ah
, AR_PHY_NEW_ADC_DC_GAIN_CORR(i
));
356 val
|= (qDcMismatch
<< 12) | (iDcMismatch
<< 21);
357 REG_WRITE(ah
, AR_PHY_NEW_ADC_DC_GAIN_CORR(i
), val
);
359 ath_dbg(common
, CALIBRATE
,
360 "ADC DC Offset Cal done for Chain %d\n", i
);
363 REG_WRITE(ah
, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
364 REG_READ(ah
, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
365 AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE
);
368 static void ar9287_hw_olc_temp_compensation(struct ath_hw
*ah
)
371 int32_t delta
, currPDADC
, slope
;
373 rddata
= REG_READ(ah
, AR_PHY_TX_PWRCTRL4
);
374 currPDADC
= MS(rddata
, AR_PHY_TX_PWRCTRL_PD_AVG_OUT
);
376 if (ah
->initPDADC
== 0 || currPDADC
== 0) {
378 * Zero value indicates that no frames have been transmitted
379 * yet, can't do temperature compensation until frames are
384 slope
= ah
->eep_ops
->get_eeprom(ah
, EEP_TEMPSENSE_SLOPE
);
386 if (slope
== 0) { /* to avoid divide by zero case */
389 delta
= ((currPDADC
- ah
->initPDADC
)*4) / slope
;
391 REG_RMW_FIELD(ah
, AR_PHY_CH0_TX_PWRCTRL11
,
392 AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP
, delta
);
393 REG_RMW_FIELD(ah
, AR_PHY_CH1_TX_PWRCTRL11
,
394 AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP
, delta
);
398 static void ar9280_hw_olc_temp_compensation(struct ath_hw
*ah
)
401 int delta
, currPDADC
, regval
;
403 rddata
= REG_READ(ah
, AR_PHY_TX_PWRCTRL4
);
404 currPDADC
= MS(rddata
, AR_PHY_TX_PWRCTRL_PD_AVG_OUT
);
406 if (ah
->initPDADC
== 0 || currPDADC
== 0)
409 if (ah
->eep_ops
->get_eeprom(ah
, EEP_DAC_HPWR_5G
))
410 delta
= (currPDADC
- ah
->initPDADC
+ 4) / 8;
412 delta
= (currPDADC
- ah
->initPDADC
+ 5) / 10;
414 if (delta
!= ah
->PDADCdelta
) {
415 ah
->PDADCdelta
= delta
;
416 for (i
= 1; i
< AR9280_TX_GAIN_TABLE_SIZE
; i
++) {
417 regval
= ah
->originalGain
[i
] - delta
;
422 AR_PHY_TX_GAIN_TBL1
+ i
* 4,
423 AR_PHY_TX_GAIN
, regval
);
428 static void ar9271_hw_pa_cal(struct ath_hw
*ah
, bool is_reset
)
433 { AR9285_AN_TOP3
, 0 },
434 { AR9285_AN_RXTXBB1
, 0 },
435 { AR9285_AN_RF2G1
, 0 },
436 { AR9285_AN_RF2G2
, 0 },
437 { AR9285_AN_TOP2
, 0 },
438 { AR9285_AN_RF2G8
, 0 },
439 { AR9285_AN_RF2G7
, 0 },
440 { AR9285_AN_RF2G3
, 0 },
443 REG_READ_ARRAY(ah
, regList
, ARRAY_SIZE(regList
));
445 ENABLE_REG_RMW_BUFFER(ah
);
447 REG_CLR_BIT(ah
, AR9285_AN_RF2G6
, 1 << 0);
449 REG_SET_BIT(ah
, 0x9808, 1 << 27);
450 /* 786c,b23,1, pwddac=1 */
451 REG_SET_BIT(ah
, AR9285_AN_TOP3
, AR9285_AN_TOP3_PWDDAC
);
452 /* 7854, b5,1, pdrxtxbb=1 */
453 REG_SET_BIT(ah
, AR9285_AN_RXTXBB1
, AR9285_AN_RXTXBB1_PDRXTXBB1
);
454 /* 7854, b7,1, pdv2i=1 */
455 REG_SET_BIT(ah
, AR9285_AN_RXTXBB1
, AR9285_AN_RXTXBB1_PDV2I
);
456 /* 7854, b8,1, pddacinterface=1 */
457 REG_SET_BIT(ah
, AR9285_AN_RXTXBB1
, AR9285_AN_RXTXBB1_PDDACIF
);
458 /* 7824,b12,0, offcal=0 */
459 REG_CLR_BIT(ah
, AR9285_AN_RF2G2
, AR9285_AN_RF2G2_OFFCAL
);
460 /* 7838, b1,0, pwddb=0 */
461 REG_CLR_BIT(ah
, AR9285_AN_RF2G7
, AR9285_AN_RF2G7_PWDDB
);
462 /* 7820,b11,0, enpacal=0 */
463 REG_CLR_BIT(ah
, AR9285_AN_RF2G1
, AR9285_AN_RF2G1_ENPACAL
);
464 /* 7820,b25,1, pdpadrv1=0 */
465 REG_CLR_BIT(ah
, AR9285_AN_RF2G1
, AR9285_AN_RF2G1_PDPADRV1
);
466 /* 7820,b24,0, pdpadrv2=0 */
467 REG_CLR_BIT(ah
, AR9285_AN_RF2G1
, AR9285_AN_RF2G1_PDPADRV2
);
468 /* 7820,b23,0, pdpaout=0 */
469 REG_CLR_BIT(ah
, AR9285_AN_RF2G1
, AR9285_AN_RF2G1_PDPAOUT
);
470 /* 783c,b14-16,7, padrvgn2tab_0=7 */
471 REG_RMW_FIELD(ah
, AR9285_AN_RF2G8
, AR9285_AN_RF2G8_PADRVGN2TAB0
, 7);
473 * 7838,b29-31,0, padrvgn1tab_0=0
474 * does not matter since we turn it off
476 REG_RMW_FIELD(ah
, AR9285_AN_RF2G7
, AR9285_AN_RF2G7_PADRVGN2TAB0
, 0);
477 /* 7828, b0-11, ccom=fff */
478 REG_RMW_FIELD(ah
, AR9285_AN_RF2G3
, AR9271_AN_RF2G3_CCOMP
, 0xfff);
479 REG_RMW_BUFFER_FLUSH(ah
);
482 * localmode=1,bmode=1,bmoderxtx=1,synthon=1,
483 * txon=1,paon=1,oscon=1,synthon_force=1
485 REG_WRITE(ah
, AR9285_AN_TOP2
, 0xca0358a0);
487 REG_RMW_FIELD(ah
, AR9285_AN_RF2G6
, AR9271_AN_RF2G6_OFFS
, 0);
490 for (i
= 6; i
> 0; i
--) {
491 regVal
= REG_READ(ah
, AR9285_AN_RF2G6
);
492 regVal
|= (1 << (20 + i
));
493 REG_WRITE(ah
, AR9285_AN_RF2G6
, regVal
);
495 /* regVal = REG_READ(ah, 0x7834); */
496 regVal
&= (~(0x1 << (20 + i
)));
497 regVal
|= (MS(REG_READ(ah
, AR9285_AN_RF2G9
),
498 AR9285_AN_RXTXBB1_SPARE9
)
500 REG_WRITE(ah
, AR9285_AN_RF2G6
, regVal
);
503 regVal
= (regVal
>> 20) & 0x7f;
505 /* Update PA cal info */
506 if ((!is_reset
) && (ah
->pacal_info
.prev_offset
== regVal
)) {
507 if (ah
->pacal_info
.max_skipcount
< MAX_PACAL_SKIPCOUNT
)
508 ah
->pacal_info
.max_skipcount
=
509 2 * ah
->pacal_info
.max_skipcount
;
510 ah
->pacal_info
.skipcount
= ah
->pacal_info
.max_skipcount
;
512 ah
->pacal_info
.max_skipcount
= 1;
513 ah
->pacal_info
.skipcount
= 0;
514 ah
->pacal_info
.prev_offset
= regVal
;
518 ENABLE_REG_RMW_BUFFER(ah
);
520 REG_SET_BIT(ah
, AR9285_AN_RF2G6
, 1 << 0);
522 REG_CLR_BIT(ah
, 0x9808, 1 << 27);
523 REG_RMW_BUFFER_FLUSH(ah
);
525 ENABLE_REGWRITE_BUFFER(ah
);
526 for (i
= 0; i
< ARRAY_SIZE(regList
); i
++)
527 REG_WRITE(ah
, regList
[i
][0], regList
[i
][1]);
529 REGWRITE_BUFFER_FLUSH(ah
);
532 static inline void ar9285_hw_pa_cal(struct ath_hw
*ah
, bool is_reset
)
534 struct ath_common
*common
= ath9k_hw_common(ah
);
536 int i
, offset
, offs_6_1
, offs_0
;
537 u32 ccomp_org
, reg_field
;
548 ath_dbg(common
, CALIBRATE
, "Running PA Calibration\n");
550 /* PA CAL is not needed for high power solution */
551 if (ah
->eep_ops
->get_eeprom(ah
, EEP_TXGAIN_TYPE
) ==
552 AR5416_EEP_TXGAIN_HIGH_POWER
)
555 for (i
= 0; i
< ARRAY_SIZE(regList
); i
++)
556 regList
[i
][1] = REG_READ(ah
, regList
[i
][0]);
558 regVal
= REG_READ(ah
, 0x7834);
560 REG_WRITE(ah
, 0x7834, regVal
);
561 regVal
= REG_READ(ah
, 0x9808);
562 regVal
|= (0x1 << 27);
563 REG_WRITE(ah
, 0x9808, regVal
);
565 REG_RMW_FIELD(ah
, AR9285_AN_TOP3
, AR9285_AN_TOP3_PWDDAC
, 1);
566 REG_RMW_FIELD(ah
, AR9285_AN_RXTXBB1
, AR9285_AN_RXTXBB1_PDRXTXBB1
, 1);
567 REG_RMW_FIELD(ah
, AR9285_AN_RXTXBB1
, AR9285_AN_RXTXBB1_PDV2I
, 1);
568 REG_RMW_FIELD(ah
, AR9285_AN_RXTXBB1
, AR9285_AN_RXTXBB1_PDDACIF
, 1);
569 REG_RMW_FIELD(ah
, AR9285_AN_RF2G2
, AR9285_AN_RF2G2_OFFCAL
, 0);
570 REG_RMW_FIELD(ah
, AR9285_AN_RF2G7
, AR9285_AN_RF2G7_PWDDB
, 0);
571 REG_RMW_FIELD(ah
, AR9285_AN_RF2G1
, AR9285_AN_RF2G1_ENPACAL
, 0);
572 REG_RMW_FIELD(ah
, AR9285_AN_RF2G1
, AR9285_AN_RF2G1_PDPADRV1
, 0);
573 REG_RMW_FIELD(ah
, AR9285_AN_RF2G1
, AR9285_AN_RF2G1_PDPADRV2
, 0);
574 REG_RMW_FIELD(ah
, AR9285_AN_RF2G1
, AR9285_AN_RF2G1_PDPAOUT
, 0);
575 REG_RMW_FIELD(ah
, AR9285_AN_RF2G8
, AR9285_AN_RF2G8_PADRVGN2TAB0
, 7);
576 REG_RMW_FIELD(ah
, AR9285_AN_RF2G7
, AR9285_AN_RF2G7_PADRVGN2TAB0
, 0);
577 ccomp_org
= MS(REG_READ(ah
, AR9285_AN_RF2G6
), AR9285_AN_RF2G6_CCOMP
);
578 REG_RMW_FIELD(ah
, AR9285_AN_RF2G6
, AR9285_AN_RF2G6_CCOMP
, 0xf);
580 REG_WRITE(ah
, AR9285_AN_TOP2
, 0xca0358a0);
582 REG_RMW_FIELD(ah
, AR9285_AN_RF2G6
, AR9285_AN_RF2G6_OFFS
, 0);
583 REG_RMW_FIELD(ah
, AR9285_AN_RF2G3
, AR9285_AN_RF2G3_PDVCCOMP
, 0);
585 for (i
= 6; i
> 0; i
--) {
586 regVal
= REG_READ(ah
, 0x7834);
587 regVal
|= (1 << (19 + i
));
588 REG_WRITE(ah
, 0x7834, regVal
);
590 regVal
= REG_READ(ah
, 0x7834);
591 regVal
&= (~(0x1 << (19 + i
)));
592 reg_field
= MS(REG_READ(ah
, 0x7840), AR9285_AN_RXTXBB1_SPARE9
);
593 regVal
|= (reg_field
<< (19 + i
));
594 REG_WRITE(ah
, 0x7834, regVal
);
597 REG_RMW_FIELD(ah
, AR9285_AN_RF2G3
, AR9285_AN_RF2G3_PDVCCOMP
, 1);
599 reg_field
= MS(REG_READ(ah
, AR9285_AN_RF2G9
), AR9285_AN_RXTXBB1_SPARE9
);
600 REG_RMW_FIELD(ah
, AR9285_AN_RF2G3
, AR9285_AN_RF2G3_PDVCCOMP
, reg_field
);
601 offs_6_1
= MS(REG_READ(ah
, AR9285_AN_RF2G6
), AR9285_AN_RF2G6_OFFS
);
602 offs_0
= MS(REG_READ(ah
, AR9285_AN_RF2G3
), AR9285_AN_RF2G3_PDVCCOMP
);
604 offset
= (offs_6_1
<<1) | offs_0
;
606 offs_6_1
= offset
>>1;
609 if ((!is_reset
) && (ah
->pacal_info
.prev_offset
== offset
)) {
610 if (ah
->pacal_info
.max_skipcount
< MAX_PACAL_SKIPCOUNT
)
611 ah
->pacal_info
.max_skipcount
=
612 2 * ah
->pacal_info
.max_skipcount
;
613 ah
->pacal_info
.skipcount
= ah
->pacal_info
.max_skipcount
;
615 ah
->pacal_info
.max_skipcount
= 1;
616 ah
->pacal_info
.skipcount
= 0;
617 ah
->pacal_info
.prev_offset
= offset
;
620 REG_RMW_FIELD(ah
, AR9285_AN_RF2G6
, AR9285_AN_RF2G6_OFFS
, offs_6_1
);
621 REG_RMW_FIELD(ah
, AR9285_AN_RF2G3
, AR9285_AN_RF2G3_PDVCCOMP
, offs_0
);
623 regVal
= REG_READ(ah
, 0x7834);
625 REG_WRITE(ah
, 0x7834, regVal
);
626 regVal
= REG_READ(ah
, 0x9808);
627 regVal
&= (~(0x1 << 27));
628 REG_WRITE(ah
, 0x9808, regVal
);
630 for (i
= 0; i
< ARRAY_SIZE(regList
); i
++)
631 REG_WRITE(ah
, regList
[i
][0], regList
[i
][1]);
633 REG_RMW_FIELD(ah
, AR9285_AN_RF2G6
, AR9285_AN_RF2G6_CCOMP
, ccomp_org
);
636 static void ar9002_hw_pa_cal(struct ath_hw
*ah
, bool is_reset
)
638 if (AR_SREV_9271(ah
)) {
639 if (is_reset
|| !ah
->pacal_info
.skipcount
)
640 ar9271_hw_pa_cal(ah
, is_reset
);
642 ah
->pacal_info
.skipcount
--;
643 } else if (AR_SREV_9285_12_OR_LATER(ah
)) {
644 if (is_reset
|| !ah
->pacal_info
.skipcount
)
645 ar9285_hw_pa_cal(ah
, is_reset
);
647 ah
->pacal_info
.skipcount
--;
651 static void ar9002_hw_olc_temp_compensation(struct ath_hw
*ah
)
653 if (OLC_FOR_AR9287_10_LATER
)
654 ar9287_hw_olc_temp_compensation(ah
);
655 else if (OLC_FOR_AR9280_20_LATER
)
656 ar9280_hw_olc_temp_compensation(ah
);
659 static int ar9002_hw_calibrate(struct ath_hw
*ah
, struct ath9k_channel
*chan
,
660 u8 rxchainmask
, bool longcal
)
662 struct ath9k_cal_list
*currCal
= ah
->cal_list_curr
;
663 bool nfcal
, nfcal_pending
= false, percal_pending
;
666 nfcal
= !!(REG_READ(ah
, AR_PHY_AGC_CONTROL
) & AR_PHY_AGC_CONTROL_NF
);
668 nfcal_pending
= test_bit(NFCAL_PENDING
, &ah
->caldata
->cal_flags
);
670 percal_pending
= (currCal
&&
671 (currCal
->calState
== CAL_RUNNING
||
672 currCal
->calState
== CAL_WAITING
));
674 if (percal_pending
&& !nfcal
) {
675 if (!ar9002_hw_per_calibration(ah
, chan
, rxchainmask
, currCal
))
678 ah
->cal_list_curr
= currCal
= currCal
->calNext
;
679 if (currCal
->calState
== CAL_WAITING
)
680 ath9k_hw_reset_calibration(ah
, currCal
);
685 /* Do NF cal only at longer intervals */
686 if (longcal
|| nfcal_pending
) {
688 * Get the value from the previous NF cal and update
691 if (ath9k_hw_getnf(ah
, chan
)) {
693 * Load the NF from history buffer of the current
695 * NF is slow time-variant, so it is OK to use a
698 ret
= ath9k_hw_loadnf(ah
, ah
->curchan
);
704 ath9k_hw_start_nfcal(ah
, false);
705 /* Do periodic PAOffset Cal */
706 ar9002_hw_pa_cal(ah
, false);
707 ar9002_hw_olc_temp_compensation(ah
);
711 return !percal_pending
;
714 /* Carrier leakage Calibration fix */
715 static bool ar9285_hw_cl_cal(struct ath_hw
*ah
, struct ath9k_channel
*chan
)
717 struct ath_common
*common
= ath9k_hw_common(ah
);
719 REG_SET_BIT(ah
, AR_PHY_CL_CAL_CTL
, AR_PHY_CL_CAL_ENABLE
);
720 if (IS_CHAN_HT20(chan
)) {
721 REG_SET_BIT(ah
, AR_PHY_CL_CAL_CTL
, AR_PHY_PARALLEL_CAL_ENABLE
);
722 REG_SET_BIT(ah
, AR_PHY_TURBO
, AR_PHY_FC_DYN2040_EN
);
723 REG_CLR_BIT(ah
, AR_PHY_AGC_CONTROL
,
724 AR_PHY_AGC_CONTROL_FLTR_CAL
);
725 REG_CLR_BIT(ah
, AR_PHY_TPCRG1
, AR_PHY_TPCRG1_PD_CAL_ENABLE
);
726 REG_SET_BIT(ah
, AR_PHY_AGC_CONTROL
, AR_PHY_AGC_CONTROL_CAL
);
727 if (!ath9k_hw_wait(ah
, AR_PHY_AGC_CONTROL
,
728 AR_PHY_AGC_CONTROL_CAL
, 0, AH_WAIT_TIMEOUT
)) {
729 ath_dbg(common
, CALIBRATE
,
730 "offset calibration failed to complete in %d ms; noisy environment?\n",
731 AH_WAIT_TIMEOUT
/ 1000);
734 REG_CLR_BIT(ah
, AR_PHY_TURBO
, AR_PHY_FC_DYN2040_EN
);
735 REG_CLR_BIT(ah
, AR_PHY_CL_CAL_CTL
, AR_PHY_PARALLEL_CAL_ENABLE
);
736 REG_CLR_BIT(ah
, AR_PHY_CL_CAL_CTL
, AR_PHY_CL_CAL_ENABLE
);
738 REG_CLR_BIT(ah
, AR_PHY_ADC_CTL
, AR_PHY_ADC_CTL_OFF_PWDADC
);
739 REG_SET_BIT(ah
, AR_PHY_AGC_CONTROL
, AR_PHY_AGC_CONTROL_FLTR_CAL
);
740 REG_SET_BIT(ah
, AR_PHY_TPCRG1
, AR_PHY_TPCRG1_PD_CAL_ENABLE
);
741 REG_SET_BIT(ah
, AR_PHY_AGC_CONTROL
, AR_PHY_AGC_CONTROL_CAL
);
742 if (!ath9k_hw_wait(ah
, AR_PHY_AGC_CONTROL
, AR_PHY_AGC_CONTROL_CAL
,
743 0, AH_WAIT_TIMEOUT
)) {
744 ath_dbg(common
, CALIBRATE
,
745 "offset calibration failed to complete in %d ms; noisy environment?\n",
746 AH_WAIT_TIMEOUT
/ 1000);
750 REG_SET_BIT(ah
, AR_PHY_ADC_CTL
, AR_PHY_ADC_CTL_OFF_PWDADC
);
751 REG_CLR_BIT(ah
, AR_PHY_CL_CAL_CTL
, AR_PHY_CL_CAL_ENABLE
);
752 REG_CLR_BIT(ah
, AR_PHY_AGC_CONTROL
, AR_PHY_AGC_CONTROL_FLTR_CAL
);
757 static bool ar9285_hw_clc(struct ath_hw
*ah
, struct ath9k_channel
*chan
)
760 u_int32_t txgain_max
;
761 u_int32_t clc_gain
, gain_mask
= 0, clc_num
= 0;
762 u_int32_t reg_clc_I0
, reg_clc_Q0
;
763 u_int32_t i0_num
= 0;
764 u_int32_t q0_num
= 0;
765 u_int32_t total_num
= 0;
766 u_int32_t reg_rf2g5_org
;
769 if (!(ar9285_hw_cl_cal(ah
, chan
)))
772 txgain_max
= MS(REG_READ(ah
, AR_PHY_TX_PWRCTRL7
),
773 AR_PHY_TX_PWRCTRL_TX_GAIN_TAB_MAX
);
775 for (i
= 0; i
< (txgain_max
+1); i
++) {
776 clc_gain
= (REG_READ(ah
, (AR_PHY_TX_GAIN_TBL1
+(i
<<2))) &
777 AR_PHY_TX_GAIN_CLC
) >> AR_PHY_TX_GAIN_CLC_S
;
778 if (!(gain_mask
& (1 << clc_gain
))) {
779 gain_mask
|= (1 << clc_gain
);
784 for (i
= 0; i
< clc_num
; i
++) {
785 reg_clc_I0
= (REG_READ(ah
, (AR_PHY_CLC_TBL1
+ (i
<< 2)))
786 & AR_PHY_CLC_I0
) >> AR_PHY_CLC_I0_S
;
787 reg_clc_Q0
= (REG_READ(ah
, (AR_PHY_CLC_TBL1
+ (i
<< 2)))
788 & AR_PHY_CLC_Q0
) >> AR_PHY_CLC_Q0_S
;
795 total_num
= i0_num
+ q0_num
;
796 if (total_num
> AR9285_CLCAL_REDO_THRESH
) {
797 reg_rf2g5_org
= REG_READ(ah
, AR9285_RF2G5
);
798 if (AR_SREV_9285E_20(ah
)) {
799 REG_WRITE(ah
, AR9285_RF2G5
,
800 (reg_rf2g5_org
& AR9285_RF2G5_IC50TX
) |
801 AR9285_RF2G5_IC50TX_XE_SET
);
803 REG_WRITE(ah
, AR9285_RF2G5
,
804 (reg_rf2g5_org
& AR9285_RF2G5_IC50TX
) |
805 AR9285_RF2G5_IC50TX_SET
);
807 retv
= ar9285_hw_cl_cal(ah
, chan
);
808 REG_WRITE(ah
, AR9285_RF2G5
, reg_rf2g5_org
);
813 static bool ar9002_hw_init_cal(struct ath_hw
*ah
, struct ath9k_channel
*chan
)
815 struct ath_common
*common
= ath9k_hw_common(ah
);
817 if (AR_SREV_9271(ah
)) {
818 if (!ar9285_hw_cl_cal(ah
, chan
))
820 } else if (AR_SREV_9285(ah
) && AR_SREV_9285_12_OR_LATER(ah
)) {
821 if (!ar9285_hw_clc(ah
, chan
))
824 if (AR_SREV_9280_20_OR_LATER(ah
)) {
825 if (!AR_SREV_9287_11_OR_LATER(ah
))
826 REG_CLR_BIT(ah
, AR_PHY_ADC_CTL
,
827 AR_PHY_ADC_CTL_OFF_PWDADC
);
828 REG_SET_BIT(ah
, AR_PHY_AGC_CONTROL
,
829 AR_PHY_AGC_CONTROL_FLTR_CAL
);
832 /* Calibrate the AGC */
833 REG_WRITE(ah
, AR_PHY_AGC_CONTROL
,
834 REG_READ(ah
, AR_PHY_AGC_CONTROL
) |
835 AR_PHY_AGC_CONTROL_CAL
);
837 /* Poll for offset calibration complete */
838 if (!ath9k_hw_wait(ah
, AR_PHY_AGC_CONTROL
,
839 AR_PHY_AGC_CONTROL_CAL
,
840 0, AH_WAIT_TIMEOUT
)) {
841 ath_dbg(common
, CALIBRATE
,
842 "offset calibration failed to complete in %d ms; noisy environment?\n",
843 AH_WAIT_TIMEOUT
/ 1000);
847 if (AR_SREV_9280_20_OR_LATER(ah
)) {
848 if (!AR_SREV_9287_11_OR_LATER(ah
))
849 REG_SET_BIT(ah
, AR_PHY_ADC_CTL
,
850 AR_PHY_ADC_CTL_OFF_PWDADC
);
851 REG_CLR_BIT(ah
, AR_PHY_AGC_CONTROL
,
852 AR_PHY_AGC_CONTROL_FLTR_CAL
);
856 /* Do PA Calibration */
857 ar9002_hw_pa_cal(ah
, true);
858 ath9k_hw_loadnf(ah
, chan
);
859 ath9k_hw_start_nfcal(ah
, true);
862 set_bit(NFCAL_PENDING
, &ah
->caldata
->cal_flags
);
864 ah
->cal_list
= ah
->cal_list_last
= ah
->cal_list_curr
= NULL
;
866 /* Enable IQ, ADC Gain and ADC DC offset CALs */
867 if (AR_SREV_9100(ah
) || AR_SREV_9160_10_OR_LATER(ah
)) {
868 ah
->supp_cals
= IQ_MISMATCH_CAL
;
870 if (AR_SREV_9160_10_OR_LATER(ah
))
871 ah
->supp_cals
|= ADC_GAIN_CAL
| ADC_DC_CAL
;
873 if (AR_SREV_9287(ah
))
874 ah
->supp_cals
&= ~ADC_GAIN_CAL
;
876 if (ar9002_hw_is_cal_supported(ah
, chan
, ADC_GAIN_CAL
)) {
877 INIT_CAL(&ah
->adcgain_caldata
);
878 INSERT_CAL(ah
, &ah
->adcgain_caldata
);
879 ath_dbg(common
, CALIBRATE
,
880 "enabling ADC Gain Calibration\n");
883 if (ar9002_hw_is_cal_supported(ah
, chan
, ADC_DC_CAL
)) {
884 INIT_CAL(&ah
->adcdc_caldata
);
885 INSERT_CAL(ah
, &ah
->adcdc_caldata
);
886 ath_dbg(common
, CALIBRATE
,
887 "enabling ADC DC Calibration\n");
890 if (ar9002_hw_is_cal_supported(ah
, chan
, IQ_MISMATCH_CAL
)) {
891 INIT_CAL(&ah
->iq_caldata
);
892 INSERT_CAL(ah
, &ah
->iq_caldata
);
893 ath_dbg(common
, CALIBRATE
, "enabling IQ Calibration\n");
896 ah
->cal_list_curr
= ah
->cal_list
;
898 if (ah
->cal_list_curr
)
899 ath9k_hw_reset_calibration(ah
, ah
->cal_list_curr
);
903 ah
->caldata
->CalValid
= 0;
908 static const struct ath9k_percal_data iq_cal_multi_sample
= {
912 ar9002_hw_iqcal_collect
,
913 ar9002_hw_iqcalibrate
915 static const struct ath9k_percal_data iq_cal_single_sample
= {
919 ar9002_hw_iqcal_collect
,
920 ar9002_hw_iqcalibrate
922 static const struct ath9k_percal_data adc_gain_cal_multi_sample
= {
926 ar9002_hw_adc_gaincal_collect
,
927 ar9002_hw_adc_gaincal_calibrate
929 static const struct ath9k_percal_data adc_gain_cal_single_sample
= {
933 ar9002_hw_adc_gaincal_collect
,
934 ar9002_hw_adc_gaincal_calibrate
936 static const struct ath9k_percal_data adc_dc_cal_multi_sample
= {
940 ar9002_hw_adc_dccal_collect
,
941 ar9002_hw_adc_dccal_calibrate
943 static const struct ath9k_percal_data adc_dc_cal_single_sample
= {
947 ar9002_hw_adc_dccal_collect
,
948 ar9002_hw_adc_dccal_calibrate
951 static void ar9002_hw_init_cal_settings(struct ath_hw
*ah
)
953 if (AR_SREV_9100(ah
)) {
954 ah
->iq_caldata
.calData
= &iq_cal_multi_sample
;
955 ah
->supp_cals
= IQ_MISMATCH_CAL
;
959 if (AR_SREV_9160_10_OR_LATER(ah
)) {
960 if (AR_SREV_9280_20_OR_LATER(ah
)) {
961 ah
->iq_caldata
.calData
= &iq_cal_single_sample
;
962 ah
->adcgain_caldata
.calData
=
963 &adc_gain_cal_single_sample
;
964 ah
->adcdc_caldata
.calData
=
965 &adc_dc_cal_single_sample
;
967 ah
->iq_caldata
.calData
= &iq_cal_multi_sample
;
968 ah
->adcgain_caldata
.calData
=
969 &adc_gain_cal_multi_sample
;
970 ah
->adcdc_caldata
.calData
=
971 &adc_dc_cal_multi_sample
;
973 ah
->supp_cals
= ADC_GAIN_CAL
| ADC_DC_CAL
| IQ_MISMATCH_CAL
;
975 if (AR_SREV_9287(ah
))
976 ah
->supp_cals
&= ~ADC_GAIN_CAL
;
980 void ar9002_hw_attach_calib_ops(struct ath_hw
*ah
)
982 struct ath_hw_private_ops
*priv_ops
= ath9k_hw_private_ops(ah
);
983 struct ath_hw_ops
*ops
= ath9k_hw_ops(ah
);
985 priv_ops
->init_cal_settings
= ar9002_hw_init_cal_settings
;
986 priv_ops
->init_cal
= ar9002_hw_init_cal
;
987 priv_ops
->setup_calibration
= ar9002_hw_setup_calibration
;
989 ops
->calibrate
= ar9002_hw_calibrate
;