xref: /freebsd/sys/dev/ath/ath_hal/ar5212/ar5212_attach.c (revision 5dcd9c10612684d1c823670cbb5b4715028784e7)
1 /*
2  * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting
3  * Copyright (c) 2002-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 "ar5212/ar5212.h"
26 #include "ar5212/ar5212reg.h"
27 #include "ar5212/ar5212phy.h"
28 
29 #define AH_5212_COMMON
30 #include "ar5212/ar5212.ini"
31 
32 static void ar5212ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore);
33 static void ar5212DisablePCIE(struct ath_hal *ah);
34 
35 static const struct ath_hal_private ar5212hal = {{
36 	.ah_magic			= AR5212_MAGIC,
37 
38 	.ah_getRateTable		= ar5212GetRateTable,
39 	.ah_detach			= ar5212Detach,
40 
41 	/* Reset Functions */
42 	.ah_reset			= ar5212Reset,
43 	.ah_phyDisable			= ar5212PhyDisable,
44 	.ah_disable			= ar5212Disable,
45 	.ah_configPCIE			= ar5212ConfigPCIE,
46 	.ah_disablePCIE			= ar5212DisablePCIE,
47 	.ah_setPCUConfig		= ar5212SetPCUConfig,
48 	.ah_perCalibration		= ar5212PerCalibration,
49 	.ah_perCalibrationN		= ar5212PerCalibrationN,
50 	.ah_resetCalValid		= ar5212ResetCalValid,
51 	.ah_setTxPowerLimit		= ar5212SetTxPowerLimit,
52 	.ah_getChanNoise		= ath_hal_getChanNoise,
53 
54 	/* Transmit functions */
55 	.ah_updateTxTrigLevel		= ar5212UpdateTxTrigLevel,
56 	.ah_setupTxQueue		= ar5212SetupTxQueue,
57 	.ah_setTxQueueProps             = ar5212SetTxQueueProps,
58 	.ah_getTxQueueProps             = ar5212GetTxQueueProps,
59 	.ah_releaseTxQueue		= ar5212ReleaseTxQueue,
60 	.ah_resetTxQueue		= ar5212ResetTxQueue,
61 	.ah_getTxDP			= ar5212GetTxDP,
62 	.ah_setTxDP			= ar5212SetTxDP,
63 	.ah_numTxPending		= ar5212NumTxPending,
64 	.ah_startTxDma			= ar5212StartTxDma,
65 	.ah_stopTxDma			= ar5212StopTxDma,
66 	.ah_setupTxDesc			= ar5212SetupTxDesc,
67 	.ah_setupXTxDesc		= ar5212SetupXTxDesc,
68 	.ah_fillTxDesc			= ar5212FillTxDesc,
69 	.ah_procTxDesc			= ar5212ProcTxDesc,
70 	.ah_getTxIntrQueue		= ar5212GetTxIntrQueue,
71 	.ah_reqTxIntrDesc 		= ar5212IntrReqTxDesc,
72 	.ah_getTxCompletionRates	= ar5212GetTxCompletionRates,
73 
74 	/* RX Functions */
75 	.ah_getRxDP			= ar5212GetRxDP,
76 	.ah_setRxDP			= ar5212SetRxDP,
77 	.ah_enableReceive		= ar5212EnableReceive,
78 	.ah_stopDmaReceive		= ar5212StopDmaReceive,
79 	.ah_startPcuReceive		= ar5212StartPcuReceive,
80 	.ah_stopPcuReceive		= ar5212StopPcuReceive,
81 	.ah_setMulticastFilter		= ar5212SetMulticastFilter,
82 	.ah_setMulticastFilterIndex	= ar5212SetMulticastFilterIndex,
83 	.ah_clrMulticastFilterIndex	= ar5212ClrMulticastFilterIndex,
84 	.ah_getRxFilter			= ar5212GetRxFilter,
85 	.ah_setRxFilter			= ar5212SetRxFilter,
86 	.ah_setupRxDesc			= ar5212SetupRxDesc,
87 	.ah_procRxDesc			= ar5212ProcRxDesc,
88 	.ah_rxMonitor			= ar5212RxMonitor,
89 	.ah_aniPoll			= ar5212AniPoll,
90 	.ah_procMibEvent		= ar5212ProcessMibIntr,
91 
92 	/* Misc Functions */
93 	.ah_getCapability		= ar5212GetCapability,
94 	.ah_setCapability		= ar5212SetCapability,
95 	.ah_getDiagState		= ar5212GetDiagState,
96 	.ah_getMacAddress		= ar5212GetMacAddress,
97 	.ah_setMacAddress		= ar5212SetMacAddress,
98 	.ah_getBssIdMask		= ar5212GetBssIdMask,
99 	.ah_setBssIdMask		= ar5212SetBssIdMask,
100 	.ah_setRegulatoryDomain		= ar5212SetRegulatoryDomain,
101 	.ah_setLedState			= ar5212SetLedState,
102 	.ah_writeAssocid		= ar5212WriteAssocid,
103 	.ah_gpioCfgInput		= ar5212GpioCfgInput,
104 	.ah_gpioCfgOutput		= ar5212GpioCfgOutput,
105 	.ah_gpioGet			= ar5212GpioGet,
106 	.ah_gpioSet			= ar5212GpioSet,
107 	.ah_gpioSetIntr			= ar5212GpioSetIntr,
108 	.ah_getTsf32			= ar5212GetTsf32,
109 	.ah_getTsf64			= ar5212GetTsf64,
110 	.ah_resetTsf			= ar5212ResetTsf,
111 	.ah_detectCardPresent		= ar5212DetectCardPresent,
112 	.ah_updateMibCounters		= ar5212UpdateMibCounters,
113 	.ah_getRfGain			= ar5212GetRfgain,
114 	.ah_getDefAntenna		= ar5212GetDefAntenna,
115 	.ah_setDefAntenna		= ar5212SetDefAntenna,
116 	.ah_getAntennaSwitch		= ar5212GetAntennaSwitch,
117 	.ah_setAntennaSwitch		= ar5212SetAntennaSwitch,
118 	.ah_setSifsTime			= ar5212SetSifsTime,
119 	.ah_getSifsTime			= ar5212GetSifsTime,
120 	.ah_setSlotTime			= ar5212SetSlotTime,
121 	.ah_getSlotTime			= ar5212GetSlotTime,
122 	.ah_setAckTimeout		= ar5212SetAckTimeout,
123 	.ah_getAckTimeout		= ar5212GetAckTimeout,
124 	.ah_setAckCTSRate		= ar5212SetAckCTSRate,
125 	.ah_getAckCTSRate		= ar5212GetAckCTSRate,
126 	.ah_setCTSTimeout		= ar5212SetCTSTimeout,
127 	.ah_getCTSTimeout		= ar5212GetCTSTimeout,
128 	.ah_setDecompMask               = ar5212SetDecompMask,
129 	.ah_setCoverageClass            = ar5212SetCoverageClass,
130 
131 	/* Key Cache Functions */
132 	.ah_getKeyCacheSize		= ar5212GetKeyCacheSize,
133 	.ah_resetKeyCacheEntry		= ar5212ResetKeyCacheEntry,
134 	.ah_isKeyCacheEntryValid	= ar5212IsKeyCacheEntryValid,
135 	.ah_setKeyCacheEntry		= ar5212SetKeyCacheEntry,
136 	.ah_setKeyCacheEntryMac		= ar5212SetKeyCacheEntryMac,
137 
138 	/* Power Management Functions */
139 	.ah_setPowerMode		= ar5212SetPowerMode,
140 	.ah_getPowerMode		= ar5212GetPowerMode,
141 
142 	/* Beacon Functions */
143 	.ah_setBeaconTimers		= ar5212SetBeaconTimers,
144 	.ah_beaconInit			= ar5212BeaconInit,
145 	.ah_setStationBeaconTimers	= ar5212SetStaBeaconTimers,
146 	.ah_resetStationBeaconTimers	= ar5212ResetStaBeaconTimers,
147 
148 	/* Interrupt Functions */
149 	.ah_isInterruptPending		= ar5212IsInterruptPending,
150 	.ah_getPendingInterrupts	= ar5212GetPendingInterrupts,
151 	.ah_getInterrupts		= ar5212GetInterrupts,
152 	.ah_setInterrupts		= ar5212SetInterrupts },
153 
154 	.ah_getChannelEdges		= ar5212GetChannelEdges,
155 	.ah_getWirelessModes		= ar5212GetWirelessModes,
156 	.ah_eepromRead			= ar5212EepromRead,
157 #ifdef AH_SUPPORT_WRITE_EEPROM
158 	.ah_eepromWrite			= ar5212EepromWrite,
159 #endif
160 	.ah_getChipPowerLimits		= ar5212GetChipPowerLimits,
161 };
162 
163 uint32_t
164 ar5212GetRadioRev(struct ath_hal *ah)
165 {
166 	uint32_t val;
167 	int i;
168 
169 	/* Read Radio Chip Rev Extract */
170 	OS_REG_WRITE(ah, AR_PHY(0x34), 0x00001c16);
171 	for (i = 0; i < 8; i++)
172 		OS_REG_WRITE(ah, AR_PHY(0x20), 0x00010000);
173 	val = (OS_REG_READ(ah, AR_PHY(256)) >> 24) & 0xff;
174 	val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4);
175 	return ath_hal_reverseBits(val, 8);
176 }
177 
178 static void
179 ar5212AniSetup(struct ath_hal *ah)
180 {
181 	static const struct ar5212AniParams aniparams = {
182 		.maxNoiseImmunityLevel	= 4,	/* levels 0..4 */
183 		.totalSizeDesired	= { -55, -55, -55, -55, -62 },
184 		.coarseHigh		= { -14, -14, -14, -14, -12 },
185 		.coarseLow		= { -64, -64, -64, -64, -70 },
186 		.firpwr			= { -78, -78, -78, -78, -80 },
187 		.maxSpurImmunityLevel	= 2,	/* NB: depends on chip rev */
188 		.cycPwrThr1		= { 2, 4, 6, 8, 10, 12, 14, 16 },
189 		.maxFirstepLevel	= 2,	/* levels 0..2 */
190 		.firstep		= { 0, 4, 8 },
191 		.ofdmTrigHigh		= 500,
192 		.ofdmTrigLow		= 200,
193 		.cckTrigHigh		= 200,
194 		.cckTrigLow		= 100,
195 		.rssiThrHigh		= 40,
196 		.rssiThrLow		= 7,
197 		.period			= 100,
198 	};
199 	if (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_GRIFFIN) {
200 		struct ar5212AniParams tmp;
201 		OS_MEMCPY(&tmp, &aniparams, sizeof(struct ar5212AniParams));
202 		tmp.maxSpurImmunityLevel = 7;	/* Venice and earlier */
203 		ar5212AniAttach(ah, &tmp, &tmp, AH_TRUE);
204 	} else
205 		ar5212AniAttach(ah, &aniparams, &aniparams, AH_TRUE);
206 }
207 
208 /*
209  * Attach for an AR5212 part.
210  */
211 void
212 ar5212InitState(struct ath_hal_5212 *ahp, uint16_t devid, HAL_SOFTC sc,
213 	HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *status)
214 {
215 #define	N(a)	(sizeof(a)/sizeof(a[0]))
216 	static const uint8_t defbssidmask[IEEE80211_ADDR_LEN] =
217 		{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
218 	struct ath_hal *ah;
219 
220 	ah = &ahp->ah_priv.h;
221 	/* set initial values */
222 	OS_MEMCPY(&ahp->ah_priv, &ar5212hal, sizeof(struct ath_hal_private));
223 	ah->ah_sc = sc;
224 	ah->ah_st = st;
225 	ah->ah_sh = sh;
226 
227 	ah->ah_devid = devid;			/* NB: for alq */
228 	AH_PRIVATE(ah)->ah_devid = devid;
229 	AH_PRIVATE(ah)->ah_subvendorid = 0;	/* XXX */
230 
231 	AH_PRIVATE(ah)->ah_powerLimit = MAX_RATE_POWER;
232 	AH_PRIVATE(ah)->ah_tpScale = HAL_TP_SCALE_MAX;	/* no scaling */
233 
234 	ahp->ah_antControl = HAL_ANT_VARIABLE;
235 	ahp->ah_diversity = AH_TRUE;
236 	ahp->ah_bIQCalibration = AH_FALSE;
237 	/*
238 	 * Enable MIC handling.
239 	 */
240 	ahp->ah_staId1Defaults = AR_STA_ID1_CRPT_MIC_ENABLE;
241 	ahp->ah_rssiThr = INIT_RSSI_THR;
242 	ahp->ah_tpcEnabled = AH_FALSE;		/* disabled by default */
243 	ahp->ah_phyPowerOn = AH_FALSE;
244 	ahp->ah_macTPC = SM(MAX_RATE_POWER, AR_TPC_ACK)
245 		       | SM(MAX_RATE_POWER, AR_TPC_CTS)
246 		       | SM(MAX_RATE_POWER, AR_TPC_CHIRP);
247 	ahp->ah_beaconInterval = 100;		/* XXX [20..1000] */
248 	ahp->ah_enable32kHzClock = DONT_USE_32KHZ;/* XXX */
249 	ahp->ah_slottime = (u_int) -1;
250 	ahp->ah_acktimeout = (u_int) -1;
251 	ahp->ah_ctstimeout = (u_int) -1;
252 	ahp->ah_sifstime = (u_int) -1;
253 	ahp->ah_txTrigLev = INIT_TX_FIFO_THRESHOLD,
254 	ahp->ah_maxTxTrigLev = MAX_TX_FIFO_THRESHOLD,
255 
256 	OS_MEMCPY(&ahp->ah_bssidmask, defbssidmask, IEEE80211_ADDR_LEN);
257 #undef N
258 }
259 
260 /*
261  * Validate MAC version and revision.
262  */
263 static HAL_BOOL
264 ar5212IsMacSupported(uint8_t macVersion, uint8_t macRev)
265 {
266 #define	N(a)	(sizeof(a)/sizeof(a[0]))
267 	static const struct {
268 		uint8_t	version;
269 		uint8_t	revMin, revMax;
270 	} macs[] = {
271 	    { AR_SREV_VERSION_VENICE,
272 	      AR_SREV_D2PLUS,		AR_SREV_REVISION_MAX },
273 	    { AR_SREV_VERSION_GRIFFIN,
274 	      AR_SREV_D2PLUS,		AR_SREV_REVISION_MAX },
275 	    { AR_SREV_5413,
276 	      AR_SREV_REVISION_MIN,	AR_SREV_REVISION_MAX },
277 	    { AR_SREV_5424,
278 	      AR_SREV_REVISION_MIN,	AR_SREV_REVISION_MAX },
279 	    { AR_SREV_2425,
280 	      AR_SREV_REVISION_MIN,	AR_SREV_REVISION_MAX },
281 	    { AR_SREV_2417,
282 	      AR_SREV_REVISION_MIN,	AR_SREV_REVISION_MAX },
283 	};
284 	int i;
285 
286 	for (i = 0; i < N(macs); i++)
287 		if (macs[i].version == macVersion &&
288 		    macs[i].revMin <= macRev && macRev <= macs[i].revMax)
289 			return AH_TRUE;
290 	return AH_FALSE;
291 #undef N
292 }
293 
294 /*
295  * Attach for an AR5212 part.
296  */
297 static struct ath_hal *
298 ar5212Attach(uint16_t devid, HAL_SOFTC sc,
299 	HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata,
300 	HAL_STATUS *status)
301 {
302 #define	AH_EEPROM_PROTECT(ah) \
303 	(AH_PRIVATE(ah)->ah_ispcie)? AR_EEPROM_PROTECT_PCIE : AR_EEPROM_PROTECT)
304 	struct ath_hal_5212 *ahp;
305 	struct ath_hal *ah;
306 	struct ath_hal_rf *rf;
307 	uint32_t val;
308 	uint16_t eeval;
309 	HAL_STATUS ecode;
310 
311 	HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n",
312 	    __func__, sc, (void*) st, (void*) sh);
313 
314 	/* NB: memory is returned zero'd */
315 	ahp = ath_hal_malloc(sizeof (struct ath_hal_5212));
316 	if (ahp == AH_NULL) {
317 		HALDEBUG(AH_NULL, HAL_DEBUG_ANY,
318 		    "%s: cannot allocate memory for state block\n", __func__);
319 		*status = HAL_ENOMEM;
320 		return AH_NULL;
321 	}
322 	ar5212InitState(ahp, devid, sc, st, sh, status);
323 	ah = &ahp->ah_priv.h;
324 
325 	if (!ar5212SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) {
326 		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't wakeup chip\n",
327 		    __func__);
328 		ecode = HAL_EIO;
329 		goto bad;
330 	}
331 	/* Read Revisions from Chips before taking out of reset */
332 	val = OS_REG_READ(ah, AR_SREV) & AR_SREV_ID;
333 	AH_PRIVATE(ah)->ah_macVersion = val >> AR_SREV_ID_S;
334 	AH_PRIVATE(ah)->ah_macRev = val & AR_SREV_REVISION;
335 	AH_PRIVATE(ah)->ah_ispcie = IS_5424(ah) || IS_2425(ah);
336 
337 	if (!ar5212IsMacSupported(AH_PRIVATE(ah)->ah_macVersion, AH_PRIVATE(ah)->ah_macRev)) {
338 		HALDEBUG(ah, HAL_DEBUG_ANY,
339 		    "%s: Mac Chip Rev 0x%02x.%x not supported\n" ,
340 		    __func__, AH_PRIVATE(ah)->ah_macVersion,
341 		    AH_PRIVATE(ah)->ah_macRev);
342 		ecode = HAL_ENOTSUPP;
343 		goto bad;
344 	}
345 
346 	/* setup common ini data; rf backends handle remainder */
347 	HAL_INI_INIT(&ahp->ah_ini_modes, ar5212Modes, 6);
348 	HAL_INI_INIT(&ahp->ah_ini_common, ar5212Common, 2);
349 
350 	if (!ar5212ChipReset(ah, AH_NULL)) {	/* reset chip */
351 		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__);
352 		ecode = HAL_EIO;
353 		goto bad;
354 	}
355 
356 	AH_PRIVATE(ah)->ah_phyRev = OS_REG_READ(ah, AR_PHY_CHIP_ID);
357 
358 	if (AH_PRIVATE(ah)->ah_ispcie) {
359 		/* XXX: build flag to disable this? */
360 		ath_hal_configPCIE(ah, AH_FALSE);
361 	}
362 
363 	if (!ar5212ChipTest(ah)) {
364 		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: hardware self-test failed\n",
365 		    __func__);
366 		ecode = HAL_ESELFTEST;
367 		goto bad;
368 	}
369 
370 	/* Enable PCI core retry fix in software for Hainan and up */
371 	if (AH_PRIVATE(ah)->ah_macVersion >= AR_SREV_VERSION_VENICE)
372 		OS_REG_SET_BIT(ah, AR_PCICFG, AR_PCICFG_RETRYFIXEN);
373 
374 	/*
375 	 * Set correct Baseband to analog shift
376 	 * setting to access analog chips.
377 	 */
378 	OS_REG_WRITE(ah, AR_PHY(0), 0x00000007);
379 
380 	/* Read Radio Chip Rev Extract */
381 	AH_PRIVATE(ah)->ah_analog5GhzRev = ar5212GetRadioRev(ah);
382 
383 	rf = ath_hal_rfprobe(ah, &ecode);
384 	if (rf == AH_NULL)
385 		goto bad;
386 
387 	/* NB: silently accept anything in release code per Atheros */
388 	switch (AH_PRIVATE(ah)->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR) {
389 	case AR_RAD5111_SREV_MAJOR:
390 	case AR_RAD5112_SREV_MAJOR:
391 	case AR_RAD2112_SREV_MAJOR:
392 	case AR_RAD2111_SREV_MAJOR:
393 	case AR_RAD2413_SREV_MAJOR:
394 	case AR_RAD5413_SREV_MAJOR:
395 	case AR_RAD5424_SREV_MAJOR:
396 		break;
397 	default:
398 		if (AH_PRIVATE(ah)->ah_analog5GhzRev == 0) {
399 			/*
400 			 * When RF_Silent is used, the
401 			 * analog chip is reset.  So when the system boots
402 			 * up with the radio switch off we cannot determine
403 			 * the RF chip rev.  To workaround this check the
404 			 * mac+phy revs and if Hainan, set the radio rev
405 			 * to Derby.
406 			 */
407 			if (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_VENICE &&
408 			    AH_PRIVATE(ah)->ah_macRev == AR_SREV_HAINAN &&
409 			    AH_PRIVATE(ah)->ah_phyRev == AR_PHYREV_HAINAN) {
410 				AH_PRIVATE(ah)->ah_analog5GhzRev = AR_ANALOG5REV_HAINAN;
411 				break;
412 			}
413 			if (IS_2413(ah)) {		/* Griffin */
414 				AH_PRIVATE(ah)->ah_analog5GhzRev =
415 				    AR_RAD2413_SREV_MAJOR | 0x1;
416 				break;
417 			}
418 			if (IS_5413(ah)) {		/* Eagle */
419 				AH_PRIVATE(ah)->ah_analog5GhzRev =
420 				    AR_RAD5413_SREV_MAJOR | 0x2;
421 				break;
422 			}
423 			if (IS_2425(ah) || IS_2417(ah)) {/* Swan or Nala */
424 				AH_PRIVATE(ah)->ah_analog5GhzRev =
425 				    AR_RAD5424_SREV_MAJOR | 0x2;
426 				break;
427 			}
428 		}
429 #ifdef AH_DEBUG
430 		HALDEBUG(ah, HAL_DEBUG_ANY,
431 		    "%s: 5G Radio Chip Rev 0x%02X is not supported by "
432 		    "this driver\n",
433 		    __func__, AH_PRIVATE(ah)->ah_analog5GhzRev);
434 		ecode = HAL_ENOTSUPP;
435 		goto bad;
436 #endif
437 	}
438 	if (IS_RAD5112_REV1(ah)) {
439 		HALDEBUG(ah, HAL_DEBUG_ANY,
440 		    "%s: 5112 Rev 1 is not supported by this "
441 		    "driver (analog5GhzRev 0x%x)\n", __func__,
442 		    AH_PRIVATE(ah)->ah_analog5GhzRev);
443 		ecode = HAL_ENOTSUPP;
444 		goto bad;
445 	}
446 
447 	val = OS_REG_READ(ah, AR_PCICFG);
448 	val = MS(val, AR_PCICFG_EEPROM_SIZE);
449 	if (val == 0) {
450 		if (!AH_PRIVATE(ah)->ah_ispcie) {
451 			HALDEBUG(ah, HAL_DEBUG_ANY,
452 			    "%s: unsupported EEPROM size %u (0x%x) found\n",
453 			    __func__, val, val);
454 			ecode = HAL_EESIZE;
455 			goto bad;
456 		}
457 		/* XXX AH_PRIVATE(ah)->ah_isPciExpress = AH_TRUE; */
458 	} else if (val != AR_PCICFG_EEPROM_SIZE_16K) {
459 		if (AR_PCICFG_EEPROM_SIZE_FAILED == val) {
460 			HALDEBUG(ah, HAL_DEBUG_ANY,
461 			    "%s: unsupported EEPROM size %u (0x%x) found\n",
462 			    __func__, val, val);
463 			ecode = HAL_EESIZE;
464 			goto bad;
465 		}
466 		HALDEBUG(ah, HAL_DEBUG_ANY,
467 		    "%s: EEPROM size = %d. Must be %d (16k).\n",
468 		    __func__, val, AR_PCICFG_EEPROM_SIZE_16K);
469 		ecode = HAL_EESIZE;
470 		goto bad;
471 	}
472 	ecode = ath_hal_legacyEepromAttach(ah);
473 	if (ecode != HAL_OK) {
474 		goto bad;
475 	}
476 	ahp->ah_isHb63 = IS_2425(ah) && ath_hal_eepromGetFlag(ah, AR_EEP_ISTALON);
477 
478 	/*
479 	 * If Bmode and AR5212, verify 2.4 analog exists
480 	 */
481 	if (ath_hal_eepromGetFlag(ah, AR_EEP_BMODE) &&
482 	    (AH_PRIVATE(ah)->ah_analog5GhzRev & 0xF0) == AR_RAD5111_SREV_MAJOR) {
483 		/*
484 		 * Set correct Baseband to analog shift
485 		 * setting to access analog chips.
486 		 */
487 		OS_REG_WRITE(ah, AR_PHY(0), 0x00004007);
488 		OS_DELAY(2000);
489 		AH_PRIVATE(ah)->ah_analog2GhzRev = ar5212GetRadioRev(ah);
490 
491 		/* Set baseband for 5GHz chip */
492 		OS_REG_WRITE(ah, AR_PHY(0), 0x00000007);
493 		OS_DELAY(2000);
494 		if ((AH_PRIVATE(ah)->ah_analog2GhzRev & 0xF0) != AR_RAD2111_SREV_MAJOR) {
495 			HALDEBUG(ah, HAL_DEBUG_ANY,
496 			    "%s: 2G Radio Chip Rev 0x%02X is not "
497 			    "supported by this driver\n", __func__,
498 			    AH_PRIVATE(ah)->ah_analog2GhzRev);
499 			ecode = HAL_ENOTSUPP;
500 			goto bad;
501 		}
502 	}
503 
504 	ecode = ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, &eeval);
505 	if (ecode != HAL_OK) {
506 		HALDEBUG(ah, HAL_DEBUG_ANY,
507 		    "%s: cannot read regulatory domain from EEPROM\n",
508 		    __func__);
509 		goto bad;
510         }
511 	AH_PRIVATE(ah)->ah_currentRD = eeval;
512 	/* XXX record serial number */
513 
514 	/*
515 	 * Got everything we need now to setup the capabilities.
516 	 */
517 	if (!ar5212FillCapabilityInfo(ah)) {
518 		HALDEBUG(ah, HAL_DEBUG_ANY,
519 		    "%s: failed ar5212FillCapabilityInfo\n", __func__);
520 		ecode = HAL_EEREAD;
521 		goto bad;
522 	}
523 
524 	if (!rf->attach(ah, &ecode)) {
525 		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RF setup failed, status %u\n",
526 		    __func__, ecode);
527 		goto bad;
528 	}
529 	/*
530 	 * Set noise floor adjust method; we arrange a
531 	 * direct call instead of thunking.
532 	 */
533 	AH_PRIVATE(ah)->ah_getNfAdjust = ahp->ah_rfHal->getNfAdjust;
534 
535 	/* Initialize gain ladder thermal calibration structure */
536 	ar5212InitializeGainValues(ah);
537 
538 	ecode = ath_hal_eepromGet(ah, AR_EEP_MACADDR, ahp->ah_macaddr);
539 	if (ecode != HAL_OK) {
540 		HALDEBUG(ah, HAL_DEBUG_ANY,
541 		    "%s: error getting mac address from EEPROM\n", __func__);
542 		goto bad;
543         }
544 
545 	ar5212AniSetup(ah);
546 	/* Setup of Radar/AR structures happens in ath_hal_initchannels*/
547 	ar5212InitNfCalHistBuffer(ah);
548 
549 	/* XXX EAR stuff goes here */
550 
551 	HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n", __func__);
552 
553 	return ah;
554 
555 bad:
556 	if (ahp)
557 		ar5212Detach((struct ath_hal *) ahp);
558 	if (status)
559 		*status = ecode;
560 	return AH_NULL;
561 #undef AH_EEPROM_PROTECT
562 }
563 
564 void
565 ar5212Detach(struct ath_hal *ah)
566 {
567 	HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s:\n", __func__);
568 
569 	HALASSERT(ah != AH_NULL);
570 	HALASSERT(ah->ah_magic == AR5212_MAGIC);
571 
572 	ar5212AniDetach(ah);
573 	ar5212RfDetach(ah);
574 	ar5212Disable(ah);
575 	ar5212SetPowerMode(ah, HAL_PM_FULL_SLEEP, AH_TRUE);
576 
577 	ath_hal_eepromDetach(ah);
578 	ath_hal_free(ah);
579 }
580 
581 HAL_BOOL
582 ar5212ChipTest(struct ath_hal *ah)
583 {
584 	uint32_t regAddr[2] = { AR_STA_ID0, AR_PHY_BASE+(8 << 2) };
585 	uint32_t regHold[2];
586 	uint32_t patternData[4] =
587 	    { 0x55555555, 0xaaaaaaaa, 0x66666666, 0x99999999 };
588 	int i, j;
589 
590 	/* Test PHY & MAC registers */
591 	for (i = 0; i < 2; i++) {
592 		uint32_t addr = regAddr[i];
593 		uint32_t wrData, rdData;
594 
595 		regHold[i] = OS_REG_READ(ah, addr);
596 		for (j = 0; j < 0x100; j++) {
597 			wrData = (j << 16) | j;
598 			OS_REG_WRITE(ah, addr, wrData);
599 			rdData = OS_REG_READ(ah, addr);
600 			if (rdData != wrData) {
601 				HALDEBUG(ah, HAL_DEBUG_ANY,
602 "%s: address test failed addr: 0x%08x - wr:0x%08x != rd:0x%08x\n",
603 				__func__, addr, wrData, rdData);
604 				return AH_FALSE;
605 			}
606 		}
607 		for (j = 0; j < 4; j++) {
608 			wrData = patternData[j];
609 			OS_REG_WRITE(ah, addr, wrData);
610 			rdData = OS_REG_READ(ah, addr);
611 			if (wrData != rdData) {
612 				HALDEBUG(ah, HAL_DEBUG_ANY,
613 "%s: address test failed addr: 0x%08x - wr:0x%08x != rd:0x%08x\n",
614 					__func__, addr, wrData, rdData);
615 				return AH_FALSE;
616 			}
617 		}
618 		OS_REG_WRITE(ah, regAddr[i], regHold[i]);
619 	}
620 	OS_DELAY(100);
621 	return AH_TRUE;
622 }
623 
624 /*
625  * Store the channel edges for the requested operational mode
626  */
627 HAL_BOOL
628 ar5212GetChannelEdges(struct ath_hal *ah,
629 	uint16_t flags, uint16_t *low, uint16_t *high)
630 {
631 	if (flags & IEEE80211_CHAN_5GHZ) {
632 		*low = 4915;
633 		*high = 6100;
634 		return AH_TRUE;
635 	}
636 	if ((flags & IEEE80211_CHAN_2GHZ) &&
637 	    (ath_hal_eepromGetFlag(ah, AR_EEP_BMODE) ||
638 	     ath_hal_eepromGetFlag(ah, AR_EEP_GMODE))) {
639 		*low = 2312;
640 		*high = 2732;
641 		return AH_TRUE;
642 	}
643 	return AH_FALSE;
644 }
645 
646 /*
647  * Disable PLL when in L0s as well as receiver clock when in L1.
648  * This power saving option must be enabled through the Serdes.
649  *
650  * Programming the Serdes must go through the same 288 bit serial shift
651  * register as the other analog registers.  Hence the 9 writes.
652  *
653  * XXX Clean up the magic numbers.
654  */
655 static void
656 ar5212ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore)
657 {
658 	OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00);
659 	OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
660 
661 	/* RX shut off when elecidle is asserted */
662 	OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x28000039);
663 	OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x53160824);
664 	OS_REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980579);
665 
666 	/* Shut off PLL and CLKREQ active in L1 */
667 	OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x001defff);
668 	OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);
669 	OS_REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);
670 	OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x000e3007);
671 
672 	/* Load the new settings */
673 	OS_REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
674 }
675 
676 static void
677 ar5212DisablePCIE(struct ath_hal *ah)
678 {
679 	/* NB: fill in for 9100 */
680 }
681 
682 /*
683  * Fill all software cached or static hardware state information.
684  * Return failure if capabilities are to come from EEPROM and
685  * cannot be read.
686  */
687 HAL_BOOL
688 ar5212FillCapabilityInfo(struct ath_hal *ah)
689 {
690 #define	AR_KEYTABLE_SIZE	128
691 #define	IS_GRIFFIN_LITE(ah) \
692     (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_GRIFFIN && \
693      AH_PRIVATE(ah)->ah_macRev == AR_SREV_GRIFFIN_LITE)
694 #define	IS_COBRA(ah) \
695     (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_COBRA)
696 #define IS_2112(ah) \
697 	((AH_PRIVATE(ah)->ah_analog5GhzRev & 0xF0) == AR_RAD2112_SREV_MAJOR)
698 
699 	struct ath_hal_private *ahpriv = AH_PRIVATE(ah);
700 	HAL_CAPABILITIES *pCap = &ahpriv->ah_caps;
701 	uint16_t capField, val;
702 
703 	/* Read the capability EEPROM location */
704 	if (ath_hal_eepromGet(ah, AR_EEP_OPCAP, &capField) != HAL_OK) {
705 		HALDEBUG(ah, HAL_DEBUG_ANY,
706 		    "%s: unable to read caps from eeprom\n", __func__);
707 		return AH_FALSE;
708 	}
709 	if (IS_2112(ah))
710 		ath_hal_eepromSet(ah, AR_EEP_AMODE, AH_FALSE);
711 	if (capField == 0 && IS_GRIFFIN_LITE(ah)) {
712 		/*
713 		 * For griffin-lite cards with unprogrammed capabilities.
714 		 */
715 		ath_hal_eepromSet(ah, AR_EEP_COMPRESS, AH_FALSE);
716 		ath_hal_eepromSet(ah, AR_EEP_FASTFRAME, AH_FALSE);
717 		ath_hal_eepromSet(ah, AR_EEP_TURBO5DISABLE, AH_TRUE);
718 		ath_hal_eepromSet(ah, AR_EEP_TURBO2DISABLE, AH_TRUE);
719 		HALDEBUG(ah, HAL_DEBUG_ATTACH,
720 		    "%s: override caps for griffin-lite, now 0x%x (+!turbo)\n",
721 		    __func__, capField);
722 	}
723 
724 	/* Modify reg domain on newer cards that need to work with older sw */
725 	if (ahpriv->ah_opmode != HAL_M_HOSTAP &&
726 	    ahpriv->ah_subvendorid == AR_SUBVENDOR_ID_NEW_A) {
727 		if (ahpriv->ah_currentRD == 0x64 ||
728 		    ahpriv->ah_currentRD == 0x65)
729 			ahpriv->ah_currentRD += 5;
730 		else if (ahpriv->ah_currentRD == 0x41)
731 			ahpriv->ah_currentRD = 0x43;
732 		HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: regdomain mapped to 0x%x\n",
733 		    __func__, ahpriv->ah_currentRD);
734 	}
735 
736 	if (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_2417 ||
737 	    AH_PRIVATE(ah)->ah_macVersion == AR_SREV_2425) {
738 		HALDEBUG(ah, HAL_DEBUG_ATTACH,
739 		    "%s: enable Bmode and disable turbo for Swan/Nala\n",
740 		    __func__);
741 		ath_hal_eepromSet(ah, AR_EEP_BMODE, AH_TRUE);
742 		ath_hal_eepromSet(ah, AR_EEP_COMPRESS, AH_FALSE);
743 		ath_hal_eepromSet(ah, AR_EEP_FASTFRAME, AH_FALSE);
744 		ath_hal_eepromSet(ah, AR_EEP_TURBO5DISABLE, AH_TRUE);
745 		ath_hal_eepromSet(ah, AR_EEP_TURBO2DISABLE, AH_TRUE);
746 	}
747 
748 	/* Construct wireless mode from EEPROM */
749 	pCap->halWirelessModes = 0;
750 	if (ath_hal_eepromGetFlag(ah, AR_EEP_AMODE)) {
751 		pCap->halWirelessModes |= HAL_MODE_11A;
752 		if (!ath_hal_eepromGetFlag(ah, AR_EEP_TURBO5DISABLE))
753 			pCap->halWirelessModes |= HAL_MODE_TURBO;
754 	}
755 	if (ath_hal_eepromGetFlag(ah, AR_EEP_BMODE))
756 		pCap->halWirelessModes |= HAL_MODE_11B;
757 	if (ath_hal_eepromGetFlag(ah, AR_EEP_GMODE) &&
758 	    ahpriv->ah_subvendorid != AR_SUBVENDOR_ID_NOG) {
759 		pCap->halWirelessModes |= HAL_MODE_11G;
760 		if (!ath_hal_eepromGetFlag(ah, AR_EEP_TURBO2DISABLE))
761 			pCap->halWirelessModes |= HAL_MODE_108G;
762 	}
763 
764 	pCap->halLow2GhzChan = 2312;
765 	/* XXX 2417 too? */
766 	if (IS_RAD5112_ANY(ah) || IS_5413(ah) || IS_2425(ah) ||  IS_2417(ah))
767 		pCap->halHigh2GhzChan = 2500;
768 	else
769 		pCap->halHigh2GhzChan = 2732;
770 
771 	pCap->halLow5GhzChan = 4915;
772 	pCap->halHigh5GhzChan = 6100;
773 
774 	pCap->halCipherCkipSupport = AH_FALSE;
775 	pCap->halCipherTkipSupport = AH_TRUE;
776 	pCap->halCipherAesCcmSupport =
777 		(ath_hal_eepromGetFlag(ah, AR_EEP_AES) &&
778 		 ((AH_PRIVATE(ah)->ah_macVersion > AR_SREV_VERSION_VENICE) ||
779 		  ((AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_VENICE) &&
780 		   (AH_PRIVATE(ah)->ah_macRev >= AR_SREV_VERSION_OAHU))));
781 
782 	pCap->halMicCkipSupport    = AH_FALSE;
783 	pCap->halMicTkipSupport    = AH_TRUE;
784 	pCap->halMicAesCcmSupport  = ath_hal_eepromGetFlag(ah, AR_EEP_AES);
785 	/*
786 	 * Starting with Griffin TX+RX mic keys can be combined
787 	 * in one key cache slot.
788 	 */
789 	if (AH_PRIVATE(ah)->ah_macVersion >= AR_SREV_VERSION_GRIFFIN)
790 		pCap->halTkipMicTxRxKeySupport = AH_TRUE;
791 	else
792 		pCap->halTkipMicTxRxKeySupport = AH_FALSE;
793 	pCap->halChanSpreadSupport = AH_TRUE;
794 	pCap->halSleepAfterBeaconBroken = AH_TRUE;
795 
796 	if (ahpriv->ah_macRev > 1 || IS_COBRA(ah)) {
797 		pCap->halCompressSupport   =
798 			ath_hal_eepromGetFlag(ah, AR_EEP_COMPRESS) &&
799 			(pCap->halWirelessModes & (HAL_MODE_11A|HAL_MODE_11G)) != 0;
800 		pCap->halBurstSupport = ath_hal_eepromGetFlag(ah, AR_EEP_BURST);
801 		pCap->halFastFramesSupport =
802 			ath_hal_eepromGetFlag(ah, AR_EEP_FASTFRAME) &&
803 			(pCap->halWirelessModes & (HAL_MODE_11A|HAL_MODE_11G)) != 0;
804 		pCap->halChapTuningSupport = AH_TRUE;
805 		pCap->halTurboPrimeSupport = AH_TRUE;
806 	}
807 	pCap->halTurboGSupport = pCap->halWirelessModes & HAL_MODE_108G;
808 
809 	pCap->halPSPollBroken = AH_TRUE;	/* XXX fixed in later revs? */
810 	pCap->halVEOLSupport = AH_TRUE;
811 	pCap->halBssIdMaskSupport = AH_TRUE;
812 	pCap->halMcastKeySrchSupport = AH_TRUE;
813 	if ((ahpriv->ah_macVersion == AR_SREV_VERSION_VENICE &&
814 	     ahpriv->ah_macRev == 8) ||
815 	    ahpriv->ah_macVersion > AR_SREV_VERSION_VENICE)
816 		pCap->halTsfAddSupport = AH_TRUE;
817 
818 	if (ath_hal_eepromGet(ah, AR_EEP_MAXQCU, &val) == HAL_OK)
819 		pCap->halTotalQueues = val;
820 	else
821 		pCap->halTotalQueues = HAL_NUM_TX_QUEUES;
822 
823 	if (ath_hal_eepromGet(ah, AR_EEP_KCENTRIES, &val) == HAL_OK)
824 		pCap->halKeyCacheSize = val;
825 	else
826 		pCap->halKeyCacheSize = AR_KEYTABLE_SIZE;
827 
828 	pCap->halChanHalfRate = AH_TRUE;
829 	pCap->halChanQuarterRate = AH_TRUE;
830 
831 	if (ath_hal_eepromGetFlag(ah, AR_EEP_RFKILL) &&
832 	    ath_hal_eepromGet(ah, AR_EEP_RFSILENT, &ahpriv->ah_rfsilent) == HAL_OK) {
833 		/* NB: enabled by default */
834 		ahpriv->ah_rfkillEnabled = AH_TRUE;
835 		pCap->halRfSilentSupport = AH_TRUE;
836 	}
837 
838 	/* NB: this is a guess, noone seems to know the answer */
839 	ahpriv->ah_rxornIsFatal =
840 	    (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_VENICE);
841 
842 	/* enable features that first appeared in Hainan */
843 	if ((AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_VENICE &&
844 	     AH_PRIVATE(ah)->ah_macRev == AR_SREV_HAINAN) ||
845 	    AH_PRIVATE(ah)->ah_macVersion > AR_SREV_VERSION_VENICE) {
846 		/* h/w phy counters */
847 		pCap->halHwPhyCounterSupport = AH_TRUE;
848 		/* bssid match disable */
849 		pCap->halBssidMatchSupport = AH_TRUE;
850 	}
851 
852 	pCap->halTstampPrecision = 15;
853 	pCap->halIntrMask = HAL_INT_COMMON
854 			| HAL_INT_RX
855 			| HAL_INT_TX
856 			| HAL_INT_FATAL
857 			| HAL_INT_BNR
858 			| HAL_INT_BMISC
859 			;
860 	if (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_GRIFFIN)
861 		pCap->halIntrMask &= ~HAL_INT_TBTT;
862 
863 	pCap->hal4kbSplitTransSupport = AH_TRUE;
864 
865 	return AH_TRUE;
866 #undef IS_COBRA
867 #undef IS_GRIFFIN_LITE
868 #undef AR_KEYTABLE_SIZE
869 }
870 
871 static const char*
872 ar5212Probe(uint16_t vendorid, uint16_t devid)
873 {
874 	if (vendorid == ATHEROS_VENDOR_ID ||
875 	    vendorid == ATHEROS_3COM_VENDOR_ID ||
876 	    vendorid == ATHEROS_3COM2_VENDOR_ID) {
877 		switch (devid) {
878 		case AR5212_FPGA:
879 			return "Atheros 5212 (FPGA)";
880 		case AR5212_DEVID:
881 		case AR5212_DEVID_IBM:
882 		case AR5212_DEFAULT:
883 			return "Atheros 5212";
884 		case AR5212_AR2413:
885 			return "Atheros 2413";
886 		case AR5212_AR2417:
887 			return "Atheros 2417";
888 		case AR5212_AR5413:
889 			return "Atheros 5413";
890 		case AR5212_AR5424:
891 			return "Atheros 5424/2424";
892 		}
893 	}
894 	return AH_NULL;
895 }
896 AH_CHIP(AR5212, ar5212Probe, ar5212Attach);
897