1/*
2 * Copyright (c) 2008-2011 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 "ar9002_phy.h"
20
21#define AR9285_CLCAL_REDO_THRESH    1
22
23enum ar9002_cal_types {
24	ADC_GAIN_CAL = BIT(0),
25	ADC_DC_CAL = BIT(1),
26	IQ_MISMATCH_CAL = BIT(2),
27};
28
29static bool ar9002_hw_is_cal_supported(struct ath_hw *ah,
30				struct ath9k_channel *chan,
31				enum ar9002_cal_types cal_type)
32{
33	bool supported = false;
34	switch (ah->supp_cals & cal_type) {
35	case IQ_MISMATCH_CAL:
36		supported = true;
37		break;
38	case ADC_GAIN_CAL:
39	case ADC_DC_CAL:
40		/* Run ADC Gain Cal for non-CCK & non 2GHz-HT20 only */
41		if (!((IS_CHAN_2GHZ(chan) || IS_CHAN_A_FAST_CLOCK(ah, chan)) &&
42		      IS_CHAN_HT20(chan)))
43			supported = true;
44		break;
45	}
46	return supported;
47}
48
49static void ar9002_hw_setup_calibration(struct ath_hw *ah,
50					struct ath9k_cal_list *currCal)
51{
52	struct ath_common *common = ath9k_hw_common(ah);
53
54	REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(0),
55		      AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX,
56		      currCal->calData->calCountMax);
57
58	switch (currCal->calData->calType) {
59	case IQ_MISMATCH_CAL:
60		REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ);
61		ath_dbg(common, CALIBRATE,
62			"starting IQ Mismatch Calibration\n");
63		break;
64	case ADC_GAIN_CAL:
65		REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_GAIN);
66		ath_dbg(common, CALIBRATE, "starting ADC Gain Calibration\n");
67		break;
68	case ADC_DC_CAL:
69		REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_PER);
70		ath_dbg(common, CALIBRATE, "starting ADC DC Calibration\n");
71		break;
72	}
73
74	REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0),
75		    AR_PHY_TIMING_CTRL4_DO_CAL);
76}
77
78static bool ar9002_hw_per_calibration(struct ath_hw *ah,
79				      struct ath9k_channel *ichan,
80				      u8 rxchainmask,
81				      struct ath9k_cal_list *currCal)
82{
83	struct ath9k_hw_cal_data *caldata = ah->caldata;
84	bool iscaldone = false;
85
86	if (currCal->calState == CAL_RUNNING) {
87		if (!(REG_READ(ah, AR_PHY_TIMING_CTRL4(0)) &
88		      AR_PHY_TIMING_CTRL4_DO_CAL)) {
89
90			currCal->calData->calCollect(ah);
91			ah->cal_samples++;
92
93			if (ah->cal_samples >=
94			    currCal->calData->calNumSamples) {
95				int i, numChains = 0;
96				for (i = 0; i < AR5416_MAX_CHAINS; i++) {
97					if (rxchainmask & (1 << i))
98						numChains++;
99				}
100
101				currCal->calData->calPostProc(ah, numChains);
102				caldata->CalValid |= currCal->calData->calType;
103				currCal->calState = CAL_DONE;
104				iscaldone = true;
105			} else {
106				ar9002_hw_setup_calibration(ah, currCal);
107			}
108		}
109	} else if (!(caldata->CalValid & currCal->calData->calType)) {
110		ath9k_hw_reset_calibration(ah, currCal);
111	}
112
113	return iscaldone;
114}
115
116static void ar9002_hw_iqcal_collect(struct ath_hw *ah)
117{
118	int i;
119
120	for (i = 0; i < AR5416_MAX_CHAINS; i++) {
121		ah->totalPowerMeasI[i] +=
122			REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
123		ah->totalPowerMeasQ[i] +=
124			REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
125		ah->totalIqCorrMeas[i] +=
126			(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
127		ath_dbg(ath9k_hw_common(ah), CALIBRATE,
128			"%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
129			ah->cal_samples, i, ah->totalPowerMeasI[i],
130			ah->totalPowerMeasQ[i],
131			ah->totalIqCorrMeas[i]);
132	}
133}
134
135static void ar9002_hw_adc_gaincal_collect(struct ath_hw *ah)
136{
137	int i;
138
139	for (i = 0; i < AR5416_MAX_CHAINS; i++) {
140		ah->totalAdcIOddPhase[i] +=
141			REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
142		ah->totalAdcIEvenPhase[i] +=
143			REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
144		ah->totalAdcQOddPhase[i] +=
145			REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
146		ah->totalAdcQEvenPhase[i] +=
147			REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
148
149		ath_dbg(ath9k_hw_common(ah), CALIBRATE,
150			"%d: Chn %d oddi=0x%08x; eveni=0x%08x; oddq=0x%08x; evenq=0x%08x;\n",
151			ah->cal_samples, i,
152			ah->totalAdcIOddPhase[i],
153			ah->totalAdcIEvenPhase[i],
154			ah->totalAdcQOddPhase[i],
155			ah->totalAdcQEvenPhase[i]);
156	}
157}
158
159static void ar9002_hw_adc_dccal_collect(struct ath_hw *ah)
160{
161	int i;
162
163	for (i = 0; i < AR5416_MAX_CHAINS; i++) {
164		ah->totalAdcDcOffsetIOddPhase[i] +=
165			(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
166		ah->totalAdcDcOffsetIEvenPhase[i] +=
167			(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
168		ah->totalAdcDcOffsetQOddPhase[i] +=
169			(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
170		ah->totalAdcDcOffsetQEvenPhase[i] +=
171			(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
172
173		ath_dbg(ath9k_hw_common(ah), CALIBRATE,
174			"%d: Chn %d oddi=0x%08x; eveni=0x%08x; oddq=0x%08x; evenq=0x%08x;\n",
175			ah->cal_samples, i,
176			ah->totalAdcDcOffsetIOddPhase[i],
177			ah->totalAdcDcOffsetIEvenPhase[i],
178			ah->totalAdcDcOffsetQOddPhase[i],
179			ah->totalAdcDcOffsetQEvenPhase[i]);
180	}
181}
182
183static void ar9002_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
184{
185	struct ath_common *common = ath9k_hw_common(ah);
186	u32 powerMeasQ, powerMeasI, iqCorrMeas;
187	u32 qCoffDenom, iCoffDenom;
188	int32_t qCoff, iCoff;
189	int iqCorrNeg, i;
190
191	for (i = 0; i < numChains; i++) {
192		powerMeasI = ah->totalPowerMeasI[i];
193		powerMeasQ = ah->totalPowerMeasQ[i];
194		iqCorrMeas = ah->totalIqCorrMeas[i];
195
196		ath_dbg(common, CALIBRATE,
197			"Starting IQ Cal and Correction for Chain %d\n",
198			i);
199
200		ath_dbg(common, CALIBRATE,
201			"Original: Chn %d iq_corr_meas = 0x%08x\n",
202			i, ah->totalIqCorrMeas[i]);
203
204		iqCorrNeg = 0;
205
206		if (iqCorrMeas > 0x80000000) {
207			iqCorrMeas = (0xffffffff - iqCorrMeas) + 1;
208			iqCorrNeg = 1;
209		}
210
211		ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_i = 0x%08x\n",
212			i, powerMeasI);
213		ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_q = 0x%08x\n",
214			i, powerMeasQ);
215		ath_dbg(common, CALIBRATE, "iqCorrNeg is 0x%08x\n", iqCorrNeg);
216
217		iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128;
218		qCoffDenom = powerMeasQ / 64;
219
220		if ((powerMeasQ != 0) && (iCoffDenom != 0) &&
221		    (qCoffDenom != 0)) {
222			iCoff = iqCorrMeas / iCoffDenom;
223			qCoff = powerMeasI / qCoffDenom - 64;
224			ath_dbg(common, CALIBRATE, "Chn %d iCoff = 0x%08x\n",
225				i, iCoff);
226			ath_dbg(common, CALIBRATE, "Chn %d qCoff = 0x%08x\n",
227				i, qCoff);
228
229			iCoff = iCoff & 0x3f;
230			ath_dbg(common, CALIBRATE,
231				"New: Chn %d iCoff = 0x%08x\n", i, iCoff);
232			if (iqCorrNeg == 0x0)
233				iCoff = 0x40 - iCoff;
234
235			if (qCoff > 15)
236				qCoff = 15;
237			else if (qCoff <= -16)
238				qCoff = -16;
239
240			ath_dbg(common, CALIBRATE,
241				"Chn %d : iCoff = 0x%x  qCoff = 0x%x\n",
242				i, iCoff, qCoff);
243
244			REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i),
245				      AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF,
246				      iCoff);
247			REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i),
248				      AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF,
249				      qCoff);
250			ath_dbg(common, CALIBRATE,
251				"IQ Cal and Correction done for Chain %d\n",
252				i);
253		}
254	}
255
256	REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0),
257		    AR_PHY_TIMING_CTRL4_IQCORR_ENABLE);
258}
259
260static void ar9002_hw_adc_gaincal_calibrate(struct ath_hw *ah, u8 numChains)
261{
262	struct ath_common *common = ath9k_hw_common(ah);
263	u32 iOddMeasOffset, iEvenMeasOffset, qOddMeasOffset, qEvenMeasOffset;
264	u32 qGainMismatch, iGainMismatch, val, i;
265
266	for (i = 0; i < numChains; i++) {
267		iOddMeasOffset = ah->totalAdcIOddPhase[i];
268		iEvenMeasOffset = ah->totalAdcIEvenPhase[i];
269		qOddMeasOffset = ah->totalAdcQOddPhase[i];
270		qEvenMeasOffset = ah->totalAdcQEvenPhase[i];
271
272		ath_dbg(common, CALIBRATE,
273			"Starting ADC Gain Cal for Chain %d\n", i);
274
275		ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_odd_i = 0x%08x\n",
276			i, iOddMeasOffset);
277		ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_even_i = 0x%08x\n",
278			i, iEvenMeasOffset);
279		ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_odd_q = 0x%08x\n",
280			i, qOddMeasOffset);
281		ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_even_q = 0x%08x\n",
282			i, qEvenMeasOffset);
283
284		if (iOddMeasOffset != 0 && qEvenMeasOffset != 0) {
285			iGainMismatch =
286				((iEvenMeasOffset * 32) /
287				 iOddMeasOffset) & 0x3f;
288			qGainMismatch =
289				((qOddMeasOffset * 32) /
290				 qEvenMeasOffset) & 0x3f;
291
292			ath_dbg(common, CALIBRATE,
293				"Chn %d gain_mismatch_i = 0x%08x\n",
294				i, iGainMismatch);
295			ath_dbg(common, CALIBRATE,
296				"Chn %d gain_mismatch_q = 0x%08x\n",
297				i, qGainMismatch);
298
299			val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
300			val &= 0xfffff000;
301			val |= (qGainMismatch) | (iGainMismatch << 6);
302			REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
303
304			ath_dbg(common, CALIBRATE,
305				"ADC Gain Cal done for Chain %d\n", i);
306		}
307	}
308
309	REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
310		  REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
311		  AR_PHY_NEW_ADC_GAIN_CORR_ENABLE);
312}
313
314static void ar9002_hw_adc_dccal_calibrate(struct ath_hw *ah, u8 numChains)
315{
316	struct ath_common *common = ath9k_hw_common(ah);
317	u32 iOddMeasOffset, iEvenMeasOffset, val, i;
318	int32_t qOddMeasOffset, qEvenMeasOffset, qDcMismatch, iDcMismatch;
319	const struct ath9k_percal_data *calData =
320		ah->cal_list_curr->calData;
321	u32 numSamples =
322		(1 << (calData->calCountMax + 5)) * calData->calNumSamples;
323
324	for (i = 0; i < numChains; i++) {
325		iOddMeasOffset = ah->totalAdcDcOffsetIOddPhase[i];
326		iEvenMeasOffset = ah->totalAdcDcOffsetIEvenPhase[i];
327		qOddMeasOffset = ah->totalAdcDcOffsetQOddPhase[i];
328		qEvenMeasOffset = ah->totalAdcDcOffsetQEvenPhase[i];
329
330		ath_dbg(common, CALIBRATE,
331			"Starting ADC DC Offset Cal for Chain %d\n", i);
332
333		ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_odd_i = %d\n",
334			i, iOddMeasOffset);
335		ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_even_i = %d\n",
336			i, iEvenMeasOffset);
337		ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_odd_q = %d\n",
338			i, qOddMeasOffset);
339		ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_even_q = %d\n",
340			i, qEvenMeasOffset);
341
342		iDcMismatch = (((iEvenMeasOffset - iOddMeasOffset) * 2) /
343			       numSamples) & 0x1ff;
344		qDcMismatch = (((qOddMeasOffset - qEvenMeasOffset) * 2) /
345			       numSamples) & 0x1ff;
346
347		ath_dbg(common, CALIBRATE,
348			"Chn %d dc_offset_mismatch_i = 0x%08x\n",
349			i, iDcMismatch);
350		ath_dbg(common, CALIBRATE,
351			"Chn %d dc_offset_mismatch_q = 0x%08x\n",
352			i, qDcMismatch);
353
354		val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
355		val &= 0xc0000fff;
356		val |= (qDcMismatch << 12) | (iDcMismatch << 21);
357		REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
358
359		ath_dbg(common, CALIBRATE,
360			"ADC DC Offset Cal done for Chain %d\n", i);
361	}
362
363	REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
364		  REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
365		  AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE);
366}
367
368static void ar9287_hw_olc_temp_compensation(struct ath_hw *ah)
369{
370	u32 rddata;
371	int32_t delta, currPDADC, slope;
372
373	rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4);
374	currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT);
375
376	if (ah->initPDADC == 0 || currPDADC == 0) {
377		/*
378		 * Zero value indicates that no frames have been transmitted
379		 * yet, can't do temperature compensation until frames are
380		 * transmitted.
381		 */
382		return;
383	} else {
384		slope = ah->eep_ops->get_eeprom(ah, EEP_TEMPSENSE_SLOPE);
385
386		if (slope == 0) { /* to avoid divide by zero case */
387			delta = 0;
388		} else {
389			delta = ((currPDADC - ah->initPDADC)*4) / slope;
390		}
391		REG_RMW_FIELD(ah, AR_PHY_CH0_TX_PWRCTRL11,
392			      AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta);
393		REG_RMW_FIELD(ah, AR_PHY_CH1_TX_PWRCTRL11,
394			      AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta);
395	}
396}
397
398static void ar9280_hw_olc_temp_compensation(struct ath_hw *ah)
399{
400	u32 rddata, i;
401	int delta, currPDADC, regval;
402
403	rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4);
404	currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT);
405
406	if (ah->initPDADC == 0 || currPDADC == 0)
407		return;
408
409	if (ah->eep_ops->get_eeprom(ah, EEP_DAC_HPWR_5G))
410		delta = (currPDADC - ah->initPDADC + 4) / 8;
411	else
412		delta = (currPDADC - ah->initPDADC + 5) / 10;
413
414	if (delta != ah->PDADCdelta) {
415		ah->PDADCdelta = delta;
416		for (i = 1; i < AR9280_TX_GAIN_TABLE_SIZE; i++) {
417			regval = ah->originalGain[i] - delta;
418			if (regval < 0)
419				regval = 0;
420
421			REG_RMW_FIELD(ah,
422				      AR_PHY_TX_GAIN_TBL1 + i * 4,
423				      AR_PHY_TX_GAIN, regval);
424		}
425	}
426}
427
428static void ar9271_hw_pa_cal(struct ath_hw *ah, bool is_reset)
429{
430	u32 regVal;
431	unsigned int i;
432	u32 regList[][2] = {
433		{ AR9285_AN_TOP3, 0 },
434		{ AR9285_AN_RXTXBB1, 0 },
435		{ AR9285_AN_RF2G1, 0 },
436		{ AR9285_AN_RF2G2, 0 },
437		{ AR9285_AN_TOP2, 0 },
438		{ AR9285_AN_RF2G8, 0 },
439		{ AR9285_AN_RF2G7, 0 },
440		{ AR9285_AN_RF2G3, 0 },
441	};
442
443	REG_READ_ARRAY(ah, regList, ARRAY_SIZE(regList));
444
445	ENABLE_REG_RMW_BUFFER(ah);
446	/* 7834, b1=0 */
447	REG_CLR_BIT(ah, AR9285_AN_RF2G6, 1 << 0);
448	/* 9808, b27=1 */
449	REG_SET_BIT(ah, 0x9808, 1 << 27);
450	/* 786c,b23,1, pwddac=1 */
451	REG_SET_BIT(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC);
452	/* 7854, b5,1, pdrxtxbb=1 */
453	REG_SET_BIT(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1);
454	/* 7854, b7,1, pdv2i=1 */
455	REG_SET_BIT(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I);
456	/* 7854, b8,1, pddacinterface=1 */
457	REG_SET_BIT(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF);
458	/* 7824,b12,0, offcal=0 */
459	REG_CLR_BIT(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL);
460	/* 7838, b1,0, pwddb=0 */
461	REG_CLR_BIT(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB);
462	/* 7820,b11,0, enpacal=0 */
463	REG_CLR_BIT(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL);
464	/* 7820,b25,1, pdpadrv1=0 */
465	REG_CLR_BIT(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1);
466	/* 7820,b24,0, pdpadrv2=0 */
467	REG_CLR_BIT(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2);
468	/* 7820,b23,0, pdpaout=0 */
469	REG_CLR_BIT(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT);
470	/* 783c,b14-16,7, padrvgn2tab_0=7 */
471	REG_RMW_FIELD(ah, AR9285_AN_RF2G8, AR9285_AN_RF2G8_PADRVGN2TAB0, 7);
472	/*
473	 * 7838,b29-31,0, padrvgn1tab_0=0
474	 * does not matter since we turn it off
475	 */
476	REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PADRVGN2TAB0, 0);
477	/* 7828, b0-11, ccom=fff */
478	REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9271_AN_RF2G3_CCOMP, 0xfff);
479	REG_RMW_BUFFER_FLUSH(ah);
480
481	/* Set:
482	 * localmode=1,bmode=1,bmoderxtx=1,synthon=1,
483	 * txon=1,paon=1,oscon=1,synthon_force=1
484	 */
485	REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0);
486	udelay(30);
487	REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9271_AN_RF2G6_OFFS, 0);
488
489	/* find off_6_1; */
490	for (i = 6; i > 0; i--) {
491		regVal = REG_READ(ah, AR9285_AN_RF2G6);
492		regVal |= (1 << (20 + i));
493		REG_WRITE(ah, AR9285_AN_RF2G6, regVal);
494		udelay(1);
495		/* regVal = REG_READ(ah, 0x7834); */
496		regVal &= (~(0x1 << (20 + i)));
497		regVal |= (MS(REG_READ(ah, AR9285_AN_RF2G9),
498			      AR9285_AN_RXTXBB1_SPARE9)
499			    << (20 + i));
500		REG_WRITE(ah, AR9285_AN_RF2G6, regVal);
501	}
502
503	regVal = (regVal >> 20) & 0x7f;
504
505	/* Update PA cal info */
506	if ((!is_reset) && (ah->pacal_info.prev_offset == regVal)) {
507		if (ah->pacal_info.max_skipcount < MAX_PACAL_SKIPCOUNT)
508			ah->pacal_info.max_skipcount =
509				2 * ah->pacal_info.max_skipcount;
510		ah->pacal_info.skipcount = ah->pacal_info.max_skipcount;
511	} else {
512		ah->pacal_info.max_skipcount = 1;
513		ah->pacal_info.skipcount = 0;
514		ah->pacal_info.prev_offset = regVal;
515	}
516
517
518	ENABLE_REG_RMW_BUFFER(ah);
519	/* 7834, b1=1 */
520	REG_SET_BIT(ah, AR9285_AN_RF2G6, 1 << 0);
521	/* 9808, b27=0 */
522	REG_CLR_BIT(ah, 0x9808, 1 << 27);
523	REG_RMW_BUFFER_FLUSH(ah);
524
525	ENABLE_REGWRITE_BUFFER(ah);
526	for (i = 0; i < ARRAY_SIZE(regList); i++)
527		REG_WRITE(ah, regList[i][0], regList[i][1]);
528
529	REGWRITE_BUFFER_FLUSH(ah);
530}
531
532static inline void ar9285_hw_pa_cal(struct ath_hw *ah, bool is_reset)
533{
534	struct ath_common *common = ath9k_hw_common(ah);
535	u32 regVal;
536	int i, offset, offs_6_1, offs_0;
537	u32 ccomp_org, reg_field;
538	u32 regList[][2] = {
539		{ 0x786c, 0 },
540		{ 0x7854, 0 },
541		{ 0x7820, 0 },
542		{ 0x7824, 0 },
543		{ 0x7868, 0 },
544		{ 0x783c, 0 },
545		{ 0x7838, 0 },
546	};
547
548	ath_dbg(common, CALIBRATE, "Running PA Calibration\n");
549
550	/* PA CAL is not needed for high power solution */
551	if (ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE) ==
552	    AR5416_EEP_TXGAIN_HIGH_POWER)
553		return;
554
555	for (i = 0; i < ARRAY_SIZE(regList); i++)
556		regList[i][1] = REG_READ(ah, regList[i][0]);
557
558	regVal = REG_READ(ah, 0x7834);
559	regVal &= (~(0x1));
560	REG_WRITE(ah, 0x7834, regVal);
561	regVal = REG_READ(ah, 0x9808);
562	regVal |= (0x1 << 27);
563	REG_WRITE(ah, 0x9808, regVal);
564
565	REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1);
566	REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1);
567	REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1);
568	REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1);
569	REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0);
570	REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0);
571	REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0);
572	REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 0);
573	REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2, 0);
574	REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0);
575	REG_RMW_FIELD(ah, AR9285_AN_RF2G8, AR9285_AN_RF2G8_PADRVGN2TAB0, 7);
576	REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PADRVGN2TAB0, 0);
577	ccomp_org = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_CCOMP);
578	REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, 0xf);
579
580	REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0);
581	udelay(30);
582	REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, 0);
583	REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 0);
584
585	for (i = 6; i > 0; i--) {
586		regVal = REG_READ(ah, 0x7834);
587		regVal |= (1 << (19 + i));
588		REG_WRITE(ah, 0x7834, regVal);
589		udelay(1);
590		regVal = REG_READ(ah, 0x7834);
591		regVal &= (~(0x1 << (19 + i)));
592		reg_field = MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9);
593		regVal |= (reg_field << (19 + i));
594		REG_WRITE(ah, 0x7834, regVal);
595	}
596
597	REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 1);
598	udelay(1);
599	reg_field = MS(REG_READ(ah, AR9285_AN_RF2G9), AR9285_AN_RXTXBB1_SPARE9);
600	REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, reg_field);
601	offs_6_1 = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_OFFS);
602	offs_0   = MS(REG_READ(ah, AR9285_AN_RF2G3), AR9285_AN_RF2G3_PDVCCOMP);
603
604	offset = (offs_6_1<<1) | offs_0;
605	offset = offset - 0;
606	offs_6_1 = offset>>1;
607	offs_0 = offset & 1;
608
609	if ((!is_reset) && (ah->pacal_info.prev_offset == offset)) {
610		if (ah->pacal_info.max_skipcount < MAX_PACAL_SKIPCOUNT)
611			ah->pacal_info.max_skipcount =
612				2 * ah->pacal_info.max_skipcount;
613		ah->pacal_info.skipcount = ah->pacal_info.max_skipcount;
614	} else {
615		ah->pacal_info.max_skipcount = 1;
616		ah->pacal_info.skipcount = 0;
617		ah->pacal_info.prev_offset = offset;
618	}
619
620	REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, offs_6_1);
621	REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, offs_0);
622
623	regVal = REG_READ(ah, 0x7834);
624	regVal |= 0x1;
625	REG_WRITE(ah, 0x7834, regVal);
626	regVal = REG_READ(ah, 0x9808);
627	regVal &= (~(0x1 << 27));
628	REG_WRITE(ah, 0x9808, regVal);
629
630	for (i = 0; i < ARRAY_SIZE(regList); i++)
631		REG_WRITE(ah, regList[i][0], regList[i][1]);
632
633	REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, ccomp_org);
634}
635
636static void ar9002_hw_pa_cal(struct ath_hw *ah, bool is_reset)
637{
638	if (AR_SREV_9271(ah)) {
639		if (is_reset || !ah->pacal_info.skipcount)
640			ar9271_hw_pa_cal(ah, is_reset);
641		else
642			ah->pacal_info.skipcount--;
643	} else if (AR_SREV_9285_12_OR_LATER(ah)) {
644		if (is_reset || !ah->pacal_info.skipcount)
645			ar9285_hw_pa_cal(ah, is_reset);
646		else
647			ah->pacal_info.skipcount--;
648	}
649}
650
651static void ar9002_hw_olc_temp_compensation(struct ath_hw *ah)
652{
653	if (OLC_FOR_AR9287_10_LATER)
654		ar9287_hw_olc_temp_compensation(ah);
655	else if (OLC_FOR_AR9280_20_LATER)
656		ar9280_hw_olc_temp_compensation(ah);
657}
658
659static int ar9002_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan,
660			       u8 rxchainmask, bool longcal)
661{
662	struct ath9k_cal_list *currCal = ah->cal_list_curr;
663	bool nfcal, nfcal_pending = false, percal_pending;
664	int ret;
665
666	nfcal = !!(REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF);
667	if (ah->caldata)
668		nfcal_pending = test_bit(NFCAL_PENDING, &ah->caldata->cal_flags);
669
670	percal_pending = (currCal &&
671			  (currCal->calState == CAL_RUNNING ||
672			   currCal->calState == CAL_WAITING));
673
674	if (percal_pending && !nfcal) {
675		if (!ar9002_hw_per_calibration(ah, chan, rxchainmask, currCal))
676			return 0;
677
678		ah->cal_list_curr = currCal = currCal->calNext;
679		if (currCal->calState == CAL_WAITING) {
680			ath9k_hw_reset_calibration(ah, currCal);
681			return 0;
682		}
683	}
684
685	/* Do NF cal only at longer intervals */
686	if (longcal || nfcal_pending) {
687		/*
688		 * Get the value from the previous NF cal and update
689		 * history buffer.
690		 */
691		if (ath9k_hw_getnf(ah, chan)) {
692			/*
693			 * Load the NF from history buffer of the current
694			 * channel.
695			 * NF is slow time-variant, so it is OK to use a
696			 * historical value.
697			 */
698			ret = ath9k_hw_loadnf(ah, ah->curchan);
699			if (ret < 0)
700				return ret;
701		}
702
703		if (longcal) {
704			ath9k_hw_start_nfcal(ah, false);
705			/* Do periodic PAOffset Cal */
706			ar9002_hw_pa_cal(ah, false);
707			ar9002_hw_olc_temp_compensation(ah);
708		}
709	}
710
711	return !percal_pending;
712}
713
714/* Carrier leakage Calibration fix */
715static bool ar9285_hw_cl_cal(struct ath_hw *ah, struct ath9k_channel *chan)
716{
717	struct ath_common *common = ath9k_hw_common(ah);
718
719	REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
720	if (IS_CHAN_HT20(chan)) {
721		REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE);
722		REG_SET_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN);
723		REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
724			    AR_PHY_AGC_CONTROL_FLTR_CAL);
725		REG_CLR_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE);
726		REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL);
727		if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
728				  AR_PHY_AGC_CONTROL_CAL, 0, AH_WAIT_TIMEOUT)) {
729			ath_dbg(common, CALIBRATE,
730				"offset calibration failed to complete in %d ms; noisy environment?\n",
731				AH_WAIT_TIMEOUT / 1000);
732			return false;
733		}
734		REG_CLR_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN);
735		REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE);
736		REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
737	}
738	REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
739	REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL);
740	REG_SET_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE);
741	REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL);
742	if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL,
743			  0, AH_WAIT_TIMEOUT)) {
744		ath_dbg(common, CALIBRATE,
745			"offset calibration failed to complete in %d ms; noisy environment?\n",
746			AH_WAIT_TIMEOUT / 1000);
747		return false;
748	}
749
750	REG_SET_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
751	REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
752	REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL);
753
754	return true;
755}
756
757static bool ar9285_hw_clc(struct ath_hw *ah, struct ath9k_channel *chan)
758{
759	int i;
760	u_int32_t txgain_max;
761	u_int32_t clc_gain, gain_mask = 0, clc_num = 0;
762	u_int32_t reg_clc_I0, reg_clc_Q0;
763	u_int32_t i0_num = 0;
764	u_int32_t q0_num = 0;
765	u_int32_t total_num = 0;
766	u_int32_t reg_rf2g5_org;
767	bool retv = true;
768
769	if (!(ar9285_hw_cl_cal(ah, chan)))
770		return false;
771
772	txgain_max = MS(REG_READ(ah, AR_PHY_TX_PWRCTRL7),
773			AR_PHY_TX_PWRCTRL_TX_GAIN_TAB_MAX);
774
775	for (i = 0; i < (txgain_max+1); i++) {
776		clc_gain = (REG_READ(ah, (AR_PHY_TX_GAIN_TBL1+(i<<2))) &
777			   AR_PHY_TX_GAIN_CLC) >> AR_PHY_TX_GAIN_CLC_S;
778		if (!(gain_mask & (1 << clc_gain))) {
779			gain_mask |= (1 << clc_gain);
780			clc_num++;
781		}
782	}
783
784	for (i = 0; i < clc_num; i++) {
785		reg_clc_I0 = (REG_READ(ah, (AR_PHY_CLC_TBL1 + (i << 2)))
786			      & AR_PHY_CLC_I0) >> AR_PHY_CLC_I0_S;
787		reg_clc_Q0 = (REG_READ(ah, (AR_PHY_CLC_TBL1 + (i << 2)))
788			      & AR_PHY_CLC_Q0) >> AR_PHY_CLC_Q0_S;
789		if (reg_clc_I0 == 0)
790			i0_num++;
791
792		if (reg_clc_Q0 == 0)
793			q0_num++;
794	}
795	total_num = i0_num + q0_num;
796	if (total_num > AR9285_CLCAL_REDO_THRESH) {
797		reg_rf2g5_org = REG_READ(ah, AR9285_RF2G5);
798		if (AR_SREV_9285E_20(ah)) {
799			REG_WRITE(ah, AR9285_RF2G5,
800				  (reg_rf2g5_org & AR9285_RF2G5_IC50TX) |
801				  AR9285_RF2G5_IC50TX_XE_SET);
802		} else {
803			REG_WRITE(ah, AR9285_RF2G5,
804				  (reg_rf2g5_org & AR9285_RF2G5_IC50TX) |
805				  AR9285_RF2G5_IC50TX_SET);
806		}
807		retv = ar9285_hw_cl_cal(ah, chan);
808		REG_WRITE(ah, AR9285_RF2G5, reg_rf2g5_org);
809	}
810	return retv;
811}
812
813static bool ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan)
814{
815	struct ath_common *common = ath9k_hw_common(ah);
816
817	if (AR_SREV_9271(ah)) {
818		if (!ar9285_hw_cl_cal(ah, chan))
819			return false;
820	} else if (AR_SREV_9285(ah) && AR_SREV_9285_12_OR_LATER(ah)) {
821		if (!ar9285_hw_clc(ah, chan))
822			return false;
823	} else {
824		if (AR_SREV_9280_20_OR_LATER(ah)) {
825			if (!AR_SREV_9287_11_OR_LATER(ah))
826				REG_CLR_BIT(ah, AR_PHY_ADC_CTL,
827					    AR_PHY_ADC_CTL_OFF_PWDADC);
828			REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
829				    AR_PHY_AGC_CONTROL_FLTR_CAL);
830		}
831
832		/* Calibrate the AGC */
833		REG_WRITE(ah, AR_PHY_AGC_CONTROL,
834			  REG_READ(ah, AR_PHY_AGC_CONTROL) |
835			  AR_PHY_AGC_CONTROL_CAL);
836
837		/* Poll for offset calibration complete */
838		if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
839				   AR_PHY_AGC_CONTROL_CAL,
840				   0, AH_WAIT_TIMEOUT)) {
841			ath_dbg(common, CALIBRATE,
842				"offset calibration failed to complete in %d ms; noisy environment?\n",
843				AH_WAIT_TIMEOUT / 1000);
844			return false;
845		}
846
847		if (AR_SREV_9280_20_OR_LATER(ah)) {
848			if (!AR_SREV_9287_11_OR_LATER(ah))
849				REG_SET_BIT(ah, AR_PHY_ADC_CTL,
850					    AR_PHY_ADC_CTL_OFF_PWDADC);
851			REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
852				    AR_PHY_AGC_CONTROL_FLTR_CAL);
853		}
854	}
855
856	/* Do PA Calibration */
857	ar9002_hw_pa_cal(ah, true);
858	ath9k_hw_loadnf(ah, chan);
859	ath9k_hw_start_nfcal(ah, true);
860
861	if (ah->caldata)
862		set_bit(NFCAL_PENDING, &ah->caldata->cal_flags);
863
864	ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL;
865
866	/* Enable IQ, ADC Gain and ADC DC offset CALs */
867	if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) {
868		ah->supp_cals = IQ_MISMATCH_CAL;
869
870		if (AR_SREV_9160_10_OR_LATER(ah))
871			ah->supp_cals |= ADC_GAIN_CAL | ADC_DC_CAL;
872
873		if (AR_SREV_9287(ah))
874			ah->supp_cals &= ~ADC_GAIN_CAL;
875
876		if (ar9002_hw_is_cal_supported(ah, chan, ADC_GAIN_CAL)) {
877			INIT_CAL(&ah->adcgain_caldata);
878			INSERT_CAL(ah, &ah->adcgain_caldata);
879			ath_dbg(common, CALIBRATE,
880					"enabling ADC Gain Calibration\n");
881		}
882
883		if (ar9002_hw_is_cal_supported(ah, chan, ADC_DC_CAL)) {
884			INIT_CAL(&ah->adcdc_caldata);
885			INSERT_CAL(ah, &ah->adcdc_caldata);
886			ath_dbg(common, CALIBRATE,
887					"enabling ADC DC Calibration\n");
888		}
889
890		if (ar9002_hw_is_cal_supported(ah, chan, IQ_MISMATCH_CAL)) {
891			INIT_CAL(&ah->iq_caldata);
892			INSERT_CAL(ah, &ah->iq_caldata);
893			ath_dbg(common, CALIBRATE, "enabling IQ Calibration\n");
894		}
895
896		ah->cal_list_curr = ah->cal_list;
897
898		if (ah->cal_list_curr)
899			ath9k_hw_reset_calibration(ah, ah->cal_list_curr);
900	}
901
902	if (ah->caldata)
903		ah->caldata->CalValid = 0;
904
905	return true;
906}
907
908static const struct ath9k_percal_data iq_cal_multi_sample = {
909	IQ_MISMATCH_CAL,
910	MAX_CAL_SAMPLES,
911	PER_MIN_LOG_COUNT,
912	ar9002_hw_iqcal_collect,
913	ar9002_hw_iqcalibrate
914};
915static const struct ath9k_percal_data iq_cal_single_sample = {
916	IQ_MISMATCH_CAL,
917	MIN_CAL_SAMPLES,
918	PER_MAX_LOG_COUNT,
919	ar9002_hw_iqcal_collect,
920	ar9002_hw_iqcalibrate
921};
922static const struct ath9k_percal_data adc_gain_cal_multi_sample = {
923	ADC_GAIN_CAL,
924	MAX_CAL_SAMPLES,
925	PER_MIN_LOG_COUNT,
926	ar9002_hw_adc_gaincal_collect,
927	ar9002_hw_adc_gaincal_calibrate
928};
929static const struct ath9k_percal_data adc_gain_cal_single_sample = {
930	ADC_GAIN_CAL,
931	MIN_CAL_SAMPLES,
932	PER_MAX_LOG_COUNT,
933	ar9002_hw_adc_gaincal_collect,
934	ar9002_hw_adc_gaincal_calibrate
935};
936static const struct ath9k_percal_data adc_dc_cal_multi_sample = {
937	ADC_DC_CAL,
938	MAX_CAL_SAMPLES,
939	PER_MIN_LOG_COUNT,
940	ar9002_hw_adc_dccal_collect,
941	ar9002_hw_adc_dccal_calibrate
942};
943static const struct ath9k_percal_data adc_dc_cal_single_sample = {
944	ADC_DC_CAL,
945	MIN_CAL_SAMPLES,
946	PER_MAX_LOG_COUNT,
947	ar9002_hw_adc_dccal_collect,
948	ar9002_hw_adc_dccal_calibrate
949};
950
951static void ar9002_hw_init_cal_settings(struct ath_hw *ah)
952{
953	if (AR_SREV_9100(ah)) {
954		ah->iq_caldata.calData = &iq_cal_multi_sample;
955		ah->supp_cals = IQ_MISMATCH_CAL;
956		return;
957	}
958
959	if (AR_SREV_9160_10_OR_LATER(ah)) {
960		if (AR_SREV_9280_20_OR_LATER(ah)) {
961			ah->iq_caldata.calData = &iq_cal_single_sample;
962			ah->adcgain_caldata.calData =
963				&adc_gain_cal_single_sample;
964			ah->adcdc_caldata.calData =
965				&adc_dc_cal_single_sample;
966		} else {
967			ah->iq_caldata.calData = &iq_cal_multi_sample;
968			ah->adcgain_caldata.calData =
969				&adc_gain_cal_multi_sample;
970			ah->adcdc_caldata.calData =
971				&adc_dc_cal_multi_sample;
972		}
973		ah->supp_cals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL;
974
975		if (AR_SREV_9287(ah))
976			ah->supp_cals &= ~ADC_GAIN_CAL;
977	}
978}
979
980void ar9002_hw_attach_calib_ops(struct ath_hw *ah)
981{
982	struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
983	struct ath_hw_ops *ops = ath9k_hw_ops(ah);
984
985	priv_ops->init_cal_settings = ar9002_hw_init_cal_settings;
986	priv_ops->init_cal = ar9002_hw_init_cal;
987	priv_ops->setup_calibration = ar9002_hw_setup_calibration;
988
989	ops->calibrate = ar9002_hw_calibrate;
990}
991