xref: /freebsd/sys/dev/ath/ath_hal/ar5212/ar5212_attach.c (revision 95ee2897e98f5d444f26ed2334cc7c439f9c16c6)
16e778a7eSPedro F. Giffuni /*-
26e778a7eSPedro F. Giffuni  * SPDX-License-Identifier: ISC
36e778a7eSPedro F. Giffuni  *
459efa8b5SSam Leffler  * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting
514779705SSam Leffler  * Copyright (c) 2002-2008 Atheros Communications, Inc.
614779705SSam Leffler  *
714779705SSam Leffler  * Permission to use, copy, modify, and/or distribute this software for any
814779705SSam Leffler  * purpose with or without fee is hereby granted, provided that the above
914779705SSam Leffler  * copyright notice and this permission notice appear in all copies.
1014779705SSam Leffler  *
1114779705SSam Leffler  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1214779705SSam Leffler  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1314779705SSam Leffler  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1414779705SSam Leffler  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1514779705SSam Leffler  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1614779705SSam Leffler  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1714779705SSam Leffler  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1814779705SSam Leffler  */
1914779705SSam Leffler #include "opt_ah.h"
2014779705SSam Leffler 
2114779705SSam Leffler #include "ah.h"
2214779705SSam Leffler #include "ah_internal.h"
2314779705SSam Leffler #include "ah_devid.h"
2414779705SSam Leffler 
2514779705SSam Leffler #include "ar5212/ar5212.h"
2614779705SSam Leffler #include "ar5212/ar5212reg.h"
2714779705SSam Leffler #include "ar5212/ar5212phy.h"
2814779705SSam Leffler 
2914779705SSam Leffler #define AH_5212_COMMON
3014779705SSam Leffler #include "ar5212/ar5212.ini"
3114779705SSam Leffler 
32ae2a0aa4SAdrian Chadd static void ar5212ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore,
33ae2a0aa4SAdrian Chadd 		HAL_BOOL power_off);
3444834ea4SSam Leffler static void ar5212DisablePCIE(struct ath_hal *ah);
3544834ea4SSam Leffler 
3614779705SSam Leffler static const struct ath_hal_private ar5212hal = {{
3714779705SSam Leffler 	.ah_magic			= AR5212_MAGIC,
3814779705SSam Leffler 
3914779705SSam Leffler 	.ah_getRateTable		= ar5212GetRateTable,
4014779705SSam Leffler 	.ah_detach			= ar5212Detach,
4114779705SSam Leffler 
4214779705SSam Leffler 	/* Reset Functions */
4314779705SSam Leffler 	.ah_reset			= ar5212Reset,
4414779705SSam Leffler 	.ah_phyDisable			= ar5212PhyDisable,
4514779705SSam Leffler 	.ah_disable			= ar5212Disable,
4644834ea4SSam Leffler 	.ah_configPCIE			= ar5212ConfigPCIE,
4744834ea4SSam Leffler 	.ah_disablePCIE			= ar5212DisablePCIE,
4814779705SSam Leffler 	.ah_setPCUConfig		= ar5212SetPCUConfig,
4914779705SSam Leffler 	.ah_perCalibration		= ar5212PerCalibration,
5014779705SSam Leffler 	.ah_perCalibrationN		= ar5212PerCalibrationN,
5114779705SSam Leffler 	.ah_resetCalValid		= ar5212ResetCalValid,
5214779705SSam Leffler 	.ah_setTxPowerLimit		= ar5212SetTxPowerLimit,
5314779705SSam Leffler 	.ah_getChanNoise		= ath_hal_getChanNoise,
5414779705SSam Leffler 
5514779705SSam Leffler 	/* Transmit functions */
5614779705SSam Leffler 	.ah_updateTxTrigLevel		= ar5212UpdateTxTrigLevel,
5714779705SSam Leffler 	.ah_setupTxQueue		= ar5212SetupTxQueue,
5814779705SSam Leffler 	.ah_setTxQueueProps             = ar5212SetTxQueueProps,
5914779705SSam Leffler 	.ah_getTxQueueProps             = ar5212GetTxQueueProps,
6014779705SSam Leffler 	.ah_releaseTxQueue		= ar5212ReleaseTxQueue,
6114779705SSam Leffler 	.ah_resetTxQueue		= ar5212ResetTxQueue,
6214779705SSam Leffler 	.ah_getTxDP			= ar5212GetTxDP,
6314779705SSam Leffler 	.ah_setTxDP			= ar5212SetTxDP,
6414779705SSam Leffler 	.ah_numTxPending		= ar5212NumTxPending,
6514779705SSam Leffler 	.ah_startTxDma			= ar5212StartTxDma,
6614779705SSam Leffler 	.ah_stopTxDma			= ar5212StopTxDma,
6714779705SSam Leffler 	.ah_setupTxDesc			= ar5212SetupTxDesc,
6814779705SSam Leffler 	.ah_setupXTxDesc		= ar5212SetupXTxDesc,
6914779705SSam Leffler 	.ah_fillTxDesc			= ar5212FillTxDesc,
7014779705SSam Leffler 	.ah_procTxDesc			= ar5212ProcTxDesc,
7114779705SSam Leffler 	.ah_getTxIntrQueue		= ar5212GetTxIntrQueue,
7214779705SSam Leffler 	.ah_reqTxIntrDesc 		= ar5212IntrReqTxDesc,
739ea46744SAdrian Chadd 	.ah_getTxCompletionRates	= ar5212GetTxCompletionRates,
74ad3e6dcdSAdrian Chadd 	.ah_setTxDescLink		= ar5212SetTxDescLink,
75ad3e6dcdSAdrian Chadd 	.ah_getTxDescLink		= ar5212GetTxDescLink,
76ad3e6dcdSAdrian Chadd 	.ah_getTxDescLinkPtr		= ar5212GetTxDescLinkPtr,
7714779705SSam Leffler 
7814779705SSam Leffler 	/* RX Functions */
7914779705SSam Leffler 	.ah_getRxDP			= ar5212GetRxDP,
8014779705SSam Leffler 	.ah_setRxDP			= ar5212SetRxDP,
8114779705SSam Leffler 	.ah_enableReceive		= ar5212EnableReceive,
8214779705SSam Leffler 	.ah_stopDmaReceive		= ar5212StopDmaReceive,
8314779705SSam Leffler 	.ah_startPcuReceive		= ar5212StartPcuReceive,
8414779705SSam Leffler 	.ah_stopPcuReceive		= ar5212StopPcuReceive,
8514779705SSam Leffler 	.ah_setMulticastFilter		= ar5212SetMulticastFilter,
8614779705SSam Leffler 	.ah_setMulticastFilterIndex	= ar5212SetMulticastFilterIndex,
8714779705SSam Leffler 	.ah_clrMulticastFilterIndex	= ar5212ClrMulticastFilterIndex,
8814779705SSam Leffler 	.ah_getRxFilter			= ar5212GetRxFilter,
8914779705SSam Leffler 	.ah_setRxFilter			= ar5212SetRxFilter,
9014779705SSam Leffler 	.ah_setupRxDesc			= ar5212SetupRxDesc,
9114779705SSam Leffler 	.ah_procRxDesc			= ar5212ProcRxDesc,
92a108ab63SAdrian Chadd 	.ah_rxMonitor			= ar5212RxMonitor,
93a108ab63SAdrian Chadd 	.ah_aniPoll			= ar5212AniPoll,
9414779705SSam Leffler 	.ah_procMibEvent		= ar5212ProcessMibIntr,
9514779705SSam Leffler 
9614779705SSam Leffler 	/* Misc Functions */
9714779705SSam Leffler 	.ah_getCapability		= ar5212GetCapability,
9814779705SSam Leffler 	.ah_setCapability		= ar5212SetCapability,
9914779705SSam Leffler 	.ah_getDiagState		= ar5212GetDiagState,
10014779705SSam Leffler 	.ah_getMacAddress		= ar5212GetMacAddress,
10114779705SSam Leffler 	.ah_setMacAddress		= ar5212SetMacAddress,
10214779705SSam Leffler 	.ah_getBssIdMask		= ar5212GetBssIdMask,
10314779705SSam Leffler 	.ah_setBssIdMask		= ar5212SetBssIdMask,
10414779705SSam Leffler 	.ah_setRegulatoryDomain		= ar5212SetRegulatoryDomain,
10514779705SSam Leffler 	.ah_setLedState			= ar5212SetLedState,
10614779705SSam Leffler 	.ah_writeAssocid		= ar5212WriteAssocid,
10714779705SSam Leffler 	.ah_gpioCfgInput		= ar5212GpioCfgInput,
10814779705SSam Leffler 	.ah_gpioCfgOutput		= ar5212GpioCfgOutput,
10914779705SSam Leffler 	.ah_gpioGet			= ar5212GpioGet,
11014779705SSam Leffler 	.ah_gpioSet			= ar5212GpioSet,
11114779705SSam Leffler 	.ah_gpioSetIntr			= ar5212GpioSetIntr,
11214779705SSam Leffler 	.ah_getTsf32			= ar5212GetTsf32,
11314779705SSam Leffler 	.ah_getTsf64			= ar5212GetTsf64,
114c83ba0b9SAdrian Chadd 	.ah_setTsf64			= ar5212SetTsf64,
11514779705SSam Leffler 	.ah_resetTsf			= ar5212ResetTsf,
11614779705SSam Leffler 	.ah_detectCardPresent		= ar5212DetectCardPresent,
11714779705SSam Leffler 	.ah_updateMibCounters		= ar5212UpdateMibCounters,
11814779705SSam Leffler 	.ah_getRfGain			= ar5212GetRfgain,
11914779705SSam Leffler 	.ah_getDefAntenna		= ar5212GetDefAntenna,
12014779705SSam Leffler 	.ah_setDefAntenna		= ar5212SetDefAntenna,
12114779705SSam Leffler 	.ah_getAntennaSwitch		= ar5212GetAntennaSwitch,
12214779705SSam Leffler 	.ah_setAntennaSwitch		= ar5212SetAntennaSwitch,
12314779705SSam Leffler 	.ah_setSifsTime			= ar5212SetSifsTime,
12414779705SSam Leffler 	.ah_getSifsTime			= ar5212GetSifsTime,
12514779705SSam Leffler 	.ah_setSlotTime			= ar5212SetSlotTime,
12614779705SSam Leffler 	.ah_getSlotTime			= ar5212GetSlotTime,
12714779705SSam Leffler 	.ah_setAckTimeout		= ar5212SetAckTimeout,
12814779705SSam Leffler 	.ah_getAckTimeout		= ar5212GetAckTimeout,
12914779705SSam Leffler 	.ah_setAckCTSRate		= ar5212SetAckCTSRate,
13014779705SSam Leffler 	.ah_getAckCTSRate		= ar5212GetAckCTSRate,
13114779705SSam Leffler 	.ah_setCTSTimeout		= ar5212SetCTSTimeout,
13214779705SSam Leffler 	.ah_getCTSTimeout		= ar5212GetCTSTimeout,
13314779705SSam Leffler 	.ah_setDecompMask		= ar5212SetDecompMask,
13414779705SSam Leffler 	.ah_setCoverageClass		= ar5212SetCoverageClass,
13504d172dbSAdrian Chadd 	.ah_setQuiet			= ar5212SetQuiet,
136352f07f6SAdrian Chadd 	.ah_getMibCycleCounts		= ar5212GetMibCycleCounts,
137d2a72d67SAdrian Chadd 	.ah_setChainMasks		= ar5212SetChainMasks,
138*bed90bf8SAdrian Chadd 	.ah_getNav			= ar5212GetNav,
139*bed90bf8SAdrian Chadd 	.ah_setNav			= ar5212SetNav,
14014779705SSam Leffler 
1412cb5233bSAdrian Chadd 	/* DFS Functions */
1422cb5233bSAdrian Chadd 	.ah_enableDfs			= ar5212EnableDfs,
1432cb5233bSAdrian Chadd 	.ah_getDfsThresh		= ar5212GetDfsThresh,
14447152caeSAdrian Chadd 	.ah_getDfsDefaultThresh		= ar5212GetDfsDefaultThresh,
1453d423111SAdrian Chadd 	.ah_procRadarEvent		= ar5212ProcessRadarEvent,
14660829c48SAdrian Chadd 	.ah_isFastClockEnabled		= ar5212IsFastClockEnabled,
1477f925de1SAdrian Chadd 	.ah_get11nExtBusy		= ar5212Get11nExtBusy,
1482cb5233bSAdrian Chadd 
14914779705SSam Leffler 	/* Key Cache Functions */
15014779705SSam Leffler 	.ah_getKeyCacheSize		= ar5212GetKeyCacheSize,
15114779705SSam Leffler 	.ah_resetKeyCacheEntry		= ar5212ResetKeyCacheEntry,
15214779705SSam Leffler 	.ah_isKeyCacheEntryValid	= ar5212IsKeyCacheEntryValid,
15314779705SSam Leffler 	.ah_setKeyCacheEntry		= ar5212SetKeyCacheEntry,
15414779705SSam Leffler 	.ah_setKeyCacheEntryMac		= ar5212SetKeyCacheEntryMac,
15514779705SSam Leffler 
15614779705SSam Leffler 	/* Power Management Functions */
15714779705SSam Leffler 	.ah_setPowerMode		= ar5212SetPowerMode,
15814779705SSam Leffler 	.ah_getPowerMode		= ar5212GetPowerMode,
15914779705SSam Leffler 
16014779705SSam Leffler 	/* Beacon Functions */
16114779705SSam Leffler 	.ah_setBeaconTimers		= ar5212SetBeaconTimers,
16214779705SSam Leffler 	.ah_beaconInit			= ar5212BeaconInit,
16314779705SSam Leffler 	.ah_setStationBeaconTimers	= ar5212SetStaBeaconTimers,
16414779705SSam Leffler 	.ah_resetStationBeaconTimers	= ar5212ResetStaBeaconTimers,
165fc4de9b7SAdrian Chadd 	.ah_getNextTBTT			= ar5212GetNextTBTT,
16614779705SSam Leffler 
16714779705SSam Leffler 	/* Interrupt Functions */
16814779705SSam Leffler 	.ah_isInterruptPending		= ar5212IsInterruptPending,
16914779705SSam Leffler 	.ah_getPendingInterrupts	= ar5212GetPendingInterrupts,
17014779705SSam Leffler 	.ah_getInterrupts		= ar5212GetInterrupts,
17114779705SSam Leffler 	.ah_setInterrupts		= ar5212SetInterrupts },
17214779705SSam Leffler 
17314779705SSam Leffler 	.ah_getChannelEdges		= ar5212GetChannelEdges,
17414779705SSam Leffler 	.ah_getWirelessModes		= ar5212GetWirelessModes,
17514779705SSam Leffler 	.ah_eepromRead			= ar5212EepromRead,
17614779705SSam Leffler #ifdef AH_SUPPORT_WRITE_EEPROM
17714779705SSam Leffler 	.ah_eepromWrite			= ar5212EepromWrite,
17814779705SSam Leffler #endif
17914779705SSam Leffler 	.ah_getChipPowerLimits		= ar5212GetChipPowerLimits,
18014779705SSam Leffler };
18114779705SSam Leffler 
18214779705SSam Leffler uint32_t
ar5212GetRadioRev(struct ath_hal * ah)18314779705SSam Leffler ar5212GetRadioRev(struct ath_hal *ah)
18414779705SSam Leffler {
18514779705SSam Leffler 	uint32_t val;
18614779705SSam Leffler 	int i;
18714779705SSam Leffler 
18814779705SSam Leffler 	/* Read Radio Chip Rev Extract */
18914779705SSam Leffler 	OS_REG_WRITE(ah, AR_PHY(0x34), 0x00001c16);
19014779705SSam Leffler 	for (i = 0; i < 8; i++)
19114779705SSam Leffler 		OS_REG_WRITE(ah, AR_PHY(0x20), 0x00010000);
19214779705SSam Leffler 	val = (OS_REG_READ(ah, AR_PHY(256)) >> 24) & 0xff;
19314779705SSam Leffler 	val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4);
19414779705SSam Leffler 	return ath_hal_reverseBits(val, 8);
19514779705SSam Leffler }
19614779705SSam Leffler 
19714779705SSam Leffler static void
ar5212AniSetup(struct ath_hal * ah)19814779705SSam Leffler ar5212AniSetup(struct ath_hal *ah)
19914779705SSam Leffler {
20014779705SSam Leffler 	static const struct ar5212AniParams aniparams = {
20114779705SSam Leffler 		.maxNoiseImmunityLevel	= 4,	/* levels 0..4 */
20214779705SSam Leffler 		.totalSizeDesired	= { -55, -55, -55, -55, -62 },
20314779705SSam Leffler 		.coarseHigh		= { -14, -14, -14, -14, -12 },
20414779705SSam Leffler 		.coarseLow		= { -64, -64, -64, -64, -70 },
20514779705SSam Leffler 		.firpwr			= { -78, -78, -78, -78, -80 },
20614779705SSam Leffler 		.maxSpurImmunityLevel	= 2,	/* NB: depends on chip rev */
20714779705SSam Leffler 		.cycPwrThr1		= { 2, 4, 6, 8, 10, 12, 14, 16 },
20814779705SSam Leffler 		.maxFirstepLevel	= 2,	/* levels 0..2 */
20914779705SSam Leffler 		.firstep		= { 0, 4, 8 },
21014779705SSam Leffler 		.ofdmTrigHigh		= 500,
21114779705SSam Leffler 		.ofdmTrigLow		= 200,
21214779705SSam Leffler 		.cckTrigHigh		= 200,
21314779705SSam Leffler 		.cckTrigLow		= 100,
21414779705SSam Leffler 		.rssiThrHigh		= 40,
21514779705SSam Leffler 		.rssiThrLow		= 7,
21614779705SSam Leffler 		.period			= 100,
21714779705SSam Leffler 	};
21814779705SSam Leffler 	if (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_GRIFFIN) {
21914779705SSam Leffler 		struct ar5212AniParams tmp;
22014779705SSam Leffler 		OS_MEMCPY(&tmp, &aniparams, sizeof(struct ar5212AniParams));
22114779705SSam Leffler 		tmp.maxSpurImmunityLevel = 7;	/* Venice and earlier */
22214779705SSam Leffler 		ar5212AniAttach(ah, &tmp, &tmp, AH_TRUE);
22314779705SSam Leffler 	} else
22414779705SSam Leffler 		ar5212AniAttach(ah, &aniparams, &aniparams, AH_TRUE);
2259f456336SAdrian Chadd 
2269f456336SAdrian Chadd 	/* Set overridable ANI methods */
2279f456336SAdrian Chadd 	AH5212(ah)->ah_aniControl = ar5212AniControl;
22814779705SSam Leffler }
22914779705SSam Leffler 
23014779705SSam Leffler /*
23114779705SSam Leffler  * Attach for an AR5212 part.
23214779705SSam Leffler  */
23314779705SSam Leffler void
ar5212InitState(struct ath_hal_5212 * ahp,uint16_t devid,HAL_SOFTC sc,HAL_BUS_TAG st,HAL_BUS_HANDLE sh,HAL_STATUS * status)23414779705SSam Leffler ar5212InitState(struct ath_hal_5212 *ahp, uint16_t devid, HAL_SOFTC sc,
23514779705SSam Leffler 	HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *status)
23614779705SSam Leffler {
23714779705SSam Leffler #define	N(a)	(sizeof(a)/sizeof(a[0]))
23814779705SSam Leffler 	static const uint8_t defbssidmask[IEEE80211_ADDR_LEN] =
23914779705SSam Leffler 		{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
24014779705SSam Leffler 	struct ath_hal *ah;
24114779705SSam Leffler 
24214779705SSam Leffler 	ah = &ahp->ah_priv.h;
24314779705SSam Leffler 	/* set initial values */
24414779705SSam Leffler 	OS_MEMCPY(&ahp->ah_priv, &ar5212hal, sizeof(struct ath_hal_private));
24514779705SSam Leffler 	ah->ah_sc = sc;
24614779705SSam Leffler 	ah->ah_st = st;
24714779705SSam Leffler 	ah->ah_sh = sh;
24814779705SSam Leffler 
24914779705SSam Leffler 	ah->ah_devid = devid;			/* NB: for alq */
25014779705SSam Leffler 	AH_PRIVATE(ah)->ah_devid = devid;
25114779705SSam Leffler 	AH_PRIVATE(ah)->ah_subvendorid = 0;	/* XXX */
25214779705SSam Leffler 
25314779705SSam Leffler 	AH_PRIVATE(ah)->ah_powerLimit = MAX_RATE_POWER;
25414779705SSam Leffler 	AH_PRIVATE(ah)->ah_tpScale = HAL_TP_SCALE_MAX;	/* no scaling */
25514779705SSam Leffler 
25614779705SSam Leffler 	ahp->ah_antControl = HAL_ANT_VARIABLE;
25714779705SSam Leffler 	ahp->ah_diversity = AH_TRUE;
25814779705SSam Leffler 	ahp->ah_bIQCalibration = AH_FALSE;
25914779705SSam Leffler 	/*
26014779705SSam Leffler 	 * Enable MIC handling.
26114779705SSam Leffler 	 */
26214779705SSam Leffler 	ahp->ah_staId1Defaults = AR_STA_ID1_CRPT_MIC_ENABLE;
26314779705SSam Leffler 	ahp->ah_rssiThr = INIT_RSSI_THR;
26414779705SSam Leffler 	ahp->ah_tpcEnabled = AH_FALSE;		/* disabled by default */
26514779705SSam Leffler 	ahp->ah_phyPowerOn = AH_FALSE;
26614779705SSam Leffler 	ahp->ah_macTPC = SM(MAX_RATE_POWER, AR_TPC_ACK)
26714779705SSam Leffler 		       | SM(MAX_RATE_POWER, AR_TPC_CTS)
26814779705SSam Leffler 		       | SM(MAX_RATE_POWER, AR_TPC_CHIRP);
26914779705SSam Leffler 	ahp->ah_beaconInterval = 100;		/* XXX [20..1000] */
27014779705SSam Leffler 	ahp->ah_enable32kHzClock = DONT_USE_32KHZ;/* XXX */
27114779705SSam Leffler 	ahp->ah_slottime = (u_int) -1;
27214779705SSam Leffler 	ahp->ah_acktimeout = (u_int) -1;
27314779705SSam Leffler 	ahp->ah_ctstimeout = (u_int) -1;
27414779705SSam Leffler 	ahp->ah_sifstime = (u_int) -1;
275f0be707dSPedro F. Giffuni 	ahp->ah_txTrigLev = INIT_TX_FIFO_THRESHOLD;
276f0be707dSPedro F. Giffuni 	ahp->ah_maxTxTrigLev = MAX_TX_FIFO_THRESHOLD;
277256796dbSRui Paulo 
27814779705SSam Leffler 	OS_MEMCPY(&ahp->ah_bssidmask, defbssidmask, IEEE80211_ADDR_LEN);
27914779705SSam Leffler #undef N
28014779705SSam Leffler }
28114779705SSam Leffler 
28214779705SSam Leffler /*
28314779705SSam Leffler  * Validate MAC version and revision.
28414779705SSam Leffler  */
28514779705SSam Leffler static HAL_BOOL
ar5212IsMacSupported(uint8_t macVersion,uint8_t macRev)28614779705SSam Leffler ar5212IsMacSupported(uint8_t macVersion, uint8_t macRev)
28714779705SSam Leffler {
28814779705SSam Leffler #define	N(a)	(sizeof(a)/sizeof(a[0]))
28914779705SSam Leffler 	static const struct {
29014779705SSam Leffler 		uint8_t	version;
29114779705SSam Leffler 		uint8_t	revMin, revMax;
29214779705SSam Leffler 	} macs[] = {
29314779705SSam Leffler 	    { AR_SREV_VERSION_VENICE,
29414779705SSam Leffler 	      AR_SREV_D2PLUS,		AR_SREV_REVISION_MAX },
29514779705SSam Leffler 	    { AR_SREV_VERSION_GRIFFIN,
29614779705SSam Leffler 	      AR_SREV_D2PLUS,		AR_SREV_REVISION_MAX },
29714779705SSam Leffler 	    { AR_SREV_5413,
29814779705SSam Leffler 	      AR_SREV_REVISION_MIN,	AR_SREV_REVISION_MAX },
29914779705SSam Leffler 	    { AR_SREV_5424,
30014779705SSam Leffler 	      AR_SREV_REVISION_MIN,	AR_SREV_REVISION_MAX },
30114779705SSam Leffler 	    { AR_SREV_2425,
30214779705SSam Leffler 	      AR_SREV_REVISION_MIN,	AR_SREV_REVISION_MAX },
30314779705SSam Leffler 	    { AR_SREV_2417,
30414779705SSam Leffler 	      AR_SREV_REVISION_MIN,	AR_SREV_REVISION_MAX },
30514779705SSam Leffler 	};
30614779705SSam Leffler 	int i;
30714779705SSam Leffler 
30814779705SSam Leffler 	for (i = 0; i < N(macs); i++)
30914779705SSam Leffler 		if (macs[i].version == macVersion &&
31014779705SSam Leffler 		    macs[i].revMin <= macRev && macRev <= macs[i].revMax)
31114779705SSam Leffler 			return AH_TRUE;
31214779705SSam Leffler 	return AH_FALSE;
31314779705SSam Leffler #undef N
31414779705SSam Leffler }
31514779705SSam Leffler 
31614779705SSam Leffler /*
31714779705SSam Leffler  * Attach for an AR5212 part.
31814779705SSam Leffler  */
31914779705SSam Leffler static struct ath_hal *
ar5212Attach(uint16_t devid,HAL_SOFTC sc,HAL_BUS_TAG st,HAL_BUS_HANDLE sh,uint16_t * eepromdata,HAL_OPS_CONFIG * ah_config,HAL_STATUS * status)32014779705SSam Leffler ar5212Attach(uint16_t devid, HAL_SOFTC sc,
32188117a53SAdrian Chadd 	HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata,
3229389d5a9SAdrian Chadd 	HAL_OPS_CONFIG *ah_config, HAL_STATUS *status)
32314779705SSam Leffler {
32414779705SSam Leffler #define	AH_EEPROM_PROTECT(ah) \
32544834ea4SSam Leffler 	(AH_PRIVATE(ah)->ah_ispcie)? AR_EEPROM_PROTECT_PCIE : AR_EEPROM_PROTECT)
32614779705SSam Leffler 	struct ath_hal_5212 *ahp;
32714779705SSam Leffler 	struct ath_hal *ah;
32814779705SSam Leffler 	struct ath_hal_rf *rf;
32914779705SSam Leffler 	uint32_t val;
33014779705SSam Leffler 	uint16_t eeval;
33114779705SSam Leffler 	HAL_STATUS ecode;
33214779705SSam Leffler 
3330e56140aSAdrian Chadd 	HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n",
33414779705SSam Leffler 	    __func__, sc, (void*) st, (void*) sh);
33514779705SSam Leffler 
33614779705SSam Leffler 	/* NB: memory is returned zero'd */
33714779705SSam Leffler 	ahp = ath_hal_malloc(sizeof (struct ath_hal_5212));
33814779705SSam Leffler 	if (ahp == AH_NULL) {
3390e56140aSAdrian Chadd 		HALDEBUG(AH_NULL, HAL_DEBUG_ANY,
34014779705SSam Leffler 		    "%s: cannot allocate memory for state block\n", __func__);
34114779705SSam Leffler 		*status = HAL_ENOMEM;
34214779705SSam Leffler 		return AH_NULL;
34314779705SSam Leffler 	}
34414779705SSam Leffler 	ar5212InitState(ahp, devid, sc, st, sh, status);
34514779705SSam Leffler 	ah = &ahp->ah_priv.h;
34614779705SSam Leffler 
34714779705SSam Leffler 	if (!ar5212SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) {
34814779705SSam Leffler 		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't wakeup chip\n",
34914779705SSam Leffler 		    __func__);
35014779705SSam Leffler 		ecode = HAL_EIO;
35114779705SSam Leffler 		goto bad;
35214779705SSam Leffler 	}
35314779705SSam Leffler 	/* Read Revisions from Chips before taking out of reset */
35414779705SSam Leffler 	val = OS_REG_READ(ah, AR_SREV) & AR_SREV_ID;
35514779705SSam Leffler 	AH_PRIVATE(ah)->ah_macVersion = val >> AR_SREV_ID_S;
35614779705SSam Leffler 	AH_PRIVATE(ah)->ah_macRev = val & AR_SREV_REVISION;
35744834ea4SSam Leffler 	AH_PRIVATE(ah)->ah_ispcie = IS_5424(ah) || IS_2425(ah);
35814779705SSam Leffler 
35914779705SSam Leffler 	if (!ar5212IsMacSupported(AH_PRIVATE(ah)->ah_macVersion, AH_PRIVATE(ah)->ah_macRev)) {
36014779705SSam Leffler 		HALDEBUG(ah, HAL_DEBUG_ANY,
36114779705SSam Leffler 		    "%s: Mac Chip Rev 0x%02x.%x not supported\n" ,
36214779705SSam Leffler 		    __func__, AH_PRIVATE(ah)->ah_macVersion,
36314779705SSam Leffler 		    AH_PRIVATE(ah)->ah_macRev);
36414779705SSam Leffler 		ecode = HAL_ENOTSUPP;
36514779705SSam Leffler 		goto bad;
36614779705SSam Leffler 	}
36714779705SSam Leffler 
36814779705SSam Leffler 	/* setup common ini data; rf backends handle remainder */
36914779705SSam Leffler 	HAL_INI_INIT(&ahp->ah_ini_modes, ar5212Modes, 6);
37014779705SSam Leffler 	HAL_INI_INIT(&ahp->ah_ini_common, ar5212Common, 2);
37114779705SSam Leffler 
37214779705SSam Leffler 	if (!ar5212ChipReset(ah, AH_NULL)) {	/* reset chip */
37314779705SSam Leffler 		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__);
37414779705SSam Leffler 		ecode = HAL_EIO;
37514779705SSam Leffler 		goto bad;
37614779705SSam Leffler 	}
37714779705SSam Leffler 
37814779705SSam Leffler 	AH_PRIVATE(ah)->ah_phyRev = OS_REG_READ(ah, AR_PHY_CHIP_ID);
37914779705SSam Leffler 
38044834ea4SSam Leffler 	if (AH_PRIVATE(ah)->ah_ispcie) {
38114779705SSam Leffler 		/* XXX: build flag to disable this? */
382ae2a0aa4SAdrian Chadd 		ath_hal_configPCIE(ah, AH_FALSE, AH_FALSE);
38314779705SSam Leffler 	}
38414779705SSam Leffler 
38514779705SSam Leffler 	if (!ar5212ChipTest(ah)) {
38614779705SSam Leffler 		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: hardware self-test failed\n",
38714779705SSam Leffler 		    __func__);
38814779705SSam Leffler 		ecode = HAL_ESELFTEST;
38914779705SSam Leffler 		goto bad;
39014779705SSam Leffler 	}
39114779705SSam Leffler 
39214779705SSam Leffler 	/* Enable PCI core retry fix in software for Hainan and up */
39314779705SSam Leffler 	if (AH_PRIVATE(ah)->ah_macVersion >= AR_SREV_VERSION_VENICE)
39414779705SSam Leffler 		OS_REG_SET_BIT(ah, AR_PCICFG, AR_PCICFG_RETRYFIXEN);
39514779705SSam Leffler 
39614779705SSam Leffler 	/*
39714779705SSam Leffler 	 * Set correct Baseband to analog shift
39814779705SSam Leffler 	 * setting to access analog chips.
39914779705SSam Leffler 	 */
40014779705SSam Leffler 	OS_REG_WRITE(ah, AR_PHY(0), 0x00000007);
40114779705SSam Leffler 
40214779705SSam Leffler 	/* Read Radio Chip Rev Extract */
40314779705SSam Leffler 	AH_PRIVATE(ah)->ah_analog5GhzRev = ar5212GetRadioRev(ah);
40414779705SSam Leffler 
40514779705SSam Leffler 	rf = ath_hal_rfprobe(ah, &ecode);
40614779705SSam Leffler 	if (rf == AH_NULL)
40714779705SSam Leffler 		goto bad;
40814779705SSam Leffler 
40914779705SSam Leffler 	/* NB: silently accept anything in release code per Atheros */
41014779705SSam Leffler 	switch (AH_PRIVATE(ah)->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR) {
41114779705SSam Leffler 	case AR_RAD5111_SREV_MAJOR:
41214779705SSam Leffler 	case AR_RAD5112_SREV_MAJOR:
41314779705SSam Leffler 	case AR_RAD2112_SREV_MAJOR:
41414779705SSam Leffler 	case AR_RAD2111_SREV_MAJOR:
41514779705SSam Leffler 	case AR_RAD2413_SREV_MAJOR:
41614779705SSam Leffler 	case AR_RAD5413_SREV_MAJOR:
41714779705SSam Leffler 	case AR_RAD5424_SREV_MAJOR:
41814779705SSam Leffler 		break;
41914779705SSam Leffler 	default:
42014779705SSam Leffler 		if (AH_PRIVATE(ah)->ah_analog5GhzRev == 0) {
42114779705SSam Leffler 			/*
42214779705SSam Leffler 			 * When RF_Silent is used, the
42314779705SSam Leffler 			 * analog chip is reset.  So when the system boots
42414779705SSam Leffler 			 * up with the radio switch off we cannot determine
42514779705SSam Leffler 			 * the RF chip rev.  To workaround this check the
42614779705SSam Leffler 			 * mac+phy revs and if Hainan, set the radio rev
42714779705SSam Leffler 			 * to Derby.
42814779705SSam Leffler 			 */
42914779705SSam Leffler 			if (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_VENICE &&
43014779705SSam Leffler 			    AH_PRIVATE(ah)->ah_macRev == AR_SREV_HAINAN &&
43114779705SSam Leffler 			    AH_PRIVATE(ah)->ah_phyRev == AR_PHYREV_HAINAN) {
43214779705SSam Leffler 				AH_PRIVATE(ah)->ah_analog5GhzRev = AR_ANALOG5REV_HAINAN;
43314779705SSam Leffler 				break;
43414779705SSam Leffler 			}
43514779705SSam Leffler 			if (IS_2413(ah)) {		/* Griffin */
43614779705SSam Leffler 				AH_PRIVATE(ah)->ah_analog5GhzRev =
43714779705SSam Leffler 				    AR_RAD2413_SREV_MAJOR | 0x1;
43814779705SSam Leffler 				break;
43914779705SSam Leffler 			}
44014779705SSam Leffler 			if (IS_5413(ah)) {		/* Eagle */
44114779705SSam Leffler 				AH_PRIVATE(ah)->ah_analog5GhzRev =
44214779705SSam Leffler 				    AR_RAD5413_SREV_MAJOR | 0x2;
44314779705SSam Leffler 				break;
44414779705SSam Leffler 			}
44514779705SSam Leffler 			if (IS_2425(ah) || IS_2417(ah)) {/* Swan or Nala */
44614779705SSam Leffler 				AH_PRIVATE(ah)->ah_analog5GhzRev =
44714779705SSam Leffler 				    AR_RAD5424_SREV_MAJOR | 0x2;
44814779705SSam Leffler 				break;
44914779705SSam Leffler 			}
45014779705SSam Leffler 		}
45114779705SSam Leffler #ifdef AH_DEBUG
45214779705SSam Leffler 		HALDEBUG(ah, HAL_DEBUG_ANY,
45314779705SSam Leffler 		    "%s: 5G Radio Chip Rev 0x%02X is not supported by "
45414779705SSam Leffler 		    "this driver\n",
45514779705SSam Leffler 		    __func__, AH_PRIVATE(ah)->ah_analog5GhzRev);
45614779705SSam Leffler 		ecode = HAL_ENOTSUPP;
45714779705SSam Leffler 		goto bad;
45814779705SSam Leffler #endif
45914779705SSam Leffler 	}
46014779705SSam Leffler 	if (IS_RAD5112_REV1(ah)) {
46114779705SSam Leffler 		HALDEBUG(ah, HAL_DEBUG_ANY,
46214779705SSam Leffler 		    "%s: 5112 Rev 1 is not supported by this "
46314779705SSam Leffler 		    "driver (analog5GhzRev 0x%x)\n", __func__,
46414779705SSam Leffler 		    AH_PRIVATE(ah)->ah_analog5GhzRev);
46514779705SSam Leffler 		ecode = HAL_ENOTSUPP;
46614779705SSam Leffler 		goto bad;
46714779705SSam Leffler 	}
46814779705SSam Leffler 
46914779705SSam Leffler 	val = OS_REG_READ(ah, AR_PCICFG);
47014779705SSam Leffler 	val = MS(val, AR_PCICFG_EEPROM_SIZE);
47114779705SSam Leffler 	if (val == 0) {
47244834ea4SSam Leffler 		if (!AH_PRIVATE(ah)->ah_ispcie) {
47314779705SSam Leffler 			HALDEBUG(ah, HAL_DEBUG_ANY,
47414779705SSam Leffler 			    "%s: unsupported EEPROM size %u (0x%x) found\n",
47514779705SSam Leffler 			    __func__, val, val);
47614779705SSam Leffler 			ecode = HAL_EESIZE;
47714779705SSam Leffler 			goto bad;
47814779705SSam Leffler 		}
47914779705SSam Leffler 		/* XXX AH_PRIVATE(ah)->ah_isPciExpress = AH_TRUE; */
48014779705SSam Leffler 	} else if (val != AR_PCICFG_EEPROM_SIZE_16K) {
48114779705SSam Leffler 		if (AR_PCICFG_EEPROM_SIZE_FAILED == val) {
48214779705SSam Leffler 			HALDEBUG(ah, HAL_DEBUG_ANY,
48314779705SSam Leffler 			    "%s: unsupported EEPROM size %u (0x%x) found\n",
48414779705SSam Leffler 			    __func__, val, val);
48514779705SSam Leffler 			ecode = HAL_EESIZE;
48614779705SSam Leffler 			goto bad;
48714779705SSam Leffler 		}
48814779705SSam Leffler 		HALDEBUG(ah, HAL_DEBUG_ANY,
48914779705SSam Leffler 		    "%s: EEPROM size = %d. Must be %d (16k).\n",
49014779705SSam Leffler 		    __func__, val, AR_PCICFG_EEPROM_SIZE_16K);
49114779705SSam Leffler 		ecode = HAL_EESIZE;
49214779705SSam Leffler 		goto bad;
49314779705SSam Leffler 	}
49414779705SSam Leffler 	ecode = ath_hal_legacyEepromAttach(ah);
49514779705SSam Leffler 	if (ecode != HAL_OK) {
49614779705SSam Leffler 		goto bad;
49714779705SSam Leffler 	}
49814779705SSam Leffler 	ahp->ah_isHb63 = IS_2425(ah) && ath_hal_eepromGetFlag(ah, AR_EEP_ISTALON);
49914779705SSam Leffler 
50014779705SSam Leffler 	/*
50114779705SSam Leffler 	 * If Bmode and AR5212, verify 2.4 analog exists
50214779705SSam Leffler 	 */
50314779705SSam Leffler 	if (ath_hal_eepromGetFlag(ah, AR_EEP_BMODE) &&
50414779705SSam Leffler 	    (AH_PRIVATE(ah)->ah_analog5GhzRev & 0xF0) == AR_RAD5111_SREV_MAJOR) {
50514779705SSam Leffler 		/*
50614779705SSam Leffler 		 * Set correct Baseband to analog shift
50714779705SSam Leffler 		 * setting to access analog chips.
50814779705SSam Leffler 		 */
50914779705SSam Leffler 		OS_REG_WRITE(ah, AR_PHY(0), 0x00004007);
51014779705SSam Leffler 		OS_DELAY(2000);
51114779705SSam Leffler 		AH_PRIVATE(ah)->ah_analog2GhzRev = ar5212GetRadioRev(ah);
51214779705SSam Leffler 
51314779705SSam Leffler 		/* Set baseband for 5GHz chip */
51414779705SSam Leffler 		OS_REG_WRITE(ah, AR_PHY(0), 0x00000007);
51514779705SSam Leffler 		OS_DELAY(2000);
51614779705SSam Leffler 		if ((AH_PRIVATE(ah)->ah_analog2GhzRev & 0xF0) != AR_RAD2111_SREV_MAJOR) {
51714779705SSam Leffler 			HALDEBUG(ah, HAL_DEBUG_ANY,
51814779705SSam Leffler 			    "%s: 2G Radio Chip Rev 0x%02X is not "
51914779705SSam Leffler 			    "supported by this driver\n", __func__,
52014779705SSam Leffler 			    AH_PRIVATE(ah)->ah_analog2GhzRev);
52114779705SSam Leffler 			ecode = HAL_ENOTSUPP;
52214779705SSam Leffler 			goto bad;
52314779705SSam Leffler 		}
52414779705SSam Leffler 	}
52514779705SSam Leffler 
52614779705SSam Leffler 	ecode = ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, &eeval);
52714779705SSam Leffler 	if (ecode != HAL_OK) {
52814779705SSam Leffler 		HALDEBUG(ah, HAL_DEBUG_ANY,
52914779705SSam Leffler 		    "%s: cannot read regulatory domain from EEPROM\n",
53014779705SSam Leffler 		    __func__);
53114779705SSam Leffler 		goto bad;
53214779705SSam Leffler         }
53314779705SSam Leffler 	AH_PRIVATE(ah)->ah_currentRD = eeval;
53414779705SSam Leffler 	/* XXX record serial number */
53514779705SSam Leffler 
53614779705SSam Leffler 	/*
53714779705SSam Leffler 	 * Got everything we need now to setup the capabilities.
53814779705SSam Leffler 	 */
53914779705SSam Leffler 	if (!ar5212FillCapabilityInfo(ah)) {
54014779705SSam Leffler 		HALDEBUG(ah, HAL_DEBUG_ANY,
54114779705SSam Leffler 		    "%s: failed ar5212FillCapabilityInfo\n", __func__);
54214779705SSam Leffler 		ecode = HAL_EEREAD;
54314779705SSam Leffler 		goto bad;
54414779705SSam Leffler 	}
54514779705SSam Leffler 
54614779705SSam Leffler 	if (!rf->attach(ah, &ecode)) {
54714779705SSam Leffler 		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RF setup failed, status %u\n",
54814779705SSam Leffler 		    __func__, ecode);
54914779705SSam Leffler 		goto bad;
55014779705SSam Leffler 	}
55114779705SSam Leffler 	/*
55214779705SSam Leffler 	 * Set noise floor adjust method; we arrange a
55314779705SSam Leffler 	 * direct call instead of thunking.
55414779705SSam Leffler 	 */
55514779705SSam Leffler 	AH_PRIVATE(ah)->ah_getNfAdjust = ahp->ah_rfHal->getNfAdjust;
55614779705SSam Leffler 
55714779705SSam Leffler 	/* Initialize gain ladder thermal calibration structure */
55814779705SSam Leffler 	ar5212InitializeGainValues(ah);
55914779705SSam Leffler 
56014779705SSam Leffler 	ecode = ath_hal_eepromGet(ah, AR_EEP_MACADDR, ahp->ah_macaddr);
56114779705SSam Leffler 	if (ecode != HAL_OK) {
56214779705SSam Leffler 		HALDEBUG(ah, HAL_DEBUG_ANY,
56314779705SSam Leffler 		    "%s: error getting mac address from EEPROM\n", __func__);
56414779705SSam Leffler 		goto bad;
56514779705SSam Leffler         }
56614779705SSam Leffler 
56714779705SSam Leffler 	ar5212AniSetup(ah);
56814779705SSam Leffler 	/* Setup of Radar/AR structures happens in ath_hal_initchannels*/
56914779705SSam Leffler 	ar5212InitNfCalHistBuffer(ah);
57014779705SSam Leffler 
57114779705SSam Leffler 	/* XXX EAR stuff goes here */
57214779705SSam Leffler 
57314779705SSam Leffler 	HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n", __func__);
57414779705SSam Leffler 
57514779705SSam Leffler 	return ah;
57614779705SSam Leffler 
57714779705SSam Leffler bad:
57814779705SSam Leffler 	if (ahp)
57914779705SSam Leffler 		ar5212Detach((struct ath_hal *) ahp);
58014779705SSam Leffler 	if (status)
58114779705SSam Leffler 		*status = ecode;
58214779705SSam Leffler 	return AH_NULL;
58314779705SSam Leffler #undef AH_EEPROM_PROTECT
58414779705SSam Leffler }
58514779705SSam Leffler 
58614779705SSam Leffler void
ar5212Detach(struct ath_hal * ah)58714779705SSam Leffler ar5212Detach(struct ath_hal *ah)
58814779705SSam Leffler {
58914779705SSam Leffler 	HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s:\n", __func__);
59014779705SSam Leffler 
59114779705SSam Leffler 	HALASSERT(ah != AH_NULL);
59214779705SSam Leffler 	HALASSERT(ah->ah_magic == AR5212_MAGIC);
59314779705SSam Leffler 
59414779705SSam Leffler 	ar5212AniDetach(ah);
59514779705SSam Leffler 	ar5212RfDetach(ah);
59614779705SSam Leffler 	ar5212Disable(ah);
59714779705SSam Leffler 	ar5212SetPowerMode(ah, HAL_PM_FULL_SLEEP, AH_TRUE);
59814779705SSam Leffler 
59914779705SSam Leffler 	ath_hal_eepromDetach(ah);
60014779705SSam Leffler 	ath_hal_free(ah);
60114779705SSam Leffler }
60214779705SSam Leffler 
60314779705SSam Leffler HAL_BOOL
ar5212ChipTest(struct ath_hal * ah)60414779705SSam Leffler ar5212ChipTest(struct ath_hal *ah)
60514779705SSam Leffler {
60614779705SSam Leffler 	uint32_t regAddr[2] = { AR_STA_ID0, AR_PHY_BASE+(8 << 2) };
60714779705SSam Leffler 	uint32_t regHold[2];
60814779705SSam Leffler 	uint32_t patternData[4] =
60914779705SSam Leffler 	    { 0x55555555, 0xaaaaaaaa, 0x66666666, 0x99999999 };
61014779705SSam Leffler 	int i, j;
61114779705SSam Leffler 
61214779705SSam Leffler 	/* Test PHY & MAC registers */
61314779705SSam Leffler 	for (i = 0; i < 2; i++) {
61414779705SSam Leffler 		uint32_t addr = regAddr[i];
61514779705SSam Leffler 		uint32_t wrData, rdData;
61614779705SSam Leffler 
61714779705SSam Leffler 		regHold[i] = OS_REG_READ(ah, addr);
61814779705SSam Leffler 		for (j = 0; j < 0x100; j++) {
61914779705SSam Leffler 			wrData = (j << 16) | j;
62014779705SSam Leffler 			OS_REG_WRITE(ah, addr, wrData);
62114779705SSam Leffler 			rdData = OS_REG_READ(ah, addr);
62214779705SSam Leffler 			if (rdData != wrData) {
62314779705SSam Leffler 				HALDEBUG(ah, HAL_DEBUG_ANY,
62414779705SSam Leffler "%s: address test failed addr: 0x%08x - wr:0x%08x != rd:0x%08x\n",
62514779705SSam Leffler 				__func__, addr, wrData, rdData);
62614779705SSam Leffler 				return AH_FALSE;
62714779705SSam Leffler 			}
62814779705SSam Leffler 		}
62914779705SSam Leffler 		for (j = 0; j < 4; j++) {
63014779705SSam Leffler 			wrData = patternData[j];
63114779705SSam Leffler 			OS_REG_WRITE(ah, addr, wrData);
63214779705SSam Leffler 			rdData = OS_REG_READ(ah, addr);
63314779705SSam Leffler 			if (wrData != rdData) {
63414779705SSam Leffler 				HALDEBUG(ah, HAL_DEBUG_ANY,
63514779705SSam Leffler "%s: address test failed addr: 0x%08x - wr:0x%08x != rd:0x%08x\n",
63614779705SSam Leffler 					__func__, addr, wrData, rdData);
63714779705SSam Leffler 				return AH_FALSE;
63814779705SSam Leffler 			}
63914779705SSam Leffler 		}
64014779705SSam Leffler 		OS_REG_WRITE(ah, regAddr[i], regHold[i]);
64114779705SSam Leffler 	}
64214779705SSam Leffler 	OS_DELAY(100);
64314779705SSam Leffler 	return AH_TRUE;
64414779705SSam Leffler }
64514779705SSam Leffler 
64614779705SSam Leffler /*
64714779705SSam Leffler  * Store the channel edges for the requested operational mode
64814779705SSam Leffler  */
64914779705SSam Leffler HAL_BOOL
ar5212GetChannelEdges(struct ath_hal * ah,uint16_t flags,uint16_t * low,uint16_t * high)65014779705SSam Leffler ar5212GetChannelEdges(struct ath_hal *ah,
65114779705SSam Leffler 	uint16_t flags, uint16_t *low, uint16_t *high)
65214779705SSam Leffler {
65359efa8b5SSam Leffler 	if (flags & IEEE80211_CHAN_5GHZ) {
65414779705SSam Leffler 		*low = 4915;
65514779705SSam Leffler 		*high = 6100;
65614779705SSam Leffler 		return AH_TRUE;
65714779705SSam Leffler 	}
65859efa8b5SSam Leffler 	if ((flags & IEEE80211_CHAN_2GHZ) &&
65914779705SSam Leffler 	    (ath_hal_eepromGetFlag(ah, AR_EEP_BMODE) ||
66014779705SSam Leffler 	     ath_hal_eepromGetFlag(ah, AR_EEP_GMODE))) {
66114779705SSam Leffler 		*low = 2312;
66214779705SSam Leffler 		*high = 2732;
66314779705SSam Leffler 		return AH_TRUE;
66414779705SSam Leffler 	}
66514779705SSam Leffler 	return AH_FALSE;
66614779705SSam Leffler }
66714779705SSam Leffler 
66814779705SSam Leffler /*
66944834ea4SSam Leffler  * Disable PLL when in L0s as well as receiver clock when in L1.
67044834ea4SSam Leffler  * This power saving option must be enabled through the Serdes.
67144834ea4SSam Leffler  *
67244834ea4SSam Leffler  * Programming the Serdes must go through the same 288 bit serial shift
67344834ea4SSam Leffler  * register as the other analog registers.  Hence the 9 writes.
67444834ea4SSam Leffler  *
67544834ea4SSam Leffler  * XXX Clean up the magic numbers.
67644834ea4SSam Leffler  */
67744834ea4SSam Leffler static void
ar5212ConfigPCIE(struct ath_hal * ah,HAL_BOOL restore,HAL_BOOL power_off)678ae2a0aa4SAdrian Chadd ar5212ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore, HAL_BOOL power_off)
67944834ea4SSam Leffler {
68044834ea4SSam Leffler 	OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00);
68144834ea4SSam Leffler 	OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
68244834ea4SSam Leffler 
68344834ea4SSam Leffler 	/* RX shut off when elecidle is asserted */
68444834ea4SSam Leffler 	OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x28000039);
68544834ea4SSam Leffler 	OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x53160824);
68644834ea4SSam Leffler 	OS_REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980579);
68744834ea4SSam Leffler 
68844834ea4SSam Leffler 	/* Shut off PLL and CLKREQ active in L1 */
68944834ea4SSam Leffler 	OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x001defff);
69044834ea4SSam Leffler 	OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);
69144834ea4SSam Leffler 	OS_REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);
69244834ea4SSam Leffler 	OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x000e3007);
69344834ea4SSam Leffler 
69444834ea4SSam Leffler 	/* Load the new settings */
69544834ea4SSam Leffler 	OS_REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
69644834ea4SSam Leffler }
69744834ea4SSam Leffler 
69844834ea4SSam Leffler static void
ar5212DisablePCIE(struct ath_hal * ah)69944834ea4SSam Leffler ar5212DisablePCIE(struct ath_hal *ah)
70044834ea4SSam Leffler {
70144834ea4SSam Leffler 	/* NB: fill in for 9100 */
70244834ea4SSam Leffler }
70344834ea4SSam Leffler 
70444834ea4SSam Leffler /*
70514779705SSam Leffler  * Fill all software cached or static hardware state information.
70614779705SSam Leffler  * Return failure if capabilities are to come from EEPROM and
70714779705SSam Leffler  * cannot be read.
70814779705SSam Leffler  */
70914779705SSam Leffler HAL_BOOL
ar5212FillCapabilityInfo(struct ath_hal * ah)71014779705SSam Leffler ar5212FillCapabilityInfo(struct ath_hal *ah)
71114779705SSam Leffler {
71214779705SSam Leffler #define	AR_KEYTABLE_SIZE	128
71314779705SSam Leffler #define	IS_GRIFFIN_LITE(ah) \
71414779705SSam Leffler     (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_GRIFFIN && \
71514779705SSam Leffler      AH_PRIVATE(ah)->ah_macRev == AR_SREV_GRIFFIN_LITE)
71614779705SSam Leffler #define	IS_COBRA(ah) \
71714779705SSam Leffler     (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_COBRA)
71814779705SSam Leffler #define IS_2112(ah) \
71914779705SSam Leffler 	((AH_PRIVATE(ah)->ah_analog5GhzRev & 0xF0) == AR_RAD2112_SREV_MAJOR)
72014779705SSam Leffler 
72114779705SSam Leffler 	struct ath_hal_private *ahpriv = AH_PRIVATE(ah);
72214779705SSam Leffler 	HAL_CAPABILITIES *pCap = &ahpriv->ah_caps;
72314779705SSam Leffler 	uint16_t capField, val;
72414779705SSam Leffler 
72514779705SSam Leffler 	/* Read the capability EEPROM location */
72614779705SSam Leffler 	if (ath_hal_eepromGet(ah, AR_EEP_OPCAP, &capField) != HAL_OK) {
72714779705SSam Leffler 		HALDEBUG(ah, HAL_DEBUG_ANY,
72814779705SSam Leffler 		    "%s: unable to read caps from eeprom\n", __func__);
72914779705SSam Leffler 		return AH_FALSE;
73014779705SSam Leffler 	}
73114779705SSam Leffler 	if (IS_2112(ah))
73214779705SSam Leffler 		ath_hal_eepromSet(ah, AR_EEP_AMODE, AH_FALSE);
73314779705SSam Leffler 	if (capField == 0 && IS_GRIFFIN_LITE(ah)) {
73414779705SSam Leffler 		/*
73514779705SSam Leffler 		 * For griffin-lite cards with unprogrammed capabilities.
73614779705SSam Leffler 		 */
73714779705SSam Leffler 		ath_hal_eepromSet(ah, AR_EEP_COMPRESS, AH_FALSE);
73814779705SSam Leffler 		ath_hal_eepromSet(ah, AR_EEP_FASTFRAME, AH_FALSE);
73914779705SSam Leffler 		ath_hal_eepromSet(ah, AR_EEP_TURBO5DISABLE, AH_TRUE);
74014779705SSam Leffler 		ath_hal_eepromSet(ah, AR_EEP_TURBO2DISABLE, AH_TRUE);
74114779705SSam Leffler 		HALDEBUG(ah, HAL_DEBUG_ATTACH,
74214779705SSam Leffler 		    "%s: override caps for griffin-lite, now 0x%x (+!turbo)\n",
74314779705SSam Leffler 		    __func__, capField);
74414779705SSam Leffler 	}
74514779705SSam Leffler 
74614779705SSam Leffler 	/* Modify reg domain on newer cards that need to work with older sw */
74714779705SSam Leffler 	if (ahpriv->ah_opmode != HAL_M_HOSTAP &&
74814779705SSam Leffler 	    ahpriv->ah_subvendorid == AR_SUBVENDOR_ID_NEW_A) {
74914779705SSam Leffler 		if (ahpriv->ah_currentRD == 0x64 ||
75014779705SSam Leffler 		    ahpriv->ah_currentRD == 0x65)
75114779705SSam Leffler 			ahpriv->ah_currentRD += 5;
75214779705SSam Leffler 		else if (ahpriv->ah_currentRD == 0x41)
75314779705SSam Leffler 			ahpriv->ah_currentRD = 0x43;
75414779705SSam Leffler 		HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: regdomain mapped to 0x%x\n",
75514779705SSam Leffler 		    __func__, ahpriv->ah_currentRD);
75614779705SSam Leffler 	}
75714779705SSam Leffler 
75814779705SSam Leffler 	if (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_2417 ||
75914779705SSam Leffler 	    AH_PRIVATE(ah)->ah_macVersion == AR_SREV_2425) {
76014779705SSam Leffler 		HALDEBUG(ah, HAL_DEBUG_ATTACH,
76114779705SSam Leffler 		    "%s: enable Bmode and disable turbo for Swan/Nala\n",
76214779705SSam Leffler 		    __func__);
76314779705SSam Leffler 		ath_hal_eepromSet(ah, AR_EEP_BMODE, AH_TRUE);
76414779705SSam Leffler 		ath_hal_eepromSet(ah, AR_EEP_COMPRESS, AH_FALSE);
76514779705SSam Leffler 		ath_hal_eepromSet(ah, AR_EEP_FASTFRAME, AH_FALSE);
76614779705SSam Leffler 		ath_hal_eepromSet(ah, AR_EEP_TURBO5DISABLE, AH_TRUE);
76714779705SSam Leffler 		ath_hal_eepromSet(ah, AR_EEP_TURBO2DISABLE, AH_TRUE);
76814779705SSam Leffler 	}
76914779705SSam Leffler 
77014779705SSam Leffler 	/* Construct wireless mode from EEPROM */
77114779705SSam Leffler 	pCap->halWirelessModes = 0;
77214779705SSam Leffler 	if (ath_hal_eepromGetFlag(ah, AR_EEP_AMODE)) {
77314779705SSam Leffler 		pCap->halWirelessModes |= HAL_MODE_11A;
77414779705SSam Leffler 		if (!ath_hal_eepromGetFlag(ah, AR_EEP_TURBO5DISABLE))
77514779705SSam Leffler 			pCap->halWirelessModes |= HAL_MODE_TURBO;
77614779705SSam Leffler 	}
77714779705SSam Leffler 	if (ath_hal_eepromGetFlag(ah, AR_EEP_BMODE))
77814779705SSam Leffler 		pCap->halWirelessModes |= HAL_MODE_11B;
77914779705SSam Leffler 	if (ath_hal_eepromGetFlag(ah, AR_EEP_GMODE) &&
78014779705SSam Leffler 	    ahpriv->ah_subvendorid != AR_SUBVENDOR_ID_NOG) {
78114779705SSam Leffler 		pCap->halWirelessModes |= HAL_MODE_11G;
78214779705SSam Leffler 		if (!ath_hal_eepromGetFlag(ah, AR_EEP_TURBO2DISABLE))
78314779705SSam Leffler 			pCap->halWirelessModes |= HAL_MODE_108G;
78414779705SSam Leffler 	}
78514779705SSam Leffler 
78614779705SSam Leffler 	pCap->halLow2GhzChan = 2312;
78714779705SSam Leffler 	/* XXX 2417 too? */
78814779705SSam Leffler 	if (IS_RAD5112_ANY(ah) || IS_5413(ah) || IS_2425(ah) ||  IS_2417(ah))
78914779705SSam Leffler 		pCap->halHigh2GhzChan = 2500;
79014779705SSam Leffler 	else
79114779705SSam Leffler 		pCap->halHigh2GhzChan = 2732;
79214779705SSam Leffler 
793adadb607SAdrian Chadd 	/*
794adadb607SAdrian Chadd 	 * For AR5111 version < 4, the lowest centre frequency supported is
795adadb607SAdrian Chadd 	 * 5130MHz.  For AR5111 version 4, the 4.9GHz channels are supported
796adadb607SAdrian Chadd 	 * but only in 10MHz increments.
797adadb607SAdrian Chadd 	 *
798adadb607SAdrian Chadd 	 * In addition, the programming method is wrong - it uses the IEEE
799adadb607SAdrian Chadd 	 * channel number to calculate the frequency, rather than the
800adadb607SAdrian Chadd 	 * channel centre.  Since half/quarter rates re-use some of the
801adadb607SAdrian Chadd 	 * 5GHz channel IEEE numbers, this will result in a badly programmed
802adadb607SAdrian Chadd 	 * synth.
803adadb607SAdrian Chadd 	 *
804adadb607SAdrian Chadd 	 * Until the relevant support is written, just limit lower frequency
805adadb607SAdrian Chadd 	 * support for AR5111 so things aren't incorrectly programmed.
806adadb607SAdrian Chadd 	 *
807adadb607SAdrian Chadd 	 * XXX It's also possible this code doesn't correctly limit the
808adadb607SAdrian Chadd 	 * centre frequencies of potential channels; this is very important
809adadb607SAdrian Chadd 	 * for half/quarter rate!
810adadb607SAdrian Chadd 	 */
811adadb607SAdrian Chadd 	if (AH_RADIO_MAJOR(ah) == AR_RAD5111_SREV_MAJOR) {
812adadb607SAdrian Chadd 		pCap->halLow5GhzChan = 5120; /* XXX lowest centre = 5130MHz */
813adadb607SAdrian Chadd 	} else {
81414779705SSam Leffler 		pCap->halLow5GhzChan = 4915;
815adadb607SAdrian Chadd 	}
81614779705SSam Leffler 	pCap->halHigh5GhzChan = 6100;
81714779705SSam Leffler 
81814779705SSam Leffler 	pCap->halCipherCkipSupport = AH_FALSE;
81914779705SSam Leffler 	pCap->halCipherTkipSupport = AH_TRUE;
82014779705SSam Leffler 	pCap->halCipherAesCcmSupport =
82114779705SSam Leffler 		(ath_hal_eepromGetFlag(ah, AR_EEP_AES) &&
82214779705SSam Leffler 		 ((AH_PRIVATE(ah)->ah_macVersion > AR_SREV_VERSION_VENICE) ||
82314779705SSam Leffler 		  ((AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_VENICE) &&
82414779705SSam Leffler 		   (AH_PRIVATE(ah)->ah_macRev >= AR_SREV_VERSION_OAHU))));
82514779705SSam Leffler 
82614779705SSam Leffler 	pCap->halMicCkipSupport    = AH_FALSE;
82714779705SSam Leffler 	pCap->halMicTkipSupport    = AH_TRUE;
82814779705SSam Leffler 	pCap->halMicAesCcmSupport  = ath_hal_eepromGetFlag(ah, AR_EEP_AES);
82914779705SSam Leffler 	/*
83014779705SSam Leffler 	 * Starting with Griffin TX+RX mic keys can be combined
83114779705SSam Leffler 	 * in one key cache slot.
83214779705SSam Leffler 	 */
83314779705SSam Leffler 	if (AH_PRIVATE(ah)->ah_macVersion >= AR_SREV_VERSION_GRIFFIN)
83414779705SSam Leffler 		pCap->halTkipMicTxRxKeySupport = AH_TRUE;
83514779705SSam Leffler 	else
83614779705SSam Leffler 		pCap->halTkipMicTxRxKeySupport = AH_FALSE;
83714779705SSam Leffler 	pCap->halChanSpreadSupport = AH_TRUE;
83814779705SSam Leffler 	pCap->halSleepAfterBeaconBroken = AH_TRUE;
83914779705SSam Leffler 
84014779705SSam Leffler 	if (ahpriv->ah_macRev > 1 || IS_COBRA(ah)) {
84114779705SSam Leffler 		pCap->halCompressSupport   =
84214779705SSam Leffler 			ath_hal_eepromGetFlag(ah, AR_EEP_COMPRESS) &&
84314779705SSam Leffler 			(pCap->halWirelessModes & (HAL_MODE_11A|HAL_MODE_11G)) != 0;
84414779705SSam Leffler 		pCap->halBurstSupport = ath_hal_eepromGetFlag(ah, AR_EEP_BURST);
84514779705SSam Leffler 		pCap->halFastFramesSupport =
84614779705SSam Leffler 			ath_hal_eepromGetFlag(ah, AR_EEP_FASTFRAME) &&
84714779705SSam Leffler 			(pCap->halWirelessModes & (HAL_MODE_11A|HAL_MODE_11G)) != 0;
84814779705SSam Leffler 		pCap->halChapTuningSupport = AH_TRUE;
84914779705SSam Leffler 		pCap->halTurboPrimeSupport = AH_TRUE;
85014779705SSam Leffler 	}
85114779705SSam Leffler 	pCap->halTurboGSupport = pCap->halWirelessModes & HAL_MODE_108G;
85214779705SSam Leffler 
85314779705SSam Leffler 	pCap->halPSPollBroken = AH_TRUE;	/* XXX fixed in later revs? */
854ee3e4df9SAdrian Chadd 	pCap->halNumMRRetries = 4;		/* Hardware supports 4 MRR */
855217ad7d2SAdrian Chadd 	pCap->halNumTxMaps = 1;			/* Single TX ptr per descr */
85614779705SSam Leffler 	pCap->halVEOLSupport = AH_TRUE;
85714779705SSam Leffler 	pCap->halBssIdMaskSupport = AH_TRUE;
85814779705SSam Leffler 	pCap->halMcastKeySrchSupport = AH_TRUE;
85914779705SSam Leffler 	if ((ahpriv->ah_macVersion == AR_SREV_VERSION_VENICE &&
86014779705SSam Leffler 	     ahpriv->ah_macRev == 8) ||
86114779705SSam Leffler 	    ahpriv->ah_macVersion > AR_SREV_VERSION_VENICE)
86214779705SSam Leffler 		pCap->halTsfAddSupport = AH_TRUE;
86314779705SSam Leffler 
86414779705SSam Leffler 	if (ath_hal_eepromGet(ah, AR_EEP_MAXQCU, &val) == HAL_OK)
86514779705SSam Leffler 		pCap->halTotalQueues = val;
86614779705SSam Leffler 	else
86714779705SSam Leffler 		pCap->halTotalQueues = HAL_NUM_TX_QUEUES;
86814779705SSam Leffler 
86914779705SSam Leffler 	if (ath_hal_eepromGet(ah, AR_EEP_KCENTRIES, &val) == HAL_OK)
87014779705SSam Leffler 		pCap->halKeyCacheSize = val;
87114779705SSam Leffler 	else
87214779705SSam Leffler 		pCap->halKeyCacheSize = AR_KEYTABLE_SIZE;
87314779705SSam Leffler 
87414779705SSam Leffler 	pCap->halChanHalfRate = AH_TRUE;
87514779705SSam Leffler 	pCap->halChanQuarterRate = AH_TRUE;
87614779705SSam Leffler 
8777f925de1SAdrian Chadd 	/*
8787f925de1SAdrian Chadd 	 * RSSI uses the combined field; some 11n NICs may use
8797f925de1SAdrian Chadd 	 * the control chain RSSI.
8807f925de1SAdrian Chadd 	 */
8817f925de1SAdrian Chadd 	pCap->halUseCombinedRadarRssi = AH_TRUE;
8827f925de1SAdrian Chadd 
88314779705SSam Leffler 	if (ath_hal_eepromGetFlag(ah, AR_EEP_RFKILL) &&
88414779705SSam Leffler 	    ath_hal_eepromGet(ah, AR_EEP_RFSILENT, &ahpriv->ah_rfsilent) == HAL_OK) {
88514779705SSam Leffler 		/* NB: enabled by default */
88614779705SSam Leffler 		ahpriv->ah_rfkillEnabled = AH_TRUE;
88714779705SSam Leffler 		pCap->halRfSilentSupport = AH_TRUE;
88814779705SSam Leffler 	}
88914779705SSam Leffler 
89014779705SSam Leffler 	/* NB: this is a guess, no one seems to know the answer */
89114779705SSam Leffler 	ahpriv->ah_rxornIsFatal =
89214779705SSam Leffler 	    (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_VENICE);
89314779705SSam Leffler 
8943c3e9d33SSam Leffler 	/* enable features that first appeared in Hainan */
8953c3e9d33SSam Leffler 	if ((AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_VENICE &&
89614779705SSam Leffler 	     AH_PRIVATE(ah)->ah_macRev == AR_SREV_HAINAN) ||
8973c3e9d33SSam Leffler 	    AH_PRIVATE(ah)->ah_macVersion > AR_SREV_VERSION_VENICE) {
8983c3e9d33SSam Leffler 		/* h/w phy counters */
8993c3e9d33SSam Leffler 		pCap->halHwPhyCounterSupport = AH_TRUE;
9003c3e9d33SSam Leffler 		/* bssid match disable */
9013c3e9d33SSam Leffler 		pCap->halBssidMatchSupport = AH_TRUE;
9023c3e9d33SSam Leffler 	}
90314779705SSam Leffler 
90451558243SAdrian Chadd 	pCap->halRxTstampPrecision = 15;
90551558243SAdrian Chadd 	pCap->halTxTstampPrecision = 16;
906683f3134SSam Leffler 	pCap->halIntrMask = HAL_INT_COMMON
907683f3134SSam Leffler 			| HAL_INT_RX
908683f3134SSam Leffler 			| HAL_INT_TX
909683f3134SSam Leffler 			| HAL_INT_FATAL
910683f3134SSam Leffler 			| HAL_INT_BNR
911683f3134SSam Leffler 			| HAL_INT_BMISC
912683f3134SSam Leffler 			;
913210411e0SSam Leffler 	if (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_GRIFFIN)
914210411e0SSam Leffler 		pCap->halIntrMask &= ~HAL_INT_TBTT;
91514779705SSam Leffler 
916e0e5b8b4SAdrian Chadd 	pCap->hal4kbSplitTransSupport = AH_TRUE;
9178a2a6beeSAdrian Chadd 	pCap->halHasRxSelfLinkedTail = AH_TRUE;
918e0e5b8b4SAdrian Chadd 
91914779705SSam Leffler 	return AH_TRUE;
92014779705SSam Leffler #undef IS_COBRA
92114779705SSam Leffler #undef IS_GRIFFIN_LITE
92214779705SSam Leffler #undef AR_KEYTABLE_SIZE
92314779705SSam Leffler }
92414779705SSam Leffler 
92514779705SSam Leffler static const char*
ar5212Probe(uint16_t vendorid,uint16_t devid)92614779705SSam Leffler ar5212Probe(uint16_t vendorid, uint16_t devid)
92714779705SSam Leffler {
92814779705SSam Leffler 	if (vendorid == ATHEROS_VENDOR_ID ||
92914779705SSam Leffler 	    vendorid == ATHEROS_3COM_VENDOR_ID ||
93014779705SSam Leffler 	    vendorid == ATHEROS_3COM2_VENDOR_ID) {
93114779705SSam Leffler 		switch (devid) {
93214779705SSam Leffler 		case AR5212_FPGA:
93314779705SSam Leffler 			return "Atheros 5212 (FPGA)";
93414779705SSam Leffler 		case AR5212_DEVID:
93514779705SSam Leffler 		case AR5212_DEVID_IBM:
93614779705SSam Leffler 		case AR5212_DEFAULT:
93714779705SSam Leffler 			return "Atheros 5212";
93814779705SSam Leffler 		case AR5212_AR2413:
93914779705SSam Leffler 			return "Atheros 2413";
94014779705SSam Leffler 		case AR5212_AR2417:
94114779705SSam Leffler 			return "Atheros 2417";
94214779705SSam Leffler 		case AR5212_AR5413:
94314779705SSam Leffler 			return "Atheros 5413";
94414779705SSam Leffler 		case AR5212_AR5424:
94514779705SSam Leffler 			return "Atheros 5424/2424";
94614779705SSam Leffler 		}
94714779705SSam Leffler 	}
94814779705SSam Leffler 	return AH_NULL;
94914779705SSam Leffler }
95014779705SSam Leffler AH_CHIP(AR5212, ar5212Probe, ar5212Attach);
951