calib.c 34.4 KB
Newer Older
S
Sujith 已提交
1
/*
2
 * Copyright (c) 2008-2009 Atheros Communications Inc.
S
Sujith 已提交
3 4 5 6 7 8 9 10 11 12 13 14 15 16
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

17
#include "hw.h"
S
Sujith 已提交
18 19 20 21 22 23 24 25

/* We can tune this as we go by monitoring really low values */
#define ATH9K_NF_TOO_LOW	-60

/* AR5416 may return very high value (like -31 dBm), in those cases the nf
 * is incorrect and we should use the static NF value. Later we can try to
 * find out why they are reporting these values */

26
static bool ath9k_hw_nf_in_range(struct ath_hw *ah, s16 nf)
S
Sujith 已提交
27 28
{
	if (nf > ATH9K_NF_TOO_LOW) {
29 30 31 32 33
		ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
			  "noise floor value detected (%d) is "
			  "lower than what we think is a "
			  "reasonable value (%d)\n",
			  nf, ATH9K_NF_TOO_LOW);
S
Sujith 已提交
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
		return false;
	}
	return true;
}

static int16_t ath9k_hw_get_nf_hist_mid(int16_t *nfCalBuffer)
{
	int16_t nfval;
	int16_t sort[ATH9K_NF_CAL_HIST_MAX];
	int i, j;

	for (i = 0; i < ATH9K_NF_CAL_HIST_MAX; i++)
		sort[i] = nfCalBuffer[i];

	for (i = 0; i < ATH9K_NF_CAL_HIST_MAX - 1; i++) {
		for (j = 1; j < ATH9K_NF_CAL_HIST_MAX - i; j++) {
			if (sort[j] > sort[j - 1]) {
				nfval = sort[j];
				sort[j] = sort[j - 1];
				sort[j - 1] = nfval;
			}
		}
	}
	nfval = sort[(ATH9K_NF_CAL_HIST_MAX - 1) >> 1];

	return nfval;
}

static void ath9k_hw_update_nfcal_hist_buffer(struct ath9k_nfcal_hist *h,
					      int16_t *nfarray)
{
	int i;

	for (i = 0; i < NUM_NF_READINGS; i++) {
		h[i].nfCalBuffer[h[i].currIndex] = nfarray[i];

		if (++h[i].currIndex >= ATH9K_NF_CAL_HIST_MAX)
			h[i].currIndex = 0;

		if (h[i].invalidNFcount > 0) {
			if (nfarray[i] < AR_PHY_CCA_MIN_BAD_VALUE ||
			    nfarray[i] > AR_PHY_CCA_MAX_HIGH_VALUE) {
				h[i].invalidNFcount = ATH9K_NF_CAL_HIST_MAX;
			} else {
				h[i].invalidNFcount--;
				h[i].privNF = nfarray[i];
			}
		} else {
			h[i].privNF =
				ath9k_hw_get_nf_hist_mid(h[i].nfCalBuffer);
		}
	}
	return;
}

89
static void ath9k_hw_do_getnf(struct ath_hw *ah,
S
Sujith 已提交
90 91
			      int16_t nfarray[NUM_NF_READINGS])
{
92
	struct ath_common *common = ath9k_hw_common(ah);
S
Sujith 已提交
93 94 95 96 97 98 99 100 101
	int16_t nf;

	if (AR_SREV_9280_10_OR_LATER(ah))
		nf = MS(REG_READ(ah, AR_PHY_CCA), AR9280_PHY_MINCCA_PWR);
	else
		nf = MS(REG_READ(ah, AR_PHY_CCA), AR_PHY_MINCCA_PWR);

	if (nf & 0x100)
		nf = 0 - ((nf ^ 0x1ff) + 1);
102 103
	ath_print(common, ATH_DBG_CALIBRATE,
		  "NF calibrated [ctl] [chain 0] is %d\n", nf);
S
Sujith 已提交
104 105
	nfarray[0] = nf;

106 107 108 109 110 111 112
	if (!AR_SREV_9285(ah)) {
		if (AR_SREV_9280_10_OR_LATER(ah))
			nf = MS(REG_READ(ah, AR_PHY_CH1_CCA),
					AR9280_PHY_CH1_MINCCA_PWR);
		else
			nf = MS(REG_READ(ah, AR_PHY_CH1_CCA),
					AR_PHY_CH1_MINCCA_PWR);
S
Sujith 已提交
113 114 115

		if (nf & 0x100)
			nf = 0 - ((nf ^ 0x1ff) + 1);
116 117
		ath_print(common, ATH_DBG_CALIBRATE,
			  "NF calibrated [ctl] [chain 1] is %d\n", nf);
118 119
		nfarray[1] = nf;

120
		if (!AR_SREV_9280(ah) && !AR_SREV_9287(ah)) {
121 122 123 124
			nf = MS(REG_READ(ah, AR_PHY_CH2_CCA),
					AR_PHY_CH2_MINCCA_PWR);
			if (nf & 0x100)
				nf = 0 - ((nf ^ 0x1ff) + 1);
125 126
			ath_print(common, ATH_DBG_CALIBRATE,
				  "NF calibrated [ctl] [chain 2] is %d\n", nf);
127 128
			nfarray[2] = nf;
		}
S
Sujith 已提交
129 130 131 132 133 134 135 136 137 138 139
	}

	if (AR_SREV_9280_10_OR_LATER(ah))
		nf = MS(REG_READ(ah, AR_PHY_EXT_CCA),
			AR9280_PHY_EXT_MINCCA_PWR);
	else
		nf = MS(REG_READ(ah, AR_PHY_EXT_CCA),
			AR_PHY_EXT_MINCCA_PWR);

	if (nf & 0x100)
		nf = 0 - ((nf ^ 0x1ff) + 1);
140 141
	ath_print(common, ATH_DBG_CALIBRATE,
		  "NF calibrated [ext] [chain 0] is %d\n", nf);
S
Sujith 已提交
142 143
	nfarray[3] = nf;

144 145 146 147 148 149 150
	if (!AR_SREV_9285(ah)) {
		if (AR_SREV_9280_10_OR_LATER(ah))
			nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA),
					AR9280_PHY_CH1_EXT_MINCCA_PWR);
		else
			nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA),
					AR_PHY_CH1_EXT_MINCCA_PWR);
S
Sujith 已提交
151 152 153

		if (nf & 0x100)
			nf = 0 - ((nf ^ 0x1ff) + 1);
154 155
		ath_print(common, ATH_DBG_CALIBRATE,
			  "NF calibrated [ext] [chain 1] is %d\n", nf);
156 157
		nfarray[4] = nf;

158
		if (!AR_SREV_9280(ah) && !AR_SREV_9287(ah)) {
159 160 161 162
			nf = MS(REG_READ(ah, AR_PHY_CH2_EXT_CCA),
					AR_PHY_CH2_EXT_MINCCA_PWR);
			if (nf & 0x100)
				nf = 0 - ((nf ^ 0x1ff) + 1);
163 164
			ath_print(common, ATH_DBG_CALIBRATE,
				  "NF calibrated [ext] [chain 2] is %d\n", nf);
165 166
			nfarray[5] = nf;
		}
S
Sujith 已提交
167 168 169
	}
}

170
static bool getNoiseFloorThresh(struct ath_hw *ah,
171
				enum ieee80211_band band,
S
Sujith 已提交
172 173
				int16_t *nft)
{
174 175
	switch (band) {
	case IEEE80211_BAND_5GHZ:
S
Sujith 已提交
176
		*nft = (int8_t)ah->eep_ops->get_eeprom(ah, EEP_NFTHRESH_5);
S
Sujith 已提交
177
		break;
178
	case IEEE80211_BAND_2GHZ:
S
Sujith 已提交
179
		*nft = (int8_t)ah->eep_ops->get_eeprom(ah, EEP_NFTHRESH_2);
S
Sujith 已提交
180 181
		break;
	default:
182
		BUG_ON(1);
S
Sujith 已提交
183 184 185 186 187 188
		return false;
	}

	return true;
}

189
static void ath9k_hw_setup_calibration(struct ath_hw *ah,
190
				       struct ath9k_cal_list *currCal)
S
Sujith 已提交
191
{
192 193
	struct ath_common *common = ath9k_hw_common(ah);

S
Sujith 已提交
194 195 196 197 198 199 200
	REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(0),
		      AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX,
		      currCal->calData->calCountMax);

	switch (currCal->calData->calType) {
	case IQ_MISMATCH_CAL:
		REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ);
201 202
		ath_print(common, ATH_DBG_CALIBRATE,
			  "starting IQ Mismatch Calibration\n");
S
Sujith 已提交
203 204 205
		break;
	case ADC_GAIN_CAL:
		REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_GAIN);
206 207
		ath_print(common, ATH_DBG_CALIBRATE,
			  "starting ADC Gain Calibration\n");
S
Sujith 已提交
208 209 210
		break;
	case ADC_DC_CAL:
		REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_PER);
211 212
		ath_print(common, ATH_DBG_CALIBRATE,
			  "starting ADC DC Calibration\n");
S
Sujith 已提交
213 214 215
		break;
	case ADC_DC_INIT_CAL:
		REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_INIT);
216 217
		ath_print(common, ATH_DBG_CALIBRATE,
			  "starting Init ADC DC Calibration\n");
S
Sujith 已提交
218 219 220 221 222 223 224
		break;
	}

	REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0),
		    AR_PHY_TIMING_CTRL4_DO_CAL);
}

225
static void ath9k_hw_reset_calibration(struct ath_hw *ah,
226
				       struct ath9k_cal_list *currCal)
S
Sujith 已提交
227 228 229 230 231 232 233 234
{
	int i;

	ath9k_hw_setup_calibration(ah, currCal);

	currCal->calState = CAL_RUNNING;

	for (i = 0; i < AR5416_MAX_CHAINS; i++) {
235 236 237 238
		ah->meas0.sign[i] = 0;
		ah->meas1.sign[i] = 0;
		ah->meas2.sign[i] = 0;
		ah->meas3.sign[i] = 0;
S
Sujith 已提交
239 240
	}

241
	ah->cal_samples = 0;
S
Sujith 已提交
242 243
}

S
Sujith 已提交
244
static bool ath9k_hw_per_calibration(struct ath_hw *ah,
S
Sujith 已提交
245 246
				     struct ath9k_channel *ichan,
				     u8 rxchainmask,
247
				     struct ath9k_cal_list *currCal)
S
Sujith 已提交
248
{
S
Sujith 已提交
249
	bool iscaldone = false;
S
Sujith 已提交
250 251 252 253 254 255

	if (currCal->calState == CAL_RUNNING) {
		if (!(REG_READ(ah, AR_PHY_TIMING_CTRL4(0)) &
		      AR_PHY_TIMING_CTRL4_DO_CAL)) {

			currCal->calData->calCollect(ah);
256
			ah->cal_samples++;
S
Sujith 已提交
257

258
			if (ah->cal_samples >= currCal->calData->calNumSamples) {
S
Sujith 已提交
259 260 261 262 263 264 265 266 267
				int i, numChains = 0;
				for (i = 0; i < AR5416_MAX_CHAINS; i++) {
					if (rxchainmask & (1 << i))
						numChains++;
				}

				currCal->calData->calPostProc(ah, numChains);
				ichan->CalValid |= currCal->calData->calType;
				currCal->calState = CAL_DONE;
S
Sujith 已提交
268
				iscaldone = true;
S
Sujith 已提交
269 270 271 272 273 274 275
			} else {
				ath9k_hw_setup_calibration(ah, currCal);
			}
		}
	} else if (!(ichan->CalValid & currCal->calData->calType)) {
		ath9k_hw_reset_calibration(ah, currCal);
	}
S
Sujith 已提交
276 277

	return iscaldone;
S
Sujith 已提交
278 279
}

280
/* Assumes you are talking about the currently configured channel */
281
static bool ath9k_hw_iscal_supported(struct ath_hw *ah,
282
				     enum ath9k_cal_types calType)
S
Sujith 已提交
283
{
284
	struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
S
Sujith 已提交
285

286
	switch (calType & ah->supp_cals) {
287 288
	case IQ_MISMATCH_CAL: /* Both 2 GHz and 5 GHz support OFDM */
		return true;
S
Sujith 已提交
289 290
	case ADC_GAIN_CAL:
	case ADC_DC_CAL:
291 292
		if (!(conf->channel->band == IEEE80211_BAND_2GHZ &&
		      conf_is_ht20(conf)))
293
			return true;
S
Sujith 已提交
294 295
		break;
	}
296
	return false;
S
Sujith 已提交
297 298
}

299
static void ath9k_hw_iqcal_collect(struct ath_hw *ah)
S
Sujith 已提交
300 301 302 303
{
	int i;

	for (i = 0; i < AR5416_MAX_CHAINS; i++) {
304
		ah->totalPowerMeasI[i] +=
S
Sujith 已提交
305
			REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
306
		ah->totalPowerMeasQ[i] +=
S
Sujith 已提交
307
			REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
308
		ah->totalIqCorrMeas[i] +=
S
Sujith 已提交
309
			(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
310 311 312 313 314
		ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
			  "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
			  ah->cal_samples, i, ah->totalPowerMeasI[i],
			  ah->totalPowerMeasQ[i],
			  ah->totalIqCorrMeas[i]);
S
Sujith 已提交
315 316 317
	}
}

318
static void ath9k_hw_adc_gaincal_collect(struct ath_hw *ah)
S
Sujith 已提交
319 320 321 322
{
	int i;

	for (i = 0; i < AR5416_MAX_CHAINS; i++) {
323
		ah->totalAdcIOddPhase[i] +=
S
Sujith 已提交
324
			REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
325
		ah->totalAdcIEvenPhase[i] +=
S
Sujith 已提交
326
			REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
327
		ah->totalAdcQOddPhase[i] +=
S
Sujith 已提交
328
			REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
329
		ah->totalAdcQEvenPhase[i] +=
S
Sujith 已提交
330 331
			REG_READ(ah, AR_PHY_CAL_MEAS_3(i));

332 333 334 335 336 337 338 339
		ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
			  "%d: Chn %d oddi=0x%08x; eveni=0x%08x; "
			  "oddq=0x%08x; evenq=0x%08x;\n",
			  ah->cal_samples, i,
			  ah->totalAdcIOddPhase[i],
			  ah->totalAdcIEvenPhase[i],
			  ah->totalAdcQOddPhase[i],
			  ah->totalAdcQEvenPhase[i]);
S
Sujith 已提交
340 341 342
	}
}

343
static void ath9k_hw_adc_dccal_collect(struct ath_hw *ah)
S
Sujith 已提交
344 345 346 347
{
	int i;

	for (i = 0; i < AR5416_MAX_CHAINS; i++) {
348
		ah->totalAdcDcOffsetIOddPhase[i] +=
S
Sujith 已提交
349
			(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
350
		ah->totalAdcDcOffsetIEvenPhase[i] +=
S
Sujith 已提交
351
			(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
352
		ah->totalAdcDcOffsetQOddPhase[i] +=
S
Sujith 已提交
353
			(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
354
		ah->totalAdcDcOffsetQEvenPhase[i] +=
S
Sujith 已提交
355 356
			(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_3(i));

357 358 359 360 361 362 363 364
		ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
			  "%d: Chn %d oddi=0x%08x; eveni=0x%08x; "
			  "oddq=0x%08x; evenq=0x%08x;\n",
			  ah->cal_samples, i,
			  ah->totalAdcDcOffsetIOddPhase[i],
			  ah->totalAdcDcOffsetIEvenPhase[i],
			  ah->totalAdcDcOffsetQOddPhase[i],
			  ah->totalAdcDcOffsetQEvenPhase[i]);
S
Sujith 已提交
365 366 367
	}
}

368
static void ath9k_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
S
Sujith 已提交
369
{
370
	struct ath_common *common = ath9k_hw_common(ah);
S
Sujith 已提交
371 372 373 374 375 376
	u32 powerMeasQ, powerMeasI, iqCorrMeas;
	u32 qCoffDenom, iCoffDenom;
	int32_t qCoff, iCoff;
	int iqCorrNeg, i;

	for (i = 0; i < numChains; i++) {
377 378 379
		powerMeasI = ah->totalPowerMeasI[i];
		powerMeasQ = ah->totalPowerMeasQ[i];
		iqCorrMeas = ah->totalIqCorrMeas[i];
S
Sujith 已提交
380

381 382 383
		ath_print(common, ATH_DBG_CALIBRATE,
			  "Starting IQ Cal and Correction for Chain %d\n",
			  i);
S
Sujith 已提交
384

385 386 387
		ath_print(common, ATH_DBG_CALIBRATE,
			  "Orignal: Chn %diq_corr_meas = 0x%08x\n",
			  i, ah->totalIqCorrMeas[i]);
S
Sujith 已提交
388 389 390 391 392 393 394 395

		iqCorrNeg = 0;

		if (iqCorrMeas > 0x80000000) {
			iqCorrMeas = (0xffffffff - iqCorrMeas) + 1;
			iqCorrNeg = 1;
		}

396 397 398 399 400 401
		ath_print(common, ATH_DBG_CALIBRATE,
			  "Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI);
		ath_print(common, ATH_DBG_CALIBRATE,
			  "Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ);
		ath_print(common, ATH_DBG_CALIBRATE, "iqCorrNeg is 0x%08x\n",
			  iqCorrNeg);
S
Sujith 已提交
402 403 404 405

		iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128;
		qCoffDenom = powerMeasQ / 64;

V
Vivek Natarajan 已提交
406 407
		if ((powerMeasQ != 0) && (iCoffDenom != 0) &&
		    (qCoffDenom != 0)) {
S
Sujith 已提交
408 409
			iCoff = iqCorrMeas / iCoffDenom;
			qCoff = powerMeasI / qCoffDenom - 64;
410 411 412 413
			ath_print(common, ATH_DBG_CALIBRATE,
				  "Chn %d iCoff = 0x%08x\n", i, iCoff);
			ath_print(common, ATH_DBG_CALIBRATE,
				  "Chn %d qCoff = 0x%08x\n", i, qCoff);
S
Sujith 已提交
414 415

			iCoff = iCoff & 0x3f;
416 417
			ath_print(common, ATH_DBG_CALIBRATE,
				  "New: Chn %d iCoff = 0x%08x\n", i, iCoff);
S
Sujith 已提交
418 419 420 421 422 423 424 425
			if (iqCorrNeg == 0x0)
				iCoff = 0x40 - iCoff;

			if (qCoff > 15)
				qCoff = 15;
			else if (qCoff <= -16)
				qCoff = 16;

426 427 428
			ath_print(common, ATH_DBG_CALIBRATE,
				  "Chn %d : iCoff = 0x%x  qCoff = 0x%x\n",
				  i, iCoff, qCoff);
S
Sujith 已提交
429 430 431 432 433 434 435

			REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i),
				      AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF,
				      iCoff);
			REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i),
				      AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF,
				      qCoff);
436 437 438
			ath_print(common, ATH_DBG_CALIBRATE,
				  "IQ Cal and Correction done for Chain %d\n",
				  i);
S
Sujith 已提交
439 440 441 442 443 444 445
		}
	}

	REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0),
		    AR_PHY_TIMING_CTRL4_IQCORR_ENABLE);
}

446
static void ath9k_hw_adc_gaincal_calibrate(struct ath_hw *ah, u8 numChains)
S
Sujith 已提交
447
{
448
	struct ath_common *common = ath9k_hw_common(ah);
S
Sujith 已提交
449 450 451 452
	u32 iOddMeasOffset, iEvenMeasOffset, qOddMeasOffset, qEvenMeasOffset;
	u32 qGainMismatch, iGainMismatch, val, i;

	for (i = 0; i < numChains; i++) {
453 454 455 456
		iOddMeasOffset = ah->totalAdcIOddPhase[i];
		iEvenMeasOffset = ah->totalAdcIEvenPhase[i];
		qOddMeasOffset = ah->totalAdcQOddPhase[i];
		qEvenMeasOffset = ah->totalAdcQEvenPhase[i];
S
Sujith 已提交
457

458 459 460 461 462 463 464 465 466 467 468 469 470 471 472
		ath_print(common, ATH_DBG_CALIBRATE,
			  "Starting ADC Gain Cal for Chain %d\n", i);

		ath_print(common, ATH_DBG_CALIBRATE,
			  "Chn %d pwr_meas_odd_i = 0x%08x\n", i,
			  iOddMeasOffset);
		ath_print(common, ATH_DBG_CALIBRATE,
			  "Chn %d pwr_meas_even_i = 0x%08x\n", i,
			  iEvenMeasOffset);
		ath_print(common, ATH_DBG_CALIBRATE,
			  "Chn %d pwr_meas_odd_q = 0x%08x\n", i,
			  qOddMeasOffset);
		ath_print(common, ATH_DBG_CALIBRATE,
			  "Chn %d pwr_meas_even_q = 0x%08x\n", i,
			  qEvenMeasOffset);
S
Sujith 已提交
473 474 475 476 477 478 479 480 481

		if (iOddMeasOffset != 0 && qEvenMeasOffset != 0) {
			iGainMismatch =
				((iEvenMeasOffset * 32) /
				 iOddMeasOffset) & 0x3f;
			qGainMismatch =
				((qOddMeasOffset * 32) /
				 qEvenMeasOffset) & 0x3f;

482 483 484 485 486 487
			ath_print(common, ATH_DBG_CALIBRATE,
				  "Chn %d gain_mismatch_i = 0x%08x\n", i,
				  iGainMismatch);
			ath_print(common, ATH_DBG_CALIBRATE,
				  "Chn %d gain_mismatch_q = 0x%08x\n", i,
				  qGainMismatch);
S
Sujith 已提交
488 489 490 491 492 493

			val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
			val &= 0xfffff000;
			val |= (qGainMismatch) | (iGainMismatch << 6);
			REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);

494 495
			ath_print(common, ATH_DBG_CALIBRATE,
				  "ADC Gain Cal done for Chain %d\n", i);
S
Sujith 已提交
496 497 498 499 500 501 502 503
		}
	}

	REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
		  REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
		  AR_PHY_NEW_ADC_GAIN_CORR_ENABLE);
}

504
static void ath9k_hw_adc_dccal_calibrate(struct ath_hw *ah, u8 numChains)
S
Sujith 已提交
505
{
506
	struct ath_common *common = ath9k_hw_common(ah);
S
Sujith 已提交
507 508
	u32 iOddMeasOffset, iEvenMeasOffset, val, i;
	int32_t qOddMeasOffset, qEvenMeasOffset, qDcMismatch, iDcMismatch;
509
	const struct ath9k_percal_data *calData =
510
		ah->cal_list_curr->calData;
S
Sujith 已提交
511 512 513 514
	u32 numSamples =
		(1 << (calData->calCountMax + 5)) * calData->calNumSamples;

	for (i = 0; i < numChains; i++) {
515 516 517 518
		iOddMeasOffset = ah->totalAdcDcOffsetIOddPhase[i];
		iEvenMeasOffset = ah->totalAdcDcOffsetIEvenPhase[i];
		qOddMeasOffset = ah->totalAdcDcOffsetQOddPhase[i];
		qEvenMeasOffset = ah->totalAdcDcOffsetQEvenPhase[i];
S
Sujith 已提交
519

520 521 522 523 524 525 526 527 528 529 530 531 532 533 534
		ath_print(common, ATH_DBG_CALIBRATE,
			   "Starting ADC DC Offset Cal for Chain %d\n", i);

		ath_print(common, ATH_DBG_CALIBRATE,
			  "Chn %d pwr_meas_odd_i = %d\n", i,
			  iOddMeasOffset);
		ath_print(common, ATH_DBG_CALIBRATE,
			  "Chn %d pwr_meas_even_i = %d\n", i,
			  iEvenMeasOffset);
		ath_print(common, ATH_DBG_CALIBRATE,
			  "Chn %d pwr_meas_odd_q = %d\n", i,
			  qOddMeasOffset);
		ath_print(common, ATH_DBG_CALIBRATE,
			  "Chn %d pwr_meas_even_q = %d\n", i,
			  qEvenMeasOffset);
S
Sujith 已提交
535 536 537 538 539 540

		iDcMismatch = (((iEvenMeasOffset - iOddMeasOffset) * 2) /
			       numSamples) & 0x1ff;
		qDcMismatch = (((qOddMeasOffset - qEvenMeasOffset) * 2) /
			       numSamples) & 0x1ff;

541 542 543 544 545 546
		ath_print(common, ATH_DBG_CALIBRATE,
			  "Chn %d dc_offset_mismatch_i = 0x%08x\n", i,
			  iDcMismatch);
		ath_print(common, ATH_DBG_CALIBRATE,
			  "Chn %d dc_offset_mismatch_q = 0x%08x\n", i,
			  qDcMismatch);
S
Sujith 已提交
547 548 549 550 551 552

		val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
		val &= 0xc0000fff;
		val |= (qDcMismatch << 12) | (iDcMismatch << 21);
		REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);

553 554
		ath_print(common, ATH_DBG_CALIBRATE,
			  "ADC DC Offset Cal done for Chain %d\n", i);
S
Sujith 已提交
555 556 557 558 559 560 561
	}

	REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
		  REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
		  AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE);
}

562
/* This is done for the currently configured channel */
563
bool ath9k_hw_reset_calvalid(struct ath_hw *ah)
S
Sujith 已提交
564
{
565 566
	struct ath_common *common = ath9k_hw_common(ah);
	struct ieee80211_conf *conf = &common->hw->conf;
567
	struct ath9k_cal_list *currCal = ah->cal_list_curr;
S
Sujith 已提交
568

569
	if (!ah->curchan)
570
		return true;
S
Sujith 已提交
571 572

	if (!AR_SREV_9100(ah) && !AR_SREV_9160_10_OR_LATER(ah))
573
		return true;
S
Sujith 已提交
574 575

	if (currCal == NULL)
576
		return true;
S
Sujith 已提交
577 578

	if (currCal->calState != CAL_DONE) {
579 580 581
		ath_print(common, ATH_DBG_CALIBRATE,
			  "Calibration state incorrect, %d\n",
			  currCal->calState);
582
		return true;
S
Sujith 已提交
583 584
	}

585 586
	if (!ath9k_hw_iscal_supported(ah, currCal->calData->calType))
		return true;
S
Sujith 已提交
587

588 589 590
	ath_print(common, ATH_DBG_CALIBRATE,
		  "Resetting Cal %d state for channel %u\n",
		  currCal->calData->calType, conf->channel->center_freq);
S
Sujith 已提交
591

592
	ah->curchan->CalValid &= ~currCal->calData->calType;
S
Sujith 已提交
593 594
	currCal->calState = CAL_WAITING;

595
	return false;
S
Sujith 已提交
596 597
}

598
void ath9k_hw_start_nfcal(struct ath_hw *ah)
S
Sujith 已提交
599 600 601 602 603 604 605 606
{
	REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
		    AR_PHY_AGC_CONTROL_ENABLE_NF);
	REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
		    AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
	REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
}

607
void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan)
S
Sujith 已提交
608 609 610 611 612 613 614 615 616 617 618 619
{
	struct ath9k_nfcal_hist *h;
	int i, j;
	int32_t val;
	const u32 ar5416_cca_regs[6] = {
		AR_PHY_CCA,
		AR_PHY_CH1_CCA,
		AR_PHY_CH2_CCA,
		AR_PHY_EXT_CCA,
		AR_PHY_CH1_EXT_CCA,
		AR_PHY_CH2_EXT_CCA
	};
620
	u8 chainmask, rx_chain_status;
S
Sujith 已提交
621

622
	rx_chain_status = REG_READ(ah, AR_PHY_RX_CHAINMASK);
S
Sujith 已提交
623 624
	if (AR_SREV_9285(ah))
		chainmask = 0x9;
625 626 627 628 629 630 631 632 633 634 635 636 637
	else if (AR_SREV_9280(ah) || AR_SREV_9287(ah)) {
		if ((rx_chain_status & 0x2) || (rx_chain_status & 0x4))
			chainmask = 0x1B;
		else
			chainmask = 0x09;
	} else {
		if (rx_chain_status & 0x4)
			chainmask = 0x3F;
		else if (rx_chain_status & 0x2)
			chainmask = 0x1B;
		else
			chainmask = 0x09;
	}
S
Sujith 已提交
638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655

	h = ah->nfCalHist;

	for (i = 0; i < NUM_NF_READINGS; i++) {
		if (chainmask & (1 << i)) {
			val = REG_READ(ah, ar5416_cca_regs[i]);
			val &= 0xFFFFFE00;
			val |= (((u32) (h[i].privNF) << 1) & 0x1ff);
			REG_WRITE(ah, ar5416_cca_regs[i], val);
		}
	}

	REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
		    AR_PHY_AGC_CONTROL_ENABLE_NF);
	REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
		    AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
	REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);

656
	for (j = 0; j < 5; j++) {
S
Sujith 已提交
657 658 659
		if ((REG_READ(ah, AR_PHY_AGC_CONTROL) &
		     AR_PHY_AGC_CONTROL_NF) == 0)
			break;
660
		udelay(50);
S
Sujith 已提交
661 662 663 664 665 666 667 668 669 670 671 672
	}

	for (i = 0; i < NUM_NF_READINGS; i++) {
		if (chainmask & (1 << i)) {
			val = REG_READ(ah, ar5416_cca_regs[i]);
			val &= 0xFFFFFE00;
			val |= (((u32) (-50) << 1) & 0x1ff);
			REG_WRITE(ah, ar5416_cca_regs[i], val);
		}
	}
}

673
int16_t ath9k_hw_getnf(struct ath_hw *ah,
S
Sujith 已提交
674 675
		       struct ath9k_channel *chan)
{
676
	struct ath_common *common = ath9k_hw_common(ah);
S
Sujith 已提交
677 678 679
	int16_t nf, nfThresh;
	int16_t nfarray[NUM_NF_READINGS] = { 0 };
	struct ath9k_nfcal_hist *h;
680
	struct ieee80211_channel *c = chan->chan;
S
Sujith 已提交
681 682 683

	chan->channelFlags &= (~CHANNEL_CW_INT);
	if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) {
684 685
		ath_print(common, ATH_DBG_CALIBRATE,
			  "NF did not complete in calibration window\n");
S
Sujith 已提交
686 687 688 689 690 691
		nf = 0;
		chan->rawNoiseFloor = nf;
		return chan->rawNoiseFloor;
	} else {
		ath9k_hw_do_getnf(ah, nfarray);
		nf = nfarray[0];
692
		if (getNoiseFloorThresh(ah, c->band, &nfThresh)
S
Sujith 已提交
693
		    && nf > nfThresh) {
694 695 696 697
			ath_print(common, ATH_DBG_CALIBRATE,
				  "noise floor failed detected; "
				  "detected %d, threshold %d\n",
				  nf, nfThresh);
S
Sujith 已提交
698 699 700 701 702 703 704 705 706 707 708 709
			chan->channelFlags |= CHANNEL_CW_INT;
		}
	}

	h = ah->nfCalHist;

	ath9k_hw_update_nfcal_hist_buffer(h, nfarray);
	chan->rawNoiseFloor = h[0].privNF;

	return chan->rawNoiseFloor;
}

710
void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah)
S
Sujith 已提交
711 712
{
	int i, j;
713 714 715 716 717 718
	s16 noise_floor;

	if (AR_SREV_9280(ah))
		noise_floor = AR_PHY_CCA_MAX_AR9280_GOOD_VALUE;
	else if (AR_SREV_9285(ah))
		noise_floor = AR_PHY_CCA_MAX_AR9285_GOOD_VALUE;
719 720
	else if (AR_SREV_9287(ah))
		noise_floor = AR_PHY_CCA_MAX_AR9287_GOOD_VALUE;
721 722
	else
		noise_floor = AR_PHY_CCA_MAX_AR5416_GOOD_VALUE;
S
Sujith 已提交
723 724 725

	for (i = 0; i < NUM_NF_READINGS; i++) {
		ah->nfCalHist[i].currIndex = 0;
726
		ah->nfCalHist[i].privNF = noise_floor;
S
Sujith 已提交
727 728 729
		ah->nfCalHist[i].invalidNFcount =
			AR_PHY_CCA_FILTERWINDOW_LENGTH;
		for (j = 0; j < ATH9K_NF_CAL_HIST_MAX; j++) {
730
			ah->nfCalHist[i].nfCalBuffer[j] = noise_floor;
S
Sujith 已提交
731 732 733 734
		}
	}
}

735
s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan)
S
Sujith 已提交
736 737 738
{
	s16 nf;

739
	if (chan->rawNoiseFloor == 0)
740 741
		nf = -96;
	else
742
		nf = chan->rawNoiseFloor;
S
Sujith 已提交
743 744 745 746 747 748 749

	if (!ath9k_hw_nf_in_range(ah, nf))
		nf = ATH_DEFAULT_NOISE_FLOOR;

	return nf;
}

V
Vivek Natarajan 已提交
750
static void ath9k_olc_temp_compensation_9287(struct ath_hw *ah)
751
{
V
Vivek Natarajan 已提交
752 753
	u32 rddata;
	int32_t delta, currPDADC, slope;
754 755 756 757

	rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4);
	currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT);

V
Vivek Natarajan 已提交
758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782
	if (ah->initPDADC == 0 || currPDADC == 0) {
		/*
		 * Zero value indicates that no frames have been transmitted yet,
		 * can't do temperature compensation until frames are transmitted.
		 */
		return;
	} else {
		slope = ah->eep_ops->get_eeprom(ah, EEP_TEMPSENSE_SLOPE);

		if (slope == 0) { /* to avoid divide by zero case */
			delta = 0;
		} else {
			delta = ((currPDADC - ah->initPDADC)*4) / slope;
		}
		REG_RMW_FIELD(ah, AR_PHY_CH0_TX_PWRCTRL11,
			      AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta);
		REG_RMW_FIELD(ah, AR_PHY_CH1_TX_PWRCTRL11,
			      AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta);
	}
}

static void ath9k_olc_temp_compensation(struct ath_hw *ah)
{
	u32 rddata, i;
	int delta, currPDADC, regval;
783

784
	if (OLC_FOR_AR9287_10_LATER) {
V
Vivek Natarajan 已提交
785 786 787 788 789
		ath9k_olc_temp_compensation_9287(ah);
	} else {
		rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4);
		currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT);

790 791 792
		if (ah->initPDADC == 0 || currPDADC == 0) {
			return;
		} else {
V
Vivek Natarajan 已提交
793 794
			if (ah->eep_ops->get_eeprom(ah, EEP_DAC_HPWR_5G))
				delta = (currPDADC - ah->initPDADC + 4) / 8;
795
			else
V
Vivek Natarajan 已提交
796 797 798 799 800 801 802 803 804 805 806 807 808
				delta = (currPDADC - ah->initPDADC + 5) / 10;

			if (delta != ah->PDADCdelta) {
				ah->PDADCdelta = delta;
				for (i = 1; i < AR9280_TX_GAIN_TABLE_SIZE; i++) {
					regval = ah->originalGain[i] - delta;
					if (regval < 0)
						regval = 0;

					REG_RMW_FIELD(ah,
						      AR_PHY_TX_GAIN_TBL1 + i * 4,
						      AR_PHY_TX_GAIN, regval);
				}
809
			}
810 811 812 813
		}
	}
}

814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905
static void ath9k_hw_9271_pa_cal(struct ath_hw *ah)
{
	u32 regVal;
	unsigned int i;
	u32 regList [][2] = {
		{ 0x786c, 0 },
		{ 0x7854, 0 },
		{ 0x7820, 0 },
		{ 0x7824, 0 },
		{ 0x7868, 0 },
		{ 0x783c, 0 },
		{ 0x7838, 0 } ,
		{ 0x7828, 0 } ,
	};

	for (i = 0; i < ARRAY_SIZE(regList); i++)
		regList[i][1] = REG_READ(ah, regList[i][0]);

	regVal = REG_READ(ah, 0x7834);
	regVal &= (~(0x1));
	REG_WRITE(ah, 0x7834, regVal);
	regVal = REG_READ(ah, 0x9808);
	regVal |= (0x1 << 27);
	REG_WRITE(ah, 0x9808, regVal);

	/* 786c,b23,1, pwddac=1 */
	REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1);
	/* 7854, b5,1, pdrxtxbb=1 */
	REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1);
	/* 7854, b7,1, pdv2i=1 */
	REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1);
	/* 7854, b8,1, pddacinterface=1 */
	REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1);
	/* 7824,b12,0, offcal=0 */
	REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0);
	/* 7838, b1,0, pwddb=0 */
	REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0);
	/* 7820,b11,0, enpacal=0 */
	REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0);
	/* 7820,b25,1, pdpadrv1=0 */
	REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 0);
	/* 7820,b24,0, pdpadrv2=0 */
	REG_RMW_FIELD(ah, AR9285_AN_RF2G1,AR9285_AN_RF2G1_PDPADRV2,0);
	/* 7820,b23,0, pdpaout=0 */
	REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0);
	/* 783c,b14-16,7, padrvgn2tab_0=7 */
	REG_RMW_FIELD(ah, AR9285_AN_RF2G8,AR9285_AN_RF2G8_PADRVGN2TAB0, 7);
	/*
	 * 7838,b29-31,0, padrvgn1tab_0=0
	 * does not matter since we turn it off
	 */
	REG_RMW_FIELD(ah, AR9285_AN_RF2G7,AR9285_AN_RF2G7_PADRVGN2TAB0, 0);

	REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9271_AN_RF2G3_CCOMP, 0xfff);

	/* Set:
	 * localmode=1,bmode=1,bmoderxtx=1,synthon=1,
	 * txon=1,paon=1,oscon=1,synthon_force=1
	 */
	REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0);
	udelay(30);
	REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9271_AN_RF2G6_OFFS, 0);

	/* find off_6_1; */
	for (i = 6; i >= 0; i--) {
		regVal = REG_READ(ah, 0x7834);
		regVal |= (1 << (20 + i));
		REG_WRITE(ah, 0x7834, regVal);
		udelay(1);
		//regVal = REG_READ(ah, 0x7834);
		regVal &= (~(0x1 << (20 + i)));
		regVal |= (MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9)
			    << (20 + i));
		REG_WRITE(ah, 0x7834, regVal);
	}

	/*  Empirical offset correction  */
#if 0
	REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9271_AN_RF2G6_OFFS, 0x20);
#endif

	regVal = REG_READ(ah, 0x7834);
	regVal |= 0x1;
	REG_WRITE(ah, 0x7834, regVal);
	regVal = REG_READ(ah, 0x9808);
	regVal &= (~(0x1 << 27));
	REG_WRITE(ah, 0x9808, regVal);

	for (i = 0; i < ARRAY_SIZE(regList); i++)
		REG_WRITE(ah, regList[i][0], regList[i][1]);
}

906
static inline void ath9k_hw_9285_pa_cal(struct ath_hw *ah, bool is_reset)
907
{
908
	struct ath_common *common = ath9k_hw_common(ah);
909 910 911 912 913 914 915 916 917 918 919 920 921
	u32 regVal;
	int i, offset, offs_6_1, offs_0;
	u32 ccomp_org, reg_field;
	u32 regList[][2] = {
		{ 0x786c, 0 },
		{ 0x7854, 0 },
		{ 0x7820, 0 },
		{ 0x7824, 0 },
		{ 0x7868, 0 },
		{ 0x783c, 0 },
		{ 0x7838, 0 },
	};

922
	ath_print(common, ATH_DBG_CALIBRATE, "Running PA Calibration\n");
923

S
Sujith 已提交
924 925 926 927 928
	/* PA CAL is not needed for high power solution */
	if (ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE) ==
	    AR5416_EEP_TXGAIN_HIGH_POWER)
		return;

929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950
	if (AR_SREV_9285_11(ah)) {
		REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14));
		udelay(10);
	}

	for (i = 0; i < ARRAY_SIZE(regList); i++)
		regList[i][1] = REG_READ(ah, regList[i][0]);

	regVal = REG_READ(ah, 0x7834);
	regVal &= (~(0x1));
	REG_WRITE(ah, 0x7834, regVal);
	regVal = REG_READ(ah, 0x9808);
	regVal |= (0x1 << 27);
	REG_WRITE(ah, 0x9808, regVal);

	REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1);
	REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1);
	REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1);
	REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1);
	REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0);
	REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0);
	REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0);
951
	REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 0);
952 953 954 955 956
	REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2, 0);
	REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0);
	REG_RMW_FIELD(ah, AR9285_AN_RF2G8, AR9285_AN_RF2G8_PADRVGN2TAB0, 7);
	REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PADRVGN2TAB0, 0);
	ccomp_org = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_CCOMP);
957
	REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, 0xf);
958 959 960 961 962 963 964 965 966 967 968

	REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0);
	udelay(30);
	REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, 0);
	REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 0);

	for (i = 6; i > 0; i--) {
		regVal = REG_READ(ah, 0x7834);
		regVal |= (1 << (19 + i));
		REG_WRITE(ah, 0x7834, regVal);
		udelay(1);
S
Sujith 已提交
969
		regVal = REG_READ(ah, 0x7834);
970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987
		regVal &= (~(0x1 << (19 + i)));
		reg_field = MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9);
		regVal |= (reg_field << (19 + i));
		REG_WRITE(ah, 0x7834, regVal);
	}

	REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 1);
	udelay(1);
	reg_field = MS(REG_READ(ah, AR9285_AN_RF2G9), AR9285_AN_RXTXBB1_SPARE9);
	REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, reg_field);
	offs_6_1 = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_OFFS);
	offs_0   = MS(REG_READ(ah, AR9285_AN_RF2G3), AR9285_AN_RF2G3_PDVCCOMP);

	offset = (offs_6_1<<1) | offs_0;
	offset = offset - 0;
	offs_6_1 = offset>>1;
	offs_0 = offset & 1;

988 989 990 991 992 993 994 995 996 997 998
	if ((!is_reset) && (ah->pacal_info.prev_offset == offset)) {
		if (ah->pacal_info.max_skipcount < MAX_PACAL_SKIPCOUNT)
			ah->pacal_info.max_skipcount =
				2 * ah->pacal_info.max_skipcount;
		ah->pacal_info.skipcount = ah->pacal_info.max_skipcount;
	} else {
		ah->pacal_info.max_skipcount = 1;
		ah->pacal_info.skipcount = 0;
		ah->pacal_info.prev_offset = offset;
	}

999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018
	REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, offs_6_1);
	REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, offs_0);

	regVal = REG_READ(ah, 0x7834);
	regVal |= 0x1;
	REG_WRITE(ah, 0x7834, regVal);
	regVal = REG_READ(ah, 0x9808);
	regVal &= (~(0x1 << 27));
	REG_WRITE(ah, 0x9808, regVal);

	for (i = 0; i < ARRAY_SIZE(regList); i++)
		REG_WRITE(ah, regList[i][0], regList[i][1]);

	REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, ccomp_org);

	if (AR_SREV_9285_11(ah))
		REG_WRITE(ah, AR9285_AN_TOP4, AR9285_AN_TOP4_DEFAULT);

}

1019
bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan,
S
Sujith 已提交
1020
			u8 rxchainmask, bool longcal)
1021
{
S
Sujith 已提交
1022
	bool iscaldone = true;
1023
	struct ath9k_cal_list *currCal = ah->cal_list_curr;
1024 1025 1026 1027

	if (currCal &&
	    (currCal->calState == CAL_RUNNING ||
	     currCal->calState == CAL_WAITING)) {
S
Sujith 已提交
1028 1029 1030
		iscaldone = ath9k_hw_per_calibration(ah, chan,
						     rxchainmask, currCal);
		if (iscaldone) {
1031 1032 1033
			ah->cal_list_curr = currCal = currCal->calNext;

			if (currCal->calState == CAL_WAITING) {
S
Sujith 已提交
1034
				iscaldone = false;
1035 1036 1037 1038 1039
				ath9k_hw_reset_calibration(ah, currCal);
			}
		}
	}

1040
	/* Do NF cal only at longer intervals */
1041
	if (longcal) {
1042 1043 1044
		/* Do periodic PAOffset Cal */
		if (AR_SREV_9271(ah))
			ath9k_hw_9271_pa_cal(ah);
1045 1046 1047 1048 1049 1050
		else if (AR_SREV_9285_11_OR_LATER(ah)) {
			if (!ah->pacal_info.skipcount)
				ath9k_hw_9285_pa_cal(ah, false);
			else
				ah->pacal_info.skipcount--;
		}
1051

1052
		if (OLC_FOR_AR9280_20_LATER || OLC_FOR_AR9287_10_LATER)
1053
			ath9k_olc_temp_compensation(ah);
1054 1055

		/* Get the value from the previous NF cal and update history buffer */
1056
		ath9k_hw_getnf(ah, chan);
1057 1058 1059 1060 1061

		/*
		 * Load the NF from history buffer of the current channel.
		 * NF is slow time-variant, so it is OK to use a historical value.
		 */
1062
		ath9k_hw_loadnf(ah, ah->curchan);
1063

1064 1065 1066
		ath9k_hw_start_nfcal(ah);
	}

S
Sujith 已提交
1067
	return iscaldone;
1068 1069
}

1070
static bool ar9285_clc(struct ath_hw *ah, struct ath9k_channel *chan)
1071
{
1072 1073
	struct ath_common *common = ath9k_hw_common(ah);

1074
	REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
S
Sujith 已提交
1075
	if (IS_CHAN_HT20(chan)) {
1076 1077 1078 1079 1080 1081 1082 1083
		REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE);
		REG_SET_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN);
		REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
			    AR_PHY_AGC_CONTROL_FLTR_CAL);
		REG_CLR_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE);
		REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL);
		if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
				  AR_PHY_AGC_CONTROL_CAL, 0, AH_WAIT_TIMEOUT)) {
1084 1085 1086
			ath_print(common, ATH_DBG_CALIBRATE, "offset "
				  "calibration failed to complete in "
				  "1ms; noisy ??\n");
1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098
			return false;
		}
		REG_CLR_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN);
		REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE);
		REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
	}
	REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
	REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL);
	REG_SET_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE);
	REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL);
	if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL,
			  0, AH_WAIT_TIMEOUT)) {
1099 1100
		ath_print(common, ATH_DBG_CALIBRATE, "offset calibration "
			  "failed to complete in 1ms; noisy ??\n");
1101 1102 1103 1104 1105 1106 1107 1108 1109 1110
		return false;
	}

	REG_SET_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
	REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
	REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL);

	return true;
}

1111
bool ath9k_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan)
S
Sujith 已提交
1112
{
1113 1114
	struct ath_common *common = ath9k_hw_common(ah);

1115
	if (AR_SREV_9285_12_OR_LATER(ah)) {
1116 1117
		if (!ar9285_clc(ah, chan))
			return false;
1118 1119
	} else {
		if (AR_SREV_9280_10_OR_LATER(ah)) {
1120 1121 1122 1123 1124
			if (!AR_SREV_9287_10_OR_LATER(ah))
				REG_CLR_BIT(ah, AR_PHY_ADC_CTL,
					    AR_PHY_ADC_CTL_OFF_PWDADC);
			REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
				    AR_PHY_AGC_CONTROL_FLTR_CAL);
1125
		}
1126

1127
		/* Calibrate the AGC */
1128
		REG_WRITE(ah, AR_PHY_AGC_CONTROL,
1129 1130
			  REG_READ(ah, AR_PHY_AGC_CONTROL) |
			  AR_PHY_AGC_CONTROL_CAL);
1131

1132 1133 1134
		/* Poll for offset calibration complete */
		if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL,
				   0, AH_WAIT_TIMEOUT)) {
1135 1136 1137
			ath_print(common, ATH_DBG_CALIBRATE,
				  "offset calibration failed to "
				  "complete in 1ms; noisy environment?\n");
1138 1139 1140
			return false;
		}

1141
		if (AR_SREV_9280_10_OR_LATER(ah)) {
1142 1143 1144 1145 1146
			if (!AR_SREV_9287_10_OR_LATER(ah))
				REG_SET_BIT(ah, AR_PHY_ADC_CTL,
					    AR_PHY_ADC_CTL_OFF_PWDADC);
			REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
				    AR_PHY_AGC_CONTROL_FLTR_CAL);
1147
		}
1148 1149 1150
	}

	/* Do PA Calibration */
1151
	if (AR_SREV_9285_11_OR_LATER(ah))
1152
		ath9k_hw_9285_pa_cal(ah, true);
1153

1154
	/* Do NF Calibration after DC offset and other calibrations */
S
Sujith 已提交
1155
	REG_WRITE(ah, AR_PHY_AGC_CONTROL,
1156
		  REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_NF);
S
Sujith 已提交
1157

1158
	ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL;
S
Sujith 已提交
1159

1160
	/* Enable IQ, ADC Gain and ADC DC offset CALs */
S
Sujith 已提交
1161
	if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) {
1162
		if (ath9k_hw_iscal_supported(ah, ADC_GAIN_CAL)) {
1163 1164
			INIT_CAL(&ah->adcgain_caldata);
			INSERT_CAL(ah, &ah->adcgain_caldata);
1165 1166
			ath_print(common, ATH_DBG_CALIBRATE,
				  "enabling ADC Gain Calibration.\n");
S
Sujith 已提交
1167
		}
1168
		if (ath9k_hw_iscal_supported(ah, ADC_DC_CAL)) {
1169 1170
			INIT_CAL(&ah->adcdc_caldata);
			INSERT_CAL(ah, &ah->adcdc_caldata);
1171 1172
			ath_print(common, ATH_DBG_CALIBRATE,
				  "enabling ADC DC Calibration.\n");
S
Sujith 已提交
1173
		}
1174
		if (ath9k_hw_iscal_supported(ah, IQ_MISMATCH_CAL)) {
1175 1176
			INIT_CAL(&ah->iq_caldata);
			INSERT_CAL(ah, &ah->iq_caldata);
1177 1178
			ath_print(common, ATH_DBG_CALIBRATE,
				  "enabling IQ Calibration.\n");
S
Sujith 已提交
1179 1180
		}

1181
		ah->cal_list_curr = ah->cal_list;
S
Sujith 已提交
1182

1183 1184
		if (ah->cal_list_curr)
			ath9k_hw_reset_calibration(ah, ah->cal_list_curr);
S
Sujith 已提交
1185 1186
	}

1187
	chan->CalValid = 0;
S
Sujith 已提交
1188 1189 1190 1191

	return true;
}

1192
const struct ath9k_percal_data iq_cal_multi_sample = {
S
Sujith 已提交
1193 1194 1195 1196 1197 1198
	IQ_MISMATCH_CAL,
	MAX_CAL_SAMPLES,
	PER_MIN_LOG_COUNT,
	ath9k_hw_iqcal_collect,
	ath9k_hw_iqcalibrate
};
1199
const struct ath9k_percal_data iq_cal_single_sample = {
S
Sujith 已提交
1200 1201 1202 1203 1204 1205
	IQ_MISMATCH_CAL,
	MIN_CAL_SAMPLES,
	PER_MAX_LOG_COUNT,
	ath9k_hw_iqcal_collect,
	ath9k_hw_iqcalibrate
};
1206
const struct ath9k_percal_data adc_gain_cal_multi_sample = {
S
Sujith 已提交
1207 1208 1209 1210 1211 1212
	ADC_GAIN_CAL,
	MAX_CAL_SAMPLES,
	PER_MIN_LOG_COUNT,
	ath9k_hw_adc_gaincal_collect,
	ath9k_hw_adc_gaincal_calibrate
};
1213
const struct ath9k_percal_data adc_gain_cal_single_sample = {
S
Sujith 已提交
1214 1215 1216 1217 1218 1219
	ADC_GAIN_CAL,
	MIN_CAL_SAMPLES,
	PER_MAX_LOG_COUNT,
	ath9k_hw_adc_gaincal_collect,
	ath9k_hw_adc_gaincal_calibrate
};
1220
const struct ath9k_percal_data adc_dc_cal_multi_sample = {
S
Sujith 已提交
1221 1222 1223 1224 1225 1226
	ADC_DC_CAL,
	MAX_CAL_SAMPLES,
	PER_MIN_LOG_COUNT,
	ath9k_hw_adc_dccal_collect,
	ath9k_hw_adc_dccal_calibrate
};
1227
const struct ath9k_percal_data adc_dc_cal_single_sample = {
S
Sujith 已提交
1228 1229 1230 1231 1232 1233
	ADC_DC_CAL,
	MIN_CAL_SAMPLES,
	PER_MAX_LOG_COUNT,
	ath9k_hw_adc_dccal_collect,
	ath9k_hw_adc_dccal_calibrate
};
1234
const struct ath9k_percal_data adc_init_dc_cal = {
S
Sujith 已提交
1235 1236 1237 1238 1239 1240
	ADC_DC_INIT_CAL,
	MIN_CAL_SAMPLES,
	INIT_LOG_COUNT,
	ath9k_hw_adc_dccal_collect,
	ath9k_hw_adc_dccal_calibrate
};