Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / ipxe / src / drivers / net / ath / ath9k / ath9k_ar9003_calib.c
1 /*
2  * Copyright (c) 2010-2011 Atheros Communications Inc.
3  *
4  * Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
5  * Original from Linux kernel 3.0.1
6  *
7  * Permission to use, copy, modify, and/or distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19
20 #include <ipxe/io.h>
21
22 #include "hw.h"
23 #include "hw-ops.h"
24 #include "ar9003_phy.h"
25
26 #define MAX_MEASUREMENT 8
27 #define MAX_MAG_DELTA   11
28 #define MAX_PHS_DELTA   10
29
30 struct coeff {
31         int mag_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT];
32         int phs_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT];
33         int iqc_coeff[2];
34 };
35
36 enum ar9003_cal_types {
37         IQ_MISMATCH_CAL = BIT(0),
38         TEMP_COMP_CAL = BIT(1),
39 };
40
41 static void ar9003_hw_setup_calibration(struct ath_hw *ah,
42                                         struct ath9k_cal_list *currCal)
43 {
44         /* Select calibration to run */
45         switch (currCal->calData->calType) {
46         case IQ_MISMATCH_CAL:
47                 /*
48                  * Start calibration with
49                  * 2^(INIT_IQCAL_LOG_COUNT_MAX+1) samples
50                  */
51                 REG_RMW_FIELD(ah, AR_PHY_TIMING4,
52                               AR_PHY_TIMING4_IQCAL_LOG_COUNT_MAX,
53                 currCal->calData->calCountMax);
54                 REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ);
55
56                 DBG2("ath9k: "
57                         "starting IQ Mismatch Calibration\n");
58
59                 /* Kick-off cal */
60                 REG_SET_BIT(ah, AR_PHY_TIMING4, AR_PHY_TIMING4_DO_CAL);
61                 break;
62         case TEMP_COMP_CAL:
63                 REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_THERM,
64                               AR_PHY_65NM_CH0_THERM_LOCAL, 1);
65                 REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_THERM,
66                               AR_PHY_65NM_CH0_THERM_START, 1);
67
68                 DBG2("ath9k: "
69                         "starting Temperature Compensation Calibration\n");
70                 break;
71         }
72 }
73
74 /*
75  * Generic calibration routine.
76  * Recalibrate the lower PHY chips to account for temperature/environment
77  * changes.
78  */
79 static int ar9003_hw_per_calibration(struct ath_hw *ah,
80                                       struct ath9k_channel *ichan __unused,
81                                       u8 rxchainmask,
82                                       struct ath9k_cal_list *currCal)
83 {
84         struct ath9k_hw_cal_data *caldata = ah->caldata;
85         /* Cal is assumed not done until explicitly set below */
86         int iscaldone = 0;
87
88         /* Calibration in progress. */
89         if (currCal->calState == CAL_RUNNING) {
90                 /* Check to see if it has finished. */
91                 if (!(REG_READ(ah, AR_PHY_TIMING4) & AR_PHY_TIMING4_DO_CAL)) {
92                         /*
93                         * Accumulate cal measures for active chains
94                         */
95                         currCal->calData->calCollect(ah);
96                         ah->cal_samples++;
97
98                         if (ah->cal_samples >=
99                             currCal->calData->calNumSamples) {
100                                 unsigned int i, numChains = 0;
101                                 for (i = 0; i < AR9300_MAX_CHAINS; i++) {
102                                         if (rxchainmask & (1 << i))
103                                                 numChains++;
104                                 }
105
106                                 /*
107                                 * Process accumulated data
108                                 */
109                                 currCal->calData->calPostProc(ah, numChains);
110
111                                 /* Calibration has finished. */
112                                 caldata->CalValid |= currCal->calData->calType;
113                                 currCal->calState = CAL_DONE;
114                                 iscaldone = 1;
115                         } else {
116                         /*
117                          * Set-up collection of another sub-sample until we
118                          * get desired number
119                          */
120                         ar9003_hw_setup_calibration(ah, currCal);
121                         }
122                 }
123         } else if (!(caldata->CalValid & currCal->calData->calType)) {
124                 /* If current cal is marked invalid in channel, kick it off */
125                 ath9k_hw_reset_calibration(ah, currCal);
126         }
127
128         return iscaldone;
129 }
130
131 static int ar9003_hw_calibrate(struct ath_hw *ah,
132                                 struct ath9k_channel *chan,
133                                 u8 rxchainmask,
134                                 int longcal)
135 {
136         int iscaldone = 1;
137         struct ath9k_cal_list *currCal = ah->cal_list_curr;
138
139         /*
140          * For given calibration:
141          * 1. Call generic cal routine
142          * 2. When this cal is done (isCalDone) if we have more cals waiting
143          *    (eg after reset), mask this to upper layers by not propagating
144          *    isCalDone if it is set to TRUE.
145          *    Instead, change isCalDone to FALSE and setup the waiting cal(s)
146          *    to be run.
147          */
148         if (currCal &&
149             (currCal->calState == CAL_RUNNING ||
150              currCal->calState == CAL_WAITING)) {
151                 iscaldone = ar9003_hw_per_calibration(ah, chan,
152                                                       rxchainmask, currCal);
153                 if (iscaldone) {
154                         ah->cal_list_curr = currCal = currCal->calNext;
155
156                         if (currCal->calState == CAL_WAITING) {
157                                 iscaldone = 0;
158                                 ath9k_hw_reset_calibration(ah, currCal);
159                         }
160                 }
161         }
162
163         /* Do NF cal only at longer intervals */
164         if (longcal) {
165                 /*
166                  * Get the value from the previous NF cal and update
167                  * history buffer.
168                  */
169                 ath9k_hw_getnf(ah, chan);
170
171                 /*
172                  * Load the NF from history buffer of the current channel.
173                  * NF is slow time-variant, so it is OK to use a historical
174                  * value.
175                  */
176                 ath9k_hw_loadnf(ah, ah->curchan);
177
178                 /* start NF calibration, without updating BB NF register */
179                 ath9k_hw_start_nfcal(ah, 0);
180         }
181
182         return iscaldone;
183 }
184
185 static void ar9003_hw_iqcal_collect(struct ath_hw *ah)
186 {
187         int i;
188
189         /* Accumulate IQ cal measures for active chains */
190         for (i = 0; i < AR5416_MAX_CHAINS; i++) {
191                 if (ah->txchainmask & BIT(i)) {
192                         ah->totalPowerMeasI[i] +=
193                                 REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
194                         ah->totalPowerMeasQ[i] +=
195                                 REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
196                         ah->totalIqCorrMeas[i] +=
197                                 (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
198                         DBG2("ath9k: "
199                                 "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
200                                 ah->cal_samples, i, ah->totalPowerMeasI[i],
201                                 ah->totalPowerMeasQ[i],
202                                 ah->totalIqCorrMeas[i]);
203                 }
204         }
205 }
206
207 static void ar9003_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
208 {
209         u32 powerMeasQ, powerMeasI, iqCorrMeas;
210         u32 qCoffDenom, iCoffDenom;
211         int32_t qCoff, iCoff;
212         int iqCorrNeg, i;
213         static const uint32_t offset_array[3] = {
214                 AR_PHY_RX_IQCAL_CORR_B0,
215                 AR_PHY_RX_IQCAL_CORR_B1,
216                 AR_PHY_RX_IQCAL_CORR_B2,
217         };
218
219         for (i = 0; i < numChains; i++) {
220                 powerMeasI = ah->totalPowerMeasI[i];
221                 powerMeasQ = ah->totalPowerMeasQ[i];
222                 iqCorrMeas = ah->totalIqCorrMeas[i];
223
224                 DBG2("ath9k: "
225                         "Starting IQ Cal and Correction for Chain %d\n",
226                         i);
227
228                 DBG2("ath9k: "
229                         "Orignal: Chn %diq_corr_meas = 0x%08x\n",
230                         i, ah->totalIqCorrMeas[i]);
231
232                 iqCorrNeg = 0;
233
234                 if (iqCorrMeas > 0x80000000) {
235                         iqCorrMeas = (0xffffffff - iqCorrMeas) + 1;
236                         iqCorrNeg = 1;
237                 }
238
239                 DBG2("ath9k: "
240                         "Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI);
241                 DBG2("ath9k: "
242                         "Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ);
243                 DBG2("ath9k: iqCorrNeg is 0x%08x\n",
244                         iqCorrNeg);
245
246                 iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 256;
247                 qCoffDenom = powerMeasQ / 64;
248
249                 if ((iCoffDenom != 0) && (qCoffDenom != 0)) {
250                         iCoff = iqCorrMeas / iCoffDenom;
251                         qCoff = powerMeasI / qCoffDenom - 64;
252                         DBG2("ath9k: "
253                                 "Chn %d iCoff = 0x%08x\n", i, iCoff);
254                         DBG2("ath9k: "
255                                 "Chn %d qCoff = 0x%08x\n", i, qCoff);
256
257                         /* Force bounds on iCoff */
258                         if (iCoff >= 63)
259                                 iCoff = 63;
260                         else if (iCoff <= -63)
261                                 iCoff = -63;
262
263                         /* Negate iCoff if iqCorrNeg == 0 */
264                         if (iqCorrNeg == 0x0)
265                                 iCoff = -iCoff;
266
267                         /* Force bounds on qCoff */
268                         if (qCoff >= 63)
269                                 qCoff = 63;
270                         else if (qCoff <= -63)
271                                 qCoff = -63;
272
273                         iCoff = iCoff & 0x7f;
274                         qCoff = qCoff & 0x7f;
275
276                         DBG2("ath9k: "
277                                 "Chn %d : iCoff = 0x%x  qCoff = 0x%x\n",
278                                 i, iCoff, qCoff);
279                         DBG2("ath9k: "
280                                 "Register offset (0x%04x) before update = 0x%x\n",
281                                 offset_array[i],
282                                 REG_READ(ah, offset_array[i]));
283
284                         REG_RMW_FIELD(ah, offset_array[i],
285                                       AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF,
286                                       iCoff);
287                         REG_RMW_FIELD(ah, offset_array[i],
288                                       AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF,
289                                       qCoff);
290                         DBG2("ath9k: "
291                                 "Register offset (0x%04x) QI COFF (bitfields 0x%08x) after update = 0x%x\n",
292                                 offset_array[i],
293                                 AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF,
294                                 REG_READ(ah, offset_array[i]));
295                         DBG2("ath9k: "
296                                 "Register offset (0x%04x) QQ COFF (bitfields 0x%08x) after update = 0x%x\n",
297                                 offset_array[i],
298                                 AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF,
299                                 REG_READ(ah, offset_array[i]));
300
301                         DBG2("ath9k: "
302                                 "IQ Cal and Correction done for Chain %d\n", i);
303                 }
304         }
305
306         REG_SET_BIT(ah, AR_PHY_RX_IQCAL_CORR_B0,
307                     AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE);
308         DBG2("ath9k: "
309                 "IQ Cal and Correction (offset 0x%04x) enabled (bit position 0x%08x). New Value 0x%08x\n",
310                 (unsigned) (AR_PHY_RX_IQCAL_CORR_B0),
311                 AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE,
312                 REG_READ(ah, AR_PHY_RX_IQCAL_CORR_B0));
313 }
314
315 static const struct ath9k_percal_data iq_cal_single_sample = {
316         IQ_MISMATCH_CAL,
317         MIN_CAL_SAMPLES,
318         PER_MAX_LOG_COUNT,
319         ar9003_hw_iqcal_collect,
320         ar9003_hw_iqcalibrate
321 };
322
323 static void ar9003_hw_init_cal_settings(struct ath_hw *ah)
324 {
325         ah->iq_caldata.calData = &iq_cal_single_sample;
326 }
327
328 /*
329  * solve 4x4 linear equation used in loopback iq cal.
330  */
331 static int ar9003_hw_solve_iq_cal(struct ath_hw *ah __unused,
332                                    s32 sin_2phi_1,
333                                    s32 cos_2phi_1,
334                                    s32 sin_2phi_2,
335                                    s32 cos_2phi_2,
336                                    s32 mag_a0_d0,
337                                    s32 phs_a0_d0,
338                                    s32 mag_a1_d0,
339                                    s32 phs_a1_d0,
340                                    s32 solved_eq[])
341 {
342         s32 f1 = cos_2phi_1 - cos_2phi_2,
343             f3 = sin_2phi_1 - sin_2phi_2,
344             f2;
345         s32 mag_tx, phs_tx, mag_rx, phs_rx;
346         const s32 result_shift = 1 << 15;
347
348         f2 = (f1 * f1 + f3 * f3) / result_shift;
349
350         if (!f2) {
351                 DBG("ath9k: Divide by 0\n");
352                 return 0;
353         }
354
355         /* mag mismatch, tx */
356         mag_tx = f1 * (mag_a0_d0  - mag_a1_d0) + f3 * (phs_a0_d0 - phs_a1_d0);
357         /* phs mismatch, tx */
358         phs_tx = f3 * (-mag_a0_d0 + mag_a1_d0) + f1 * (phs_a0_d0 - phs_a1_d0);
359
360         mag_tx = (mag_tx / f2);
361         phs_tx = (phs_tx / f2);
362
363         /* mag mismatch, rx */
364         mag_rx = mag_a0_d0 - (cos_2phi_1 * mag_tx + sin_2phi_1 * phs_tx) /
365                  result_shift;
366         /* phs mismatch, rx */
367         phs_rx = phs_a0_d0 + (sin_2phi_1 * mag_tx - cos_2phi_1 * phs_tx) /
368                  result_shift;
369
370         solved_eq[0] = mag_tx;
371         solved_eq[1] = phs_tx;
372         solved_eq[2] = mag_rx;
373         solved_eq[3] = phs_rx;
374
375         return 1;
376 }
377
378 static s32 ar9003_hw_find_mag_approx(struct ath_hw *ah __unused, s32 in_re, s32 in_im)
379 {
380         s32 abs_i = abs(in_re),
381             abs_q = abs(in_im),
382             max_abs, min_abs;
383
384         if (abs_i > abs_q) {
385                 max_abs = abs_i;
386                 min_abs = abs_q;
387         } else {
388                 max_abs = abs_q;
389                 min_abs = abs_i;
390         }
391
392         return max_abs - (max_abs / 32) + (min_abs / 8) + (min_abs / 4);
393 }
394
395 #define DELPT 32
396
397 static int ar9003_hw_calc_iq_corr(struct ath_hw *ah,
398                                    s32 chain_idx,
399                                    const s32 iq_res[],
400                                    s32 iqc_coeff[])
401 {
402         s32 i2_m_q2_a0_d0, i2_p_q2_a0_d0, iq_corr_a0_d0,
403             i2_m_q2_a0_d1, i2_p_q2_a0_d1, iq_corr_a0_d1,
404             i2_m_q2_a1_d0, i2_p_q2_a1_d0, iq_corr_a1_d0,
405             i2_m_q2_a1_d1, i2_p_q2_a1_d1, iq_corr_a1_d1;
406         s32 mag_a0_d0, mag_a1_d0, mag_a0_d1, mag_a1_d1,
407             phs_a0_d0, phs_a1_d0, phs_a0_d1, phs_a1_d1,
408             sin_2phi_1, cos_2phi_1,
409             sin_2phi_2, cos_2phi_2;
410         s32 mag_tx, phs_tx, mag_rx, phs_rx;
411         s32 solved_eq[4], mag_corr_tx, phs_corr_tx, mag_corr_rx, phs_corr_rx,
412             q_q_coff, q_i_coff;
413         const s32 res_scale = 1 << 15;
414         const s32 delpt_shift = 1 << 8;
415         s32 mag1, mag2;
416
417         i2_m_q2_a0_d0 = iq_res[0] & 0xfff;
418         i2_p_q2_a0_d0 = (iq_res[0] >> 12) & 0xfff;
419         iq_corr_a0_d0 = ((iq_res[0] >> 24) & 0xff) + ((iq_res[1] & 0xf) << 8);
420
421         if (i2_m_q2_a0_d0 > 0x800)
422                 i2_m_q2_a0_d0 = -((0xfff - i2_m_q2_a0_d0) + 1);
423
424         if (i2_p_q2_a0_d0 > 0x800)
425                 i2_p_q2_a0_d0 = -((0xfff - i2_p_q2_a0_d0) + 1);
426
427         if (iq_corr_a0_d0 > 0x800)
428                 iq_corr_a0_d0 = -((0xfff - iq_corr_a0_d0) + 1);
429
430         i2_m_q2_a0_d1 = (iq_res[1] >> 4) & 0xfff;
431         i2_p_q2_a0_d1 = (iq_res[2] & 0xfff);
432         iq_corr_a0_d1 = (iq_res[2] >> 12) & 0xfff;
433
434         if (i2_m_q2_a0_d1 > 0x800)
435                 i2_m_q2_a0_d1 = -((0xfff - i2_m_q2_a0_d1) + 1);
436
437         if (i2_p_q2_a0_d1 > 0x800)
438                 i2_p_q2_a0_d1 = -((0xfff - i2_p_q2_a0_d1) + 1);
439
440         if (iq_corr_a0_d1 > 0x800)
441                 iq_corr_a0_d1 = -((0xfff - iq_corr_a0_d1) + 1);
442
443         i2_m_q2_a1_d0 = ((iq_res[2] >> 24) & 0xff) + ((iq_res[3] & 0xf) << 8);
444         i2_p_q2_a1_d0 = (iq_res[3] >> 4) & 0xfff;
445         iq_corr_a1_d0 = iq_res[4] & 0xfff;
446
447         if (i2_m_q2_a1_d0 > 0x800)
448                 i2_m_q2_a1_d0 = -((0xfff - i2_m_q2_a1_d0) + 1);
449
450         if (i2_p_q2_a1_d0 > 0x800)
451                 i2_p_q2_a1_d0 = -((0xfff - i2_p_q2_a1_d0) + 1);
452
453         if (iq_corr_a1_d0 > 0x800)
454                 iq_corr_a1_d0 = -((0xfff - iq_corr_a1_d0) + 1);
455
456         i2_m_q2_a1_d1 = (iq_res[4] >> 12) & 0xfff;
457         i2_p_q2_a1_d1 = ((iq_res[4] >> 24) & 0xff) + ((iq_res[5] & 0xf) << 8);
458         iq_corr_a1_d1 = (iq_res[5] >> 4) & 0xfff;
459
460         if (i2_m_q2_a1_d1 > 0x800)
461                 i2_m_q2_a1_d1 = -((0xfff - i2_m_q2_a1_d1) + 1);
462
463         if (i2_p_q2_a1_d1 > 0x800)
464                 i2_p_q2_a1_d1 = -((0xfff - i2_p_q2_a1_d1) + 1);
465
466         if (iq_corr_a1_d1 > 0x800)
467                 iq_corr_a1_d1 = -((0xfff - iq_corr_a1_d1) + 1);
468
469         if ((i2_p_q2_a0_d0 == 0) || (i2_p_q2_a0_d1 == 0) ||
470             (i2_p_q2_a1_d0 == 0) || (i2_p_q2_a1_d1 == 0)) {
471                 DBG("ath9k: "
472                         "Divide by 0:\n"
473                         "a0_d0=%d\n"
474                         "a0_d1=%d\n"
475                         "a2_d0=%d\n"
476                         "a1_d1=%d\n",
477                         i2_p_q2_a0_d0, i2_p_q2_a0_d1,
478                         i2_p_q2_a1_d0, i2_p_q2_a1_d1);
479                 return 0;
480         }
481
482         mag_a0_d0 = (i2_m_q2_a0_d0 * res_scale) / i2_p_q2_a0_d0;
483         phs_a0_d0 = (iq_corr_a0_d0 * res_scale) / i2_p_q2_a0_d0;
484
485         mag_a0_d1 = (i2_m_q2_a0_d1 * res_scale) / i2_p_q2_a0_d1;
486         phs_a0_d1 = (iq_corr_a0_d1 * res_scale) / i2_p_q2_a0_d1;
487
488         mag_a1_d0 = (i2_m_q2_a1_d0 * res_scale) / i2_p_q2_a1_d0;
489         phs_a1_d0 = (iq_corr_a1_d0 * res_scale) / i2_p_q2_a1_d0;
490
491         mag_a1_d1 = (i2_m_q2_a1_d1 * res_scale) / i2_p_q2_a1_d1;
492         phs_a1_d1 = (iq_corr_a1_d1 * res_scale) / i2_p_q2_a1_d1;
493
494         /* w/o analog phase shift */
495         sin_2phi_1 = (((mag_a0_d0 - mag_a0_d1) * delpt_shift) / DELPT);
496         /* w/o analog phase shift */
497         cos_2phi_1 = (((phs_a0_d1 - phs_a0_d0) * delpt_shift) / DELPT);
498         /* w/  analog phase shift */
499         sin_2phi_2 = (((mag_a1_d0 - mag_a1_d1) * delpt_shift) / DELPT);
500         /* w/  analog phase shift */
501         cos_2phi_2 = (((phs_a1_d1 - phs_a1_d0) * delpt_shift) / DELPT);
502
503         /*
504          * force sin^2 + cos^2 = 1;
505          * find magnitude by approximation
506          */
507         mag1 = ar9003_hw_find_mag_approx(ah, cos_2phi_1, sin_2phi_1);
508         mag2 = ar9003_hw_find_mag_approx(ah, cos_2phi_2, sin_2phi_2);
509
510         if ((mag1 == 0) || (mag2 == 0)) {
511                 DBG("ath9k: "
512                         "Divide by 0: mag1=%d, mag2=%d\n",
513                         mag1, mag2);
514                 return 0;
515         }
516
517         /* normalization sin and cos by mag */
518         sin_2phi_1 = (sin_2phi_1 * res_scale / mag1);
519         cos_2phi_1 = (cos_2phi_1 * res_scale / mag1);
520         sin_2phi_2 = (sin_2phi_2 * res_scale / mag2);
521         cos_2phi_2 = (cos_2phi_2 * res_scale / mag2);
522
523         /* calculate IQ mismatch */
524         if (!ar9003_hw_solve_iq_cal(ah,
525                              sin_2phi_1, cos_2phi_1,
526                              sin_2phi_2, cos_2phi_2,
527                              mag_a0_d0, phs_a0_d0,
528                              mag_a1_d0,
529                              phs_a1_d0, solved_eq)) {
530                 DBG("ath9k: "
531                         "Call to ar9003_hw_solve_iq_cal() failed.\n");
532                 return 0;
533         }
534
535         mag_tx = solved_eq[0];
536         phs_tx = solved_eq[1];
537         mag_rx = solved_eq[2];
538         phs_rx = solved_eq[3];
539
540         DBG2("ath9k: "
541                 "chain %d: mag mismatch=%d phase mismatch=%d\n",
542                 chain_idx, mag_tx/res_scale, phs_tx/res_scale);
543
544         if (res_scale == mag_tx) {
545                 DBG("ath9k: "
546                         "Divide by 0: mag_tx=%d, res_scale=%d\n",
547                         mag_tx, res_scale);
548                 return 0;
549         }
550
551         /* calculate and quantize Tx IQ correction factor */
552         mag_corr_tx = (mag_tx * res_scale) / (res_scale - mag_tx);
553         phs_corr_tx = -phs_tx;
554
555         q_q_coff = (mag_corr_tx * 128 / res_scale);
556         q_i_coff = (phs_corr_tx * 256 / res_scale);
557
558         DBG2("ath9k: "
559                 "tx chain %d: mag corr=%d  phase corr=%d\n",
560                 chain_idx, q_q_coff, q_i_coff);
561
562         if (q_i_coff < -63)
563                 q_i_coff = -63;
564         if (q_i_coff > 63)
565                 q_i_coff = 63;
566         if (q_q_coff < -63)
567                 q_q_coff = -63;
568         if (q_q_coff > 63)
569                 q_q_coff = 63;
570
571         iqc_coeff[0] = (q_q_coff * 128) + q_i_coff;
572
573         DBG2("ath9k: "
574                 "tx chain %d: iq corr coeff=%x\n",
575                 chain_idx, iqc_coeff[0]);
576
577         if (-mag_rx == res_scale) {
578                 DBG("ath9k: "
579                         "Divide by 0: mag_rx=%d, res_scale=%d\n",
580                         mag_rx, res_scale);
581                 return 0;
582         }
583
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;
587
588         q_q_coff = (mag_corr_rx * 128 / res_scale);
589         q_i_coff = (phs_corr_rx * 256 / res_scale);
590
591         DBG("ath9k: "
592                 "rx chain %d: mag corr=%d  phase corr=%d\n",
593                 chain_idx, q_q_coff, q_i_coff);
594
595         if (q_i_coff < -63)
596                 q_i_coff = -63;
597         if (q_i_coff > 63)
598                 q_i_coff = 63;
599         if (q_q_coff < -63)
600                 q_q_coff = -63;
601         if (q_q_coff > 63)
602                 q_q_coff = 63;
603
604         iqc_coeff[1] = (q_q_coff * 128) + q_i_coff;
605
606         DBG2("ath9k: "
607                 "rx chain %d: iq corr coeff=%x\n",
608                 chain_idx, iqc_coeff[1]);
609
610         return 1;
611 }
612
613 static void ar9003_hw_detect_outlier(int *mp_coeff, int nmeasurement,
614                                      int max_delta)
615 {
616         int mp_max = -64, max_idx = 0;
617         int mp_min = 63, min_idx = 0;
618         int mp_avg = 0, i, outlier_idx = 0;
619
620         /* find min/max mismatch across all calibrated gains */
621         for (i = 0; i < nmeasurement; i++) {
622                 mp_avg += mp_coeff[i];
623                 if (mp_coeff[i] > mp_max) {
624                         mp_max = mp_coeff[i];
625                         max_idx = i;
626                 } else if (mp_coeff[i] < mp_min) {
627                         mp_min = mp_coeff[i];
628                         min_idx = i;
629                 }
630         }
631
632         /* find average (exclude max abs value) */
633         for (i = 0; i < nmeasurement; i++) {
634                 if ((abs(mp_coeff[i]) < abs(mp_max)) ||
635                     (abs(mp_coeff[i]) < abs(mp_min)))
636                         mp_avg += mp_coeff[i];
637         }
638         mp_avg /= (nmeasurement - 1);
639
640         /* detect outlier */
641         if (abs(mp_max - mp_min) > max_delta) {
642                 if (abs(mp_max - mp_avg) > abs(mp_min - mp_avg))
643                         outlier_idx = max_idx;
644                 else
645                         outlier_idx = min_idx;
646         }
647         mp_coeff[outlier_idx] = mp_avg;
648 }
649
650 static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah,
651                                                  u8 num_chains,
652                                                  struct coeff *coeff)
653 {
654         int i, im, nmeasurement;
655         u32 tx_corr_coeff[MAX_MEASUREMENT][AR9300_MAX_CHAINS];
656
657         memset(tx_corr_coeff, 0, sizeof(tx_corr_coeff));
658         for (i = 0; i < MAX_MEASUREMENT / 2; i++) {
659                 tx_corr_coeff[i * 2][0] = tx_corr_coeff[(i * 2) + 1][0] =
660                                         AR_PHY_TX_IQCAL_CORR_COEFF_B0(i);
661                 if (!AR_SREV_9485(ah)) {
662                         tx_corr_coeff[i * 2][1] =
663                         tx_corr_coeff[(i * 2) + 1][1] =
664                                         AR_PHY_TX_IQCAL_CORR_COEFF_B1(i);
665
666                         tx_corr_coeff[i * 2][2] =
667                         tx_corr_coeff[(i * 2) + 1][2] =
668                                         AR_PHY_TX_IQCAL_CORR_COEFF_B2(i);
669                 }
670         }
671
672         /* Load the average of 2 passes */
673         for (i = 0; i < num_chains; i++) {
674                 nmeasurement = REG_READ_FIELD(ah,
675                                 AR_PHY_TX_IQCAL_STATUS_B0,
676                                 AR_PHY_CALIBRATED_GAINS_0);
677
678                 if (nmeasurement > MAX_MEASUREMENT)
679                         nmeasurement = MAX_MEASUREMENT;
680
681                 /* detect outlier only if nmeasurement > 1 */
682                 if (nmeasurement > 1) {
683                         /* Detect magnitude outlier */
684                         ar9003_hw_detect_outlier(coeff->mag_coeff[i],
685                                         nmeasurement, MAX_MAG_DELTA);
686
687                         /* Detect phase outlier */
688                         ar9003_hw_detect_outlier(coeff->phs_coeff[i],
689                                         nmeasurement, MAX_PHS_DELTA);
690                 }
691
692                 for (im = 0; im < nmeasurement; im++) {
693
694                         coeff->iqc_coeff[0] = (coeff->mag_coeff[i][im] & 0x7f) |
695                                 ((coeff->phs_coeff[i][im] & 0x7f) << 7);
696
697                         if ((im % 2) == 0)
698                                 REG_RMW_FIELD(ah, tx_corr_coeff[im][i],
699                                         AR_PHY_TX_IQCAL_CORR_COEFF_00_COEFF_TABLE,
700                                         coeff->iqc_coeff[0]);
701                         else
702                                 REG_RMW_FIELD(ah, tx_corr_coeff[im][i],
703                                         AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE,
704                                         coeff->iqc_coeff[0]);
705                 }
706         }
707
708         REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_3,
709                       AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN, 0x1);
710         REG_RMW_FIELD(ah, AR_PHY_RX_IQCAL_CORR_B0,
711                       AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, 0x1);
712
713         return;
714
715 }
716
717 static int ar9003_hw_tx_iq_cal_run(struct ath_hw *ah)
718 {
719         u8 tx_gain_forced;
720
721         tx_gain_forced = REG_READ_FIELD(ah, AR_PHY_TX_FORCED_GAIN,
722                                         AR_PHY_TXGAIN_FORCE);
723         if (tx_gain_forced)
724                 REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN,
725                               AR_PHY_TXGAIN_FORCE, 0);
726
727         REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START,
728                       AR_PHY_TX_IQCAL_START_DO_CAL, 1);
729
730         if (!ath9k_hw_wait(ah, AR_PHY_TX_IQCAL_START,
731                         AR_PHY_TX_IQCAL_START_DO_CAL, 0,
732                         AH_WAIT_TIMEOUT)) {
733                 DBG2("ath9k: "
734                         "Tx IQ Cal is not completed.\n");
735                 return 0;
736         }
737         return 1;
738 }
739
740 static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah)
741 {
742         const u32 txiqcal_status[AR9300_MAX_CHAINS] = {
743                 AR_PHY_TX_IQCAL_STATUS_B0,
744                 AR_PHY_TX_IQCAL_STATUS_B1,
745                 AR_PHY_TX_IQCAL_STATUS_B2,
746         };
747         const uint32_t chan_info_tab[] = {
748                 AR_PHY_CHAN_INFO_TAB_0,
749                 AR_PHY_CHAN_INFO_TAB_1,
750                 AR_PHY_CHAN_INFO_TAB_2,
751         };
752         struct coeff coeff;
753         s32 iq_res[6];
754         u8 num_chains = 0;
755         int i, im, j;
756         int nmeasurement;
757
758         for (i = 0; i < AR9300_MAX_CHAINS; i++) {
759                 if (ah->txchainmask & (1 << i))
760                         num_chains++;
761         }
762
763         for (i = 0; i < num_chains; i++) {
764                 nmeasurement = REG_READ_FIELD(ah,
765                                 AR_PHY_TX_IQCAL_STATUS_B0,
766                                 AR_PHY_CALIBRATED_GAINS_0);
767                 if (nmeasurement > MAX_MEASUREMENT)
768                         nmeasurement = MAX_MEASUREMENT;
769
770                 for (im = 0; im < nmeasurement; im++) {
771                         DBG2("ath9k: "
772                                 "Doing Tx IQ Cal for chain %d.\n", i);
773
774                         if (REG_READ(ah, txiqcal_status[i]) &
775                                         AR_PHY_TX_IQCAL_STATUS_FAILED) {
776                                 DBG("ath9k: "
777                                         "Tx IQ Cal failed for chain %d.\n", i);
778                                 goto tx_iqcal_fail;
779                         }
780
781                         for (j = 0; j < 3; j++) {
782                                 u32 idx = 2 * j, offset = 4 * (3 * im + j);
783
784                                 REG_RMW_FIELD(ah,
785                                                 AR_PHY_CHAN_INFO_MEMORY,
786                                                 AR_PHY_CHAN_INFO_TAB_S2_READ,
787                                                 0);
788
789                                 /* 32 bits */
790                                 iq_res[idx] = REG_READ(ah,
791                                                 chan_info_tab[i] +
792                                                 offset);
793
794                                 REG_RMW_FIELD(ah,
795                                                 AR_PHY_CHAN_INFO_MEMORY,
796                                                 AR_PHY_CHAN_INFO_TAB_S2_READ,
797                                                 1);
798
799                                 /* 16 bits */
800                                 iq_res[idx + 1] = 0xffff & REG_READ(ah,
801                                                 chan_info_tab[i] + offset);
802
803                                 DBG2("ath9k: "
804                                         "IQ RES[%d]=0x%x"
805                                         "IQ_RES[%d]=0x%x\n",
806                                         idx, iq_res[idx], idx + 1,
807                                         iq_res[idx + 1]);
808                         }
809
810                         if (!ar9003_hw_calc_iq_corr(ah, i, iq_res,
811                                                 coeff.iqc_coeff)) {
812                                 DBG("ath9k: "
813                                         "Failed in calculation of \
814                                         IQ correction.\n");
815                                 goto tx_iqcal_fail;
816                         }
817
818                         coeff.mag_coeff[i][im] = coeff.iqc_coeff[0] & 0x7f;
819                         coeff.phs_coeff[i][im] =
820                                 (coeff.iqc_coeff[0] >> 7) & 0x7f;
821
822                         if (coeff.mag_coeff[i][im] > 63)
823                                 coeff.mag_coeff[i][im] -= 128;
824                         if (coeff.phs_coeff[i][im] > 63)
825                                 coeff.phs_coeff[i][im] -= 128;
826                 }
827         }
828         ar9003_hw_tx_iqcal_load_avg_2_passes(ah, num_chains, &coeff);
829
830         return;
831
832 tx_iqcal_fail:
833         DBG("ath9k: Tx IQ Cal failed\n");
834         return;
835 }
836 static int ar9003_hw_init_cal(struct ath_hw *ah,
837                                struct ath9k_channel *chan __unused)
838 {
839         struct ath9k_hw_capabilities *pCap = &ah->caps;
840         int val;
841         int txiqcal_done = 0;
842
843         val = REG_READ(ah, AR_ENT_OTP);
844         DBG2("ath9k: ath9k: AR_ENT_OTP 0x%x\n", val);
845
846         /* Configure rx/tx chains before running AGC/TxiQ cals */
847         if (val & AR_ENT_OTP_CHAIN2_DISABLE)
848                 ar9003_hw_set_chain_masks(ah, 0x3, 0x3);
849         else
850                 ar9003_hw_set_chain_masks(ah, pCap->rx_chainmask,
851                                           pCap->tx_chainmask);
852
853         /* Do Tx IQ Calibration */
854         REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1,
855                       AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT,
856                       DELPT);
857
858         /*
859          * For AR9485 or later chips, TxIQ cal runs as part of
860          * AGC calibration
861          */
862         if (AR_SREV_9485_OR_LATER(ah))
863                 txiqcal_done = 1;
864         else {
865                 txiqcal_done = ar9003_hw_tx_iq_cal_run(ah);
866                 REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS);
867                 udelay(5);
868                 REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
869         }
870
871         /* Calibrate the AGC */
872         REG_WRITE(ah, AR_PHY_AGC_CONTROL,
873                   REG_READ(ah, AR_PHY_AGC_CONTROL) |
874                   AR_PHY_AGC_CONTROL_CAL);
875
876         /* Poll for offset calibration complete */
877         if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL,
878                            0, AH_WAIT_TIMEOUT)) {
879                 DBG("ath9k: "
880                         "offset calibration failed to complete in 1ms; noisy environment?\n");
881                 return 0;
882         }
883
884         if (txiqcal_done)
885                 ar9003_hw_tx_iq_cal_post_proc(ah);
886
887         /* Revert chainmasks to their original values before NF cal */
888         ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
889
890         ath9k_hw_start_nfcal(ah, 1);
891
892         /* Initialize list pointers */
893         ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL;
894         ah->supp_cals = IQ_MISMATCH_CAL;
895
896         if (ah->supp_cals & IQ_MISMATCH_CAL) {
897                 INIT_CAL(&ah->iq_caldata);
898                 INSERT_CAL(ah, &ah->iq_caldata);
899                 DBG2("ath9k: "
900                         "enabling IQ Calibration.\n");
901         }
902
903         if (ah->supp_cals & TEMP_COMP_CAL) {
904                 INIT_CAL(&ah->tempCompCalData);
905                 INSERT_CAL(ah, &ah->tempCompCalData);
906                 DBG2("ath9k: "
907                         "enabling Temperature Compensation Calibration.\n");
908         }
909
910         /* Initialize current pointer to first element in list */
911         ah->cal_list_curr = ah->cal_list;
912
913         if (ah->cal_list_curr)
914                 ath9k_hw_reset_calibration(ah, ah->cal_list_curr);
915
916         if (ah->caldata)
917                 ah->caldata->CalValid = 0;
918
919         return 1;
920 }
921
922 void ar9003_hw_attach_calib_ops(struct ath_hw *ah)
923 {
924         struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
925         struct ath_hw_ops *ops = ath9k_hw_ops(ah);
926
927         priv_ops->init_cal_settings = ar9003_hw_init_cal_settings;
928         priv_ops->init_cal = ar9003_hw_init_cal;
929         priv_ops->setup_calibration = ar9003_hw_setup_calibration;
930
931         ops->calibrate = ar9003_hw_calibrate;
932 }