ath9k_hw: abstract the AR_PHY_AGC_CONTROL register access
[deliverable/linux.git] / drivers / net / wireless / ath / ath9k / ar9003_calib.c
CommitLineData
795f5e2c
LR
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
21static void ar9003_hw_setup_calibration(struct ath_hw *ah,
22 struct ath9k_cal_list *currCal)
23{
24 /* TODO */
25}
26
27static bool ar9003_hw_calibrate(struct ath_hw *ah,
28 struct ath9k_channel *chan,
29 u8 rxchainmask,
30 bool longcal)
31{
32 /* TODO */
33 return false;
34}
35
36static bool ar9003_hw_init_cal(struct ath_hw *ah,
37 struct ath9k_channel *chan)
38{
39 /* TODO */
40 return false;
41}
42
590b7d2f
LR
43static void ar9003_hw_iqcal_collect(struct ath_hw *ah)
44{
45 int i;
46
47 /* Accumulate IQ cal measures for active chains */
48 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
49 ah->totalPowerMeasI[i] +=
50 REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
51 ah->totalPowerMeasQ[i] +=
52 REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
53 ah->totalIqCorrMeas[i] +=
54 (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
55 ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
56 "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
57 ah->cal_samples, i, ah->totalPowerMeasI[i],
58 ah->totalPowerMeasQ[i],
59 ah->totalIqCorrMeas[i]);
60 }
61}
62
63static void ar9003_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
64{
65 struct ath_common *common = ath9k_hw_common(ah);
66 u32 powerMeasQ, powerMeasI, iqCorrMeas;
67 u32 qCoffDenom, iCoffDenom;
68 int32_t qCoff, iCoff;
69 int iqCorrNeg, i;
70 const u_int32_t offset_array[3] = {
71 AR_PHY_RX_IQCAL_CORR_B0,
72 AR_PHY_RX_IQCAL_CORR_B1,
73 AR_PHY_RX_IQCAL_CORR_B2,
74 };
75
76 for (i = 0; i < numChains; i++) {
77 powerMeasI = ah->totalPowerMeasI[i];
78 powerMeasQ = ah->totalPowerMeasQ[i];
79 iqCorrMeas = ah->totalIqCorrMeas[i];
80
81 ath_print(common, ATH_DBG_CALIBRATE,
82 "Starting IQ Cal and Correction for Chain %d\n",
83 i);
84
85 ath_print(common, ATH_DBG_CALIBRATE,
86 "Orignal: Chn %diq_corr_meas = 0x%08x\n",
87 i, ah->totalIqCorrMeas[i]);
88
89 iqCorrNeg = 0;
90
91 if (iqCorrMeas > 0x80000000) {
92 iqCorrMeas = (0xffffffff - iqCorrMeas) + 1;
93 iqCorrNeg = 1;
94 }
95
96 ath_print(common, ATH_DBG_CALIBRATE,
97 "Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI);
98 ath_print(common, ATH_DBG_CALIBRATE,
99 "Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ);
100 ath_print(common, ATH_DBG_CALIBRATE, "iqCorrNeg is 0x%08x\n",
101 iqCorrNeg);
102
103 iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 256;
104 qCoffDenom = powerMeasQ / 64;
105
106 if ((iCoffDenom != 0) && (qCoffDenom != 0)) {
107 iCoff = iqCorrMeas / iCoffDenom;
108 qCoff = powerMeasI / qCoffDenom - 64;
109 ath_print(common, ATH_DBG_CALIBRATE,
110 "Chn %d iCoff = 0x%08x\n", i, iCoff);
111 ath_print(common, ATH_DBG_CALIBRATE,
112 "Chn %d qCoff = 0x%08x\n", i, qCoff);
113
114 /* Force bounds on iCoff */
115 if (iCoff >= 63)
116 iCoff = 63;
117 else if (iCoff <= -63)
118 iCoff = -63;
119
120 /* Negate iCoff if iqCorrNeg == 0 */
121 if (iqCorrNeg == 0x0)
122 iCoff = -iCoff;
123
124 /* Force bounds on qCoff */
125 if (qCoff >= 63)
126 qCoff = 63;
127 else if (qCoff <= -63)
128 qCoff = -63;
129
130 iCoff = iCoff & 0x7f;
131 qCoff = qCoff & 0x7f;
132
133 ath_print(common, ATH_DBG_CALIBRATE,
134 "Chn %d : iCoff = 0x%x qCoff = 0x%x\n",
135 i, iCoff, qCoff);
136 ath_print(common, ATH_DBG_CALIBRATE,
137 "Register offset (0x%04x) "
138 "before update = 0x%x\n",
139 offset_array[i],
140 REG_READ(ah, offset_array[i]));
141
142 REG_RMW_FIELD(ah, offset_array[i],
143 AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF,
144 iCoff);
145 REG_RMW_FIELD(ah, offset_array[i],
146 AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF,
147 qCoff);
148 ath_print(common, ATH_DBG_CALIBRATE,
149 "Register offset (0x%04x) QI COFF "
150 "(bitfields 0x%08x) after update = 0x%x\n",
151 offset_array[i],
152 AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF,
153 REG_READ(ah, offset_array[i]));
154 ath_print(common, ATH_DBG_CALIBRATE,
155 "Register offset (0x%04x) QQ COFF "
156 "(bitfields 0x%08x) after update = 0x%x\n",
157 offset_array[i],
158 AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF,
159 REG_READ(ah, offset_array[i]));
160
161 ath_print(common, ATH_DBG_CALIBRATE,
162 "IQ Cal and Correction done for Chain %d\n",
163 i);
164 }
165 }
166
167 REG_SET_BIT(ah, AR_PHY_RX_IQCAL_CORR_B0,
168 AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE);
169 ath_print(common, ATH_DBG_CALIBRATE,
170 "IQ Cal and Correction (offset 0x%04x) enabled "
171 "(bit position 0x%08x). New Value 0x%08x\n",
172 (unsigned) (AR_PHY_RX_IQCAL_CORR_B0),
173 AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE,
174 REG_READ(ah, AR_PHY_RX_IQCAL_CORR_B0));
175}
176
177static const struct ath9k_percal_data iq_cal_single_sample = {
178 IQ_MISMATCH_CAL,
179 MIN_CAL_SAMPLES,
180 PER_MAX_LOG_COUNT,
181 ar9003_hw_iqcal_collect,
182 ar9003_hw_iqcalibrate
183};
184
795f5e2c
LR
185static void ar9003_hw_init_cal_settings(struct ath_hw *ah)
186{
590b7d2f
LR
187 ah->iq_caldata.calData = &iq_cal_single_sample;
188 ah->supp_cals = IQ_MISMATCH_CAL;
795f5e2c
LR
189}
190
191static bool ar9003_hw_iscal_supported(struct ath_hw *ah,
192 enum ath9k_cal_types calType)
193{
194 /* TODO */
195 return false;
196}
197
198void ar9003_hw_attach_calib_ops(struct ath_hw *ah)
199{
200 struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
201 struct ath_hw_ops *ops = ath9k_hw_ops(ah);
202
203 priv_ops->init_cal_settings = ar9003_hw_init_cal_settings;
204 priv_ops->init_cal = ar9003_hw_init_cal;
205 priv_ops->setup_calibration = ar9003_hw_setup_calibration;
206 priv_ops->iscal_supported = ar9003_hw_iscal_supported;
207
208 ops->calibrate = ar9003_hw_calibrate;
209}
This page took 0.113534 seconds and 5 git commands to generate.