xref: /freebsd/sys/dev/ath/ath_hal/ar9002/ar9280_attach.c (revision 3ef51c5fb9163f2aafb1c14729e06a8bf0c4d113)
1 /*
2  * Copyright (c) 2008-2009 Sam Leffler, Errno Consulting
3  * Copyright (c) 2008 Atheros Communications, Inc.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  *
17  * $FreeBSD$
18  */
19 #include "opt_ah.h"
20 
21 #include "ah.h"
22 #include "ah_internal.h"
23 #include "ah_devid.h"
24 
25 #include "ah_eeprom_v14.h"		/* XXX for tx/rx gain */
26 
27 #include "ar9002/ar9280.h"
28 #include "ar5416/ar5416reg.h"
29 #include "ar5416/ar5416phy.h"
30 
31 #include "ar9002/ar9280v1.ini"
32 #include "ar9002/ar9280v2.ini"
33 #include "ar9002/ar9280_olc.h"
34 
35 static const HAL_PERCAL_DATA ar9280_iq_cal = {		/* single sample */
36 	.calName = "IQ", .calType = IQ_MISMATCH_CAL,
37 	.calNumSamples	= MIN_CAL_SAMPLES,
38 	.calCountMax	= PER_MAX_LOG_COUNT,
39 	.calCollect	= ar5416IQCalCollect,
40 	.calPostProc	= ar5416IQCalibration
41 };
42 static const HAL_PERCAL_DATA ar9280_adc_gain_cal = {	/* single sample */
43 	.calName = "ADC Gain", .calType = ADC_GAIN_CAL,
44 	.calNumSamples	= MIN_CAL_SAMPLES,
45 	.calCountMax	= PER_MAX_LOG_COUNT,
46 	.calCollect	= ar5416AdcGainCalCollect,
47 	.calPostProc	= ar5416AdcGainCalibration
48 };
49 static const HAL_PERCAL_DATA ar9280_adc_dc_cal = {	/* single sample */
50 	.calName = "ADC DC", .calType = ADC_DC_CAL,
51 	.calNumSamples	= MIN_CAL_SAMPLES,
52 	.calCountMax	= PER_MAX_LOG_COUNT,
53 	.calCollect	= ar5416AdcDcCalCollect,
54 	.calPostProc	= ar5416AdcDcCalibration
55 };
56 static const HAL_PERCAL_DATA ar9280_adc_init_dc_cal = {
57 	.calName = "ADC Init DC", .calType = ADC_DC_INIT_CAL,
58 	.calNumSamples	= MIN_CAL_SAMPLES,
59 	.calCountMax	= INIT_LOG_COUNT,
60 	.calCollect	= ar5416AdcDcCalCollect,
61 	.calPostProc	= ar5416AdcDcCalibration
62 };
63 
64 static void ar9280ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore);
65 static HAL_BOOL ar9280FillCapabilityInfo(struct ath_hal *ah);
66 static void ar9280WriteIni(struct ath_hal *ah,
67 	const struct ieee80211_channel *chan);
68 
69 static void
70 ar9280AniSetup(struct ath_hal *ah)
71 {
72 	/*
73 	 * These are the parameters from the AR5416 ANI code;
74 	 * they likely need quite a bit of adjustment for the
75 	 * AR9280.
76 	 */
77         static const struct ar5212AniParams aniparams = {
78                 .maxNoiseImmunityLevel  = 4,    /* levels 0..4 */
79                 .totalSizeDesired       = { -55, -55, -55, -55, -62 },
80                 .coarseHigh             = { -14, -14, -14, -14, -12 },
81                 .coarseLow              = { -64, -64, -64, -64, -70 },
82                 .firpwr                 = { -78, -78, -78, -78, -80 },
83                 .maxSpurImmunityLevel   = 2,
84                 .cycPwrThr1             = { 2, 4, 6 },
85                 .maxFirstepLevel        = 2,    /* levels 0..2 */
86                 .firstep                = { 0, 4, 8 },
87                 .ofdmTrigHigh           = 500,
88                 .ofdmTrigLow            = 200,
89                 .cckTrigHigh            = 200,
90                 .cckTrigLow             = 100,
91                 .rssiThrHigh            = 40,
92                 .rssiThrLow             = 7,
93                 .period                 = 100,
94         };
95 	/* NB: disable ANI noise immmunity for reliable RIFS rx */
96 	AH5416(ah)->ah_ani_function &= ~(1 << HAL_ANI_NOISE_IMMUNITY_LEVEL);
97 
98         /* NB: ANI is not enabled yet */
99         ar5416AniAttach(ah, &aniparams, &aniparams, AH_TRUE);
100 }
101 
102 void
103 ar9280InitPLL(struct ath_hal *ah, const struct ieee80211_channel *chan)
104 {
105 	uint32_t pll = SM(0x5, AR_RTC_SOWL_PLL_REFDIV);
106 
107 	if (AR_SREV_MERLIN_20(ah) &&
108 	    chan != AH_NULL && IEEE80211_IS_CHAN_5GHZ(chan)) {
109 		/*
110 		 * PLL WAR for Merlin 2.0/2.1
111 		 * When doing fast clock, set PLL to 0x142c
112 		 * Else, set PLL to 0x2850 to prevent reset-to-reset variation
113 		 */
114 		pll = IS_5GHZ_FAST_CLOCK_EN(ah, chan) ? 0x142c : 0x2850;
115 	} else if (AR_SREV_MERLIN_10_OR_LATER(ah)) {
116 		pll = SM(0x5, AR_RTC_SOWL_PLL_REFDIV);
117 		if (chan != AH_NULL) {
118 			if (IEEE80211_IS_CHAN_HALF(chan))
119 				pll |= SM(0x1, AR_RTC_SOWL_PLL_CLKSEL);
120 			else if (IEEE80211_IS_CHAN_QUARTER(chan))
121 				pll |= SM(0x2, AR_RTC_SOWL_PLL_CLKSEL);
122 			if (IEEE80211_IS_CHAN_5GHZ(chan))
123 				pll |= SM(0x28, AR_RTC_SOWL_PLL_DIV);
124 			else
125 				pll |= SM(0x2c, AR_RTC_SOWL_PLL_DIV);
126 		} else
127 			pll |= SM(0x2c, AR_RTC_SOWL_PLL_DIV);
128 	}
129 
130 	OS_REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll);
131 	OS_DELAY(RTC_PLL_SETTLE_DELAY);
132 	OS_REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_SLEEP_DERIVED_CLK);
133 }
134 
135 /* XXX shouldn't be here! */
136 #define	EEP_MINOR(_ah) \
137 	(AH_PRIVATE(_ah)->ah_eeversion & AR5416_EEP_VER_MINOR_MASK)
138 
139 /*
140  * Attach for an AR9280 part.
141  */
142 static struct ath_hal *
143 ar9280Attach(uint16_t devid, HAL_SOFTC sc,
144 	HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata,
145 	HAL_STATUS *status)
146 {
147 	struct ath_hal_9280 *ahp9280;
148 	struct ath_hal_5212 *ahp;
149 	struct ath_hal *ah;
150 	uint32_t val;
151 	HAL_STATUS ecode;
152 	HAL_BOOL rfStatus;
153 	int8_t pwr_table_offset;
154 	uint8_t pwr;
155 
156 	HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n",
157 	    __func__, sc, (void*) st, (void*) sh);
158 
159 	/* NB: memory is returned zero'd */
160 	ahp9280 = ath_hal_malloc(sizeof (struct ath_hal_9280));
161 	if (ahp9280 == AH_NULL) {
162 		HALDEBUG(AH_NULL, HAL_DEBUG_ANY,
163 		    "%s: cannot allocate memory for state block\n", __func__);
164 		*status = HAL_ENOMEM;
165 		return AH_NULL;
166 	}
167 	ahp = AH5212(ahp9280);
168 	ah = &ahp->ah_priv.h;
169 
170 	ar5416InitState(AH5416(ah), devid, sc, st, sh, status);
171 
172 
173 	/*
174 	 * Use the "local" EEPROM data given to us by the higher layers.
175 	 * This is a private copy out of system flash. The Linux ath9k
176 	 * commit for the initial AR9130 support mentions MMIO flash
177 	 * access is "unreliable." -adrian
178 	 */
179 	if (eepromdata != AH_NULL) {
180 		AH_PRIVATE((ah))->ah_eepromRead = ath_hal_EepromDataRead;
181 		AH_PRIVATE((ah))->ah_eepromWrite = NULL;
182 		ah->ah_eepromdata = eepromdata;
183 	}
184 
185 	/* XXX override with 9280 specific state */
186 	/* override 5416 methods for our needs */
187 	AH5416(ah)->ah_initPLL = ar9280InitPLL;
188 
189 	ah->ah_setAntennaSwitch		= ar9280SetAntennaSwitch;
190 	ah->ah_configPCIE		= ar9280ConfigPCIE;
191 
192 	AH5416(ah)->ah_cal.iqCalData.calData = &ar9280_iq_cal;
193 	AH5416(ah)->ah_cal.adcGainCalData.calData = &ar9280_adc_gain_cal;
194 	AH5416(ah)->ah_cal.adcDcCalData.calData = &ar9280_adc_dc_cal;
195 	AH5416(ah)->ah_cal.adcDcCalInitData.calData = &ar9280_adc_init_dc_cal;
196 	AH5416(ah)->ah_cal.suppCals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL;
197 
198 	AH5416(ah)->ah_spurMitigate	= ar9280SpurMitigate;
199 	AH5416(ah)->ah_writeIni		= ar9280WriteIni;
200 	AH5416(ah)->ah_olcInit		= ar9280olcInit;
201 	AH5416(ah)->ah_olcTempCompensation = ar9280olcTemperatureCompensation;
202 	AH5416(ah)->ah_setPowerCalTable	= ar9280SetPowerCalTable;
203 
204 	AH5416(ah)->ah_rx_chainmask	= AR9280_DEFAULT_RXCHAINMASK;
205 	AH5416(ah)->ah_tx_chainmask	= AR9280_DEFAULT_TXCHAINMASK;
206 
207 	if (!ar5416SetResetReg(ah, HAL_RESET_POWER_ON)) {
208 		/* reset chip */
209 		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't reset chip\n",
210 		    __func__);
211 		ecode = HAL_EIO;
212 		goto bad;
213 	}
214 
215 	if (!ar5416SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) {
216 		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't wakeup chip\n",
217 		    __func__);
218 		ecode = HAL_EIO;
219 		goto bad;
220 	}
221 	/* Read Revisions from Chips before taking out of reset */
222 	val = OS_REG_READ(ah, AR_SREV);
223 	HALDEBUG(ah, HAL_DEBUG_ATTACH,
224 	    "%s: ID 0x%x VERSION 0x%x TYPE 0x%x REVISION 0x%x\n",
225 	    __func__, MS(val, AR_XSREV_ID), MS(val, AR_XSREV_VERSION),
226 	    MS(val, AR_XSREV_TYPE), MS(val, AR_XSREV_REVISION));
227 	/* NB: include chip type to differentiate from pre-Sowl versions */
228 	AH_PRIVATE(ah)->ah_macVersion =
229 	    (val & AR_XSREV_VERSION) >> AR_XSREV_TYPE_S;
230 	AH_PRIVATE(ah)->ah_macRev = MS(val, AR_XSREV_REVISION);
231 	AH_PRIVATE(ah)->ah_ispcie = (val & AR_XSREV_TYPE_HOST_MODE) == 0;
232 
233 	/* setup common ini data; rf backends handle remainder */
234 	if (AR_SREV_MERLIN_20_OR_LATER(ah)) {
235 		HAL_INI_INIT(&ahp->ah_ini_modes, ar9280Modes_v2, 6);
236 		HAL_INI_INIT(&ahp->ah_ini_common, ar9280Common_v2, 2);
237 		HAL_INI_INIT(&AH5416(ah)->ah_ini_pcieserdes,
238 		    ar9280PciePhy_clkreq_always_on_L1_v2, 2);
239 		HAL_INI_INIT(&ahp9280->ah_ini_xmodes,
240 		    ar9280Modes_fast_clock_v2, 3);
241 	} else {
242 		HAL_INI_INIT(&ahp->ah_ini_modes, ar9280Modes_v1, 6);
243 		HAL_INI_INIT(&ahp->ah_ini_common, ar9280Common_v1, 2);
244 		HAL_INI_INIT(&AH5416(ah)->ah_ini_pcieserdes,
245 		    ar9280PciePhy_v1, 2);
246 	}
247 	ar5416AttachPCIE(ah);
248 
249 	ecode = ath_hal_v14EepromAttach(ah);
250 	if (ecode != HAL_OK)
251 		goto bad;
252 
253 	if (!ar5416ChipReset(ah, AH_NULL)) {	/* reset chip */
254 		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__);
255 		ecode = HAL_EIO;
256 		goto bad;
257 	}
258 
259 	AH_PRIVATE(ah)->ah_phyRev = OS_REG_READ(ah, AR_PHY_CHIP_ID);
260 
261 	if (!ar5212ChipTest(ah)) {
262 		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: hardware self-test failed\n",
263 		    __func__);
264 		ecode = HAL_ESELFTEST;
265 		goto bad;
266 	}
267 
268 	/*
269 	 * Set correct Baseband to analog shift
270 	 * setting to access analog chips.
271 	 */
272 	OS_REG_WRITE(ah, AR_PHY(0), 0x00000007);
273 
274 	/* Read Radio Chip Rev Extract */
275 	AH_PRIVATE(ah)->ah_analog5GhzRev = ar5416GetRadioRev(ah);
276 	switch (AH_PRIVATE(ah)->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR) {
277         case AR_RAD2133_SREV_MAJOR:	/* Sowl: 2G/3x3 */
278 	case AR_RAD5133_SREV_MAJOR:	/* Sowl: 2+5G/3x3 */
279 		break;
280 	default:
281 		if (AH_PRIVATE(ah)->ah_analog5GhzRev == 0) {
282 			AH_PRIVATE(ah)->ah_analog5GhzRev =
283 				AR_RAD5133_SREV_MAJOR;
284 			break;
285 		}
286 #ifdef AH_DEBUG
287 		HALDEBUG(ah, HAL_DEBUG_ANY,
288 		    "%s: 5G Radio Chip Rev 0x%02X is not supported by "
289 		    "this driver\n", __func__,
290 		    AH_PRIVATE(ah)->ah_analog5GhzRev);
291 		ecode = HAL_ENOTSUPP;
292 		goto bad;
293 #endif
294 	}
295 	rfStatus = ar9280RfAttach(ah, &ecode);
296 	if (!rfStatus) {
297 		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RF setup failed, status %u\n",
298 		    __func__, ecode);
299 		goto bad;
300 	}
301 
302 	/* Enable fixup for AR_AN_TOP2 if necessary */
303 	/*
304 	 * The v14 EEPROM layer returns HAL_EIO if PWDCLKIND isn't supported
305 	 * by the EEPROM version.
306 	 *
307 	 * ath9k checks the EEPROM minor version is >= 0x0a here, instead of
308 	 * the abstracted EEPROM access layer.
309 	 */
310 	ecode = ath_hal_eepromGet(ah, AR_EEP_PWDCLKIND, &pwr);
311 	if (AR_SREV_MERLIN_20_OR_LATER(ah) && ecode == HAL_OK && pwr == 0) {
312 		printf("[ath] enabling AN_TOP2_FIXUP\n");
313 		AH5416(ah)->ah_need_an_top2_fixup = 1;
314 	}
315 
316         /*
317          * Check whether the power table offset isn't the default.
318          * This can occur with eeprom minor V21 or greater on Merlin.
319          */
320 	(void) ath_hal_eepromGet(ah, AR_EEP_PWR_TABLE_OFFSET, &pwr_table_offset);
321 	if (pwr_table_offset != AR5416_PWR_TABLE_OFFSET_DB)
322 		ath_hal_printf(ah, "[ath]: default pwr offset: %d dBm != EEPROM pwr offset: %d dBm; curves will be adjusted.\n",
323 		    AR5416_PWR_TABLE_OFFSET_DB, (int) pwr_table_offset);
324 
325 	/* XXX check for >= minor ver 17 */
326 	if (AR_SREV_MERLIN_20(ah)) {
327 		/* setup rxgain table */
328 		switch (ath_hal_eepromGet(ah, AR_EEP_RXGAIN_TYPE, AH_NULL)) {
329 		case AR5416_EEP_RXGAIN_13dB_BACKOFF:
330 			HAL_INI_INIT(&ahp9280->ah_ini_rxgain,
331 			    ar9280Modes_backoff_13db_rxgain_v2, 6);
332 			break;
333 		case AR5416_EEP_RXGAIN_23dB_BACKOFF:
334 			HAL_INI_INIT(&ahp9280->ah_ini_rxgain,
335 			    ar9280Modes_backoff_23db_rxgain_v2, 6);
336 			break;
337 		case AR5416_EEP_RXGAIN_ORIG:
338 			HAL_INI_INIT(&ahp9280->ah_ini_rxgain,
339 			    ar9280Modes_original_rxgain_v2, 6);
340 			break;
341 		default:
342 			HALASSERT(AH_FALSE);
343 			goto bad;		/* XXX ? try to continue */
344 		}
345 	}
346 
347 	/* XXX check for >= minor ver 19 */
348 	if (AR_SREV_MERLIN_20(ah)) {
349 		/* setp txgain table */
350 		switch (ath_hal_eepromGet(ah, AR_EEP_TXGAIN_TYPE, AH_NULL)) {
351 		case AR5416_EEP_TXGAIN_HIGH_POWER:
352 			HAL_INI_INIT(&ahp9280->ah_ini_txgain,
353 			    ar9280Modes_high_power_tx_gain_v2, 6);
354 			break;
355 		case AR5416_EEP_TXGAIN_ORIG:
356 			HAL_INI_INIT(&ahp9280->ah_ini_txgain,
357 			    ar9280Modes_original_tx_gain_v2, 6);
358 			break;
359 		default:
360 			HALASSERT(AH_FALSE);
361 			goto bad;		/* XXX ? try to continue */
362 		}
363 	}
364 
365 	/*
366 	 * Got everything we need now to setup the capabilities.
367 	 */
368 	if (!ar9280FillCapabilityInfo(ah)) {
369 		ecode = HAL_EEREAD;
370 		goto bad;
371 	}
372 
373 	ecode = ath_hal_eepromGet(ah, AR_EEP_MACADDR, ahp->ah_macaddr);
374 	if (ecode != HAL_OK) {
375 		HALDEBUG(ah, HAL_DEBUG_ANY,
376 		    "%s: error getting mac address from EEPROM\n", __func__);
377 		goto bad;
378         }
379 	/* XXX How about the serial number ? */
380 	/* Read Reg Domain */
381 	AH_PRIVATE(ah)->ah_currentRD =
382 	    ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, AH_NULL);
383 	AH_PRIVATE(ah)->ah_currentRDext =
384 	    ath_hal_eepromGet(ah, AR_EEP_REGDMN_1, AH_NULL);
385 
386 	/*
387 	 * ah_miscMode is populated by ar5416FillCapabilityInfo()
388 	 * starting from griffin. Set here to make sure that
389 	 * AR_MISC_MODE_MIC_NEW_LOC_ENABLE is set before a GTK is
390 	 * placed into hardware.
391 	 */
392 	if (ahp->ah_miscMode != 0)
393 		OS_REG_WRITE(ah, AR_MISC_MODE, OS_REG_READ(ah, AR_MISC_MODE) | ahp->ah_miscMode);
394 
395 	ar9280AniSetup(ah);			/* Anti Noise Immunity */
396 
397 	/* Setup noise floor min/max/nominal values */
398 	AH5416(ah)->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_9280_2GHZ;
399 	AH5416(ah)->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_9280_2GHZ;
400 	AH5416(ah)->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9280_2GHZ;
401 	AH5416(ah)->nf_5g.max = AR_PHY_CCA_MAX_GOOD_VAL_9280_5GHZ;
402 	AH5416(ah)->nf_5g.min = AR_PHY_CCA_MIN_GOOD_VAL_9280_5GHZ;
403 	AH5416(ah)->nf_5g.nominal = AR_PHY_CCA_NOM_VAL_9280_5GHZ;
404 
405 	ar5416InitNfHistBuff(AH5416(ah)->ah_cal.nfCalHist);
406 
407 	HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n", __func__);
408 
409 	return ah;
410 bad:
411 	if (ah != AH_NULL)
412 		ah->ah_detach(ah);
413 	if (status)
414 		*status = ecode;
415 	return AH_NULL;
416 }
417 
418 static void
419 ar9280ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore)
420 {
421 	if (AH_PRIVATE(ah)->ah_ispcie && !restore) {
422 		ath_hal_ini_write(ah, &AH5416(ah)->ah_ini_pcieserdes, 1, 0);
423 		OS_DELAY(1000);
424 		OS_REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
425 		OS_REG_WRITE(ah, AR_WA, AR9280_WA_DEFAULT);
426 	}
427 }
428 
429 static void
430 ar9280WriteIni(struct ath_hal *ah, const struct ieee80211_channel *chan)
431 {
432 	u_int modesIndex, freqIndex;
433 	int regWrites = 0;
434 	int i;
435 	const HAL_INI_ARRAY *ia;
436 
437 	/* Setup the indices for the next set of register array writes */
438 	/* XXX Ignore 11n dynamic mode on the AR5416 for the moment */
439 	if (IEEE80211_IS_CHAN_2GHZ(chan)) {
440 		freqIndex = 2;
441 		if (IEEE80211_IS_CHAN_HT40(chan))
442 			modesIndex = 3;
443 		else if (IEEE80211_IS_CHAN_108G(chan))
444 			modesIndex = 5;
445 		else
446 			modesIndex = 4;
447 	} else {
448 		freqIndex = 1;
449 		if (IEEE80211_IS_CHAN_HT40(chan) ||
450 		    IEEE80211_IS_CHAN_TURBO(chan))
451 			modesIndex = 2;
452 		else
453 			modesIndex = 1;
454 	}
455 
456 	/* Set correct Baseband to analog shift setting to access analog chips. */
457 	OS_REG_WRITE(ah, AR_PHY(0), 0x00000007);
458 	OS_REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC);
459 
460 	/*
461 	 * This is unwound because at the moment, there's a requirement
462 	 * for Merlin (and later, perhaps) to have a specific bit fixed
463 	 * in the AR_AN_TOP2 register before writing it.
464 	 */
465 	ia = &AH5212(ah)->ah_ini_modes;
466 #if 0
467 	regWrites = ath_hal_ini_write(ah, &AH5212(ah)->ah_ini_modes,
468 	    modesIndex, regWrites);
469 #endif
470 	HALASSERT(modesIndex < ia->cols);
471 	for (i = 0; i < ia->rows; i++) {
472 		uint32_t reg = HAL_INI_VAL(ia, i, 0);
473 		uint32_t val = HAL_INI_VAL(ia, i, modesIndex);
474 
475 		if (reg == AR_AN_TOP2 && AH5416(ah)->ah_need_an_top2_fixup)
476 			val &= ~AR_AN_TOP2_PWDCLKIND;
477 
478 		OS_REG_WRITE(ah, reg, val);
479 
480 		/* Analog shift register delay seems needed for Merlin - PR kern/154220 */
481 		if (reg >= 0x7800 && reg < 0x7900)
482 			OS_DELAY(100);
483 
484 		DMA_YIELD(regWrites);
485 	}
486 
487 	if (AR_SREV_MERLIN_20_OR_LATER(ah)) {
488 		regWrites = ath_hal_ini_write(ah, &AH9280(ah)->ah_ini_rxgain,
489 		    modesIndex, regWrites);
490 		regWrites = ath_hal_ini_write(ah, &AH9280(ah)->ah_ini_txgain,
491 		    modesIndex, regWrites);
492 	}
493 	/* XXX Merlin 100us delay for shift registers */
494 	regWrites = ath_hal_ini_write(ah, &AH5212(ah)->ah_ini_common,
495 	    1, regWrites);
496 
497 	if (AR_SREV_MERLIN_20(ah) && IS_5GHZ_FAST_CLOCK_EN(ah, chan)) {
498 		/* 5GHz channels w/ Fast Clock use different modal values */
499 		regWrites = ath_hal_ini_write(ah, &AH9280(ah)->ah_ini_xmodes,
500 		    modesIndex, regWrites);
501 	}
502 }
503 
504 #define	AR_BASE_FREQ_2GHZ	2300
505 #define	AR_BASE_FREQ_5GHZ	4900
506 #define	AR_SPUR_FEEQ_BOUND_HT40	19
507 #define	AR_SPUR_FEEQ_BOUND_HT20	10
508 
509 void
510 ar9280SpurMitigate(struct ath_hal *ah, const struct ieee80211_channel *chan)
511 {
512     static const int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8,
513                 AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60 };
514     static const int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10,
515                 AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60 };
516     static int inc[4] = { 0, 100, 0, 0 };
517 
518     int bb_spur = AR_NO_SPUR;
519     int freq;
520     int bin, cur_bin;
521     int bb_spur_off, spur_subchannel_sd;
522     int spur_freq_sd;
523     int spur_delta_phase;
524     int denominator;
525     int upper, lower, cur_vit_mask;
526     int tmp, newVal;
527     int i;
528     CHAN_CENTERS centers;
529 
530     int8_t mask_m[123];
531     int8_t mask_p[123];
532     int8_t mask_amt;
533     int tmp_mask;
534     int cur_bb_spur;
535     HAL_BOOL is2GHz = IEEE80211_IS_CHAN_2GHZ(chan);
536 
537     OS_MEMZERO(&mask_m, sizeof(int8_t) * 123);
538     OS_MEMZERO(&mask_p, sizeof(int8_t) * 123);
539 
540     ar5416GetChannelCenters(ah, chan, &centers);
541     freq = centers.synth_center;
542 
543     /*
544      * Need to verify range +/- 9.38 for static ht20 and +/- 18.75 for ht40,
545      * otherwise spur is out-of-band and can be ignored.
546      */
547     for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) {
548         cur_bb_spur = ath_hal_getSpurChan(ah, i, is2GHz);
549         /* Get actual spur freq in MHz from EEPROM read value */
550         if (is2GHz) {
551             cur_bb_spur =  (cur_bb_spur / 10) + AR_BASE_FREQ_2GHZ;
552         } else {
553             cur_bb_spur =  (cur_bb_spur / 10) + AR_BASE_FREQ_5GHZ;
554         }
555 
556         if (AR_NO_SPUR == cur_bb_spur)
557             break;
558         cur_bb_spur = cur_bb_spur - freq;
559 
560         if (IEEE80211_IS_CHAN_HT40(chan)) {
561             if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT40) &&
562                 (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT40)) {
563                 bb_spur = cur_bb_spur;
564                 break;
565             }
566         } else if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT20) &&
567                    (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT20)) {
568             bb_spur = cur_bb_spur;
569             break;
570         }
571     }
572 
573     if (AR_NO_SPUR == bb_spur) {
574 #if 1
575         /*
576          * MRC CCK can interfere with beacon detection and cause deaf/mute.
577          * Disable MRC CCK for now.
578          */
579         OS_REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK, AR_PHY_FORCE_CLKEN_CCK_MRC_MUX);
580 #else
581         /* Enable MRC CCK if no spur is found in this channel. */
582         OS_REG_SET_BIT(ah, AR_PHY_FORCE_CLKEN_CCK, AR_PHY_FORCE_CLKEN_CCK_MRC_MUX);
583 #endif
584         return;
585     } else {
586         /*
587          * For Merlin, spur can break CCK MRC algorithm. Disable CCK MRC if spur
588          * is found in this channel.
589          */
590         OS_REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK, AR_PHY_FORCE_CLKEN_CCK_MRC_MUX);
591     }
592 
593     bin = bb_spur * 320;
594 
595     tmp = OS_REG_READ(ah, AR_PHY_TIMING_CTRL4_CHAIN(0));
596 
597     newVal = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI |
598         AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER |
599         AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK |
600         AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK);
601     OS_REG_WRITE(ah, AR_PHY_TIMING_CTRL4_CHAIN(0), newVal);
602 
603     newVal = (AR_PHY_SPUR_REG_MASK_RATE_CNTL |
604         AR_PHY_SPUR_REG_ENABLE_MASK_PPM |
605         AR_PHY_SPUR_REG_MASK_RATE_SELECT |
606         AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI |
607         SM(AR5416_SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH));
608     OS_REG_WRITE(ah, AR_PHY_SPUR_REG, newVal);
609 
610     /* Pick control or extn channel to cancel the spur */
611     if (IEEE80211_IS_CHAN_HT40(chan)) {
612         if (bb_spur < 0) {
613             spur_subchannel_sd = 1;
614             bb_spur_off = bb_spur + 10;
615         } else {
616             spur_subchannel_sd = 0;
617             bb_spur_off = bb_spur - 10;
618         }
619     } else {
620         spur_subchannel_sd = 0;
621         bb_spur_off = bb_spur;
622     }
623 
624     /*
625      * spur_delta_phase = bb_spur/40 * 2**21 for static ht20,
626      * /80 for dyn2040.
627      */
628     if (IEEE80211_IS_CHAN_HT40(chan))
629         spur_delta_phase = ((bb_spur * 262144) / 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE;
630     else
631         spur_delta_phase = ((bb_spur * 524288) / 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE;
632 
633     /*
634      * in 11A mode the denominator of spur_freq_sd should be 40 and
635      * it should be 44 in 11G
636      */
637     denominator = IEEE80211_IS_CHAN_2GHZ(chan) ? 44 : 40;
638     spur_freq_sd = ((bb_spur_off * 2048) / denominator) & 0x3ff;
639 
640     newVal = (AR_PHY_TIMING11_USE_SPUR_IN_AGC |
641         SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) |
642         SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE));
643     OS_REG_WRITE(ah, AR_PHY_TIMING11, newVal);
644 
645     /* Choose to cancel between control and extension channels */
646     newVal = spur_subchannel_sd << AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S;
647     OS_REG_WRITE(ah, AR_PHY_SFCORR_EXT, newVal);
648 
649     /*
650      * ============================================
651      * Set Pilot and Channel Masks
652      *
653      * pilot mask 1 [31:0] = +6..-26, no 0 bin
654      * pilot mask 2 [19:0] = +26..+7
655      *
656      * channel mask 1 [31:0] = +6..-26, no 0 bin
657      * channel mask 2 [19:0] = +26..+7
658      */
659     cur_bin = -6000;
660     upper = bin + 100;
661     lower = bin - 100;
662 
663     for (i = 0; i < 4; i++) {
664         int pilot_mask = 0;
665         int chan_mask  = 0;
666         int bp         = 0;
667         for (bp = 0; bp < 30; bp++) {
668             if ((cur_bin > lower) && (cur_bin < upper)) {
669                 pilot_mask = pilot_mask | 0x1 << bp;
670                 chan_mask  = chan_mask | 0x1 << bp;
671             }
672             cur_bin += 100;
673         }
674         cur_bin += inc[i];
675         OS_REG_WRITE(ah, pilot_mask_reg[i], pilot_mask);
676         OS_REG_WRITE(ah, chan_mask_reg[i], chan_mask);
677     }
678 
679     /* =================================================
680      * viterbi mask 1 based on channel magnitude
681      * four levels 0-3
682      *  - mask (-27 to 27) (reg 64,0x9900 to 67,0x990c)
683      *      [1 2 2 1] for -9.6 or [1 2 1] for +16
684      *  - enable_mask_ppm, all bins move with freq
685      *
686      *  - mask_select,    8 bits for rates (reg 67,0x990c)
687      *  - mask_rate_cntl, 8 bits for rates (reg 67,0x990c)
688      *      choose which mask to use mask or mask2
689      */
690 
691     /*
692      * viterbi mask 2  2nd set for per data rate puncturing
693      * four levels 0-3
694      *  - mask_select, 8 bits for rates (reg 67)
695      *  - mask (-27 to 27) (reg 98,0x9988 to 101,0x9994)
696      *      [1 2 2 1] for -9.6 or [1 2 1] for +16
697      */
698     cur_vit_mask = 6100;
699     upper        = bin + 120;
700     lower        = bin - 120;
701 
702     for (i = 0; i < 123; i++) {
703         if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) {
704             if ((abs(cur_vit_mask - bin)) < 75) {
705                 mask_amt = 1;
706             } else {
707                 mask_amt = 0;
708             }
709             if (cur_vit_mask < 0) {
710                 mask_m[abs(cur_vit_mask / 100)] = mask_amt;
711             } else {
712                 mask_p[cur_vit_mask / 100] = mask_amt;
713             }
714         }
715         cur_vit_mask -= 100;
716     }
717 
718     tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28)
719           | (mask_m[48] << 26) | (mask_m[49] << 24)
720           | (mask_m[50] << 22) | (mask_m[51] << 20)
721           | (mask_m[52] << 18) | (mask_m[53] << 16)
722           | (mask_m[54] << 14) | (mask_m[55] << 12)
723           | (mask_m[56] << 10) | (mask_m[57] <<  8)
724           | (mask_m[58] <<  6) | (mask_m[59] <<  4)
725           | (mask_m[60] <<  2) | (mask_m[61] <<  0);
726     OS_REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask);
727     OS_REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask);
728 
729     tmp_mask =             (mask_m[31] << 28)
730           | (mask_m[32] << 26) | (mask_m[33] << 24)
731           | (mask_m[34] << 22) | (mask_m[35] << 20)
732           | (mask_m[36] << 18) | (mask_m[37] << 16)
733           | (mask_m[48] << 14) | (mask_m[39] << 12)
734           | (mask_m[40] << 10) | (mask_m[41] <<  8)
735           | (mask_m[42] <<  6) | (mask_m[43] <<  4)
736           | (mask_m[44] <<  2) | (mask_m[45] <<  0);
737     OS_REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask);
738     OS_REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask);
739 
740     tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28)
741           | (mask_m[18] << 26) | (mask_m[18] << 24)
742           | (mask_m[20] << 22) | (mask_m[20] << 20)
743           | (mask_m[22] << 18) | (mask_m[22] << 16)
744           | (mask_m[24] << 14) | (mask_m[24] << 12)
745           | (mask_m[25] << 10) | (mask_m[26] <<  8)
746           | (mask_m[27] <<  6) | (mask_m[28] <<  4)
747           | (mask_m[29] <<  2) | (mask_m[30] <<  0);
748     OS_REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask);
749     OS_REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask);
750 
751     tmp_mask = (mask_m[ 0] << 30) | (mask_m[ 1] << 28)
752           | (mask_m[ 2] << 26) | (mask_m[ 3] << 24)
753           | (mask_m[ 4] << 22) | (mask_m[ 5] << 20)
754           | (mask_m[ 6] << 18) | (mask_m[ 7] << 16)
755           | (mask_m[ 8] << 14) | (mask_m[ 9] << 12)
756           | (mask_m[10] << 10) | (mask_m[11] <<  8)
757           | (mask_m[12] <<  6) | (mask_m[13] <<  4)
758           | (mask_m[14] <<  2) | (mask_m[15] <<  0);
759     OS_REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask);
760     OS_REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask);
761 
762     tmp_mask =             (mask_p[15] << 28)
763           | (mask_p[14] << 26) | (mask_p[13] << 24)
764           | (mask_p[12] << 22) | (mask_p[11] << 20)
765           | (mask_p[10] << 18) | (mask_p[ 9] << 16)
766           | (mask_p[ 8] << 14) | (mask_p[ 7] << 12)
767           | (mask_p[ 6] << 10) | (mask_p[ 5] <<  8)
768           | (mask_p[ 4] <<  6) | (mask_p[ 3] <<  4)
769           | (mask_p[ 2] <<  2) | (mask_p[ 1] <<  0);
770     OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask);
771     OS_REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask);
772 
773     tmp_mask =             (mask_p[30] << 28)
774           | (mask_p[29] << 26) | (mask_p[28] << 24)
775           | (mask_p[27] << 22) | (mask_p[26] << 20)
776           | (mask_p[25] << 18) | (mask_p[24] << 16)
777           | (mask_p[23] << 14) | (mask_p[22] << 12)
778           | (mask_p[21] << 10) | (mask_p[20] <<  8)
779           | (mask_p[19] <<  6) | (mask_p[18] <<  4)
780           | (mask_p[17] <<  2) | (mask_p[16] <<  0);
781     OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask);
782     OS_REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask);
783 
784     tmp_mask =             (mask_p[45] << 28)
785           | (mask_p[44] << 26) | (mask_p[43] << 24)
786           | (mask_p[42] << 22) | (mask_p[41] << 20)
787           | (mask_p[40] << 18) | (mask_p[39] << 16)
788           | (mask_p[38] << 14) | (mask_p[37] << 12)
789           | (mask_p[36] << 10) | (mask_p[35] <<  8)
790           | (mask_p[34] <<  6) | (mask_p[33] <<  4)
791           | (mask_p[32] <<  2) | (mask_p[31] <<  0);
792     OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask);
793     OS_REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask);
794 
795     tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28)
796           | (mask_p[59] << 26) | (mask_p[58] << 24)
797           | (mask_p[57] << 22) | (mask_p[56] << 20)
798           | (mask_p[55] << 18) | (mask_p[54] << 16)
799           | (mask_p[53] << 14) | (mask_p[52] << 12)
800           | (mask_p[51] << 10) | (mask_p[50] <<  8)
801           | (mask_p[49] <<  6) | (mask_p[48] <<  4)
802           | (mask_p[47] <<  2) | (mask_p[46] <<  0);
803     OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask);
804     OS_REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask);
805 }
806 
807 /*
808  * Fill all software cached or static hardware state information.
809  * Return failure if capabilities are to come from EEPROM and
810  * cannot be read.
811  */
812 static HAL_BOOL
813 ar9280FillCapabilityInfo(struct ath_hal *ah)
814 {
815 	HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
816 
817 	if (!ar5416FillCapabilityInfo(ah))
818 		return AH_FALSE;
819 	pCap->halNumGpioPins = 10;
820 	pCap->halWowSupport = AH_TRUE;
821 	pCap->halWowMatchPatternExact = AH_TRUE;
822 #if 0
823 	pCap->halWowMatchPatternDword = AH_TRUE;
824 #endif
825 	pCap->halCSTSupport = AH_TRUE;
826 	pCap->halRifsRxSupport = AH_TRUE;
827 	pCap->halRifsTxSupport = AH_TRUE;
828 	pCap->halRtsAggrLimit = 64*1024;	/* 802.11n max */
829 	pCap->halExtChanDfsSupport = AH_TRUE;
830 	pCap->halUseCombinedRadarRssi = AH_TRUE;
831 #if 0
832 	/* XXX bluetooth */
833 	pCap->halBtCoexSupport = AH_TRUE;
834 #endif
835 	pCap->halAutoSleepSupport = AH_FALSE;	/* XXX? */
836 	pCap->hal4kbSplitTransSupport = AH_FALSE;
837 	/* Disable this so Block-ACK works correctly */
838 	pCap->halHasRxSelfLinkedTail = AH_FALSE;
839 	pCap->halMbssidAggrSupport = AH_TRUE;
840 	pCap->hal4AddrAggrSupport = AH_TRUE;
841 
842 	if (AR_SREV_MERLIN_20(ah)) {
843 		pCap->halPSPollBroken = AH_FALSE;
844 		/*
845 		 * This just enables the support; it doesn't
846 		 * state 5ghz fast clock will always be used.
847 		 */
848 		pCap->halSupportsFastClock5GHz = AH_TRUE;
849 	}
850 	pCap->halRxStbcSupport = 1;
851 	pCap->halTxStbcSupport = 1;
852 	pCap->halEnhancedDfsSupport = AH_TRUE;
853 
854 	return AH_TRUE;
855 }
856 
857 /*
858  * This has been disabled - having the HAL flip chainmasks on/off
859  * when attempting to implement 11n disrupts things. For now, just
860  * leave this flipped off and worry about implementing TX diversity
861  * for legacy and MCS0-7 when 11n is fully functioning.
862  */
863 HAL_BOOL
864 ar9280SetAntennaSwitch(struct ath_hal *ah, HAL_ANT_SETTING settings)
865 {
866 #define ANTENNA0_CHAINMASK    0x1
867 #define ANTENNA1_CHAINMASK    0x2
868 #if 0
869 	struct ath_hal_5416 *ahp = AH5416(ah);
870 
871 	/* Antenna selection is done by setting the tx/rx chainmasks approp. */
872 	switch (settings) {
873 	case HAL_ANT_FIXED_A:
874 		/* Enable first antenna only */
875 		ahp->ah_tx_chainmask = ANTENNA0_CHAINMASK;
876 		ahp->ah_rx_chainmask = ANTENNA0_CHAINMASK;
877 		break;
878 	case HAL_ANT_FIXED_B:
879 		/* Enable second antenna only, after checking capability */
880 		if (AH_PRIVATE(ah)->ah_caps.halTxChainMask > ANTENNA1_CHAINMASK)
881 			ahp->ah_tx_chainmask = ANTENNA1_CHAINMASK;
882 		ahp->ah_rx_chainmask = ANTENNA1_CHAINMASK;
883 		break;
884 	case HAL_ANT_VARIABLE:
885 		/* Restore original chainmask settings */
886 		/* XXX */
887 		ahp->ah_tx_chainmask = AR9280_DEFAULT_TXCHAINMASK;
888 		ahp->ah_rx_chainmask = AR9280_DEFAULT_RXCHAINMASK;
889 		break;
890 	}
891 
892 	HALDEBUG(ah, HAL_DEBUG_ANY, "%s: settings=%d, tx/rx chainmask=%d/%d\n",
893 	    __func__, settings, ahp->ah_tx_chainmask, ahp->ah_rx_chainmask);
894 
895 #endif
896 	return AH_TRUE;
897 #undef ANTENNA0_CHAINMASK
898 #undef ANTENNA1_CHAINMASK
899 }
900 
901 static const char*
902 ar9280Probe(uint16_t vendorid, uint16_t devid)
903 {
904 	if (vendorid == ATHEROS_VENDOR_ID) {
905 		if (devid == AR9280_DEVID_PCI)
906 			return "Atheros 9220";
907 		if (devid == AR9280_DEVID_PCIE)
908 			return "Atheros 9280";
909 	}
910 	return AH_NULL;
911 }
912 AH_CHIP(AR9280, ar9280Probe, ar9280Attach);
913