1185377Ssam/* 2187831Ssam * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting 3185377Ssam * Copyright (c) 2002-2006 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 * 17187831Ssam * $FreeBSD$ 18185377Ssam */ 19185377Ssam#include "opt_ah.h" 20185377Ssam 21185377Ssam#include "ah.h" 22185377Ssam#include "ah_internal.h" 23185377Ssam#include "ah_devid.h" 24185377Ssam 25185377Ssam#include "ar5211/ar5211.h" 26185377Ssam#include "ar5211/ar5211reg.h" 27185377Ssam#include "ar5211/ar5211phy.h" 28185377Ssam 29185377Ssam#include "ah_eeprom_v3.h" 30185377Ssam 31185377Ssamstatic HAL_BOOL ar5211GetChannelEdges(struct ath_hal *ah, 32185377Ssam uint16_t flags, uint16_t *low, uint16_t *high); 33185377Ssamstatic HAL_BOOL ar5211GetChipPowerLimits(struct ath_hal *ah, 34187831Ssam struct ieee80211_channel *chan); 35185377Ssam 36235972Sadrianstatic void ar5211ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore, 37235972Sadrian HAL_BOOL power_off); 38188979Ssamstatic void ar5211DisablePCIE(struct ath_hal *ah); 39188979Ssam 40185377Ssamstatic const struct ath_hal_private ar5211hal = {{ 41185377Ssam .ah_magic = AR5211_MAGIC, 42185377Ssam 43185377Ssam .ah_getRateTable = ar5211GetRateTable, 44185377Ssam .ah_detach = ar5211Detach, 45185377Ssam 46185377Ssam /* Reset Functions */ 47185377Ssam .ah_reset = ar5211Reset, 48185377Ssam .ah_phyDisable = ar5211PhyDisable, 49185377Ssam .ah_disable = ar5211Disable, 50188979Ssam .ah_configPCIE = ar5211ConfigPCIE, 51188979Ssam .ah_disablePCIE = ar5211DisablePCIE, 52185377Ssam .ah_setPCUConfig = ar5211SetPCUConfig, 53185377Ssam .ah_perCalibration = ar5211PerCalibration, 54185380Ssam .ah_perCalibrationN = ar5211PerCalibrationN, 55185380Ssam .ah_resetCalValid = ar5211ResetCalValid, 56185377Ssam .ah_setTxPowerLimit = ar5211SetTxPowerLimit, 57185377Ssam .ah_getChanNoise = ath_hal_getChanNoise, 58185377Ssam 59185377Ssam /* Transmit functions */ 60185377Ssam .ah_updateTxTrigLevel = ar5211UpdateTxTrigLevel, 61185377Ssam .ah_setupTxQueue = ar5211SetupTxQueue, 62185377Ssam .ah_setTxQueueProps = ar5211SetTxQueueProps, 63185377Ssam .ah_getTxQueueProps = ar5211GetTxQueueProps, 64185377Ssam .ah_releaseTxQueue = ar5211ReleaseTxQueue, 65185377Ssam .ah_resetTxQueue = ar5211ResetTxQueue, 66185377Ssam .ah_getTxDP = ar5211GetTxDP, 67185377Ssam .ah_setTxDP = ar5211SetTxDP, 68185377Ssam .ah_numTxPending = ar5211NumTxPending, 69185377Ssam .ah_startTxDma = ar5211StartTxDma, 70185377Ssam .ah_stopTxDma = ar5211StopTxDma, 71185377Ssam .ah_setupTxDesc = ar5211SetupTxDesc, 72185377Ssam .ah_setupXTxDesc = ar5211SetupXTxDesc, 73185377Ssam .ah_fillTxDesc = ar5211FillTxDesc, 74185377Ssam .ah_procTxDesc = ar5211ProcTxDesc, 75185377Ssam .ah_getTxIntrQueue = ar5211GetTxIntrQueue, 76185377Ssam .ah_reqTxIntrDesc = ar5211IntrReqTxDesc, 77217621Sadrian .ah_getTxCompletionRates = ar5211GetTxCompletionRates, 78238607Sadrian .ah_setTxDescLink = ar5211SetTxDescLink, 79238607Sadrian .ah_getTxDescLink = ar5211GetTxDescLink, 80238607Sadrian .ah_getTxDescLinkPtr = ar5211GetTxDescLinkPtr, 81185377Ssam 82185377Ssam /* RX Functions */ 83185377Ssam .ah_getRxDP = ar5211GetRxDP, 84185377Ssam .ah_setRxDP = ar5211SetRxDP, 85185377Ssam .ah_enableReceive = ar5211EnableReceive, 86185377Ssam .ah_stopDmaReceive = ar5211StopDmaReceive, 87185377Ssam .ah_startPcuReceive = ar5211StartPcuReceive, 88185377Ssam .ah_stopPcuReceive = ar5211StopPcuReceive, 89185377Ssam .ah_setMulticastFilter = ar5211SetMulticastFilter, 90185377Ssam .ah_setMulticastFilterIndex = ar5211SetMulticastFilterIndex, 91185377Ssam .ah_clrMulticastFilterIndex = ar5211ClrMulticastFilterIndex, 92185377Ssam .ah_getRxFilter = ar5211GetRxFilter, 93185377Ssam .ah_setRxFilter = ar5211SetRxFilter, 94185377Ssam .ah_setupRxDesc = ar5211SetupRxDesc, 95185377Ssam .ah_procRxDesc = ar5211ProcRxDesc, 96217684Sadrian .ah_rxMonitor = ar5211RxMonitor, 97217684Sadrian .ah_aniPoll = ar5211AniPoll, 98185377Ssam .ah_procMibEvent = ar5211MibEvent, 99185377Ssam 100185377Ssam /* Misc Functions */ 101185377Ssam .ah_getCapability = ar5211GetCapability, 102185377Ssam .ah_setCapability = ar5211SetCapability, 103185377Ssam .ah_getDiagState = ar5211GetDiagState, 104185377Ssam .ah_getMacAddress = ar5211GetMacAddress, 105185377Ssam .ah_setMacAddress = ar5211SetMacAddress, 106185377Ssam .ah_getBssIdMask = ar5211GetBssIdMask, 107185377Ssam .ah_setBssIdMask = ar5211SetBssIdMask, 108185380Ssam .ah_setRegulatoryDomain = ar5211SetRegulatoryDomain, 109185377Ssam .ah_setLedState = ar5211SetLedState, 110185377Ssam .ah_writeAssocid = ar5211WriteAssocid, 111185377Ssam .ah_gpioCfgInput = ar5211GpioCfgInput, 112185377Ssam .ah_gpioCfgOutput = ar5211GpioCfgOutput, 113185377Ssam .ah_gpioGet = ar5211GpioGet, 114185377Ssam .ah_gpioSet = ar5211GpioSet, 115185377Ssam .ah_gpioSetIntr = ar5211GpioSetIntr, 116185377Ssam .ah_getTsf32 = ar5211GetTsf32, 117185377Ssam .ah_getTsf64 = ar5211GetTsf64, 118185377Ssam .ah_resetTsf = ar5211ResetTsf, 119185377Ssam .ah_detectCardPresent = ar5211DetectCardPresent, 120185377Ssam .ah_updateMibCounters = ar5211UpdateMibCounters, 121185377Ssam .ah_getRfGain = ar5211GetRfgain, 122185377Ssam .ah_getDefAntenna = ar5211GetDefAntenna, 123185377Ssam .ah_setDefAntenna = ar5211SetDefAntenna, 124185377Ssam .ah_getAntennaSwitch = ar5211GetAntennaSwitch, 125185377Ssam .ah_setAntennaSwitch = ar5211SetAntennaSwitch, 126185377Ssam .ah_setSifsTime = ar5211SetSifsTime, 127185377Ssam .ah_getSifsTime = ar5211GetSifsTime, 128185377Ssam .ah_setSlotTime = ar5211SetSlotTime, 129185377Ssam .ah_getSlotTime = ar5211GetSlotTime, 130185377Ssam .ah_setAckTimeout = ar5211SetAckTimeout, 131185377Ssam .ah_getAckTimeout = ar5211GetAckTimeout, 132185377Ssam .ah_setAckCTSRate = ar5211SetAckCTSRate, 133185377Ssam .ah_getAckCTSRate = ar5211GetAckCTSRate, 134185377Ssam .ah_setCTSTimeout = ar5211SetCTSTimeout, 135185377Ssam .ah_getCTSTimeout = ar5211GetCTSTimeout, 136234873Sadrian .ah_setDecompMask = ar5211SetDecompMask, 137234873Sadrian .ah_setCoverageClass = ar5211SetCoverageClass, 138234873Sadrian .ah_get11nExtBusy = ar5211Get11nExtBusy, 139234873Sadrian .ah_getMibCycleCounts = ar5211GetMibCycleCounts, 140247286Sadrian .ah_setChainMasks = ar5211SetChainMasks, 141235206Sadrian .ah_enableDfs = ar5211EnableDfs, 142235206Sadrian .ah_getDfsThresh = ar5211GetDfsThresh, 143235206Sadrian /* XXX procRadarEvent */ 144235206Sadrian /* XXX isFastClockEnabled */ 145185377Ssam 146185377Ssam /* Key Cache Functions */ 147185377Ssam .ah_getKeyCacheSize = ar5211GetKeyCacheSize, 148185377Ssam .ah_resetKeyCacheEntry = ar5211ResetKeyCacheEntry, 149185377Ssam .ah_isKeyCacheEntryValid = ar5211IsKeyCacheEntryValid, 150185377Ssam .ah_setKeyCacheEntry = ar5211SetKeyCacheEntry, 151185377Ssam .ah_setKeyCacheEntryMac = ar5211SetKeyCacheEntryMac, 152185377Ssam 153185377Ssam /* Power Management Functions */ 154185377Ssam .ah_setPowerMode = ar5211SetPowerMode, 155185377Ssam .ah_getPowerMode = ar5211GetPowerMode, 156185377Ssam 157185377Ssam /* Beacon Functions */ 158185377Ssam .ah_setBeaconTimers = ar5211SetBeaconTimers, 159185377Ssam .ah_beaconInit = ar5211BeaconInit, 160185377Ssam .ah_setStationBeaconTimers = ar5211SetStaBeaconTimers, 161185377Ssam .ah_resetStationBeaconTimers = ar5211ResetStaBeaconTimers, 162225444Sadrian .ah_getNextTBTT = ar5211GetNextTBTT, 163185377Ssam 164185377Ssam /* Interrupt Functions */ 165185377Ssam .ah_isInterruptPending = ar5211IsInterruptPending, 166185377Ssam .ah_getPendingInterrupts = ar5211GetPendingInterrupts, 167185377Ssam .ah_getInterrupts = ar5211GetInterrupts, 168185377Ssam .ah_setInterrupts = ar5211SetInterrupts }, 169185377Ssam 170185377Ssam .ah_getChannelEdges = ar5211GetChannelEdges, 171185377Ssam .ah_getWirelessModes = ar5211GetWirelessModes, 172185377Ssam .ah_eepromRead = ar5211EepromRead, 173185377Ssam#ifdef AH_SUPPORT_WRITE_EEPROM 174185377Ssam .ah_eepromWrite = ar5211EepromWrite, 175185377Ssam#endif 176185377Ssam .ah_getChipPowerLimits = ar5211GetChipPowerLimits, 177185377Ssam}; 178185377Ssam 179185377Ssamstatic HAL_BOOL ar5211ChipTest(struct ath_hal *); 180185377Ssamstatic HAL_BOOL ar5211FillCapabilityInfo(struct ath_hal *ah); 181185377Ssam 182185377Ssam/* 183185377Ssam * Return the revsion id for the radio chip. This 184185377Ssam * fetched via the PHY. 185185377Ssam */ 186185377Ssamstatic uint32_t 187185377Ssamar5211GetRadioRev(struct ath_hal *ah) 188185377Ssam{ 189185377Ssam uint32_t val; 190185377Ssam int i; 191185377Ssam 192185377Ssam OS_REG_WRITE(ah, (AR_PHY_BASE + (0x34 << 2)), 0x00001c16); 193185377Ssam for (i = 0; i < 8; i++) 194185377Ssam OS_REG_WRITE(ah, (AR_PHY_BASE + (0x20 << 2)), 0x00010000); 195185377Ssam val = (OS_REG_READ(ah, AR_PHY_BASE + (256 << 2)) >> 24) & 0xff; 196185377Ssam val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4); 197185377Ssam return ath_hal_reverseBits(val, 8); 198185377Ssam} 199185377Ssam 200185377Ssam/* 201185377Ssam * Attach for an AR5211 part. 202185377Ssam */ 203188972Ssamstatic struct ath_hal * 204185377Ssamar5211Attach(uint16_t devid, HAL_SOFTC sc, 205217624Sadrian HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata, 206217624Sadrian HAL_STATUS *status) 207185377Ssam{ 208185377Ssam#define N(a) (sizeof(a)/sizeof(a[0])) 209185377Ssam struct ath_hal_5211 *ahp; 210185377Ssam struct ath_hal *ah; 211185377Ssam uint32_t val; 212185377Ssam uint16_t eeval; 213185377Ssam HAL_STATUS ecode; 214185377Ssam 215225883Sadrian HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n", 216185377Ssam __func__, sc, (void*) st, (void*) sh); 217185377Ssam 218185377Ssam /* NB: memory is returned zero'd */ 219185377Ssam ahp = ath_hal_malloc(sizeof (struct ath_hal_5211)); 220185377Ssam if (ahp == AH_NULL) { 221225883Sadrian HALDEBUG(AH_NULL, HAL_DEBUG_ANY, 222185377Ssam "%s: cannot allocate memory for state block\n", __func__); 223185377Ssam ecode = HAL_ENOMEM; 224185377Ssam goto bad; 225185377Ssam } 226185377Ssam ah = &ahp->ah_priv.h; 227185377Ssam /* set initial values */ 228185377Ssam OS_MEMCPY(&ahp->ah_priv, &ar5211hal, sizeof(struct ath_hal_private)); 229185377Ssam ah->ah_sc = sc; 230185377Ssam ah->ah_st = st; 231185377Ssam ah->ah_sh = sh; 232185377Ssam 233185377Ssam ah->ah_devid = devid; /* NB: for AH_DEBUG_ALQ */ 234185377Ssam AH_PRIVATE(ah)->ah_devid = devid; 235185377Ssam AH_PRIVATE(ah)->ah_subvendorid = 0; /* XXX */ 236185377Ssam 237185377Ssam AH_PRIVATE(ah)->ah_powerLimit = MAX_RATE_POWER; 238185377Ssam AH_PRIVATE(ah)->ah_tpScale = HAL_TP_SCALE_MAX; /* no scaling */ 239185377Ssam 240185377Ssam ahp->ah_diversityControl = HAL_ANT_VARIABLE; 241185377Ssam ahp->ah_staId1Defaults = 0; 242185377Ssam ahp->ah_rssiThr = INIT_RSSI_THR; 243185377Ssam ahp->ah_sifstime = (u_int) -1; 244185377Ssam ahp->ah_slottime = (u_int) -1; 245185377Ssam ahp->ah_acktimeout = (u_int) -1; 246185377Ssam ahp->ah_ctstimeout = (u_int) -1; 247185377Ssam 248187831Ssam if (!ar5211ChipReset(ah, AH_NULL)) { /* reset chip */ 249185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__); 250185377Ssam ecode = HAL_EIO; 251185377Ssam goto bad; 252185377Ssam } 253185377Ssam if (AH_PRIVATE(ah)->ah_devid == AR5211_FPGA11B) { 254185377Ssam /* set it back to OFDM mode to be able to read analog rev id */ 255185377Ssam OS_REG_WRITE(ah, AR5211_PHY_MODE, AR5211_PHY_MODE_OFDM); 256185377Ssam OS_REG_WRITE(ah, AR_PHY_PLL_CTL, AR_PHY_PLL_CTL_44); 257185377Ssam OS_DELAY(1000); 258185377Ssam } 259185377Ssam 260185377Ssam /* Read Revisions from Chips */ 261185377Ssam val = OS_REG_READ(ah, AR_SREV) & AR_SREV_ID_M; 262185377Ssam AH_PRIVATE(ah)->ah_macVersion = val >> AR_SREV_ID_S; 263185377Ssam AH_PRIVATE(ah)->ah_macRev = val & AR_SREV_REVISION_M; 264185377Ssam 265185377Ssam if (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_MAUI_2 || 266185377Ssam AH_PRIVATE(ah)->ah_macVersion > AR_SREV_VERSION_OAHU) { 267185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, 268185377Ssam "%s: Mac Chip Rev 0x%x is not supported by this driver\n", 269185377Ssam __func__, AH_PRIVATE(ah)->ah_macVersion); 270185377Ssam ecode = HAL_ENOTSUPP; 271185377Ssam goto bad; 272185377Ssam } 273185377Ssam 274185377Ssam AH_PRIVATE(ah)->ah_phyRev = OS_REG_READ(ah, AR_PHY_CHIP_ID); 275185377Ssam 276185377Ssam if (!ar5211ChipTest(ah)) { 277185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, "%s: hardware self-test failed\n", 278185377Ssam __func__); 279185377Ssam ecode = HAL_ESELFTEST; 280185377Ssam goto bad; 281185377Ssam } 282185377Ssam 283185377Ssam /* Set correct Baseband to analog shift setting to access analog chips. */ 284185377Ssam if (AH_PRIVATE(ah)->ah_macVersion >= AR_SREV_VERSION_OAHU) { 285185377Ssam OS_REG_WRITE(ah, AR_PHY_BASE, 0x00000007); 286185377Ssam } else { 287185377Ssam OS_REG_WRITE(ah, AR_PHY_BASE, 0x00000047); 288185377Ssam } 289185377Ssam OS_DELAY(2000); 290185377Ssam 291185377Ssam /* Read Radio Chip Rev Extract */ 292185377Ssam AH_PRIVATE(ah)->ah_analog5GhzRev = ar5211GetRadioRev(ah); 293185377Ssam if ((AH_PRIVATE(ah)->ah_analog5GhzRev & 0xf0) != RAD5_SREV_MAJOR) { 294185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, 295185377Ssam "%s: 5G Radio Chip Rev 0x%02X is not supported by this " 296185377Ssam "driver\n", __func__, AH_PRIVATE(ah)->ah_analog5GhzRev); 297185377Ssam ecode = HAL_ENOTSUPP; 298185377Ssam goto bad; 299185377Ssam } 300185377Ssam 301185377Ssam val = (OS_REG_READ(ah, AR_PCICFG) & AR_PCICFG_EEPROM_SIZE_M) >> 302185377Ssam AR_PCICFG_EEPROM_SIZE_S; 303185377Ssam if (val != AR_PCICFG_EEPROM_SIZE_16K) { 304185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unsupported EEPROM size " 305185377Ssam "%u (0x%x) found\n", __func__, val, val); 306185377Ssam ecode = HAL_EESIZE; 307185377Ssam goto bad; 308185377Ssam } 309185377Ssam ecode = ath_hal_legacyEepromAttach(ah); 310185377Ssam if (ecode != HAL_OK) { 311185377Ssam goto bad; 312185377Ssam } 313185377Ssam 314185377Ssam /* If Bmode and AR5211, verify 2.4 analog exists */ 315185377Ssam if (AH_PRIVATE(ah)->ah_macVersion >= AR_SREV_VERSION_OAHU && 316185377Ssam ath_hal_eepromGetFlag(ah, AR_EEP_BMODE)) { 317185377Ssam /* Set correct Baseband to analog shift setting to access analog chips. */ 318185377Ssam OS_REG_WRITE(ah, AR_PHY_BASE, 0x00004007); 319185377Ssam OS_DELAY(2000); 320185377Ssam AH_PRIVATE(ah)->ah_analog2GhzRev = ar5211GetRadioRev(ah); 321185377Ssam 322185377Ssam /* Set baseband for 5GHz chip */ 323185377Ssam OS_REG_WRITE(ah, AR_PHY_BASE, 0x00000007); 324185377Ssam OS_DELAY(2000); 325185377Ssam if ((AH_PRIVATE(ah)->ah_analog2GhzRev & 0xF0) != RAD2_SREV_MAJOR) { 326185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, 327185377Ssam "%s: 2G Radio Chip Rev 0x%x is not supported by " 328185377Ssam "this driver\n", __func__, 329185377Ssam AH_PRIVATE(ah)->ah_analog2GhzRev); 330185377Ssam ecode = HAL_ENOTSUPP; 331185377Ssam goto bad; 332185377Ssam } 333185377Ssam } else { 334185377Ssam ath_hal_eepromSet(ah, AR_EEP_BMODE, AH_FALSE); 335185377Ssam } 336185377Ssam 337185377Ssam ecode = ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, &eeval); 338185377Ssam if (ecode != HAL_OK) { 339185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, 340185377Ssam "%s: cannot read regulatory domain from EEPROM\n", 341185377Ssam __func__); 342185377Ssam goto bad; 343185377Ssam } 344185377Ssam AH_PRIVATE(ah)->ah_currentRD = eeval; 345185377Ssam AH_PRIVATE(ah)->ah_getNfAdjust = ar5211GetNfAdjust; 346185380Ssam 347185377Ssam /* 348185377Ssam * Got everything we need now to setup the capabilities. 349185377Ssam */ 350185377Ssam (void) ar5211FillCapabilityInfo(ah); 351185377Ssam 352185377Ssam /* Initialize gain ladder thermal calibration structure */ 353185377Ssam ar5211InitializeGainValues(ah); 354185377Ssam 355185377Ssam ecode = ath_hal_eepromGet(ah, AR_EEP_MACADDR, ahp->ah_macaddr); 356185377Ssam if (ecode != HAL_OK) { 357185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, 358185377Ssam "%s: error getting mac address from EEPROM\n", __func__); 359185377Ssam goto bad; 360185377Ssam } 361185377Ssam 362185377Ssam HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n", __func__); 363185377Ssam 364185377Ssam return ah; 365185377Ssambad: 366185377Ssam if (ahp) 367185377Ssam ar5211Detach((struct ath_hal *) ahp); 368185377Ssam if (status) 369185377Ssam *status = ecode; 370185377Ssam return AH_NULL; 371185377Ssam#undef N 372185377Ssam} 373185377Ssam 374185377Ssamvoid 375185377Ssamar5211Detach(struct ath_hal *ah) 376185377Ssam{ 377185377Ssam HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s:\n", __func__); 378185377Ssam 379185377Ssam HALASSERT(ah != AH_NULL); 380185377Ssam HALASSERT(ah->ah_magic == AR5211_MAGIC); 381185377Ssam 382185377Ssam ath_hal_eepromDetach(ah); 383185377Ssam ath_hal_free(ah); 384185377Ssam} 385185377Ssam 386185377Ssamstatic HAL_BOOL 387185377Ssamar5211ChipTest(struct ath_hal *ah) 388185377Ssam{ 389185377Ssam uint32_t regAddr[2] = { AR_STA_ID0, AR_PHY_BASE+(8 << 2) }; 390185377Ssam uint32_t regHold[2]; 391185377Ssam uint32_t patternData[4] = 392185377Ssam { 0x55555555, 0xaaaaaaaa, 0x66666666, 0x99999999 }; 393185377Ssam int i, j; 394185377Ssam 395185377Ssam /* Test PHY & MAC registers */ 396185377Ssam for (i = 0; i < 2; i++) { 397185377Ssam uint32_t addr = regAddr[i]; 398185377Ssam uint32_t wrData, rdData; 399185377Ssam 400185377Ssam regHold[i] = OS_REG_READ(ah, addr); 401185377Ssam for (j = 0; j < 0x100; j++) { 402185377Ssam wrData = (j << 16) | j; 403185377Ssam OS_REG_WRITE(ah, addr, wrData); 404185377Ssam rdData = OS_REG_READ(ah, addr); 405185377Ssam if (rdData != wrData) { 406185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, 407185377Ssam"%s: address test failed addr: 0x%08x - wr:0x%08x != rd:0x%08x\n", 408185377Ssam __func__, addr, wrData, rdData); 409185377Ssam return AH_FALSE; 410185377Ssam } 411185377Ssam } 412185377Ssam for (j = 0; j < 4; j++) { 413185377Ssam wrData = patternData[j]; 414185377Ssam OS_REG_WRITE(ah, addr, wrData); 415185377Ssam rdData = OS_REG_READ(ah, addr); 416185377Ssam if (wrData != rdData) { 417185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, 418185377Ssam"%s: address test failed addr: 0x%08x - wr:0x%08x != rd:0x%08x\n", 419185377Ssam __func__, addr, wrData, rdData); 420185377Ssam return AH_FALSE; 421185377Ssam } 422185377Ssam } 423185377Ssam OS_REG_WRITE(ah, regAddr[i], regHold[i]); 424185377Ssam } 425185377Ssam OS_DELAY(100); 426185377Ssam return AH_TRUE; 427185377Ssam} 428185377Ssam 429185377Ssam/* 430185377Ssam * Store the channel edges for the requested operational mode 431185377Ssam */ 432185377Ssamstatic HAL_BOOL 433185377Ssamar5211GetChannelEdges(struct ath_hal *ah, 434185377Ssam uint16_t flags, uint16_t *low, uint16_t *high) 435185377Ssam{ 436187831Ssam if (flags & IEEE80211_CHAN_5GHZ) { 437185377Ssam *low = 4920; 438185377Ssam *high = 6100; 439185377Ssam return AH_TRUE; 440185377Ssam } 441187831Ssam if (flags & IEEE80211_CHAN_2GHZ && 442187831Ssam ath_hal_eepromGetFlag(ah, AR_EEP_BMODE)) { 443185377Ssam *low = 2312; 444185377Ssam *high = 2732; 445185377Ssam return AH_TRUE; 446185377Ssam } 447185377Ssam return AH_FALSE; 448185377Ssam} 449185377Ssam 450185377Ssamstatic HAL_BOOL 451187831Ssamar5211GetChipPowerLimits(struct ath_hal *ah, struct ieee80211_channel *chan) 452185377Ssam{ 453185377Ssam /* XXX fill in, this is just a placeholder */ 454187831Ssam HALDEBUG(ah, HAL_DEBUG_ATTACH, 455187831Ssam "%s: no min/max power for %u/0x%x\n", 456187831Ssam __func__, chan->ic_freq, chan->ic_flags); 457187831Ssam chan->ic_maxpower = MAX_RATE_POWER; 458187831Ssam chan->ic_minpower = 0; 459185377Ssam return AH_TRUE; 460185377Ssam} 461185377Ssam 462188979Ssamstatic void 463235972Sadrianar5211ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore, HAL_BOOL power_off) 464188979Ssam{ 465188979Ssam} 466188979Ssam 467188979Ssamstatic void 468188979Ssamar5211DisablePCIE(struct ath_hal *ah) 469188979Ssam{ 470188979Ssam} 471188979Ssam 472185377Ssam/* 473185377Ssam * Fill all software cached or static hardware state information. 474185377Ssam */ 475185377Ssamstatic HAL_BOOL 476185377Ssamar5211FillCapabilityInfo(struct ath_hal *ah) 477185377Ssam{ 478185377Ssam struct ath_hal_private *ahpriv = AH_PRIVATE(ah); 479185377Ssam HAL_CAPABILITIES *pCap = &ahpriv->ah_caps; 480185377Ssam 481185377Ssam /* Construct wireless mode from EEPROM */ 482185377Ssam pCap->halWirelessModes = 0; 483185377Ssam if (ath_hal_eepromGetFlag(ah, AR_EEP_AMODE)) { 484185377Ssam pCap->halWirelessModes |= HAL_MODE_11A; 485185377Ssam if (!ath_hal_eepromGetFlag(ah, AR_EEP_TURBO5DISABLE)) 486185377Ssam pCap->halWirelessModes |= HAL_MODE_TURBO; 487185377Ssam } 488185377Ssam if (ath_hal_eepromGetFlag(ah, AR_EEP_BMODE)) 489185377Ssam pCap->halWirelessModes |= HAL_MODE_11B; 490185377Ssam 491185377Ssam pCap->halLow2GhzChan = 2312; 492185377Ssam pCap->halHigh2GhzChan = 2732; 493185377Ssam pCap->halLow5GhzChan = 4920; 494185377Ssam pCap->halHigh5GhzChan = 6100; 495185377Ssam 496185377Ssam pCap->halChanSpreadSupport = AH_TRUE; 497185377Ssam pCap->halSleepAfterBeaconBroken = AH_TRUE; 498185377Ssam pCap->halPSPollBroken = AH_TRUE; 499185377Ssam pCap->halVEOLSupport = AH_TRUE; 500238858Sadrian pCap->halNumMRRetries = 1; /* No hardware MRR support */ 501239643Sadrian pCap->halNumTxMaps = 1; /* Single TX ptr per descr */ 502185377Ssam 503185377Ssam pCap->halTotalQueues = HAL_NUM_TX_QUEUES; 504185377Ssam pCap->halKeyCacheSize = 128; 505185377Ssam 506185377Ssam /* XXX not needed */ 507185377Ssam pCap->halChanHalfRate = AH_FALSE; 508185377Ssam pCap->halChanQuarterRate = AH_FALSE; 509185377Ssam 510230791Sadrian /* 511230791Sadrian * RSSI uses the combined field; some 11n NICs may use 512230791Sadrian * the control chain RSSI. 513230791Sadrian */ 514230791Sadrian pCap->halUseCombinedRadarRssi = AH_TRUE; 515230791Sadrian 516185377Ssam if (ath_hal_eepromGetFlag(ah, AR_EEP_RFKILL) && 517185377Ssam ath_hal_eepromGet(ah, AR_EEP_RFSILENT, &ahpriv->ah_rfsilent) == HAL_OK) { 518185377Ssam /* NB: enabled by default */ 519185377Ssam ahpriv->ah_rfkillEnabled = AH_TRUE; 520185377Ssam pCap->halRfSilentSupport = AH_TRUE; 521185377Ssam } 522185377Ssam 523185377Ssam pCap->halTstampPrecision = 13; 524192396Ssam pCap->halIntrMask = HAL_INT_COMMON 525192396Ssam | HAL_INT_RX 526192396Ssam | HAL_INT_TX 527192396Ssam | HAL_INT_FATAL 528192396Ssam | HAL_INT_BNR 529192396Ssam | HAL_INT_TIM 530192396Ssam ; 531185377Ssam 532218436Sadrian pCap->hal4kbSplitTransSupport = AH_TRUE; 533220324Sadrian pCap->halHasRxSelfLinkedTail = AH_TRUE; 534218436Sadrian 535185377Ssam /* XXX might be ok w/ some chip revs */ 536185377Ssam ahpriv->ah_rxornIsFatal = AH_TRUE; 537185377Ssam return AH_TRUE; 538185377Ssam} 539185406Ssam 540185406Ssamstatic const char* 541185406Ssamar5211Probe(uint16_t vendorid, uint16_t devid) 542185406Ssam{ 543185406Ssam if (vendorid == ATHEROS_VENDOR_ID) { 544185406Ssam if (devid == AR5211_DEVID || devid == AR5311_DEVID || 545185406Ssam devid == AR5211_DEFAULT) 546185406Ssam return "Atheros 5211"; 547185406Ssam if (devid == AR5211_FPGA11B) 548185406Ssam return "Atheros 5211 (FPGA)"; 549185406Ssam } 550185406Ssam return AH_NULL; 551185406Ssam} 552185418SsamAH_CHIP(AR5211, ar5211Probe, ar5211Attach); 553