xref: /dflybsd-src/sys/dev/netif/ath/ath_hal/ar5312/ar5312_reset.c (revision b14ca477c2f404b36ad553a9e4f1b8b18836304e)
1572ff6f6SMatthew Dillon /*
2572ff6f6SMatthew Dillon  * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting
3572ff6f6SMatthew Dillon  * Copyright (c) 2002-2008 Atheros Communications, Inc.
4572ff6f6SMatthew Dillon  *
5572ff6f6SMatthew Dillon  * Permission to use, copy, modify, and/or distribute this software for any
6572ff6f6SMatthew Dillon  * purpose with or without fee is hereby granted, provided that the above
7572ff6f6SMatthew Dillon  * copyright notice and this permission notice appear in all copies.
8572ff6f6SMatthew Dillon  *
9572ff6f6SMatthew Dillon  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10572ff6f6SMatthew Dillon  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11572ff6f6SMatthew Dillon  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12572ff6f6SMatthew Dillon  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13572ff6f6SMatthew Dillon  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14572ff6f6SMatthew Dillon  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15572ff6f6SMatthew Dillon  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16572ff6f6SMatthew Dillon  *
17572ff6f6SMatthew Dillon  * $FreeBSD$
18572ff6f6SMatthew Dillon  */
19572ff6f6SMatthew Dillon #include "opt_ah.h"
20572ff6f6SMatthew Dillon 
21572ff6f6SMatthew Dillon #ifdef AH_SUPPORT_AR5312
22572ff6f6SMatthew Dillon 
23572ff6f6SMatthew Dillon #include "ah.h"
24572ff6f6SMatthew Dillon #include "ah_internal.h"
25572ff6f6SMatthew Dillon #include "ah_devid.h"
26572ff6f6SMatthew Dillon 
27572ff6f6SMatthew Dillon #include "ar5312/ar5312.h"
28572ff6f6SMatthew Dillon #include "ar5312/ar5312reg.h"
29572ff6f6SMatthew Dillon #include "ar5312/ar5312phy.h"
30572ff6f6SMatthew Dillon 
31572ff6f6SMatthew Dillon #include "ah_eeprom_v3.h"
32572ff6f6SMatthew Dillon 
33572ff6f6SMatthew Dillon /* Additional Time delay to wait after activiting the Base band */
34572ff6f6SMatthew Dillon #define BASE_ACTIVATE_DELAY	100	/* 100 usec */
35572ff6f6SMatthew Dillon #define PLL_SETTLE_DELAY	300	/* 300 usec */
36572ff6f6SMatthew Dillon 
37572ff6f6SMatthew Dillon extern int16_t ar5212GetNf(struct ath_hal *, const struct ieee80211_channel *);
38572ff6f6SMatthew Dillon extern void ar5212SetRateDurationTable(struct ath_hal *,
39572ff6f6SMatthew Dillon 		const struct ieee80211_channel *);
40572ff6f6SMatthew Dillon extern HAL_BOOL ar5212SetTransmitPower(struct ath_hal *ah,
41572ff6f6SMatthew Dillon 	         const struct ieee80211_channel *chan, uint16_t *rfXpdGain);
42572ff6f6SMatthew Dillon extern void ar5212SetDeltaSlope(struct ath_hal *,
43572ff6f6SMatthew Dillon 		 const struct ieee80211_channel *);
44572ff6f6SMatthew Dillon extern HAL_BOOL ar5212SetBoardValues(struct ath_hal *,
45572ff6f6SMatthew Dillon 		 const struct ieee80211_channel *);
46572ff6f6SMatthew Dillon extern void ar5212SetIFSTiming(struct ath_hal *,
47572ff6f6SMatthew Dillon 		 const struct ieee80211_channel *);
48572ff6f6SMatthew Dillon extern HAL_BOOL	ar5212IsSpurChannel(struct ath_hal *,
49572ff6f6SMatthew Dillon 		 const struct ieee80211_channel *);
50572ff6f6SMatthew Dillon extern HAL_BOOL	ar5212ChannelChange(struct ath_hal *,
51572ff6f6SMatthew Dillon 		 const struct ieee80211_channel *);
52572ff6f6SMatthew Dillon 
53572ff6f6SMatthew Dillon static HAL_BOOL ar5312SetResetReg(struct ath_hal *, uint32_t resetMask);
54572ff6f6SMatthew Dillon 
55572ff6f6SMatthew Dillon static int
write_common(struct ath_hal * ah,const HAL_INI_ARRAY * ia,HAL_BOOL bChannelChange,int writes)56572ff6f6SMatthew Dillon write_common(struct ath_hal *ah, const HAL_INI_ARRAY *ia,
57572ff6f6SMatthew Dillon 	HAL_BOOL bChannelChange, int writes)
58572ff6f6SMatthew Dillon {
59572ff6f6SMatthew Dillon #define IS_NO_RESET_TIMER_ADDR(x)                      \
60572ff6f6SMatthew Dillon     ( (((x) >= AR_BEACON) && ((x) <= AR_CFP_DUR)) || \
61572ff6f6SMatthew Dillon       (((x) >= AR_SLEEP1) && ((x) <= AR_SLEEP3)))
62572ff6f6SMatthew Dillon #define	V(r, c)	(ia)->data[((r)*(ia)->cols) + (c)]
63572ff6f6SMatthew Dillon 	int i;
64572ff6f6SMatthew Dillon 
65572ff6f6SMatthew Dillon 	/* Write Common Array Parameters */
66572ff6f6SMatthew Dillon 	for (i = 0; i < ia->rows; i++) {
67572ff6f6SMatthew Dillon 		uint32_t reg = V(i, 0);
68572ff6f6SMatthew Dillon 		/* XXX timer/beacon setup registers? */
69572ff6f6SMatthew Dillon 		/* On channel change, don't reset the PCU registers */
70572ff6f6SMatthew Dillon 		if (!(bChannelChange && IS_NO_RESET_TIMER_ADDR(reg))) {
71572ff6f6SMatthew Dillon 			OS_REG_WRITE(ah, reg, V(i, 1));
72572ff6f6SMatthew Dillon 			DMA_YIELD(writes);
73572ff6f6SMatthew Dillon 		}
74572ff6f6SMatthew Dillon 	}
75572ff6f6SMatthew Dillon 	return writes;
76572ff6f6SMatthew Dillon #undef IS_NO_RESET_TIMER_ADDR
77572ff6f6SMatthew Dillon #undef V
78572ff6f6SMatthew Dillon }
79572ff6f6SMatthew Dillon 
80572ff6f6SMatthew Dillon /*
81572ff6f6SMatthew Dillon  * Places the device in and out of reset and then places sane
82572ff6f6SMatthew Dillon  * values in the registers based on EEPROM config, initialization
83572ff6f6SMatthew Dillon  * vectors (as determined by the mode), and station configuration
84572ff6f6SMatthew Dillon  *
85572ff6f6SMatthew Dillon  * bChannelChange is used to preserve DMA/PCU registers across
86572ff6f6SMatthew Dillon  * a HW Reset during channel change.
87572ff6f6SMatthew Dillon  */
88572ff6f6SMatthew Dillon HAL_BOOL
ar5312Reset(struct ath_hal * ah,HAL_OPMODE opmode,struct ieee80211_channel * chan,HAL_BOOL bChannelChange,HAL_RESET_TYPE resetType,HAL_STATUS * status)89572ff6f6SMatthew Dillon ar5312Reset(struct ath_hal *ah, HAL_OPMODE opmode,
90572ff6f6SMatthew Dillon 	struct ieee80211_channel *chan,
91*b14ca477SMatthew Dillon 	HAL_BOOL bChannelChange,
92*b14ca477SMatthew Dillon 	HAL_RESET_TYPE resetType,
93*b14ca477SMatthew Dillon 	HAL_STATUS *status)
94572ff6f6SMatthew Dillon {
95572ff6f6SMatthew Dillon #define	N(a)	(sizeof (a) / sizeof (a[0]))
96572ff6f6SMatthew Dillon #define	FAIL(_code)	do { ecode = _code; goto bad; } while (0)
97572ff6f6SMatthew Dillon 	struct ath_hal_5212 *ahp = AH5212(ah);
98572ff6f6SMatthew Dillon 	HAL_CHANNEL_INTERNAL *ichan;
99572ff6f6SMatthew Dillon 	const HAL_EEPROM *ee;
100572ff6f6SMatthew Dillon 	uint32_t saveFrameSeqCount, saveDefAntenna;
101572ff6f6SMatthew Dillon 	uint32_t macStaId1, synthDelay, txFrm2TxDStart;
102572ff6f6SMatthew Dillon 	uint16_t rfXpdGain[MAX_NUM_PDGAINS_PER_CHANNEL];
103572ff6f6SMatthew Dillon 	int16_t cckOfdmPwrDelta = 0;
104572ff6f6SMatthew Dillon 	u_int modesIndex, freqIndex;
105572ff6f6SMatthew Dillon 	HAL_STATUS ecode;
106572ff6f6SMatthew Dillon 	int i, regWrites = 0;
107572ff6f6SMatthew Dillon 	uint32_t testReg;
108572ff6f6SMatthew Dillon 	uint32_t saveLedState = 0;
109572ff6f6SMatthew Dillon 
110572ff6f6SMatthew Dillon 	HALASSERT(ah->ah_magic == AR5212_MAGIC);
111572ff6f6SMatthew Dillon 	ee = AH_PRIVATE(ah)->ah_eeprom;
112572ff6f6SMatthew Dillon 
113572ff6f6SMatthew Dillon 	OS_MARK(ah, AH_MARK_RESET, bChannelChange);
114572ff6f6SMatthew Dillon 	/*
115572ff6f6SMatthew Dillon 	 * Map public channel to private.
116572ff6f6SMatthew Dillon 	 */
117572ff6f6SMatthew Dillon 	ichan = ath_hal_checkchannel(ah, chan);
118572ff6f6SMatthew Dillon 	if (ichan == AH_NULL) {
119572ff6f6SMatthew Dillon 		HALDEBUG(ah, HAL_DEBUG_ANY,
120572ff6f6SMatthew Dillon 		    "%s: invalid channel %u/0x%x; no mapping\n",
121572ff6f6SMatthew Dillon 		    __func__, chan->ic_freq, chan->ic_flags);
122572ff6f6SMatthew Dillon 		FAIL(HAL_EINVAL);
123572ff6f6SMatthew Dillon 	}
124572ff6f6SMatthew Dillon 	switch (opmode) {
125572ff6f6SMatthew Dillon 	case HAL_M_STA:
126572ff6f6SMatthew Dillon 	case HAL_M_IBSS:
127572ff6f6SMatthew Dillon 	case HAL_M_HOSTAP:
128572ff6f6SMatthew Dillon 	case HAL_M_MONITOR:
129572ff6f6SMatthew Dillon 		break;
130572ff6f6SMatthew Dillon 	default:
131572ff6f6SMatthew Dillon 		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid operating mode %u\n",
132572ff6f6SMatthew Dillon 		    __func__, opmode);
133572ff6f6SMatthew Dillon 		FAIL(HAL_EINVAL);
134572ff6f6SMatthew Dillon 		break;
135572ff6f6SMatthew Dillon 	}
136572ff6f6SMatthew Dillon 	HALASSERT(ahp->ah_eeversion >= AR_EEPROM_VER3);
137572ff6f6SMatthew Dillon 
138572ff6f6SMatthew Dillon 	/* Preserve certain DMA hardware registers on a channel change */
139572ff6f6SMatthew Dillon 	if (bChannelChange) {
140572ff6f6SMatthew Dillon 		/*
141572ff6f6SMatthew Dillon 		 * On Venice, the TSF is almost preserved across a reset;
142572ff6f6SMatthew Dillon 		 * it requires the doubling writes to the RESET_TSF
143572ff6f6SMatthew Dillon 		 * bit in the AR_BEACON register; it also has the quirk
144572ff6f6SMatthew Dillon 		 * of the TSF going back in time on the station (station
145572ff6f6SMatthew Dillon 		 * latches onto the last beacon's tsf during a reset 50%
146572ff6f6SMatthew Dillon 		 * of the times); the latter is not a problem for adhoc
147572ff6f6SMatthew Dillon 		 * stations since as long as the TSF is behind, it will
148572ff6f6SMatthew Dillon 		 * get resynchronized on receiving the next beacon; the
149572ff6f6SMatthew Dillon 		 * TSF going backwards in time could be a problem for the
150572ff6f6SMatthew Dillon 		 * sleep operation (supported on infrastructure stations
151572ff6f6SMatthew Dillon 		 * only) - the best and most general fix for this situation
152572ff6f6SMatthew Dillon 		 * is to resynchronize the various sleep/beacon timers on
153572ff6f6SMatthew Dillon 		 * the receipt of the next beacon i.e. when the TSF itself
154572ff6f6SMatthew Dillon 		 * gets resynchronized to the AP's TSF - power save is
155572ff6f6SMatthew Dillon 		 * needed to be temporarily disabled until that time
156572ff6f6SMatthew Dillon 		 *
157572ff6f6SMatthew Dillon 		 * Need to save the sequence number to restore it after
158572ff6f6SMatthew Dillon 		 * the reset!
159572ff6f6SMatthew Dillon 		 */
160572ff6f6SMatthew Dillon 		saveFrameSeqCount = OS_REG_READ(ah, AR_D_SEQNUM);
161572ff6f6SMatthew Dillon 	} else
162572ff6f6SMatthew Dillon 		saveFrameSeqCount = 0;		/* NB: silence compiler */
163572ff6f6SMatthew Dillon 
164572ff6f6SMatthew Dillon 	/* If the channel change is across the same mode - perform a fast channel change */
165572ff6f6SMatthew Dillon 	if ((IS_2413(ah) || IS_5413(ah))) {
166572ff6f6SMatthew Dillon 		/*
167572ff6f6SMatthew Dillon 		 * Channel change can only be used when:
168572ff6f6SMatthew Dillon 		 *  -channel change requested - so it's not the initial reset.
169572ff6f6SMatthew Dillon 		 *  -it's not a change to the current channel - often called when switching modes
170572ff6f6SMatthew Dillon 		 *   on a channel
171572ff6f6SMatthew Dillon 		 *  -the modes of the previous and requested channel are the same - some ugly code for XR
172572ff6f6SMatthew Dillon 		 */
173572ff6f6SMatthew Dillon 		if (bChannelChange &&
174572ff6f6SMatthew Dillon 		    AH_PRIVATE(ah)->ah_curchan != AH_NULL &&
175572ff6f6SMatthew Dillon 		    (chan->ic_freq != AH_PRIVATE(ah)->ah_curchan->ic_freq) &&
176572ff6f6SMatthew Dillon 		    ((chan->ic_flags & IEEE80211_CHAN_ALLTURBO) ==
177572ff6f6SMatthew Dillon 		     (AH_PRIVATE(ah)->ah_curchan->ic_flags & IEEE80211_CHAN_ALLTURBO))) {
178572ff6f6SMatthew Dillon 			if (ar5212ChannelChange(ah, chan))
179572ff6f6SMatthew Dillon 				/* If ChannelChange completed - skip the rest of reset */
180572ff6f6SMatthew Dillon 				return AH_TRUE;
181572ff6f6SMatthew Dillon 		}
182572ff6f6SMatthew Dillon 	}
183572ff6f6SMatthew Dillon 
184572ff6f6SMatthew Dillon 	/*
185572ff6f6SMatthew Dillon 	 * Preserve the antenna on a channel change
186572ff6f6SMatthew Dillon 	 */
187572ff6f6SMatthew Dillon 	saveDefAntenna = OS_REG_READ(ah, AR_DEF_ANTENNA);
188572ff6f6SMatthew Dillon 	if (saveDefAntenna == 0)		/* XXX magic constants */
189572ff6f6SMatthew Dillon 		saveDefAntenna = 1;
190572ff6f6SMatthew Dillon 
191572ff6f6SMatthew Dillon 	/* Save hardware flag before chip reset clears the register */
192572ff6f6SMatthew Dillon 	macStaId1 = OS_REG_READ(ah, AR_STA_ID1) &
193572ff6f6SMatthew Dillon 		(AR_STA_ID1_BASE_RATE_11B | AR_STA_ID1_USE_DEFANT);
194572ff6f6SMatthew Dillon 
195572ff6f6SMatthew Dillon 	/* Save led state from pci config register */
196572ff6f6SMatthew Dillon 	if (!IS_5315(ah))
197572ff6f6SMatthew Dillon 		saveLedState = OS_REG_READ(ah, AR5312_PCICFG) &
198572ff6f6SMatthew Dillon 			(AR_PCICFG_LEDCTL | AR_PCICFG_LEDMODE | AR_PCICFG_LEDBLINK |
199572ff6f6SMatthew Dillon 			 AR_PCICFG_LEDSLOW);
200572ff6f6SMatthew Dillon 
201572ff6f6SMatthew Dillon 	ar5312RestoreClock(ah, opmode);		/* move to refclk operation */
202572ff6f6SMatthew Dillon 
203572ff6f6SMatthew Dillon 	/*
204572ff6f6SMatthew Dillon 	 * Adjust gain parameters before reset if
205572ff6f6SMatthew Dillon 	 * there's an outstanding gain updated.
206572ff6f6SMatthew Dillon 	 */
207572ff6f6SMatthew Dillon 	(void) ar5212GetRfgain(ah);
208572ff6f6SMatthew Dillon 
209572ff6f6SMatthew Dillon 	if (!ar5312ChipReset(ah, chan)) {
210572ff6f6SMatthew Dillon 		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__);
211572ff6f6SMatthew Dillon 		FAIL(HAL_EIO);
212572ff6f6SMatthew Dillon 	}
213572ff6f6SMatthew Dillon 
214572ff6f6SMatthew Dillon 	/* Setup the indices for the next set of register array writes */
215572ff6f6SMatthew Dillon 	if (IEEE80211_IS_CHAN_2GHZ(chan)) {
216572ff6f6SMatthew Dillon 		freqIndex  = 2;
217572ff6f6SMatthew Dillon 		modesIndex = IEEE80211_IS_CHAN_108G(chan) ? 5 :
218572ff6f6SMatthew Dillon 			     IEEE80211_IS_CHAN_G(chan) ? 4 : 3;
219572ff6f6SMatthew Dillon 	} else {
220572ff6f6SMatthew Dillon 		freqIndex  = 1;
221572ff6f6SMatthew Dillon 		modesIndex = IEEE80211_IS_CHAN_ST(chan) ? 2 : 1;
222572ff6f6SMatthew Dillon 	}
223572ff6f6SMatthew Dillon 
224572ff6f6SMatthew Dillon 	OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__);
225572ff6f6SMatthew Dillon 
226572ff6f6SMatthew Dillon 	/* Set correct Baseband to analog shift setting to access analog chips. */
227572ff6f6SMatthew Dillon 	OS_REG_WRITE(ah, AR_PHY(0), 0x00000007);
228572ff6f6SMatthew Dillon 
229572ff6f6SMatthew Dillon 	regWrites = ath_hal_ini_write(ah, &ahp->ah_ini_modes, modesIndex, 0);
230572ff6f6SMatthew Dillon 	regWrites = write_common(ah, &ahp->ah_ini_common, bChannelChange,
231572ff6f6SMatthew Dillon 		regWrites);
232572ff6f6SMatthew Dillon 	ahp->ah_rfHal->writeRegs(ah, modesIndex, freqIndex, regWrites);
233572ff6f6SMatthew Dillon 
234572ff6f6SMatthew Dillon 	OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__);
235572ff6f6SMatthew Dillon 
236572ff6f6SMatthew Dillon 	if (IEEE80211_IS_CHAN_HALF(chan) || IEEE80211_IS_CHAN_QUARTER(chan))
237572ff6f6SMatthew Dillon 		ar5212SetIFSTiming(ah, chan);
238572ff6f6SMatthew Dillon 
239572ff6f6SMatthew Dillon 	/* Overwrite INI values for revised chipsets */
240572ff6f6SMatthew Dillon 	if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_2) {
241572ff6f6SMatthew Dillon 		/* ADC_CTL */
242572ff6f6SMatthew Dillon 		OS_REG_WRITE(ah, AR_PHY_ADC_CTL,
243572ff6f6SMatthew Dillon 			     SM(2, AR_PHY_ADC_CTL_OFF_INBUFGAIN) |
244572ff6f6SMatthew Dillon 			     SM(2, AR_PHY_ADC_CTL_ON_INBUFGAIN) |
245572ff6f6SMatthew Dillon 			     AR_PHY_ADC_CTL_OFF_PWDDAC |
246572ff6f6SMatthew Dillon 			     AR_PHY_ADC_CTL_OFF_PWDADC);
247572ff6f6SMatthew Dillon 
248572ff6f6SMatthew Dillon 		/* TX_PWR_ADJ */
249572ff6f6SMatthew Dillon 		if (chan->channel == 2484) {
250572ff6f6SMatthew Dillon 			cckOfdmPwrDelta = SCALE_OC_DELTA(ee->ee_cckOfdmPwrDelta - ee->ee_scaledCh14FilterCckDelta);
251572ff6f6SMatthew Dillon 		} else {
252572ff6f6SMatthew Dillon 			cckOfdmPwrDelta = SCALE_OC_DELTA(ee->ee_cckOfdmPwrDelta);
253572ff6f6SMatthew Dillon 		}
254572ff6f6SMatthew Dillon 
255572ff6f6SMatthew Dillon 		if (IEEE80211_IS_CHAN_G(chan)) {
256572ff6f6SMatthew Dillon 			OS_REG_WRITE(ah, AR_PHY_TXPWRADJ,
257572ff6f6SMatthew Dillon 				     SM((ee->ee_cckOfdmPwrDelta*-1), AR_PHY_TXPWRADJ_CCK_GAIN_DELTA) |
258572ff6f6SMatthew Dillon 				     SM((cckOfdmPwrDelta*-1), AR_PHY_TXPWRADJ_CCK_PCDAC_INDEX));
259572ff6f6SMatthew Dillon 		} else {
260572ff6f6SMatthew Dillon 			OS_REG_WRITE(ah, AR_PHY_TXPWRADJ, 0);
261572ff6f6SMatthew Dillon 		}
262572ff6f6SMatthew Dillon 
263572ff6f6SMatthew Dillon 		/* Add barker RSSI thresh enable as disabled */
264572ff6f6SMatthew Dillon 		OS_REG_CLR_BIT(ah, AR_PHY_DAG_CTRLCCK,
265572ff6f6SMatthew Dillon 			       AR_PHY_DAG_CTRLCCK_EN_RSSI_THR);
266572ff6f6SMatthew Dillon 		OS_REG_RMW_FIELD(ah, AR_PHY_DAG_CTRLCCK,
267572ff6f6SMatthew Dillon 				 AR_PHY_DAG_CTRLCCK_RSSI_THR, 2);
268572ff6f6SMatthew Dillon 
269572ff6f6SMatthew Dillon 		/* Set the mute mask to the correct default */
270572ff6f6SMatthew Dillon 		OS_REG_WRITE(ah, AR_SEQ_MASK, 0x0000000F);
271572ff6f6SMatthew Dillon 	}
272572ff6f6SMatthew Dillon 
273572ff6f6SMatthew Dillon 	if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_3) {
274572ff6f6SMatthew Dillon 		/* Clear reg to alllow RX_CLEAR line debug */
275572ff6f6SMatthew Dillon 		OS_REG_WRITE(ah, AR_PHY_BLUETOOTH,  0);
276572ff6f6SMatthew Dillon 	}
277572ff6f6SMatthew Dillon 	if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_4) {
278572ff6f6SMatthew Dillon #ifdef notyet
279572ff6f6SMatthew Dillon 		/* Enable burst prefetch for the data queues */
280572ff6f6SMatthew Dillon 		OS_REG_RMW_FIELD(ah, AR_D_FPCTL, ... );
281572ff6f6SMatthew Dillon 		/* Enable double-buffering */
282572ff6f6SMatthew Dillon 		OS_REG_CLR_BIT(ah, AR_TXCFG, AR_TXCFG_DBL_BUF_DIS);
283572ff6f6SMatthew Dillon #endif
284572ff6f6SMatthew Dillon 	}
285572ff6f6SMatthew Dillon 
286572ff6f6SMatthew Dillon 	if (IS_5312_2_X(ah)) {
287572ff6f6SMatthew Dillon 		/* ADC_CTRL */
288572ff6f6SMatthew Dillon 		OS_REG_WRITE(ah, AR_PHY_SIGMA_DELTA,
289572ff6f6SMatthew Dillon 			     SM(2, AR_PHY_SIGMA_DELTA_ADC_SEL) |
290572ff6f6SMatthew Dillon 			     SM(4, AR_PHY_SIGMA_DELTA_FILT2) |
291572ff6f6SMatthew Dillon 			     SM(0x16, AR_PHY_SIGMA_DELTA_FILT1) |
292572ff6f6SMatthew Dillon 			     SM(0, AR_PHY_SIGMA_DELTA_ADC_CLIP));
293572ff6f6SMatthew Dillon 
294572ff6f6SMatthew Dillon 		if (IEEE80211_IS_CHAN_2GHZ(chan))
295572ff6f6SMatthew Dillon 			OS_REG_RMW_FIELD(ah, AR_PHY_RXGAIN, AR_PHY_RXGAIN_TXRX_RF_MAX, 0x0F);
296572ff6f6SMatthew Dillon 
297572ff6f6SMatthew Dillon 		/* CCK Short parameter adjustment in 11B mode */
298572ff6f6SMatthew Dillon 		if (IEEE80211_IS_CHAN_B(chan))
299572ff6f6SMatthew Dillon 			OS_REG_RMW_FIELD(ah, AR_PHY_CCK_RXCTRL4, AR_PHY_CCK_RXCTRL4_FREQ_EST_SHORT, 12);
300572ff6f6SMatthew Dillon 
301572ff6f6SMatthew Dillon 		/* Set ADC/DAC select values */
302572ff6f6SMatthew Dillon 		OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x04);
303572ff6f6SMatthew Dillon 
304572ff6f6SMatthew Dillon 		/* Increase 11A AGC Settling */
305572ff6f6SMatthew Dillon 		if (IEEE80211_IS_CHAN_A(chan))
306572ff6f6SMatthew Dillon 			OS_REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_AGC, 32);
307572ff6f6SMatthew Dillon 	} else {
308572ff6f6SMatthew Dillon 		/* Set ADC/DAC select values */
309572ff6f6SMatthew Dillon 		OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0e);
310572ff6f6SMatthew Dillon 	}
311572ff6f6SMatthew Dillon 
312572ff6f6SMatthew Dillon 	/* Setup the transmit power values. */
313572ff6f6SMatthew Dillon 	if (!ar5212SetTransmitPower(ah, chan, rfXpdGain)) {
314572ff6f6SMatthew Dillon 		HALDEBUG(ah, HAL_DEBUG_ANY,
315572ff6f6SMatthew Dillon 		    "%s: error init'ing transmit power\n", __func__);
316572ff6f6SMatthew Dillon 		FAIL(HAL_EIO);
317572ff6f6SMatthew Dillon 	}
318572ff6f6SMatthew Dillon 
319572ff6f6SMatthew Dillon 	/* Write the analog registers */
320572ff6f6SMatthew Dillon 	if (!ahp->ah_rfHal->setRfRegs(ah, chan, modesIndex, rfXpdGain)) {
321572ff6f6SMatthew Dillon 		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: ar5212SetRfRegs failed\n",
322572ff6f6SMatthew Dillon 		    __func__);
323572ff6f6SMatthew Dillon 		FAIL(HAL_EIO);
324572ff6f6SMatthew Dillon 	}
325572ff6f6SMatthew Dillon 
326572ff6f6SMatthew Dillon 	/* Write delta slope for OFDM enabled modes (A, G, Turbo) */
327572ff6f6SMatthew Dillon 	if (IEEE80211_IS_CHAN_OFDM(chan)) {
328572ff6f6SMatthew Dillon 		if (IS_5413(ah) ||
329572ff6f6SMatthew Dillon 		   AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER5_3)
330572ff6f6SMatthew Dillon 			ar5212SetSpurMitigation(ah, chan);
331572ff6f6SMatthew Dillon 		ar5212SetDeltaSlope(ah, chan);
332572ff6f6SMatthew Dillon 	}
333572ff6f6SMatthew Dillon 
334572ff6f6SMatthew Dillon 	/* Setup board specific options for EEPROM version 3 */
335572ff6f6SMatthew Dillon 	if (!ar5212SetBoardValues(ah, chan)) {
336572ff6f6SMatthew Dillon 		HALDEBUG(ah, HAL_DEBUG_ANY,
337572ff6f6SMatthew Dillon 		    "%s: error setting board options\n", __func__);
338572ff6f6SMatthew Dillon 		FAIL(HAL_EIO);
339572ff6f6SMatthew Dillon 	}
340572ff6f6SMatthew Dillon 
341572ff6f6SMatthew Dillon 	/* Restore certain DMA hardware registers on a channel change */
342572ff6f6SMatthew Dillon 	if (bChannelChange)
343572ff6f6SMatthew Dillon 		OS_REG_WRITE(ah, AR_D_SEQNUM, saveFrameSeqCount);
344572ff6f6SMatthew Dillon 
345572ff6f6SMatthew Dillon 	OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__);
346572ff6f6SMatthew Dillon 
347572ff6f6SMatthew Dillon 	OS_REG_WRITE(ah, AR_STA_ID0, LE_READ_4(ahp->ah_macaddr));
348572ff6f6SMatthew Dillon 	OS_REG_WRITE(ah, AR_STA_ID1, LE_READ_2(ahp->ah_macaddr + 4)
349572ff6f6SMatthew Dillon 		| macStaId1
350572ff6f6SMatthew Dillon 		| AR_STA_ID1_RTS_USE_DEF
351572ff6f6SMatthew Dillon 		| ahp->ah_staId1Defaults
352572ff6f6SMatthew Dillon 	);
353572ff6f6SMatthew Dillon 	ar5212SetOperatingMode(ah, opmode);
354572ff6f6SMatthew Dillon 
355572ff6f6SMatthew Dillon 	/* Set Venice BSSID mask according to current state */
356572ff6f6SMatthew Dillon 	OS_REG_WRITE(ah, AR_BSSMSKL, LE_READ_4(ahp->ah_bssidmask));
357572ff6f6SMatthew Dillon 	OS_REG_WRITE(ah, AR_BSSMSKU, LE_READ_2(ahp->ah_bssidmask + 4));
358572ff6f6SMatthew Dillon 
359572ff6f6SMatthew Dillon 	/* Restore previous led state */
360572ff6f6SMatthew Dillon 	if (!IS_5315(ah))
361572ff6f6SMatthew Dillon 		OS_REG_WRITE(ah, AR5312_PCICFG, OS_REG_READ(ah, AR_PCICFG) | saveLedState);
362572ff6f6SMatthew Dillon 
363572ff6f6SMatthew Dillon 	/* Restore previous antenna */
364572ff6f6SMatthew Dillon 	OS_REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna);
365572ff6f6SMatthew Dillon 
366572ff6f6SMatthew Dillon 	/* then our BSSID */
367572ff6f6SMatthew Dillon 	OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid));
368572ff6f6SMatthew Dillon 	OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid + 4));
369572ff6f6SMatthew Dillon 
370572ff6f6SMatthew Dillon 	/* Restore bmiss rssi & count thresholds */
371572ff6f6SMatthew Dillon 	OS_REG_WRITE(ah, AR_RSSI_THR, ahp->ah_rssiThr);
372572ff6f6SMatthew Dillon 
373572ff6f6SMatthew Dillon 	OS_REG_WRITE(ah, AR_ISR, ~0);		/* cleared on write */
374572ff6f6SMatthew Dillon 
375572ff6f6SMatthew Dillon 	if (!ar5212SetChannel(ah, chan))
376572ff6f6SMatthew Dillon 		FAIL(HAL_EIO);
377572ff6f6SMatthew Dillon 
378572ff6f6SMatthew Dillon 	OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__);
379572ff6f6SMatthew Dillon 
380572ff6f6SMatthew Dillon 	ar5212SetCoverageClass(ah, AH_PRIVATE(ah)->ah_coverageClass, 1);
381572ff6f6SMatthew Dillon 
382572ff6f6SMatthew Dillon 	ar5212SetRateDurationTable(ah, chan);
383572ff6f6SMatthew Dillon 
384572ff6f6SMatthew Dillon 	/* Set Tx frame start to tx data start delay */
385572ff6f6SMatthew Dillon 	if (IS_RAD5112_ANY(ah) &&
386572ff6f6SMatthew Dillon 	    (IEEE80211_IS_CHAN_HALF(chan) || IEEE80211_IS_CHAN_QUARTER(chan))) {
387572ff6f6SMatthew Dillon 		txFrm2TxDStart =
388572ff6f6SMatthew Dillon 			IEEE80211_IS_CHAN_HALF(chan) ?
389572ff6f6SMatthew Dillon 					TX_FRAME_D_START_HALF_RATE:
390572ff6f6SMatthew Dillon 					TX_FRAME_D_START_QUARTER_RATE;
391572ff6f6SMatthew Dillon 		OS_REG_RMW_FIELD(ah, AR_PHY_TX_CTL,
392572ff6f6SMatthew Dillon 			AR_PHY_TX_FRAME_TO_TX_DATA_START, txFrm2TxDStart);
393572ff6f6SMatthew Dillon 	}
394572ff6f6SMatthew Dillon 
395572ff6f6SMatthew Dillon 	/*
396572ff6f6SMatthew Dillon 	 * Setup fast diversity.
397572ff6f6SMatthew Dillon 	 * Fast diversity can be enabled or disabled via regadd.txt.
398572ff6f6SMatthew Dillon 	 * Default is enabled.
399572ff6f6SMatthew Dillon 	 * For reference,
400572ff6f6SMatthew Dillon 	 *    Disable: reg        val
401572ff6f6SMatthew Dillon 	 *             0x00009860 0x00009d18 (if 11a / 11g, else no change)
402572ff6f6SMatthew Dillon 	 *             0x00009970 0x192bb514
403572ff6f6SMatthew Dillon 	 *             0x0000a208 0xd03e4648
404572ff6f6SMatthew Dillon 	 *
405572ff6f6SMatthew Dillon 	 *    Enable:  0x00009860 0x00009d10 (if 11a / 11g, else no change)
406572ff6f6SMatthew Dillon 	 *             0x00009970 0x192fb514
407572ff6f6SMatthew Dillon 	 *             0x0000a208 0xd03e6788
408572ff6f6SMatthew Dillon 	 */
409572ff6f6SMatthew Dillon 
410572ff6f6SMatthew Dillon 	/* XXX Setup pre PHY ENABLE EAR additions */
411572ff6f6SMatthew Dillon 
412572ff6f6SMatthew Dillon 	/* flush SCAL reg */
413572ff6f6SMatthew Dillon 	if (IS_5312_2_X(ah)) {
414572ff6f6SMatthew Dillon 		(void) OS_REG_READ(ah, AR_PHY_SLEEP_SCAL);
415572ff6f6SMatthew Dillon 	}
416572ff6f6SMatthew Dillon 
417572ff6f6SMatthew Dillon 	/*
418572ff6f6SMatthew Dillon 	 * Wait for the frequency synth to settle (synth goes on
419572ff6f6SMatthew Dillon 	 * via AR_PHY_ACTIVE_EN).  Read the phy active delay register.
420572ff6f6SMatthew Dillon 	 * Value is in 100ns increments.
421572ff6f6SMatthew Dillon 	 */
422572ff6f6SMatthew Dillon 	synthDelay = OS_REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;
423572ff6f6SMatthew Dillon 	if (IEEE80211_IS_CHAN_B(chan)) {
424572ff6f6SMatthew Dillon 		synthDelay = (4 * synthDelay) / 22;
425572ff6f6SMatthew Dillon 	} else {
426572ff6f6SMatthew Dillon 		synthDelay /= 10;
427572ff6f6SMatthew Dillon 	}
428572ff6f6SMatthew Dillon 
429572ff6f6SMatthew Dillon 	/* Activate the PHY (includes baseband activate and synthesizer on) */
430572ff6f6SMatthew Dillon 	OS_REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
431572ff6f6SMatthew Dillon 
432572ff6f6SMatthew Dillon 	/*
433572ff6f6SMatthew Dillon 	 * There is an issue if the AP starts the calibration before
434572ff6f6SMatthew Dillon 	 * the base band timeout completes.  This could result in the
435572ff6f6SMatthew Dillon 	 * rx_clear false triggering.  As a workaround we add delay an
436572ff6f6SMatthew Dillon 	 * extra BASE_ACTIVATE_DELAY usecs to ensure this condition
437572ff6f6SMatthew Dillon 	 * does not happen.
438572ff6f6SMatthew Dillon 	 */
439572ff6f6SMatthew Dillon 	if (IEEE80211_IS_CHAN_HALF(chan)) {
440572ff6f6SMatthew Dillon 		OS_DELAY((synthDelay << 1) + BASE_ACTIVATE_DELAY);
441572ff6f6SMatthew Dillon 	} else if (IEEE80211_IS_CHAN_QUARTER(chan)) {
442572ff6f6SMatthew Dillon 		OS_DELAY((synthDelay << 2) + BASE_ACTIVATE_DELAY);
443572ff6f6SMatthew Dillon 	} else {
444572ff6f6SMatthew Dillon 		OS_DELAY(synthDelay + BASE_ACTIVATE_DELAY);
445572ff6f6SMatthew Dillon 	}
446572ff6f6SMatthew Dillon 
447572ff6f6SMatthew Dillon 	/*
448572ff6f6SMatthew Dillon 	 * The udelay method is not reliable with notebooks.
449572ff6f6SMatthew Dillon 	 * Need to check to see if the baseband is ready
450572ff6f6SMatthew Dillon 	 */
451572ff6f6SMatthew Dillon 	testReg = OS_REG_READ(ah, AR_PHY_TESTCTRL);
452572ff6f6SMatthew Dillon 	/* Selects the Tx hold */
453572ff6f6SMatthew Dillon 	OS_REG_WRITE(ah, AR_PHY_TESTCTRL, AR_PHY_TESTCTRL_TXHOLD);
454572ff6f6SMatthew Dillon 	i = 0;
455572ff6f6SMatthew Dillon 	while ((i++ < 20) &&
456572ff6f6SMatthew Dillon 	       (OS_REG_READ(ah, 0x9c24) & 0x10)) /* test if baseband not ready */		OS_DELAY(200);
457572ff6f6SMatthew Dillon 	OS_REG_WRITE(ah, AR_PHY_TESTCTRL, testReg);
458572ff6f6SMatthew Dillon 
459572ff6f6SMatthew Dillon 	/* Calibrate the AGC and start a NF calculation */
460572ff6f6SMatthew Dillon 	OS_REG_WRITE(ah, AR_PHY_AGC_CONTROL,
461572ff6f6SMatthew Dillon 		  OS_REG_READ(ah, AR_PHY_AGC_CONTROL)
462572ff6f6SMatthew Dillon 		| AR_PHY_AGC_CONTROL_CAL
463572ff6f6SMatthew Dillon 		| AR_PHY_AGC_CONTROL_NF);
464572ff6f6SMatthew Dillon 
465572ff6f6SMatthew Dillon 	if (!IEEE80211_IS_CHAN_B(chan) && ahp->ah_bIQCalibration != IQ_CAL_DONE) {
466572ff6f6SMatthew Dillon 		/* Start IQ calibration w/ 2^(INIT_IQCAL_LOG_COUNT_MAX+1) samples */
467572ff6f6SMatthew Dillon 		OS_REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4,
468572ff6f6SMatthew Dillon 			AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX,
469572ff6f6SMatthew Dillon 			INIT_IQCAL_LOG_COUNT_MAX);
470572ff6f6SMatthew Dillon 		OS_REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4,
471572ff6f6SMatthew Dillon 			AR_PHY_TIMING_CTRL4_DO_IQCAL);
472572ff6f6SMatthew Dillon 		ahp->ah_bIQCalibration = IQ_CAL_RUNNING;
473572ff6f6SMatthew Dillon 	} else
474572ff6f6SMatthew Dillon 		ahp->ah_bIQCalibration = IQ_CAL_INACTIVE;
475572ff6f6SMatthew Dillon 
476572ff6f6SMatthew Dillon 	/* Setup compression registers */
477572ff6f6SMatthew Dillon 	ar5212SetCompRegs(ah);
478572ff6f6SMatthew Dillon 
479572ff6f6SMatthew Dillon 	/* Set 1:1 QCU to DCU mapping for all queues */
480572ff6f6SMatthew Dillon 	for (i = 0; i < AR_NUM_DCU; i++)
481572ff6f6SMatthew Dillon 		OS_REG_WRITE(ah, AR_DQCUMASK(i), 1 << i);
482572ff6f6SMatthew Dillon 
483572ff6f6SMatthew Dillon 	ahp->ah_intrTxqs = 0;
484572ff6f6SMatthew Dillon 	for (i = 0; i < AH_PRIVATE(ah)->ah_caps.halTotalQueues; i++)
485572ff6f6SMatthew Dillon 		ar5212ResetTxQueue(ah, i);
486572ff6f6SMatthew Dillon 
487572ff6f6SMatthew Dillon 	/*
488572ff6f6SMatthew Dillon 	 * Setup interrupt handling.  Note that ar5212ResetTxQueue
489572ff6f6SMatthew Dillon 	 * manipulates the secondary IMR's as queues are enabled
490572ff6f6SMatthew Dillon 	 * and disabled.  This is done with RMW ops to insure the
491572ff6f6SMatthew Dillon 	 * settings we make here are preserved.
492572ff6f6SMatthew Dillon 	 */
493572ff6f6SMatthew Dillon 	ahp->ah_maskReg = AR_IMR_TXOK | AR_IMR_TXERR | AR_IMR_TXURN
494572ff6f6SMatthew Dillon 			| AR_IMR_RXOK | AR_IMR_RXERR | AR_IMR_RXORN
495572ff6f6SMatthew Dillon 			| AR_IMR_HIUERR
496572ff6f6SMatthew Dillon 			;
497572ff6f6SMatthew Dillon 	if (opmode == HAL_M_HOSTAP)
498572ff6f6SMatthew Dillon 		ahp->ah_maskReg |= AR_IMR_MIB;
499572ff6f6SMatthew Dillon 	OS_REG_WRITE(ah, AR_IMR, ahp->ah_maskReg);
500572ff6f6SMatthew Dillon 	/* Enable bus errors that are OR'd to set the HIUERR bit */
501572ff6f6SMatthew Dillon 	OS_REG_WRITE(ah, AR_IMR_S2,
502572ff6f6SMatthew Dillon 		OS_REG_READ(ah, AR_IMR_S2)
503572ff6f6SMatthew Dillon 		| AR_IMR_S2_MCABT | AR_IMR_S2_SSERR | AR_IMR_S2_DPERR);
504572ff6f6SMatthew Dillon 
505572ff6f6SMatthew Dillon 	if (AH_PRIVATE(ah)->ah_rfkillEnabled)
506572ff6f6SMatthew Dillon 		ar5212EnableRfKill(ah);
507572ff6f6SMatthew Dillon 
508572ff6f6SMatthew Dillon 	if (!ath_hal_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0)) {
509572ff6f6SMatthew Dillon 		HALDEBUG(ah, HAL_DEBUG_ANY,
510572ff6f6SMatthew Dillon 		    "%s: offset calibration failed to complete in 1ms;"
511572ff6f6SMatthew Dillon 		    " noisy environment?\n", __func__);
512572ff6f6SMatthew Dillon 	}
513572ff6f6SMatthew Dillon 
514572ff6f6SMatthew Dillon 	/*
515572ff6f6SMatthew Dillon 	 * Set clocks back to 32kHz if they had been using refClk, then
516572ff6f6SMatthew Dillon 	 * use an external 32kHz crystal when sleeping, if one exists.
517572ff6f6SMatthew Dillon 	 */
518572ff6f6SMatthew Dillon 	ar5312SetupClock(ah, opmode);
519572ff6f6SMatthew Dillon 
520572ff6f6SMatthew Dillon 	/*
521572ff6f6SMatthew Dillon 	 * Writing to AR_BEACON will start timers. Hence it should
522572ff6f6SMatthew Dillon 	 * be the last register to be written. Do not reset tsf, do
523572ff6f6SMatthew Dillon 	 * not enable beacons at this point, but preserve other values
524572ff6f6SMatthew Dillon 	 * like beaconInterval.
525572ff6f6SMatthew Dillon 	 */
526572ff6f6SMatthew Dillon 	OS_REG_WRITE(ah, AR_BEACON,
527572ff6f6SMatthew Dillon 		(OS_REG_READ(ah, AR_BEACON) &~ (AR_BEACON_EN | AR_BEACON_RESET_TSF)));
528572ff6f6SMatthew Dillon 
529572ff6f6SMatthew Dillon 	/* XXX Setup post reset EAR additions */
530572ff6f6SMatthew Dillon 
531572ff6f6SMatthew Dillon 	/*  QoS support */
532572ff6f6SMatthew Dillon 	if (AH_PRIVATE(ah)->ah_macVersion > AR_SREV_VERSION_VENICE ||
533572ff6f6SMatthew Dillon 	    (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_VENICE &&
534572ff6f6SMatthew Dillon 	     AH_PRIVATE(ah)->ah_macRev >= AR_SREV_GRIFFIN_LITE)) {
535572ff6f6SMatthew Dillon 		OS_REG_WRITE(ah, AR_QOS_CONTROL, 0x100aa);	/* XXX magic */
536572ff6f6SMatthew Dillon 		OS_REG_WRITE(ah, AR_QOS_SELECT, 0x3210);	/* XXX magic */
537572ff6f6SMatthew Dillon 	}
538572ff6f6SMatthew Dillon 
539572ff6f6SMatthew Dillon 	/* Turn on NOACK Support for QoS packets */
540572ff6f6SMatthew Dillon 	OS_REG_WRITE(ah, AR_NOACK,
541572ff6f6SMatthew Dillon 		     SM(2, AR_NOACK_2BIT_VALUE) |
542572ff6f6SMatthew Dillon 		     SM(5, AR_NOACK_BIT_OFFSET) |
543572ff6f6SMatthew Dillon 		     SM(0, AR_NOACK_BYTE_OFFSET));
544572ff6f6SMatthew Dillon 
545572ff6f6SMatthew Dillon 	/* Restore user-specified settings */
546572ff6f6SMatthew Dillon 	if (ahp->ah_miscMode != 0)
547572ff6f6SMatthew Dillon 		OS_REG_WRITE(ah, AR_MISC_MODE, ahp->ah_miscMode);
548572ff6f6SMatthew Dillon 	if (ahp->ah_slottime != (u_int) -1)
549572ff6f6SMatthew Dillon 		ar5212SetSlotTime(ah, ahp->ah_slottime);
550572ff6f6SMatthew Dillon 	if (ahp->ah_acktimeout != (u_int) -1)
551572ff6f6SMatthew Dillon 		ar5212SetAckTimeout(ah, ahp->ah_acktimeout);
552572ff6f6SMatthew Dillon 	if (ahp->ah_ctstimeout != (u_int) -1)
553572ff6f6SMatthew Dillon 		ar5212SetCTSTimeout(ah, ahp->ah_ctstimeout);
554572ff6f6SMatthew Dillon 	if (ahp->ah_sifstime != (u_int) -1)
555572ff6f6SMatthew Dillon 		ar5212SetSifsTime(ah, ahp->ah_sifstime);
556572ff6f6SMatthew Dillon 	if (AH_PRIVATE(ah)->ah_diagreg != 0)
557572ff6f6SMatthew Dillon 		OS_REG_WRITE(ah, AR_DIAG_SW, AH_PRIVATE(ah)->ah_diagreg);
558572ff6f6SMatthew Dillon 
559572ff6f6SMatthew Dillon 	AH_PRIVATE(ah)->ah_opmode = opmode;	/* record operating mode */
560572ff6f6SMatthew Dillon 
561572ff6f6SMatthew Dillon 	if (bChannelChange && !IEEE80211_IS_CHAN_DFS(chan))
562572ff6f6SMatthew Dillon 		chan->ic_state &= ~IEEE80211_CHANSTATE_CWINT;
563572ff6f6SMatthew Dillon 
564572ff6f6SMatthew Dillon 	HALDEBUG(ah, HAL_DEBUG_RESET, "%s: done\n", __func__);
565572ff6f6SMatthew Dillon 
566572ff6f6SMatthew Dillon 	OS_MARK(ah, AH_MARK_RESET_DONE, 0);
567572ff6f6SMatthew Dillon 
568572ff6f6SMatthew Dillon 	return AH_TRUE;
569572ff6f6SMatthew Dillon bad:
570572ff6f6SMatthew Dillon 	OS_MARK(ah, AH_MARK_RESET_DONE, ecode);
571572ff6f6SMatthew Dillon 	if (status != AH_NULL)
572572ff6f6SMatthew Dillon 		*status = ecode;
573572ff6f6SMatthew Dillon 	return AH_FALSE;
574572ff6f6SMatthew Dillon #undef FAIL
575572ff6f6SMatthew Dillon #undef N
576572ff6f6SMatthew Dillon }
577572ff6f6SMatthew Dillon 
578572ff6f6SMatthew Dillon /*
579572ff6f6SMatthew Dillon  * Places the PHY and Radio chips into reset.  A full reset
580572ff6f6SMatthew Dillon  * must be called to leave this state.  The PCI/MAC/PCU are
581572ff6f6SMatthew Dillon  * not placed into reset as we must receive interrupt to
582572ff6f6SMatthew Dillon  * re-enable the hardware.
583572ff6f6SMatthew Dillon  */
584572ff6f6SMatthew Dillon HAL_BOOL
ar5312PhyDisable(struct ath_hal * ah)585572ff6f6SMatthew Dillon ar5312PhyDisable(struct ath_hal *ah)
586572ff6f6SMatthew Dillon {
587572ff6f6SMatthew Dillon     return ar5312SetResetReg(ah, AR_RC_BB);
588572ff6f6SMatthew Dillon }
589572ff6f6SMatthew Dillon 
590572ff6f6SMatthew Dillon /*
591572ff6f6SMatthew Dillon  * Places all of hardware into reset
592572ff6f6SMatthew Dillon  */
593572ff6f6SMatthew Dillon HAL_BOOL
ar5312Disable(struct ath_hal * ah)594572ff6f6SMatthew Dillon ar5312Disable(struct ath_hal *ah)
595572ff6f6SMatthew Dillon {
596572ff6f6SMatthew Dillon 	if (!ar5312SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE))
597572ff6f6SMatthew Dillon 		return AH_FALSE;
598572ff6f6SMatthew Dillon 	/*
599572ff6f6SMatthew Dillon 	 * Reset the HW - PCI must be reset after the rest of the
600572ff6f6SMatthew Dillon 	 * device has been reset.
601572ff6f6SMatthew Dillon 	 */
602572ff6f6SMatthew Dillon 	return ar5312SetResetReg(ah, AR_RC_MAC | AR_RC_BB);
603572ff6f6SMatthew Dillon }
604572ff6f6SMatthew Dillon 
605572ff6f6SMatthew Dillon /*
606572ff6f6SMatthew Dillon  * Places the hardware into reset and then pulls it out of reset
607572ff6f6SMatthew Dillon  *
608572ff6f6SMatthew Dillon  * TODO: Only write the PLL if we're changing to or from CCK mode
609572ff6f6SMatthew Dillon  *
610572ff6f6SMatthew Dillon  * WARNING: The order of the PLL and mode registers must be correct.
611572ff6f6SMatthew Dillon  */
612572ff6f6SMatthew Dillon HAL_BOOL
ar5312ChipReset(struct ath_hal * ah,const struct ieee80211_channel * chan)613572ff6f6SMatthew Dillon ar5312ChipReset(struct ath_hal *ah, const struct ieee80211_channel *chan)
614572ff6f6SMatthew Dillon {
615572ff6f6SMatthew Dillon 
616572ff6f6SMatthew Dillon 	OS_MARK(ah, AH_MARK_CHIPRESET, chan ? chan->ic_freq : 0);
617572ff6f6SMatthew Dillon 
618572ff6f6SMatthew Dillon 	/*
619572ff6f6SMatthew Dillon 	 * Reset the HW
620572ff6f6SMatthew Dillon 	 */
621572ff6f6SMatthew Dillon 	if (!ar5312SetResetReg(ah, AR_RC_MAC | AR_RC_BB)) {
622572ff6f6SMatthew Dillon 		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: ar5312SetResetReg failed\n",
623572ff6f6SMatthew Dillon 		    __func__);
624572ff6f6SMatthew Dillon 		return AH_FALSE;
625572ff6f6SMatthew Dillon 	}
626572ff6f6SMatthew Dillon 
627572ff6f6SMatthew Dillon 	/* Bring out of sleep mode (AGAIN) */
628572ff6f6SMatthew Dillon 	if (!ar5312SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) {
629572ff6f6SMatthew Dillon 		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: ar5312SetPowerMode failed\n",
630572ff6f6SMatthew Dillon 		    __func__);
631572ff6f6SMatthew Dillon 		return AH_FALSE;
632572ff6f6SMatthew Dillon 	}
633572ff6f6SMatthew Dillon 
634572ff6f6SMatthew Dillon 	/* Clear warm reset register */
635572ff6f6SMatthew Dillon 	if (!ar5312SetResetReg(ah, 0)) {
636572ff6f6SMatthew Dillon 		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: ar5312SetResetReg failed\n",
637572ff6f6SMatthew Dillon 		    __func__);
638572ff6f6SMatthew Dillon 		return AH_FALSE;
639572ff6f6SMatthew Dillon 	}
640572ff6f6SMatthew Dillon 
641572ff6f6SMatthew Dillon 	/*
642572ff6f6SMatthew Dillon 	 * Perform warm reset before the mode/PLL/turbo registers
643572ff6f6SMatthew Dillon 	 * are changed in order to deactivate the radio.  Mode changes
644572ff6f6SMatthew Dillon 	 * with an active radio can result in corrupted shifts to the
645572ff6f6SMatthew Dillon 	 * radio device.
646572ff6f6SMatthew Dillon 	 */
647572ff6f6SMatthew Dillon 
648572ff6f6SMatthew Dillon 	/*
649572ff6f6SMatthew Dillon 	 * Set CCK and Turbo modes correctly.
650572ff6f6SMatthew Dillon 	 */
651572ff6f6SMatthew Dillon 	if (chan != AH_NULL) {		/* NB: can be null during attach */
652572ff6f6SMatthew Dillon 		uint32_t rfMode, phyPLL = 0, curPhyPLL, turbo;
653572ff6f6SMatthew Dillon 
654572ff6f6SMatthew Dillon 		if (IS_RAD5112_ANY(ah)) {
655572ff6f6SMatthew Dillon 			rfMode = AR_PHY_MODE_AR5112;
656572ff6f6SMatthew Dillon 			if (!IS_5315(ah)) {
657572ff6f6SMatthew Dillon 				if (IEEE80211_IS_CHAN_CCK(chan)) {
658572ff6f6SMatthew Dillon 					phyPLL = AR_PHY_PLL_CTL_44_5312;
659572ff6f6SMatthew Dillon 				} else {
660572ff6f6SMatthew Dillon 					if (IEEE80211_IS_CHAN_HALF(chan)) {
661572ff6f6SMatthew Dillon 						phyPLL = AR_PHY_PLL_CTL_40_5312_HALF;
662572ff6f6SMatthew Dillon 					} else if (IEEE80211_IS_CHAN_QUARTER(chan)) {
663572ff6f6SMatthew Dillon 						phyPLL = AR_PHY_PLL_CTL_40_5312_QUARTER;
664572ff6f6SMatthew Dillon 					} else {
665572ff6f6SMatthew Dillon 						phyPLL = AR_PHY_PLL_CTL_40_5312;
666572ff6f6SMatthew Dillon 					}
667572ff6f6SMatthew Dillon 				}
668572ff6f6SMatthew Dillon 			} else {
669572ff6f6SMatthew Dillon 				if (IEEE80211_IS_CHAN_CCK(chan))
670572ff6f6SMatthew Dillon 					phyPLL = AR_PHY_PLL_CTL_44_5112;
671572ff6f6SMatthew Dillon 				else
672572ff6f6SMatthew Dillon 					phyPLL = AR_PHY_PLL_CTL_40_5112;
673572ff6f6SMatthew Dillon 				if (IEEE80211_IS_CHAN_HALF(chan))
674572ff6f6SMatthew Dillon 					phyPLL |= AR_PHY_PLL_CTL_HALF;
675572ff6f6SMatthew Dillon 				else if (IEEE80211_IS_CHAN_QUARTER(chan))
676572ff6f6SMatthew Dillon 					phyPLL |= AR_PHY_PLL_CTL_QUARTER;
677572ff6f6SMatthew Dillon 			}
678572ff6f6SMatthew Dillon 		} else {
679572ff6f6SMatthew Dillon 			rfMode = AR_PHY_MODE_AR5111;
680572ff6f6SMatthew Dillon 			if (IEEE80211_IS_CHAN_CCK(chan))
681572ff6f6SMatthew Dillon 				phyPLL = AR_PHY_PLL_CTL_44;
682572ff6f6SMatthew Dillon 			else
683572ff6f6SMatthew Dillon 				phyPLL = AR_PHY_PLL_CTL_40;
684572ff6f6SMatthew Dillon 			if (IEEE80211_IS_CHAN_HALF(chan))
685572ff6f6SMatthew Dillon 				phyPLL = AR_PHY_PLL_CTL_HALF;
686572ff6f6SMatthew Dillon 			else if (IEEE80211_IS_CHAN_QUARTER(chan))
687572ff6f6SMatthew Dillon 				phyPLL = AR_PHY_PLL_CTL_QUARTER;
688572ff6f6SMatthew Dillon 		}
689572ff6f6SMatthew Dillon 		if (IEEE80211_IS_CHAN_G(chan))
690572ff6f6SMatthew Dillon 			rfMode |= AR_PHY_MODE_DYNAMIC;
691572ff6f6SMatthew Dillon 		else if (IEEE80211_IS_CHAN_OFDM(chan))
692572ff6f6SMatthew Dillon 			rfMode |= AR_PHY_MODE_OFDM;
693572ff6f6SMatthew Dillon 		else
694572ff6f6SMatthew Dillon 			rfMode |= AR_PHY_MODE_CCK;
695572ff6f6SMatthew Dillon 		if (IEEE80211_IS_CHAN_5GHZ(chan))
696572ff6f6SMatthew Dillon 			rfMode |= AR_PHY_MODE_RF5GHZ;
697572ff6f6SMatthew Dillon 		else
698572ff6f6SMatthew Dillon 			rfMode |= AR_PHY_MODE_RF2GHZ;
699572ff6f6SMatthew Dillon 		turbo = IEEE80211_IS_CHAN_TURBO(chan) ?
700572ff6f6SMatthew Dillon 			(AR_PHY_FC_TURBO_MODE | AR_PHY_FC_TURBO_SHORT) : 0;
701572ff6f6SMatthew Dillon 		curPhyPLL = OS_REG_READ(ah, AR_PHY_PLL_CTL);
702572ff6f6SMatthew Dillon 		/*
703572ff6f6SMatthew Dillon 		 * PLL, Mode, and Turbo values must be written in the correct
704572ff6f6SMatthew Dillon 		 * order to ensure:
705572ff6f6SMatthew Dillon 		 * - The PLL cannot be set to 44 unless the CCK or DYNAMIC
706572ff6f6SMatthew Dillon 		 *   mode bit is set
707572ff6f6SMatthew Dillon 		 * - Turbo cannot be set at the same time as CCK or DYNAMIC
708572ff6f6SMatthew Dillon 		 */
709572ff6f6SMatthew Dillon 		if (IEEE80211_IS_CHAN_CCK(chan)) {
710572ff6f6SMatthew Dillon 			OS_REG_WRITE(ah, AR_PHY_TURBO, turbo);
711572ff6f6SMatthew Dillon 			OS_REG_WRITE(ah, AR_PHY_MODE, rfMode);
712572ff6f6SMatthew Dillon 			if (curPhyPLL != phyPLL) {
713572ff6f6SMatthew Dillon 				OS_REG_WRITE(ah,  AR_PHY_PLL_CTL,  phyPLL);
714572ff6f6SMatthew Dillon 				/* Wait for the PLL to settle */
715572ff6f6SMatthew Dillon 				OS_DELAY(PLL_SETTLE_DELAY);
716572ff6f6SMatthew Dillon 			}
717572ff6f6SMatthew Dillon 		} else {
718572ff6f6SMatthew Dillon 			if (curPhyPLL != phyPLL) {
719572ff6f6SMatthew Dillon 				OS_REG_WRITE(ah,  AR_PHY_PLL_CTL,  phyPLL);
720572ff6f6SMatthew Dillon 				/* Wait for the PLL to settle */
721572ff6f6SMatthew Dillon 				OS_DELAY(PLL_SETTLE_DELAY);
722572ff6f6SMatthew Dillon 			}
723572ff6f6SMatthew Dillon 			OS_REG_WRITE(ah, AR_PHY_TURBO, turbo);
724572ff6f6SMatthew Dillon 			OS_REG_WRITE(ah, AR_PHY_MODE, rfMode);
725572ff6f6SMatthew Dillon 		}
726572ff6f6SMatthew Dillon 	}
727572ff6f6SMatthew Dillon 	return AH_TRUE;
728572ff6f6SMatthew Dillon }
729572ff6f6SMatthew Dillon 
730572ff6f6SMatthew Dillon /*
731572ff6f6SMatthew Dillon  * Write the given reset bit mask into the reset register
732572ff6f6SMatthew Dillon  */
733572ff6f6SMatthew Dillon static HAL_BOOL
ar5312SetResetReg(struct ath_hal * ah,uint32_t resetMask)734572ff6f6SMatthew Dillon ar5312SetResetReg(struct ath_hal *ah, uint32_t resetMask)
735572ff6f6SMatthew Dillon {
736572ff6f6SMatthew Dillon 	uint32_t mask = resetMask ? resetMask : ~0;
737572ff6f6SMatthew Dillon 	HAL_BOOL rt;
738572ff6f6SMatthew Dillon 
739572ff6f6SMatthew Dillon         if ((rt = ar5312MacReset(ah, mask)) == AH_FALSE) {
740572ff6f6SMatthew Dillon 		return rt;
741572ff6f6SMatthew Dillon 	}
742572ff6f6SMatthew Dillon         if ((resetMask & AR_RC_MAC) == 0) {
743572ff6f6SMatthew Dillon 		if (isBigEndian()) {
744572ff6f6SMatthew Dillon 			/*
745572ff6f6SMatthew Dillon 			 * Set CFG, little-endian for descriptor accesses.
746572ff6f6SMatthew Dillon 			 */
747572ff6f6SMatthew Dillon #ifdef AH_NEED_DESC_SWAP
748572ff6f6SMatthew Dillon 			mask = INIT_CONFIG_STATUS | AR_CFG_SWRD;
749572ff6f6SMatthew Dillon #else
750572ff6f6SMatthew Dillon 			mask = INIT_CONFIG_STATUS |
751572ff6f6SMatthew Dillon                                 AR_CFG_SWTD | AR_CFG_SWRD;
752572ff6f6SMatthew Dillon #endif
753572ff6f6SMatthew Dillon 			OS_REG_WRITE(ah, AR_CFG, mask);
754572ff6f6SMatthew Dillon 		} else
755572ff6f6SMatthew Dillon 			OS_REG_WRITE(ah, AR_CFG, INIT_CONFIG_STATUS);
756572ff6f6SMatthew Dillon 	}
757572ff6f6SMatthew Dillon 	return rt;
758572ff6f6SMatthew Dillon }
759572ff6f6SMatthew Dillon 
760572ff6f6SMatthew Dillon /*
761572ff6f6SMatthew Dillon  * ar5312MacReset resets (and then un-resets) the specified
762572ff6f6SMatthew Dillon  * wireless components.
763572ff6f6SMatthew Dillon  * Note: The RCMask cannot be zero on entering from ar5312SetResetReg.
764572ff6f6SMatthew Dillon  */
765572ff6f6SMatthew Dillon 
766572ff6f6SMatthew Dillon HAL_BOOL
ar5312MacReset(struct ath_hal * ah,unsigned int RCMask)767572ff6f6SMatthew Dillon ar5312MacReset(struct ath_hal *ah, unsigned int RCMask)
768572ff6f6SMatthew Dillon {
769572ff6f6SMatthew Dillon 	int wlanNum = AR5312_UNIT(ah);
770572ff6f6SMatthew Dillon 	uint32_t resetBB, resetBits, regMask;
771572ff6f6SMatthew Dillon 	uint32_t reg;
772572ff6f6SMatthew Dillon 
773572ff6f6SMatthew Dillon 	if (RCMask == 0)
774572ff6f6SMatthew Dillon 		return(AH_FALSE);
775572ff6f6SMatthew Dillon #if ( AH_SUPPORT_2316 || AH_SUPPORT_2317 )
776572ff6f6SMatthew Dillon 	    if (IS_5315(ah)) {
777572ff6f6SMatthew Dillon 			switch(wlanNum) {
778572ff6f6SMatthew Dillon 			case 0:
779572ff6f6SMatthew Dillon 				resetBB = AR5315_RC_BB0_CRES | AR5315_RC_WBB0_RES;
780572ff6f6SMatthew Dillon 				/* Warm and cold reset bits for wbb */
781572ff6f6SMatthew Dillon 				resetBits = AR5315_RC_WMAC0_RES;
782572ff6f6SMatthew Dillon 				break;
783572ff6f6SMatthew Dillon 			case 1:
784572ff6f6SMatthew Dillon 				resetBB = AR5315_RC_BB1_CRES | AR5315_RC_WBB1_RES;
785572ff6f6SMatthew Dillon 				/* Warm and cold reset bits for wbb */
786572ff6f6SMatthew Dillon 				resetBits = AR5315_RC_WMAC1_RES;
787572ff6f6SMatthew Dillon 				break;
788572ff6f6SMatthew Dillon 			default:
789572ff6f6SMatthew Dillon 				return(AH_FALSE);
790572ff6f6SMatthew Dillon 			}
791572ff6f6SMatthew Dillon 			regMask = ~(resetBB | resetBits);
792572ff6f6SMatthew Dillon 
793572ff6f6SMatthew Dillon 			/* read before */
794572ff6f6SMatthew Dillon 			reg = OS_REG_READ(ah,
795572ff6f6SMatthew Dillon 							  (AR5315_RSTIMER_BASE - ((uint32_t) ah->ah_sh) + AR5315_RESET));
796572ff6f6SMatthew Dillon 
797572ff6f6SMatthew Dillon 			if (RCMask == AR_RC_BB) {
798572ff6f6SMatthew Dillon 				/* Put baseband in reset */
799572ff6f6SMatthew Dillon 				reg |= resetBB;    /* Cold and warm reset the baseband bits */
800572ff6f6SMatthew Dillon 			} else {
801572ff6f6SMatthew Dillon 				/*
802572ff6f6SMatthew Dillon 				 * Reset the MAC and baseband.  This is a bit different than
803572ff6f6SMatthew Dillon 				 * the PCI version, but holding in reset causes problems.
804572ff6f6SMatthew Dillon 				 */
805572ff6f6SMatthew Dillon 				reg &= regMask;
806572ff6f6SMatthew Dillon 				reg |= (resetBits | resetBB) ;
807572ff6f6SMatthew Dillon 			}
808572ff6f6SMatthew Dillon 			OS_REG_WRITE(ah,
809572ff6f6SMatthew Dillon 						 (AR5315_RSTIMER_BASE - ((uint32_t) ah->ah_sh)+AR5315_RESET),
810572ff6f6SMatthew Dillon 						 reg);
811572ff6f6SMatthew Dillon 			/* read after */
812572ff6f6SMatthew Dillon 			OS_REG_READ(ah,
813572ff6f6SMatthew Dillon 						(AR5315_RSTIMER_BASE - ((uint32_t) ah->ah_sh) +AR5315_RESET));
814572ff6f6SMatthew Dillon 			OS_DELAY(100);
815572ff6f6SMatthew Dillon 
816572ff6f6SMatthew Dillon 			/* Bring MAC and baseband out of reset */
817572ff6f6SMatthew Dillon 			reg &= regMask;
818572ff6f6SMatthew Dillon 			/* read before */
819572ff6f6SMatthew Dillon 			OS_REG_READ(ah,
820572ff6f6SMatthew Dillon 						(AR5315_RSTIMER_BASE- ((uint32_t) ah->ah_sh) +AR5315_RESET));
821572ff6f6SMatthew Dillon 			OS_REG_WRITE(ah,
822572ff6f6SMatthew Dillon 						 (AR5315_RSTIMER_BASE - ((uint32_t) ah->ah_sh)+AR5315_RESET),
823572ff6f6SMatthew Dillon 						 reg);
824572ff6f6SMatthew Dillon 			/* read after */
825572ff6f6SMatthew Dillon 			OS_REG_READ(ah,
826572ff6f6SMatthew Dillon 						(AR5315_RSTIMER_BASE- ((uint32_t) ah->ah_sh) +AR5315_RESET));
827572ff6f6SMatthew Dillon 
828572ff6f6SMatthew Dillon 
829572ff6f6SMatthew Dillon 		}
830572ff6f6SMatthew Dillon         else
831572ff6f6SMatthew Dillon #endif
832572ff6f6SMatthew Dillon 		{
833572ff6f6SMatthew Dillon 
834572ff6f6SMatthew Dillon 			switch(wlanNum) {
835572ff6f6SMatthew Dillon 			case 0:
836572ff6f6SMatthew Dillon 				resetBB = AR5312_RC_BB0_CRES | AR5312_RC_WBB0_RES;
837572ff6f6SMatthew Dillon 				/* Warm and cold reset bits for wbb */
838572ff6f6SMatthew Dillon 				resetBits = AR5312_RC_WMAC0_RES;
839572ff6f6SMatthew Dillon 				break;
840572ff6f6SMatthew Dillon 			case 1:
841572ff6f6SMatthew Dillon 				resetBB = AR5312_RC_BB1_CRES | AR5312_RC_WBB1_RES;
842572ff6f6SMatthew Dillon 				/* Warm and cold reset bits for wbb */
843572ff6f6SMatthew Dillon 				resetBits = AR5312_RC_WMAC1_RES;
844572ff6f6SMatthew Dillon 				break;
845572ff6f6SMatthew Dillon 			default:
846572ff6f6SMatthew Dillon 				return(AH_FALSE);
847572ff6f6SMatthew Dillon 			}
848572ff6f6SMatthew Dillon 			regMask = ~(resetBB | resetBits);
849572ff6f6SMatthew Dillon 
850572ff6f6SMatthew Dillon 			/* read before */
851572ff6f6SMatthew Dillon 			reg = OS_REG_READ(ah,
852572ff6f6SMatthew Dillon 							  (AR5312_RSTIMER_BASE - ((uint32_t) ah->ah_sh) + AR5312_RESET));
853572ff6f6SMatthew Dillon 
854572ff6f6SMatthew Dillon 			if (RCMask == AR_RC_BB) {
855572ff6f6SMatthew Dillon 				/* Put baseband in reset */
856572ff6f6SMatthew Dillon 				reg |= resetBB;    /* Cold and warm reset the baseband bits */
857572ff6f6SMatthew Dillon 			} else {
858572ff6f6SMatthew Dillon 				/*
859572ff6f6SMatthew Dillon 				 * Reset the MAC and baseband.  This is a bit different than
860572ff6f6SMatthew Dillon 				 * the PCI version, but holding in reset causes problems.
861572ff6f6SMatthew Dillon 				 */
862572ff6f6SMatthew Dillon 				reg &= regMask;
863572ff6f6SMatthew Dillon 				reg |= (resetBits | resetBB) ;
864572ff6f6SMatthew Dillon 			}
865572ff6f6SMatthew Dillon 			OS_REG_WRITE(ah,
866572ff6f6SMatthew Dillon 						 (AR5312_RSTIMER_BASE - ((uint32_t) ah->ah_sh)+AR5312_RESET),
867572ff6f6SMatthew Dillon 						 reg);
868572ff6f6SMatthew Dillon 			/* read after */
869572ff6f6SMatthew Dillon 			OS_REG_READ(ah,
870572ff6f6SMatthew Dillon 						(AR5312_RSTIMER_BASE - ((uint32_t) ah->ah_sh) +AR5312_RESET));
871572ff6f6SMatthew Dillon 			OS_DELAY(100);
872572ff6f6SMatthew Dillon 
873572ff6f6SMatthew Dillon 			/* Bring MAC and baseband out of reset */
874572ff6f6SMatthew Dillon 			reg &= regMask;
875572ff6f6SMatthew Dillon 			/* read before */
876572ff6f6SMatthew Dillon 			OS_REG_READ(ah,
877572ff6f6SMatthew Dillon 						(AR5312_RSTIMER_BASE- ((uint32_t) ah->ah_sh) +AR5312_RESET));
878572ff6f6SMatthew Dillon 			OS_REG_WRITE(ah,
879572ff6f6SMatthew Dillon 						 (AR5312_RSTIMER_BASE - ((uint32_t) ah->ah_sh)+AR5312_RESET),
880572ff6f6SMatthew Dillon 						 reg);
881572ff6f6SMatthew Dillon 			/* read after */
882572ff6f6SMatthew Dillon 			OS_REG_READ(ah,
883572ff6f6SMatthew Dillon 						(AR5312_RSTIMER_BASE- ((uint32_t) ah->ah_sh) +AR5312_RESET));
884572ff6f6SMatthew Dillon 		}
885572ff6f6SMatthew Dillon 	return(AH_TRUE);
886572ff6f6SMatthew Dillon }
887572ff6f6SMatthew Dillon 
888572ff6f6SMatthew Dillon #endif /* AH_SUPPORT_AR5312 */
889