162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci * Copyright (c) 2008-2011 Atheros Communications Inc.
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Permission to use, copy, modify, and/or distribute this software for any
562306a36Sopenharmony_ci * purpose with or without fee is hereby granted, provided that the above
662306a36Sopenharmony_ci * copyright notice and this permission notice appear in all copies.
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
962306a36Sopenharmony_ci * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1062306a36Sopenharmony_ci * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1162306a36Sopenharmony_ci * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1262306a36Sopenharmony_ci * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1362306a36Sopenharmony_ci * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1462306a36Sopenharmony_ci * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1562306a36Sopenharmony_ci */
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci#include "hw.h"
1862306a36Sopenharmony_ci#include "hw-ops.h"
1962306a36Sopenharmony_ci#include "ar9002_phy.h"
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci#define AR9285_CLCAL_REDO_THRESH    1
2262306a36Sopenharmony_ci/* AGC & I/Q calibrations time limit, ms */
2362306a36Sopenharmony_ci#define AR9002_CAL_MAX_TIME		30000
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_cienum ar9002_cal_types {
2662306a36Sopenharmony_ci	ADC_GAIN_CAL = BIT(0),
2762306a36Sopenharmony_ci	ADC_DC_CAL = BIT(1),
2862306a36Sopenharmony_ci	IQ_MISMATCH_CAL = BIT(2),
2962306a36Sopenharmony_ci};
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_cistatic bool ar9002_hw_is_cal_supported(struct ath_hw *ah,
3262306a36Sopenharmony_ci				struct ath9k_channel *chan,
3362306a36Sopenharmony_ci				enum ar9002_cal_types cal_type)
3462306a36Sopenharmony_ci{
3562306a36Sopenharmony_ci	bool supported = false;
3662306a36Sopenharmony_ci	switch (ah->supp_cals & cal_type) {
3762306a36Sopenharmony_ci	case IQ_MISMATCH_CAL:
3862306a36Sopenharmony_ci		supported = true;
3962306a36Sopenharmony_ci		break;
4062306a36Sopenharmony_ci	case ADC_GAIN_CAL:
4162306a36Sopenharmony_ci	case ADC_DC_CAL:
4262306a36Sopenharmony_ci		/* Run even/odd ADCs calibrations for HT40 channels only */
4362306a36Sopenharmony_ci		if (IS_CHAN_HT40(chan))
4462306a36Sopenharmony_ci			supported = true;
4562306a36Sopenharmony_ci		break;
4662306a36Sopenharmony_ci	}
4762306a36Sopenharmony_ci	return supported;
4862306a36Sopenharmony_ci}
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_cistatic void ar9002_hw_setup_calibration(struct ath_hw *ah,
5162306a36Sopenharmony_ci					struct ath9k_cal_list *currCal)
5262306a36Sopenharmony_ci{
5362306a36Sopenharmony_ci	struct ath_common *common = ath9k_hw_common(ah);
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci	REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(0),
5662306a36Sopenharmony_ci		      AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX,
5762306a36Sopenharmony_ci		      currCal->calData->calCountMax);
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci	switch (currCal->calData->calType) {
6062306a36Sopenharmony_ci	case IQ_MISMATCH_CAL:
6162306a36Sopenharmony_ci		REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ);
6262306a36Sopenharmony_ci		ath_dbg(common, CALIBRATE,
6362306a36Sopenharmony_ci			"starting IQ Mismatch Calibration\n");
6462306a36Sopenharmony_ci		break;
6562306a36Sopenharmony_ci	case ADC_GAIN_CAL:
6662306a36Sopenharmony_ci		REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_GAIN);
6762306a36Sopenharmony_ci		ath_dbg(common, CALIBRATE, "starting ADC Gain Calibration\n");
6862306a36Sopenharmony_ci		break;
6962306a36Sopenharmony_ci	case ADC_DC_CAL:
7062306a36Sopenharmony_ci		REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_PER);
7162306a36Sopenharmony_ci		ath_dbg(common, CALIBRATE, "starting ADC DC Calibration\n");
7262306a36Sopenharmony_ci		break;
7362306a36Sopenharmony_ci	}
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ci	REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0),
7662306a36Sopenharmony_ci		    AR_PHY_TIMING_CTRL4_DO_CAL);
7762306a36Sopenharmony_ci}
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_cistatic bool ar9002_hw_per_calibration(struct ath_hw *ah,
8062306a36Sopenharmony_ci				      struct ath9k_channel *ichan,
8162306a36Sopenharmony_ci				      u8 rxchainmask,
8262306a36Sopenharmony_ci				      struct ath9k_cal_list *currCal)
8362306a36Sopenharmony_ci{
8462306a36Sopenharmony_ci	struct ath9k_hw_cal_data *caldata = ah->caldata;
8562306a36Sopenharmony_ci	bool iscaldone = false;
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci	if (currCal->calState == CAL_RUNNING) {
8862306a36Sopenharmony_ci		if (!(REG_READ(ah, AR_PHY_TIMING_CTRL4(0)) &
8962306a36Sopenharmony_ci		      AR_PHY_TIMING_CTRL4_DO_CAL)) {
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci			currCal->calData->calCollect(ah);
9262306a36Sopenharmony_ci			ah->cal_samples++;
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci			if (ah->cal_samples >=
9562306a36Sopenharmony_ci			    currCal->calData->calNumSamples) {
9662306a36Sopenharmony_ci				int i, numChains = 0;
9762306a36Sopenharmony_ci				for (i = 0; i < AR5416_MAX_CHAINS; i++) {
9862306a36Sopenharmony_ci					if (rxchainmask & (1 << i))
9962306a36Sopenharmony_ci						numChains++;
10062306a36Sopenharmony_ci				}
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ci				currCal->calData->calPostProc(ah, numChains);
10362306a36Sopenharmony_ci				caldata->CalValid |= currCal->calData->calType;
10462306a36Sopenharmony_ci				currCal->calState = CAL_DONE;
10562306a36Sopenharmony_ci				iscaldone = true;
10662306a36Sopenharmony_ci			} else {
10762306a36Sopenharmony_ci				ar9002_hw_setup_calibration(ah, currCal);
10862306a36Sopenharmony_ci			}
10962306a36Sopenharmony_ci		} else if (time_after(jiffies, ah->cal_start_time +
11062306a36Sopenharmony_ci				      msecs_to_jiffies(AR9002_CAL_MAX_TIME))) {
11162306a36Sopenharmony_ci			REG_CLR_BIT(ah, AR_PHY_TIMING_CTRL4(0),
11262306a36Sopenharmony_ci				    AR_PHY_TIMING_CTRL4_DO_CAL);
11362306a36Sopenharmony_ci			ath_dbg(ath9k_hw_common(ah), CALIBRATE,
11462306a36Sopenharmony_ci				"calibration timeout\n");
11562306a36Sopenharmony_ci			currCal->calState = CAL_WAITING;	/* Try later */
11662306a36Sopenharmony_ci			iscaldone = true;
11762306a36Sopenharmony_ci		}
11862306a36Sopenharmony_ci	} else if (!(caldata->CalValid & currCal->calData->calType)) {
11962306a36Sopenharmony_ci		ath9k_hw_reset_calibration(ah, currCal);
12062306a36Sopenharmony_ci	}
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci	return iscaldone;
12362306a36Sopenharmony_ci}
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_cistatic void ar9002_hw_iqcal_collect(struct ath_hw *ah)
12662306a36Sopenharmony_ci{
12762306a36Sopenharmony_ci	int i;
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_ci	for (i = 0; i < AR5416_MAX_CHAINS; i++) {
13062306a36Sopenharmony_ci		ah->totalPowerMeasI[i] +=
13162306a36Sopenharmony_ci			REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
13262306a36Sopenharmony_ci		ah->totalPowerMeasQ[i] +=
13362306a36Sopenharmony_ci			REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
13462306a36Sopenharmony_ci		ah->totalIqCorrMeas[i] +=
13562306a36Sopenharmony_ci			(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
13662306a36Sopenharmony_ci		ath_dbg(ath9k_hw_common(ah), CALIBRATE,
13762306a36Sopenharmony_ci			"%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
13862306a36Sopenharmony_ci			ah->cal_samples, i, ah->totalPowerMeasI[i],
13962306a36Sopenharmony_ci			ah->totalPowerMeasQ[i],
14062306a36Sopenharmony_ci			ah->totalIqCorrMeas[i]);
14162306a36Sopenharmony_ci	}
14262306a36Sopenharmony_ci}
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_cistatic void ar9002_hw_adc_gaincal_collect(struct ath_hw *ah)
14562306a36Sopenharmony_ci{
14662306a36Sopenharmony_ci	int i;
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_ci	for (i = 0; i < AR5416_MAX_CHAINS; i++) {
14962306a36Sopenharmony_ci		ah->totalAdcIOddPhase[i] +=
15062306a36Sopenharmony_ci			REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
15162306a36Sopenharmony_ci		ah->totalAdcIEvenPhase[i] +=
15262306a36Sopenharmony_ci			REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
15362306a36Sopenharmony_ci		ah->totalAdcQOddPhase[i] +=
15462306a36Sopenharmony_ci			REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
15562306a36Sopenharmony_ci		ah->totalAdcQEvenPhase[i] +=
15662306a36Sopenharmony_ci			REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
15762306a36Sopenharmony_ci
15862306a36Sopenharmony_ci		ath_dbg(ath9k_hw_common(ah), CALIBRATE,
15962306a36Sopenharmony_ci			"%d: Chn %d oddi=0x%08x; eveni=0x%08x; oddq=0x%08x; evenq=0x%08x;\n",
16062306a36Sopenharmony_ci			ah->cal_samples, i,
16162306a36Sopenharmony_ci			ah->totalAdcIOddPhase[i],
16262306a36Sopenharmony_ci			ah->totalAdcIEvenPhase[i],
16362306a36Sopenharmony_ci			ah->totalAdcQOddPhase[i],
16462306a36Sopenharmony_ci			ah->totalAdcQEvenPhase[i]);
16562306a36Sopenharmony_ci	}
16662306a36Sopenharmony_ci}
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_cistatic void ar9002_hw_adc_dccal_collect(struct ath_hw *ah)
16962306a36Sopenharmony_ci{
17062306a36Sopenharmony_ci	int i;
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_ci	for (i = 0; i < AR5416_MAX_CHAINS; i++) {
17362306a36Sopenharmony_ci		ah->totalAdcDcOffsetIOddPhase[i] +=
17462306a36Sopenharmony_ci			(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
17562306a36Sopenharmony_ci		ah->totalAdcDcOffsetIEvenPhase[i] +=
17662306a36Sopenharmony_ci			(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
17762306a36Sopenharmony_ci		ah->totalAdcDcOffsetQOddPhase[i] +=
17862306a36Sopenharmony_ci			(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
17962306a36Sopenharmony_ci		ah->totalAdcDcOffsetQEvenPhase[i] +=
18062306a36Sopenharmony_ci			(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_ci		ath_dbg(ath9k_hw_common(ah), CALIBRATE,
18362306a36Sopenharmony_ci			"%d: Chn %d oddi=0x%08x; eveni=0x%08x; oddq=0x%08x; evenq=0x%08x;\n",
18462306a36Sopenharmony_ci			ah->cal_samples, i,
18562306a36Sopenharmony_ci			ah->totalAdcDcOffsetIOddPhase[i],
18662306a36Sopenharmony_ci			ah->totalAdcDcOffsetIEvenPhase[i],
18762306a36Sopenharmony_ci			ah->totalAdcDcOffsetQOddPhase[i],
18862306a36Sopenharmony_ci			ah->totalAdcDcOffsetQEvenPhase[i]);
18962306a36Sopenharmony_ci	}
19062306a36Sopenharmony_ci}
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_cistatic void ar9002_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
19362306a36Sopenharmony_ci{
19462306a36Sopenharmony_ci	struct ath_common *common = ath9k_hw_common(ah);
19562306a36Sopenharmony_ci	u32 powerMeasQ, powerMeasI, iqCorrMeas;
19662306a36Sopenharmony_ci	u32 qCoffDenom, iCoffDenom;
19762306a36Sopenharmony_ci	int32_t qCoff, iCoff;
19862306a36Sopenharmony_ci	int iqCorrNeg, i;
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ci	for (i = 0; i < numChains; i++) {
20162306a36Sopenharmony_ci		powerMeasI = ah->totalPowerMeasI[i];
20262306a36Sopenharmony_ci		powerMeasQ = ah->totalPowerMeasQ[i];
20362306a36Sopenharmony_ci		iqCorrMeas = ah->totalIqCorrMeas[i];
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_ci		ath_dbg(common, CALIBRATE,
20662306a36Sopenharmony_ci			"Starting IQ Cal and Correction for Chain %d\n",
20762306a36Sopenharmony_ci			i);
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci		ath_dbg(common, CALIBRATE,
21062306a36Sopenharmony_ci			"Original: Chn %d iq_corr_meas = 0x%08x\n",
21162306a36Sopenharmony_ci			i, ah->totalIqCorrMeas[i]);
21262306a36Sopenharmony_ci
21362306a36Sopenharmony_ci		iqCorrNeg = 0;
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_ci		if (iqCorrMeas > 0x80000000) {
21662306a36Sopenharmony_ci			iqCorrMeas = (0xffffffff - iqCorrMeas) + 1;
21762306a36Sopenharmony_ci			iqCorrNeg = 1;
21862306a36Sopenharmony_ci		}
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_ci		ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_i = 0x%08x\n",
22162306a36Sopenharmony_ci			i, powerMeasI);
22262306a36Sopenharmony_ci		ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_q = 0x%08x\n",
22362306a36Sopenharmony_ci			i, powerMeasQ);
22462306a36Sopenharmony_ci		ath_dbg(common, CALIBRATE, "iqCorrNeg is 0x%08x\n", iqCorrNeg);
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_ci		iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128;
22762306a36Sopenharmony_ci		qCoffDenom = powerMeasQ / 64;
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_ci		if ((powerMeasQ != 0) && (iCoffDenom != 0) &&
23062306a36Sopenharmony_ci		    (qCoffDenom != 0)) {
23162306a36Sopenharmony_ci			iCoff = iqCorrMeas / iCoffDenom;
23262306a36Sopenharmony_ci			qCoff = powerMeasI / qCoffDenom - 64;
23362306a36Sopenharmony_ci			ath_dbg(common, CALIBRATE, "Chn %d iCoff = 0x%08x\n",
23462306a36Sopenharmony_ci				i, iCoff);
23562306a36Sopenharmony_ci			ath_dbg(common, CALIBRATE, "Chn %d qCoff = 0x%08x\n",
23662306a36Sopenharmony_ci				i, qCoff);
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_ci			iCoff = iCoff & 0x3f;
23962306a36Sopenharmony_ci			ath_dbg(common, CALIBRATE,
24062306a36Sopenharmony_ci				"New: Chn %d iCoff = 0x%08x\n", i, iCoff);
24162306a36Sopenharmony_ci			if (iqCorrNeg == 0x0)
24262306a36Sopenharmony_ci				iCoff = 0x40 - iCoff;
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_ci			if (qCoff > 15)
24562306a36Sopenharmony_ci				qCoff = 15;
24662306a36Sopenharmony_ci			else if (qCoff <= -16)
24762306a36Sopenharmony_ci				qCoff = -16;
24862306a36Sopenharmony_ci
24962306a36Sopenharmony_ci			ath_dbg(common, CALIBRATE,
25062306a36Sopenharmony_ci				"Chn %d : iCoff = 0x%x  qCoff = 0x%x\n",
25162306a36Sopenharmony_ci				i, iCoff, qCoff);
25262306a36Sopenharmony_ci
25362306a36Sopenharmony_ci			REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i),
25462306a36Sopenharmony_ci				      AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF,
25562306a36Sopenharmony_ci				      iCoff);
25662306a36Sopenharmony_ci			REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i),
25762306a36Sopenharmony_ci				      AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF,
25862306a36Sopenharmony_ci				      qCoff);
25962306a36Sopenharmony_ci			ath_dbg(common, CALIBRATE,
26062306a36Sopenharmony_ci				"IQ Cal and Correction done for Chain %d\n",
26162306a36Sopenharmony_ci				i);
26262306a36Sopenharmony_ci		}
26362306a36Sopenharmony_ci	}
26462306a36Sopenharmony_ci
26562306a36Sopenharmony_ci	REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0),
26662306a36Sopenharmony_ci		    AR_PHY_TIMING_CTRL4_IQCORR_ENABLE);
26762306a36Sopenharmony_ci}
26862306a36Sopenharmony_ci
26962306a36Sopenharmony_cistatic void ar9002_hw_adc_gaincal_calibrate(struct ath_hw *ah, u8 numChains)
27062306a36Sopenharmony_ci{
27162306a36Sopenharmony_ci	struct ath_common *common = ath9k_hw_common(ah);
27262306a36Sopenharmony_ci	u32 iOddMeasOffset, iEvenMeasOffset, qOddMeasOffset, qEvenMeasOffset;
27362306a36Sopenharmony_ci	u32 qGainMismatch, iGainMismatch, val, i;
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_ci	for (i = 0; i < numChains; i++) {
27662306a36Sopenharmony_ci		iOddMeasOffset = ah->totalAdcIOddPhase[i];
27762306a36Sopenharmony_ci		iEvenMeasOffset = ah->totalAdcIEvenPhase[i];
27862306a36Sopenharmony_ci		qOddMeasOffset = ah->totalAdcQOddPhase[i];
27962306a36Sopenharmony_ci		qEvenMeasOffset = ah->totalAdcQEvenPhase[i];
28062306a36Sopenharmony_ci
28162306a36Sopenharmony_ci		ath_dbg(common, CALIBRATE,
28262306a36Sopenharmony_ci			"Starting ADC Gain Cal for Chain %d\n", i);
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_ci		ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_odd_i = 0x%08x\n",
28562306a36Sopenharmony_ci			i, iOddMeasOffset);
28662306a36Sopenharmony_ci		ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_even_i = 0x%08x\n",
28762306a36Sopenharmony_ci			i, iEvenMeasOffset);
28862306a36Sopenharmony_ci		ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_odd_q = 0x%08x\n",
28962306a36Sopenharmony_ci			i, qOddMeasOffset);
29062306a36Sopenharmony_ci		ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_even_q = 0x%08x\n",
29162306a36Sopenharmony_ci			i, qEvenMeasOffset);
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_ci		if (iOddMeasOffset != 0 && qEvenMeasOffset != 0) {
29462306a36Sopenharmony_ci			iGainMismatch =
29562306a36Sopenharmony_ci				((iEvenMeasOffset * 32) /
29662306a36Sopenharmony_ci				 iOddMeasOffset) & 0x3f;
29762306a36Sopenharmony_ci			qGainMismatch =
29862306a36Sopenharmony_ci				((qOddMeasOffset * 32) /
29962306a36Sopenharmony_ci				 qEvenMeasOffset) & 0x3f;
30062306a36Sopenharmony_ci
30162306a36Sopenharmony_ci			ath_dbg(common, CALIBRATE,
30262306a36Sopenharmony_ci				"Chn %d gain_mismatch_i = 0x%08x\n",
30362306a36Sopenharmony_ci				i, iGainMismatch);
30462306a36Sopenharmony_ci			ath_dbg(common, CALIBRATE,
30562306a36Sopenharmony_ci				"Chn %d gain_mismatch_q = 0x%08x\n",
30662306a36Sopenharmony_ci				i, qGainMismatch);
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_ci			val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
30962306a36Sopenharmony_ci			val &= 0xfffff000;
31062306a36Sopenharmony_ci			val |= (qGainMismatch) | (iGainMismatch << 6);
31162306a36Sopenharmony_ci			REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
31262306a36Sopenharmony_ci
31362306a36Sopenharmony_ci			ath_dbg(common, CALIBRATE,
31462306a36Sopenharmony_ci				"ADC Gain Cal done for Chain %d\n", i);
31562306a36Sopenharmony_ci		}
31662306a36Sopenharmony_ci	}
31762306a36Sopenharmony_ci
31862306a36Sopenharmony_ci	REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
31962306a36Sopenharmony_ci		  REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
32062306a36Sopenharmony_ci		  AR_PHY_NEW_ADC_GAIN_CORR_ENABLE);
32162306a36Sopenharmony_ci}
32262306a36Sopenharmony_ci
32362306a36Sopenharmony_cistatic void ar9002_hw_adc_dccal_calibrate(struct ath_hw *ah, u8 numChains)
32462306a36Sopenharmony_ci{
32562306a36Sopenharmony_ci	struct ath_common *common = ath9k_hw_common(ah);
32662306a36Sopenharmony_ci	u32 iOddMeasOffset, iEvenMeasOffset, val, i;
32762306a36Sopenharmony_ci	int32_t qOddMeasOffset, qEvenMeasOffset, qDcMismatch, iDcMismatch;
32862306a36Sopenharmony_ci	const struct ath9k_percal_data *calData =
32962306a36Sopenharmony_ci		ah->cal_list_curr->calData;
33062306a36Sopenharmony_ci	u32 numSamples =
33162306a36Sopenharmony_ci		(1 << (calData->calCountMax + 5)) * calData->calNumSamples;
33262306a36Sopenharmony_ci
33362306a36Sopenharmony_ci	for (i = 0; i < numChains; i++) {
33462306a36Sopenharmony_ci		iOddMeasOffset = ah->totalAdcDcOffsetIOddPhase[i];
33562306a36Sopenharmony_ci		iEvenMeasOffset = ah->totalAdcDcOffsetIEvenPhase[i];
33662306a36Sopenharmony_ci		qOddMeasOffset = ah->totalAdcDcOffsetQOddPhase[i];
33762306a36Sopenharmony_ci		qEvenMeasOffset = ah->totalAdcDcOffsetQEvenPhase[i];
33862306a36Sopenharmony_ci
33962306a36Sopenharmony_ci		ath_dbg(common, CALIBRATE,
34062306a36Sopenharmony_ci			"Starting ADC DC Offset Cal for Chain %d\n", i);
34162306a36Sopenharmony_ci
34262306a36Sopenharmony_ci		ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_odd_i = %d\n",
34362306a36Sopenharmony_ci			i, iOddMeasOffset);
34462306a36Sopenharmony_ci		ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_even_i = %d\n",
34562306a36Sopenharmony_ci			i, iEvenMeasOffset);
34662306a36Sopenharmony_ci		ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_odd_q = %d\n",
34762306a36Sopenharmony_ci			i, qOddMeasOffset);
34862306a36Sopenharmony_ci		ath_dbg(common, CALIBRATE, "Chn %d pwr_meas_even_q = %d\n",
34962306a36Sopenharmony_ci			i, qEvenMeasOffset);
35062306a36Sopenharmony_ci
35162306a36Sopenharmony_ci		iDcMismatch = (((iEvenMeasOffset - iOddMeasOffset) * 2) /
35262306a36Sopenharmony_ci			       numSamples) & 0x1ff;
35362306a36Sopenharmony_ci		qDcMismatch = (((qOddMeasOffset - qEvenMeasOffset) * 2) /
35462306a36Sopenharmony_ci			       numSamples) & 0x1ff;
35562306a36Sopenharmony_ci
35662306a36Sopenharmony_ci		ath_dbg(common, CALIBRATE,
35762306a36Sopenharmony_ci			"Chn %d dc_offset_mismatch_i = 0x%08x\n",
35862306a36Sopenharmony_ci			i, iDcMismatch);
35962306a36Sopenharmony_ci		ath_dbg(common, CALIBRATE,
36062306a36Sopenharmony_ci			"Chn %d dc_offset_mismatch_q = 0x%08x\n",
36162306a36Sopenharmony_ci			i, qDcMismatch);
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_ci		val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
36462306a36Sopenharmony_ci		val &= 0xc0000fff;
36562306a36Sopenharmony_ci		val |= (qDcMismatch << 12) | (iDcMismatch << 21);
36662306a36Sopenharmony_ci		REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
36762306a36Sopenharmony_ci
36862306a36Sopenharmony_ci		ath_dbg(common, CALIBRATE,
36962306a36Sopenharmony_ci			"ADC DC Offset Cal done for Chain %d\n", i);
37062306a36Sopenharmony_ci	}
37162306a36Sopenharmony_ci
37262306a36Sopenharmony_ci	REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
37362306a36Sopenharmony_ci		  REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
37462306a36Sopenharmony_ci		  AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE);
37562306a36Sopenharmony_ci}
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_cistatic void ar9287_hw_olc_temp_compensation(struct ath_hw *ah)
37862306a36Sopenharmony_ci{
37962306a36Sopenharmony_ci	u32 rddata;
38062306a36Sopenharmony_ci	int32_t delta, currPDADC, slope;
38162306a36Sopenharmony_ci
38262306a36Sopenharmony_ci	rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4);
38362306a36Sopenharmony_ci	currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT);
38462306a36Sopenharmony_ci
38562306a36Sopenharmony_ci	if (ah->initPDADC == 0 || currPDADC == 0) {
38662306a36Sopenharmony_ci		/*
38762306a36Sopenharmony_ci		 * Zero value indicates that no frames have been transmitted
38862306a36Sopenharmony_ci		 * yet, can't do temperature compensation until frames are
38962306a36Sopenharmony_ci		 * transmitted.
39062306a36Sopenharmony_ci		 */
39162306a36Sopenharmony_ci		return;
39262306a36Sopenharmony_ci	} else {
39362306a36Sopenharmony_ci		slope = ah->eep_ops->get_eeprom(ah, EEP_TEMPSENSE_SLOPE);
39462306a36Sopenharmony_ci
39562306a36Sopenharmony_ci		if (slope == 0) { /* to avoid divide by zero case */
39662306a36Sopenharmony_ci			delta = 0;
39762306a36Sopenharmony_ci		} else {
39862306a36Sopenharmony_ci			delta = ((currPDADC - ah->initPDADC)*4) / slope;
39962306a36Sopenharmony_ci		}
40062306a36Sopenharmony_ci		REG_RMW_FIELD(ah, AR_PHY_CH0_TX_PWRCTRL11,
40162306a36Sopenharmony_ci			      AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta);
40262306a36Sopenharmony_ci		REG_RMW_FIELD(ah, AR_PHY_CH1_TX_PWRCTRL11,
40362306a36Sopenharmony_ci			      AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta);
40462306a36Sopenharmony_ci	}
40562306a36Sopenharmony_ci}
40662306a36Sopenharmony_ci
40762306a36Sopenharmony_cistatic void ar9280_hw_olc_temp_compensation(struct ath_hw *ah)
40862306a36Sopenharmony_ci{
40962306a36Sopenharmony_ci	u32 rddata, i;
41062306a36Sopenharmony_ci	int delta, currPDADC, regval;
41162306a36Sopenharmony_ci
41262306a36Sopenharmony_ci	rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4);
41362306a36Sopenharmony_ci	currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT);
41462306a36Sopenharmony_ci
41562306a36Sopenharmony_ci	if (ah->initPDADC == 0 || currPDADC == 0)
41662306a36Sopenharmony_ci		return;
41762306a36Sopenharmony_ci
41862306a36Sopenharmony_ci	if (ah->eep_ops->get_eeprom(ah, EEP_DAC_HPWR_5G))
41962306a36Sopenharmony_ci		delta = (currPDADC - ah->initPDADC + 4) / 8;
42062306a36Sopenharmony_ci	else
42162306a36Sopenharmony_ci		delta = (currPDADC - ah->initPDADC + 5) / 10;
42262306a36Sopenharmony_ci
42362306a36Sopenharmony_ci	if (delta != ah->PDADCdelta) {
42462306a36Sopenharmony_ci		ah->PDADCdelta = delta;
42562306a36Sopenharmony_ci		for (i = 1; i < AR9280_TX_GAIN_TABLE_SIZE; i++) {
42662306a36Sopenharmony_ci			regval = ah->originalGain[i] - delta;
42762306a36Sopenharmony_ci			if (regval < 0)
42862306a36Sopenharmony_ci				regval = 0;
42962306a36Sopenharmony_ci
43062306a36Sopenharmony_ci			REG_RMW_FIELD(ah,
43162306a36Sopenharmony_ci				      AR_PHY_TX_GAIN_TBL1 + i * 4,
43262306a36Sopenharmony_ci				      AR_PHY_TX_GAIN, regval);
43362306a36Sopenharmony_ci		}
43462306a36Sopenharmony_ci	}
43562306a36Sopenharmony_ci}
43662306a36Sopenharmony_ci
43762306a36Sopenharmony_cistatic void ar9271_hw_pa_cal(struct ath_hw *ah, bool is_reset)
43862306a36Sopenharmony_ci{
43962306a36Sopenharmony_ci	u32 regVal;
44062306a36Sopenharmony_ci	unsigned int i;
44162306a36Sopenharmony_ci	u32 regList[][2] = {
44262306a36Sopenharmony_ci		{ AR9285_AN_TOP3, 0 },
44362306a36Sopenharmony_ci		{ AR9285_AN_RXTXBB1, 0 },
44462306a36Sopenharmony_ci		{ AR9285_AN_RF2G1, 0 },
44562306a36Sopenharmony_ci		{ AR9285_AN_RF2G2, 0 },
44662306a36Sopenharmony_ci		{ AR9285_AN_TOP2, 0 },
44762306a36Sopenharmony_ci		{ AR9285_AN_RF2G8, 0 },
44862306a36Sopenharmony_ci		{ AR9285_AN_RF2G7, 0 },
44962306a36Sopenharmony_ci		{ AR9285_AN_RF2G3, 0 },
45062306a36Sopenharmony_ci	};
45162306a36Sopenharmony_ci
45262306a36Sopenharmony_ci	REG_READ_ARRAY(ah, regList, ARRAY_SIZE(regList));
45362306a36Sopenharmony_ci
45462306a36Sopenharmony_ci	ENABLE_REG_RMW_BUFFER(ah);
45562306a36Sopenharmony_ci	/* 7834, b1=0 */
45662306a36Sopenharmony_ci	REG_CLR_BIT(ah, AR9285_AN_RF2G6, 1 << 0);
45762306a36Sopenharmony_ci	/* 9808, b27=1 */
45862306a36Sopenharmony_ci	REG_SET_BIT(ah, 0x9808, 1 << 27);
45962306a36Sopenharmony_ci	/* 786c,b23,1, pwddac=1 */
46062306a36Sopenharmony_ci	REG_SET_BIT(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC);
46162306a36Sopenharmony_ci	/* 7854, b5,1, pdrxtxbb=1 */
46262306a36Sopenharmony_ci	REG_SET_BIT(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1);
46362306a36Sopenharmony_ci	/* 7854, b7,1, pdv2i=1 */
46462306a36Sopenharmony_ci	REG_SET_BIT(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I);
46562306a36Sopenharmony_ci	/* 7854, b8,1, pddacinterface=1 */
46662306a36Sopenharmony_ci	REG_SET_BIT(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF);
46762306a36Sopenharmony_ci	/* 7824,b12,0, offcal=0 */
46862306a36Sopenharmony_ci	REG_CLR_BIT(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL);
46962306a36Sopenharmony_ci	/* 7838, b1,0, pwddb=0 */
47062306a36Sopenharmony_ci	REG_CLR_BIT(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB);
47162306a36Sopenharmony_ci	/* 7820,b11,0, enpacal=0 */
47262306a36Sopenharmony_ci	REG_CLR_BIT(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL);
47362306a36Sopenharmony_ci	/* 7820,b25,1, pdpadrv1=0 */
47462306a36Sopenharmony_ci	REG_CLR_BIT(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1);
47562306a36Sopenharmony_ci	/* 7820,b24,0, pdpadrv2=0 */
47662306a36Sopenharmony_ci	REG_CLR_BIT(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2);
47762306a36Sopenharmony_ci	/* 7820,b23,0, pdpaout=0 */
47862306a36Sopenharmony_ci	REG_CLR_BIT(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT);
47962306a36Sopenharmony_ci	/* 783c,b14-16,7, padrvgn2tab_0=7 */
48062306a36Sopenharmony_ci	REG_RMW_FIELD(ah, AR9285_AN_RF2G8, AR9285_AN_RF2G8_PADRVGN2TAB0, 7);
48162306a36Sopenharmony_ci	/*
48262306a36Sopenharmony_ci	 * 7838,b29-31,0, padrvgn1tab_0=0
48362306a36Sopenharmony_ci	 * does not matter since we turn it off
48462306a36Sopenharmony_ci	 */
48562306a36Sopenharmony_ci	REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PADRVGN2TAB0, 0);
48662306a36Sopenharmony_ci	/* 7828, b0-11, ccom=fff */
48762306a36Sopenharmony_ci	REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9271_AN_RF2G3_CCOMP, 0xfff);
48862306a36Sopenharmony_ci	REG_RMW_BUFFER_FLUSH(ah);
48962306a36Sopenharmony_ci
49062306a36Sopenharmony_ci	/* Set:
49162306a36Sopenharmony_ci	 * localmode=1,bmode=1,bmoderxtx=1,synthon=1,
49262306a36Sopenharmony_ci	 * txon=1,paon=1,oscon=1,synthon_force=1
49362306a36Sopenharmony_ci	 */
49462306a36Sopenharmony_ci	REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0);
49562306a36Sopenharmony_ci	udelay(30);
49662306a36Sopenharmony_ci	REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9271_AN_RF2G6_OFFS, 0);
49762306a36Sopenharmony_ci
49862306a36Sopenharmony_ci	/* find off_6_1; */
49962306a36Sopenharmony_ci	for (i = 6; i > 0; i--) {
50062306a36Sopenharmony_ci		regVal = REG_READ(ah, AR9285_AN_RF2G6);
50162306a36Sopenharmony_ci		regVal |= (1 << (20 + i));
50262306a36Sopenharmony_ci		REG_WRITE(ah, AR9285_AN_RF2G6, regVal);
50362306a36Sopenharmony_ci		udelay(1);
50462306a36Sopenharmony_ci		/* regVal = REG_READ(ah, 0x7834); */
50562306a36Sopenharmony_ci		regVal &= (~(0x1 << (20 + i)));
50662306a36Sopenharmony_ci		regVal |= (MS(REG_READ(ah, AR9285_AN_RF2G9),
50762306a36Sopenharmony_ci			      AR9285_AN_RXTXBB1_SPARE9)
50862306a36Sopenharmony_ci			    << (20 + i));
50962306a36Sopenharmony_ci		REG_WRITE(ah, AR9285_AN_RF2G6, regVal);
51062306a36Sopenharmony_ci	}
51162306a36Sopenharmony_ci
51262306a36Sopenharmony_ci	regVal = (regVal >> 20) & 0x7f;
51362306a36Sopenharmony_ci
51462306a36Sopenharmony_ci	/* Update PA cal info */
51562306a36Sopenharmony_ci	if ((!is_reset) && (ah->pacal_info.prev_offset == regVal)) {
51662306a36Sopenharmony_ci		if (ah->pacal_info.max_skipcount < MAX_PACAL_SKIPCOUNT)
51762306a36Sopenharmony_ci			ah->pacal_info.max_skipcount =
51862306a36Sopenharmony_ci				2 * ah->pacal_info.max_skipcount;
51962306a36Sopenharmony_ci		ah->pacal_info.skipcount = ah->pacal_info.max_skipcount;
52062306a36Sopenharmony_ci	} else {
52162306a36Sopenharmony_ci		ah->pacal_info.max_skipcount = 1;
52262306a36Sopenharmony_ci		ah->pacal_info.skipcount = 0;
52362306a36Sopenharmony_ci		ah->pacal_info.prev_offset = regVal;
52462306a36Sopenharmony_ci	}
52562306a36Sopenharmony_ci
52662306a36Sopenharmony_ci
52762306a36Sopenharmony_ci	ENABLE_REG_RMW_BUFFER(ah);
52862306a36Sopenharmony_ci	/* 7834, b1=1 */
52962306a36Sopenharmony_ci	REG_SET_BIT(ah, AR9285_AN_RF2G6, 1 << 0);
53062306a36Sopenharmony_ci	/* 9808, b27=0 */
53162306a36Sopenharmony_ci	REG_CLR_BIT(ah, 0x9808, 1 << 27);
53262306a36Sopenharmony_ci	REG_RMW_BUFFER_FLUSH(ah);
53362306a36Sopenharmony_ci
53462306a36Sopenharmony_ci	ENABLE_REGWRITE_BUFFER(ah);
53562306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(regList); i++)
53662306a36Sopenharmony_ci		REG_WRITE(ah, regList[i][0], regList[i][1]);
53762306a36Sopenharmony_ci
53862306a36Sopenharmony_ci	REGWRITE_BUFFER_FLUSH(ah);
53962306a36Sopenharmony_ci}
54062306a36Sopenharmony_ci
54162306a36Sopenharmony_cistatic inline void ar9285_hw_pa_cal(struct ath_hw *ah, bool is_reset)
54262306a36Sopenharmony_ci{
54362306a36Sopenharmony_ci	struct ath_common *common = ath9k_hw_common(ah);
54462306a36Sopenharmony_ci	u32 regVal;
54562306a36Sopenharmony_ci	int i, offset, offs_6_1, offs_0;
54662306a36Sopenharmony_ci	u32 ccomp_org, reg_field;
54762306a36Sopenharmony_ci	u32 regList[][2] = {
54862306a36Sopenharmony_ci		{ 0x786c, 0 },
54962306a36Sopenharmony_ci		{ 0x7854, 0 },
55062306a36Sopenharmony_ci		{ 0x7820, 0 },
55162306a36Sopenharmony_ci		{ 0x7824, 0 },
55262306a36Sopenharmony_ci		{ 0x7868, 0 },
55362306a36Sopenharmony_ci		{ 0x783c, 0 },
55462306a36Sopenharmony_ci		{ 0x7838, 0 },
55562306a36Sopenharmony_ci	};
55662306a36Sopenharmony_ci
55762306a36Sopenharmony_ci	ath_dbg(common, CALIBRATE, "Running PA Calibration\n");
55862306a36Sopenharmony_ci
55962306a36Sopenharmony_ci	/* PA CAL is not needed for high power solution */
56062306a36Sopenharmony_ci	if (ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE) ==
56162306a36Sopenharmony_ci	    AR5416_EEP_TXGAIN_HIGH_POWER)
56262306a36Sopenharmony_ci		return;
56362306a36Sopenharmony_ci
56462306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(regList); i++)
56562306a36Sopenharmony_ci		regList[i][1] = REG_READ(ah, regList[i][0]);
56662306a36Sopenharmony_ci
56762306a36Sopenharmony_ci	regVal = REG_READ(ah, 0x7834);
56862306a36Sopenharmony_ci	regVal &= (~(0x1));
56962306a36Sopenharmony_ci	REG_WRITE(ah, 0x7834, regVal);
57062306a36Sopenharmony_ci	regVal = REG_READ(ah, 0x9808);
57162306a36Sopenharmony_ci	regVal |= (0x1 << 27);
57262306a36Sopenharmony_ci	REG_WRITE(ah, 0x9808, regVal);
57362306a36Sopenharmony_ci
57462306a36Sopenharmony_ci	REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1);
57562306a36Sopenharmony_ci	REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1);
57662306a36Sopenharmony_ci	REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1);
57762306a36Sopenharmony_ci	REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1);
57862306a36Sopenharmony_ci	REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0);
57962306a36Sopenharmony_ci	REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0);
58062306a36Sopenharmony_ci	REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0);
58162306a36Sopenharmony_ci	REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 0);
58262306a36Sopenharmony_ci	REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2, 0);
58362306a36Sopenharmony_ci	REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0);
58462306a36Sopenharmony_ci	REG_RMW_FIELD(ah, AR9285_AN_RF2G8, AR9285_AN_RF2G8_PADRVGN2TAB0, 7);
58562306a36Sopenharmony_ci	REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PADRVGN2TAB0, 0);
58662306a36Sopenharmony_ci	ccomp_org = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_CCOMP);
58762306a36Sopenharmony_ci	REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, 0xf);
58862306a36Sopenharmony_ci
58962306a36Sopenharmony_ci	REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0);
59062306a36Sopenharmony_ci	udelay(30);
59162306a36Sopenharmony_ci	REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, 0);
59262306a36Sopenharmony_ci	REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 0);
59362306a36Sopenharmony_ci
59462306a36Sopenharmony_ci	for (i = 6; i > 0; i--) {
59562306a36Sopenharmony_ci		regVal = REG_READ(ah, 0x7834);
59662306a36Sopenharmony_ci		regVal |= (1 << (19 + i));
59762306a36Sopenharmony_ci		REG_WRITE(ah, 0x7834, regVal);
59862306a36Sopenharmony_ci		udelay(1);
59962306a36Sopenharmony_ci		regVal = REG_READ(ah, 0x7834);
60062306a36Sopenharmony_ci		regVal &= (~(0x1 << (19 + i)));
60162306a36Sopenharmony_ci		reg_field = MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9);
60262306a36Sopenharmony_ci		regVal |= (reg_field << (19 + i));
60362306a36Sopenharmony_ci		REG_WRITE(ah, 0x7834, regVal);
60462306a36Sopenharmony_ci	}
60562306a36Sopenharmony_ci
60662306a36Sopenharmony_ci	REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 1);
60762306a36Sopenharmony_ci	udelay(1);
60862306a36Sopenharmony_ci	reg_field = MS(REG_READ(ah, AR9285_AN_RF2G9), AR9285_AN_RXTXBB1_SPARE9);
60962306a36Sopenharmony_ci	REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, reg_field);
61062306a36Sopenharmony_ci	offs_6_1 = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_OFFS);
61162306a36Sopenharmony_ci	offs_0   = MS(REG_READ(ah, AR9285_AN_RF2G3), AR9285_AN_RF2G3_PDVCCOMP);
61262306a36Sopenharmony_ci
61362306a36Sopenharmony_ci	offset = (offs_6_1<<1) | offs_0;
61462306a36Sopenharmony_ci	offset = offset - 0;
61562306a36Sopenharmony_ci	offs_6_1 = offset>>1;
61662306a36Sopenharmony_ci	offs_0 = offset & 1;
61762306a36Sopenharmony_ci
61862306a36Sopenharmony_ci	if ((!is_reset) && (ah->pacal_info.prev_offset == offset)) {
61962306a36Sopenharmony_ci		if (ah->pacal_info.max_skipcount < MAX_PACAL_SKIPCOUNT)
62062306a36Sopenharmony_ci			ah->pacal_info.max_skipcount =
62162306a36Sopenharmony_ci				2 * ah->pacal_info.max_skipcount;
62262306a36Sopenharmony_ci		ah->pacal_info.skipcount = ah->pacal_info.max_skipcount;
62362306a36Sopenharmony_ci	} else {
62462306a36Sopenharmony_ci		ah->pacal_info.max_skipcount = 1;
62562306a36Sopenharmony_ci		ah->pacal_info.skipcount = 0;
62662306a36Sopenharmony_ci		ah->pacal_info.prev_offset = offset;
62762306a36Sopenharmony_ci	}
62862306a36Sopenharmony_ci
62962306a36Sopenharmony_ci	REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, offs_6_1);
63062306a36Sopenharmony_ci	REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, offs_0);
63162306a36Sopenharmony_ci
63262306a36Sopenharmony_ci	regVal = REG_READ(ah, 0x7834);
63362306a36Sopenharmony_ci	regVal |= 0x1;
63462306a36Sopenharmony_ci	REG_WRITE(ah, 0x7834, regVal);
63562306a36Sopenharmony_ci	regVal = REG_READ(ah, 0x9808);
63662306a36Sopenharmony_ci	regVal &= (~(0x1 << 27));
63762306a36Sopenharmony_ci	REG_WRITE(ah, 0x9808, regVal);
63862306a36Sopenharmony_ci
63962306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(regList); i++)
64062306a36Sopenharmony_ci		REG_WRITE(ah, regList[i][0], regList[i][1]);
64162306a36Sopenharmony_ci
64262306a36Sopenharmony_ci	REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, ccomp_org);
64362306a36Sopenharmony_ci}
64462306a36Sopenharmony_ci
64562306a36Sopenharmony_cistatic void ar9002_hw_pa_cal(struct ath_hw *ah, bool is_reset)
64662306a36Sopenharmony_ci{
64762306a36Sopenharmony_ci	if (AR_SREV_9271(ah)) {
64862306a36Sopenharmony_ci		if (is_reset || !ah->pacal_info.skipcount)
64962306a36Sopenharmony_ci			ar9271_hw_pa_cal(ah, is_reset);
65062306a36Sopenharmony_ci		else
65162306a36Sopenharmony_ci			ah->pacal_info.skipcount--;
65262306a36Sopenharmony_ci	} else if (AR_SREV_9285_12_OR_LATER(ah)) {
65362306a36Sopenharmony_ci		if (is_reset || !ah->pacal_info.skipcount)
65462306a36Sopenharmony_ci			ar9285_hw_pa_cal(ah, is_reset);
65562306a36Sopenharmony_ci		else
65662306a36Sopenharmony_ci			ah->pacal_info.skipcount--;
65762306a36Sopenharmony_ci	}
65862306a36Sopenharmony_ci}
65962306a36Sopenharmony_ci
66062306a36Sopenharmony_cistatic void ar9002_hw_olc_temp_compensation(struct ath_hw *ah)
66162306a36Sopenharmony_ci{
66262306a36Sopenharmony_ci	if (OLC_FOR_AR9287_10_LATER(ah))
66362306a36Sopenharmony_ci		ar9287_hw_olc_temp_compensation(ah);
66462306a36Sopenharmony_ci	else if (OLC_FOR_AR9280_20_LATER(ah))
66562306a36Sopenharmony_ci		ar9280_hw_olc_temp_compensation(ah);
66662306a36Sopenharmony_ci}
66762306a36Sopenharmony_ci
66862306a36Sopenharmony_cistatic int ar9002_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan,
66962306a36Sopenharmony_ci			       u8 rxchainmask, bool longcal)
67062306a36Sopenharmony_ci{
67162306a36Sopenharmony_ci	struct ath9k_cal_list *currCal = ah->cal_list_curr;
67262306a36Sopenharmony_ci	bool nfcal, nfcal_pending = false, percal_pending;
67362306a36Sopenharmony_ci	int ret;
67462306a36Sopenharmony_ci
67562306a36Sopenharmony_ci	nfcal = !!(REG_READ(ah, AR_PHY_AGC_CONTROL(ah)) & AR_PHY_AGC_CONTROL_NF);
67662306a36Sopenharmony_ci	if (ah->caldata) {
67762306a36Sopenharmony_ci		nfcal_pending = test_bit(NFCAL_PENDING, &ah->caldata->cal_flags);
67862306a36Sopenharmony_ci		if (longcal)		/* Remember to not miss */
67962306a36Sopenharmony_ci			set_bit(LONGCAL_PENDING, &ah->caldata->cal_flags);
68062306a36Sopenharmony_ci		else if (test_bit(LONGCAL_PENDING, &ah->caldata->cal_flags))
68162306a36Sopenharmony_ci			longcal = true;	/* Respin a previous one */
68262306a36Sopenharmony_ci	}
68362306a36Sopenharmony_ci
68462306a36Sopenharmony_ci	percal_pending = (currCal &&
68562306a36Sopenharmony_ci			  (currCal->calState == CAL_RUNNING ||
68662306a36Sopenharmony_ci			   currCal->calState == CAL_WAITING));
68762306a36Sopenharmony_ci
68862306a36Sopenharmony_ci	if (percal_pending && !nfcal) {
68962306a36Sopenharmony_ci		if (!ar9002_hw_per_calibration(ah, chan, rxchainmask, currCal))
69062306a36Sopenharmony_ci			return 0;
69162306a36Sopenharmony_ci
69262306a36Sopenharmony_ci		/* Looking for next waiting calibration if any */
69362306a36Sopenharmony_ci		for (currCal = currCal->calNext; currCal != ah->cal_list_curr;
69462306a36Sopenharmony_ci		     currCal = currCal->calNext) {
69562306a36Sopenharmony_ci			if (currCal->calState == CAL_WAITING)
69662306a36Sopenharmony_ci				break;
69762306a36Sopenharmony_ci		}
69862306a36Sopenharmony_ci		if (currCal->calState == CAL_WAITING) {
69962306a36Sopenharmony_ci			percal_pending = true;
70062306a36Sopenharmony_ci			ah->cal_list_curr = currCal;
70162306a36Sopenharmony_ci		} else {
70262306a36Sopenharmony_ci			percal_pending = false;
70362306a36Sopenharmony_ci			ah->cal_list_curr = ah->cal_list;
70462306a36Sopenharmony_ci		}
70562306a36Sopenharmony_ci	}
70662306a36Sopenharmony_ci
70762306a36Sopenharmony_ci	/* Do not start a next calibration if the longcal is in action */
70862306a36Sopenharmony_ci	if (percal_pending && !nfcal && !longcal) {
70962306a36Sopenharmony_ci		ath9k_hw_reset_calibration(ah, currCal);
71062306a36Sopenharmony_ci
71162306a36Sopenharmony_ci		return 0;
71262306a36Sopenharmony_ci	}
71362306a36Sopenharmony_ci
71462306a36Sopenharmony_ci	/* Do NF cal only at longer intervals */
71562306a36Sopenharmony_ci	if (longcal || nfcal_pending) {
71662306a36Sopenharmony_ci		/*
71762306a36Sopenharmony_ci		 * Get the value from the previous NF cal and update
71862306a36Sopenharmony_ci		 * history buffer.
71962306a36Sopenharmony_ci		 */
72062306a36Sopenharmony_ci		if (ath9k_hw_getnf(ah, chan)) {
72162306a36Sopenharmony_ci			/*
72262306a36Sopenharmony_ci			 * Load the NF from history buffer of the current
72362306a36Sopenharmony_ci			 * channel.
72462306a36Sopenharmony_ci			 * NF is slow time-variant, so it is OK to use a
72562306a36Sopenharmony_ci			 * historical value.
72662306a36Sopenharmony_ci			 */
72762306a36Sopenharmony_ci			ret = ath9k_hw_loadnf(ah, ah->curchan);
72862306a36Sopenharmony_ci			if (ret < 0)
72962306a36Sopenharmony_ci				return ret;
73062306a36Sopenharmony_ci		}
73162306a36Sopenharmony_ci
73262306a36Sopenharmony_ci		if (longcal) {
73362306a36Sopenharmony_ci			if (ah->caldata)
73462306a36Sopenharmony_ci				clear_bit(LONGCAL_PENDING,
73562306a36Sopenharmony_ci					  &ah->caldata->cal_flags);
73662306a36Sopenharmony_ci			ath9k_hw_start_nfcal(ah, false);
73762306a36Sopenharmony_ci			/* Do periodic PAOffset Cal */
73862306a36Sopenharmony_ci			ar9002_hw_pa_cal(ah, false);
73962306a36Sopenharmony_ci			ar9002_hw_olc_temp_compensation(ah);
74062306a36Sopenharmony_ci		}
74162306a36Sopenharmony_ci	}
74262306a36Sopenharmony_ci
74362306a36Sopenharmony_ci	return !percal_pending;
74462306a36Sopenharmony_ci}
74562306a36Sopenharmony_ci
74662306a36Sopenharmony_ci/* Carrier leakage Calibration fix */
74762306a36Sopenharmony_cistatic bool ar9285_hw_cl_cal(struct ath_hw *ah, struct ath9k_channel *chan)
74862306a36Sopenharmony_ci{
74962306a36Sopenharmony_ci	struct ath_common *common = ath9k_hw_common(ah);
75062306a36Sopenharmony_ci
75162306a36Sopenharmony_ci	REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
75262306a36Sopenharmony_ci	if (IS_CHAN_HT20(chan)) {
75362306a36Sopenharmony_ci		REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE);
75462306a36Sopenharmony_ci		REG_SET_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN);
75562306a36Sopenharmony_ci		REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL(ah),
75662306a36Sopenharmony_ci			    AR_PHY_AGC_CONTROL_FLTR_CAL);
75762306a36Sopenharmony_ci		REG_CLR_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE);
75862306a36Sopenharmony_ci		REG_SET_BIT(ah, AR_PHY_AGC_CONTROL(ah), AR_PHY_AGC_CONTROL_CAL);
75962306a36Sopenharmony_ci		if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL(ah),
76062306a36Sopenharmony_ci				  AR_PHY_AGC_CONTROL_CAL, 0, AH_WAIT_TIMEOUT)) {
76162306a36Sopenharmony_ci			ath_dbg(common, CALIBRATE,
76262306a36Sopenharmony_ci				"offset calibration failed to complete in %d ms; noisy environment?\n",
76362306a36Sopenharmony_ci				AH_WAIT_TIMEOUT / 1000);
76462306a36Sopenharmony_ci			return false;
76562306a36Sopenharmony_ci		}
76662306a36Sopenharmony_ci		REG_CLR_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN);
76762306a36Sopenharmony_ci		REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE);
76862306a36Sopenharmony_ci		REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
76962306a36Sopenharmony_ci	}
77062306a36Sopenharmony_ci	REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
77162306a36Sopenharmony_ci	REG_SET_BIT(ah, AR_PHY_AGC_CONTROL(ah), AR_PHY_AGC_CONTROL_FLTR_CAL);
77262306a36Sopenharmony_ci	REG_SET_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE);
77362306a36Sopenharmony_ci	REG_SET_BIT(ah, AR_PHY_AGC_CONTROL(ah), AR_PHY_AGC_CONTROL_CAL);
77462306a36Sopenharmony_ci	if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL(ah), AR_PHY_AGC_CONTROL_CAL,
77562306a36Sopenharmony_ci			  0, AH_WAIT_TIMEOUT)) {
77662306a36Sopenharmony_ci		ath_dbg(common, CALIBRATE,
77762306a36Sopenharmony_ci			"offset calibration failed to complete in %d ms; noisy environment?\n",
77862306a36Sopenharmony_ci			AH_WAIT_TIMEOUT / 1000);
77962306a36Sopenharmony_ci		return false;
78062306a36Sopenharmony_ci	}
78162306a36Sopenharmony_ci
78262306a36Sopenharmony_ci	REG_SET_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
78362306a36Sopenharmony_ci	REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
78462306a36Sopenharmony_ci	REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL(ah), AR_PHY_AGC_CONTROL_FLTR_CAL);
78562306a36Sopenharmony_ci
78662306a36Sopenharmony_ci	return true;
78762306a36Sopenharmony_ci}
78862306a36Sopenharmony_ci
78962306a36Sopenharmony_cistatic bool ar9285_hw_clc(struct ath_hw *ah, struct ath9k_channel *chan)
79062306a36Sopenharmony_ci{
79162306a36Sopenharmony_ci	int i;
79262306a36Sopenharmony_ci	u_int32_t txgain_max;
79362306a36Sopenharmony_ci	u_int32_t clc_gain, gain_mask = 0, clc_num = 0;
79462306a36Sopenharmony_ci	u_int32_t reg_clc_I0, reg_clc_Q0;
79562306a36Sopenharmony_ci	u_int32_t i0_num = 0;
79662306a36Sopenharmony_ci	u_int32_t q0_num = 0;
79762306a36Sopenharmony_ci	u_int32_t total_num = 0;
79862306a36Sopenharmony_ci	u_int32_t reg_rf2g5_org;
79962306a36Sopenharmony_ci	bool retv = true;
80062306a36Sopenharmony_ci
80162306a36Sopenharmony_ci	if (!(ar9285_hw_cl_cal(ah, chan)))
80262306a36Sopenharmony_ci		return false;
80362306a36Sopenharmony_ci
80462306a36Sopenharmony_ci	txgain_max = MS(REG_READ(ah, AR_PHY_TX_PWRCTRL7),
80562306a36Sopenharmony_ci			AR_PHY_TX_PWRCTRL_TX_GAIN_TAB_MAX);
80662306a36Sopenharmony_ci
80762306a36Sopenharmony_ci	for (i = 0; i < (txgain_max+1); i++) {
80862306a36Sopenharmony_ci		clc_gain = (REG_READ(ah, (AR_PHY_TX_GAIN_TBL1+(i<<2))) &
80962306a36Sopenharmony_ci			   AR_PHY_TX_GAIN_CLC) >> AR_PHY_TX_GAIN_CLC_S;
81062306a36Sopenharmony_ci		if (!(gain_mask & (1 << clc_gain))) {
81162306a36Sopenharmony_ci			gain_mask |= (1 << clc_gain);
81262306a36Sopenharmony_ci			clc_num++;
81362306a36Sopenharmony_ci		}
81462306a36Sopenharmony_ci	}
81562306a36Sopenharmony_ci
81662306a36Sopenharmony_ci	for (i = 0; i < clc_num; i++) {
81762306a36Sopenharmony_ci		reg_clc_I0 = (REG_READ(ah, (AR_PHY_CLC_TBL1 + (i << 2)))
81862306a36Sopenharmony_ci			      & AR_PHY_CLC_I0) >> AR_PHY_CLC_I0_S;
81962306a36Sopenharmony_ci		reg_clc_Q0 = (REG_READ(ah, (AR_PHY_CLC_TBL1 + (i << 2)))
82062306a36Sopenharmony_ci			      & AR_PHY_CLC_Q0) >> AR_PHY_CLC_Q0_S;
82162306a36Sopenharmony_ci		if (reg_clc_I0 == 0)
82262306a36Sopenharmony_ci			i0_num++;
82362306a36Sopenharmony_ci
82462306a36Sopenharmony_ci		if (reg_clc_Q0 == 0)
82562306a36Sopenharmony_ci			q0_num++;
82662306a36Sopenharmony_ci	}
82762306a36Sopenharmony_ci	total_num = i0_num + q0_num;
82862306a36Sopenharmony_ci	if (total_num > AR9285_CLCAL_REDO_THRESH) {
82962306a36Sopenharmony_ci		reg_rf2g5_org = REG_READ(ah, AR9285_RF2G5);
83062306a36Sopenharmony_ci		if (AR_SREV_9285E_20(ah)) {
83162306a36Sopenharmony_ci			REG_WRITE(ah, AR9285_RF2G5,
83262306a36Sopenharmony_ci				  (reg_rf2g5_org & AR9285_RF2G5_IC50TX) |
83362306a36Sopenharmony_ci				  AR9285_RF2G5_IC50TX_XE_SET);
83462306a36Sopenharmony_ci		} else {
83562306a36Sopenharmony_ci			REG_WRITE(ah, AR9285_RF2G5,
83662306a36Sopenharmony_ci				  (reg_rf2g5_org & AR9285_RF2G5_IC50TX) |
83762306a36Sopenharmony_ci				  AR9285_RF2G5_IC50TX_SET);
83862306a36Sopenharmony_ci		}
83962306a36Sopenharmony_ci		retv = ar9285_hw_cl_cal(ah, chan);
84062306a36Sopenharmony_ci		REG_WRITE(ah, AR9285_RF2G5, reg_rf2g5_org);
84162306a36Sopenharmony_ci	}
84262306a36Sopenharmony_ci	return retv;
84362306a36Sopenharmony_ci}
84462306a36Sopenharmony_ci
84562306a36Sopenharmony_cistatic bool ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan)
84662306a36Sopenharmony_ci{
84762306a36Sopenharmony_ci	struct ath_common *common = ath9k_hw_common(ah);
84862306a36Sopenharmony_ci
84962306a36Sopenharmony_ci	if (AR_SREV_9271(ah)) {
85062306a36Sopenharmony_ci		if (!ar9285_hw_cl_cal(ah, chan))
85162306a36Sopenharmony_ci			return false;
85262306a36Sopenharmony_ci	} else if (AR_SREV_9285(ah) && AR_SREV_9285_12_OR_LATER(ah)) {
85362306a36Sopenharmony_ci		if (!ar9285_hw_clc(ah, chan))
85462306a36Sopenharmony_ci			return false;
85562306a36Sopenharmony_ci	} else {
85662306a36Sopenharmony_ci		if (AR_SREV_9280_20_OR_LATER(ah)) {
85762306a36Sopenharmony_ci			if (!AR_SREV_9287_11_OR_LATER(ah))
85862306a36Sopenharmony_ci				REG_CLR_BIT(ah, AR_PHY_ADC_CTL,
85962306a36Sopenharmony_ci					    AR_PHY_ADC_CTL_OFF_PWDADC);
86062306a36Sopenharmony_ci			REG_SET_BIT(ah, AR_PHY_AGC_CONTROL(ah),
86162306a36Sopenharmony_ci				    AR_PHY_AGC_CONTROL_FLTR_CAL);
86262306a36Sopenharmony_ci		}
86362306a36Sopenharmony_ci
86462306a36Sopenharmony_ci		/* Calibrate the AGC */
86562306a36Sopenharmony_ci		REG_WRITE(ah, AR_PHY_AGC_CONTROL(ah),
86662306a36Sopenharmony_ci			  REG_READ(ah, AR_PHY_AGC_CONTROL(ah)) |
86762306a36Sopenharmony_ci			  AR_PHY_AGC_CONTROL_CAL);
86862306a36Sopenharmony_ci
86962306a36Sopenharmony_ci		/* Poll for offset calibration complete */
87062306a36Sopenharmony_ci		if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL(ah),
87162306a36Sopenharmony_ci				   AR_PHY_AGC_CONTROL_CAL,
87262306a36Sopenharmony_ci				   0, AH_WAIT_TIMEOUT)) {
87362306a36Sopenharmony_ci			ath_dbg(common, CALIBRATE,
87462306a36Sopenharmony_ci				"offset calibration failed to complete in %d ms; noisy environment?\n",
87562306a36Sopenharmony_ci				AH_WAIT_TIMEOUT / 1000);
87662306a36Sopenharmony_ci			return false;
87762306a36Sopenharmony_ci		}
87862306a36Sopenharmony_ci
87962306a36Sopenharmony_ci		if (AR_SREV_9280_20_OR_LATER(ah)) {
88062306a36Sopenharmony_ci			if (!AR_SREV_9287_11_OR_LATER(ah))
88162306a36Sopenharmony_ci				REG_SET_BIT(ah, AR_PHY_ADC_CTL,
88262306a36Sopenharmony_ci					    AR_PHY_ADC_CTL_OFF_PWDADC);
88362306a36Sopenharmony_ci			REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL(ah),
88462306a36Sopenharmony_ci				    AR_PHY_AGC_CONTROL_FLTR_CAL);
88562306a36Sopenharmony_ci		}
88662306a36Sopenharmony_ci	}
88762306a36Sopenharmony_ci
88862306a36Sopenharmony_ci	/* Do PA Calibration */
88962306a36Sopenharmony_ci	ar9002_hw_pa_cal(ah, true);
89062306a36Sopenharmony_ci	ath9k_hw_loadnf(ah, chan);
89162306a36Sopenharmony_ci	ath9k_hw_start_nfcal(ah, true);
89262306a36Sopenharmony_ci
89362306a36Sopenharmony_ci	ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL;
89462306a36Sopenharmony_ci
89562306a36Sopenharmony_ci	/* Enable IQ, ADC Gain and ADC DC offset CALs */
89662306a36Sopenharmony_ci	if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) {
89762306a36Sopenharmony_ci		ah->supp_cals = IQ_MISMATCH_CAL;
89862306a36Sopenharmony_ci
89962306a36Sopenharmony_ci		if (AR_SREV_9160_10_OR_LATER(ah))
90062306a36Sopenharmony_ci			ah->supp_cals |= ADC_GAIN_CAL | ADC_DC_CAL;
90162306a36Sopenharmony_ci
90262306a36Sopenharmony_ci		if (AR_SREV_9287(ah))
90362306a36Sopenharmony_ci			ah->supp_cals &= ~ADC_GAIN_CAL;
90462306a36Sopenharmony_ci
90562306a36Sopenharmony_ci		if (ar9002_hw_is_cal_supported(ah, chan, ADC_GAIN_CAL)) {
90662306a36Sopenharmony_ci			INIT_CAL(&ah->adcgain_caldata);
90762306a36Sopenharmony_ci			INSERT_CAL(ah, &ah->adcgain_caldata);
90862306a36Sopenharmony_ci			ath_dbg(common, CALIBRATE,
90962306a36Sopenharmony_ci					"enabling ADC Gain Calibration\n");
91062306a36Sopenharmony_ci		}
91162306a36Sopenharmony_ci
91262306a36Sopenharmony_ci		if (ar9002_hw_is_cal_supported(ah, chan, ADC_DC_CAL)) {
91362306a36Sopenharmony_ci			INIT_CAL(&ah->adcdc_caldata);
91462306a36Sopenharmony_ci			INSERT_CAL(ah, &ah->adcdc_caldata);
91562306a36Sopenharmony_ci			ath_dbg(common, CALIBRATE,
91662306a36Sopenharmony_ci					"enabling ADC DC Calibration\n");
91762306a36Sopenharmony_ci		}
91862306a36Sopenharmony_ci
91962306a36Sopenharmony_ci		if (ar9002_hw_is_cal_supported(ah, chan, IQ_MISMATCH_CAL)) {
92062306a36Sopenharmony_ci			INIT_CAL(&ah->iq_caldata);
92162306a36Sopenharmony_ci			INSERT_CAL(ah, &ah->iq_caldata);
92262306a36Sopenharmony_ci			ath_dbg(common, CALIBRATE, "enabling IQ Calibration\n");
92362306a36Sopenharmony_ci		}
92462306a36Sopenharmony_ci
92562306a36Sopenharmony_ci		ah->cal_list_curr = ah->cal_list;
92662306a36Sopenharmony_ci
92762306a36Sopenharmony_ci		if (ah->cal_list_curr)
92862306a36Sopenharmony_ci			ath9k_hw_reset_calibration(ah, ah->cal_list_curr);
92962306a36Sopenharmony_ci	}
93062306a36Sopenharmony_ci
93162306a36Sopenharmony_ci	if (ah->caldata)
93262306a36Sopenharmony_ci		ah->caldata->CalValid = 0;
93362306a36Sopenharmony_ci
93462306a36Sopenharmony_ci	return true;
93562306a36Sopenharmony_ci}
93662306a36Sopenharmony_ci
93762306a36Sopenharmony_cistatic const struct ath9k_percal_data iq_cal_multi_sample = {
93862306a36Sopenharmony_ci	IQ_MISMATCH_CAL,
93962306a36Sopenharmony_ci	MAX_CAL_SAMPLES,
94062306a36Sopenharmony_ci	PER_MIN_LOG_COUNT,
94162306a36Sopenharmony_ci	ar9002_hw_iqcal_collect,
94262306a36Sopenharmony_ci	ar9002_hw_iqcalibrate
94362306a36Sopenharmony_ci};
94462306a36Sopenharmony_cistatic const struct ath9k_percal_data iq_cal_single_sample = {
94562306a36Sopenharmony_ci	IQ_MISMATCH_CAL,
94662306a36Sopenharmony_ci	MIN_CAL_SAMPLES,
94762306a36Sopenharmony_ci	PER_MAX_LOG_COUNT,
94862306a36Sopenharmony_ci	ar9002_hw_iqcal_collect,
94962306a36Sopenharmony_ci	ar9002_hw_iqcalibrate
95062306a36Sopenharmony_ci};
95162306a36Sopenharmony_cistatic const struct ath9k_percal_data adc_gain_cal_multi_sample = {
95262306a36Sopenharmony_ci	ADC_GAIN_CAL,
95362306a36Sopenharmony_ci	MAX_CAL_SAMPLES,
95462306a36Sopenharmony_ci	PER_MIN_LOG_COUNT,
95562306a36Sopenharmony_ci	ar9002_hw_adc_gaincal_collect,
95662306a36Sopenharmony_ci	ar9002_hw_adc_gaincal_calibrate
95762306a36Sopenharmony_ci};
95862306a36Sopenharmony_cistatic const struct ath9k_percal_data adc_gain_cal_single_sample = {
95962306a36Sopenharmony_ci	ADC_GAIN_CAL,
96062306a36Sopenharmony_ci	MIN_CAL_SAMPLES,
96162306a36Sopenharmony_ci	PER_MAX_LOG_COUNT,
96262306a36Sopenharmony_ci	ar9002_hw_adc_gaincal_collect,
96362306a36Sopenharmony_ci	ar9002_hw_adc_gaincal_calibrate
96462306a36Sopenharmony_ci};
96562306a36Sopenharmony_cistatic const struct ath9k_percal_data adc_dc_cal_multi_sample = {
96662306a36Sopenharmony_ci	ADC_DC_CAL,
96762306a36Sopenharmony_ci	MAX_CAL_SAMPLES,
96862306a36Sopenharmony_ci	PER_MIN_LOG_COUNT,
96962306a36Sopenharmony_ci	ar9002_hw_adc_dccal_collect,
97062306a36Sopenharmony_ci	ar9002_hw_adc_dccal_calibrate
97162306a36Sopenharmony_ci};
97262306a36Sopenharmony_cistatic const struct ath9k_percal_data adc_dc_cal_single_sample = {
97362306a36Sopenharmony_ci	ADC_DC_CAL,
97462306a36Sopenharmony_ci	MIN_CAL_SAMPLES,
97562306a36Sopenharmony_ci	PER_MAX_LOG_COUNT,
97662306a36Sopenharmony_ci	ar9002_hw_adc_dccal_collect,
97762306a36Sopenharmony_ci	ar9002_hw_adc_dccal_calibrate
97862306a36Sopenharmony_ci};
97962306a36Sopenharmony_ci
98062306a36Sopenharmony_cistatic void ar9002_hw_init_cal_settings(struct ath_hw *ah)
98162306a36Sopenharmony_ci{
98262306a36Sopenharmony_ci	if (AR_SREV_9100(ah)) {
98362306a36Sopenharmony_ci		ah->iq_caldata.calData = &iq_cal_multi_sample;
98462306a36Sopenharmony_ci		ah->supp_cals = IQ_MISMATCH_CAL;
98562306a36Sopenharmony_ci		return;
98662306a36Sopenharmony_ci	}
98762306a36Sopenharmony_ci
98862306a36Sopenharmony_ci	if (AR_SREV_9160_10_OR_LATER(ah)) {
98962306a36Sopenharmony_ci		if (AR_SREV_9280_20_OR_LATER(ah)) {
99062306a36Sopenharmony_ci			ah->iq_caldata.calData = &iq_cal_single_sample;
99162306a36Sopenharmony_ci			ah->adcgain_caldata.calData =
99262306a36Sopenharmony_ci				&adc_gain_cal_single_sample;
99362306a36Sopenharmony_ci			ah->adcdc_caldata.calData =
99462306a36Sopenharmony_ci				&adc_dc_cal_single_sample;
99562306a36Sopenharmony_ci		} else {
99662306a36Sopenharmony_ci			ah->iq_caldata.calData = &iq_cal_multi_sample;
99762306a36Sopenharmony_ci			ah->adcgain_caldata.calData =
99862306a36Sopenharmony_ci				&adc_gain_cal_multi_sample;
99962306a36Sopenharmony_ci			ah->adcdc_caldata.calData =
100062306a36Sopenharmony_ci				&adc_dc_cal_multi_sample;
100162306a36Sopenharmony_ci		}
100262306a36Sopenharmony_ci		ah->supp_cals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL;
100362306a36Sopenharmony_ci
100462306a36Sopenharmony_ci		if (AR_SREV_9287(ah))
100562306a36Sopenharmony_ci			ah->supp_cals &= ~ADC_GAIN_CAL;
100662306a36Sopenharmony_ci	}
100762306a36Sopenharmony_ci}
100862306a36Sopenharmony_ci
100962306a36Sopenharmony_civoid ar9002_hw_attach_calib_ops(struct ath_hw *ah)
101062306a36Sopenharmony_ci{
101162306a36Sopenharmony_ci	struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
101262306a36Sopenharmony_ci	struct ath_hw_ops *ops = ath9k_hw_ops(ah);
101362306a36Sopenharmony_ci
101462306a36Sopenharmony_ci	priv_ops->init_cal_settings = ar9002_hw_init_cal_settings;
101562306a36Sopenharmony_ci	priv_ops->init_cal = ar9002_hw_init_cal;
101662306a36Sopenharmony_ci	priv_ops->setup_calibration = ar9002_hw_setup_calibration;
101762306a36Sopenharmony_ci
101862306a36Sopenharmony_ci	ops->calibrate = ar9002_hw_calibrate;
101962306a36Sopenharmony_ci}
1020