1185377Ssam/* 2187831Ssam * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting 3185377Ssam * Copyright (c) 2002-2008 Atheros Communications, Inc. 4185377Ssam * 5185377Ssam * Permission to use, copy, modify, and/or distribute this software for any 6185377Ssam * purpose with or without fee is hereby granted, provided that the above 7185377Ssam * copyright notice and this permission notice appear in all copies. 8185377Ssam * 9185377Ssam * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10185377Ssam * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11185377Ssam * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12185377Ssam * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13185377Ssam * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14185377Ssam * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15185377Ssam * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16185377Ssam * 17187611Ssam * $FreeBSD$ 18185377Ssam */ 19185377Ssam#include "opt_ah.h" 20185377Ssam 21185377Ssam#ifdef AH_SUPPORT_AR5312 22185377Ssam 23185377Ssam#include "ah.h" 24185377Ssam#include "ah_internal.h" 25185377Ssam#include "ah_devid.h" 26185377Ssam 27185377Ssam#include "ar5312/ar5312.h" 28185377Ssam#include "ar5312/ar5312reg.h" 29185377Ssam#include "ar5312/ar5312phy.h" 30185377Ssam 31185377Ssam#include "ah_eeprom_v3.h" 32185377Ssam 33185377Ssam/* Additional Time delay to wait after activiting the Base band */ 34185377Ssam#define BASE_ACTIVATE_DELAY 100 /* 100 usec */ 35185377Ssam#define PLL_SETTLE_DELAY 300 /* 300 usec */ 36185377Ssam 37187831Ssamextern int16_t ar5212GetNf(struct ath_hal *, const struct ieee80211_channel *); 38187831Ssamextern void ar5212SetRateDurationTable(struct ath_hal *, 39187831Ssam const struct ieee80211_channel *); 40185377Ssamextern HAL_BOOL ar5212SetTransmitPower(struct ath_hal *ah, 41187831Ssam const struct ieee80211_channel *chan, uint16_t *rfXpdGain); 42187831Ssamextern void ar5212SetDeltaSlope(struct ath_hal *, 43187831Ssam const struct ieee80211_channel *); 44187831Ssamextern HAL_BOOL ar5212SetBoardValues(struct ath_hal *, 45187831Ssam const struct ieee80211_channel *); 46187831Ssamextern void ar5212SetIFSTiming(struct ath_hal *, 47187831Ssam const struct ieee80211_channel *); 48187831Ssamextern HAL_BOOL ar5212IsSpurChannel(struct ath_hal *, 49187831Ssam const struct ieee80211_channel *); 50187831Ssamextern HAL_BOOL ar5212ChannelChange(struct ath_hal *, 51187831Ssam const struct ieee80211_channel *); 52185377Ssam 53185377Ssamstatic HAL_BOOL ar5312SetResetReg(struct ath_hal *, uint32_t resetMask); 54185377Ssam 55185377Ssamstatic int 56185377Ssamwrite_common(struct ath_hal *ah, const HAL_INI_ARRAY *ia, 57185377Ssam HAL_BOOL bChannelChange, int writes) 58185377Ssam{ 59185377Ssam#define IS_NO_RESET_TIMER_ADDR(x) \ 60185377Ssam ( (((x) >= AR_BEACON) && ((x) <= AR_CFP_DUR)) || \ 61185377Ssam (((x) >= AR_SLEEP1) && ((x) <= AR_SLEEP3))) 62185377Ssam#define V(r, c) (ia)->data[((r)*(ia)->cols) + (c)] 63185377Ssam int i; 64185377Ssam 65185377Ssam /* Write Common Array Parameters */ 66185377Ssam for (i = 0; i < ia->rows; i++) { 67185377Ssam uint32_t reg = V(i, 0); 68185377Ssam /* XXX timer/beacon setup registers? */ 69185377Ssam /* On channel change, don't reset the PCU registers */ 70185377Ssam if (!(bChannelChange && IS_NO_RESET_TIMER_ADDR(reg))) { 71185377Ssam OS_REG_WRITE(ah, reg, V(i, 1)); 72185377Ssam DMA_YIELD(writes); 73185377Ssam } 74185377Ssam } 75185377Ssam return writes; 76185377Ssam#undef IS_NO_RESET_TIMER_ADDR 77185377Ssam#undef V 78185377Ssam} 79185377Ssam 80185377Ssam/* 81185377Ssam * Places the device in and out of reset and then places sane 82185377Ssam * values in the registers based on EEPROM config, initialization 83185377Ssam * vectors (as determined by the mode), and station configuration 84185377Ssam * 85185377Ssam * bChannelChange is used to preserve DMA/PCU registers across 86185377Ssam * a HW Reset during channel change. 87185377Ssam */ 88185377SsamHAL_BOOL 89185377Ssamar5312Reset(struct ath_hal *ah, HAL_OPMODE opmode, 90187831Ssam struct ieee80211_channel *chan, 91290612Sadrian HAL_BOOL bChannelChange, 92290612Sadrian HAL_RESET_TYPE resetType, 93290612Sadrian HAL_STATUS *status) 94185377Ssam{ 95185377Ssam#define N(a) (sizeof (a) / sizeof (a[0])) 96185377Ssam#define FAIL(_code) do { ecode = _code; goto bad; } while (0) 97185377Ssam struct ath_hal_5212 *ahp = AH5212(ah); 98185377Ssam HAL_CHANNEL_INTERNAL *ichan; 99185377Ssam const HAL_EEPROM *ee; 100185377Ssam uint32_t saveFrameSeqCount, saveDefAntenna; 101185377Ssam uint32_t macStaId1, synthDelay, txFrm2TxDStart; 102185377Ssam uint16_t rfXpdGain[MAX_NUM_PDGAINS_PER_CHANNEL]; 103185377Ssam int16_t cckOfdmPwrDelta = 0; 104185377Ssam u_int modesIndex, freqIndex; 105185377Ssam HAL_STATUS ecode; 106185377Ssam int i, regWrites = 0; 107185377Ssam uint32_t testReg; 108185377Ssam uint32_t saveLedState = 0; 109185377Ssam 110185377Ssam HALASSERT(ah->ah_magic == AR5212_MAGIC); 111185377Ssam ee = AH_PRIVATE(ah)->ah_eeprom; 112185377Ssam 113185377Ssam OS_MARK(ah, AH_MARK_RESET, bChannelChange); 114185377Ssam /* 115185377Ssam * Map public channel to private. 116185377Ssam */ 117185377Ssam ichan = ath_hal_checkchannel(ah, chan); 118185377Ssam if (ichan == AH_NULL) { 119185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, 120185377Ssam "%s: invalid channel %u/0x%x; no mapping\n", 121187831Ssam __func__, chan->ic_freq, chan->ic_flags); 122185377Ssam FAIL(HAL_EINVAL); 123185377Ssam } 124185377Ssam switch (opmode) { 125185377Ssam case HAL_M_STA: 126185377Ssam case HAL_M_IBSS: 127185377Ssam case HAL_M_HOSTAP: 128185377Ssam case HAL_M_MONITOR: 129185377Ssam break; 130185377Ssam default: 131185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid operating mode %u\n", 132185377Ssam __func__, opmode); 133185377Ssam FAIL(HAL_EINVAL); 134185377Ssam break; 135185377Ssam } 136185377Ssam HALASSERT(ahp->ah_eeversion >= AR_EEPROM_VER3); 137185377Ssam 138185377Ssam /* Preserve certain DMA hardware registers on a channel change */ 139185377Ssam if (bChannelChange) { 140185377Ssam /* 141185377Ssam * On Venice, the TSF is almost preserved across a reset; 142185377Ssam * it requires the doubling writes to the RESET_TSF 143185377Ssam * bit in the AR_BEACON register; it also has the quirk 144185377Ssam * of the TSF going back in time on the station (station 145185377Ssam * latches onto the last beacon's tsf during a reset 50% 146185377Ssam * of the times); the latter is not a problem for adhoc 147185377Ssam * stations since as long as the TSF is behind, it will 148185377Ssam * get resynchronized on receiving the next beacon; the 149185377Ssam * TSF going backwards in time could be a problem for the 150185377Ssam * sleep operation (supported on infrastructure stations 151185377Ssam * only) - the best and most general fix for this situation 152185377Ssam * is to resynchronize the various sleep/beacon timers on 153185377Ssam * the receipt of the next beacon i.e. when the TSF itself 154185377Ssam * gets resynchronized to the AP's TSF - power save is 155185377Ssam * needed to be temporarily disabled until that time 156185377Ssam * 157185377Ssam * Need to save the sequence number to restore it after 158185377Ssam * the reset! 159185377Ssam */ 160185377Ssam saveFrameSeqCount = OS_REG_READ(ah, AR_D_SEQNUM); 161185377Ssam } else 162185377Ssam saveFrameSeqCount = 0; /* NB: silence compiler */ 163185377Ssam 164185377Ssam /* If the channel change is across the same mode - perform a fast channel change */ 165185377Ssam if ((IS_2413(ah) || IS_5413(ah))) { 166185377Ssam /* 167185377Ssam * Channel change can only be used when: 168185377Ssam * -channel change requested - so it's not the initial reset. 169185377Ssam * -it's not a change to the current channel - often called when switching modes 170185377Ssam * on a channel 171185380Ssam * -the modes of the previous and requested channel are the same - some ugly code for XR 172185377Ssam */ 173185377Ssam if (bChannelChange && 174187831Ssam AH_PRIVATE(ah)->ah_curchan != AH_NULL && 175187831Ssam (chan->ic_freq != AH_PRIVATE(ah)->ah_curchan->ic_freq) && 176187831Ssam ((chan->ic_flags & IEEE80211_CHAN_ALLTURBO) == 177187831Ssam (AH_PRIVATE(ah)->ah_curchan->ic_flags & IEEE80211_CHAN_ALLTURBO))) { 178185377Ssam if (ar5212ChannelChange(ah, chan)) 179185377Ssam /* If ChannelChange completed - skip the rest of reset */ 180185377Ssam return AH_TRUE; 181185377Ssam } 182185377Ssam } 183185377Ssam 184185377Ssam /* 185185377Ssam * Preserve the antenna on a channel change 186185377Ssam */ 187185377Ssam saveDefAntenna = OS_REG_READ(ah, AR_DEF_ANTENNA); 188185377Ssam if (saveDefAntenna == 0) /* XXX magic constants */ 189185377Ssam saveDefAntenna = 1; 190185377Ssam 191185377Ssam /* Save hardware flag before chip reset clears the register */ 192185377Ssam macStaId1 = OS_REG_READ(ah, AR_STA_ID1) & 193185377Ssam (AR_STA_ID1_BASE_RATE_11B | AR_STA_ID1_USE_DEFANT); 194185377Ssam 195185377Ssam /* Save led state from pci config register */ 196185377Ssam if (!IS_5315(ah)) 197185377Ssam saveLedState = OS_REG_READ(ah, AR5312_PCICFG) & 198185377Ssam (AR_PCICFG_LEDCTL | AR_PCICFG_LEDMODE | AR_PCICFG_LEDBLINK | 199185377Ssam AR_PCICFG_LEDSLOW); 200185377Ssam 201185377Ssam ar5312RestoreClock(ah, opmode); /* move to refclk operation */ 202185377Ssam 203185377Ssam /* 204185377Ssam * Adjust gain parameters before reset if 205185377Ssam * there's an outstanding gain updated. 206185377Ssam */ 207185377Ssam (void) ar5212GetRfgain(ah); 208185377Ssam 209185377Ssam if (!ar5312ChipReset(ah, chan)) { 210185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__); 211185377Ssam FAIL(HAL_EIO); 212185377Ssam } 213185377Ssam 214185377Ssam /* Setup the indices for the next set of register array writes */ 215187831Ssam if (IEEE80211_IS_CHAN_2GHZ(chan)) { 216187831Ssam freqIndex = 2; 217187831Ssam modesIndex = IEEE80211_IS_CHAN_108G(chan) ? 5 : 218187831Ssam IEEE80211_IS_CHAN_G(chan) ? 4 : 3; 219187831Ssam } else { 220185377Ssam freqIndex = 1; 221187831Ssam modesIndex = IEEE80211_IS_CHAN_ST(chan) ? 2 : 1; 222185377Ssam } 223185377Ssam 224185377Ssam OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__); 225185377Ssam 226185377Ssam /* Set correct Baseband to analog shift setting to access analog chips. */ 227185377Ssam OS_REG_WRITE(ah, AR_PHY(0), 0x00000007); 228185377Ssam 229185377Ssam regWrites = ath_hal_ini_write(ah, &ahp->ah_ini_modes, modesIndex, 0); 230185377Ssam regWrites = write_common(ah, &ahp->ah_ini_common, bChannelChange, 231185377Ssam regWrites); 232185377Ssam ahp->ah_rfHal->writeRegs(ah, modesIndex, freqIndex, regWrites); 233185377Ssam 234185377Ssam OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__); 235185377Ssam 236187831Ssam if (IEEE80211_IS_CHAN_HALF(chan) || IEEE80211_IS_CHAN_QUARTER(chan)) 237185377Ssam ar5212SetIFSTiming(ah, chan); 238185377Ssam 239185377Ssam /* Overwrite INI values for revised chipsets */ 240185377Ssam if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_2) { 241185377Ssam /* ADC_CTL */ 242185377Ssam OS_REG_WRITE(ah, AR_PHY_ADC_CTL, 243185377Ssam SM(2, AR_PHY_ADC_CTL_OFF_INBUFGAIN) | 244185377Ssam SM(2, AR_PHY_ADC_CTL_ON_INBUFGAIN) | 245185377Ssam AR_PHY_ADC_CTL_OFF_PWDDAC | 246185377Ssam AR_PHY_ADC_CTL_OFF_PWDADC); 247185377Ssam 248185377Ssam /* TX_PWR_ADJ */ 249185377Ssam if (chan->channel == 2484) { 250185377Ssam cckOfdmPwrDelta = SCALE_OC_DELTA(ee->ee_cckOfdmPwrDelta - ee->ee_scaledCh14FilterCckDelta); 251185377Ssam } else { 252185377Ssam cckOfdmPwrDelta = SCALE_OC_DELTA(ee->ee_cckOfdmPwrDelta); 253185377Ssam } 254185377Ssam 255187831Ssam if (IEEE80211_IS_CHAN_G(chan)) { 256185377Ssam OS_REG_WRITE(ah, AR_PHY_TXPWRADJ, 257185377Ssam SM((ee->ee_cckOfdmPwrDelta*-1), AR_PHY_TXPWRADJ_CCK_GAIN_DELTA) | 258185377Ssam SM((cckOfdmPwrDelta*-1), AR_PHY_TXPWRADJ_CCK_PCDAC_INDEX)); 259185377Ssam } else { 260185377Ssam OS_REG_WRITE(ah, AR_PHY_TXPWRADJ, 0); 261185377Ssam } 262185377Ssam 263185377Ssam /* Add barker RSSI thresh enable as disabled */ 264185377Ssam OS_REG_CLR_BIT(ah, AR_PHY_DAG_CTRLCCK, 265185377Ssam AR_PHY_DAG_CTRLCCK_EN_RSSI_THR); 266185377Ssam OS_REG_RMW_FIELD(ah, AR_PHY_DAG_CTRLCCK, 267185377Ssam AR_PHY_DAG_CTRLCCK_RSSI_THR, 2); 268185377Ssam 269185377Ssam /* Set the mute mask to the correct default */ 270185377Ssam OS_REG_WRITE(ah, AR_SEQ_MASK, 0x0000000F); 271185377Ssam } 272185377Ssam 273185377Ssam if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_3) { 274185377Ssam /* Clear reg to alllow RX_CLEAR line debug */ 275185377Ssam OS_REG_WRITE(ah, AR_PHY_BLUETOOTH, 0); 276185377Ssam } 277185377Ssam if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_4) { 278185377Ssam#ifdef notyet 279185377Ssam /* Enable burst prefetch for the data queues */ 280185377Ssam OS_REG_RMW_FIELD(ah, AR_D_FPCTL, ... ); 281185377Ssam /* Enable double-buffering */ 282185377Ssam OS_REG_CLR_BIT(ah, AR_TXCFG, AR_TXCFG_DBL_BUF_DIS); 283185377Ssam#endif 284185377Ssam } 285185377Ssam 286185377Ssam if (IS_5312_2_X(ah)) { 287185377Ssam /* ADC_CTRL */ 288185377Ssam OS_REG_WRITE(ah, AR_PHY_SIGMA_DELTA, 289185377Ssam SM(2, AR_PHY_SIGMA_DELTA_ADC_SEL) | 290185377Ssam SM(4, AR_PHY_SIGMA_DELTA_FILT2) | 291185377Ssam SM(0x16, AR_PHY_SIGMA_DELTA_FILT1) | 292185377Ssam SM(0, AR_PHY_SIGMA_DELTA_ADC_CLIP)); 293185377Ssam 294187831Ssam if (IEEE80211_IS_CHAN_2GHZ(chan)) 295185377Ssam OS_REG_RMW_FIELD(ah, AR_PHY_RXGAIN, AR_PHY_RXGAIN_TXRX_RF_MAX, 0x0F); 296185377Ssam 297185377Ssam /* CCK Short parameter adjustment in 11B mode */ 298187831Ssam if (IEEE80211_IS_CHAN_B(chan)) 299185377Ssam OS_REG_RMW_FIELD(ah, AR_PHY_CCK_RXCTRL4, AR_PHY_CCK_RXCTRL4_FREQ_EST_SHORT, 12); 300185377Ssam 301185377Ssam /* Set ADC/DAC select values */ 302185377Ssam OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x04); 303185377Ssam 304185377Ssam /* Increase 11A AGC Settling */ 305187831Ssam if (IEEE80211_IS_CHAN_A(chan)) 306185377Ssam OS_REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_AGC, 32); 307185377Ssam } else { 308185377Ssam /* Set ADC/DAC select values */ 309185377Ssam OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0e); 310185377Ssam } 311185377Ssam 312185377Ssam /* Setup the transmit power values. */ 313187831Ssam if (!ar5212SetTransmitPower(ah, chan, rfXpdGain)) { 314185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, 315185377Ssam "%s: error init'ing transmit power\n", __func__); 316185377Ssam FAIL(HAL_EIO); 317185377Ssam } 318185377Ssam 319185377Ssam /* Write the analog registers */ 320187831Ssam if (!ahp->ah_rfHal->setRfRegs(ah, chan, modesIndex, rfXpdGain)) { 321185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, "%s: ar5212SetRfRegs failed\n", 322185377Ssam __func__); 323185377Ssam FAIL(HAL_EIO); 324185377Ssam } 325185377Ssam 326185377Ssam /* Write delta slope for OFDM enabled modes (A, G, Turbo) */ 327187831Ssam if (IEEE80211_IS_CHAN_OFDM(chan)) { 328187831Ssam if (IS_5413(ah) || 329187831Ssam AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER5_3) 330187831Ssam ar5212SetSpurMitigation(ah, chan); 331185377Ssam ar5212SetDeltaSlope(ah, chan); 332185377Ssam } 333185377Ssam 334185377Ssam /* Setup board specific options for EEPROM version 3 */ 335187831Ssam if (!ar5212SetBoardValues(ah, chan)) { 336185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, 337185377Ssam "%s: error setting board options\n", __func__); 338185377Ssam FAIL(HAL_EIO); 339185377Ssam } 340185377Ssam 341185377Ssam /* Restore certain DMA hardware registers on a channel change */ 342185377Ssam if (bChannelChange) 343185377Ssam OS_REG_WRITE(ah, AR_D_SEQNUM, saveFrameSeqCount); 344185377Ssam 345185377Ssam OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__); 346185377Ssam 347185377Ssam OS_REG_WRITE(ah, AR_STA_ID0, LE_READ_4(ahp->ah_macaddr)); 348185377Ssam OS_REG_WRITE(ah, AR_STA_ID1, LE_READ_2(ahp->ah_macaddr + 4) 349185377Ssam | macStaId1 350185377Ssam | AR_STA_ID1_RTS_USE_DEF 351185377Ssam | ahp->ah_staId1Defaults 352185377Ssam ); 353185377Ssam ar5212SetOperatingMode(ah, opmode); 354185377Ssam 355185377Ssam /* Set Venice BSSID mask according to current state */ 356185377Ssam OS_REG_WRITE(ah, AR_BSSMSKL, LE_READ_4(ahp->ah_bssidmask)); 357185377Ssam OS_REG_WRITE(ah, AR_BSSMSKU, LE_READ_2(ahp->ah_bssidmask + 4)); 358185377Ssam 359185377Ssam /* Restore previous led state */ 360185377Ssam if (!IS_5315(ah)) 361185377Ssam OS_REG_WRITE(ah, AR5312_PCICFG, OS_REG_READ(ah, AR_PCICFG) | saveLedState); 362185377Ssam 363185377Ssam /* Restore previous antenna */ 364185377Ssam OS_REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna); 365185377Ssam 366185377Ssam /* then our BSSID */ 367185377Ssam OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid)); 368185377Ssam OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid + 4)); 369185377Ssam 370185377Ssam /* Restore bmiss rssi & count thresholds */ 371185377Ssam OS_REG_WRITE(ah, AR_RSSI_THR, ahp->ah_rssiThr); 372185377Ssam 373185377Ssam OS_REG_WRITE(ah, AR_ISR, ~0); /* cleared on write */ 374185377Ssam 375187831Ssam if (!ar5212SetChannel(ah, chan)) 376185377Ssam FAIL(HAL_EIO); 377185377Ssam 378185377Ssam OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__); 379185377Ssam 380185377Ssam ar5212SetCoverageClass(ah, AH_PRIVATE(ah)->ah_coverageClass, 1); 381185377Ssam 382185377Ssam ar5212SetRateDurationTable(ah, chan); 383185377Ssam 384185377Ssam /* Set Tx frame start to tx data start delay */ 385185380Ssam if (IS_RAD5112_ANY(ah) && 386187831Ssam (IEEE80211_IS_CHAN_HALF(chan) || IEEE80211_IS_CHAN_QUARTER(chan))) { 387185377Ssam txFrm2TxDStart = 388187831Ssam IEEE80211_IS_CHAN_HALF(chan) ? 389185377Ssam TX_FRAME_D_START_HALF_RATE: 390185377Ssam TX_FRAME_D_START_QUARTER_RATE; 391185377Ssam OS_REG_RMW_FIELD(ah, AR_PHY_TX_CTL, 392185377Ssam AR_PHY_TX_FRAME_TO_TX_DATA_START, txFrm2TxDStart); 393185377Ssam } 394185377Ssam 395185377Ssam /* 396185377Ssam * Setup fast diversity. 397185377Ssam * Fast diversity can be enabled or disabled via regadd.txt. 398185377Ssam * Default is enabled. 399185377Ssam * For reference, 400185377Ssam * Disable: reg val 401185377Ssam * 0x00009860 0x00009d18 (if 11a / 11g, else no change) 402185377Ssam * 0x00009970 0x192bb514 403185377Ssam * 0x0000a208 0xd03e4648 404185377Ssam * 405185377Ssam * Enable: 0x00009860 0x00009d10 (if 11a / 11g, else no change) 406185377Ssam * 0x00009970 0x192fb514 407185377Ssam * 0x0000a208 0xd03e6788 408185377Ssam */ 409185377Ssam 410185377Ssam /* XXX Setup pre PHY ENABLE EAR additions */ 411185377Ssam 412185377Ssam /* flush SCAL reg */ 413185377Ssam if (IS_5312_2_X(ah)) { 414185377Ssam (void) OS_REG_READ(ah, AR_PHY_SLEEP_SCAL); 415185377Ssam } 416185377Ssam 417185377Ssam /* 418185377Ssam * Wait for the frequency synth to settle (synth goes on 419185377Ssam * via AR_PHY_ACTIVE_EN). Read the phy active delay register. 420185377Ssam * Value is in 100ns increments. 421185377Ssam */ 422185377Ssam synthDelay = OS_REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY; 423187831Ssam if (IEEE80211_IS_CHAN_B(chan)) { 424185377Ssam synthDelay = (4 * synthDelay) / 22; 425185377Ssam } else { 426185377Ssam synthDelay /= 10; 427185377Ssam } 428185377Ssam 429185377Ssam /* Activate the PHY (includes baseband activate and synthesizer on) */ 430185377Ssam OS_REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); 431185377Ssam 432185377Ssam /* 433185377Ssam * There is an issue if the AP starts the calibration before 434185377Ssam * the base band timeout completes. This could result in the 435185377Ssam * rx_clear false triggering. As a workaround we add delay an 436185377Ssam * extra BASE_ACTIVATE_DELAY usecs to ensure this condition 437185377Ssam * does not happen. 438185377Ssam */ 439187831Ssam if (IEEE80211_IS_CHAN_HALF(chan)) { 440185377Ssam OS_DELAY((synthDelay << 1) + BASE_ACTIVATE_DELAY); 441187831Ssam } else if (IEEE80211_IS_CHAN_QUARTER(chan)) { 442185377Ssam OS_DELAY((synthDelay << 2) + BASE_ACTIVATE_DELAY); 443185377Ssam } else { 444185377Ssam OS_DELAY(synthDelay + BASE_ACTIVATE_DELAY); 445185377Ssam } 446185377Ssam 447185377Ssam /* 448185377Ssam * The udelay method is not reliable with notebooks. 449185377Ssam * Need to check to see if the baseband is ready 450185377Ssam */ 451185377Ssam testReg = OS_REG_READ(ah, AR_PHY_TESTCTRL); 452185377Ssam /* Selects the Tx hold */ 453185377Ssam OS_REG_WRITE(ah, AR_PHY_TESTCTRL, AR_PHY_TESTCTRL_TXHOLD); 454185377Ssam i = 0; 455185377Ssam while ((i++ < 20) && 456185377Ssam (OS_REG_READ(ah, 0x9c24) & 0x10)) /* test if baseband not ready */ OS_DELAY(200); 457185377Ssam OS_REG_WRITE(ah, AR_PHY_TESTCTRL, testReg); 458185377Ssam 459185377Ssam /* Calibrate the AGC and start a NF calculation */ 460185377Ssam OS_REG_WRITE(ah, AR_PHY_AGC_CONTROL, 461185377Ssam OS_REG_READ(ah, AR_PHY_AGC_CONTROL) 462185377Ssam | AR_PHY_AGC_CONTROL_CAL 463185377Ssam | AR_PHY_AGC_CONTROL_NF); 464185377Ssam 465187831Ssam if (!IEEE80211_IS_CHAN_B(chan) && ahp->ah_bIQCalibration != IQ_CAL_DONE) { 466185377Ssam /* Start IQ calibration w/ 2^(INIT_IQCAL_LOG_COUNT_MAX+1) samples */ 467185377Ssam OS_REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4, 468185377Ssam AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX, 469185377Ssam INIT_IQCAL_LOG_COUNT_MAX); 470185377Ssam OS_REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4, 471185377Ssam AR_PHY_TIMING_CTRL4_DO_IQCAL); 472185377Ssam ahp->ah_bIQCalibration = IQ_CAL_RUNNING; 473185377Ssam } else 474185377Ssam ahp->ah_bIQCalibration = IQ_CAL_INACTIVE; 475185377Ssam 476185377Ssam /* Setup compression registers */ 477185377Ssam ar5212SetCompRegs(ah); 478185377Ssam 479185377Ssam /* Set 1:1 QCU to DCU mapping for all queues */ 480185377Ssam for (i = 0; i < AR_NUM_DCU; i++) 481185377Ssam OS_REG_WRITE(ah, AR_DQCUMASK(i), 1 << i); 482185377Ssam 483185377Ssam ahp->ah_intrTxqs = 0; 484185377Ssam for (i = 0; i < AH_PRIVATE(ah)->ah_caps.halTotalQueues; i++) 485185377Ssam ar5212ResetTxQueue(ah, i); 486185377Ssam 487185377Ssam /* 488185377Ssam * Setup interrupt handling. Note that ar5212ResetTxQueue 489185377Ssam * manipulates the secondary IMR's as queues are enabled 490185377Ssam * and disabled. This is done with RMW ops to insure the 491185377Ssam * settings we make here are preserved. 492185377Ssam */ 493185377Ssam ahp->ah_maskReg = AR_IMR_TXOK | AR_IMR_TXERR | AR_IMR_TXURN 494185377Ssam | AR_IMR_RXOK | AR_IMR_RXERR | AR_IMR_RXORN 495185377Ssam | AR_IMR_HIUERR 496185377Ssam ; 497185377Ssam if (opmode == HAL_M_HOSTAP) 498185377Ssam ahp->ah_maskReg |= AR_IMR_MIB; 499185377Ssam OS_REG_WRITE(ah, AR_IMR, ahp->ah_maskReg); 500185377Ssam /* Enable bus errors that are OR'd to set the HIUERR bit */ 501185377Ssam OS_REG_WRITE(ah, AR_IMR_S2, 502185377Ssam OS_REG_READ(ah, AR_IMR_S2) 503185377Ssam | AR_IMR_S2_MCABT | AR_IMR_S2_SSERR | AR_IMR_S2_DPERR); 504185377Ssam 505185377Ssam if (AH_PRIVATE(ah)->ah_rfkillEnabled) 506185377Ssam ar5212EnableRfKill(ah); 507185377Ssam 508185377Ssam if (!ath_hal_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0)) { 509185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, 510185377Ssam "%s: offset calibration failed to complete in 1ms;" 511185377Ssam " noisy environment?\n", __func__); 512185377Ssam } 513185377Ssam 514185377Ssam /* 515185377Ssam * Set clocks back to 32kHz if they had been using refClk, then 516185377Ssam * use an external 32kHz crystal when sleeping, if one exists. 517185377Ssam */ 518185377Ssam ar5312SetupClock(ah, opmode); 519185377Ssam 520185377Ssam /* 521185377Ssam * Writing to AR_BEACON will start timers. Hence it should 522185377Ssam * be the last register to be written. Do not reset tsf, do 523185377Ssam * not enable beacons at this point, but preserve other values 524185377Ssam * like beaconInterval. 525185377Ssam */ 526185377Ssam OS_REG_WRITE(ah, AR_BEACON, 527185377Ssam (OS_REG_READ(ah, AR_BEACON) &~ (AR_BEACON_EN | AR_BEACON_RESET_TSF))); 528185377Ssam 529185377Ssam /* XXX Setup post reset EAR additions */ 530185377Ssam 531185377Ssam /* QoS support */ 532185377Ssam if (AH_PRIVATE(ah)->ah_macVersion > AR_SREV_VERSION_VENICE || 533185377Ssam (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_VENICE && 534185377Ssam AH_PRIVATE(ah)->ah_macRev >= AR_SREV_GRIFFIN_LITE)) { 535185377Ssam OS_REG_WRITE(ah, AR_QOS_CONTROL, 0x100aa); /* XXX magic */ 536185377Ssam OS_REG_WRITE(ah, AR_QOS_SELECT, 0x3210); /* XXX magic */ 537185377Ssam } 538185377Ssam 539185377Ssam /* Turn on NOACK Support for QoS packets */ 540185377Ssam OS_REG_WRITE(ah, AR_NOACK, 541185377Ssam SM(2, AR_NOACK_2BIT_VALUE) | 542185377Ssam SM(5, AR_NOACK_BIT_OFFSET) | 543185377Ssam SM(0, AR_NOACK_BYTE_OFFSET)); 544185377Ssam 545185377Ssam /* Restore user-specified settings */ 546185377Ssam if (ahp->ah_miscMode != 0) 547185377Ssam OS_REG_WRITE(ah, AR_MISC_MODE, ahp->ah_miscMode); 548185377Ssam if (ahp->ah_slottime != (u_int) -1) 549185377Ssam ar5212SetSlotTime(ah, ahp->ah_slottime); 550185377Ssam if (ahp->ah_acktimeout != (u_int) -1) 551185377Ssam ar5212SetAckTimeout(ah, ahp->ah_acktimeout); 552185377Ssam if (ahp->ah_ctstimeout != (u_int) -1) 553185377Ssam ar5212SetCTSTimeout(ah, ahp->ah_ctstimeout); 554185377Ssam if (ahp->ah_sifstime != (u_int) -1) 555185377Ssam ar5212SetSifsTime(ah, ahp->ah_sifstime); 556185377Ssam if (AH_PRIVATE(ah)->ah_diagreg != 0) 557185377Ssam OS_REG_WRITE(ah, AR_DIAG_SW, AH_PRIVATE(ah)->ah_diagreg); 558185377Ssam 559185377Ssam AH_PRIVATE(ah)->ah_opmode = opmode; /* record operating mode */ 560185377Ssam 561187831Ssam if (bChannelChange && !IEEE80211_IS_CHAN_DFS(chan)) 562187831Ssam chan->ic_state &= ~IEEE80211_CHANSTATE_CWINT; 563185377Ssam 564185377Ssam HALDEBUG(ah, HAL_DEBUG_RESET, "%s: done\n", __func__); 565185377Ssam 566185377Ssam OS_MARK(ah, AH_MARK_RESET_DONE, 0); 567185377Ssam 568185377Ssam return AH_TRUE; 569185377Ssambad: 570185377Ssam OS_MARK(ah, AH_MARK_RESET_DONE, ecode); 571187611Ssam if (status != AH_NULL) 572185377Ssam *status = ecode; 573185377Ssam return AH_FALSE; 574185377Ssam#undef FAIL 575185377Ssam#undef N 576185377Ssam} 577185377Ssam 578185377Ssam/* 579185377Ssam * Places the PHY and Radio chips into reset. A full reset 580185377Ssam * must be called to leave this state. The PCI/MAC/PCU are 581185377Ssam * not placed into reset as we must receive interrupt to 582185377Ssam * re-enable the hardware. 583185377Ssam */ 584185377SsamHAL_BOOL 585185377Ssamar5312PhyDisable(struct ath_hal *ah) 586185377Ssam{ 587185377Ssam return ar5312SetResetReg(ah, AR_RC_BB); 588185377Ssam} 589185377Ssam 590185377Ssam/* 591185377Ssam * Places all of hardware into reset 592185377Ssam */ 593185377SsamHAL_BOOL 594185377Ssamar5312Disable(struct ath_hal *ah) 595185377Ssam{ 596185377Ssam if (!ar5312SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) 597185377Ssam return AH_FALSE; 598185377Ssam /* 599185377Ssam * Reset the HW - PCI must be reset after the rest of the 600185377Ssam * device has been reset. 601185377Ssam */ 602185377Ssam return ar5312SetResetReg(ah, AR_RC_MAC | AR_RC_BB); 603185377Ssam} 604185377Ssam 605185377Ssam/* 606185377Ssam * Places the hardware into reset and then pulls it out of reset 607185377Ssam * 608185377Ssam * TODO: Only write the PLL if we're changing to or from CCK mode 609185377Ssam * 610185377Ssam * WARNING: The order of the PLL and mode registers must be correct. 611185377Ssam */ 612185377SsamHAL_BOOL 613187831Ssamar5312ChipReset(struct ath_hal *ah, const struct ieee80211_channel *chan) 614185377Ssam{ 615185377Ssam 616187831Ssam OS_MARK(ah, AH_MARK_CHIPRESET, chan ? chan->ic_freq : 0); 617185377Ssam 618185377Ssam /* 619185377Ssam * Reset the HW 620185377Ssam */ 621185377Ssam if (!ar5312SetResetReg(ah, AR_RC_MAC | AR_RC_BB)) { 622185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, "%s: ar5312SetResetReg failed\n", 623185377Ssam __func__); 624185377Ssam return AH_FALSE; 625185377Ssam } 626185377Ssam 627185377Ssam /* Bring out of sleep mode (AGAIN) */ 628185377Ssam if (!ar5312SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) { 629185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, "%s: ar5312SetPowerMode failed\n", 630185377Ssam __func__); 631185377Ssam return AH_FALSE; 632185377Ssam } 633185377Ssam 634185377Ssam /* Clear warm reset register */ 635185377Ssam if (!ar5312SetResetReg(ah, 0)) { 636185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, "%s: ar5312SetResetReg failed\n", 637185377Ssam __func__); 638185377Ssam return AH_FALSE; 639185377Ssam } 640185377Ssam 641185377Ssam /* 642185377Ssam * Perform warm reset before the mode/PLL/turbo registers 643185377Ssam * are changed in order to deactivate the radio. Mode changes 644185377Ssam * with an active radio can result in corrupted shifts to the 645185377Ssam * radio device. 646185377Ssam */ 647185377Ssam 648185377Ssam /* 649185377Ssam * Set CCK and Turbo modes correctly. 650185377Ssam */ 651185377Ssam if (chan != AH_NULL) { /* NB: can be null during attach */ 652185377Ssam uint32_t rfMode, phyPLL = 0, curPhyPLL, turbo; 653185377Ssam 654185380Ssam if (IS_RAD5112_ANY(ah)) { 655185377Ssam rfMode = AR_PHY_MODE_AR5112; 656185377Ssam if (!IS_5315(ah)) { 657187831Ssam if (IEEE80211_IS_CHAN_CCK(chan)) { 658185377Ssam phyPLL = AR_PHY_PLL_CTL_44_5312; 659185377Ssam } else { 660187831Ssam if (IEEE80211_IS_CHAN_HALF(chan)) { 661185377Ssam phyPLL = AR_PHY_PLL_CTL_40_5312_HALF; 662187831Ssam } else if (IEEE80211_IS_CHAN_QUARTER(chan)) { 663185377Ssam phyPLL = AR_PHY_PLL_CTL_40_5312_QUARTER; 664185377Ssam } else { 665185377Ssam phyPLL = AR_PHY_PLL_CTL_40_5312; 666185377Ssam } 667185377Ssam } 668185377Ssam } else { 669187831Ssam if (IEEE80211_IS_CHAN_CCK(chan)) 670185377Ssam phyPLL = AR_PHY_PLL_CTL_44_5112; 671185380Ssam else 672185380Ssam phyPLL = AR_PHY_PLL_CTL_40_5112; 673187831Ssam if (IEEE80211_IS_CHAN_HALF(chan)) 674185380Ssam phyPLL |= AR_PHY_PLL_CTL_HALF; 675187831Ssam else if (IEEE80211_IS_CHAN_QUARTER(chan)) 676185380Ssam phyPLL |= AR_PHY_PLL_CTL_QUARTER; 677185377Ssam } 678185377Ssam } else { 679185377Ssam rfMode = AR_PHY_MODE_AR5111; 680187831Ssam if (IEEE80211_IS_CHAN_CCK(chan)) 681185377Ssam phyPLL = AR_PHY_PLL_CTL_44; 682185380Ssam else 683185380Ssam phyPLL = AR_PHY_PLL_CTL_40; 684187831Ssam if (IEEE80211_IS_CHAN_HALF(chan)) 685185380Ssam phyPLL = AR_PHY_PLL_CTL_HALF; 686187831Ssam else if (IEEE80211_IS_CHAN_QUARTER(chan)) 687185380Ssam phyPLL = AR_PHY_PLL_CTL_QUARTER; 688185377Ssam } 689187831Ssam if (IEEE80211_IS_CHAN_G(chan)) 690185377Ssam rfMode |= AR_PHY_MODE_DYNAMIC; 691187831Ssam else if (IEEE80211_IS_CHAN_OFDM(chan)) 692185377Ssam rfMode |= AR_PHY_MODE_OFDM; 693185377Ssam else 694185377Ssam rfMode |= AR_PHY_MODE_CCK; 695187831Ssam if (IEEE80211_IS_CHAN_5GHZ(chan)) 696185377Ssam rfMode |= AR_PHY_MODE_RF5GHZ; 697185377Ssam else 698185377Ssam rfMode |= AR_PHY_MODE_RF2GHZ; 699187831Ssam turbo = IEEE80211_IS_CHAN_TURBO(chan) ? 700185377Ssam (AR_PHY_FC_TURBO_MODE | AR_PHY_FC_TURBO_SHORT) : 0; 701185377Ssam curPhyPLL = OS_REG_READ(ah, AR_PHY_PLL_CTL); 702185377Ssam /* 703185377Ssam * PLL, Mode, and Turbo values must be written in the correct 704185377Ssam * order to ensure: 705185377Ssam * - The PLL cannot be set to 44 unless the CCK or DYNAMIC 706185377Ssam * mode bit is set 707185377Ssam * - Turbo cannot be set at the same time as CCK or DYNAMIC 708185377Ssam */ 709187831Ssam if (IEEE80211_IS_CHAN_CCK(chan)) { 710185377Ssam OS_REG_WRITE(ah, AR_PHY_TURBO, turbo); 711185377Ssam OS_REG_WRITE(ah, AR_PHY_MODE, rfMode); 712185377Ssam if (curPhyPLL != phyPLL) { 713185377Ssam OS_REG_WRITE(ah, AR_PHY_PLL_CTL, phyPLL); 714185377Ssam /* Wait for the PLL to settle */ 715185377Ssam OS_DELAY(PLL_SETTLE_DELAY); 716185377Ssam } 717185377Ssam } else { 718185377Ssam if (curPhyPLL != phyPLL) { 719185377Ssam OS_REG_WRITE(ah, AR_PHY_PLL_CTL, phyPLL); 720185377Ssam /* Wait for the PLL to settle */ 721185377Ssam OS_DELAY(PLL_SETTLE_DELAY); 722185377Ssam } 723185377Ssam OS_REG_WRITE(ah, AR_PHY_TURBO, turbo); 724185377Ssam OS_REG_WRITE(ah, AR_PHY_MODE, rfMode); 725185377Ssam } 726185377Ssam } 727185377Ssam return AH_TRUE; 728185377Ssam} 729185377Ssam 730185377Ssam/* 731185377Ssam * Write the given reset bit mask into the reset register 732185377Ssam */ 733185377Ssamstatic HAL_BOOL 734185377Ssamar5312SetResetReg(struct ath_hal *ah, uint32_t resetMask) 735185377Ssam{ 736185377Ssam uint32_t mask = resetMask ? resetMask : ~0; 737185377Ssam HAL_BOOL rt; 738185377Ssam 739185377Ssam if ((rt = ar5312MacReset(ah, mask)) == AH_FALSE) { 740185377Ssam return rt; 741185377Ssam } 742185377Ssam if ((resetMask & AR_RC_MAC) == 0) { 743185377Ssam if (isBigEndian()) { 744185377Ssam /* 745234450Sadrian * Set CFG, little-endian for descriptor accesses. 746185377Ssam */ 747185377Ssam#ifdef AH_NEED_DESC_SWAP 748185377Ssam mask = INIT_CONFIG_STATUS | AR_CFG_SWRD; 749185377Ssam#else 750185377Ssam mask = INIT_CONFIG_STATUS | 751185377Ssam AR_CFG_SWTD | AR_CFG_SWRD; 752185377Ssam#endif 753185377Ssam OS_REG_WRITE(ah, AR_CFG, mask); 754185377Ssam } else 755185377Ssam OS_REG_WRITE(ah, AR_CFG, INIT_CONFIG_STATUS); 756185377Ssam } 757185377Ssam return rt; 758185377Ssam} 759185377Ssam 760185377Ssam/* 761185377Ssam * ar5312MacReset resets (and then un-resets) the specified 762185377Ssam * wireless components. 763185377Ssam * Note: The RCMask cannot be zero on entering from ar5312SetResetReg. 764185377Ssam */ 765185377Ssam 766185377SsamHAL_BOOL 767185377Ssamar5312MacReset(struct ath_hal *ah, unsigned int RCMask) 768185377Ssam{ 769185377Ssam int wlanNum = AR5312_UNIT(ah); 770185377Ssam uint32_t resetBB, resetBits, regMask; 771185377Ssam uint32_t reg; 772185377Ssam 773185377Ssam if (RCMask == 0) 774185377Ssam return(AH_FALSE); 775185377Ssam#if ( AH_SUPPORT_2316 || AH_SUPPORT_2317 ) 776185377Ssam if (IS_5315(ah)) { 777185377Ssam switch(wlanNum) { 778185377Ssam case 0: 779185377Ssam resetBB = AR5315_RC_BB0_CRES | AR5315_RC_WBB0_RES; 780185377Ssam /* Warm and cold reset bits for wbb */ 781185377Ssam resetBits = AR5315_RC_WMAC0_RES; 782185377Ssam break; 783185377Ssam case 1: 784185377Ssam resetBB = AR5315_RC_BB1_CRES | AR5315_RC_WBB1_RES; 785185377Ssam /* Warm and cold reset bits for wbb */ 786185377Ssam resetBits = AR5315_RC_WMAC1_RES; 787185377Ssam break; 788185377Ssam default: 789185377Ssam return(AH_FALSE); 790185377Ssam } 791185377Ssam regMask = ~(resetBB | resetBits); 792185377Ssam 793185377Ssam /* read before */ 794185377Ssam reg = OS_REG_READ(ah, 795185377Ssam (AR5315_RSTIMER_BASE - ((uint32_t) ah->ah_sh) + AR5315_RESET)); 796185377Ssam 797185377Ssam if (RCMask == AR_RC_BB) { 798185377Ssam /* Put baseband in reset */ 799185377Ssam reg |= resetBB; /* Cold and warm reset the baseband bits */ 800185377Ssam } else { 801185377Ssam /* 802185377Ssam * Reset the MAC and baseband. This is a bit different than 803185377Ssam * the PCI version, but holding in reset causes problems. 804185377Ssam */ 805185377Ssam reg &= regMask; 806185377Ssam reg |= (resetBits | resetBB) ; 807185377Ssam } 808185377Ssam OS_REG_WRITE(ah, 809185377Ssam (AR5315_RSTIMER_BASE - ((uint32_t) ah->ah_sh)+AR5315_RESET), 810185377Ssam reg); 811185377Ssam /* read after */ 812185377Ssam OS_REG_READ(ah, 813185377Ssam (AR5315_RSTIMER_BASE - ((uint32_t) ah->ah_sh) +AR5315_RESET)); 814185377Ssam OS_DELAY(100); 815185377Ssam 816185377Ssam /* Bring MAC and baseband out of reset */ 817185377Ssam reg &= regMask; 818185377Ssam /* read before */ 819185377Ssam OS_REG_READ(ah, 820185377Ssam (AR5315_RSTIMER_BASE- ((uint32_t) ah->ah_sh) +AR5315_RESET)); 821185377Ssam OS_REG_WRITE(ah, 822185377Ssam (AR5315_RSTIMER_BASE - ((uint32_t) ah->ah_sh)+AR5315_RESET), 823185377Ssam reg); 824185377Ssam /* read after */ 825185377Ssam OS_REG_READ(ah, 826185377Ssam (AR5315_RSTIMER_BASE- ((uint32_t) ah->ah_sh) +AR5315_RESET)); 827185377Ssam 828185377Ssam 829185377Ssam } 830185377Ssam else 831185377Ssam#endif 832185377Ssam { 833185377Ssam 834185377Ssam switch(wlanNum) { 835185377Ssam case 0: 836185377Ssam resetBB = AR5312_RC_BB0_CRES | AR5312_RC_WBB0_RES; 837185377Ssam /* Warm and cold reset bits for wbb */ 838185377Ssam resetBits = AR5312_RC_WMAC0_RES; 839185377Ssam break; 840185377Ssam case 1: 841185377Ssam resetBB = AR5312_RC_BB1_CRES | AR5312_RC_WBB1_RES; 842185377Ssam /* Warm and cold reset bits for wbb */ 843185377Ssam resetBits = AR5312_RC_WMAC1_RES; 844185377Ssam break; 845185377Ssam default: 846185377Ssam return(AH_FALSE); 847185377Ssam } 848185377Ssam regMask = ~(resetBB | resetBits); 849185377Ssam 850185377Ssam /* read before */ 851185377Ssam reg = OS_REG_READ(ah, 852185377Ssam (AR5312_RSTIMER_BASE - ((uint32_t) ah->ah_sh) + AR5312_RESET)); 853185377Ssam 854185377Ssam if (RCMask == AR_RC_BB) { 855185377Ssam /* Put baseband in reset */ 856185377Ssam reg |= resetBB; /* Cold and warm reset the baseband bits */ 857185377Ssam } else { 858185377Ssam /* 859185377Ssam * Reset the MAC and baseband. This is a bit different than 860185377Ssam * the PCI version, but holding in reset causes problems. 861185377Ssam */ 862185377Ssam reg &= regMask; 863185377Ssam reg |= (resetBits | resetBB) ; 864185377Ssam } 865185377Ssam OS_REG_WRITE(ah, 866185377Ssam (AR5312_RSTIMER_BASE - ((uint32_t) ah->ah_sh)+AR5312_RESET), 867185377Ssam reg); 868185377Ssam /* read after */ 869185377Ssam OS_REG_READ(ah, 870185377Ssam (AR5312_RSTIMER_BASE - ((uint32_t) ah->ah_sh) +AR5312_RESET)); 871185377Ssam OS_DELAY(100); 872185377Ssam 873185377Ssam /* Bring MAC and baseband out of reset */ 874185377Ssam reg &= regMask; 875185377Ssam /* read before */ 876185377Ssam OS_REG_READ(ah, 877185377Ssam (AR5312_RSTIMER_BASE- ((uint32_t) ah->ah_sh) +AR5312_RESET)); 878185377Ssam OS_REG_WRITE(ah, 879185377Ssam (AR5312_RSTIMER_BASE - ((uint32_t) ah->ah_sh)+AR5312_RESET), 880185377Ssam reg); 881185377Ssam /* read after */ 882185377Ssam OS_REG_READ(ah, 883185377Ssam (AR5312_RSTIMER_BASE- ((uint32_t) ah->ah_sh) +AR5312_RESET)); 884185377Ssam } 885185377Ssam return(AH_TRUE); 886185377Ssam} 887185377Ssam 888185377Ssam#endif /* AH_SUPPORT_AR5312 */ 889