2 * Copyright (c) 2010-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 "ar9003_phy.h"
20 #include "ar9003_rtt.h"
21 #include "ar9003_mci.h"
23 #define MAX_MEASUREMENT MAX_IQCAL_MEASUREMENT
24 #define MAX_MAG_DELTA 11
25 #define MAX_PHS_DELTA 10
28 int mag_coeff
[AR9300_MAX_CHAINS
][MAX_MEASUREMENT
];
29 int phs_coeff
[AR9300_MAX_CHAINS
][MAX_MEASUREMENT
];
33 enum ar9003_cal_types
{
34 IQ_MISMATCH_CAL
= BIT(0),
37 static void ar9003_hw_setup_calibration(struct ath_hw
*ah
,
38 struct ath9k_cal_list
*currCal
)
40 struct ath_common
*common
= ath9k_hw_common(ah
);
42 /* Select calibration to run */
43 switch (currCal
->calData
->calType
) {
46 * Start calibration with
47 * 2^(INIT_IQCAL_LOG_COUNT_MAX+1) samples
49 REG_RMW_FIELD(ah
, AR_PHY_TIMING4
,
50 AR_PHY_TIMING4_IQCAL_LOG_COUNT_MAX
,
51 currCal
->calData
->calCountMax
);
52 REG_WRITE(ah
, AR_PHY_CALMODE
, AR_PHY_CALMODE_IQ
);
54 ath_dbg(common
, CALIBRATE
,
55 "starting IQ Mismatch Calibration\n");
58 REG_SET_BIT(ah
, AR_PHY_TIMING4
, AR_PHY_TIMING4_DO_CAL
);
61 ath_err(common
, "Invalid calibration type\n");
67 * Generic calibration routine.
68 * Recalibrate the lower PHY chips to account for temperature/environment
71 static bool ar9003_hw_per_calibration(struct ath_hw
*ah
,
72 struct ath9k_channel
*ichan
,
74 struct ath9k_cal_list
*currCal
)
76 struct ath9k_hw_cal_data
*caldata
= ah
->caldata
;
77 /* Cal is assumed not done until explicitly set below */
78 bool iscaldone
= false;
80 /* Calibration in progress. */
81 if (currCal
->calState
== CAL_RUNNING
) {
82 /* Check to see if it has finished. */
83 if (!(REG_READ(ah
, AR_PHY_TIMING4
) & AR_PHY_TIMING4_DO_CAL
)) {
85 * Accumulate cal measures for active chains
87 currCal
->calData
->calCollect(ah
);
90 if (ah
->cal_samples
>=
91 currCal
->calData
->calNumSamples
) {
92 unsigned int i
, numChains
= 0;
93 for (i
= 0; i
< AR9300_MAX_CHAINS
; i
++) {
94 if (rxchainmask
& (1 << i
))
99 * Process accumulated data
101 currCal
->calData
->calPostProc(ah
, numChains
);
103 /* Calibration has finished. */
104 caldata
->CalValid
|= currCal
->calData
->calType
;
105 currCal
->calState
= CAL_DONE
;
109 * Set-up collection of another sub-sample until we
112 ar9003_hw_setup_calibration(ah
, currCal
);
115 } else if (!(caldata
->CalValid
& currCal
->calData
->calType
)) {
116 /* If current cal is marked invalid in channel, kick it off */
117 ath9k_hw_reset_calibration(ah
, currCal
);
123 static bool ar9003_hw_calibrate(struct ath_hw
*ah
,
124 struct ath9k_channel
*chan
,
128 bool iscaldone
= true;
129 struct ath9k_cal_list
*currCal
= ah
->cal_list_curr
;
132 * For given calibration:
133 * 1. Call generic cal routine
134 * 2. When this cal is done (isCalDone) if we have more cals waiting
135 * (eg after reset), mask this to upper layers by not propagating
136 * isCalDone if it is set to TRUE.
137 * Instead, change isCalDone to FALSE and setup the waiting cal(s)
141 (currCal
->calState
== CAL_RUNNING
||
142 currCal
->calState
== CAL_WAITING
)) {
143 iscaldone
= ar9003_hw_per_calibration(ah
, chan
,
144 rxchainmask
, currCal
);
146 ah
->cal_list_curr
= currCal
= currCal
->calNext
;
148 if (currCal
->calState
== CAL_WAITING
) {
150 ath9k_hw_reset_calibration(ah
, currCal
);
156 * Do NF cal only at longer intervals. Get the value from
157 * the previous NF cal and update history buffer.
159 if (longcal
&& ath9k_hw_getnf(ah
, chan
)) {
161 * Load the NF from history buffer of the current channel.
162 * NF is slow time-variant, so it is OK to use a historical
165 ath9k_hw_loadnf(ah
, ah
->curchan
);
167 /* start NF calibration, without updating BB NF register */
168 ath9k_hw_start_nfcal(ah
, false);
174 static void ar9003_hw_iqcal_collect(struct ath_hw
*ah
)
178 /* Accumulate IQ cal measures for active chains */
179 for (i
= 0; i
< AR5416_MAX_CHAINS
; i
++) {
180 if (ah
->txchainmask
& BIT(i
)) {
181 ah
->totalPowerMeasI
[i
] +=
182 REG_READ(ah
, AR_PHY_CAL_MEAS_0(i
));
183 ah
->totalPowerMeasQ
[i
] +=
184 REG_READ(ah
, AR_PHY_CAL_MEAS_1(i
));
185 ah
->totalIqCorrMeas
[i
] +=
186 (int32_t) REG_READ(ah
, AR_PHY_CAL_MEAS_2(i
));
187 ath_dbg(ath9k_hw_common(ah
), CALIBRATE
,
188 "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
189 ah
->cal_samples
, i
, ah
->totalPowerMeasI
[i
],
190 ah
->totalPowerMeasQ
[i
],
191 ah
->totalIqCorrMeas
[i
]);
196 static void ar9003_hw_iqcalibrate(struct ath_hw
*ah
, u8 numChains
)
198 struct ath_common
*common
= ath9k_hw_common(ah
);
199 u32 powerMeasQ
, powerMeasI
, iqCorrMeas
;
200 u32 qCoffDenom
, iCoffDenom
;
201 int32_t qCoff
, iCoff
;
203 static const u_int32_t offset_array
[3] = {
204 AR_PHY_RX_IQCAL_CORR_B0
,
205 AR_PHY_RX_IQCAL_CORR_B1
,
206 AR_PHY_RX_IQCAL_CORR_B2
,
209 for (i
= 0; i
< numChains
; i
++) {
210 powerMeasI
= ah
->totalPowerMeasI
[i
];
211 powerMeasQ
= ah
->totalPowerMeasQ
[i
];
212 iqCorrMeas
= ah
->totalIqCorrMeas
[i
];
214 ath_dbg(common
, CALIBRATE
,
215 "Starting IQ Cal and Correction for Chain %d\n", i
);
217 ath_dbg(common
, CALIBRATE
,
218 "Original: Chn %d iq_corr_meas = 0x%08x\n",
219 i
, ah
->totalIqCorrMeas
[i
]);
223 if (iqCorrMeas
> 0x80000000) {
224 iqCorrMeas
= (0xffffffff - iqCorrMeas
) + 1;
228 ath_dbg(common
, CALIBRATE
, "Chn %d pwr_meas_i = 0x%08x\n",
230 ath_dbg(common
, CALIBRATE
, "Chn %d pwr_meas_q = 0x%08x\n",
232 ath_dbg(common
, CALIBRATE
, "iqCorrNeg is 0x%08x\n", iqCorrNeg
);
234 iCoffDenom
= (powerMeasI
/ 2 + powerMeasQ
/ 2) / 256;
235 qCoffDenom
= powerMeasQ
/ 64;
237 if ((iCoffDenom
!= 0) && (qCoffDenom
!= 0)) {
238 iCoff
= iqCorrMeas
/ iCoffDenom
;
239 qCoff
= powerMeasI
/ qCoffDenom
- 64;
240 ath_dbg(common
, CALIBRATE
, "Chn %d iCoff = 0x%08x\n",
242 ath_dbg(common
, CALIBRATE
, "Chn %d qCoff = 0x%08x\n",
245 /* Force bounds on iCoff */
248 else if (iCoff
<= -63)
251 /* Negate iCoff if iqCorrNeg == 0 */
252 if (iqCorrNeg
== 0x0)
255 /* Force bounds on qCoff */
258 else if (qCoff
<= -63)
261 iCoff
= iCoff
& 0x7f;
262 qCoff
= qCoff
& 0x7f;
264 ath_dbg(common
, CALIBRATE
,
265 "Chn %d : iCoff = 0x%x qCoff = 0x%x\n",
267 ath_dbg(common
, CALIBRATE
,
268 "Register offset (0x%04x) before update = 0x%x\n",
270 REG_READ(ah
, offset_array
[i
]));
272 if (AR_SREV_9565(ah
) &&
273 (iCoff
== 63 || qCoff
== 63 ||
274 iCoff
== -63 || qCoff
== -63))
277 REG_RMW_FIELD(ah
, offset_array
[i
],
278 AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF
,
280 REG_RMW_FIELD(ah
, offset_array
[i
],
281 AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF
,
283 ath_dbg(common
, CALIBRATE
,
284 "Register offset (0x%04x) QI COFF (bitfields 0x%08x) after update = 0x%x\n",
286 AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF
,
287 REG_READ(ah
, offset_array
[i
]));
288 ath_dbg(common
, CALIBRATE
,
289 "Register offset (0x%04x) QQ COFF (bitfields 0x%08x) after update = 0x%x\n",
291 AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF
,
292 REG_READ(ah
, offset_array
[i
]));
294 ath_dbg(common
, CALIBRATE
,
295 "IQ Cal and Correction done for Chain %d\n", i
);
299 REG_SET_BIT(ah
, AR_PHY_RX_IQCAL_CORR_B0
,
300 AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE
);
301 ath_dbg(common
, CALIBRATE
,
302 "IQ Cal and Correction (offset 0x%04x) enabled (bit position 0x%08x). New Value 0x%08x\n",
303 (unsigned) (AR_PHY_RX_IQCAL_CORR_B0
),
304 AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE
,
305 REG_READ(ah
, AR_PHY_RX_IQCAL_CORR_B0
));
308 static const struct ath9k_percal_data iq_cal_single_sample
= {
312 ar9003_hw_iqcal_collect
,
313 ar9003_hw_iqcalibrate
316 static void ar9003_hw_init_cal_settings(struct ath_hw
*ah
)
318 ah
->iq_caldata
.calData
= &iq_cal_single_sample
;
320 if (AR_SREV_9300_20_OR_LATER(ah
)) {
321 ah
->enabled_cals
|= TX_IQ_CAL
;
322 if (AR_SREV_9485_OR_LATER(ah
) && !AR_SREV_9340(ah
))
323 ah
->enabled_cals
|= TX_IQ_ON_AGC_CAL
;
326 ah
->supp_cals
= IQ_MISMATCH_CAL
;
330 * solve 4x4 linear equation used in loopback iq cal.
332 static bool ar9003_hw_solve_iq_cal(struct ath_hw
*ah
,
343 s32 f1
= cos_2phi_1
- cos_2phi_2
,
344 f3
= sin_2phi_1
- sin_2phi_2
,
346 s32 mag_tx
, phs_tx
, mag_rx
, phs_rx
;
347 const s32 result_shift
= 1 << 15;
348 struct ath_common
*common
= ath9k_hw_common(ah
);
350 f2
= (f1
* f1
+ f3
* f3
) / result_shift
;
353 ath_dbg(common
, CALIBRATE
, "Divide by 0\n");
357 /* mag mismatch, tx */
358 mag_tx
= f1
* (mag_a0_d0
- mag_a1_d0
) + f3
* (phs_a0_d0
- phs_a1_d0
);
359 /* phs mismatch, tx */
360 phs_tx
= f3
* (-mag_a0_d0
+ mag_a1_d0
) + f1
* (phs_a0_d0
- phs_a1_d0
);
362 mag_tx
= (mag_tx
/ f2
);
363 phs_tx
= (phs_tx
/ f2
);
365 /* mag mismatch, rx */
366 mag_rx
= mag_a0_d0
- (cos_2phi_1
* mag_tx
+ sin_2phi_1
* phs_tx
) /
368 /* phs mismatch, rx */
369 phs_rx
= phs_a0_d0
+ (sin_2phi_1
* mag_tx
- cos_2phi_1
* phs_tx
) /
372 solved_eq
[0] = mag_tx
;
373 solved_eq
[1] = phs_tx
;
374 solved_eq
[2] = mag_rx
;
375 solved_eq
[3] = phs_rx
;
380 static s32
ar9003_hw_find_mag_approx(struct ath_hw
*ah
, s32 in_re
, s32 in_im
)
382 s32 abs_i
= abs(in_re
),
394 return max_abs
- (max_abs
/ 32) + (min_abs
/ 8) + (min_abs
/ 4);
399 static bool ar9003_hw_calc_iq_corr(struct ath_hw
*ah
,
404 s32 i2_m_q2_a0_d0
, i2_p_q2_a0_d0
, iq_corr_a0_d0
,
405 i2_m_q2_a0_d1
, i2_p_q2_a0_d1
, iq_corr_a0_d1
,
406 i2_m_q2_a1_d0
, i2_p_q2_a1_d0
, iq_corr_a1_d0
,
407 i2_m_q2_a1_d1
, i2_p_q2_a1_d1
, iq_corr_a1_d1
;
408 s32 mag_a0_d0
, mag_a1_d0
, mag_a0_d1
, mag_a1_d1
,
409 phs_a0_d0
, phs_a1_d0
, phs_a0_d1
, phs_a1_d1
,
410 sin_2phi_1
, cos_2phi_1
,
411 sin_2phi_2
, cos_2phi_2
;
412 s32 mag_tx
, phs_tx
, mag_rx
, phs_rx
;
413 s32 solved_eq
[4], mag_corr_tx
, phs_corr_tx
, mag_corr_rx
, phs_corr_rx
,
415 const s32 res_scale
= 1 << 15;
416 const s32 delpt_shift
= 1 << 8;
418 struct ath_common
*common
= ath9k_hw_common(ah
);
420 i2_m_q2_a0_d0
= iq_res
[0] & 0xfff;
421 i2_p_q2_a0_d0
= (iq_res
[0] >> 12) & 0xfff;
422 iq_corr_a0_d0
= ((iq_res
[0] >> 24) & 0xff) + ((iq_res
[1] & 0xf) << 8);
424 if (i2_m_q2_a0_d0
> 0x800)
425 i2_m_q2_a0_d0
= -((0xfff - i2_m_q2_a0_d0
) + 1);
427 if (i2_p_q2_a0_d0
> 0x800)
428 i2_p_q2_a0_d0
= -((0xfff - i2_p_q2_a0_d0
) + 1);
430 if (iq_corr_a0_d0
> 0x800)
431 iq_corr_a0_d0
= -((0xfff - iq_corr_a0_d0
) + 1);
433 i2_m_q2_a0_d1
= (iq_res
[1] >> 4) & 0xfff;
434 i2_p_q2_a0_d1
= (iq_res
[2] & 0xfff);
435 iq_corr_a0_d1
= (iq_res
[2] >> 12) & 0xfff;
437 if (i2_m_q2_a0_d1
> 0x800)
438 i2_m_q2_a0_d1
= -((0xfff - i2_m_q2_a0_d1
) + 1);
440 if (i2_p_q2_a0_d1
> 0x800)
441 i2_p_q2_a0_d1
= -((0xfff - i2_p_q2_a0_d1
) + 1);
443 if (iq_corr_a0_d1
> 0x800)
444 iq_corr_a0_d1
= -((0xfff - iq_corr_a0_d1
) + 1);
446 i2_m_q2_a1_d0
= ((iq_res
[2] >> 24) & 0xff) + ((iq_res
[3] & 0xf) << 8);
447 i2_p_q2_a1_d0
= (iq_res
[3] >> 4) & 0xfff;
448 iq_corr_a1_d0
= iq_res
[4] & 0xfff;
450 if (i2_m_q2_a1_d0
> 0x800)
451 i2_m_q2_a1_d0
= -((0xfff - i2_m_q2_a1_d0
) + 1);
453 if (i2_p_q2_a1_d0
> 0x800)
454 i2_p_q2_a1_d0
= -((0xfff - i2_p_q2_a1_d0
) + 1);
456 if (iq_corr_a1_d0
> 0x800)
457 iq_corr_a1_d0
= -((0xfff - iq_corr_a1_d0
) + 1);
459 i2_m_q2_a1_d1
= (iq_res
[4] >> 12) & 0xfff;
460 i2_p_q2_a1_d1
= ((iq_res
[4] >> 24) & 0xff) + ((iq_res
[5] & 0xf) << 8);
461 iq_corr_a1_d1
= (iq_res
[5] >> 4) & 0xfff;
463 if (i2_m_q2_a1_d1
> 0x800)
464 i2_m_q2_a1_d1
= -((0xfff - i2_m_q2_a1_d1
) + 1);
466 if (i2_p_q2_a1_d1
> 0x800)
467 i2_p_q2_a1_d1
= -((0xfff - i2_p_q2_a1_d1
) + 1);
469 if (iq_corr_a1_d1
> 0x800)
470 iq_corr_a1_d1
= -((0xfff - iq_corr_a1_d1
) + 1);
472 if ((i2_p_q2_a0_d0
== 0) || (i2_p_q2_a0_d1
== 0) ||
473 (i2_p_q2_a1_d0
== 0) || (i2_p_q2_a1_d1
== 0)) {
474 ath_dbg(common
, CALIBRATE
,
480 i2_p_q2_a0_d0
, i2_p_q2_a0_d1
,
481 i2_p_q2_a1_d0
, i2_p_q2_a1_d1
);
485 mag_a0_d0
= (i2_m_q2_a0_d0
* res_scale
) / i2_p_q2_a0_d0
;
486 phs_a0_d0
= (iq_corr_a0_d0
* res_scale
) / i2_p_q2_a0_d0
;
488 mag_a0_d1
= (i2_m_q2_a0_d1
* res_scale
) / i2_p_q2_a0_d1
;
489 phs_a0_d1
= (iq_corr_a0_d1
* res_scale
) / i2_p_q2_a0_d1
;
491 mag_a1_d0
= (i2_m_q2_a1_d0
* res_scale
) / i2_p_q2_a1_d0
;
492 phs_a1_d0
= (iq_corr_a1_d0
* res_scale
) / i2_p_q2_a1_d0
;
494 mag_a1_d1
= (i2_m_q2_a1_d1
* res_scale
) / i2_p_q2_a1_d1
;
495 phs_a1_d1
= (iq_corr_a1_d1
* res_scale
) / i2_p_q2_a1_d1
;
497 /* w/o analog phase shift */
498 sin_2phi_1
= (((mag_a0_d0
- mag_a0_d1
) * delpt_shift
) / DELPT
);
499 /* w/o analog phase shift */
500 cos_2phi_1
= (((phs_a0_d1
- phs_a0_d0
) * delpt_shift
) / DELPT
);
501 /* w/ analog phase shift */
502 sin_2phi_2
= (((mag_a1_d0
- mag_a1_d1
) * delpt_shift
) / DELPT
);
503 /* w/ analog phase shift */
504 cos_2phi_2
= (((phs_a1_d1
- phs_a1_d0
) * delpt_shift
) / DELPT
);
507 * force sin^2 + cos^2 = 1;
508 * find magnitude by approximation
510 mag1
= ar9003_hw_find_mag_approx(ah
, cos_2phi_1
, sin_2phi_1
);
511 mag2
= ar9003_hw_find_mag_approx(ah
, cos_2phi_2
, sin_2phi_2
);
513 if ((mag1
== 0) || (mag2
== 0)) {
514 ath_dbg(common
, CALIBRATE
, "Divide by 0: mag1=%d, mag2=%d\n",
519 /* normalization sin and cos by mag */
520 sin_2phi_1
= (sin_2phi_1
* res_scale
/ mag1
);
521 cos_2phi_1
= (cos_2phi_1
* res_scale
/ mag1
);
522 sin_2phi_2
= (sin_2phi_2
* res_scale
/ mag2
);
523 cos_2phi_2
= (cos_2phi_2
* res_scale
/ mag2
);
525 /* calculate IQ mismatch */
526 if (!ar9003_hw_solve_iq_cal(ah
,
527 sin_2phi_1
, cos_2phi_1
,
528 sin_2phi_2
, cos_2phi_2
,
529 mag_a0_d0
, phs_a0_d0
,
531 phs_a1_d0
, solved_eq
)) {
532 ath_dbg(common
, CALIBRATE
,
533 "Call to ar9003_hw_solve_iq_cal() failed\n");
537 mag_tx
= solved_eq
[0];
538 phs_tx
= solved_eq
[1];
539 mag_rx
= solved_eq
[2];
540 phs_rx
= solved_eq
[3];
542 ath_dbg(common
, CALIBRATE
,
543 "chain %d: mag mismatch=%d phase mismatch=%d\n",
544 chain_idx
, mag_tx
/res_scale
, phs_tx
/res_scale
);
546 if (res_scale
== mag_tx
) {
547 ath_dbg(common
, CALIBRATE
,
548 "Divide by 0: mag_tx=%d, res_scale=%d\n",
553 /* calculate and quantize Tx IQ correction factor */
554 mag_corr_tx
= (mag_tx
* res_scale
) / (res_scale
- mag_tx
);
555 phs_corr_tx
= -phs_tx
;
557 q_q_coff
= (mag_corr_tx
* 128 / res_scale
);
558 q_i_coff
= (phs_corr_tx
* 256 / res_scale
);
560 ath_dbg(common
, CALIBRATE
, "tx chain %d: mag corr=%d phase corr=%d\n",
561 chain_idx
, q_q_coff
, q_i_coff
);
572 iqc_coeff
[0] = (q_q_coff
* 128) + q_i_coff
;
574 ath_dbg(common
, CALIBRATE
, "tx chain %d: iq corr coeff=%x\n",
575 chain_idx
, iqc_coeff
[0]);
577 if (-mag_rx
== res_scale
) {
578 ath_dbg(common
, CALIBRATE
,
579 "Divide by 0: mag_rx=%d, res_scale=%d\n",
584 /* calculate and quantize Rx IQ correction factors */
585 mag_corr_rx
= (-mag_rx
* res_scale
) / (res_scale
+ mag_rx
);
586 phs_corr_rx
= -phs_rx
;
588 q_q_coff
= (mag_corr_rx
* 128 / res_scale
);
589 q_i_coff
= (phs_corr_rx
* 256 / res_scale
);
591 ath_dbg(common
, CALIBRATE
, "rx chain %d: mag corr=%d phase corr=%d\n",
592 chain_idx
, q_q_coff
, q_i_coff
);
603 iqc_coeff
[1] = (q_q_coff
* 128) + q_i_coff
;
605 ath_dbg(common
, CALIBRATE
, "rx chain %d: iq corr coeff=%x\n",
606 chain_idx
, iqc_coeff
[1]);
611 static void ar9003_hw_detect_outlier(int *mp_coeff
, int nmeasurement
,
614 int mp_max
= -64, max_idx
= 0;
615 int mp_min
= 63, min_idx
= 0;
616 int mp_avg
= 0, i
, outlier_idx
= 0, mp_count
= 0;
618 /* find min/max mismatch across all calibrated gains */
619 for (i
= 0; i
< nmeasurement
; i
++) {
620 if (mp_coeff
[i
] > mp_max
) {
621 mp_max
= mp_coeff
[i
];
623 } else if (mp_coeff
[i
] < mp_min
) {
624 mp_min
= mp_coeff
[i
];
629 /* find average (exclude max abs value) */
630 for (i
= 0; i
< nmeasurement
; i
++) {
631 if ((abs(mp_coeff
[i
]) < abs(mp_max
)) ||
632 (abs(mp_coeff
[i
]) < abs(mp_min
))) {
633 mp_avg
+= mp_coeff
[i
];
639 * finding mean magnitude/phase if possible, otherwise
640 * just use the last value as the mean
645 mp_avg
= mp_coeff
[nmeasurement
- 1];
648 if (abs(mp_max
- mp_min
) > max_delta
) {
649 if (abs(mp_max
- mp_avg
) > abs(mp_min
- mp_avg
))
650 outlier_idx
= max_idx
;
652 outlier_idx
= min_idx
;
654 mp_coeff
[outlier_idx
] = mp_avg
;
658 static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw
*ah
,
662 int i
, im
, nmeasurement
;
663 u32 tx_corr_coeff
[MAX_MEASUREMENT
][AR9300_MAX_CHAINS
];
664 struct ath9k_hw_cal_data
*caldata
= ah
->caldata
;
666 memset(tx_corr_coeff
, 0, sizeof(tx_corr_coeff
));
667 for (i
= 0; i
< MAX_MEASUREMENT
/ 2; i
++) {
668 tx_corr_coeff
[i
* 2][0] = tx_corr_coeff
[(i
* 2) + 1][0] =
669 AR_PHY_TX_IQCAL_CORR_COEFF_B0(i
);
670 if (!AR_SREV_9485(ah
)) {
671 tx_corr_coeff
[i
* 2][1] =
672 tx_corr_coeff
[(i
* 2) + 1][1] =
673 AR_PHY_TX_IQCAL_CORR_COEFF_B1(i
);
675 tx_corr_coeff
[i
* 2][2] =
676 tx_corr_coeff
[(i
* 2) + 1][2] =
677 AR_PHY_TX_IQCAL_CORR_COEFF_B2(i
);
681 /* Load the average of 2 passes */
682 for (i
= 0; i
< AR9300_MAX_CHAINS
; i
++) {
683 if (!(ah
->txchainmask
& (1 << i
)))
685 nmeasurement
= REG_READ_FIELD(ah
,
686 AR_PHY_TX_IQCAL_STATUS_B0
,
687 AR_PHY_CALIBRATED_GAINS_0
);
689 if (nmeasurement
> MAX_MEASUREMENT
)
690 nmeasurement
= MAX_MEASUREMENT
;
692 /* detect outlier only if nmeasurement > 1 */
693 if (nmeasurement
> 1) {
694 /* Detect magnitude outlier */
695 ar9003_hw_detect_outlier(coeff
->mag_coeff
[i
],
696 nmeasurement
, MAX_MAG_DELTA
);
698 /* Detect phase outlier */
699 ar9003_hw_detect_outlier(coeff
->phs_coeff
[i
],
700 nmeasurement
, MAX_PHS_DELTA
);
703 for (im
= 0; im
< nmeasurement
; im
++) {
705 coeff
->iqc_coeff
[0] = (coeff
->mag_coeff
[i
][im
] & 0x7f) |
706 ((coeff
->phs_coeff
[i
][im
] & 0x7f) << 7);
709 REG_RMW_FIELD(ah
, tx_corr_coeff
[im
][i
],
710 AR_PHY_TX_IQCAL_CORR_COEFF_00_COEFF_TABLE
,
711 coeff
->iqc_coeff
[0]);
713 REG_RMW_FIELD(ah
, tx_corr_coeff
[im
][i
],
714 AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE
,
715 coeff
->iqc_coeff
[0]);
718 caldata
->tx_corr_coeff
[im
][i
] =
722 caldata
->num_measures
[i
] = nmeasurement
;
725 REG_RMW_FIELD(ah
, AR_PHY_TX_IQCAL_CONTROL_3
,
726 AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN
, 0x1);
727 REG_RMW_FIELD(ah
, AR_PHY_RX_IQCAL_CORR_B0
,
728 AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN
, 0x1);
731 caldata
->done_txiqcal_once
= is_reusable
;
736 static bool ar9003_hw_tx_iq_cal_run(struct ath_hw
*ah
)
738 struct ath_common
*common
= ath9k_hw_common(ah
);
741 tx_gain_forced
= REG_READ_FIELD(ah
, AR_PHY_TX_FORCED_GAIN
,
742 AR_PHY_TXGAIN_FORCE
);
744 REG_RMW_FIELD(ah
, AR_PHY_TX_FORCED_GAIN
,
745 AR_PHY_TXGAIN_FORCE
, 0);
747 REG_RMW_FIELD(ah
, AR_PHY_TX_IQCAL_START
,
748 AR_PHY_TX_IQCAL_START_DO_CAL
, 1);
750 if (!ath9k_hw_wait(ah
, AR_PHY_TX_IQCAL_START
,
751 AR_PHY_TX_IQCAL_START_DO_CAL
, 0,
753 ath_dbg(common
, CALIBRATE
, "Tx IQ Cal is not completed\n");
759 static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw
*ah
, bool is_reusable
)
761 struct ath_common
*common
= ath9k_hw_common(ah
);
762 const u32 txiqcal_status
[AR9300_MAX_CHAINS
] = {
763 AR_PHY_TX_IQCAL_STATUS_B0
,
764 AR_PHY_TX_IQCAL_STATUS_B1
,
765 AR_PHY_TX_IQCAL_STATUS_B2
,
767 const u_int32_t chan_info_tab
[] = {
768 AR_PHY_CHAN_INFO_TAB_0
,
769 AR_PHY_CHAN_INFO_TAB_1
,
770 AR_PHY_CHAN_INFO_TAB_2
,
777 for (i
= 0; i
< AR9300_MAX_CHAINS
; i
++) {
778 if (!(ah
->txchainmask
& (1 << i
)))
781 nmeasurement
= REG_READ_FIELD(ah
,
782 AR_PHY_TX_IQCAL_STATUS_B0
,
783 AR_PHY_CALIBRATED_GAINS_0
);
784 if (nmeasurement
> MAX_MEASUREMENT
)
785 nmeasurement
= MAX_MEASUREMENT
;
787 for (im
= 0; im
< nmeasurement
; im
++) {
788 ath_dbg(common
, CALIBRATE
,
789 "Doing Tx IQ Cal for chain %d\n", i
);
791 if (REG_READ(ah
, txiqcal_status
[i
]) &
792 AR_PHY_TX_IQCAL_STATUS_FAILED
) {
793 ath_dbg(common
, CALIBRATE
,
794 "Tx IQ Cal failed for chain %d\n", i
);
798 for (j
= 0; j
< 3; j
++) {
799 u32 idx
= 2 * j
, offset
= 4 * (3 * im
+ j
);
802 AR_PHY_CHAN_INFO_MEMORY
,
803 AR_PHY_CHAN_INFO_TAB_S2_READ
,
807 iq_res
[idx
] = REG_READ(ah
,
812 AR_PHY_CHAN_INFO_MEMORY
,
813 AR_PHY_CHAN_INFO_TAB_S2_READ
,
817 iq_res
[idx
+ 1] = 0xffff & REG_READ(ah
,
818 chan_info_tab
[i
] + offset
);
820 ath_dbg(common
, CALIBRATE
,
821 "IQ_RES[%d]=0x%x IQ_RES[%d]=0x%x\n",
822 idx
, iq_res
[idx
], idx
+ 1,
826 if (!ar9003_hw_calc_iq_corr(ah
, i
, iq_res
,
828 ath_dbg(common
, CALIBRATE
,
829 "Failed in calculation of IQ correction\n");
833 coeff
.mag_coeff
[i
][im
] = coeff
.iqc_coeff
[0] & 0x7f;
834 coeff
.phs_coeff
[i
][im
] =
835 (coeff
.iqc_coeff
[0] >> 7) & 0x7f;
837 if (coeff
.mag_coeff
[i
][im
] > 63)
838 coeff
.mag_coeff
[i
][im
] -= 128;
839 if (coeff
.phs_coeff
[i
][im
] > 63)
840 coeff
.phs_coeff
[i
][im
] -= 128;
843 ar9003_hw_tx_iqcal_load_avg_2_passes(ah
, &coeff
, is_reusable
);
848 ath_dbg(common
, CALIBRATE
, "Tx IQ Cal failed\n");
852 static void ar9003_hw_tx_iq_cal_reload(struct ath_hw
*ah
)
854 struct ath9k_hw_cal_data
*caldata
= ah
->caldata
;
855 u32 tx_corr_coeff
[MAX_MEASUREMENT
][AR9300_MAX_CHAINS
];
858 memset(tx_corr_coeff
, 0, sizeof(tx_corr_coeff
));
859 for (i
= 0; i
< MAX_MEASUREMENT
/ 2; i
++) {
860 tx_corr_coeff
[i
* 2][0] = tx_corr_coeff
[(i
* 2) + 1][0] =
861 AR_PHY_TX_IQCAL_CORR_COEFF_B0(i
);
862 if (!AR_SREV_9485(ah
)) {
863 tx_corr_coeff
[i
* 2][1] =
864 tx_corr_coeff
[(i
* 2) + 1][1] =
865 AR_PHY_TX_IQCAL_CORR_COEFF_B1(i
);
867 tx_corr_coeff
[i
* 2][2] =
868 tx_corr_coeff
[(i
* 2) + 1][2] =
869 AR_PHY_TX_IQCAL_CORR_COEFF_B2(i
);
873 for (i
= 0; i
< AR9300_MAX_CHAINS
; i
++) {
874 if (!(ah
->txchainmask
& (1 << i
)))
877 for (im
= 0; im
< caldata
->num_measures
[i
]; im
++) {
879 REG_RMW_FIELD(ah
, tx_corr_coeff
[im
][i
],
880 AR_PHY_TX_IQCAL_CORR_COEFF_00_COEFF_TABLE
,
881 caldata
->tx_corr_coeff
[im
][i
]);
883 REG_RMW_FIELD(ah
, tx_corr_coeff
[im
][i
],
884 AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE
,
885 caldata
->tx_corr_coeff
[im
][i
]);
889 REG_RMW_FIELD(ah
, AR_PHY_TX_IQCAL_CONTROL_3
,
890 AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN
, 0x1);
891 REG_RMW_FIELD(ah
, AR_PHY_RX_IQCAL_CORR_B0
,
892 AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN
, 0x1);
895 static void ar9003_hw_manual_peak_cal(struct ath_hw
*ah
, u8 chain
, bool is_2g
)
897 int offset
[8], total
= 0, test
;
900 REG_RMW_FIELD(ah
, AR_PHY_65NM_RXRF_GAINSTAGES(chain
),
901 AR_PHY_65NM_RXRF_GAINSTAGES_RX_OVERRIDE
, 0x1);
902 REG_RMW_FIELD(ah
, AR_PHY_65NM_RXRF_GAINSTAGES(chain
),
903 AR_PHY_65NM_RXRF_GAINSTAGES_LNAON_CALDC
, 0x0);
905 REG_RMW_FIELD(ah
, AR_PHY_65NM_RXRF_GAINSTAGES(chain
),
906 AR_PHY_65NM_RXRF_GAINSTAGES_LNA2G_GAIN_OVR
, 0x0);
908 REG_RMW_FIELD(ah
, AR_PHY_65NM_RXRF_GAINSTAGES(chain
),
909 AR_PHY_65NM_RXRF_GAINSTAGES_LNA5G_GAIN_OVR
, 0x0);
911 REG_RMW_FIELD(ah
, AR_PHY_65NM_RXTX2(chain
),
912 AR_PHY_65NM_RXTX2_RXON_OVR
, 0x1);
913 REG_RMW_FIELD(ah
, AR_PHY_65NM_RXTX2(chain
),
914 AR_PHY_65NM_RXTX2_RXON
, 0x0);
916 REG_RMW_FIELD(ah
, AR_PHY_65NM_RXRF_AGC(chain
),
917 AR_PHY_65NM_RXRF_AGC_AGC_OVERRIDE
, 0x1);
918 REG_RMW_FIELD(ah
, AR_PHY_65NM_RXRF_AGC(chain
),
919 AR_PHY_65NM_RXRF_AGC_AGC_ON_OVR
, 0x1);
920 REG_RMW_FIELD(ah
, AR_PHY_65NM_RXRF_AGC(chain
),
921 AR_PHY_65NM_RXRF_AGC_AGC_CAL_OVR
, 0x1);
923 REG_RMW_FIELD(ah
, AR_PHY_65NM_RXRF_AGC(chain
),
924 AR_PHY_65NM_RXRF_AGC_AGC2G_DBDAC_OVR
, 0x0);
926 REG_RMW_FIELD(ah
, AR_PHY_65NM_RXRF_AGC(chain
),
927 AR_PHY_65NM_RXRF_AGC_AGC5G_DBDAC_OVR
, 0x0);
929 for (i
= 6; i
> 0; i
--) {
930 offset
[i
] = BIT(i
- 1);
931 test
= total
+ offset
[i
];
934 REG_RMW_FIELD(ah
, AR_PHY_65NM_RXRF_AGC(chain
),
935 AR_PHY_65NM_RXRF_AGC_AGC2G_CALDAC_OVR
,
938 REG_RMW_FIELD(ah
, AR_PHY_65NM_RXRF_AGC(chain
),
939 AR_PHY_65NM_RXRF_AGC_AGC5G_CALDAC_OVR
,
942 agc_out
= REG_READ_FIELD(ah
, AR_PHY_65NM_RXRF_AGC(chain
),
943 AR_PHY_65NM_RXRF_AGC_AGC_OUT
);
944 offset
[i
] = (agc_out
) ? 0 : 1;
945 total
+= (offset
[i
] << (i
- 1));
949 REG_RMW_FIELD(ah
, AR_PHY_65NM_RXRF_AGC(chain
),
950 AR_PHY_65NM_RXRF_AGC_AGC2G_CALDAC_OVR
, total
);
952 REG_RMW_FIELD(ah
, AR_PHY_65NM_RXRF_AGC(chain
),
953 AR_PHY_65NM_RXRF_AGC_AGC5G_CALDAC_OVR
, total
);
955 REG_RMW_FIELD(ah
, AR_PHY_65NM_RXRF_GAINSTAGES(chain
),
956 AR_PHY_65NM_RXRF_GAINSTAGES_RX_OVERRIDE
, 0);
957 REG_RMW_FIELD(ah
, AR_PHY_65NM_RXTX2(chain
),
958 AR_PHY_65NM_RXTX2_RXON_OVR
, 0);
959 REG_RMW_FIELD(ah
, AR_PHY_65NM_RXRF_AGC(chain
),
960 AR_PHY_65NM_RXRF_AGC_AGC_CAL_OVR
, 0);
963 static void ar9003_hw_do_manual_peak_cal(struct ath_hw
*ah
,
964 struct ath9k_channel
*chan
)
968 if (!AR_SREV_9462(ah
) && !AR_SREV_9565(ah
) && !AR_SREV_9485(ah
))
971 for (i
= 0; i
< AR9300_MAX_CHAINS
; i
++) {
972 if (!(ah
->rxchainmask
& (1 << i
)))
974 ar9003_hw_manual_peak_cal(ah
, i
, IS_CHAN_2GHZ(chan
));
978 static void ar9003_hw_cl_cal_post_proc(struct ath_hw
*ah
, bool is_reusable
)
980 u32 cl_idx
[AR9300_MAX_CHAINS
] = { AR_PHY_CL_TAB_0
,
983 struct ath9k_hw_cal_data
*caldata
= ah
->caldata
;
984 bool txclcal_done
= false;
987 if (!caldata
|| !(ah
->enabled_cals
& TX_CL_CAL
))
990 txclcal_done
= !!(REG_READ(ah
, AR_PHY_AGC_CONTROL
) &
991 AR_PHY_AGC_CONTROL_CLC_SUCCESS
);
993 if (caldata
->done_txclcal_once
) {
994 for (i
= 0; i
< AR9300_MAX_CHAINS
; i
++) {
995 if (!(ah
->txchainmask
& (1 << i
)))
997 for (j
= 0; j
< MAX_CL_TAB_ENTRY
; j
++)
998 REG_WRITE(ah
, CL_TAB_ENTRY(cl_idx
[i
]),
999 caldata
->tx_clcal
[i
][j
]);
1001 } else if (is_reusable
&& txclcal_done
) {
1002 for (i
= 0; i
< AR9300_MAX_CHAINS
; i
++) {
1003 if (!(ah
->txchainmask
& (1 << i
)))
1005 for (j
= 0; j
< MAX_CL_TAB_ENTRY
; j
++)
1006 caldata
->tx_clcal
[i
][j
] =
1007 REG_READ(ah
, CL_TAB_ENTRY(cl_idx
[i
]));
1009 caldata
->done_txclcal_once
= true;
1013 static bool ar9003_hw_init_cal(struct ath_hw
*ah
,
1014 struct ath9k_channel
*chan
)
1016 struct ath_common
*common
= ath9k_hw_common(ah
);
1017 struct ath9k_hw_cal_data
*caldata
= ah
->caldata
;
1018 bool txiqcal_done
= false;
1019 bool is_reusable
= true, status
= true;
1020 bool run_rtt_cal
= false, run_agc_cal
, sep_iq_cal
= false;
1021 bool rtt
= !!(ah
->caps
.hw_caps
& ATH9K_HW_CAP_RTT
);
1022 u32 agc_ctrl
= 0, agc_supp_cals
= AR_PHY_AGC_CONTROL_OFFSET_CAL
|
1023 AR_PHY_AGC_CONTROL_FLTR_CAL
|
1024 AR_PHY_AGC_CONTROL_PKDET_CAL
;
1026 /* Use chip chainmask only for calibration */
1027 ar9003_hw_set_chain_masks(ah
, ah
->caps
.rx_chainmask
, ah
->caps
.tx_chainmask
);
1030 if (!ar9003_hw_rtt_restore(ah
, chan
))
1034 ath_dbg(common
, CALIBRATE
, "RTT calibration to be done\n");
1037 run_agc_cal
= run_rtt_cal
;
1040 ar9003_hw_rtt_enable(ah
);
1041 ar9003_hw_rtt_set_mask(ah
, 0x00);
1042 ar9003_hw_rtt_clear_hist(ah
);
1045 if (rtt
&& !run_rtt_cal
) {
1046 agc_ctrl
= REG_READ(ah
, AR_PHY_AGC_CONTROL
);
1047 agc_supp_cals
&= agc_ctrl
;
1048 agc_ctrl
&= ~(AR_PHY_AGC_CONTROL_OFFSET_CAL
|
1049 AR_PHY_AGC_CONTROL_FLTR_CAL
|
1050 AR_PHY_AGC_CONTROL_PKDET_CAL
);
1051 REG_WRITE(ah
, AR_PHY_AGC_CONTROL
, agc_ctrl
);
1054 if (ah
->enabled_cals
& TX_CL_CAL
) {
1055 if (caldata
&& caldata
->done_txclcal_once
)
1056 REG_CLR_BIT(ah
, AR_PHY_CL_CAL_CTL
,
1057 AR_PHY_CL_CAL_ENABLE
);
1059 REG_SET_BIT(ah
, AR_PHY_CL_CAL_CTL
,
1060 AR_PHY_CL_CAL_ENABLE
);
1065 if ((IS_CHAN_HALF_RATE(chan
) || IS_CHAN_QUARTER_RATE(chan
)) ||
1066 !(ah
->enabled_cals
& TX_IQ_CAL
))
1069 /* Do Tx IQ Calibration */
1070 REG_RMW_FIELD(ah
, AR_PHY_TX_IQCAL_CONTROL_1
,
1071 AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT
,
1075 * For AR9485 or later chips, TxIQ cal runs as part of
1078 if (ah
->enabled_cals
& TX_IQ_ON_AGC_CAL
) {
1079 if (caldata
&& !caldata
->done_txiqcal_once
)
1080 REG_SET_BIT(ah
, AR_PHY_TX_IQCAL_CONTROL_0
,
1081 AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL
);
1083 REG_CLR_BIT(ah
, AR_PHY_TX_IQCAL_CONTROL_0
,
1084 AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL
);
1085 txiqcal_done
= run_agc_cal
= true;
1086 } else if (caldata
&& !caldata
->done_txiqcal_once
) {
1092 if (ath9k_hw_mci_is_enabled(ah
) && IS_CHAN_2GHZ(chan
) && run_agc_cal
)
1093 ar9003_mci_init_cal_req(ah
, &is_reusable
);
1096 txiqcal_done
= ar9003_hw_tx_iq_cal_run(ah
);
1097 REG_WRITE(ah
, AR_PHY_ACTIVE
, AR_PHY_ACTIVE_DIS
);
1099 REG_WRITE(ah
, AR_PHY_ACTIVE
, AR_PHY_ACTIVE_EN
);
1102 if (run_agc_cal
|| !(ah
->ah_flags
& AH_FASTCC
)) {
1103 /* Calibrate the AGC */
1104 REG_WRITE(ah
, AR_PHY_AGC_CONTROL
,
1105 REG_READ(ah
, AR_PHY_AGC_CONTROL
) |
1106 AR_PHY_AGC_CONTROL_CAL
);
1108 /* Poll for offset calibration complete */
1109 status
= ath9k_hw_wait(ah
, AR_PHY_AGC_CONTROL
,
1110 AR_PHY_AGC_CONTROL_CAL
,
1111 0, AH_WAIT_TIMEOUT
);
1113 ar9003_hw_do_manual_peak_cal(ah
, chan
);
1116 if (ath9k_hw_mci_is_enabled(ah
) && IS_CHAN_2GHZ(chan
) && run_agc_cal
)
1117 ar9003_mci_init_cal_done(ah
);
1119 if (rtt
&& !run_rtt_cal
) {
1120 agc_ctrl
|= agc_supp_cals
;
1121 REG_WRITE(ah
, AR_PHY_AGC_CONTROL
, agc_ctrl
);
1126 ar9003_hw_rtt_disable(ah
);
1128 ath_dbg(common
, CALIBRATE
,
1129 "offset calibration failed to complete in %d ms; noisy environment?\n",
1130 AH_WAIT_TIMEOUT
/ 1000);
1135 ar9003_hw_tx_iq_cal_post_proc(ah
, is_reusable
);
1136 else if (caldata
&& caldata
->done_txiqcal_once
)
1137 ar9003_hw_tx_iq_cal_reload(ah
);
1139 ar9003_hw_cl_cal_post_proc(ah
, is_reusable
);
1141 if (run_rtt_cal
&& caldata
) {
1143 if (!ath9k_hw_rfbus_req(ah
))
1144 ath_err(ath9k_hw_common(ah
),
1145 "Could not stop baseband\n");
1147 ar9003_hw_rtt_fill_hist(ah
);
1149 ath9k_hw_rfbus_done(ah
);
1152 ar9003_hw_rtt_disable(ah
);
1155 /* Revert chainmask to runtime parameters */
1156 ar9003_hw_set_chain_masks(ah
, ah
->rxchainmask
, ah
->txchainmask
);
1158 /* Initialize list pointers */
1159 ah
->cal_list
= ah
->cal_list_last
= ah
->cal_list_curr
= NULL
;
1161 INIT_CAL(&ah
->iq_caldata
);
1162 INSERT_CAL(ah
, &ah
->iq_caldata
);
1163 ath_dbg(common
, CALIBRATE
, "enabling IQ Calibration\n");
1165 /* Initialize current pointer to first element in list */
1166 ah
->cal_list_curr
= ah
->cal_list
;
1168 if (ah
->cal_list_curr
)
1169 ath9k_hw_reset_calibration(ah
, ah
->cal_list_curr
);
1172 caldata
->CalValid
= 0;
1177 void ar9003_hw_attach_calib_ops(struct ath_hw
*ah
)
1179 struct ath_hw_private_ops
*priv_ops
= ath9k_hw_private_ops(ah
);
1180 struct ath_hw_ops
*ops
= ath9k_hw_ops(ah
);
1182 priv_ops
->init_cal_settings
= ar9003_hw_init_cal_settings
;
1183 priv_ops
->init_cal
= ar9003_hw_init_cal
;
1184 priv_ops
->setup_calibration
= ar9003_hw_setup_calibration
;
1186 ops
->calibrate
= ar9003_hw_calibrate
;