Linux Audio

Check our new training course

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