1/*
2 * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
3 * Use is subject to license terms.
4 */
5
6/*
7 * Copyright (c) 2008 Atheros Communications Inc.
8 *
9 * Permission to use, copy, modify, and/or distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 */
21
22#include "arn_core.h"
23#include "arn_hw.h"
24#include "arn_reg.h"
25#include "arn_phy.h"
26
27static const int16_t NOISE_FLOOR[] = { -96, -93, -98, -96, -93, -96 };
28
29/* We can tune this as we go by monitoring really low values */
30#define	ATH9K_NF_TOO_LOW	-60
31
32/*
33 * AR5416 may return very high value (like -31 dBm), in those cases the nf
34 * is incorrect and we should use the static NF value. Later we can try to
35 * find out why they are reporting these values
36 */
37
38/* ARGSUSED */
39static boolean_t
40ath9k_hw_nf_in_range(struct ath_hal *ah, signed short nf)
41{
42	if (nf > ATH9K_NF_TOO_LOW) {
43		ARN_DBG((ARN_DBG_CALIBRATE,
44		    "%s: noise floor value detected (%d) is "
45		    "lower than what we think is a "
46		    "reasonable value (%d)\n",
47		    __func__, nf, ATH9K_NF_TOO_LOW));
48
49		return (B_FALSE);
50	}
51	return (B_TRUE);
52}
53
54static int16_t
55ath9k_hw_get_nf_hist_mid(int16_t *nfCalBuffer)
56{
57	int16_t nfval;
58	int16_t sort[ATH9K_NF_CAL_HIST_MAX];
59	int i, j;
60
61	for (i = 0; i < ATH9K_NF_CAL_HIST_MAX; i++)
62		sort[i] = nfCalBuffer[i];
63
64	for (i = 0; i < ATH9K_NF_CAL_HIST_MAX - 1; i++) {
65		for (j = 1; j < ATH9K_NF_CAL_HIST_MAX - i; j++) {
66			if (sort[j] > sort[j - 1]) {
67				nfval = sort[j];
68				sort[j] = sort[j - 1];
69				sort[j - 1] = nfval;
70			}
71		}
72	}
73	nfval = sort[(ATH9K_NF_CAL_HIST_MAX - 1) >> 1];
74
75	return (nfval);
76}
77
78static void
79ath9k_hw_update_nfcal_hist_buffer(struct ath9k_nfcal_hist *h,
80    int16_t *nfarray)
81{
82	int i;
83
84	for (i = 0; i < NUM_NF_READINGS; i++) {
85		h[i].nfCalBuffer[h[i].currIndex] = nfarray[i];
86
87		if (++h[i].currIndex >= ATH9K_NF_CAL_HIST_MAX)
88			h[i].currIndex = 0;
89
90		if (h[i].invalidNFcount > 0) {
91			if (nfarray[i] < AR_PHY_CCA_MIN_BAD_VALUE ||
92			    nfarray[i] > AR_PHY_CCA_MAX_HIGH_VALUE) {
93				h[i].invalidNFcount = ATH9K_NF_CAL_HIST_MAX;
94			} else {
95				h[i].invalidNFcount--;
96				h[i].privNF = nfarray[i];
97			}
98		} else {
99			h[i].privNF =
100			    ath9k_hw_get_nf_hist_mid(h[i].nfCalBuffer);
101		}
102	}
103}
104
105static void
106ath9k_hw_do_getnf(struct ath_hal *ah,
107    int16_t nfarray[NUM_NF_READINGS])
108{
109	int16_t nf;
110
111	if (AR_SREV_9280_10_OR_LATER(ah))
112		nf = MS(REG_READ(ah, AR_PHY_CCA), AR9280_PHY_MINCCA_PWR);
113	else
114		nf = MS(REG_READ(ah, AR_PHY_CCA), AR_PHY_MINCCA_PWR);
115
116	if (nf & 0x100)
117		nf = 0 - ((nf ^ 0x1ff) + 1);
118	ARN_DBG((ARN_DBG_CALIBRATE,
119	    "NF calibrated [ctl] [chain 0] is %d\n", nf));
120	nfarray[0] = nf;
121
122	if (AR_SREV_9280_10_OR_LATER(ah))
123		nf = MS(REG_READ(ah, AR_PHY_CH1_CCA),
124		    AR9280_PHY_CH1_MINCCA_PWR);
125	else
126		nf = MS(REG_READ(ah, AR_PHY_CH1_CCA),
127		    AR_PHY_CH1_MINCCA_PWR);
128
129	if (nf & 0x100)
130		nf = 0 - ((nf ^ 0x1ff) + 1);
131	ARN_DBG((ARN_DBG_CALIBRATE,
132	    "NF calibrated [ctl] [chain 1] is %d\n", nf));
133	nfarray[1] = nf;
134
135	if (!AR_SREV_9280(ah)) {
136		nf = MS(REG_READ(ah, AR_PHY_CH2_CCA),
137		    AR_PHY_CH2_MINCCA_PWR);
138		if (nf & 0x100)
139			nf = 0 - ((nf ^ 0x1ff) + 1);
140		ARN_DBG((ARN_DBG_CALIBRATE,
141		    "NF calibrated [ctl] [chain 2] is %d\n", nf));
142		nfarray[2] = nf;
143	}
144
145	if (AR_SREV_9280_10_OR_LATER(ah))
146		nf = MS(REG_READ(ah, AR_PHY_EXT_CCA),
147		    AR9280_PHY_EXT_MINCCA_PWR);
148	else
149		nf = MS(REG_READ(ah, AR_PHY_EXT_CCA),
150		    AR_PHY_EXT_MINCCA_PWR);
151
152	if (nf & 0x100)
153		nf = 0 - ((nf ^ 0x1ff) + 1);
154	ARN_DBG((ARN_DBG_CALIBRATE,
155	    "NF calibrated [ext] [chain 0] is %d\n", nf));
156	nfarray[3] = nf;
157
158	if (AR_SREV_9280_10_OR_LATER(ah))
159		nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA),
160		    AR9280_PHY_CH1_EXT_MINCCA_PWR);
161	else
162		nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA),
163		    AR_PHY_CH1_EXT_MINCCA_PWR);
164
165	if (nf & 0x100)
166		nf = 0 - ((nf ^ 0x1ff) + 1);
167	ARN_DBG((ARN_DBG_CALIBRATE,
168	    "NF calibrated [ext] [chain 1] is %d\n", nf));
169	nfarray[4] = nf;
170
171	if (!AR_SREV_9280(ah)) {
172		nf = MS(REG_READ(ah, AR_PHY_CH2_EXT_CCA),
173		    AR_PHY_CH2_EXT_MINCCA_PWR);
174		if (nf & 0x100)
175			nf = 0 - ((nf ^ 0x1ff) + 1);
176		ARN_DBG((ARN_DBG_CALIBRATE,
177		    "NF calibrated [ext] [chain 2] is %d\n", nf));
178		nfarray[5] = nf;
179	}
180}
181
182static boolean_t
183getNoiseFloorThresh(struct ath_hal *ah,
184    const struct ath9k_channel *chan,
185    int16_t *nft)
186{
187	switch (chan->chanmode) {
188	case CHANNEL_A:
189	case CHANNEL_A_HT20:
190	case CHANNEL_A_HT40PLUS:
191	case CHANNEL_A_HT40MINUS:
192		*nft = (int8_t)ath9k_hw_get_eeprom(ah, EEP_NFTHRESH_5);
193		break;
194	case CHANNEL_B:
195	case CHANNEL_G:
196	case CHANNEL_G_HT20:
197	case CHANNEL_G_HT40PLUS:
198	case CHANNEL_G_HT40MINUS:
199		*nft = (int8_t)ath9k_hw_get_eeprom(ah, EEP_NFTHRESH_2);
200		break;
201	default:
202		ARN_DBG((ARN_DBG_CHANNEL,
203		    "%s: invalid channel flags 0x%x\n", __func__,
204		    chan->channelFlags));
205		return (B_FALSE);
206	}
207
208	return (B_TRUE);
209}
210
211static void
212ath9k_hw_setup_calibration(struct ath_hal *ah,
213    struct hal_cal_list *currCal)
214{
215	REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(0),
216	    AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX,
217	    currCal->calData->calCountMax);
218
219	switch (currCal->calData->calType) {
220	case IQ_MISMATCH_CAL:
221		REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ);
222		ARN_DBG((ARN_DBG_CALIBRATE,
223		    "%s: starting IQ Mismatch Calibration\n",
224		    __func__));
225		break;
226	case ADC_GAIN_CAL:
227		REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_GAIN);
228		ARN_DBG((ARN_DBG_CALIBRATE,
229		    "%s: starting ADC Gain Calibration\n", __func__));
230		break;
231	case ADC_DC_CAL:
232		REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_PER);
233		ARN_DBG((ARN_DBG_CALIBRATE,
234		    "%s: starting ADC DC Calibration\n", __func__));
235		break;
236	case ADC_DC_INIT_CAL:
237		REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_INIT);
238		ARN_DBG((ARN_DBG_CALIBRATE,
239		    "%s: starting Init ADC DC Calibration\n",
240		    __func__));
241		break;
242	}
243
244	REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0),
245	    AR_PHY_TIMING_CTRL4_DO_CAL);
246}
247
248static void
249ath9k_hw_reset_calibration(struct ath_hal *ah,
250    struct hal_cal_list *currCal)
251{
252	struct ath_hal_5416 *ahp = AH5416(ah);
253	int i;
254
255	ath9k_hw_setup_calibration(ah, currCal);
256
257	currCal->calState = CAL_RUNNING;
258
259	for (i = 0; i < AR5416_MAX_CHAINS; i++) {
260		ahp->ah_Meas0.sign[i] = 0;
261		ahp->ah_Meas1.sign[i] = 0;
262		ahp->ah_Meas2.sign[i] = 0;
263		ahp->ah_Meas3.sign[i] = 0;
264	}
265
266	ahp->ah_CalSamples = 0;
267}
268
269static void
270ath9k_hw_per_calibration(struct ath_hal *ah,
271    struct ath9k_channel *ichan,
272    uint8_t rxchainmask,
273    struct hal_cal_list *currCal,
274    boolean_t *isCalDone)
275{
276	struct ath_hal_5416 *ahp = AH5416(ah);
277
278	*isCalDone = B_FALSE;
279
280	if (currCal->calState == CAL_RUNNING) {
281		if (!(REG_READ(ah, AR_PHY_TIMING_CTRL4(0)) &
282		    AR_PHY_TIMING_CTRL4_DO_CAL)) {
283
284			currCal->calData->calCollect(ah);
285			ahp->ah_CalSamples++;
286
287			if (ahp->ah_CalSamples >=
288			    currCal->calData->calNumSamples) {
289				int i, numChains = 0;
290				for (i = 0; i < AR5416_MAX_CHAINS; i++) {
291					if (rxchainmask & (1 << i))
292						numChains++;
293				}
294
295				currCal->calData->calPostProc(ah, numChains);
296				ichan->CalValid |= currCal->calData->calType;
297				currCal->calState = CAL_DONE;
298				*isCalDone = B_TRUE;
299			} else {
300				ath9k_hw_setup_calibration(ah, currCal);
301			}
302		}
303	} else if (!(ichan->CalValid & currCal->calData->calType)) {
304		ath9k_hw_reset_calibration(ah, currCal);
305	}
306}
307
308static boolean_t
309ath9k_hw_iscal_supported(struct ath_hal *ah,
310    struct ath9k_channel *chan,
311    enum hal_cal_types calType)
312{
313	struct ath_hal_5416 *ahp = AH5416(ah);
314	boolean_t retval = B_FALSE;
315
316	switch (calType & ahp->ah_suppCals) {
317	case IQ_MISMATCH_CAL:
318		if (!IS_CHAN_B(chan))
319			retval = B_TRUE;
320		break;
321	case ADC_GAIN_CAL:
322	case ADC_DC_CAL:
323		if (!IS_CHAN_B(chan) &&
324		    !(IS_CHAN_2GHZ(chan) && IS_CHAN_HT20(chan)))
325			retval = B_TRUE;
326		break;
327	}
328
329	return (retval);
330}
331
332static void
333ath9k_hw_iqcal_collect(struct ath_hal *ah)
334{
335	struct ath_hal_5416 *ahp = AH5416(ah);
336	int i;
337
338	for (i = 0; i < AR5416_MAX_CHAINS; i++) {
339		ahp->ah_totalPowerMeasI[i] +=
340		    REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
341		ahp->ah_totalPowerMeasQ[i] +=
342		    REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
343		ahp->ah_totalIqCorrMeas[i] +=
344		    (int32_t)REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
345		ARN_DBG((ARN_DBG_CALIBRATE,
346		    "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
347		    ahp->ah_CalSamples, i, ahp->ah_totalPowerMeasI[i],
348		    ahp->ah_totalPowerMeasQ[i],
349		    ahp->ah_totalIqCorrMeas[i]));
350	}
351}
352
353static void
354ath9k_hw_adc_gaincal_collect(struct ath_hal *ah)
355{
356	struct ath_hal_5416 *ahp = AH5416(ah);
357	int i;
358
359	for (i = 0; i < AR5416_MAX_CHAINS; i++) {
360		ahp->ah_totalAdcIOddPhase[i] +=
361		    REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
362		ahp->ah_totalAdcIEvenPhase[i] +=
363		    REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
364		ahp->ah_totalAdcQOddPhase[i] +=
365		    REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
366		ahp->ah_totalAdcQEvenPhase[i] +=
367		    REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
368		ARN_DBG((ARN_DBG_CALIBRATE,
369		    "%d: Chn %d oddi=0x%08x; eveni=0x%08x; "
370		    "oddq=0x%08x; evenq=0x%08x;\n",
371		    ahp->ah_CalSamples, i,
372		    ahp->ah_totalAdcIOddPhase[i],
373		    ahp->ah_totalAdcIEvenPhase[i],
374		    ahp->ah_totalAdcQOddPhase[i],
375		    ahp->ah_totalAdcQEvenPhase[i]));
376	}
377}
378
379static void
380ath9k_hw_adc_dccal_collect(struct ath_hal *ah)
381{
382	struct ath_hal_5416 *ahp = AH5416(ah);
383	int i;
384
385	for (i = 0; i < AR5416_MAX_CHAINS; i++) {
386		ahp->ah_totalAdcDcOffsetIOddPhase[i] +=
387		    (int32_t)REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
388		ahp->ah_totalAdcDcOffsetIEvenPhase[i] +=
389		    (int32_t)REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
390		ahp->ah_totalAdcDcOffsetQOddPhase[i] +=
391		    (int32_t)REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
392		ahp->ah_totalAdcDcOffsetQEvenPhase[i] +=
393		    (int32_t)REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
394		ARN_DBG((ARN_DBG_CALIBRATE,
395		    "%d: Chn %d oddi=0x%08x; eveni=0x%08x; "
396		    "oddq=0x%08x; evenq=0x%08x;\n",
397		    ahp->ah_CalSamples, i,
398		    ahp->ah_totalAdcDcOffsetIOddPhase[i],
399		    ahp->ah_totalAdcDcOffsetIEvenPhase[i],
400		    ahp->ah_totalAdcDcOffsetQOddPhase[i],
401		    ahp->ah_totalAdcDcOffsetQEvenPhase[i]));
402	}
403}
404
405static void
406ath9k_hw_iqcalibrate(struct ath_hal *ah, uint8_t numChains)
407{
408	struct ath_hal_5416 *ahp = AH5416(ah);
409	uint32_t powerMeasQ, powerMeasI, iqCorrMeas;
410	uint32_t qCoffDenom, iCoffDenom;
411	int32_t qCoff, iCoff;
412	int iqCorrNeg, i;
413
414	for (i = 0; i < numChains; i++) {
415		powerMeasI = ahp->ah_totalPowerMeasI[i];
416		powerMeasQ = ahp->ah_totalPowerMeasQ[i];
417		iqCorrMeas = ahp->ah_totalIqCorrMeas[i];
418		ARN_DBG((ARN_DBG_CALIBRATE,
419		    "Starting IQ Cal and Correction for Chain %d\n",
420		    i));
421
422		ARN_DBG((ARN_DBG_CALIBRATE,
423		    "Orignal: Chn %diq_corr_meas = 0x%08x\n",
424		    i, ahp->ah_totalIqCorrMeas[i]));
425
426		iqCorrNeg = 0;
427
428		if (iqCorrMeas > 0x80000000) {
429			iqCorrMeas = (0xffffffff - iqCorrMeas) + 1;
430			iqCorrNeg = 1;
431		}
432
433		ARN_DBG((ARN_DBG_CALIBRATE,
434		    "Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI));
435		ARN_DBG((ARN_DBG_CALIBRATE,
436		    "Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ));
437		ARN_DBG((ARN_DBG_CALIBRATE, "iqCorrNeg is 0x%08x\n",
438		    iqCorrNeg));
439
440		iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128;
441		qCoffDenom = powerMeasQ / 64;
442
443		if (powerMeasQ != 0) {
444			iCoff = iqCorrMeas / iCoffDenom;
445			qCoff = powerMeasI / qCoffDenom - 64;
446
447			ARN_DBG((ARN_DBG_CALIBRATE,
448			    "Chn %d iCoff = 0x%08x\n", i, iCoff));
449			ARN_DBG((ARN_DBG_CALIBRATE,
450			    "Chn %d qCoff = 0x%08x\n", i, qCoff));
451
452			iCoff = iCoff & 0x3f;
453
454			ARN_DBG((ARN_DBG_CALIBRATE,
455			    "New: Chn %d iCoff = 0x%08x\n", i, iCoff));
456
457			if (iqCorrNeg == 0x0)
458				iCoff = 0x40 - iCoff;
459
460			if (qCoff > 15)
461				qCoff = 15;
462			else if (qCoff <= -16)
463				qCoff = 16;
464
465			ARN_DBG((ARN_DBG_CALIBRATE,
466			    "Chn %d : iCoff = 0x%x  qCoff = 0x%x\n",
467			    i, iCoff, qCoff));
468
469			REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i),
470			    AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF,
471			    iCoff);
472			REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i),
473			    AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF,
474			    qCoff);
475
476			ARN_DBG((ARN_DBG_CALIBRATE,
477			    "IQ Cal and Correction done for Chain %d\n",
478			    i));
479		}
480	}
481
482	REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0),
483	    AR_PHY_TIMING_CTRL4_IQCORR_ENABLE);
484}
485
486static void
487ath9k_hw_adc_gaincal_calibrate(struct ath_hal *ah, uint8_t numChains)
488{
489	struct ath_hal_5416 *ahp = AH5416(ah);
490	uint32_t iOddMeasOffset, iEvenMeasOffset, qOddMeasOffset,
491	    qEvenMeasOffset;
492	uint32_t qGainMismatch, iGainMismatch, val, i;
493
494	for (i = 0; i < numChains; i++) {
495		iOddMeasOffset = ahp->ah_totalAdcIOddPhase[i];
496		iEvenMeasOffset = ahp->ah_totalAdcIEvenPhase[i];
497		qOddMeasOffset = ahp->ah_totalAdcQOddPhase[i];
498		qEvenMeasOffset = ahp->ah_totalAdcQEvenPhase[i];
499
500		ARN_DBG((ARN_DBG_CALIBRATE,
501		    "Starting ADC Gain Cal for Chain %d\n", i));
502
503		ARN_DBG((ARN_DBG_CALIBRATE,
504		    "Chn %d pwr_meas_odd_i = 0x%08x\n", i,
505		    iOddMeasOffset));
506		ARN_DBG((ARN_DBG_CALIBRATE,
507		    "Chn %d pwr_meas_even_i = 0x%08x\n", i,
508		    iEvenMeasOffset));
509		ARN_DBG((ARN_DBG_CALIBRATE,
510		    "Chn %d pwr_meas_odd_q = 0x%08x\n", i,
511		    qOddMeasOffset));
512		ARN_DBG((ARN_DBG_CALIBRATE,
513		    "Chn %d pwr_meas_even_q = 0x%08x\n", i,
514		    qEvenMeasOffset));
515
516		if (iOddMeasOffset != 0 && qEvenMeasOffset != 0) {
517			iGainMismatch =
518			    ((iEvenMeasOffset * 32) /
519			    iOddMeasOffset) & 0x3f;
520			qGainMismatch =
521			    ((qOddMeasOffset * 32) /
522			    qEvenMeasOffset) & 0x3f;
523
524			ARN_DBG((ARN_DBG_CALIBRATE,
525			    "Chn %d gain_mismatch_i = 0x%08x\n", i,
526			    iGainMismatch));
527			ARN_DBG((ARN_DBG_CALIBRATE,
528			    "Chn %d gain_mismatch_q = 0x%08x\n", i,
529			    qGainMismatch));
530
531			val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
532			val &= 0xfffff000;
533			val |= (qGainMismatch) | (iGainMismatch << 6);
534			REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
535
536			ARN_DBG((ARN_DBG_CALIBRATE,
537			    "ADC Gain Cal done for Chain %d\n", i));
538		}
539	}
540
541	REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
542	    REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
543	    AR_PHY_NEW_ADC_GAIN_CORR_ENABLE);
544}
545
546static void
547ath9k_hw_adc_dccal_calibrate(struct ath_hal *ah, uint8_t numChains)
548{
549	struct ath_hal_5416 *ahp = AH5416(ah);
550	uint32_t iOddMeasOffset, iEvenMeasOffset, val, i;
551	int32_t qOddMeasOffset, qEvenMeasOffset, qDcMismatch, iDcMismatch;
552	const struct hal_percal_data *calData =
553	    ahp->ah_cal_list_curr->calData;
554	uint32_t numSamples =
555	    (1 << (calData->calCountMax + 5)) * calData->calNumSamples;
556
557	for (i = 0; i < numChains; i++) {
558		iOddMeasOffset = ahp->ah_totalAdcDcOffsetIOddPhase[i];
559		iEvenMeasOffset = ahp->ah_totalAdcDcOffsetIEvenPhase[i];
560		qOddMeasOffset = ahp->ah_totalAdcDcOffsetQOddPhase[i];
561		qEvenMeasOffset = ahp->ah_totalAdcDcOffsetQEvenPhase[i];
562
563		ARN_DBG((ARN_DBG_CALIBRATE,
564		    "Starting ADC DC Offset Cal for Chain %d\n", i));
565
566		ARN_DBG((ARN_DBG_CALIBRATE,
567		    "Chn %d pwr_meas_odd_i = %d\n", i,
568		    iOddMeasOffset));
569		ARN_DBG((ARN_DBG_CALIBRATE,
570		    "Chn %d pwr_meas_even_i = %d\n", i,
571		    iEvenMeasOffset));
572		ARN_DBG((ARN_DBG_CALIBRATE,
573		    "Chn %d pwr_meas_odd_q = %d\n", i,
574		    qOddMeasOffset));
575		ARN_DBG((ARN_DBG_CALIBRATE,
576		    "Chn %d pwr_meas_even_q = %d\n", i,
577		    qEvenMeasOffset));
578
579		iDcMismatch = (((iEvenMeasOffset - iOddMeasOffset) * 2) /
580		    numSamples) & 0x1ff;
581		qDcMismatch = (((qOddMeasOffset - qEvenMeasOffset) * 2) /
582		    numSamples) & 0x1ff;
583
584		ARN_DBG((ARN_DBG_CALIBRATE,
585		    "Chn %d dc_offset_mismatch_i = 0x%08x\n", i,
586		    iDcMismatch));
587		ARN_DBG((ARN_DBG_CALIBRATE,
588		    "Chn %d dc_offset_mismatch_q = 0x%08x\n", i,
589		    qDcMismatch));
590
591		val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
592		val &= 0xc0000fff;
593		val |= (qDcMismatch << 12) | (iDcMismatch << 21);
594		REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
595
596		ARN_DBG((ARN_DBG_CALIBRATE,
597		    "ADC DC Offset Cal done for Chain %d\n", i));
598	}
599
600	REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
601	    REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
602	    AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE);
603}
604
605void
606ath9k_hw_reset_calvalid(struct ath_hal *ah, struct ath9k_channel *chan,
607    boolean_t *isCalDone)
608{
609	struct ath_hal_5416 *ahp = AH5416(ah);
610	struct ath9k_channel *ichan =
611	    ath9k_regd_check_channel(ah, chan);
612	struct hal_cal_list *currCal = ahp->ah_cal_list_curr;
613
614	*isCalDone = B_TRUE;
615
616	if (!AR_SREV_9100(ah) && !AR_SREV_9160_10_OR_LATER(ah))
617		return;
618
619	if (currCal == NULL)
620		return;
621
622	if (ichan == NULL) {
623		ARN_DBG((ARN_DBG_CALIBRATE,
624		    "%s: invalid channel %u/0x%x; no mapping\n",
625		    __func__, chan->channel, chan->channelFlags));
626		return;
627	}
628
629
630	if (currCal->calState != CAL_DONE) {
631		ARN_DBG((ARN_DBG_CALIBRATE,
632		    "%s: Calibration state incorrect, %d\n",
633		    __func__, currCal->calState));
634		return;
635	}
636
637
638	if (!ath9k_hw_iscal_supported(ah, chan, currCal->calData->calType))
639		return;
640	ARN_DBG((ARN_DBG_CALIBRATE,
641	    "%s: Resetting Cal %d state for channel %u/0x%x\n",
642	    __func__, currCal->calData->calType, chan->channel,
643	    chan->channelFlags));
644
645	ichan->CalValid &= ~currCal->calData->calType;
646	currCal->calState = CAL_WAITING;
647
648	*isCalDone = B_FALSE;
649}
650
651void
652ath9k_hw_start_nfcal(struct ath_hal *ah)
653{
654	REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
655	    AR_PHY_AGC_CONTROL_ENABLE_NF);
656	REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
657	    AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
658	REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
659}
660
661/* ARGSUSED */
662void
663ath9k_hw_loadnf(struct ath_hal *ah, struct ath9k_channel *chan)
664{
665	struct ath9k_nfcal_hist *h;
666	int i, j;
667	int32_t val;
668	const uint32_t ar5416_cca_regs[6] = {
669		AR_PHY_CCA,
670		AR_PHY_CH1_CCA,
671		AR_PHY_CH2_CCA,
672		AR_PHY_EXT_CCA,
673		AR_PHY_CH1_EXT_CCA,
674		AR_PHY_CH2_EXT_CCA
675	};
676	uint8_t chainmask;
677
678	if (AR_SREV_9280(ah))
679		chainmask = 0x1B;
680	else
681		chainmask = 0x3F;
682
683#ifdef ARN_NF_PER_CHAN
684	h = chan->nfCalHist;
685#else
686	h = ah->nfCalHist;
687#endif
688
689	for (i = 0; i < NUM_NF_READINGS; i++) {
690		if (chainmask & (1 << i)) {
691			val = REG_READ(ah, ar5416_cca_regs[i]);
692			val &= 0xFFFFFE00;
693			val |= (((uint32_t)(h[i].privNF) << 1) & 0x1ff);
694			REG_WRITE(ah, ar5416_cca_regs[i], val);
695		}
696	}
697
698	REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
699	    AR_PHY_AGC_CONTROL_ENABLE_NF);
700	REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
701	    AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
702	REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
703
704	for (j = 0; j < 1000; j++) {
705		if ((REG_READ(ah, AR_PHY_AGC_CONTROL) &
706		    AR_PHY_AGC_CONTROL_NF) == 0)
707			break;
708		drv_usecwait(10);
709	}
710
711	for (i = 0; i < NUM_NF_READINGS; i++) {
712		if (chainmask & (1 << i)) {
713			val = REG_READ(ah, ar5416_cca_regs[i]);
714			val &= 0xFFFFFE00;
715			val |= (((uint32_t)(-50) << 1) & 0x1ff);
716			REG_WRITE(ah, ar5416_cca_regs[i], val);
717		}
718	}
719}
720
721int16_t
722ath9k_hw_getnf(struct ath_hal *ah, struct ath9k_channel *chan)
723{
724	int16_t nf, nfThresh;
725	int16_t nfarray[NUM_NF_READINGS] = { 0 };
726	struct ath9k_nfcal_hist *h;
727	/* LINTED E_FUNC_SET_NOT_USED */
728	uint8_t chainmask;
729
730	if (AR_SREV_9280(ah))
731		chainmask = 0x1B;
732	else
733		chainmask = 0x3F;
734
735	chan->channelFlags &= (~CHANNEL_CW_INT);
736	if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) {
737		ARN_DBG((ARN_DBG_CALIBRATE, "arn: "
738		    "%s: NF did not complete in calibration window\n",
739		    __func__));
740		nf = 0;
741		chan->rawNoiseFloor = nf;
742		return (chan->rawNoiseFloor);
743	} else {
744		ath9k_hw_do_getnf(ah, nfarray);
745		nf = nfarray[0];
746		if (getNoiseFloorThresh(ah, chan, &nfThresh) &&
747		    nf > nfThresh) {
748			ARN_DBG((ARN_DBG_CALIBRATE, "arn: "
749			    "%s: noise floor failed detected; "
750			    "detected %d, threshold %d\n", __func__,
751			    nf, nfThresh));
752			chan->channelFlags |= CHANNEL_CW_INT;
753		}
754	}
755
756#ifdef ARN_NF_PER_CHAN
757	h = chan->nfCalHist;
758#else
759	h = ah->nfCalHist;
760#endif
761
762	ath9k_hw_update_nfcal_hist_buffer(h, nfarray);
763	chan->rawNoiseFloor = h[0].privNF;
764
765	return (chan->rawNoiseFloor);
766}
767
768void
769ath9k_init_nfcal_hist_buffer(struct ath_hal *ah)
770{
771	int i, j;
772	int16_t noise_floor;
773
774	if (AR_SREV_9280(ah))
775		noise_floor = AR_PHY_CCA_MAX_AR9280_GOOD_VALUE;
776	else if (AR_SREV_9285(ah))
777		noise_floor = AR_PHY_CCA_MAX_AR9285_GOOD_VALUE;
778	else
779		noise_floor = AR_PHY_CCA_MAX_AR5416_GOOD_VALUE;
780
781	for (i = 0; i < NUM_NF_READINGS; i++) {
782		ah->nfCalHist[i].currIndex = 0;
783		ah->nfCalHist[i].privNF = noise_floor;
784		ah->nfCalHist[i].invalidNFcount =
785		    AR_PHY_CCA_FILTERWINDOW_LENGTH;
786		for (j = 0; j < ATH9K_NF_CAL_HIST_MAX; j++) {
787			ah->nfCalHist[i].nfCalBuffer[j] = noise_floor;
788		}
789	}
790}
791
792signed short
793ath9k_hw_getchan_noise(struct ath_hal *ah, struct ath9k_channel *chan)
794{
795	struct ath9k_channel *ichan;
796	signed short nf;
797
798	ichan = ath9k_regd_check_channel(ah, chan);
799	if (ichan == NULL) {
800		ARN_DBG((ARN_DBG_CALIBRATE,
801		    "%s: invalid channel %u/0x%x; no mapping\n",
802		    __func__, chan->channel, chan->channelFlags));
803		return (ATH_DEFAULT_NOISE_FLOOR);
804	}
805	if (ichan->rawNoiseFloor == 0) {
806		enum wireless_mode mode = ath9k_hw_chan2wmode(ah, chan);
807		nf = NOISE_FLOOR[mode];
808	} else
809		nf = ichan->rawNoiseFloor;
810
811	if (!ath9k_hw_nf_in_range(ah, nf))
812		nf = ATH_DEFAULT_NOISE_FLOOR;
813
814	return (nf);
815}
816
817boolean_t
818ath9k_hw_calibrate(struct ath_hal *ah, struct ath9k_channel *chan,
819    uint8_t rxchainmask, boolean_t longcal,
820    boolean_t *isCalDone)
821{
822	struct ath_hal_5416 *ahp = AH5416(ah);
823	struct hal_cal_list *currCal = ahp->ah_cal_list_curr;
824	struct ath9k_channel *ichan = ath9k_regd_check_channel(ah, chan);
825
826	*isCalDone = B_TRUE;
827
828	if (ichan == NULL) {
829		ARN_DBG((ARN_DBG_CHANNEL,
830		    "%s: invalid channel %u/0x%x; no mapping\n",
831		    __func__, chan->channel, chan->channelFlags));
832		return (B_FALSE);
833	}
834
835	if (currCal &&
836	    (currCal->calState == CAL_RUNNING ||
837	    currCal->calState == CAL_WAITING)) {
838		ath9k_hw_per_calibration(ah, ichan, rxchainmask, currCal,
839		    isCalDone);
840		if (*isCalDone) {
841			ahp->ah_cal_list_curr = currCal = currCal->calNext;
842
843			if (currCal->calState == CAL_WAITING) {
844				*isCalDone = B_FALSE;
845				ath9k_hw_reset_calibration(ah, currCal);
846			}
847		}
848	}
849
850	if (longcal) {
851		(void) ath9k_hw_getnf(ah, ichan);
852		ath9k_hw_loadnf(ah, ah->ah_curchan);
853		ath9k_hw_start_nfcal(ah);
854
855		if ((ichan->channelFlags & CHANNEL_CW_INT) != 0) {
856			chan->channelFlags |= CHANNEL_CW_INT;
857			ichan->channelFlags &= ~CHANNEL_CW_INT;
858		}
859	}
860
861	return (B_TRUE);
862}
863
864/* AR9285 */
865static inline void
866ath9k_hw_9285_pa_cal(struct ath_hal *ah)
867{
868
869	uint32_t regVal;
870	int i, offset, offs_6_1, offs_0;
871	uint32_t ccomp_org, reg_field;
872	uint32_t regList[][2] = {
873	    { 0x786c, 0 },
874	    { 0x7854, 0 },
875	    { 0x7820, 0 },
876	    { 0x7824, 0 },
877	    { 0x7868, 0 },
878	    { 0x783c, 0 },
879	    { 0x7838, 0 },
880	};
881
882	if (AR_SREV_9285_11(ah)) {
883		REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14));
884		drv_usecwait(10);
885	}
886
887	for (i = 0; i < ARRAY_SIZE(regList); i++)
888		regList[i][1] = REG_READ(ah, regList[i][0]);
889
890	regVal = REG_READ(ah, 0x7834);
891	regVal &= (~(0x1));
892	REG_WRITE(ah, 0x7834, regVal);
893	regVal = REG_READ(ah, 0x9808);
894	regVal |= (0x1 << 27);
895	REG_WRITE(ah, 0x9808, regVal);
896
897	REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1);
898	REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1);
899	REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1);
900	REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1);
901	REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0);
902	REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0);
903	REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0);
904	REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 1);
905	REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2, 0);
906	REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0);
907	REG_RMW_FIELD(ah, AR9285_AN_RF2G8, AR9285_AN_RF2G8_PADRVGN2TAB0, 7);
908	REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PADRVGN2TAB0, 0);
909	ccomp_org = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_CCOMP);
910	REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, 7);
911
912	REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0);
913	drv_usecwait(30);
914	REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, 0);
915	REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 0);
916
917	for (i = 6; i > 0; i--) {
918		regVal = REG_READ(ah, 0x7834);
919		regVal |= (1 << (19 + i));
920		REG_WRITE(ah, 0x7834, regVal);
921		drv_usecwait(1);
922		regVal = REG_READ(ah, 0x7834);
923		regVal &= (~(0x1 << (19 + i)));
924		reg_field = MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9);
925		regVal |= (reg_field << (19 + i));
926		REG_WRITE(ah, 0x7834, regVal);
927	}
928
929	REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 1);
930	drv_usecwait(1);
931	reg_field = MS(REG_READ(ah, AR9285_AN_RF2G9), AR9285_AN_RXTXBB1_SPARE9);
932	REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, reg_field);
933	offs_6_1 = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_OFFS);
934	offs_0   = MS(REG_READ(ah, AR9285_AN_RF2G3), AR9285_AN_RF2G3_PDVCCOMP);
935
936	offset = (offs_6_1<<1) | offs_0;
937	offset = offset - 0;
938	offs_6_1 = offset>>1;
939	offs_0 = offset & 1;
940
941	REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, offs_6_1);
942	REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, offs_0);
943
944	regVal = REG_READ(ah, 0x7834);
945	regVal |= 0x1;
946	REG_WRITE(ah, 0x7834, regVal);
947	regVal = REG_READ(ah, 0x9808);
948	regVal &= (~(0x1 << 27));
949	REG_WRITE(ah, 0x9808, regVal);
950
951	for (i = 0; i < ARRAY_SIZE(regList); i++)
952		REG_WRITE(ah, regList[i][0], regList[i][1]);
953
954	REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, ccomp_org);
955
956	if (AR_SREV_9285_11(ah))
957		REG_WRITE(ah, AR9285_AN_TOP4, AR9285_AN_TOP4_DEFAULT);
958
959}
960
961boolean_t
962ath9k_hw_init_cal(struct ath_hal *ah,
963    struct ath9k_channel *chan)
964{
965	struct ath_hal_5416 *ahp = AH5416(ah);
966	struct ath9k_channel *ichan = ath9k_regd_check_channel(ah, chan);
967
968	REG_WRITE(ah, AR_PHY_AGC_CONTROL,
969	    REG_READ(ah, AR_PHY_AGC_CONTROL) |
970	    AR_PHY_AGC_CONTROL_CAL);
971
972	if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0)) {
973		ARN_DBG((ARN_DBG_CALIBRATE,
974		    "%s: offset calibration failed to complete in 1ms; "
975		    "noisy environment?\n", __func__));
976		return (B_FALSE);
977	}
978
979	if (AR_SREV_9285(ah) && AR_SREV_9285_11_OR_LATER(ah))
980			ath9k_hw_9285_pa_cal(ah);
981
982	REG_WRITE(ah, AR_PHY_AGC_CONTROL,
983	    REG_READ(ah, AR_PHY_AGC_CONTROL) |
984	    AR_PHY_AGC_CONTROL_NF);
985
986	ahp->ah_cal_list = ahp->ah_cal_list_last = ahp->ah_cal_list_curr = NULL;
987
988	if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) {
989		if (ath9k_hw_iscal_supported(ah, chan, ADC_GAIN_CAL)) {
990			/* LINTED: E_CONSTANT_CONDITION */
991			INIT_CAL(&ahp->ah_adcGainCalData);
992			/* LINTED: E_CONSTANT_CONDITION */
993			INSERT_CAL(ahp, &ahp->ah_adcGainCalData);
994			ARN_DBG((ARN_DBG_CALIBRATE,
995			    "%s: enabling ADC Gain Calibration.\n",
996			    __func__));
997		}
998		if (ath9k_hw_iscal_supported(ah, chan, ADC_DC_CAL)) {
999			/* LINTED: E_CONSTANT_CONDITION */
1000			INIT_CAL(&ahp->ah_adcDcCalData);
1001			/* LINTED: E_CONSTANT_CONDITION */
1002			INSERT_CAL(ahp, &ahp->ah_adcDcCalData);
1003			ARN_DBG((ARN_DBG_CALIBRATE,
1004			    "%s: enabling ADC DC Calibration.\n",
1005			    __func__));
1006		}
1007		if (ath9k_hw_iscal_supported(ah, chan, IQ_MISMATCH_CAL)) {
1008			/* LINTED: E_CONSTANT_CONDITION */
1009			INIT_CAL(&ahp->ah_iqCalData);
1010			/* LINTED: E_CONSTANT_CONDITION */
1011			INSERT_CAL(ahp, &ahp->ah_iqCalData);
1012			ARN_DBG((ARN_DBG_CALIBRATE,
1013			    "%s: enabling IQ Calibration.\n",
1014			    __func__));
1015		}
1016
1017		ahp->ah_cal_list_curr = ahp->ah_cal_list;
1018
1019		if (ahp->ah_cal_list_curr)
1020			ath9k_hw_reset_calibration(ah, ahp->ah_cal_list_curr);
1021	}
1022
1023	ichan->CalValid = 0;
1024
1025	return (B_TRUE);
1026}
1027
1028const struct hal_percal_data iq_cal_multi_sample = {
1029	IQ_MISMATCH_CAL,
1030	MAX_CAL_SAMPLES,
1031	PER_MIN_LOG_COUNT,
1032	ath9k_hw_iqcal_collect,
1033	ath9k_hw_iqcalibrate
1034};
1035const struct hal_percal_data iq_cal_single_sample = {
1036	IQ_MISMATCH_CAL,
1037	MIN_CAL_SAMPLES,
1038	PER_MAX_LOG_COUNT,
1039	ath9k_hw_iqcal_collect,
1040	ath9k_hw_iqcalibrate
1041};
1042const struct hal_percal_data adc_gain_cal_multi_sample = {
1043	ADC_GAIN_CAL,
1044	MAX_CAL_SAMPLES,
1045	PER_MIN_LOG_COUNT,
1046	ath9k_hw_adc_gaincal_collect,
1047	ath9k_hw_adc_gaincal_calibrate
1048};
1049const struct hal_percal_data adc_gain_cal_single_sample = {
1050	ADC_GAIN_CAL,
1051	MIN_CAL_SAMPLES,
1052	PER_MAX_LOG_COUNT,
1053	ath9k_hw_adc_gaincal_collect,
1054	ath9k_hw_adc_gaincal_calibrate
1055};
1056const struct hal_percal_data adc_dc_cal_multi_sample = {
1057	ADC_DC_CAL,
1058	MAX_CAL_SAMPLES,
1059	PER_MIN_LOG_COUNT,
1060	ath9k_hw_adc_dccal_collect,
1061	ath9k_hw_adc_dccal_calibrate
1062};
1063const struct hal_percal_data adc_dc_cal_single_sample = {
1064	ADC_DC_CAL,
1065	MIN_CAL_SAMPLES,
1066	PER_MAX_LOG_COUNT,
1067	ath9k_hw_adc_dccal_collect,
1068	ath9k_hw_adc_dccal_calibrate
1069};
1070const struct hal_percal_data adc_init_dc_cal = {
1071	ADC_DC_INIT_CAL,
1072	MIN_CAL_SAMPLES,
1073	INIT_LOG_COUNT,
1074	ath9k_hw_adc_dccal_collect,
1075	ath9k_hw_adc_dccal_calibrate
1076};
1077