Linux Audio

Check our new training course

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