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