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
22 /* AGC & I/Q calibrations time limit, ms */
23 #define AR9002_CAL_MAX_TIME 30000
25 enum ar9002_cal_types
{
26 ADC_GAIN_CAL
= BIT(0),
28 IQ_MISMATCH_CAL
= BIT(2),
31 static bool ar9002_hw_is_cal_supported(struct ath_hw
*ah
,
32 struct ath9k_channel
*chan
,
33 enum ar9002_cal_types cal_type
)
35 bool supported
= false;
36 switch (ah
->supp_cals
& cal_type
) {
42 /* Run even/odd ADCs calibrations for HT40 channels only */
43 if (IS_CHAN_HT40(chan
))
50 static void ar9002_hw_setup_calibration(struct ath_hw
*ah
,
51 struct ath9k_cal_list
*currCal
)
53 struct ath_common
*common
= ath9k_hw_common(ah
);
55 REG_RMW_FIELD(ah
, AR_PHY_TIMING_CTRL4(0),
56 AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX
,
57 currCal
->calData
->calCountMax
);
59 switch (currCal
->calData
->calType
) {
61 REG_WRITE(ah
, AR_PHY_CALMODE
, AR_PHY_CALMODE_IQ
);
62 ath_dbg(common
, CALIBRATE
,
63 "starting IQ Mismatch Calibration\n");
66 REG_WRITE(ah
, AR_PHY_CALMODE
, AR_PHY_CALMODE_ADC_GAIN
);
67 ath_dbg(common
, CALIBRATE
, "starting ADC Gain Calibration\n");
70 REG_WRITE(ah
, AR_PHY_CALMODE
, AR_PHY_CALMODE_ADC_DC_PER
);
71 ath_dbg(common
, CALIBRATE
, "starting ADC DC Calibration\n");
75 REG_SET_BIT(ah
, AR_PHY_TIMING_CTRL4(0),
76 AR_PHY_TIMING_CTRL4_DO_CAL
);
79 static bool ar9002_hw_per_calibration(struct ath_hw
*ah
,
80 struct ath9k_channel
*ichan
,
82 struct ath9k_cal_list
*currCal
)
84 struct ath9k_hw_cal_data
*caldata
= ah
->caldata
;
85 bool iscaldone
= false;
87 if (currCal
->calState
== CAL_RUNNING
) {
88 if (!(REG_READ(ah
, AR_PHY_TIMING_CTRL4(0)) &
89 AR_PHY_TIMING_CTRL4_DO_CAL
)) {
91 currCal
->calData
->calCollect(ah
);
94 if (ah
->cal_samples
>=
95 currCal
->calData
->calNumSamples
) {
97 for (i
= 0; i
< AR5416_MAX_CHAINS
; i
++) {
98 if (rxchainmask
& (1 << i
))
102 currCal
->calData
->calPostProc(ah
, numChains
);
103 caldata
->CalValid
|= currCal
->calData
->calType
;
104 currCal
->calState
= CAL_DONE
;
107 ar9002_hw_setup_calibration(ah
, currCal
);
109 } else if (time_after(jiffies
, ah
->cal_start_time
+
110 msecs_to_jiffies(AR9002_CAL_MAX_TIME
))) {
111 REG_CLR_BIT(ah
, AR_PHY_TIMING_CTRL4(0),
112 AR_PHY_TIMING_CTRL4_DO_CAL
);
113 ath_dbg(ath9k_hw_common(ah
), CALIBRATE
,
114 "calibration timeout\n");
115 currCal
->calState
= CAL_WAITING
; /* Try later */
118 } else if (!(caldata
->CalValid
& currCal
->calData
->calType
)) {
119 ath9k_hw_reset_calibration(ah
, currCal
);
125 static void ar9002_hw_iqcal_collect(struct ath_hw
*ah
)
129 for (i
= 0; i
< AR5416_MAX_CHAINS
; i
++) {
130 ah
->totalPowerMeasI
[i
] +=
131 REG_READ(ah
, AR_PHY_CAL_MEAS_0(i
));
132 ah
->totalPowerMeasQ
[i
] +=
133 REG_READ(ah
, AR_PHY_CAL_MEAS_1(i
));
134 ah
->totalIqCorrMeas
[i
] +=
135 (int32_t) REG_READ(ah
, AR_PHY_CAL_MEAS_2(i
));
136 ath_dbg(ath9k_hw_common(ah
), CALIBRATE
,
137 "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
138 ah
->cal_samples
, i
, ah
->totalPowerMeasI
[i
],
139 ah
->totalPowerMeasQ
[i
],
140 ah
->totalIqCorrMeas
[i
]);
144 static void ar9002_hw_adc_gaincal_collect(struct ath_hw
*ah
)
148 for (i
= 0; i
< AR5416_MAX_CHAINS
; i
++) {
149 ah
->totalAdcIOddPhase
[i
] +=
150 REG_READ(ah
, AR_PHY_CAL_MEAS_0(i
));
151 ah
->totalAdcIEvenPhase
[i
] +=
152 REG_READ(ah
, AR_PHY_CAL_MEAS_1(i
));
153 ah
->totalAdcQOddPhase
[i
] +=
154 REG_READ(ah
, AR_PHY_CAL_MEAS_2(i
));
155 ah
->totalAdcQEvenPhase
[i
] +=
156 REG_READ(ah
, AR_PHY_CAL_MEAS_3(i
));
158 ath_dbg(ath9k_hw_common(ah
), CALIBRATE
,
159 "%d: Chn %d oddi=0x%08x; eveni=0x%08x; oddq=0x%08x; evenq=0x%08x;\n",
161 ah
->totalAdcIOddPhase
[i
],
162 ah
->totalAdcIEvenPhase
[i
],
163 ah
->totalAdcQOddPhase
[i
],
164 ah
->totalAdcQEvenPhase
[i
]);
168 static void ar9002_hw_adc_dccal_collect(struct ath_hw
*ah
)
172 for (i
= 0; i
< AR5416_MAX_CHAINS
; i
++) {
173 ah
->totalAdcDcOffsetIOddPhase
[i
] +=
174 (int32_t) REG_READ(ah
, AR_PHY_CAL_MEAS_0(i
));
175 ah
->totalAdcDcOffsetIEvenPhase
[i
] +=
176 (int32_t) REG_READ(ah
, AR_PHY_CAL_MEAS_1(i
));
177 ah
->totalAdcDcOffsetQOddPhase
[i
] +=
178 (int32_t) REG_READ(ah
, AR_PHY_CAL_MEAS_2(i
));
179 ah
->totalAdcDcOffsetQEvenPhase
[i
] +=
180 (int32_t) REG_READ(ah
, AR_PHY_CAL_MEAS_3(i
));
182 ath_dbg(ath9k_hw_common(ah
), CALIBRATE
,
183 "%d: Chn %d oddi=0x%08x; eveni=0x%08x; oddq=0x%08x; evenq=0x%08x;\n",
185 ah
->totalAdcDcOffsetIOddPhase
[i
],
186 ah
->totalAdcDcOffsetIEvenPhase
[i
],
187 ah
->totalAdcDcOffsetQOddPhase
[i
],
188 ah
->totalAdcDcOffsetQEvenPhase
[i
]);
192 static void ar9002_hw_iqcalibrate(struct ath_hw
*ah
, u8 numChains
)
194 struct ath_common
*common
= ath9k_hw_common(ah
);
195 u32 powerMeasQ
, powerMeasI
, iqCorrMeas
;
196 u32 qCoffDenom
, iCoffDenom
;
197 int32_t qCoff
, iCoff
;
200 for (i
= 0; i
< numChains
; i
++) {
201 powerMeasI
= ah
->totalPowerMeasI
[i
];
202 powerMeasQ
= ah
->totalPowerMeasQ
[i
];
203 iqCorrMeas
= ah
->totalIqCorrMeas
[i
];
205 ath_dbg(common
, CALIBRATE
,
206 "Starting IQ Cal and Correction for Chain %d\n",
209 ath_dbg(common
, CALIBRATE
,
210 "Original: Chn %d iq_corr_meas = 0x%08x\n",
211 i
, ah
->totalIqCorrMeas
[i
]);
215 if (iqCorrMeas
> 0x80000000) {
216 iqCorrMeas
= (0xffffffff - iqCorrMeas
) + 1;
220 ath_dbg(common
, CALIBRATE
, "Chn %d pwr_meas_i = 0x%08x\n",
222 ath_dbg(common
, CALIBRATE
, "Chn %d pwr_meas_q = 0x%08x\n",
224 ath_dbg(common
, CALIBRATE
, "iqCorrNeg is 0x%08x\n", iqCorrNeg
);
226 iCoffDenom
= (powerMeasI
/ 2 + powerMeasQ
/ 2) / 128;
227 qCoffDenom
= powerMeasQ
/ 64;
229 if ((powerMeasQ
!= 0) && (iCoffDenom
!= 0) &&
231 iCoff
= iqCorrMeas
/ iCoffDenom
;
232 qCoff
= powerMeasI
/ qCoffDenom
- 64;
233 ath_dbg(common
, CALIBRATE
, "Chn %d iCoff = 0x%08x\n",
235 ath_dbg(common
, CALIBRATE
, "Chn %d qCoff = 0x%08x\n",
238 iCoff
= iCoff
& 0x3f;
239 ath_dbg(common
, CALIBRATE
,
240 "New: Chn %d iCoff = 0x%08x\n", i
, iCoff
);
241 if (iqCorrNeg
== 0x0)
242 iCoff
= 0x40 - iCoff
;
246 else if (qCoff
<= -16)
249 ath_dbg(common
, CALIBRATE
,
250 "Chn %d : iCoff = 0x%x qCoff = 0x%x\n",
253 REG_RMW_FIELD(ah
, AR_PHY_TIMING_CTRL4(i
),
254 AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF
,
256 REG_RMW_FIELD(ah
, AR_PHY_TIMING_CTRL4(i
),
257 AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF
,
259 ath_dbg(common
, CALIBRATE
,
260 "IQ Cal and Correction done for Chain %d\n",
265 REG_SET_BIT(ah
, AR_PHY_TIMING_CTRL4(0),
266 AR_PHY_TIMING_CTRL4_IQCORR_ENABLE
);
269 static void ar9002_hw_adc_gaincal_calibrate(struct ath_hw
*ah
, u8 numChains
)
271 struct ath_common
*common
= ath9k_hw_common(ah
);
272 u32 iOddMeasOffset
, iEvenMeasOffset
, qOddMeasOffset
, qEvenMeasOffset
;
273 u32 qGainMismatch
, iGainMismatch
, val
, i
;
275 for (i
= 0; i
< numChains
; i
++) {
276 iOddMeasOffset
= ah
->totalAdcIOddPhase
[i
];
277 iEvenMeasOffset
= ah
->totalAdcIEvenPhase
[i
];
278 qOddMeasOffset
= ah
->totalAdcQOddPhase
[i
];
279 qEvenMeasOffset
= ah
->totalAdcQEvenPhase
[i
];
281 ath_dbg(common
, CALIBRATE
,
282 "Starting ADC Gain Cal for Chain %d\n", i
);
284 ath_dbg(common
, CALIBRATE
, "Chn %d pwr_meas_odd_i = 0x%08x\n",
286 ath_dbg(common
, CALIBRATE
, "Chn %d pwr_meas_even_i = 0x%08x\n",
288 ath_dbg(common
, CALIBRATE
, "Chn %d pwr_meas_odd_q = 0x%08x\n",
290 ath_dbg(common
, CALIBRATE
, "Chn %d pwr_meas_even_q = 0x%08x\n",
293 if (iOddMeasOffset
!= 0 && qEvenMeasOffset
!= 0) {
295 ((iEvenMeasOffset
* 32) /
296 iOddMeasOffset
) & 0x3f;
298 ((qOddMeasOffset
* 32) /
299 qEvenMeasOffset
) & 0x3f;
301 ath_dbg(common
, CALIBRATE
,
302 "Chn %d gain_mismatch_i = 0x%08x\n",
304 ath_dbg(common
, CALIBRATE
,
305 "Chn %d gain_mismatch_q = 0x%08x\n",
308 val
= REG_READ(ah
, AR_PHY_NEW_ADC_DC_GAIN_CORR(i
));
310 val
|= (qGainMismatch
) | (iGainMismatch
<< 6);
311 REG_WRITE(ah
, AR_PHY_NEW_ADC_DC_GAIN_CORR(i
), val
);
313 ath_dbg(common
, CALIBRATE
,
314 "ADC Gain Cal done for Chain %d\n", i
);
318 REG_WRITE(ah
, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
319 REG_READ(ah
, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
320 AR_PHY_NEW_ADC_GAIN_CORR_ENABLE
);
323 static void ar9002_hw_adc_dccal_calibrate(struct ath_hw
*ah
, u8 numChains
)
325 struct ath_common
*common
= ath9k_hw_common(ah
);
326 u32 iOddMeasOffset
, iEvenMeasOffset
, val
, i
;
327 int32_t qOddMeasOffset
, qEvenMeasOffset
, qDcMismatch
, iDcMismatch
;
328 const struct ath9k_percal_data
*calData
=
329 ah
->cal_list_curr
->calData
;
331 (1 << (calData
->calCountMax
+ 5)) * calData
->calNumSamples
;
333 for (i
= 0; i
< numChains
; i
++) {
334 iOddMeasOffset
= ah
->totalAdcDcOffsetIOddPhase
[i
];
335 iEvenMeasOffset
= ah
->totalAdcDcOffsetIEvenPhase
[i
];
336 qOddMeasOffset
= ah
->totalAdcDcOffsetQOddPhase
[i
];
337 qEvenMeasOffset
= ah
->totalAdcDcOffsetQEvenPhase
[i
];
339 ath_dbg(common
, CALIBRATE
,
340 "Starting ADC DC Offset Cal for Chain %d\n", i
);
342 ath_dbg(common
, CALIBRATE
, "Chn %d pwr_meas_odd_i = %d\n",
344 ath_dbg(common
, CALIBRATE
, "Chn %d pwr_meas_even_i = %d\n",
346 ath_dbg(common
, CALIBRATE
, "Chn %d pwr_meas_odd_q = %d\n",
348 ath_dbg(common
, CALIBRATE
, "Chn %d pwr_meas_even_q = %d\n",
351 iDcMismatch
= (((iEvenMeasOffset
- iOddMeasOffset
) * 2) /
353 qDcMismatch
= (((qOddMeasOffset
- qEvenMeasOffset
) * 2) /
356 ath_dbg(common
, CALIBRATE
,
357 "Chn %d dc_offset_mismatch_i = 0x%08x\n",
359 ath_dbg(common
, CALIBRATE
,
360 "Chn %d dc_offset_mismatch_q = 0x%08x\n",
363 val
= REG_READ(ah
, AR_PHY_NEW_ADC_DC_GAIN_CORR(i
));
365 val
|= (qDcMismatch
<< 12) | (iDcMismatch
<< 21);
366 REG_WRITE(ah
, AR_PHY_NEW_ADC_DC_GAIN_CORR(i
), val
);
368 ath_dbg(common
, CALIBRATE
,
369 "ADC DC Offset Cal done for Chain %d\n", i
);
372 REG_WRITE(ah
, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
373 REG_READ(ah
, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
374 AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE
);
377 static void ar9287_hw_olc_temp_compensation(struct ath_hw
*ah
)
380 int32_t delta
, currPDADC
, slope
;
382 rddata
= REG_READ(ah
, AR_PHY_TX_PWRCTRL4
);
383 currPDADC
= MS(rddata
, AR_PHY_TX_PWRCTRL_PD_AVG_OUT
);
385 if (ah
->initPDADC
== 0 || currPDADC
== 0) {
387 * Zero value indicates that no frames have been transmitted
388 * yet, can't do temperature compensation until frames are
393 slope
= ah
->eep_ops
->get_eeprom(ah
, EEP_TEMPSENSE_SLOPE
);
395 if (slope
== 0) { /* to avoid divide by zero case */
398 delta
= ((currPDADC
- ah
->initPDADC
)*4) / slope
;
400 REG_RMW_FIELD(ah
, AR_PHY_CH0_TX_PWRCTRL11
,
401 AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP
, delta
);
402 REG_RMW_FIELD(ah
, AR_PHY_CH1_TX_PWRCTRL11
,
403 AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP
, delta
);
407 static void ar9280_hw_olc_temp_compensation(struct ath_hw
*ah
)
410 int delta
, currPDADC
, regval
;
412 rddata
= REG_READ(ah
, AR_PHY_TX_PWRCTRL4
);
413 currPDADC
= MS(rddata
, AR_PHY_TX_PWRCTRL_PD_AVG_OUT
);
415 if (ah
->initPDADC
== 0 || currPDADC
== 0)
418 if (ah
->eep_ops
->get_eeprom(ah
, EEP_DAC_HPWR_5G
))
419 delta
= (currPDADC
- ah
->initPDADC
+ 4) / 8;
421 delta
= (currPDADC
- ah
->initPDADC
+ 5) / 10;
423 if (delta
!= ah
->PDADCdelta
) {
424 ah
->PDADCdelta
= delta
;
425 for (i
= 1; i
< AR9280_TX_GAIN_TABLE_SIZE
; i
++) {
426 regval
= ah
->originalGain
[i
] - delta
;
431 AR_PHY_TX_GAIN_TBL1
+ i
* 4,
432 AR_PHY_TX_GAIN
, regval
);
437 static void ar9271_hw_pa_cal(struct ath_hw
*ah
, bool is_reset
)
442 { AR9285_AN_TOP3
, 0 },
443 { AR9285_AN_RXTXBB1
, 0 },
444 { AR9285_AN_RF2G1
, 0 },
445 { AR9285_AN_RF2G2
, 0 },
446 { AR9285_AN_TOP2
, 0 },
447 { AR9285_AN_RF2G8
, 0 },
448 { AR9285_AN_RF2G7
, 0 },
449 { AR9285_AN_RF2G3
, 0 },
452 REG_READ_ARRAY(ah
, regList
, ARRAY_SIZE(regList
));
454 ENABLE_REG_RMW_BUFFER(ah
);
456 REG_CLR_BIT(ah
, AR9285_AN_RF2G6
, 1 << 0);
458 REG_SET_BIT(ah
, 0x9808, 1 << 27);
459 /* 786c,b23,1, pwddac=1 */
460 REG_SET_BIT(ah
, AR9285_AN_TOP3
, AR9285_AN_TOP3_PWDDAC
);
461 /* 7854, b5,1, pdrxtxbb=1 */
462 REG_SET_BIT(ah
, AR9285_AN_RXTXBB1
, AR9285_AN_RXTXBB1_PDRXTXBB1
);
463 /* 7854, b7,1, pdv2i=1 */
464 REG_SET_BIT(ah
, AR9285_AN_RXTXBB1
, AR9285_AN_RXTXBB1_PDV2I
);
465 /* 7854, b8,1, pddacinterface=1 */
466 REG_SET_BIT(ah
, AR9285_AN_RXTXBB1
, AR9285_AN_RXTXBB1_PDDACIF
);
467 /* 7824,b12,0, offcal=0 */
468 REG_CLR_BIT(ah
, AR9285_AN_RF2G2
, AR9285_AN_RF2G2_OFFCAL
);
469 /* 7838, b1,0, pwddb=0 */
470 REG_CLR_BIT(ah
, AR9285_AN_RF2G7
, AR9285_AN_RF2G7_PWDDB
);
471 /* 7820,b11,0, enpacal=0 */
472 REG_CLR_BIT(ah
, AR9285_AN_RF2G1
, AR9285_AN_RF2G1_ENPACAL
);
473 /* 7820,b25,1, pdpadrv1=0 */
474 REG_CLR_BIT(ah
, AR9285_AN_RF2G1
, AR9285_AN_RF2G1_PDPADRV1
);
475 /* 7820,b24,0, pdpadrv2=0 */
476 REG_CLR_BIT(ah
, AR9285_AN_RF2G1
, AR9285_AN_RF2G1_PDPADRV2
);
477 /* 7820,b23,0, pdpaout=0 */
478 REG_CLR_BIT(ah
, AR9285_AN_RF2G1
, AR9285_AN_RF2G1_PDPAOUT
);
479 /* 783c,b14-16,7, padrvgn2tab_0=7 */
480 REG_RMW_FIELD(ah
, AR9285_AN_RF2G8
, AR9285_AN_RF2G8_PADRVGN2TAB0
, 7);
482 * 7838,b29-31,0, padrvgn1tab_0=0
483 * does not matter since we turn it off
485 REG_RMW_FIELD(ah
, AR9285_AN_RF2G7
, AR9285_AN_RF2G7_PADRVGN2TAB0
, 0);
486 /* 7828, b0-11, ccom=fff */
487 REG_RMW_FIELD(ah
, AR9285_AN_RF2G3
, AR9271_AN_RF2G3_CCOMP
, 0xfff);
488 REG_RMW_BUFFER_FLUSH(ah
);
491 * localmode=1,bmode=1,bmoderxtx=1,synthon=1,
492 * txon=1,paon=1,oscon=1,synthon_force=1
494 REG_WRITE(ah
, AR9285_AN_TOP2
, 0xca0358a0);
496 REG_RMW_FIELD(ah
, AR9285_AN_RF2G6
, AR9271_AN_RF2G6_OFFS
, 0);
499 for (i
= 6; i
> 0; i
--) {
500 regVal
= REG_READ(ah
, AR9285_AN_RF2G6
);
501 regVal
|= (1 << (20 + i
));
502 REG_WRITE(ah
, AR9285_AN_RF2G6
, regVal
);
504 /* regVal = REG_READ(ah, 0x7834); */
505 regVal
&= (~(0x1 << (20 + i
)));
506 regVal
|= (MS(REG_READ(ah
, AR9285_AN_RF2G9
),
507 AR9285_AN_RXTXBB1_SPARE9
)
509 REG_WRITE(ah
, AR9285_AN_RF2G6
, regVal
);
512 regVal
= (regVal
>> 20) & 0x7f;
514 /* Update PA cal info */
515 if ((!is_reset
) && (ah
->pacal_info
.prev_offset
== regVal
)) {
516 if (ah
->pacal_info
.max_skipcount
< MAX_PACAL_SKIPCOUNT
)
517 ah
->pacal_info
.max_skipcount
=
518 2 * ah
->pacal_info
.max_skipcount
;
519 ah
->pacal_info
.skipcount
= ah
->pacal_info
.max_skipcount
;
521 ah
->pacal_info
.max_skipcount
= 1;
522 ah
->pacal_info
.skipcount
= 0;
523 ah
->pacal_info
.prev_offset
= regVal
;
527 ENABLE_REG_RMW_BUFFER(ah
);
529 REG_SET_BIT(ah
, AR9285_AN_RF2G6
, 1 << 0);
531 REG_CLR_BIT(ah
, 0x9808, 1 << 27);
532 REG_RMW_BUFFER_FLUSH(ah
);
534 ENABLE_REGWRITE_BUFFER(ah
);
535 for (i
= 0; i
< ARRAY_SIZE(regList
); i
++)
536 REG_WRITE(ah
, regList
[i
][0], regList
[i
][1]);
538 REGWRITE_BUFFER_FLUSH(ah
);
541 static inline void ar9285_hw_pa_cal(struct ath_hw
*ah
, bool is_reset
)
543 struct ath_common
*common
= ath9k_hw_common(ah
);
545 int i
, offset
, offs_6_1
, offs_0
;
546 u32 ccomp_org
, reg_field
;
557 ath_dbg(common
, CALIBRATE
, "Running PA Calibration\n");
559 /* PA CAL is not needed for high power solution */
560 if (ah
->eep_ops
->get_eeprom(ah
, EEP_TXGAIN_TYPE
) ==
561 AR5416_EEP_TXGAIN_HIGH_POWER
)
564 for (i
= 0; i
< ARRAY_SIZE(regList
); i
++)
565 regList
[i
][1] = REG_READ(ah
, regList
[i
][0]);
567 regVal
= REG_READ(ah
, 0x7834);
569 REG_WRITE(ah
, 0x7834, regVal
);
570 regVal
= REG_READ(ah
, 0x9808);
571 regVal
|= (0x1 << 27);
572 REG_WRITE(ah
, 0x9808, regVal
);
574 REG_RMW_FIELD(ah
, AR9285_AN_TOP3
, AR9285_AN_TOP3_PWDDAC
, 1);
575 REG_RMW_FIELD(ah
, AR9285_AN_RXTXBB1
, AR9285_AN_RXTXBB1_PDRXTXBB1
, 1);
576 REG_RMW_FIELD(ah
, AR9285_AN_RXTXBB1
, AR9285_AN_RXTXBB1_PDV2I
, 1);
577 REG_RMW_FIELD(ah
, AR9285_AN_RXTXBB1
, AR9285_AN_RXTXBB1_PDDACIF
, 1);
578 REG_RMW_FIELD(ah
, AR9285_AN_RF2G2
, AR9285_AN_RF2G2_OFFCAL
, 0);
579 REG_RMW_FIELD(ah
, AR9285_AN_RF2G7
, AR9285_AN_RF2G7_PWDDB
, 0);
580 REG_RMW_FIELD(ah
, AR9285_AN_RF2G1
, AR9285_AN_RF2G1_ENPACAL
, 0);
581 REG_RMW_FIELD(ah
, AR9285_AN_RF2G1
, AR9285_AN_RF2G1_PDPADRV1
, 0);
582 REG_RMW_FIELD(ah
, AR9285_AN_RF2G1
, AR9285_AN_RF2G1_PDPADRV2
, 0);
583 REG_RMW_FIELD(ah
, AR9285_AN_RF2G1
, AR9285_AN_RF2G1_PDPAOUT
, 0);
584 REG_RMW_FIELD(ah
, AR9285_AN_RF2G8
, AR9285_AN_RF2G8_PADRVGN2TAB0
, 7);
585 REG_RMW_FIELD(ah
, AR9285_AN_RF2G7
, AR9285_AN_RF2G7_PADRVGN2TAB0
, 0);
586 ccomp_org
= MS(REG_READ(ah
, AR9285_AN_RF2G6
), AR9285_AN_RF2G6_CCOMP
);
587 REG_RMW_FIELD(ah
, AR9285_AN_RF2G6
, AR9285_AN_RF2G6_CCOMP
, 0xf);
589 REG_WRITE(ah
, AR9285_AN_TOP2
, 0xca0358a0);
591 REG_RMW_FIELD(ah
, AR9285_AN_RF2G6
, AR9285_AN_RF2G6_OFFS
, 0);
592 REG_RMW_FIELD(ah
, AR9285_AN_RF2G3
, AR9285_AN_RF2G3_PDVCCOMP
, 0);
594 for (i
= 6; i
> 0; i
--) {
595 regVal
= REG_READ(ah
, 0x7834);
596 regVal
|= (1 << (19 + i
));
597 REG_WRITE(ah
, 0x7834, regVal
);
599 regVal
= REG_READ(ah
, 0x7834);
600 regVal
&= (~(0x1 << (19 + i
)));
601 reg_field
= MS(REG_READ(ah
, 0x7840), AR9285_AN_RXTXBB1_SPARE9
);
602 regVal
|= (reg_field
<< (19 + i
));
603 REG_WRITE(ah
, 0x7834, regVal
);
606 REG_RMW_FIELD(ah
, AR9285_AN_RF2G3
, AR9285_AN_RF2G3_PDVCCOMP
, 1);
608 reg_field
= MS(REG_READ(ah
, AR9285_AN_RF2G9
), AR9285_AN_RXTXBB1_SPARE9
);
609 REG_RMW_FIELD(ah
, AR9285_AN_RF2G3
, AR9285_AN_RF2G3_PDVCCOMP
, reg_field
);
610 offs_6_1
= MS(REG_READ(ah
, AR9285_AN_RF2G6
), AR9285_AN_RF2G6_OFFS
);
611 offs_0
= MS(REG_READ(ah
, AR9285_AN_RF2G3
), AR9285_AN_RF2G3_PDVCCOMP
);
613 offset
= (offs_6_1
<<1) | offs_0
;
615 offs_6_1
= offset
>>1;
618 if ((!is_reset
) && (ah
->pacal_info
.prev_offset
== offset
)) {
619 if (ah
->pacal_info
.max_skipcount
< MAX_PACAL_SKIPCOUNT
)
620 ah
->pacal_info
.max_skipcount
=
621 2 * ah
->pacal_info
.max_skipcount
;
622 ah
->pacal_info
.skipcount
= ah
->pacal_info
.max_skipcount
;
624 ah
->pacal_info
.max_skipcount
= 1;
625 ah
->pacal_info
.skipcount
= 0;
626 ah
->pacal_info
.prev_offset
= offset
;
629 REG_RMW_FIELD(ah
, AR9285_AN_RF2G6
, AR9285_AN_RF2G6_OFFS
, offs_6_1
);
630 REG_RMW_FIELD(ah
, AR9285_AN_RF2G3
, AR9285_AN_RF2G3_PDVCCOMP
, offs_0
);
632 regVal
= REG_READ(ah
, 0x7834);
634 REG_WRITE(ah
, 0x7834, regVal
);
635 regVal
= REG_READ(ah
, 0x9808);
636 regVal
&= (~(0x1 << 27));
637 REG_WRITE(ah
, 0x9808, regVal
);
639 for (i
= 0; i
< ARRAY_SIZE(regList
); i
++)
640 REG_WRITE(ah
, regList
[i
][0], regList
[i
][1]);
642 REG_RMW_FIELD(ah
, AR9285_AN_RF2G6
, AR9285_AN_RF2G6_CCOMP
, ccomp_org
);
645 static void ar9002_hw_pa_cal(struct ath_hw
*ah
, bool is_reset
)
647 if (AR_SREV_9271(ah
)) {
648 if (is_reset
|| !ah
->pacal_info
.skipcount
)
649 ar9271_hw_pa_cal(ah
, is_reset
);
651 ah
->pacal_info
.skipcount
--;
652 } else if (AR_SREV_9285_12_OR_LATER(ah
)) {
653 if (is_reset
|| !ah
->pacal_info
.skipcount
)
654 ar9285_hw_pa_cal(ah
, is_reset
);
656 ah
->pacal_info
.skipcount
--;
660 static void ar9002_hw_olc_temp_compensation(struct ath_hw
*ah
)
662 if (OLC_FOR_AR9287_10_LATER(ah
))
663 ar9287_hw_olc_temp_compensation(ah
);
664 else if (OLC_FOR_AR9280_20_LATER(ah
))
665 ar9280_hw_olc_temp_compensation(ah
);
668 static int ar9002_hw_calibrate(struct ath_hw
*ah
, struct ath9k_channel
*chan
,
669 u8 rxchainmask
, bool longcal
)
671 struct ath9k_cal_list
*currCal
= ah
->cal_list_curr
;
672 bool nfcal
, nfcal_pending
= false, percal_pending
;
675 nfcal
= !!(REG_READ(ah
, AR_PHY_AGC_CONTROL(ah
)) & AR_PHY_AGC_CONTROL_NF
);
677 nfcal_pending
= test_bit(NFCAL_PENDING
, &ah
->caldata
->cal_flags
);
678 if (longcal
) /* Remember to not miss */
679 set_bit(LONGCAL_PENDING
, &ah
->caldata
->cal_flags
);
680 else if (test_bit(LONGCAL_PENDING
, &ah
->caldata
->cal_flags
))
681 longcal
= true; /* Respin a previous one */
684 percal_pending
= (currCal
&&
685 (currCal
->calState
== CAL_RUNNING
||
686 currCal
->calState
== CAL_WAITING
));
688 if (percal_pending
&& !nfcal
) {
689 if (!ar9002_hw_per_calibration(ah
, chan
, rxchainmask
, currCal
))
692 /* Looking for next waiting calibration if any */
693 for (currCal
= currCal
->calNext
; currCal
!= ah
->cal_list_curr
;
694 currCal
= currCal
->calNext
) {
695 if (currCal
->calState
== CAL_WAITING
)
698 if (currCal
->calState
== CAL_WAITING
) {
699 percal_pending
= true;
700 ah
->cal_list_curr
= currCal
;
702 percal_pending
= false;
703 ah
->cal_list_curr
= ah
->cal_list
;
707 /* Do not start a next calibration if the longcal is in action */
708 if (percal_pending
&& !nfcal
&& !longcal
) {
709 ath9k_hw_reset_calibration(ah
, currCal
);
714 /* Do NF cal only at longer intervals */
715 if (longcal
|| nfcal_pending
) {
717 * Get the value from the previous NF cal and update
720 if (ath9k_hw_getnf(ah
, chan
)) {
722 * Load the NF from history buffer of the current
724 * NF is slow time-variant, so it is OK to use a
727 ret
= ath9k_hw_loadnf(ah
, ah
->curchan
);
734 clear_bit(LONGCAL_PENDING
,
735 &ah
->caldata
->cal_flags
);
736 ath9k_hw_start_nfcal(ah
, false);
737 /* Do periodic PAOffset Cal */
738 ar9002_hw_pa_cal(ah
, false);
739 ar9002_hw_olc_temp_compensation(ah
);
743 return !percal_pending
;
746 /* Carrier leakage Calibration fix */
747 static bool ar9285_hw_cl_cal(struct ath_hw
*ah
, struct ath9k_channel
*chan
)
749 struct ath_common
*common
= ath9k_hw_common(ah
);
751 REG_SET_BIT(ah
, AR_PHY_CL_CAL_CTL
, AR_PHY_CL_CAL_ENABLE
);
752 if (IS_CHAN_HT20(chan
)) {
753 REG_SET_BIT(ah
, AR_PHY_CL_CAL_CTL
, AR_PHY_PARALLEL_CAL_ENABLE
);
754 REG_SET_BIT(ah
, AR_PHY_TURBO
, AR_PHY_FC_DYN2040_EN
);
755 REG_CLR_BIT(ah
, AR_PHY_AGC_CONTROL(ah
),
756 AR_PHY_AGC_CONTROL_FLTR_CAL
);
757 REG_CLR_BIT(ah
, AR_PHY_TPCRG1
, AR_PHY_TPCRG1_PD_CAL_ENABLE
);
758 REG_SET_BIT(ah
, AR_PHY_AGC_CONTROL(ah
), AR_PHY_AGC_CONTROL_CAL
);
759 if (!ath9k_hw_wait(ah
, AR_PHY_AGC_CONTROL(ah
),
760 AR_PHY_AGC_CONTROL_CAL
, 0, AH_WAIT_TIMEOUT
)) {
761 ath_dbg(common
, CALIBRATE
,
762 "offset calibration failed to complete in %d ms; noisy environment?\n",
763 AH_WAIT_TIMEOUT
/ 1000);
766 REG_CLR_BIT(ah
, AR_PHY_TURBO
, AR_PHY_FC_DYN2040_EN
);
767 REG_CLR_BIT(ah
, AR_PHY_CL_CAL_CTL
, AR_PHY_PARALLEL_CAL_ENABLE
);
768 REG_CLR_BIT(ah
, AR_PHY_CL_CAL_CTL
, AR_PHY_CL_CAL_ENABLE
);
770 REG_CLR_BIT(ah
, AR_PHY_ADC_CTL
, AR_PHY_ADC_CTL_OFF_PWDADC
);
771 REG_SET_BIT(ah
, AR_PHY_AGC_CONTROL(ah
), AR_PHY_AGC_CONTROL_FLTR_CAL
);
772 REG_SET_BIT(ah
, AR_PHY_TPCRG1
, AR_PHY_TPCRG1_PD_CAL_ENABLE
);
773 REG_SET_BIT(ah
, AR_PHY_AGC_CONTROL(ah
), AR_PHY_AGC_CONTROL_CAL
);
774 if (!ath9k_hw_wait(ah
, AR_PHY_AGC_CONTROL(ah
), AR_PHY_AGC_CONTROL_CAL
,
775 0, AH_WAIT_TIMEOUT
)) {
776 ath_dbg(common
, CALIBRATE
,
777 "offset calibration failed to complete in %d ms; noisy environment?\n",
778 AH_WAIT_TIMEOUT
/ 1000);
782 REG_SET_BIT(ah
, AR_PHY_ADC_CTL
, AR_PHY_ADC_CTL_OFF_PWDADC
);
783 REG_CLR_BIT(ah
, AR_PHY_CL_CAL_CTL
, AR_PHY_CL_CAL_ENABLE
);
784 REG_CLR_BIT(ah
, AR_PHY_AGC_CONTROL(ah
), AR_PHY_AGC_CONTROL_FLTR_CAL
);
789 static bool ar9285_hw_clc(struct ath_hw
*ah
, struct ath9k_channel
*chan
)
792 u_int32_t txgain_max
;
793 u_int32_t clc_gain
, gain_mask
= 0, clc_num
= 0;
794 u_int32_t reg_clc_I0
, reg_clc_Q0
;
795 u_int32_t i0_num
= 0;
796 u_int32_t q0_num
= 0;
797 u_int32_t total_num
= 0;
798 u_int32_t reg_rf2g5_org
;
801 if (!(ar9285_hw_cl_cal(ah
, chan
)))
804 txgain_max
= MS(REG_READ(ah
, AR_PHY_TX_PWRCTRL7
),
805 AR_PHY_TX_PWRCTRL_TX_GAIN_TAB_MAX
);
807 for (i
= 0; i
< (txgain_max
+1); i
++) {
808 clc_gain
= (REG_READ(ah
, (AR_PHY_TX_GAIN_TBL1
+(i
<<2))) &
809 AR_PHY_TX_GAIN_CLC
) >> AR_PHY_TX_GAIN_CLC_S
;
810 if (!(gain_mask
& (1 << clc_gain
))) {
811 gain_mask
|= (1 << clc_gain
);
816 for (i
= 0; i
< clc_num
; i
++) {
817 reg_clc_I0
= (REG_READ(ah
, (AR_PHY_CLC_TBL1
+ (i
<< 2)))
818 & AR_PHY_CLC_I0
) >> AR_PHY_CLC_I0_S
;
819 reg_clc_Q0
= (REG_READ(ah
, (AR_PHY_CLC_TBL1
+ (i
<< 2)))
820 & AR_PHY_CLC_Q0
) >> AR_PHY_CLC_Q0_S
;
827 total_num
= i0_num
+ q0_num
;
828 if (total_num
> AR9285_CLCAL_REDO_THRESH
) {
829 reg_rf2g5_org
= REG_READ(ah
, AR9285_RF2G5
);
830 if (AR_SREV_9285E_20(ah
)) {
831 REG_WRITE(ah
, AR9285_RF2G5
,
832 (reg_rf2g5_org
& AR9285_RF2G5_IC50TX
) |
833 AR9285_RF2G5_IC50TX_XE_SET
);
835 REG_WRITE(ah
, AR9285_RF2G5
,
836 (reg_rf2g5_org
& AR9285_RF2G5_IC50TX
) |
837 AR9285_RF2G5_IC50TX_SET
);
839 retv
= ar9285_hw_cl_cal(ah
, chan
);
840 REG_WRITE(ah
, AR9285_RF2G5
, reg_rf2g5_org
);
845 static bool ar9002_hw_init_cal(struct ath_hw
*ah
, struct ath9k_channel
*chan
)
847 struct ath_common
*common
= ath9k_hw_common(ah
);
849 if (AR_SREV_9271(ah
)) {
850 if (!ar9285_hw_cl_cal(ah
, chan
))
852 } else if (AR_SREV_9285(ah
) && AR_SREV_9285_12_OR_LATER(ah
)) {
853 if (!ar9285_hw_clc(ah
, chan
))
856 if (AR_SREV_9280_20_OR_LATER(ah
)) {
857 if (!AR_SREV_9287_11_OR_LATER(ah
))
858 REG_CLR_BIT(ah
, AR_PHY_ADC_CTL
,
859 AR_PHY_ADC_CTL_OFF_PWDADC
);
860 REG_SET_BIT(ah
, AR_PHY_AGC_CONTROL(ah
),
861 AR_PHY_AGC_CONTROL_FLTR_CAL
);
864 /* Calibrate the AGC */
865 REG_WRITE(ah
, AR_PHY_AGC_CONTROL(ah
),
866 REG_READ(ah
, AR_PHY_AGC_CONTROL(ah
)) |
867 AR_PHY_AGC_CONTROL_CAL
);
869 /* Poll for offset calibration complete */
870 if (!ath9k_hw_wait(ah
, AR_PHY_AGC_CONTROL(ah
),
871 AR_PHY_AGC_CONTROL_CAL
,
872 0, AH_WAIT_TIMEOUT
)) {
873 ath_dbg(common
, CALIBRATE
,
874 "offset calibration failed to complete in %d ms; noisy environment?\n",
875 AH_WAIT_TIMEOUT
/ 1000);
879 if (AR_SREV_9280_20_OR_LATER(ah
)) {
880 if (!AR_SREV_9287_11_OR_LATER(ah
))
881 REG_SET_BIT(ah
, AR_PHY_ADC_CTL
,
882 AR_PHY_ADC_CTL_OFF_PWDADC
);
883 REG_CLR_BIT(ah
, AR_PHY_AGC_CONTROL(ah
),
884 AR_PHY_AGC_CONTROL_FLTR_CAL
);
888 /* Do PA Calibration */
889 ar9002_hw_pa_cal(ah
, true);
890 ath9k_hw_loadnf(ah
, chan
);
891 ath9k_hw_start_nfcal(ah
, true);
893 ah
->cal_list
= ah
->cal_list_last
= ah
->cal_list_curr
= NULL
;
895 /* Enable IQ, ADC Gain and ADC DC offset CALs */
896 if (AR_SREV_9100(ah
) || AR_SREV_9160_10_OR_LATER(ah
)) {
897 ah
->supp_cals
= IQ_MISMATCH_CAL
;
899 if (AR_SREV_9160_10_OR_LATER(ah
))
900 ah
->supp_cals
|= ADC_GAIN_CAL
| ADC_DC_CAL
;
902 if (AR_SREV_9287(ah
))
903 ah
->supp_cals
&= ~ADC_GAIN_CAL
;
905 if (ar9002_hw_is_cal_supported(ah
, chan
, ADC_GAIN_CAL
)) {
906 INIT_CAL(&ah
->adcgain_caldata
);
907 INSERT_CAL(ah
, &ah
->adcgain_caldata
);
908 ath_dbg(common
, CALIBRATE
,
909 "enabling ADC Gain Calibration\n");
912 if (ar9002_hw_is_cal_supported(ah
, chan
, ADC_DC_CAL
)) {
913 INIT_CAL(&ah
->adcdc_caldata
);
914 INSERT_CAL(ah
, &ah
->adcdc_caldata
);
915 ath_dbg(common
, CALIBRATE
,
916 "enabling ADC DC Calibration\n");
919 if (ar9002_hw_is_cal_supported(ah
, chan
, IQ_MISMATCH_CAL
)) {
920 INIT_CAL(&ah
->iq_caldata
);
921 INSERT_CAL(ah
, &ah
->iq_caldata
);
922 ath_dbg(common
, CALIBRATE
, "enabling IQ Calibration\n");
925 ah
->cal_list_curr
= ah
->cal_list
;
927 if (ah
->cal_list_curr
)
928 ath9k_hw_reset_calibration(ah
, ah
->cal_list_curr
);
932 ah
->caldata
->CalValid
= 0;
937 static const struct ath9k_percal_data iq_cal_multi_sample
= {
941 ar9002_hw_iqcal_collect
,
942 ar9002_hw_iqcalibrate
944 static const struct ath9k_percal_data iq_cal_single_sample
= {
948 ar9002_hw_iqcal_collect
,
949 ar9002_hw_iqcalibrate
951 static const struct ath9k_percal_data adc_gain_cal_multi_sample
= {
955 ar9002_hw_adc_gaincal_collect
,
956 ar9002_hw_adc_gaincal_calibrate
958 static const struct ath9k_percal_data adc_gain_cal_single_sample
= {
962 ar9002_hw_adc_gaincal_collect
,
963 ar9002_hw_adc_gaincal_calibrate
965 static const struct ath9k_percal_data adc_dc_cal_multi_sample
= {
969 ar9002_hw_adc_dccal_collect
,
970 ar9002_hw_adc_dccal_calibrate
972 static const struct ath9k_percal_data adc_dc_cal_single_sample
= {
976 ar9002_hw_adc_dccal_collect
,
977 ar9002_hw_adc_dccal_calibrate
980 static void ar9002_hw_init_cal_settings(struct ath_hw
*ah
)
982 if (AR_SREV_9100(ah
)) {
983 ah
->iq_caldata
.calData
= &iq_cal_multi_sample
;
984 ah
->supp_cals
= IQ_MISMATCH_CAL
;
988 if (AR_SREV_9160_10_OR_LATER(ah
)) {
989 if (AR_SREV_9280_20_OR_LATER(ah
)) {
990 ah
->iq_caldata
.calData
= &iq_cal_single_sample
;
991 ah
->adcgain_caldata
.calData
=
992 &adc_gain_cal_single_sample
;
993 ah
->adcdc_caldata
.calData
=
994 &adc_dc_cal_single_sample
;
996 ah
->iq_caldata
.calData
= &iq_cal_multi_sample
;
997 ah
->adcgain_caldata
.calData
=
998 &adc_gain_cal_multi_sample
;
999 ah
->adcdc_caldata
.calData
=
1000 &adc_dc_cal_multi_sample
;
1002 ah
->supp_cals
= ADC_GAIN_CAL
| ADC_DC_CAL
| IQ_MISMATCH_CAL
;
1004 if (AR_SREV_9287(ah
))
1005 ah
->supp_cals
&= ~ADC_GAIN_CAL
;
1009 void ar9002_hw_attach_calib_ops(struct ath_hw
*ah
)
1011 struct ath_hw_private_ops
*priv_ops
= ath9k_hw_private_ops(ah
);
1012 struct ath_hw_ops
*ops
= ath9k_hw_ops(ah
);
1014 priv_ops
->init_cal_settings
= ar9002_hw_init_cal_settings
;
1015 priv_ops
->init_cal
= ar9002_hw_init_cal
;
1016 priv_ops
->setup_calibration
= ar9002_hw_setup_calibration
;
1018 ops
->calibrate
= ar9002_hw_calibrate
;