ar9285_attach.c revision 235972
1190214Srpaulo/*
2190214Srpaulo * Copyright (c) 2008-2009 Sam Leffler, Errno Consulting
3190214Srpaulo * Copyright (c) 2008 Atheros Communications, Inc.
4190214Srpaulo *
5190214Srpaulo * Permission to use, copy, modify, and/or distribute this software for any
6190214Srpaulo * purpose with or without fee is hereby granted, provided that the above
7190214Srpaulo * copyright notice and this permission notice appear in all copies.
8190214Srpaulo *
9190214Srpaulo * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10190214Srpaulo * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11190214Srpaulo * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12190214Srpaulo * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13190214Srpaulo * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14190214Srpaulo * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15190214Srpaulo * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16190214Srpaulo *
17190214Srpaulo * $FreeBSD: head/sys/dev/ath/ath_hal/ar9002/ar9285_attach.c 235972 2012-05-25 05:01:27Z adrian $
18190214Srpaulo */
19190214Srpaulo#include "opt_ah.h"
20190214Srpaulo
21190214Srpaulo#include "ah.h"
22190214Srpaulo#include "ah_internal.h"
23190214Srpaulo#include "ah_devid.h"
24190214Srpaulo
25190214Srpaulo#include "ah_eeprom_v4k.h"		/* XXX for tx/rx gain */
26190214Srpaulo
27190214Srpaulo#include "ar9002/ar9280.h"
28190214Srpaulo#include "ar9002/ar9285.h"
29190214Srpaulo#include "ar5416/ar5416reg.h"
30190214Srpaulo#include "ar5416/ar5416phy.h"
31190214Srpaulo
32190214Srpaulo#include "ar9002/ar9285.ini"
33190214Srpaulo#include "ar9002/ar9285v2.ini"
34190214Srpaulo#include "ar9002/ar9280v2.ini"		/* XXX ini for tx/rx gain */
35190214Srpaulo
36190214Srpaulo#include "ar9002/ar9285_cal.h"
37190214Srpaulo#include "ar9002/ar9285_phy.h"
38190214Srpaulo#include "ar9002/ar9285_diversity.h"
39190214Srpaulo
40190214Srpaulostatic const HAL_PERCAL_DATA ar9280_iq_cal = {		/* single sample */
41190214Srpaulo	.calName = "IQ", .calType = IQ_MISMATCH_CAL,
42190214Srpaulo	.calNumSamples	= MIN_CAL_SAMPLES,
43190214Srpaulo	.calCountMax	= PER_MAX_LOG_COUNT,
44190214Srpaulo	.calCollect	= ar5416IQCalCollect,
45190214Srpaulo	.calPostProc	= ar5416IQCalibration
46190214Srpaulo};
47190214Srpaulostatic const HAL_PERCAL_DATA ar9280_adc_gain_cal = {	/* single sample */
48190214Srpaulo	.calName = "ADC Gain", .calType = ADC_GAIN_CAL,
49190214Srpaulo	.calNumSamples	= MIN_CAL_SAMPLES,
50190214Srpaulo	.calCountMax	= PER_MIN_LOG_COUNT,
51190214Srpaulo	.calCollect	= ar5416AdcGainCalCollect,
52190214Srpaulo	.calPostProc	= ar5416AdcGainCalibration
53190214Srpaulo};
54190214Srpaulostatic const HAL_PERCAL_DATA ar9280_adc_dc_cal = {	/* single sample */
55190214Srpaulo	.calName = "ADC DC", .calType = ADC_DC_CAL,
56190214Srpaulo	.calNumSamples	= MIN_CAL_SAMPLES,
57190214Srpaulo	.calCountMax	= PER_MIN_LOG_COUNT,
58190214Srpaulo	.calCollect	= ar5416AdcDcCalCollect,
59214518Srpaulo	.calPostProc	= ar5416AdcDcCalibration
60235426Sdelphij};
61235426Sdelphijstatic const HAL_PERCAL_DATA ar9280_adc_init_dc_cal = {
62235426Sdelphij	.calName = "ADC Init DC", .calType = ADC_DC_INIT_CAL,
63235426Sdelphij	.calNumSamples	= MIN_CAL_SAMPLES,
64235426Sdelphij	.calCountMax	= INIT_LOG_COUNT,
65235426Sdelphij	.calCollect	= ar5416AdcDcCalCollect,
66235426Sdelphij	.calPostProc	= ar5416AdcDcCalibration
67214518Srpaulo};
68235426Sdelphij
69190214Srpaulostatic void ar9285ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore,
70214518Srpaulo		HAL_BOOL power_off);
71214518Srpaulostatic void ar9285DisablePCIE(struct ath_hal *ah);
72214518Srpaulostatic HAL_BOOL ar9285FillCapabilityInfo(struct ath_hal *ah);
73214518Srpaulostatic void ar9285WriteIni(struct ath_hal *ah,
74214518Srpaulo	const struct ieee80211_channel *chan);
75190214Srpaulo
76190214Srpaulostatic void
77190214Srpauloar9285AniSetup(struct ath_hal *ah)
78190214Srpaulo{
79190214Srpaulo	/*
80190214Srpaulo	 * These are the parameters from the AR5416 ANI code;
81190214Srpaulo	 * they likely need quite a bit of adjustment for the
82190214Srpaulo	 * AR9285.
83190214Srpaulo	 */
84190214Srpaulo        static const struct ar5212AniParams aniparams = {
85190214Srpaulo                .maxNoiseImmunityLevel  = 4,    /* levels 0..4 */
86190214Srpaulo                .totalSizeDesired       = { -55, -55, -55, -55, -62 },
87190214Srpaulo                .coarseHigh             = { -14, -14, -14, -14, -12 },
88190214Srpaulo                .coarseLow              = { -64, -64, -64, -64, -70 },
89190214Srpaulo                .firpwr                 = { -78, -78, -78, -78, -80 },
90190214Srpaulo                .maxSpurImmunityLevel   = 2,
91190214Srpaulo                .cycPwrThr1             = { 2, 4, 6 },
92190214Srpaulo                .maxFirstepLevel        = 2,    /* levels 0..2 */
93190214Srpaulo                .firstep                = { 0, 4, 8 },
94190214Srpaulo                .ofdmTrigHigh           = 500,
95190214Srpaulo                .ofdmTrigLow            = 200,
96190214Srpaulo                .cckTrigHigh            = 200,
97190214Srpaulo                .cckTrigLow             = 100,
98190214Srpaulo                .rssiThrHigh            = 40,
99190214Srpaulo                .rssiThrLow             = 7,
100190214Srpaulo                .period                 = 100,
101190214Srpaulo        };
102190214Srpaulo	/* NB: disable ANI noise immmunity for reliable RIFS rx */
103190214Srpaulo	AH5416(ah)->ah_ani_function &= ~(1 << HAL_ANI_NOISE_IMMUNITY_LEVEL);
104190214Srpaulo
105190214Srpaulo        ar5416AniAttach(ah, &aniparams, &aniparams, AH_TRUE);
106190214Srpaulo}
107190214Srpaulo
108190214Srpaulo/*
109190214Srpaulo * Attach for an AR9285 part.
110190214Srpaulo */
111190214Srpaulostatic struct ath_hal *
112190214Srpauloar9285Attach(uint16_t devid, HAL_SOFTC sc,
113190214Srpaulo	HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata,
114190214Srpaulo	HAL_STATUS *status)
115190214Srpaulo{
116190214Srpaulo	struct ath_hal_9285 *ahp9285;
117190214Srpaulo	struct ath_hal_5212 *ahp;
118190214Srpaulo	struct ath_hal *ah;
119190214Srpaulo	uint32_t val;
120276768Sdelphij	HAL_STATUS ecode;
121276768Sdelphij	HAL_BOOL rfStatus;
122276768Sdelphij
123276768Sdelphij	HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n",
124276768Sdelphij	    __func__, sc, (void*) st, (void*) sh);
125276768Sdelphij
126276768Sdelphij	/* NB: memory is returned zero'd */
127276768Sdelphij	ahp9285 = ath_hal_malloc(sizeof (struct ath_hal_9285));
128276768Sdelphij	if (ahp9285 == AH_NULL) {
129276768Sdelphij		HALDEBUG(AH_NULL, HAL_DEBUG_ANY,
130190214Srpaulo		    "%s: cannot allocate memory for state block\n", __func__);
131190214Srpaulo		*status = HAL_ENOMEM;
132190214Srpaulo		return AH_NULL;
133190214Srpaulo	}
134190214Srpaulo	ahp = AH5212(ahp9285);
135190214Srpaulo	ah = &ahp->ah_priv.h;
136190214Srpaulo
137190214Srpaulo	ar5416InitState(AH5416(ah), devid, sc, st, sh, status);
138190214Srpaulo
139190214Srpaulo	/*
140190214Srpaulo	 * Use the "local" EEPROM data given to us by the higher layers.
141190214Srpaulo	 * This is a private copy out of system flash. The Linux ath9k
142190214Srpaulo	 * commit for the initial AR9130 support mentions MMIO flash
143190214Srpaulo	 * access is "unreliable." -adrian
144190214Srpaulo	 */
145190214Srpaulo	if (eepromdata != AH_NULL) {
146190214Srpaulo		AH_PRIVATE(ah)->ah_eepromRead = ath_hal_EepromDataRead;
147190214Srpaulo		AH_PRIVATE(ah)->ah_eepromWrite = NULL;
148190214Srpaulo		ah->ah_eepromdata = eepromdata;
149190214Srpaulo	}
150190214Srpaulo
151190214Srpaulo	/* XXX override with 9285 specific state */
152190214Srpaulo	/* override 5416 methods for our needs */
153190214Srpaulo	AH5416(ah)->ah_initPLL = ar9280InitPLL;
154190214Srpaulo
155190214Srpaulo	ah->ah_setAntennaSwitch		= ar9285SetAntennaSwitch;
156190214Srpaulo	ah->ah_configPCIE		= ar9285ConfigPCIE;
157251129Sdelphij	ah->ah_disablePCIE		= ar9285DisablePCIE;
158190214Srpaulo	ah->ah_setTxPower		= ar9285SetTransmitPower;
159190214Srpaulo	ah->ah_setBoardValues		= ar9285SetBoardValues;
160190214Srpaulo
161190214Srpaulo	AH5416(ah)->ah_cal.iqCalData.calData = &ar9280_iq_cal;
162214518Srpaulo	AH5416(ah)->ah_cal.adcGainCalData.calData = &ar9280_adc_gain_cal;
163214518Srpaulo	AH5416(ah)->ah_cal.adcDcCalData.calData = &ar9280_adc_dc_cal;
164214518Srpaulo	AH5416(ah)->ah_cal.adcDcCalInitData.calData = &ar9280_adc_init_dc_cal;
165190214Srpaulo	AH5416(ah)->ah_cal.suppCals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL;
166214518Srpaulo
167214518Srpaulo	AH5416(ah)->ah_spurMitigate	= ar9280SpurMitigate;
168214518Srpaulo	AH5416(ah)->ah_writeIni		= ar9285WriteIni;
169214518Srpaulo	AH5416(ah)->ah_rx_chainmask	= AR9285_DEFAULT_RXCHAINMASK;
170214518Srpaulo	AH5416(ah)->ah_tx_chainmask	= AR9285_DEFAULT_TXCHAINMASK;
171190214Srpaulo
172214518Srpaulo	ahp->ah_maxTxTrigLev		= MAX_TX_FIFO_THRESHOLD >> 1;
173214518Srpaulo
174190214Srpaulo	if (!ar5416SetResetReg(ah, HAL_RESET_POWER_ON)) {
175214518Srpaulo		/* reset chip */
176214518Srpaulo		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't reset chip\n",
177214518Srpaulo		    __func__);
178214518Srpaulo		ecode = HAL_EIO;
179214518Srpaulo		goto bad;
180214518Srpaulo	}
181214518Srpaulo
182214518Srpaulo	if (!ar5416SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) {
183190214Srpaulo		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't wakeup chip\n",
184190214Srpaulo		    __func__);
185214518Srpaulo		ecode = HAL_EIO;
186214518Srpaulo		goto bad;
187214518Srpaulo	}
188214518Srpaulo	/* Read Revisions from Chips before taking out of reset */
189214518Srpaulo	val = OS_REG_READ(ah, AR_SREV);
190214518Srpaulo	HALDEBUG(ah, HAL_DEBUG_ATTACH,
191214518Srpaulo	    "%s: ID 0x%x VERSION 0x%x TYPE 0x%x REVISION 0x%x\n",
192214518Srpaulo	    __func__, MS(val, AR_XSREV_ID), MS(val, AR_XSREV_VERSION),
193214518Srpaulo	    MS(val, AR_XSREV_TYPE), MS(val, AR_XSREV_REVISION));
194214518Srpaulo	/* NB: include chip type to differentiate from pre-Sowl versions */
195214518Srpaulo	AH_PRIVATE(ah)->ah_macVersion =
196214518Srpaulo	    (val & AR_XSREV_VERSION) >> AR_XSREV_TYPE_S;
197214518Srpaulo	AH_PRIVATE(ah)->ah_macRev = MS(val, AR_XSREV_REVISION);
198214518Srpaulo	AH_PRIVATE(ah)->ah_ispcie = (val & AR_XSREV_TYPE_HOST_MODE) == 0;
199214518Srpaulo
200214518Srpaulo	/* setup common ini data; rf backends handle remainder */
201214518Srpaulo	if (AR_SREV_KITE_12_OR_LATER(ah)) {
202214518Srpaulo		HAL_INI_INIT(&ahp->ah_ini_modes, ar9285Modes_v2, 6);
203214518Srpaulo		HAL_INI_INIT(&ahp->ah_ini_common, ar9285Common_v2, 2);
204214518Srpaulo		HAL_INI_INIT(&AH5416(ah)->ah_ini_pcieserdes,
205214518Srpaulo		    ar9285PciePhy_clkreq_always_on_L1_v2, 2);
206214518Srpaulo	} else {
207214518Srpaulo		HAL_INI_INIT(&ahp->ah_ini_modes, ar9285Modes, 6);
208190214Srpaulo		HAL_INI_INIT(&ahp->ah_ini_common, ar9285Common, 2);
209190214Srpaulo		HAL_INI_INIT(&AH5416(ah)->ah_ini_pcieserdes,
210190214Srpaulo		    ar9285PciePhy_clkreq_always_on_L1, 2);
211190214Srpaulo	}
212190214Srpaulo	ar5416AttachPCIE(ah);
213276768Sdelphij
214190214Srpaulo	/* Attach methods that require MAC version/revision info */
215190214Srpaulo	if (AR_SREV_KITE_12_OR_LATER(ah))
216190214Srpaulo		AH5416(ah)->ah_cal_initcal      = ar9285InitCalHardware;
217190214Srpaulo	if (AR_SREV_KITE_11_OR_LATER(ah))
218276768Sdelphij		AH5416(ah)->ah_cal_pacal        = ar9002_hw_pa_cal;
219276768Sdelphij
220214518Srpaulo	ecode = ath_hal_v4kEepromAttach(ah);
221276768Sdelphij	if (ecode != HAL_OK)
222190214Srpaulo		goto bad;
223190214Srpaulo
224276768Sdelphij	if (!ar5416ChipReset(ah, AH_NULL)) {	/* reset chip */
225276768Sdelphij		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n",
226214518Srpaulo		    __func__);
227214518Srpaulo		ecode = HAL_EIO;
228214518Srpaulo		goto bad;
229214518Srpaulo	}
230214518Srpaulo
231214518Srpaulo	AH_PRIVATE(ah)->ah_phyRev = OS_REG_READ(ah, AR_PHY_CHIP_ID);
232214518Srpaulo
233214518Srpaulo	if (!ar5212ChipTest(ah)) {
234214518Srpaulo		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: hardware self-test failed\n",
235214518Srpaulo		    __func__);
236214518Srpaulo		ecode = HAL_ESELFTEST;
237214518Srpaulo		goto bad;
238214518Srpaulo	}
239214518Srpaulo
240214518Srpaulo	/*
241214518Srpaulo	 * Set correct Baseband to analog shift
242214518Srpaulo	 * setting to access analog chips.
243214518Srpaulo	 */
244214518Srpaulo	OS_REG_WRITE(ah, AR_PHY(0), 0x00000007);
245214518Srpaulo
246214518Srpaulo	/* Read Radio Chip Rev Extract */
247214518Srpaulo	AH_PRIVATE(ah)->ah_analog5GhzRev = ar5416GetRadioRev(ah);
248214518Srpaulo	switch (AH_PRIVATE(ah)->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR) {
249214518Srpaulo        case AR_RAD2133_SREV_MAJOR:	/* Sowl: 2G/3x3 */
250214518Srpaulo	case AR_RAD5133_SREV_MAJOR:	/* Sowl: 2+5G/3x3 */
251214518Srpaulo		break;
252214518Srpaulo	default:
253214518Srpaulo		if (AH_PRIVATE(ah)->ah_analog5GhzRev == 0) {
254214518Srpaulo			AH_PRIVATE(ah)->ah_analog5GhzRev =
255214518Srpaulo				AR_RAD5133_SREV_MAJOR;
256214518Srpaulo			break;
257214518Srpaulo		}
258214518Srpaulo#ifdef AH_DEBUG
259214518Srpaulo		HALDEBUG(ah, HAL_DEBUG_ANY,
260214518Srpaulo		    "%s: 5G Radio Chip Rev 0x%02X is not supported by "
261214518Srpaulo		    "this driver\n", __func__,
262214518Srpaulo		    AH_PRIVATE(ah)->ah_analog5GhzRev);
263214518Srpaulo		ecode = HAL_ENOTSUPP;
264214518Srpaulo		goto bad;
265214518Srpaulo#endif
266214518Srpaulo	}
267214518Srpaulo	rfStatus = ar9285RfAttach(ah, &ecode);
268214518Srpaulo	if (!rfStatus) {
269214518Srpaulo		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RF setup failed, status %u\n",
270214518Srpaulo		    __func__, ecode);
271214518Srpaulo		goto bad;
272214518Srpaulo	}
273214518Srpaulo
274214518Srpaulo	HAL_INI_INIT(&ahp9285->ah_ini_rxgain, ar9280Modes_original_rxgain_v2,
275214518Srpaulo	    6);
276214518Srpaulo
277214518Srpaulo	if (AR_SREV_9285E_20(ah))
278214518Srpaulo		ath_hal_printf(ah, "[ath] AR9285E_20 detected; using XE TX gain tables\n");
279214518Srpaulo
280214518Srpaulo	/* setup txgain table */
281214518Srpaulo	switch (ath_hal_eepromGet(ah, AR_EEP_TXGAIN_TYPE, AH_NULL)) {
282214518Srpaulo	case AR5416_EEP_TXGAIN_HIGH_POWER:
283214518Srpaulo		if (AR_SREV_9285E_20(ah))
284214518Srpaulo			HAL_INI_INIT(&ahp9285->ah_ini_txgain,
285214518Srpaulo			    ar9285Modes_XE2_0_high_power, 6);
286214518Srpaulo		else
287214518Srpaulo			HAL_INI_INIT(&ahp9285->ah_ini_txgain,
288214518Srpaulo			    ar9285Modes_high_power_tx_gain_v2, 6);
289214518Srpaulo		break;
290214518Srpaulo	case AR5416_EEP_TXGAIN_ORIG:
291214518Srpaulo		if (AR_SREV_9285E_20(ah))
292214518Srpaulo			HAL_INI_INIT(&ahp9285->ah_ini_txgain,
293214518Srpaulo			    ar9285Modes_XE2_0_normal_power, 6);
294276768Sdelphij		else
295214518Srpaulo			HAL_INI_INIT(&ahp9285->ah_ini_txgain,
296190214Srpaulo			    ar9285Modes_original_tx_gain_v2, 6);
297251129Sdelphij		break;
298190214Srpaulo	default:
299251129Sdelphij		HALASSERT(AH_FALSE);
300251129Sdelphij		goto bad;		/* XXX ? try to continue */
301251129Sdelphij	}
302190214Srpaulo
303190214Srpaulo	/*
304251129Sdelphij	 * Got everything we need now to setup the capabilities.
305251129Sdelphij	 */
306251129Sdelphij	if (!ar9285FillCapabilityInfo(ah)) {
307251129Sdelphij		ecode = HAL_EEREAD;
308251129Sdelphij		goto bad;
309251129Sdelphij	}
310251129Sdelphij
311251129Sdelphij	/* Print out whether the EEPROM settings enable AR9285 diversity */
312251129Sdelphij	if (ar9285_check_div_comb(ah)) {
313251129Sdelphij		ath_hal_printf(ah, "[ath] Enabling diversity for Kite\n");
314251129Sdelphij		ah->ah_rxAntCombDiversity = ar9285_ant_comb_scan;
315251129Sdelphij	}
316251129Sdelphij
317251129Sdelphij	/* Disable 11n for the AR2427 */
318251129Sdelphij	if (devid == AR2427_DEVID_PCIE)
319251129Sdelphij		AH_PRIVATE(ah)->ah_caps.halHTSupport = AH_FALSE;
320251129Sdelphij
321251129Sdelphij	ecode = ath_hal_eepromGet(ah, AR_EEP_MACADDR, ahp->ah_macaddr);
322251129Sdelphij	if (ecode != HAL_OK) {
323251129Sdelphij		HALDEBUG(ah, HAL_DEBUG_ANY,
324251129Sdelphij		    "%s: error getting mac address from EEPROM\n", __func__);
325251129Sdelphij		goto bad;
326251129Sdelphij        }
327251129Sdelphij	/* XXX How about the serial number ? */
328251129Sdelphij	/* Read Reg Domain */
329251129Sdelphij	AH_PRIVATE(ah)->ah_currentRD =
330251129Sdelphij	    ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, AH_NULL);
331276768Sdelphij	/*
332190214Srpaulo         * For Kite and later chipsets, the following bits are not
333190214Srpaulo	 * programmed in EEPROM and so are set as enabled always.
334190214Srpaulo	 */
335190214Srpaulo	AH_PRIVATE(ah)->ah_currentRDext = AR9285_RDEXT_DEFAULT;
336190214Srpaulo
337190214Srpaulo	/*
338190214Srpaulo	 * ah_miscMode is populated by ar5416FillCapabilityInfo()
339190214Srpaulo	 * starting from griffin. Set here to make sure that
340190214Srpaulo	 * AR_MISC_MODE_MIC_NEW_LOC_ENABLE is set before a GTK is
341190214Srpaulo	 * placed into hardware.
342276768Sdelphij	 */
343190214Srpaulo	if (ahp->ah_miscMode != 0)
344190214Srpaulo		OS_REG_WRITE(ah, AR_MISC_MODE, OS_REG_READ(ah, AR_MISC_MODE) | ahp->ah_miscMode);
345190214Srpaulo
346190214Srpaulo	ar9285AniSetup(ah);			/* Anti Noise Immunity */
347190214Srpaulo
348190214Srpaulo	/* Setup noise floor min/max/nominal values */
349190214Srpaulo	AH5416(ah)->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_9285_2GHZ;
350190214Srpaulo	AH5416(ah)->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_9285_2GHZ;
351235426Sdelphij	AH5416(ah)->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9285_2GHZ;
352190214Srpaulo	/* XXX no 5ghz values? */
353190214Srpaulo
354190214Srpaulo	ar5416InitNfHistBuff(AH5416(ah)->ah_cal.nfCalHist);
355190214Srpaulo
356190214Srpaulo	HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n", __func__);
357190214Srpaulo
358276768Sdelphij	return ah;
359190214Srpaulobad:
360190214Srpaulo	if (ah != AH_NULL)
361190214Srpaulo		ah->ah_detach(ah);
362190214Srpaulo	if (status)
363190214Srpaulo		*status = ecode;
364190214Srpaulo	return AH_NULL;
365190214Srpaulo}
366276768Sdelphij
367190214Srpaulostatic void
368190214Srpauloar9285ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore, HAL_BOOL power_off)
369190214Srpaulo{
370190214Srpaulo	if (AH_PRIVATE(ah)->ah_ispcie && !restore) {
371190214Srpaulo		ath_hal_ini_write(ah, &AH5416(ah)->ah_ini_pcieserdes, 1, 0);
372190214Srpaulo		OS_DELAY(1000);
373190214Srpaulo		OS_REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
374214518Srpaulo		OS_REG_WRITE(ah, AR_WA, AR9285_WA_DEFAULT);
375190214Srpaulo	}
376190214Srpaulo}
377190214Srpaulo
378190214Srpaulostatic void
379190214Srpauloar9285DisablePCIE(struct ath_hal *ah)
380214518Srpaulo{
381190214Srpaulo	/* XXX TODO */
382190214Srpaulo}
383190214Srpaulo
384276768Sdelphijstatic void
385276768Sdelphijar9285WriteIni(struct ath_hal *ah, const struct ieee80211_channel *chan)
386276768Sdelphij{
387190214Srpaulo	u_int modesIndex, freqIndex;
388190214Srpaulo	int regWrites = 0;
389190214Srpaulo
390190214Srpaulo	/* Setup the indices for the next set of register array writes */
391190214Srpaulo	/* XXX Ignore 11n dynamic mode on the AR5416 for the moment */
392190214Srpaulo	freqIndex = 2;
393190214Srpaulo	if (IEEE80211_IS_CHAN_HT40(chan))
394190214Srpaulo		modesIndex = 3;
395190214Srpaulo	else if (IEEE80211_IS_CHAN_108G(chan))
396190214Srpaulo		modesIndex = 5;
397190214Srpaulo	else
398190214Srpaulo		modesIndex = 4;
399276768Sdelphij
400276768Sdelphij	/* Set correct Baseband to analog shift setting to access analog chips. */
401276768Sdelphij	OS_REG_WRITE(ah, AR_PHY(0), 0x00000007);
402190214Srpaulo	OS_REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC);
403190214Srpaulo	regWrites = ath_hal_ini_write(ah, &AH5212(ah)->ah_ini_modes,
404190214Srpaulo	    modesIndex, regWrites);
405276768Sdelphij	if (AR_SREV_KITE_12_OR_LATER(ah)) {
406190214Srpaulo		regWrites = ath_hal_ini_write(ah, &AH9285(ah)->ah_ini_txgain,
407190214Srpaulo		    modesIndex, regWrites);
408190214Srpaulo	}
409214518Srpaulo	regWrites = ath_hal_ini_write(ah, &AH5212(ah)->ah_ini_common,
410214518Srpaulo	    1, regWrites);
411214518Srpaulo}
412214518Srpaulo
413214518Srpaulo/*
414214518Srpaulo * Fill all software cached or static hardware state information.
415276768Sdelphij * Return failure if capabilities are to come from EEPROM and
416214518Srpaulo * cannot be read.
417214518Srpaulo */
418214518Srpaulostatic HAL_BOOL
419214518Srpauloar9285FillCapabilityInfo(struct ath_hal *ah)
420214518Srpaulo{
421214518Srpaulo	HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
422214518Srpaulo
423214518Srpaulo	if (!ar5416FillCapabilityInfo(ah))
424190214Srpaulo		return AH_FALSE;
425214518Srpaulo	pCap->halNumGpioPins = 12;
426214518Srpaulo	pCap->halWowSupport = AH_TRUE;
427214518Srpaulo	pCap->halWowMatchPatternExact = AH_TRUE;
428214518Srpaulo#if 0
429214518Srpaulo	pCap->halWowMatchPatternDword = AH_TRUE;
430214518Srpaulo#endif
431214518Srpaulo	/* AR9285 has 2 antennas but is a 1x1 stream device */
432214518Srpaulo	pCap->halTxStreams = 1;
433214518Srpaulo	pCap->halRxStreams = 1;
434190214Srpaulo
435190214Srpaulo	pCap->halCSTSupport = AH_TRUE;
436190214Srpaulo	pCap->halRifsRxSupport = AH_TRUE;
437190214Srpaulo	pCap->halRifsTxSupport = AH_TRUE;
438190214Srpaulo	pCap->halRtsAggrLimit = 64*1024;	/* 802.11n max */
439190214Srpaulo	pCap->halExtChanDfsSupport = AH_TRUE;
440190214Srpaulo	pCap->halUseCombinedRadarRssi = AH_TRUE;
441190214Srpaulo#if 0
442190214Srpaulo	/* XXX bluetooth */
443190214Srpaulo	pCap->halBtCoexSupport = AH_TRUE;
444190214Srpaulo#endif
445190214Srpaulo	pCap->halAutoSleepSupport = AH_FALSE;	/* XXX? */
446190214Srpaulo	pCap->hal4kbSplitTransSupport = AH_FALSE;
447190214Srpaulo	/* Disable this so Block-ACK works correctly */
448190214Srpaulo	pCap->halHasRxSelfLinkedTail = AH_FALSE;
449190214Srpaulo	pCap->halMbssidAggrSupport = AH_TRUE;
450214518Srpaulo	pCap->hal4AddrAggrSupport = AH_TRUE;
451190214Srpaulo
452190214Srpaulo	if (AR_SREV_KITE_12_OR_LATER(ah))
453190214Srpaulo		pCap->halPSPollBroken = AH_FALSE;
454190214Srpaulo
455190214Srpaulo	/* Only RX STBC supported */
456190214Srpaulo	pCap->halRxStbcSupport = 1;
457190214Srpaulo	pCap->halTxStbcSupport = 0;
458190214Srpaulo
459190214Srpaulo	return AH_TRUE;
460190214Srpaulo}
461190214Srpaulo
462190214Srpaulostatic const char*
463190214Srpauloar9285Probe(uint16_t vendorid, uint16_t devid)
464190214Srpaulo{
465190214Srpaulo	if (vendorid == ATHEROS_VENDOR_ID && devid == AR9285_DEVID_PCIE)
466190214Srpaulo		return "Atheros 9285";
467190214Srpaulo	if (vendorid == ATHEROS_VENDOR_ID && (devid == AR2427_DEVID_PCIE))
468190214Srpaulo		return "Atheros 2427";
469190214Srpaulo
470190214Srpaulo	return AH_NULL;
471190214Srpaulo}
472190214SrpauloAH_CHIP(AR9285, ar9285Probe, ar9285Attach);
473190214Srpaulo