iPXE
Data Structures | Macros | Enumerations | Functions | Variables
ath9k_ar9003_calib.c File Reference
#include <ipxe/io.h>
#include "hw.h"
#include "hw-ops.h"
#include "ar9003_phy.h"

Go to the source code of this file.

Data Structures

struct  coeff
 

Macros

#define MAX_MEASUREMENT   8
 
#define MAX_MAG_DELTA   11
 
#define MAX_PHS_DELTA   10
 
#define DELPT   32
 

Enumerations

enum  ar9003_cal_types { IQ_MISMATCH_CAL = BIT(0), TEMP_COMP_CAL = BIT(1) }
 

Functions

 FILE_SECBOOT (FORBIDDEN)
 
static void ar9003_hw_setup_calibration (struct ath_hw *ah, struct ath9k_cal_list *currCal)
 
static int ar9003_hw_per_calibration (struct ath_hw *ah, struct ath9k_channel *ichan __unused, u8 rxchainmask, struct ath9k_cal_list *currCal)
 
static int ar9003_hw_calibrate (struct ath_hw *ah, struct ath9k_channel *chan, u8 rxchainmask, int longcal)
 
static void ar9003_hw_iqcal_collect (struct ath_hw *ah)
 
static void ar9003_hw_iqcalibrate (struct ath_hw *ah, u8 numChains)
 
static void ar9003_hw_init_cal_settings (struct ath_hw *ah)
 
static int ar9003_hw_solve_iq_cal (struct ath_hw *ah __unused, s32 sin_2phi_1, s32 cos_2phi_1, s32 sin_2phi_2, s32 cos_2phi_2, s32 mag_a0_d0, s32 phs_a0_d0, s32 mag_a1_d0, s32 phs_a1_d0, s32 solved_eq[])
 
static s32 ar9003_hw_find_mag_approx (struct ath_hw *ah __unused, s32 in_re, s32 in_im)
 
static int ar9003_hw_calc_iq_corr (struct ath_hw *ah, s32 chain_idx, const s32 iq_res[], s32 iqc_coeff[])
 
static void ar9003_hw_detect_outlier (int *mp_coeff, int nmeasurement, int max_delta)
 
static void ar9003_hw_tx_iqcal_load_avg_2_passes (struct ath_hw *ah, u8 num_chains, struct coeff *coeff)
 
static int ar9003_hw_tx_iq_cal_run (struct ath_hw *ah)
 
static void ar9003_hw_tx_iq_cal_post_proc (struct ath_hw *ah)
 
static int ar9003_hw_init_cal (struct ath_hw *ah, struct ath9k_channel *chan __unused)
 
void ar9003_hw_attach_calib_ops (struct ath_hw *ah)
 

Variables

static const struct ath9k_percal_data iq_cal_single_sample
 

Macro Definition Documentation

◆ MAX_MEASUREMENT

#define MAX_MEASUREMENT   8

Definition at line 28 of file ath9k_ar9003_calib.c.

◆ MAX_MAG_DELTA

#define MAX_MAG_DELTA   11

Definition at line 29 of file ath9k_ar9003_calib.c.

◆ MAX_PHS_DELTA

#define MAX_PHS_DELTA   10

Definition at line 30 of file ath9k_ar9003_calib.c.

◆ DELPT

#define DELPT   32

Definition at line 397 of file ath9k_ar9003_calib.c.

Enumeration Type Documentation

◆ ar9003_cal_types

Enumerator
IQ_MISMATCH_CAL 
TEMP_COMP_CAL 

Definition at line 38 of file ath9k_ar9003_calib.c.

38  {
39  IQ_MISMATCH_CAL = BIT(0),
40  TEMP_COMP_CAL = BIT(1),
41 };
#define BIT(nr)
Definition: ath.h:34

Function Documentation

◆ FILE_SECBOOT()

FILE_SECBOOT ( FORBIDDEN  )

◆ ar9003_hw_setup_calibration()

static void ar9003_hw_setup_calibration ( struct ath_hw ah,
struct ath9k_cal_list currCal 
)
static

Definition at line 43 of file ath9k_ar9003_calib.c.

45 {
46  /* Select calibration to run */
47  switch (currCal->calData->calType) {
48  case IQ_MISMATCH_CAL:
49  /*
50  * Start calibration with
51  * 2^(INIT_IQCAL_LOG_COUNT_MAX+1) samples
52  */
55  currCal->calData->calCountMax);
57 
58  DBG2("ath9k: "
59  "starting IQ Mismatch Calibration\n");
60 
61  /* Kick-off cal */
63  break;
64  case TEMP_COMP_CAL:
69 
70  DBG2("ath9k: "
71  "starting Temperature Compensation Calibration\n");
72  break;
73  }
74 }
#define AR_PHY_CALMODE
Definition: ar9002_phy.h:374
#define REG_RMW_FIELD(_a, _r, _f, _v)
Definition: hw.h:104
#define AR_PHY_65NM_CH0_THERM_START
Definition: ar9003_phy.h:616
#define AR_PHY_65NM_CH0_THERM_LOCAL
Definition: ar9003_phy.h:614
#define AR_PHY_TIMING4_IQCAL_LOG_COUNT_MAX
Definition: ar9003_phy.h:110
#define AR_PHY_65NM_CH0_THERM
Definition: ar9003_phy.h:612
#define AR_PHY_TIMING4_DO_CAL
Definition: ar9003_phy.h:112
const struct ath9k_percal_data * calData
Definition: calib.h:89
#define REG_SET_BIT(_a, _r, _f)
Definition: hw.h:108
u32 calCountMax
Definition: calib.h:83
#define REG_WRITE(_ah, _reg, _val)
Definition: hw.h:78
uint8_t ah
Definition: registers.h:85
#define AR_PHY_TIMING4
Definition: ar9003_phy.h:30
#define DBG2(...)
Definition: compiler.h:515
#define AR_PHY_CALMODE_IQ
Definition: ar9002_phy.h:376

References ah, AR_PHY_65NM_CH0_THERM, AR_PHY_65NM_CH0_THERM_LOCAL, AR_PHY_65NM_CH0_THERM_START, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ, AR_PHY_TIMING4, AR_PHY_TIMING4_DO_CAL, AR_PHY_TIMING4_IQCAL_LOG_COUNT_MAX, ath9k_percal_data::calCountMax, ath9k_cal_list::calData, ath9k_percal_data::calType, DBG2, IQ_MISMATCH_CAL, REG_RMW_FIELD, REG_SET_BIT, REG_WRITE, and TEMP_COMP_CAL.

Referenced by ar9003_hw_attach_calib_ops(), and ar9003_hw_per_calibration().

◆ ar9003_hw_per_calibration()

static int ar9003_hw_per_calibration ( struct ath_hw ah,
struct ath9k_channel *ichan  __unused,
u8  rxchainmask,
struct ath9k_cal_list currCal 
)
static

Definition at line 81 of file ath9k_ar9003_calib.c.

85 {
86  struct ath9k_hw_cal_data *caldata = ah->caldata;
87  /* Cal is assumed not done until explicitly set below */
88  int iscaldone = 0;
89 
90  /* Calibration in progress. */
91  if (currCal->calState == CAL_RUNNING) {
92  /* Check to see if it has finished. */
94  /*
95  * Accumulate cal measures for active chains
96  */
97  currCal->calData->calCollect(ah);
98  ah->cal_samples++;
99 
100  if (ah->cal_samples >=
101  currCal->calData->calNumSamples) {
102  unsigned int i, numChains = 0;
103  for (i = 0; i < AR9300_MAX_CHAINS; i++) {
104  if (rxchainmask & (1 << i))
105  numChains++;
106  }
107 
108  /*
109  * Process accumulated data
110  */
111  currCal->calData->calPostProc(ah, numChains);
112 
113  /* Calibration has finished. */
114  caldata->CalValid |= currCal->calData->calType;
115  currCal->calState = CAL_DONE;
116  iscaldone = 1;
117  } else {
118  /*
119  * Set-up collection of another sub-sample until we
120  * get desired number
121  */
123  }
124  }
125  } else if (!(caldata->CalValid & currCal->calData->calType)) {
126  /* If current cal is marked invalid in channel, kick it off */
127  ath9k_hw_reset_calibration(ah, currCal);
128  }
129 
130  return iscaldone;
131 }
#define AR9300_MAX_CHAINS
Definition: ar9003_eeprom.h:50
static void ar9003_hw_setup_calibration(struct ath_hw *ah, struct ath9k_cal_list *currCal)
void(* calPostProc)(struct ath_hw *, u8)
Definition: calib.h:85
int32_t CalValid
Definition: hw.h:336
u32 calNumSamples
Definition: calib.h:82
Definition: calib.h:71
void(* calCollect)(struct ath_hw *)
Definition: calib.h:84
#define AR_PHY_TIMING4_DO_CAL
Definition: ar9003_phy.h:112
const struct ath9k_percal_data * calData
Definition: calib.h:89
#define REG_READ(_ah, _reg)
Definition: hw.h:81
uint8_t ah
Definition: registers.h:85
#define AR_PHY_TIMING4
Definition: ar9003_phy.h:30
void ath9k_hw_reset_calibration(struct ath_hw *ah, struct ath9k_cal_list *currCal)
Definition: ath9k_calib.c:155
enum ath9k_cal_state calState
Definition: calib.h:90

References ah, ar9003_hw_setup_calibration(), AR9300_MAX_CHAINS, AR_PHY_TIMING4, AR_PHY_TIMING4_DO_CAL, ath9k_hw_reset_calibration(), CAL_DONE, CAL_RUNNING, ath9k_percal_data::calCollect, ath9k_cal_list::calData, ath9k_percal_data::calNumSamples, ath9k_percal_data::calPostProc, ath9k_cal_list::calState, ath9k_percal_data::calType, ath9k_hw_cal_data::CalValid, and REG_READ.

Referenced by ar9003_hw_calibrate().

◆ ar9003_hw_calibrate()

static int ar9003_hw_calibrate ( struct ath_hw ah,
struct ath9k_channel chan,
u8  rxchainmask,
int  longcal 
)
static

Definition at line 133 of file ath9k_ar9003_calib.c.

137 {
138  int iscaldone = 1;
139  struct ath9k_cal_list *currCal = ah->cal_list_curr;
140 
141  /*
142  * For given calibration:
143  * 1. Call generic cal routine
144  * 2. When this cal is done (isCalDone) if we have more cals waiting
145  * (eg after reset), mask this to upper layers by not propagating
146  * isCalDone if it is set to TRUE.
147  * Instead, change isCalDone to FALSE and setup the waiting cal(s)
148  * to be run.
149  */
150  if (currCal &&
151  (currCal->calState == CAL_RUNNING ||
152  currCal->calState == CAL_WAITING)) {
153  iscaldone = ar9003_hw_per_calibration(ah, chan,
154  rxchainmask, currCal);
155  if (iscaldone) {
156  ah->cal_list_curr = currCal = currCal->calNext;
157 
158  if (currCal->calState == CAL_WAITING) {
159  iscaldone = 0;
160  ath9k_hw_reset_calibration(ah, currCal);
161  }
162  }
163  }
164 
165  /* Do NF cal only at longer intervals */
166  if (longcal) {
167  /*
168  * Get the value from the previous NF cal and update
169  * history buffer.
170  */
171  ath9k_hw_getnf(ah, chan);
172 
173  /*
174  * Load the NF from history buffer of the current channel.
175  * NF is slow time-variant, so it is OK to use a historical
176  * value.
177  */
178  ath9k_hw_loadnf(ah, ah->curchan);
179 
180  /* start NF calibration, without updating BB NF register */
182  }
183 
184  return iscaldone;
185 }
static int ar9003_hw_per_calibration(struct ath_hw *ah, struct ath9k_channel *ichan __unused, u8 rxchainmask, struct ath9k_cal_list *currCal)
void ath9k_hw_start_nfcal(struct ath_hw *ah, int update)
Definition: ath9k_calib.c:208
struct ath9k_cal_list * calNext
Definition: calib.h:91
void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan)
Definition: ath9k_calib.c:226
int ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan)
Definition: ath9k_calib.c:348
uint8_t ah
Definition: registers.h:85
void ath9k_hw_reset_calibration(struct ath_hw *ah, struct ath9k_cal_list *currCal)
Definition: ath9k_calib.c:155
enum ath9k_cal_state calState
Definition: calib.h:90

References ah, ar9003_hw_per_calibration(), ath9k_hw_getnf(), ath9k_hw_loadnf(), ath9k_hw_reset_calibration(), ath9k_hw_start_nfcal(), CAL_RUNNING, CAL_WAITING, ath9k_cal_list::calNext, and ath9k_cal_list::calState.

Referenced by ar9003_hw_attach_calib_ops().

◆ ar9003_hw_iqcal_collect()

static void ar9003_hw_iqcal_collect ( struct ath_hw ah)
static

Definition at line 187 of file ath9k_ar9003_calib.c.

188 {
189  int i;
190 
191  /* Accumulate IQ cal measures for active chains */
192  for (i = 0; i < AR5416_MAX_CHAINS; i++) {
193  if (ah->txchainmask & BIT(i)) {
194  ah->totalPowerMeasI[i] +=
196  ah->totalPowerMeasQ[i] +=
198  ah->totalIqCorrMeas[i] +=
200  DBG2("ath9k: "
201  "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
202  ah->cal_samples, i, ah->totalPowerMeasI[i],
203  ah->totalPowerMeasQ[i],
204  ah->totalIqCorrMeas[i]);
205  }
206  }
207 }
#define AR_PHY_CAL_MEAS_2(_i)
Definition: ar9002_phy.h:383
#define REG_READ(_ah, _reg)
Definition: hw.h:81
#define AR5416_MAX_CHAINS
Definition: eeprom.h:160
#define BIT(nr)
Definition: ath.h:34
signed int int32_t
Definition: stdint.h:17
#define AR_PHY_CAL_MEAS_1(_i)
Definition: ar9002_phy.h:382
uint8_t ah
Definition: registers.h:85
#define AR_PHY_CAL_MEAS_0(_i)
Definition: ar9002_phy.h:381
#define DBG2(...)
Definition: compiler.h:515

References ah, AR5416_MAX_CHAINS, AR_PHY_CAL_MEAS_0, AR_PHY_CAL_MEAS_1, AR_PHY_CAL_MEAS_2, BIT, DBG2, and REG_READ.

◆ ar9003_hw_iqcalibrate()

static void ar9003_hw_iqcalibrate ( struct ath_hw ah,
u8  numChains 
)
static

Definition at line 209 of file ath9k_ar9003_calib.c.

210 {
211  u32 powerMeasQ, powerMeasI, iqCorrMeas;
212  u32 qCoffDenom, iCoffDenom;
213  int32_t qCoff, iCoff;
214  int iqCorrNeg, i;
215  static const uint32_t offset_array[3] = {
219  };
220 
221  for (i = 0; i < numChains; i++) {
222  powerMeasI = ah->totalPowerMeasI[i];
223  powerMeasQ = ah->totalPowerMeasQ[i];
224  iqCorrMeas = ah->totalIqCorrMeas[i];
225 
226  DBG2("ath9k: "
227  "Starting IQ Cal and Correction for Chain %d\n",
228  i);
229 
230  DBG2("ath9k: "
231  "Orignal: Chn %diq_corr_meas = 0x%08x\n",
232  i, ah->totalIqCorrMeas[i]);
233 
234  iqCorrNeg = 0;
235 
236  if (iqCorrMeas > 0x80000000) {
237  iqCorrMeas = (0xffffffff - iqCorrMeas) + 1;
238  iqCorrNeg = 1;
239  }
240 
241  DBG2("ath9k: "
242  "Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI);
243  DBG2("ath9k: "
244  "Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ);
245  DBG2("ath9k: iqCorrNeg is 0x%08x\n",
246  iqCorrNeg);
247 
248  iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 256;
249  qCoffDenom = powerMeasQ / 64;
250 
251  if ((iCoffDenom != 0) && (qCoffDenom != 0)) {
252  iCoff = iqCorrMeas / iCoffDenom;
253  qCoff = powerMeasI / qCoffDenom - 64;
254  DBG2("ath9k: "
255  "Chn %d iCoff = 0x%08x\n", i, iCoff);
256  DBG2("ath9k: "
257  "Chn %d qCoff = 0x%08x\n", i, qCoff);
258 
259  /* Force bounds on iCoff */
260  if (iCoff >= 63)
261  iCoff = 63;
262  else if (iCoff <= -63)
263  iCoff = -63;
264 
265  /* Negate iCoff if iqCorrNeg == 0 */
266  if (iqCorrNeg == 0x0)
267  iCoff = -iCoff;
268 
269  /* Force bounds on qCoff */
270  if (qCoff >= 63)
271  qCoff = 63;
272  else if (qCoff <= -63)
273  qCoff = -63;
274 
275  iCoff = iCoff & 0x7f;
276  qCoff = qCoff & 0x7f;
277 
278  DBG2("ath9k: "
279  "Chn %d : iCoff = 0x%x qCoff = 0x%x\n",
280  i, iCoff, qCoff);
281  DBG2("ath9k: "
282  "Register offset (0x%04x) before update = 0x%x\n",
283  offset_array[i],
284  REG_READ(ah, offset_array[i]));
285 
286  REG_RMW_FIELD(ah, offset_array[i],
288  iCoff);
289  REG_RMW_FIELD(ah, offset_array[i],
291  qCoff);
292  DBG2("ath9k: "
293  "Register offset (0x%04x) QI COFF (bitfields 0x%08x) after update = 0x%x\n",
294  offset_array[i],
296  REG_READ(ah, offset_array[i]));
297  DBG2("ath9k: "
298  "Register offset (0x%04x) QQ COFF (bitfields 0x%08x) after update = 0x%x\n",
299  offset_array[i],
301  REG_READ(ah, offset_array[i]));
302 
303  DBG2("ath9k: "
304  "IQ Cal and Correction done for Chain %d\n", i);
305  }
306  }
307 
310  DBG2("ath9k: "
311  "IQ Cal and Correction (offset 0x%04x) enabled (bit position 0x%08x). New Value 0x%08x\n",
312  (unsigned) (AR_PHY_RX_IQCAL_CORR_B0),
315 }
#define AR_PHY_RX_IQCAL_CORR_B1
Definition: ar9003_phy.h:810
#define AR_PHY_RX_IQCAL_CORR_B2
Definition: ar9003_phy.h:866
#define AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF
Definition: ar9003_phy.h:205
#define REG_RMW_FIELD(_a, _r, _f, _v)
Definition: hw.h:104
unsigned int uint32_t
Definition: stdint.h:12
#define REG_READ(_ah, _reg)
Definition: hw.h:81
#define REG_SET_BIT(_a, _r, _f)
Definition: hw.h:108
signed int int32_t
Definition: stdint.h:17
#define AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF
Definition: ar9003_phy.h:203
uint8_t ah
Definition: registers.h:85
#define AR_PHY_RX_IQCAL_CORR_B0
Definition: ar9003_phy.h:35
#define AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE
Definition: ar9003_phy.h:207
uint32_t u32
Definition: stdint.h:24
#define DBG2(...)
Definition: compiler.h:515

References ah, AR_PHY_RX_IQCAL_CORR_B0, AR_PHY_RX_IQCAL_CORR_B1, AR_PHY_RX_IQCAL_CORR_B2, AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE, AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF, AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF, DBG2, REG_READ, REG_RMW_FIELD, and REG_SET_BIT.

◆ ar9003_hw_init_cal_settings()

static void ar9003_hw_init_cal_settings ( struct ath_hw ah)
static

Definition at line 325 of file ath9k_ar9003_calib.c.

326 {
327  ah->iq_caldata.calData = &iq_cal_single_sample;
328 }
static const struct ath9k_percal_data iq_cal_single_sample
uint8_t ah
Definition: registers.h:85

References ah, and iq_cal_single_sample.

Referenced by ar9003_hw_attach_calib_ops().

◆ ar9003_hw_solve_iq_cal()

static int ar9003_hw_solve_iq_cal ( struct ath_hw *ah  __unused,
s32  sin_2phi_1,
s32  cos_2phi_1,
s32  sin_2phi_2,
s32  cos_2phi_2,
s32  mag_a0_d0,
s32  phs_a0_d0,
s32  mag_a1_d0,
s32  phs_a1_d0,
s32  solved_eq[] 
)
static

Definition at line 333 of file ath9k_ar9003_calib.c.

343 {
344  s32 f1 = cos_2phi_1 - cos_2phi_2,
345  f3 = sin_2phi_1 - sin_2phi_2,
346  f2;
347  s32 mag_tx, phs_tx, mag_rx, phs_rx;
348  const s32 result_shift = 1 << 15;
349 
350  f2 = (f1 * f1 + f3 * f3) / result_shift;
351 
352  if (!f2) {
353  DBG("ath9k: Divide by 0\n");
354  return 0;
355  }
356 
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);
361 
362  mag_tx = (mag_tx / f2);
363  phs_tx = (phs_tx / f2);
364 
365  /* mag mismatch, rx */
366  mag_rx = mag_a0_d0 - (cos_2phi_1 * mag_tx + sin_2phi_1 * phs_tx) /
367  result_shift;
368  /* phs mismatch, rx */
369  phs_rx = phs_a0_d0 + (sin_2phi_1 * mag_tx - cos_2phi_1 * phs_tx) /
370  result_shift;
371 
372  solved_eq[0] = mag_tx;
373  solved_eq[1] = phs_tx;
374  solved_eq[2] = mag_rx;
375  solved_eq[3] = phs_rx;
376 
377  return 1;
378 }
int32_t s32
Definition: stdint.h:23
#define DBG(...)
Print a debugging message.
Definition: compiler.h:498

References DBG.

Referenced by ar9003_hw_calc_iq_corr().

◆ ar9003_hw_find_mag_approx()

static s32 ar9003_hw_find_mag_approx ( struct ath_hw *ah  __unused,
s32  in_re,
s32  in_im 
)
static

Definition at line 380 of file ath9k_ar9003_calib.c.

381 {
382  s32 abs_i = abs(in_re),
383  abs_q = abs(in_im),
384  max_abs, min_abs;
385 
386  if (abs_i > abs_q) {
387  max_abs = abs_i;
388  min_abs = abs_q;
389  } else {
390  max_abs = abs_q;
391  min_abs = abs_i;
392  }
393 
394  return max_abs - (max_abs / 32) + (min_abs / 8) + (min_abs / 4);
395 }
int32_t s32
Definition: stdint.h:23
#define abs(x)
Definition: ath.h:46

References abs.

Referenced by ar9003_hw_calc_iq_corr().

◆ ar9003_hw_calc_iq_corr()

static int ar9003_hw_calc_iq_corr ( struct ath_hw ah,
s32  chain_idx,
const s32  iq_res[],
s32  iqc_coeff[] 
)
static

Definition at line 399 of file ath9k_ar9003_calib.c.

403 {
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,
414  q_q_coff, q_i_coff;
415  const s32 res_scale = 1 << 15;
416  const s32 delpt_shift = 1 << 8;
417  s32 mag1, mag2;
418 
419  i2_m_q2_a0_d0 = iq_res[0] & 0xfff;
420  i2_p_q2_a0_d0 = (iq_res[0] >> 12) & 0xfff;
421  iq_corr_a0_d0 = ((iq_res[0] >> 24) & 0xff) + ((iq_res[1] & 0xf) << 8);
422 
423  if (i2_m_q2_a0_d0 > 0x800)
424  i2_m_q2_a0_d0 = -((0xfff - i2_m_q2_a0_d0) + 1);
425 
426  if (i2_p_q2_a0_d0 > 0x800)
427  i2_p_q2_a0_d0 = -((0xfff - i2_p_q2_a0_d0) + 1);
428 
429  if (iq_corr_a0_d0 > 0x800)
430  iq_corr_a0_d0 = -((0xfff - iq_corr_a0_d0) + 1);
431 
432  i2_m_q2_a0_d1 = (iq_res[1] >> 4) & 0xfff;
433  i2_p_q2_a0_d1 = (iq_res[2] & 0xfff);
434  iq_corr_a0_d1 = (iq_res[2] >> 12) & 0xfff;
435 
436  if (i2_m_q2_a0_d1 > 0x800)
437  i2_m_q2_a0_d1 = -((0xfff - i2_m_q2_a0_d1) + 1);
438 
439  if (i2_p_q2_a0_d1 > 0x800)
440  i2_p_q2_a0_d1 = -((0xfff - i2_p_q2_a0_d1) + 1);
441 
442  if (iq_corr_a0_d1 > 0x800)
443  iq_corr_a0_d1 = -((0xfff - iq_corr_a0_d1) + 1);
444 
445  i2_m_q2_a1_d0 = ((iq_res[2] >> 24) & 0xff) + ((iq_res[3] & 0xf) << 8);
446  i2_p_q2_a1_d0 = (iq_res[3] >> 4) & 0xfff;
447  iq_corr_a1_d0 = iq_res[4] & 0xfff;
448 
449  if (i2_m_q2_a1_d0 > 0x800)
450  i2_m_q2_a1_d0 = -((0xfff - i2_m_q2_a1_d0) + 1);
451 
452  if (i2_p_q2_a1_d0 > 0x800)
453  i2_p_q2_a1_d0 = -((0xfff - i2_p_q2_a1_d0) + 1);
454 
455  if (iq_corr_a1_d0 > 0x800)
456  iq_corr_a1_d0 = -((0xfff - iq_corr_a1_d0) + 1);
457 
458  i2_m_q2_a1_d1 = (iq_res[4] >> 12) & 0xfff;
459  i2_p_q2_a1_d1 = ((iq_res[4] >> 24) & 0xff) + ((iq_res[5] & 0xf) << 8);
460  iq_corr_a1_d1 = (iq_res[5] >> 4) & 0xfff;
461 
462  if (i2_m_q2_a1_d1 > 0x800)
463  i2_m_q2_a1_d1 = -((0xfff - i2_m_q2_a1_d1) + 1);
464 
465  if (i2_p_q2_a1_d1 > 0x800)
466  i2_p_q2_a1_d1 = -((0xfff - i2_p_q2_a1_d1) + 1);
467 
468  if (iq_corr_a1_d1 > 0x800)
469  iq_corr_a1_d1 = -((0xfff - iq_corr_a1_d1) + 1);
470 
471  if ((i2_p_q2_a0_d0 == 0) || (i2_p_q2_a0_d1 == 0) ||
472  (i2_p_q2_a1_d0 == 0) || (i2_p_q2_a1_d1 == 0)) {
473  DBG("ath9k: "
474  "Divide by 0:\n"
475  "a0_d0=%d\n"
476  "a0_d1=%d\n"
477  "a2_d0=%d\n"
478  "a1_d1=%d\n",
479  i2_p_q2_a0_d0, i2_p_q2_a0_d1,
480  i2_p_q2_a1_d0, i2_p_q2_a1_d1);
481  return 0;
482  }
483 
484  mag_a0_d0 = (i2_m_q2_a0_d0 * res_scale) / i2_p_q2_a0_d0;
485  phs_a0_d0 = (iq_corr_a0_d0 * res_scale) / i2_p_q2_a0_d0;
486 
487  mag_a0_d1 = (i2_m_q2_a0_d1 * res_scale) / i2_p_q2_a0_d1;
488  phs_a0_d1 = (iq_corr_a0_d1 * res_scale) / i2_p_q2_a0_d1;
489 
490  mag_a1_d0 = (i2_m_q2_a1_d0 * res_scale) / i2_p_q2_a1_d0;
491  phs_a1_d0 = (iq_corr_a1_d0 * res_scale) / i2_p_q2_a1_d0;
492 
493  mag_a1_d1 = (i2_m_q2_a1_d1 * res_scale) / i2_p_q2_a1_d1;
494  phs_a1_d1 = (iq_corr_a1_d1 * res_scale) / i2_p_q2_a1_d1;
495 
496  /* w/o analog phase shift */
497  sin_2phi_1 = (((mag_a0_d0 - mag_a0_d1) * delpt_shift) / DELPT);
498  /* w/o analog phase shift */
499  cos_2phi_1 = (((phs_a0_d1 - phs_a0_d0) * delpt_shift) / DELPT);
500  /* w/ analog phase shift */
501  sin_2phi_2 = (((mag_a1_d0 - mag_a1_d1) * delpt_shift) / DELPT);
502  /* w/ analog phase shift */
503  cos_2phi_2 = (((phs_a1_d1 - phs_a1_d0) * delpt_shift) / DELPT);
504 
505  /*
506  * force sin^2 + cos^2 = 1;
507  * find magnitude by approximation
508  */
509  mag1 = ar9003_hw_find_mag_approx(ah, cos_2phi_1, sin_2phi_1);
510  mag2 = ar9003_hw_find_mag_approx(ah, cos_2phi_2, sin_2phi_2);
511 
512  if ((mag1 == 0) || (mag2 == 0)) {
513  DBG("ath9k: "
514  "Divide by 0: mag1=%d, mag2=%d\n",
515  mag1, mag2);
516  return 0;
517  }
518 
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);
524 
525  /* calculate IQ mismatch */
527  sin_2phi_1, cos_2phi_1,
528  sin_2phi_2, cos_2phi_2,
529  mag_a0_d0, phs_a0_d0,
530  mag_a1_d0,
531  phs_a1_d0, solved_eq)) {
532  DBG("ath9k: "
533  "Call to ar9003_hw_solve_iq_cal() failed.\n");
534  return 0;
535  }
536 
537  mag_tx = solved_eq[0];
538  phs_tx = solved_eq[1];
539  mag_rx = solved_eq[2];
540  phs_rx = solved_eq[3];
541 
542  DBG2("ath9k: "
543  "chain %d: mag mismatch=%d phase mismatch=%d\n",
544  chain_idx, mag_tx/res_scale, phs_tx/res_scale);
545 
546  if (res_scale == mag_tx) {
547  DBG("ath9k: "
548  "Divide by 0: mag_tx=%d, res_scale=%d\n",
549  mag_tx, res_scale);
550  return 0;
551  }
552 
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;
556 
557  q_q_coff = (mag_corr_tx * 128 / res_scale);
558  q_i_coff = (phs_corr_tx * 256 / res_scale);
559 
560  DBG2("ath9k: "
561  "tx chain %d: mag corr=%d phase corr=%d\n",
562  chain_idx, q_q_coff, q_i_coff);
563 
564  if (q_i_coff < -63)
565  q_i_coff = -63;
566  if (q_i_coff > 63)
567  q_i_coff = 63;
568  if (q_q_coff < -63)
569  q_q_coff = -63;
570  if (q_q_coff > 63)
571  q_q_coff = 63;
572 
573  iqc_coeff[0] = (q_q_coff * 128) + q_i_coff;
574 
575  DBG2("ath9k: "
576  "tx chain %d: iq corr coeff=%x\n",
577  chain_idx, iqc_coeff[0]);
578 
579  if (-mag_rx == res_scale) {
580  DBG("ath9k: "
581  "Divide by 0: mag_rx=%d, res_scale=%d\n",
582  mag_rx, res_scale);
583  return 0;
584  }
585 
586  /* calculate and quantize Rx IQ correction factors */
587  mag_corr_rx = (-mag_rx * res_scale) / (res_scale + mag_rx);
588  phs_corr_rx = -phs_rx;
589 
590  q_q_coff = (mag_corr_rx * 128 / res_scale);
591  q_i_coff = (phs_corr_rx * 256 / res_scale);
592 
593  DBG("ath9k: "
594  "rx chain %d: mag corr=%d phase corr=%d\n",
595  chain_idx, q_q_coff, q_i_coff);
596 
597  if (q_i_coff < -63)
598  q_i_coff = -63;
599  if (q_i_coff > 63)
600  q_i_coff = 63;
601  if (q_q_coff < -63)
602  q_q_coff = -63;
603  if (q_q_coff > 63)
604  q_q_coff = 63;
605 
606  iqc_coeff[1] = (q_q_coff * 128) + q_i_coff;
607 
608  DBG2("ath9k: "
609  "rx chain %d: iq corr coeff=%x\n",
610  chain_idx, iqc_coeff[1]);
611 
612  return 1;
613 }
#define DELPT
int32_t s32
Definition: stdint.h:23
static int ar9003_hw_solve_iq_cal(struct ath_hw *ah __unused, s32 sin_2phi_1, s32 cos_2phi_1, s32 sin_2phi_2, s32 cos_2phi_2, s32 mag_a0_d0, s32 phs_a0_d0, s32 mag_a1_d0, s32 phs_a1_d0, s32 solved_eq[])
uint8_t ah
Definition: registers.h:85
#define DBG(...)
Print a debugging message.
Definition: compiler.h:498
#define DBG2(...)
Definition: compiler.h:515
static s32 ar9003_hw_find_mag_approx(struct ath_hw *ah __unused, s32 in_re, s32 in_im)

References ah, ar9003_hw_find_mag_approx(), ar9003_hw_solve_iq_cal(), DBG, DBG2, and DELPT.

Referenced by ar9003_hw_tx_iq_cal_post_proc().

◆ ar9003_hw_detect_outlier()

static void ar9003_hw_detect_outlier ( int *  mp_coeff,
int  nmeasurement,
int  max_delta 
)
static

Definition at line 615 of file ath9k_ar9003_calib.c.

617 {
618  int mp_max = -64, max_idx = 0;
619  int mp_min = 63, min_idx = 0;
620  int mp_avg = 0, i, outlier_idx = 0;
621 
622  /* find min/max mismatch across all calibrated gains */
623  for (i = 0; i < nmeasurement; i++) {
624  mp_avg += mp_coeff[i];
625  if (mp_coeff[i] > mp_max) {
626  mp_max = mp_coeff[i];
627  max_idx = i;
628  } else if (mp_coeff[i] < mp_min) {
629  mp_min = mp_coeff[i];
630  min_idx = i;
631  }
632  }
633 
634  /* find average (exclude max abs value) */
635  for (i = 0; i < nmeasurement; i++) {
636  if ((abs(mp_coeff[i]) < abs(mp_max)) ||
637  (abs(mp_coeff[i]) < abs(mp_min)))
638  mp_avg += mp_coeff[i];
639  }
640  mp_avg /= (nmeasurement - 1);
641 
642  /* detect outlier */
643  if (abs(mp_max - mp_min) > max_delta) {
644  if (abs(mp_max - mp_avg) > abs(mp_min - mp_avg))
645  outlier_idx = max_idx;
646  else
647  outlier_idx = min_idx;
648  }
649  mp_coeff[outlier_idx] = mp_avg;
650 }
#define abs(x)
Definition: ath.h:46

References abs.

Referenced by ar9003_hw_tx_iqcal_load_avg_2_passes().

◆ ar9003_hw_tx_iqcal_load_avg_2_passes()

static void ar9003_hw_tx_iqcal_load_avg_2_passes ( struct ath_hw ah,
u8  num_chains,
struct coeff coeff 
)
static

Definition at line 652 of file ath9k_ar9003_calib.c.

655 {
656  int i, im, nmeasurement;
657  u32 tx_corr_coeff[MAX_MEASUREMENT][AR9300_MAX_CHAINS];
658 
659  memset(tx_corr_coeff, 0, sizeof(tx_corr_coeff));
660  for (i = 0; i < MAX_MEASUREMENT / 2; i++) {
661  tx_corr_coeff[i * 2][0] = tx_corr_coeff[(i * 2) + 1][0] =
663  if (!AR_SREV_9485(ah)) {
664  tx_corr_coeff[i * 2][1] =
665  tx_corr_coeff[(i * 2) + 1][1] =
667 
668  tx_corr_coeff[i * 2][2] =
669  tx_corr_coeff[(i * 2) + 1][2] =
671  }
672  }
673 
674  /* Load the average of 2 passes */
675  for (i = 0; i < num_chains; i++) {
676  nmeasurement = REG_READ_FIELD(ah,
679 
680  if (nmeasurement > MAX_MEASUREMENT)
681  nmeasurement = MAX_MEASUREMENT;
682 
683  /* detect outlier only if nmeasurement > 1 */
684  if (nmeasurement > 1) {
685  /* Detect magnitude outlier */
687  nmeasurement, MAX_MAG_DELTA);
688 
689  /* Detect phase outlier */
691  nmeasurement, MAX_PHS_DELTA);
692  }
693 
694  for (im = 0; im < nmeasurement; im++) {
695 
696  coeff->iqc_coeff[0] = (coeff->mag_coeff[i][im] & 0x7f) |
697  ((coeff->phs_coeff[i][im] & 0x7f) << 7);
698 
699  if ((im % 2) == 0)
700  REG_RMW_FIELD(ah, tx_corr_coeff[im][i],
702  coeff->iqc_coeff[0]);
703  else
704  REG_RMW_FIELD(ah, tx_corr_coeff[im][i],
706  coeff->iqc_coeff[0]);
707  }
708  }
709 
714 
715  return;
716 
717 }
#define AR9300_MAX_CHAINS
Definition: ar9003_eeprom.h:50
int mag_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT]
#define AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN
Definition: ar9003_phy.h:62
#define MAX_MEASUREMENT
#define AR_SREV_9485(_ah)
Definition: reg.h:868
#define MAX_PHS_DELTA
#define MAX_MAG_DELTA
#define AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE
Definition: ar9003_phy.h:793
#define REG_RMW_FIELD(_a, _r, _f, _v)
Definition: hw.h:104
int phs_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT]
#define AR_PHY_TX_IQCAL_CORR_COEFF_B0(_i)
Definition: ar9003_phy.h:581
#define AR_PHY_TX_IQCAL_CORR_COEFF_B1(_i)
Definition: ar9003_phy.h:853
#define AR_PHY_TX_IQCAL_CONTROL_3
Definition: ar9003_phy.h:36
static void ar9003_hw_detect_outlier(int *mp_coeff, int nmeasurement, int max_delta)
#define AR_PHY_TX_IQCAL_CORR_COEFF_00_COEFF_TABLE
Definition: ar9003_phy.h:791
#define AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN
Definition: ar9003_phy.h:65
#define AR_PHY_TX_IQCAL_STATUS_B0
Definition: ar9003_phy.h:579
#define REG_READ_FIELD(_a, _r, _f)
Definition: hw.h:106
#define AR_PHY_CALIBRATED_GAINS_0
Definition: ar9003_phy.h:788
uint8_t ah
Definition: registers.h:85
#define AR_PHY_RX_IQCAL_CORR_B0
Definition: ar9003_phy.h:35
#define AR_PHY_TX_IQCAL_CORR_COEFF_B2(_i)
Definition: ar9003_phy.h:906
uint32_t u32
Definition: stdint.h:24
int iqc_coeff[2]
void * memset(void *dest, int character, size_t len) __nonnull

References ah, ar9003_hw_detect_outlier(), AR9300_MAX_CHAINS, AR_PHY_CALIBRATED_GAINS_0, AR_PHY_RX_IQCAL_CORR_B0, AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, AR_PHY_TX_IQCAL_CONTROL_3, AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN, AR_PHY_TX_IQCAL_CORR_COEFF_00_COEFF_TABLE, AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE, AR_PHY_TX_IQCAL_CORR_COEFF_B0, AR_PHY_TX_IQCAL_CORR_COEFF_B1, AR_PHY_TX_IQCAL_CORR_COEFF_B2, AR_PHY_TX_IQCAL_STATUS_B0, AR_SREV_9485, coeff::iqc_coeff, coeff::mag_coeff, MAX_MAG_DELTA, MAX_MEASUREMENT, MAX_PHS_DELTA, memset(), coeff::phs_coeff, REG_READ_FIELD, and REG_RMW_FIELD.

Referenced by ar9003_hw_tx_iq_cal_post_proc().

◆ ar9003_hw_tx_iq_cal_run()

static int ar9003_hw_tx_iq_cal_run ( struct ath_hw ah)
static

Definition at line 719 of file ath9k_ar9003_calib.c.

720 {
721  u8 tx_gain_forced;
722 
723  tx_gain_forced = REG_READ_FIELD(ah, AR_PHY_TX_FORCED_GAIN,
725  if (tx_gain_forced)
728 
731 
734  AH_WAIT_TIMEOUT)) {
735  DBG2("ath9k: "
736  "Tx IQ Cal is not completed.\n");
737  return 0;
738  }
739  return 1;
740 }
#define AR_PHY_TX_FORCED_GAIN
Definition: ar9003_phy.h:550
#define REG_RMW_FIELD(_a, _r, _f, _v)
Definition: hw.h:104
#define AR_PHY_TXGAIN_FORCE
Definition: ar9003_phy.h:744
#define AR_PHY_TX_IQCAL_START_DO_CAL
Definition: ar9003_phy.h:784
#define AR_PHY_TX_IQCAL_START
Definition: ar9003_phy.h:577
int ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout)
Definition: ath9k_hw.c:95
#define AH_WAIT_TIMEOUT
Definition: hw.h:146
#define REG_READ_FIELD(_a, _r, _f)
Definition: hw.h:106
uint8_t ah
Definition: registers.h:85
uint8_t u8
Definition: stdint.h:20
#define DBG2(...)
Definition: compiler.h:515

References ah, AH_WAIT_TIMEOUT, AR_PHY_TX_FORCED_GAIN, AR_PHY_TX_IQCAL_START, AR_PHY_TX_IQCAL_START_DO_CAL, AR_PHY_TXGAIN_FORCE, ath9k_hw_wait(), DBG2, REG_READ_FIELD, and REG_RMW_FIELD.

Referenced by ar9003_hw_init_cal().

◆ ar9003_hw_tx_iq_cal_post_proc()

static void ar9003_hw_tx_iq_cal_post_proc ( struct ath_hw ah)
static

Definition at line 742 of file ath9k_ar9003_calib.c.

743 {
744  const u32 txiqcal_status[AR9300_MAX_CHAINS] = {
748  };
749  const uint32_t chan_info_tab[] = {
753  };
754  struct coeff coeff;
755  s32 iq_res[6];
756  u8 num_chains = 0;
757  int i, im, j;
758  int nmeasurement;
759 
760  for (i = 0; i < AR9300_MAX_CHAINS; i++) {
761  if (ah->txchainmask & (1 << i))
762  num_chains++;
763  }
764 
765  for (i = 0; i < num_chains; i++) {
766  nmeasurement = REG_READ_FIELD(ah,
769  if (nmeasurement > MAX_MEASUREMENT)
770  nmeasurement = MAX_MEASUREMENT;
771 
772  for (im = 0; im < nmeasurement; im++) {
773  DBG2("ath9k: "
774  "Doing Tx IQ Cal for chain %d.\n", i);
775 
776  if (REG_READ(ah, txiqcal_status[i]) &
778  DBG("ath9k: "
779  "Tx IQ Cal failed for chain %d.\n", i);
780  goto tx_iqcal_fail;
781  }
782 
783  for (j = 0; j < 3; j++) {
784  u32 idx = 2 * j, offset = 4 * (3 * im + j);
785 
789  0);
790 
791  /* 32 bits */
792  iq_res[idx] = REG_READ(ah,
793  chan_info_tab[i] +
794  offset);
795 
799  1);
800 
801  /* 16 bits */
802  iq_res[idx + 1] = 0xffff & REG_READ(ah,
803  chan_info_tab[i] + offset);
804 
805  DBG2("ath9k: "
806  "IQ RES[%d]=0x%x"
807  "IQ_RES[%d]=0x%x\n",
808  idx, iq_res[idx], idx + 1,
809  iq_res[idx + 1]);
810  }
811 
812  if (!ar9003_hw_calc_iq_corr(ah, i, iq_res,
813  coeff.iqc_coeff)) {
814  DBG("ath9k: "
815  "Failed in calculation of \
816  IQ correction.\n");
817  goto tx_iqcal_fail;
818  }
819 
820  coeff.mag_coeff[i][im] = coeff.iqc_coeff[0] & 0x7f;
821  coeff.phs_coeff[i][im] =
822  (coeff.iqc_coeff[0] >> 7) & 0x7f;
823 
824  if (coeff.mag_coeff[i][im] > 63)
825  coeff.mag_coeff[i][im] -= 128;
826  if (coeff.phs_coeff[i][im] > 63)
827  coeff.phs_coeff[i][im] -= 128;
828  }
829  }
831 
832  return;
833 
834 tx_iqcal_fail:
835  DBG("ath9k: Tx IQ Cal failed\n");
836  return;
837 }
#define AR9300_MAX_CHAINS
Definition: ar9003_eeprom.h:50
int mag_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT]
#define AR_PHY_CHAN_INFO_TAB_S2_READ
Definition: ar9003_phy.h:201
int32_t s32
Definition: stdint.h:23
#define MAX_MEASUREMENT
#define REG_RMW_FIELD(_a, _r, _f, _v)
Definition: hw.h:104
int phs_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT]
#define AR_PHY_CHAN_INFO_TAB_0
Definition: ar9003_phy.h:99
#define AR_PHY_TX_IQCAL_STATUS_B2
Definition: ar9003_phy.h:905
#define AR_PHY_CHAN_INFO_TAB_2
Definition: ar9003_phy.h:865
#define AR_PHY_CHAN_INFO_TAB_1
Definition: ar9003_phy.h:809
#define AR_PHY_TX_IQCAL_STATUS_B0
Definition: ar9003_phy.h:579
unsigned int uint32_t
Definition: stdint.h:12
static int ar9003_hw_calc_iq_corr(struct ath_hw *ah, s32 chain_idx, const s32 iq_res[], s32 iqc_coeff[])
#define REG_READ(_ah, _reg)
Definition: hw.h:81
#define AR_PHY_CHAN_INFO_MEMORY
Definition: ar9002_phy.h:362
#define REG_READ_FIELD(_a, _r, _f)
Definition: hw.h:106
#define AR_PHY_CALIBRATED_GAINS_0
Definition: ar9003_phy.h:788
uint8_t ah
Definition: registers.h:85
#define AR_PHY_TX_IQCAL_STATUS_FAILED
Definition: ar9003_phy.h:787
uint16_t offset
Offset to command line.
Definition: bzimage.h:8
#define DBG(...)
Print a debugging message.
Definition: compiler.h:498
static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah, u8 num_chains, struct coeff *coeff)
#define AR_PHY_TX_IQCAL_STATUS_B1
Definition: ar9003_phy.h:852
uint8_t u8
Definition: stdint.h:20
uint32_t u32
Definition: stdint.h:24
#define DBG2(...)
Definition: compiler.h:515
int iqc_coeff[2]

References ah, ar9003_hw_calc_iq_corr(), ar9003_hw_tx_iqcal_load_avg_2_passes(), AR9300_MAX_CHAINS, AR_PHY_CALIBRATED_GAINS_0, AR_PHY_CHAN_INFO_MEMORY, AR_PHY_CHAN_INFO_TAB_0, AR_PHY_CHAN_INFO_TAB_1, AR_PHY_CHAN_INFO_TAB_2, AR_PHY_CHAN_INFO_TAB_S2_READ, AR_PHY_TX_IQCAL_STATUS_B0, AR_PHY_TX_IQCAL_STATUS_B1, AR_PHY_TX_IQCAL_STATUS_B2, AR_PHY_TX_IQCAL_STATUS_FAILED, DBG, DBG2, coeff::iqc_coeff, coeff::mag_coeff, MAX_MEASUREMENT, offset, coeff::phs_coeff, REG_READ, REG_READ_FIELD, and REG_RMW_FIELD.

Referenced by ar9003_hw_init_cal().

◆ ar9003_hw_init_cal()

static int ar9003_hw_init_cal ( struct ath_hw ah,
struct ath9k_channel *chan  __unused 
)
static

Definition at line 838 of file ath9k_ar9003_calib.c.

840 {
841  struct ath9k_hw_capabilities *pCap = &ah->caps;
842  int val;
843  int txiqcal_done = 0;
844 
846  DBG2("ath9k: ath9k: AR_ENT_OTP 0x%x\n", val);
847 
848  /* Configure rx/tx chains before running AGC/TxiQ cals */
850  ar9003_hw_set_chain_masks(ah, 0x3, 0x3);
851  else
853  pCap->tx_chainmask);
854 
855  /* Do Tx IQ Calibration */
858  DELPT);
859 
860  /*
861  * For AR9485 or later chips, TxIQ cal runs as part of
862  * AGC calibration
863  */
865  txiqcal_done = 1;
866  else {
867  txiqcal_done = ar9003_hw_tx_iq_cal_run(ah);
869  udelay(5);
871  }
872 
873  /* Calibrate the AGC */
877 
878  /* Poll for offset calibration complete */
880  0, AH_WAIT_TIMEOUT)) {
881  DBG("ath9k: "
882  "offset calibration failed to complete in 1ms; noisy environment?\n");
883  return 0;
884  }
885 
886  if (txiqcal_done)
888 
889  /* Revert chainmasks to their original values before NF cal */
890  ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
891 
893 
894  /* Initialize list pointers */
895  ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL;
896  ah->supp_cals = IQ_MISMATCH_CAL;
897 
898  if (ah->supp_cals & IQ_MISMATCH_CAL) {
899  INIT_CAL(&ah->iq_caldata);
900  INSERT_CAL(ah, &ah->iq_caldata);
901  DBG2("ath9k: "
902  "enabling IQ Calibration.\n");
903  }
904 
905  if (ah->supp_cals & TEMP_COMP_CAL) {
906  INIT_CAL(&ah->tempCompCalData);
907  INSERT_CAL(ah, &ah->tempCompCalData);
908  DBG2("ath9k: "
909  "enabling Temperature Compensation Calibration.\n");
910  }
911 
912  /* Initialize current pointer to first element in list */
913  ah->cal_list_curr = ah->cal_list;
914 
915  if (ah->cal_list_curr)
916  ath9k_hw_reset_calibration(ah, ah->cal_list_curr);
917 
918  if (ah->caldata)
919  ah->caldata->CalValid = 0;
920 
921  return 1;
922 }
#define DELPT
void __asmcall int val
Definition: setjmp.h:12
static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah)
void ath9k_hw_start_nfcal(struct ath_hw *ah, int update)
Definition: ath9k_calib.c:208
static int ar9003_hw_tx_iq_cal_run(struct ath_hw *ah)
#define AR_PHY_ACTIVE_EN
Definition: ar9002_phy.h:54
#define AR_PHY_TX_IQCAL_CONTROL_1
Definition: ar9003_phy.h:575
void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx)
#define AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT
Definition: ar9003_phy.h:782
#define AR_PHY_ACTIVE
Definition: ar9002_phy.h:53
#define AR_ENT_OTP
Definition: reg.h:1108
#define AR_PHY_AGC_CONTROL_CAL
Definition: reg.h:1911
#define REG_RMW_FIELD(_a, _r, _f, _v)
Definition: hw.h:104
#define AR_PHY_ACTIVE_DIS
Definition: ar9002_phy.h:55
#define INIT_CAL(_perCal)
Definition: calib.h:49
void udelay(unsigned long usecs)
Delay for a fixed number of microseconds.
Definition: timer.c:61
#define AR_PHY_AGC_CONTROL
Definition: reg.h:1910
#define INSERT_CAL(_ahp, _perCal)
Definition: calib.h:54
#define REG_READ(_ah, _reg)
Definition: hw.h:81
int ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout)
Definition: ath9k_hw.c:95
#define REG_WRITE(_ah, _reg, _val)
Definition: hw.h:78
#define AH_WAIT_TIMEOUT
Definition: hw.h:146
uint8_t ah
Definition: registers.h:85
#define DBG(...)
Print a debugging message.
Definition: compiler.h:498
void ath9k_hw_reset_calibration(struct ath_hw *ah, struct ath9k_cal_list *currCal)
Definition: ath9k_calib.c:155
#define NULL
NULL pointer (VOID *)
Definition: Base.h:322
#define AR_ENT_OTP_CHAIN2_DISABLE
Definition: reg.h:1109
#define DBG2(...)
Definition: compiler.h:515
#define AR_SREV_9485_OR_LATER(_ah)
Definition: reg.h:876

References ah, AH_WAIT_TIMEOUT, ar9003_hw_set_chain_masks(), ar9003_hw_tx_iq_cal_post_proc(), ar9003_hw_tx_iq_cal_run(), AR_ENT_OTP, AR_ENT_OTP_CHAIN2_DISABLE, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS, AR_PHY_ACTIVE_EN, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, AR_PHY_TX_IQCAL_CONTROL_1, AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT, AR_SREV_9485_OR_LATER, ath9k_hw_reset_calibration(), ath9k_hw_start_nfcal(), ath9k_hw_wait(), DBG, DBG2, DELPT, INIT_CAL, INSERT_CAL, IQ_MISMATCH_CAL, NULL, REG_READ, REG_RMW_FIELD, REG_WRITE, ath9k_hw_capabilities::rx_chainmask, TEMP_COMP_CAL, ath9k_hw_capabilities::tx_chainmask, udelay(), and val.

Referenced by ar9003_hw_attach_calib_ops().

◆ ar9003_hw_attach_calib_ops()

void ar9003_hw_attach_calib_ops ( struct ath_hw ah)

Definition at line 924 of file ath9k_ar9003_calib.c.

925 {
926  struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
927  struct ath_hw_ops *ops = ath9k_hw_ops(ah);
928 
930  priv_ops->init_cal = ar9003_hw_init_cal;
932 
934 }
static void ar9003_hw_setup_calibration(struct ath_hw *ah, struct ath9k_cal_list *currCal)
void(* init_cal_settings)(struct ath_hw *ah)
Definition: hw.h:553
struct ath_hw_private_ops - callbacks used internally by hardware code
Definition: hw.h:551
void(* setup_calibration)(struct ath_hw *ah, struct ath9k_cal_list *currCal)
Definition: hw.h:558
static void ar9003_hw_init_cal_settings(struct ath_hw *ah)
struct ath_hw_ops - callbacks used by hardware code and driver code
Definition: hw.h:604
int(* calibrate)(struct ath_hw *ah, struct ath9k_channel *chan, u8 rxchainmask, int longcal)
Definition: hw.h:611
static struct ath_hw_ops * ath9k_hw_ops(struct ath_hw *ah)
Definition: hw.h:885
static int ar9003_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, u8 rxchainmask, int longcal)
uint8_t ah
Definition: registers.h:85
static struct ath_hw_private_ops * ath9k_hw_private_ops(struct ath_hw *ah)
Definition: hw.h:880
static int ar9003_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan __unused)
int(* init_cal)(struct ath_hw *ah, struct ath9k_channel *chan)
Definition: hw.h:554

References ah, ar9003_hw_calibrate(), ar9003_hw_init_cal(), ar9003_hw_init_cal_settings(), ar9003_hw_setup_calibration(), ath9k_hw_ops(), ath9k_hw_private_ops(), ath_hw_ops::calibrate, ath_hw_private_ops::init_cal, ath_hw_private_ops::init_cal_settings, and ath_hw_private_ops::setup_calibration.

Referenced by ar9003_hw_attach_ops().

Variable Documentation

◆ iq_cal_single_sample

const struct ath9k_percal_data iq_cal_single_sample
static
Initial value:
= {
}
static void ar9003_hw_iqcal_collect(struct ath_hw *ah)
static void ar9003_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
#define MIN_CAL_SAMPLES
Definition: calib.h:74
#define PER_MAX_LOG_COUNT
Definition: calib.h:78

Definition at line 317 of file ath9k_ar9003_calib.c.

Referenced by ar9003_hw_init_cal_settings().