ath9k_hw: fix periodic noise floor calibration on AR9003
[linux-2.6.git] / drivers / net / wireless / ath / ath9k / ar9003_calib.c
1 /*
2  * Copyright (c) 2010 Atheros Communications Inc.
3  *
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.
7  *
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.
15  */
16
17 #include "hw.h"
18 #include "hw-ops.h"
19 #include "ar9003_phy.h"
20
21 static void ar9003_hw_setup_calibration(struct ath_hw *ah,
22                                         struct ath9k_cal_list *currCal)
23 {
24         struct ath_common *common = ath9k_hw_common(ah);
25
26         /* Select calibration to run */
27         switch (currCal->calData->calType) {
28         case IQ_MISMATCH_CAL:
29                 /*
30                  * Start calibration with
31                  * 2^(INIT_IQCAL_LOG_COUNT_MAX+1) samples
32                  */
33                 REG_RMW_FIELD(ah, AR_PHY_TIMING4,
34                               AR_PHY_TIMING4_IQCAL_LOG_COUNT_MAX,
35                 currCal->calData->calCountMax);
36                 REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ);
37
38                 ath_print(common, ATH_DBG_CALIBRATE,
39                           "starting IQ Mismatch Calibration\n");
40
41                 /* Kick-off cal */
42                 REG_SET_BIT(ah, AR_PHY_TIMING4, AR_PHY_TIMING4_DO_CAL);
43                 break;
44         case TEMP_COMP_CAL:
45                 REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_THERM,
46                               AR_PHY_65NM_CH0_THERM_LOCAL, 1);
47                 REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_THERM,
48                               AR_PHY_65NM_CH0_THERM_START, 1);
49
50                 ath_print(common, ATH_DBG_CALIBRATE,
51                           "starting Temperature Compensation Calibration\n");
52                 break;
53         case ADC_DC_INIT_CAL:
54         case ADC_GAIN_CAL:
55         case ADC_DC_CAL:
56                 /* Not yet */
57                 break;
58         }
59 }
60
61 /*
62  * Generic calibration routine.
63  * Recalibrate the lower PHY chips to account for temperature/environment
64  * changes.
65  */
66 static bool ar9003_hw_per_calibration(struct ath_hw *ah,
67                                       struct ath9k_channel *ichan,
68                                       u8 rxchainmask,
69                                       struct ath9k_cal_list *currCal)
70 {
71         /* Cal is assumed not done until explicitly set below */
72         bool iscaldone = false;
73
74         /* Calibration in progress. */
75         if (currCal->calState == CAL_RUNNING) {
76                 /* Check to see if it has finished. */
77                 if (!(REG_READ(ah, AR_PHY_TIMING4) & AR_PHY_TIMING4_DO_CAL)) {
78                         /*
79                         * Accumulate cal measures for active chains
80                         */
81                         currCal->calData->calCollect(ah);
82                         ah->cal_samples++;
83
84                         if (ah->cal_samples >=
85                             currCal->calData->calNumSamples) {
86                                 unsigned int i, numChains = 0;
87                                 for (i = 0; i < AR9300_MAX_CHAINS; i++) {
88                                         if (rxchainmask & (1 << i))
89                                                 numChains++;
90                                 }
91
92                                 /*
93                                 * Process accumulated data
94                                 */
95                                 currCal->calData->calPostProc(ah, numChains);
96
97                                 /* Calibration has finished. */
98                                 ichan->CalValid |= currCal->calData->calType;
99                                 currCal->calState = CAL_DONE;
100                                 iscaldone = true;
101                         } else {
102                         /*
103                          * Set-up collection of another sub-sample until we
104                          * get desired number
105                          */
106                         ar9003_hw_setup_calibration(ah, currCal);
107                         }
108                 }
109         } else if (!(ichan->CalValid & currCal->calData->calType)) {
110                 /* If current cal is marked invalid in channel, kick it off */
111                 ath9k_hw_reset_calibration(ah, currCal);
112         }
113
114         return iscaldone;
115 }
116
117 static bool ar9003_hw_calibrate(struct ath_hw *ah,
118                                 struct ath9k_channel *chan,
119                                 u8 rxchainmask,
120                                 bool longcal)
121 {
122         bool iscaldone = true;
123         struct ath9k_cal_list *currCal = ah->cal_list_curr;
124
125         /*
126          * For given calibration:
127          * 1. Call generic cal routine
128          * 2. When this cal is done (isCalDone) if we have more cals waiting
129          *    (eg after reset), mask this to upper layers by not propagating
130          *    isCalDone if it is set to TRUE.
131          *    Instead, change isCalDone to FALSE and setup the waiting cal(s)
132          *    to be run.
133          */
134         if (currCal &&
135             (currCal->calState == CAL_RUNNING ||
136              currCal->calState == CAL_WAITING)) {
137                 iscaldone = ar9003_hw_per_calibration(ah, chan,
138                                                       rxchainmask, currCal);
139                 if (iscaldone) {
140                         ah->cal_list_curr = currCal = currCal->calNext;
141
142                         if (currCal->calState == CAL_WAITING) {
143                                 iscaldone = false;
144                                 ath9k_hw_reset_calibration(ah, currCal);
145                         }
146                 }
147         }
148
149         /* Do NF cal only at longer intervals */
150         if (longcal) {
151                 /*
152                  * Get the value from the previous NF cal and update
153                  * history buffer.
154                  */
155                 ath9k_hw_getnf(ah, chan);
156
157                 /*
158                  * Load the NF from history buffer of the current channel.
159                  * NF is slow time-variant, so it is OK to use a historical
160                  * value.
161                  */
162                 ath9k_hw_loadnf(ah, ah->curchan);
163
164                 /* start NF calibration, without updating BB NF register */
165                 ath9k_hw_start_nfcal(ah, false);
166         }
167
168         return iscaldone;
169 }
170
171 static void ar9003_hw_iqcal_collect(struct ath_hw *ah)
172 {
173         int i;
174
175         /* Accumulate IQ cal measures for active chains */
176         for (i = 0; i < AR5416_MAX_CHAINS; i++) {
177                 ah->totalPowerMeasI[i] +=
178                         REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
179                 ah->totalPowerMeasQ[i] +=
180                         REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
181                 ah->totalIqCorrMeas[i] +=
182                         (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
183                 ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
184                           "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
185                           ah->cal_samples, i, ah->totalPowerMeasI[i],
186                           ah->totalPowerMeasQ[i],
187                           ah->totalIqCorrMeas[i]);
188         }
189 }
190
191 static void ar9003_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
192 {
193         struct ath_common *common = ath9k_hw_common(ah);
194         u32 powerMeasQ, powerMeasI, iqCorrMeas;
195         u32 qCoffDenom, iCoffDenom;
196         int32_t qCoff, iCoff;
197         int iqCorrNeg, i;
198         const u_int32_t offset_array[3] = {
199                 AR_PHY_RX_IQCAL_CORR_B0,
200                 AR_PHY_RX_IQCAL_CORR_B1,
201                 AR_PHY_RX_IQCAL_CORR_B2,
202         };
203
204         for (i = 0; i < numChains; i++) {
205                 powerMeasI = ah->totalPowerMeasI[i];
206                 powerMeasQ = ah->totalPowerMeasQ[i];
207                 iqCorrMeas = ah->totalIqCorrMeas[i];
208
209                 ath_print(common, ATH_DBG_CALIBRATE,
210                           "Starting IQ Cal and Correction for Chain %d\n",
211                           i);
212
213                 ath_print(common, ATH_DBG_CALIBRATE,
214                           "Orignal: Chn %diq_corr_meas = 0x%08x\n",
215                           i, ah->totalIqCorrMeas[i]);
216
217                 iqCorrNeg = 0;
218
219                 if (iqCorrMeas > 0x80000000) {
220                         iqCorrMeas = (0xffffffff - iqCorrMeas) + 1;
221                         iqCorrNeg = 1;
222                 }
223
224                 ath_print(common, ATH_DBG_CALIBRATE,
225                           "Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI);
226                 ath_print(common, ATH_DBG_CALIBRATE,
227                           "Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ);
228                 ath_print(common, ATH_DBG_CALIBRATE, "iqCorrNeg is 0x%08x\n",
229                           iqCorrNeg);
230
231                 iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 256;
232                 qCoffDenom = powerMeasQ / 64;
233
234                 if ((iCoffDenom != 0) && (qCoffDenom != 0)) {
235                         iCoff = iqCorrMeas / iCoffDenom;
236                         qCoff = powerMeasI / qCoffDenom - 64;
237                         ath_print(common, ATH_DBG_CALIBRATE,
238                                   "Chn %d iCoff = 0x%08x\n", i, iCoff);
239                         ath_print(common, ATH_DBG_CALIBRATE,
240                                   "Chn %d qCoff = 0x%08x\n", i, qCoff);
241
242                         /* Force bounds on iCoff */
243                         if (iCoff >= 63)
244                                 iCoff = 63;
245                         else if (iCoff <= -63)
246                                 iCoff = -63;
247
248                         /* Negate iCoff if iqCorrNeg == 0 */
249                         if (iqCorrNeg == 0x0)
250                                 iCoff = -iCoff;
251
252                         /* Force bounds on qCoff */
253                         if (qCoff >= 63)
254                                 qCoff = 63;
255                         else if (qCoff <= -63)
256                                 qCoff = -63;
257
258                         iCoff = iCoff & 0x7f;
259                         qCoff = qCoff & 0x7f;
260
261                         ath_print(common, ATH_DBG_CALIBRATE,
262                                   "Chn %d : iCoff = 0x%x  qCoff = 0x%x\n",
263                                   i, iCoff, qCoff);
264                         ath_print(common, ATH_DBG_CALIBRATE,
265                                   "Register offset (0x%04x) "
266                                   "before update = 0x%x\n",
267                                   offset_array[i],
268                                   REG_READ(ah, offset_array[i]));
269
270                         REG_RMW_FIELD(ah, offset_array[i],
271                                       AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF,
272                                       iCoff);
273                         REG_RMW_FIELD(ah, offset_array[i],
274                                       AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF,
275                                       qCoff);
276                         ath_print(common, ATH_DBG_CALIBRATE,
277                                   "Register offset (0x%04x) QI COFF "
278                                   "(bitfields 0x%08x) after update = 0x%x\n",
279                                   offset_array[i],
280                                   AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF,
281                                   REG_READ(ah, offset_array[i]));
282                         ath_print(common, ATH_DBG_CALIBRATE,
283                                   "Register offset (0x%04x) QQ COFF "
284                                   "(bitfields 0x%08x) after update = 0x%x\n",
285                                   offset_array[i],
286                                   AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF,
287                                   REG_READ(ah, offset_array[i]));
288
289                         ath_print(common, ATH_DBG_CALIBRATE,
290                                   "IQ Cal and Correction done for Chain %d\n",
291                                   i);
292                 }
293         }
294
295         REG_SET_BIT(ah, AR_PHY_RX_IQCAL_CORR_B0,
296                     AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE);
297         ath_print(common, ATH_DBG_CALIBRATE,
298                   "IQ Cal and Correction (offset 0x%04x) enabled "
299                   "(bit position 0x%08x). New Value 0x%08x\n",
300                   (unsigned) (AR_PHY_RX_IQCAL_CORR_B0),
301                   AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE,
302                   REG_READ(ah, AR_PHY_RX_IQCAL_CORR_B0));
303 }
304
305 static const struct ath9k_percal_data iq_cal_single_sample = {
306         IQ_MISMATCH_CAL,
307         MIN_CAL_SAMPLES,
308         PER_MAX_LOG_COUNT,
309         ar9003_hw_iqcal_collect,
310         ar9003_hw_iqcalibrate
311 };
312
313 static void ar9003_hw_init_cal_settings(struct ath_hw *ah)
314 {
315         ah->iq_caldata.calData = &iq_cal_single_sample;
316         ah->supp_cals = IQ_MISMATCH_CAL;
317 }
318
319 static bool ar9003_hw_iscal_supported(struct ath_hw *ah,
320                                       enum ath9k_cal_types calType)
321 {
322         switch (calType & ah->supp_cals) {
323         case IQ_MISMATCH_CAL:
324                 /*
325                  * XXX: Run IQ Mismatch for non-CCK only
326                  * Note that CHANNEL_B is never set though.
327                  */
328                 return true;
329         case ADC_GAIN_CAL:
330         case ADC_DC_CAL:
331                 return false;
332         case TEMP_COMP_CAL:
333                 return true;
334         }
335
336         return false;
337 }
338
339 /*
340  * solve 4x4 linear equation used in loopback iq cal.
341  */
342 static bool ar9003_hw_solve_iq_cal(struct ath_hw *ah,
343                                    s32 sin_2phi_1,
344                                    s32 cos_2phi_1,
345                                    s32 sin_2phi_2,
346                                    s32 cos_2phi_2,
347                                    s32 mag_a0_d0,
348                                    s32 phs_a0_d0,
349                                    s32 mag_a1_d0,
350                                    s32 phs_a1_d0,
351                                    s32 solved_eq[])
352 {
353         s32 f1 = cos_2phi_1 - cos_2phi_2,
354             f3 = sin_2phi_1 - sin_2phi_2,
355             f2;
356         s32 mag_tx, phs_tx, mag_rx, phs_rx;
357         const s32 result_shift = 1 << 15;
358         struct ath_common *common = ath9k_hw_common(ah);
359
360         f2 = (f1 * f1 + f3 * f3) / result_shift;
361
362         if (!f2) {
363                 ath_print(common, ATH_DBG_CALIBRATE, "Divide by 0\n");
364                 return false;
365         }
366
367         /* mag mismatch, tx */
368         mag_tx = f1 * (mag_a0_d0  - mag_a1_d0) + f3 * (phs_a0_d0 - phs_a1_d0);
369         /* phs mismatch, tx */
370         phs_tx = f3 * (-mag_a0_d0 + mag_a1_d0) + f1 * (phs_a0_d0 - phs_a1_d0);
371
372         mag_tx = (mag_tx / f2);
373         phs_tx = (phs_tx / f2);
374
375         /* mag mismatch, rx */
376         mag_rx = mag_a0_d0 - (cos_2phi_1 * mag_tx + sin_2phi_1 * phs_tx) /
377                  result_shift;
378         /* phs mismatch, rx */
379         phs_rx = phs_a0_d0 + (sin_2phi_1 * mag_tx - cos_2phi_1 * phs_tx) /
380                  result_shift;
381
382         solved_eq[0] = mag_tx;
383         solved_eq[1] = phs_tx;
384         solved_eq[2] = mag_rx;
385         solved_eq[3] = phs_rx;
386
387         return true;
388 }
389
390 static s32 ar9003_hw_find_mag_approx(struct ath_hw *ah, s32 in_re, s32 in_im)
391 {
392         s32 abs_i = abs(in_re),
393             abs_q = abs(in_im),
394             max_abs, min_abs;
395
396         if (abs_i > abs_q) {
397                 max_abs = abs_i;
398                 min_abs = abs_q;
399         } else {
400                 max_abs = abs_q;
401                 min_abs = abs_i;
402         }
403
404         return max_abs - (max_abs / 32) + (min_abs / 8) + (min_abs / 4);
405 }
406
407 #define DELPT 32
408
409 static bool ar9003_hw_calc_iq_corr(struct ath_hw *ah,
410                                    s32 chain_idx,
411                                    const s32 iq_res[],
412                                    s32 iqc_coeff[])
413 {
414         s32 i2_m_q2_a0_d0, i2_p_q2_a0_d0, iq_corr_a0_d0,
415             i2_m_q2_a0_d1, i2_p_q2_a0_d1, iq_corr_a0_d1,
416             i2_m_q2_a1_d0, i2_p_q2_a1_d0, iq_corr_a1_d0,
417             i2_m_q2_a1_d1, i2_p_q2_a1_d1, iq_corr_a1_d1;
418         s32 mag_a0_d0, mag_a1_d0, mag_a0_d1, mag_a1_d1,
419             phs_a0_d0, phs_a1_d0, phs_a0_d1, phs_a1_d1,
420             sin_2phi_1, cos_2phi_1,
421             sin_2phi_2, cos_2phi_2;
422         s32 mag_tx, phs_tx, mag_rx, phs_rx;
423         s32 solved_eq[4], mag_corr_tx, phs_corr_tx, mag_corr_rx, phs_corr_rx,
424             q_q_coff, q_i_coff;
425         const s32 res_scale = 1 << 15;
426         const s32 delpt_shift = 1 << 8;
427         s32 mag1, mag2;
428         struct ath_common *common = ath9k_hw_common(ah);
429
430         i2_m_q2_a0_d0 = iq_res[0] & 0xfff;
431         i2_p_q2_a0_d0 = (iq_res[0] >> 12) & 0xfff;
432         iq_corr_a0_d0 = ((iq_res[0] >> 24) & 0xff) + ((iq_res[1] & 0xf) << 8);
433
434         if (i2_m_q2_a0_d0 > 0x800)
435                 i2_m_q2_a0_d0 = -((0xfff - i2_m_q2_a0_d0) + 1);
436
437         if (i2_p_q2_a0_d0 > 0x800)
438                 i2_p_q2_a0_d0 = -((0xfff - i2_p_q2_a0_d0) + 1);
439
440         if (iq_corr_a0_d0 > 0x800)
441                 iq_corr_a0_d0 = -((0xfff - iq_corr_a0_d0) + 1);
442
443         i2_m_q2_a0_d1 = (iq_res[1] >> 4) & 0xfff;
444         i2_p_q2_a0_d1 = (iq_res[2] & 0xfff);
445         iq_corr_a0_d1 = (iq_res[2] >> 12) & 0xfff;
446
447         if (i2_m_q2_a0_d1 > 0x800)
448                 i2_m_q2_a0_d1 = -((0xfff - i2_m_q2_a0_d1) + 1);
449
450         if (i2_p_q2_a0_d1 > 0x800)
451                 i2_p_q2_a0_d1 = -((0xfff - i2_p_q2_a0_d1) + 1);
452
453         if (iq_corr_a0_d1 > 0x800)
454                 iq_corr_a0_d1 = -((0xfff - iq_corr_a0_d1) + 1);
455
456         i2_m_q2_a1_d0 = ((iq_res[2] >> 24) & 0xff) + ((iq_res[3] & 0xf) << 8);
457         i2_p_q2_a1_d0 = (iq_res[3] >> 4) & 0xfff;
458         iq_corr_a1_d0 = iq_res[4] & 0xfff;
459
460         if (i2_m_q2_a1_d0 > 0x800)
461                 i2_m_q2_a1_d0 = -((0xfff - i2_m_q2_a1_d0) + 1);
462
463         if (i2_p_q2_a1_d0 > 0x800)
464                 i2_p_q2_a1_d0 = -((0xfff - i2_p_q2_a1_d0) + 1);
465
466         if (iq_corr_a1_d0 > 0x800)
467                 iq_corr_a1_d0 = -((0xfff - iq_corr_a1_d0) + 1);
468
469         i2_m_q2_a1_d1 = (iq_res[4] >> 12) & 0xfff;
470         i2_p_q2_a1_d1 = ((iq_res[4] >> 24) & 0xff) + ((iq_res[5] & 0xf) << 8);
471         iq_corr_a1_d1 = (iq_res[5] >> 4) & 0xfff;
472
473         if (i2_m_q2_a1_d1 > 0x800)
474                 i2_m_q2_a1_d1 = -((0xfff - i2_m_q2_a1_d1) + 1);
475
476         if (i2_p_q2_a1_d1 > 0x800)
477                 i2_p_q2_a1_d1 = -((0xfff - i2_p_q2_a1_d1) + 1);
478
479         if (iq_corr_a1_d1 > 0x800)
480                 iq_corr_a1_d1 = -((0xfff - iq_corr_a1_d1) + 1);
481
482         if ((i2_p_q2_a0_d0 == 0) || (i2_p_q2_a0_d1 == 0) ||
483             (i2_p_q2_a1_d0 == 0) || (i2_p_q2_a1_d1 == 0)) {
484                 ath_print(common, ATH_DBG_CALIBRATE,
485                           "Divide by 0:\na0_d0=%d\n"
486                           "a0_d1=%d\na2_d0=%d\na1_d1=%d\n",
487                           i2_p_q2_a0_d0, i2_p_q2_a0_d1,
488                           i2_p_q2_a1_d0, i2_p_q2_a1_d1);
489                 return false;
490         }
491
492         mag_a0_d0 = (i2_m_q2_a0_d0 * res_scale) / i2_p_q2_a0_d0;
493         phs_a0_d0 = (iq_corr_a0_d0 * res_scale) / i2_p_q2_a0_d0;
494
495         mag_a0_d1 = (i2_m_q2_a0_d1 * res_scale) / i2_p_q2_a0_d1;
496         phs_a0_d1 = (iq_corr_a0_d1 * res_scale) / i2_p_q2_a0_d1;
497
498         mag_a1_d0 = (i2_m_q2_a1_d0 * res_scale) / i2_p_q2_a1_d0;
499         phs_a1_d0 = (iq_corr_a1_d0 * res_scale) / i2_p_q2_a1_d0;
500
501         mag_a1_d1 = (i2_m_q2_a1_d1 * res_scale) / i2_p_q2_a1_d1;
502         phs_a1_d1 = (iq_corr_a1_d1 * res_scale) / i2_p_q2_a1_d1;
503
504         /* w/o analog phase shift */
505         sin_2phi_1 = (((mag_a0_d0 - mag_a0_d1) * delpt_shift) / DELPT);
506         /* w/o analog phase shift */
507         cos_2phi_1 = (((phs_a0_d1 - phs_a0_d0) * delpt_shift) / DELPT);
508         /* w/  analog phase shift */
509         sin_2phi_2 = (((mag_a1_d0 - mag_a1_d1) * delpt_shift) / DELPT);
510         /* w/  analog phase shift */
511         cos_2phi_2 = (((phs_a1_d1 - phs_a1_d0) * delpt_shift) / DELPT);
512
513         /*
514          * force sin^2 + cos^2 = 1;
515          * find magnitude by approximation
516          */
517         mag1 = ar9003_hw_find_mag_approx(ah, cos_2phi_1, sin_2phi_1);
518         mag2 = ar9003_hw_find_mag_approx(ah, cos_2phi_2, sin_2phi_2);
519
520         if ((mag1 == 0) || (mag2 == 0)) {
521                 ath_print(common, ATH_DBG_CALIBRATE,
522                           "Divide by 0: mag1=%d, mag2=%d\n",
523                           mag1, mag2);
524                 return false;
525         }
526
527         /* normalization sin and cos by mag */
528         sin_2phi_1 = (sin_2phi_1 * res_scale / mag1);
529         cos_2phi_1 = (cos_2phi_1 * res_scale / mag1);
530         sin_2phi_2 = (sin_2phi_2 * res_scale / mag2);
531         cos_2phi_2 = (cos_2phi_2 * res_scale / mag2);
532
533         /* calculate IQ mismatch */
534         if (!ar9003_hw_solve_iq_cal(ah,
535                              sin_2phi_1, cos_2phi_1,
536                              sin_2phi_2, cos_2phi_2,
537                              mag_a0_d0, phs_a0_d0,
538                              mag_a1_d0,
539                              phs_a1_d0, solved_eq)) {
540                 ath_print(common, ATH_DBG_CALIBRATE,
541                           "Call to ar9003_hw_solve_iq_cal() failed.\n");
542                 return false;
543         }
544
545         mag_tx = solved_eq[0];
546         phs_tx = solved_eq[1];
547         mag_rx = solved_eq[2];
548         phs_rx = solved_eq[3];
549
550         ath_print(common, ATH_DBG_CALIBRATE,
551                   "chain %d: mag mismatch=%d phase mismatch=%d\n",
552                   chain_idx, mag_tx/res_scale, phs_tx/res_scale);
553
554         if (res_scale == mag_tx) {
555                 ath_print(common, ATH_DBG_CALIBRATE,
556                           "Divide by 0: mag_tx=%d, res_scale=%d\n",
557                           mag_tx, res_scale);
558                 return false;
559         }
560
561         /* calculate and quantize Tx IQ correction factor */
562         mag_corr_tx = (mag_tx * res_scale) / (res_scale - mag_tx);
563         phs_corr_tx = -phs_tx;
564
565         q_q_coff = (mag_corr_tx * 128 / res_scale);
566         q_i_coff = (phs_corr_tx * 256 / res_scale);
567
568         ath_print(common, ATH_DBG_CALIBRATE,
569                   "tx chain %d: mag corr=%d  phase corr=%d\n",
570                   chain_idx, q_q_coff, q_i_coff);
571
572         if (q_i_coff < -63)
573                 q_i_coff = -63;
574         if (q_i_coff > 63)
575                 q_i_coff = 63;
576         if (q_q_coff < -63)
577                 q_q_coff = -63;
578         if (q_q_coff > 63)
579                 q_q_coff = 63;
580
581         iqc_coeff[0] = (q_q_coff * 128) + q_i_coff;
582
583         ath_print(common, ATH_DBG_CALIBRATE,
584                   "tx chain %d: iq corr coeff=%x\n",
585                   chain_idx, iqc_coeff[0]);
586
587         if (-mag_rx == res_scale) {
588                 ath_print(common, ATH_DBG_CALIBRATE,
589                           "Divide by 0: mag_rx=%d, res_scale=%d\n",
590                           mag_rx, res_scale);
591                 return false;
592         }
593
594         /* calculate and quantize Rx IQ correction factors */
595         mag_corr_rx = (-mag_rx * res_scale) / (res_scale + mag_rx);
596         phs_corr_rx = -phs_rx;
597
598         q_q_coff = (mag_corr_rx * 128 / res_scale);
599         q_i_coff = (phs_corr_rx * 256 / res_scale);
600
601         ath_print(common, ATH_DBG_CALIBRATE,
602                   "rx chain %d: mag corr=%d  phase corr=%d\n",
603                   chain_idx, q_q_coff, q_i_coff);
604
605         if (q_i_coff < -63)
606                 q_i_coff = -63;
607         if (q_i_coff > 63)
608                 q_i_coff = 63;
609         if (q_q_coff < -63)
610                 q_q_coff = -63;
611         if (q_q_coff > 63)
612                 q_q_coff = 63;
613
614         iqc_coeff[1] = (q_q_coff * 128) + q_i_coff;
615
616         ath_print(common, ATH_DBG_CALIBRATE,
617                   "rx chain %d: iq corr coeff=%x\n",
618                   chain_idx, iqc_coeff[1]);
619
620         return true;
621 }
622
623 static void ar9003_hw_tx_iq_cal(struct ath_hw *ah)
624 {
625         struct ath_common *common = ath9k_hw_common(ah);
626         const u32 txiqcal_status[AR9300_MAX_CHAINS] = {
627                 AR_PHY_TX_IQCAL_STATUS_B0,
628                 AR_PHY_TX_IQCAL_STATUS_B1,
629                 AR_PHY_TX_IQCAL_STATUS_B2,
630         };
631         const u32 tx_corr_coeff[AR9300_MAX_CHAINS] = {
632                 AR_PHY_TX_IQCAL_CORR_COEFF_01_B0,
633                 AR_PHY_TX_IQCAL_CORR_COEFF_01_B1,
634                 AR_PHY_TX_IQCAL_CORR_COEFF_01_B2,
635         };
636         const u32 rx_corr[AR9300_MAX_CHAINS] = {
637                 AR_PHY_RX_IQCAL_CORR_B0,
638                 AR_PHY_RX_IQCAL_CORR_B1,
639                 AR_PHY_RX_IQCAL_CORR_B2,
640         };
641         const u_int32_t chan_info_tab[] = {
642                 AR_PHY_CHAN_INFO_TAB_0,
643                 AR_PHY_CHAN_INFO_TAB_1,
644                 AR_PHY_CHAN_INFO_TAB_2,
645         };
646         s32 iq_res[6];
647         s32 iqc_coeff[2];
648         s32 i, j;
649         u32 num_chains = 0;
650
651         for (i = 0; i < AR9300_MAX_CHAINS; i++) {
652                 if (ah->txchainmask & (1 << i))
653                         num_chains++;
654         }
655
656         REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1,
657                       AR_PHY_TX_IQCAQL_CONTROL_1_IQCORR_I_Q_COFF_DELPT,
658                       DELPT);
659         REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START,
660                       AR_PHY_TX_IQCAL_START_DO_CAL,
661                       AR_PHY_TX_IQCAL_START_DO_CAL);
662
663         if (!ath9k_hw_wait(ah, AR_PHY_TX_IQCAL_START,
664                            AR_PHY_TX_IQCAL_START_DO_CAL,
665                            0, AH_WAIT_TIMEOUT)) {
666                 ath_print(common, ATH_DBG_CALIBRATE,
667                           "Tx IQ Cal not complete.\n");
668                 goto TX_IQ_CAL_FAILED;
669         }
670
671         for (i = 0; i < num_chains; i++) {
672                 ath_print(common, ATH_DBG_CALIBRATE,
673                           "Doing Tx IQ Cal for chain %d.\n", i);
674
675                 if (REG_READ(ah, txiqcal_status[i]) &
676                              AR_PHY_TX_IQCAL_STATUS_FAILED) {
677                         ath_print(common, ATH_DBG_CALIBRATE,
678                                   "Tx IQ Cal failed for chain %d.\n", i);
679                         goto TX_IQ_CAL_FAILED;
680                 }
681
682                 for (j = 0; j < 3; j++) {
683                         u_int8_t idx = 2 * j,
684                         offset = 4 * j;
685
686                         REG_RMW_FIELD(ah, AR_PHY_CHAN_INFO_MEMORY,
687                                       AR_PHY_CHAN_INFO_TAB_S2_READ, 0);
688
689                         /* 32 bits */
690                         iq_res[idx] = REG_READ(ah, chan_info_tab[i] + offset);
691
692                         REG_RMW_FIELD(ah, AR_PHY_CHAN_INFO_MEMORY,
693                                       AR_PHY_CHAN_INFO_TAB_S2_READ, 1);
694
695                         /* 16 bits */
696                         iq_res[idx+1] = 0xffff & REG_READ(ah,
697                                                           chan_info_tab[i] +
698                                                           offset);
699
700                         ath_print(common, ATH_DBG_CALIBRATE,
701                                   "IQ RES[%d]=0x%x IQ_RES[%d]=0x%x\n",
702                                   idx, iq_res[idx], idx+1, iq_res[idx+1]);
703                 }
704
705                 if (!ar9003_hw_calc_iq_corr(ah, i, iq_res, iqc_coeff)) {
706                         ath_print(common, ATH_DBG_CALIBRATE,
707                                   "Failed in calculation of IQ correction.\n");
708                         goto TX_IQ_CAL_FAILED;
709                 }
710
711                 ath_print(common, ATH_DBG_CALIBRATE,
712                           "IQ_COEFF[0] = 0x%x IQ_COEFF[1] = 0x%x\n",
713                           iqc_coeff[0], iqc_coeff[1]);
714
715                 REG_RMW_FIELD(ah, tx_corr_coeff[i],
716                               AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE,
717                               iqc_coeff[0]);
718                 REG_RMW_FIELD(ah, rx_corr[i],
719                               AR_PHY_RX_IQCAL_CORR_LOOPBACK_IQCORR_Q_Q_COFF,
720                               iqc_coeff[1] >> 7);
721                 REG_RMW_FIELD(ah, rx_corr[i],
722                               AR_PHY_RX_IQCAL_CORR_LOOPBACK_IQCORR_Q_I_COFF,
723                               iqc_coeff[1]);
724         }
725
726         REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_3,
727                       AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN, 0x1);
728         REG_RMW_FIELD(ah, AR_PHY_RX_IQCAL_CORR_B0,
729                       AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, 0x1);
730
731         return;
732
733 TX_IQ_CAL_FAILED:
734         ath_print(common, ATH_DBG_CALIBRATE, "Tx IQ Cal failed\n");
735 }
736
737 static bool ar9003_hw_init_cal(struct ath_hw *ah,
738                                struct ath9k_channel *chan)
739 {
740         struct ath_common *common = ath9k_hw_common(ah);
741
742         /*
743          * 0x7 = 0b111 , AR9003 needs to be configured for 3-chain mode before
744          * running AGC/TxIQ cals
745          */
746         ar9003_hw_set_chain_masks(ah, 0x7, 0x7);
747
748         /* Do Tx IQ Calibration */
749         ar9003_hw_tx_iq_cal(ah);
750         REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS);
751         udelay(5);
752         REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
753
754         /* Calibrate the AGC */
755         REG_WRITE(ah, AR_PHY_AGC_CONTROL,
756                   REG_READ(ah, AR_PHY_AGC_CONTROL) |
757                   AR_PHY_AGC_CONTROL_CAL);
758
759         /* Poll for offset calibration complete */
760         if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL,
761                            0, AH_WAIT_TIMEOUT)) {
762                 ath_print(common, ATH_DBG_CALIBRATE,
763                           "offset calibration failed to "
764                           "complete in 1ms; noisy environment?\n");
765                 return false;
766         }
767
768         /* Revert chainmasks to their original values before NF cal */
769         ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
770
771         ath9k_hw_start_nfcal(ah, true);
772
773         /* Initialize list pointers */
774         ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL;
775
776         if (ar9003_hw_iscal_supported(ah, IQ_MISMATCH_CAL)) {
777                 INIT_CAL(&ah->iq_caldata);
778                 INSERT_CAL(ah, &ah->iq_caldata);
779                 ath_print(common, ATH_DBG_CALIBRATE,
780                           "enabling IQ Calibration.\n");
781         }
782
783         if (ar9003_hw_iscal_supported(ah, TEMP_COMP_CAL)) {
784                 INIT_CAL(&ah->tempCompCalData);
785                 INSERT_CAL(ah, &ah->tempCompCalData);
786                 ath_print(common, ATH_DBG_CALIBRATE,
787                           "enabling Temperature Compensation Calibration.\n");
788         }
789
790         /* Initialize current pointer to first element in list */
791         ah->cal_list_curr = ah->cal_list;
792
793         if (ah->cal_list_curr)
794                 ath9k_hw_reset_calibration(ah, ah->cal_list_curr);
795
796         chan->CalValid = 0;
797
798         return true;
799 }
800
801 void ar9003_hw_attach_calib_ops(struct ath_hw *ah)
802 {
803         struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
804         struct ath_hw_ops *ops = ath9k_hw_ops(ah);
805
806         priv_ops->init_cal_settings = ar9003_hw_init_cal_settings;
807         priv_ops->init_cal = ar9003_hw_init_cal;
808         priv_ops->setup_calibration = ar9003_hw_setup_calibration;
809         priv_ops->iscal_supported = ar9003_hw_iscal_supported;
810
811         ops->calibrate = ar9003_hw_calibrate;
812 }