| 1 | /* |
| 2 | * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting |
| 3 | * Copyright (c) 2002-2006 Atheros Communications, Inc. |
| 4 | * |
| 5 | * Permission to use, copy, modify, and/or distribute this software for any |
| 6 | * purpose with or without fee is hereby granted, provided that the above |
| 7 | * copyright notice and this permission notice appear in all copies. |
| 8 | * |
| 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
| 10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
| 11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
| 12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
| 13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
| 14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
| 15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
| 16 | * |
| 17 | * $Id: ar5211_attach.c,v 1.3 2011/03/07 11:25:42 cegger Exp $ |
| 18 | */ |
| 19 | #include "opt_ah.h" |
| 20 | |
| 21 | #include "ah.h" |
| 22 | #include "ah_internal.h" |
| 23 | #include "ah_devid.h" |
| 24 | |
| 25 | #include "ar5211/ar5211.h" |
| 26 | #include "ar5211/ar5211reg.h" |
| 27 | #include "ar5211/ar5211phy.h" |
| 28 | |
| 29 | #include "ah_eeprom_v3.h" |
| 30 | |
| 31 | static HAL_BOOL ar5211GetChannelEdges(struct ath_hal *ah, |
| 32 | uint16_t flags, uint16_t *low, uint16_t *high); |
| 33 | static HAL_BOOL ar5211GetChipPowerLimits(struct ath_hal *ah, |
| 34 | HAL_CHANNEL *chans, uint32_t nchans); |
| 35 | |
| 36 | static void ar5211ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore); |
| 37 | static void ar5211DisablePCIE(struct ath_hal *ah); |
| 38 | |
| 39 | static const struct ath_hal_private ar5211hal = {{ |
| 40 | .ah_magic = AR5211_MAGIC, |
| 41 | .ah_abi = HAL_ABI_VERSION, |
| 42 | .ah_countryCode = CTRY_DEFAULT, |
| 43 | |
| 44 | .ah_getRateTable = ar5211GetRateTable, |
| 45 | .ah_detach = ar5211Detach, |
| 46 | |
| 47 | /* Reset Functions */ |
| 48 | .ah_reset = ar5211Reset, |
| 49 | .ah_phyDisable = ar5211PhyDisable, |
| 50 | .ah_disable = ar5211Disable, |
| 51 | .ah_configPCIE = ar5211ConfigPCIE, |
| 52 | .ah_disablePCIE = ar5211DisablePCIE, |
| 53 | .ah_setPCUConfig = ar5211SetPCUConfig, |
| 54 | .ah_perCalibration = ar5211PerCalibration, |
| 55 | .ah_perCalibrationN = ar5211PerCalibrationN, |
| 56 | .ah_resetCalValid = ar5211ResetCalValid, |
| 57 | .ah_setTxPowerLimit = ar5211SetTxPowerLimit, |
| 58 | .ah_getChanNoise = ath_hal_getChanNoise, |
| 59 | |
| 60 | /* Transmit functions */ |
| 61 | .ah_updateTxTrigLevel = ar5211UpdateTxTrigLevel, |
| 62 | .ah_setupTxQueue = ar5211SetupTxQueue, |
| 63 | .ah_setTxQueueProps = ar5211SetTxQueueProps, |
| 64 | .ah_getTxQueueProps = ar5211GetTxQueueProps, |
| 65 | .ah_releaseTxQueue = ar5211ReleaseTxQueue, |
| 66 | .ah_resetTxQueue = ar5211ResetTxQueue, |
| 67 | .ah_getTxDP = ar5211GetTxDP, |
| 68 | .ah_setTxDP = ar5211SetTxDP, |
| 69 | .ah_numTxPending = ar5211NumTxPending, |
| 70 | .ah_startTxDma = ar5211StartTxDma, |
| 71 | .ah_stopTxDma = ar5211StopTxDma, |
| 72 | .ah_setupTxDesc = ar5211SetupTxDesc, |
| 73 | .ah_setupXTxDesc = ar5211SetupXTxDesc, |
| 74 | .ah_fillTxDesc = ar5211FillTxDesc, |
| 75 | .ah_procTxDesc = ar5211ProcTxDesc, |
| 76 | .ah_getTxIntrQueue = ar5211GetTxIntrQueue, |
| 77 | .ah_reqTxIntrDesc = ar5211IntrReqTxDesc, |
| 78 | |
| 79 | /* RX Functions */ |
| 80 | .ah_getRxDP = ar5211GetRxDP, |
| 81 | .ah_setRxDP = ar5211SetRxDP, |
| 82 | .ah_enableReceive = ar5211EnableReceive, |
| 83 | .ah_stopDmaReceive = ar5211StopDmaReceive, |
| 84 | .ah_startPcuReceive = ar5211StartPcuReceive, |
| 85 | .ah_stopPcuReceive = ar5211StopPcuReceive, |
| 86 | .ah_setMulticastFilter = ar5211SetMulticastFilter, |
| 87 | .ah_setMulticastFilterIndex = ar5211SetMulticastFilterIndex, |
| 88 | .ah_clrMulticastFilterIndex = ar5211ClrMulticastFilterIndex, |
| 89 | .ah_getRxFilter = ar5211GetRxFilter, |
| 90 | .ah_setRxFilter = ar5211SetRxFilter, |
| 91 | .ah_setupRxDesc = ar5211SetupRxDesc, |
| 92 | .ah_procRxDesc = ar5211ProcRxDesc, |
| 93 | .ah_rxMonitor = ar5211AniPoll, |
| 94 | .ah_procMibEvent = ar5211MibEvent, |
| 95 | |
| 96 | /* Misc Functions */ |
| 97 | .ah_getCapability = ar5211GetCapability, |
| 98 | .ah_setCapability = ar5211SetCapability, |
| 99 | .ah_getDiagState = ar5211GetDiagState, |
| 100 | .ah_getMacAddress = ar5211GetMacAddress, |
| 101 | .ah_setMacAddress = ar5211SetMacAddress, |
| 102 | .ah_getBssIdMask = ar5211GetBssIdMask, |
| 103 | .ah_setBssIdMask = ar5211SetBssIdMask, |
| 104 | .ah_setRegulatoryDomain = ar5211SetRegulatoryDomain, |
| 105 | .ah_setLedState = ar5211SetLedState, |
| 106 | .ah_writeAssocid = ar5211WriteAssocid, |
| 107 | .ah_gpioCfgInput = ar5211GpioCfgInput, |
| 108 | .ah_gpioCfgOutput = ar5211GpioCfgOutput, |
| 109 | .ah_gpioGet = ar5211GpioGet, |
| 110 | .ah_gpioSet = ar5211GpioSet, |
| 111 | .ah_gpioSetIntr = ar5211GpioSetIntr, |
| 112 | .ah_getTsf32 = ar5211GetTsf32, |
| 113 | .ah_getTsf64 = ar5211GetTsf64, |
| 114 | .ah_resetTsf = ar5211ResetTsf, |
| 115 | .ah_detectCardPresent = ar5211DetectCardPresent, |
| 116 | .ah_updateMibCounters = ar5211UpdateMibCounters, |
| 117 | .ah_getRfGain = ar5211GetRfgain, |
| 118 | .ah_getDefAntenna = ar5211GetDefAntenna, |
| 119 | .ah_setDefAntenna = ar5211SetDefAntenna, |
| 120 | .ah_getAntennaSwitch = ar5211GetAntennaSwitch, |
| 121 | .ah_setAntennaSwitch = ar5211SetAntennaSwitch, |
| 122 | .ah_setSifsTime = ar5211SetSifsTime, |
| 123 | .ah_getSifsTime = ar5211GetSifsTime, |
| 124 | .ah_setSlotTime = ar5211SetSlotTime, |
| 125 | .ah_getSlotTime = ar5211GetSlotTime, |
| 126 | .ah_setAckTimeout = ar5211SetAckTimeout, |
| 127 | .ah_getAckTimeout = ar5211GetAckTimeout, |
| 128 | .ah_setAckCTSRate = ar5211SetAckCTSRate, |
| 129 | .ah_getAckCTSRate = ar5211GetAckCTSRate, |
| 130 | .ah_setCTSTimeout = ar5211SetCTSTimeout, |
| 131 | .ah_getCTSTimeout = ar5211GetCTSTimeout, |
| 132 | .ah_setDecompMask = ar5211SetDecompMask, |
| 133 | .ah_setCoverageClass = ar5211SetCoverageClass, |
| 134 | |
| 135 | /* Key Cache Functions */ |
| 136 | .ah_getKeyCacheSize = ar5211GetKeyCacheSize, |
| 137 | .ah_resetKeyCacheEntry = ar5211ResetKeyCacheEntry, |
| 138 | .ah_isKeyCacheEntryValid = ar5211IsKeyCacheEntryValid, |
| 139 | .ah_setKeyCacheEntry = ar5211SetKeyCacheEntry, |
| 140 | .ah_setKeyCacheEntryMac = ar5211SetKeyCacheEntryMac, |
| 141 | |
| 142 | /* Power Management Functions */ |
| 143 | .ah_setPowerMode = ar5211SetPowerMode, |
| 144 | .ah_getPowerMode = ar5211GetPowerMode, |
| 145 | |
| 146 | /* Beacon Functions */ |
| 147 | .ah_setBeaconTimers = ar5211SetBeaconTimers, |
| 148 | .ah_beaconInit = ar5211BeaconInit, |
| 149 | .ah_setStationBeaconTimers = ar5211SetStaBeaconTimers, |
| 150 | .ah_resetStationBeaconTimers = ar5211ResetStaBeaconTimers, |
| 151 | |
| 152 | /* Interrupt Functions */ |
| 153 | .ah_isInterruptPending = ar5211IsInterruptPending, |
| 154 | .ah_getPendingInterrupts = ar5211GetPendingInterrupts, |
| 155 | .ah_getInterrupts = ar5211GetInterrupts, |
| 156 | .ah_setInterrupts = ar5211SetInterrupts }, |
| 157 | |
| 158 | .ah_getChannelEdges = ar5211GetChannelEdges, |
| 159 | .ah_getWirelessModes = ar5211GetWirelessModes, |
| 160 | .ah_eepromRead = ar5211EepromRead, |
| 161 | #ifdef AH_SUPPORT_WRITE_EEPROM |
| 162 | .ah_eepromWrite = ar5211EepromWrite, |
| 163 | #endif |
| 164 | .ah_gpioCfgInput = ar5211GpioCfgInput, |
| 165 | .ah_gpioCfgOutput = ar5211GpioCfgOutput, |
| 166 | .ah_gpioGet = ar5211GpioGet, |
| 167 | .ah_gpioSet = ar5211GpioSet, |
| 168 | .ah_gpioSetIntr = ar5211GpioSetIntr, |
| 169 | .ah_getChipPowerLimits = ar5211GetChipPowerLimits, |
| 170 | }; |
| 171 | |
| 172 | static HAL_BOOL ar5211ChipTest(struct ath_hal *); |
| 173 | static HAL_BOOL ar5211FillCapabilityInfo(struct ath_hal *ah); |
| 174 | |
| 175 | /* |
| 176 | * Return the revsion id for the radio chip. This |
| 177 | * fetched via the PHY. |
| 178 | */ |
| 179 | static uint32_t |
| 180 | ar5211GetRadioRev(struct ath_hal *ah) |
| 181 | { |
| 182 | uint32_t val; |
| 183 | int i; |
| 184 | |
| 185 | OS_REG_WRITE(ah, (AR_PHY_BASE + (0x34 << 2)), 0x00001c16); |
| 186 | for (i = 0; i < 8; i++) |
| 187 | OS_REG_WRITE(ah, (AR_PHY_BASE + (0x20 << 2)), 0x00010000); |
| 188 | val = (OS_REG_READ(ah, AR_PHY_BASE + (256 << 2)) >> 24) & 0xff; |
| 189 | val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4); |
| 190 | return ath_hal_reverseBits(val, 8); |
| 191 | } |
| 192 | |
| 193 | /* |
| 194 | * Attach for an AR5211 part. |
| 195 | */ |
| 196 | struct ath_hal * |
| 197 | ar5211Attach(uint16_t devid, HAL_SOFTC sc, |
| 198 | HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *status) |
| 199 | { |
| 200 | #define N(a) (sizeof(a)/sizeof(a[0])) |
| 201 | struct ath_hal_5211 *ahp; |
| 202 | struct ath_hal *ah; |
| 203 | uint32_t val; |
| 204 | uint16_t eeval; |
| 205 | HAL_STATUS ecode; |
| 206 | |
| 207 | HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n" , |
| 208 | __func__, sc, (void*) st, (void*) sh); |
| 209 | |
| 210 | /* NB: memory is returned zero'd */ |
| 211 | ahp = ath_hal_malloc(sizeof (struct ath_hal_5211)); |
| 212 | if (ahp == AH_NULL) { |
| 213 | HALDEBUG(AH_NULL, HAL_DEBUG_ANY, |
| 214 | "%s: cannot allocate memory for state block\n" , __func__); |
| 215 | ecode = HAL_ENOMEM; |
| 216 | goto bad; |
| 217 | } |
| 218 | ah = &ahp->ah_priv.h; |
| 219 | /* set initial values */ |
| 220 | OS_MEMCPY(&ahp->ah_priv, &ar5211hal, sizeof(struct ath_hal_private)); |
| 221 | ah->ah_sc = sc; |
| 222 | ah->ah_st = st; |
| 223 | ah->ah_sh = sh; |
| 224 | |
| 225 | ah->ah_devid = devid; /* NB: for AH_DEBUG_ALQ */ |
| 226 | AH_PRIVATE(ah)->ah_devid = devid; |
| 227 | AH_PRIVATE(ah)->ah_subvendorid = 0; /* XXX */ |
| 228 | |
| 229 | AH_PRIVATE(ah)->ah_powerLimit = MAX_RATE_POWER; |
| 230 | AH_PRIVATE(ah)->ah_tpScale = HAL_TP_SCALE_MAX; /* no scaling */ |
| 231 | |
| 232 | ahp->ah_diversityControl = HAL_ANT_VARIABLE; |
| 233 | ahp->ah_staId1Defaults = 0; |
| 234 | ahp->ah_rssiThr = INIT_RSSI_THR; |
| 235 | ahp->ah_sifstime = (u_int) -1; |
| 236 | ahp->ah_slottime = (u_int) -1; |
| 237 | ahp->ah_acktimeout = (u_int) -1; |
| 238 | ahp->ah_ctstimeout = (u_int) -1; |
| 239 | |
| 240 | if (!ar5211ChipReset(ah, AH_FALSE)) { /* reset chip */ |
| 241 | HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n" , __func__); |
| 242 | ecode = HAL_EIO; |
| 243 | goto bad; |
| 244 | } |
| 245 | if (AH_PRIVATE(ah)->ah_devid == AR5211_FPGA11B) { |
| 246 | /* set it back to OFDM mode to be able to read analog rev id */ |
| 247 | OS_REG_WRITE(ah, AR5211_PHY_MODE, AR5211_PHY_MODE_OFDM); |
| 248 | OS_REG_WRITE(ah, AR_PHY_PLL_CTL, AR_PHY_PLL_CTL_44); |
| 249 | OS_DELAY(1000); |
| 250 | } |
| 251 | |
| 252 | /* Read Revisions from Chips */ |
| 253 | val = OS_REG_READ(ah, AR_SREV) & AR_SREV_ID_M; |
| 254 | AH_PRIVATE(ah)->ah_macVersion = val >> AR_SREV_ID_S; |
| 255 | AH_PRIVATE(ah)->ah_macRev = val & AR_SREV_REVISION_M; |
| 256 | |
| 257 | if (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_MAUI_2 || |
| 258 | AH_PRIVATE(ah)->ah_macVersion > AR_SREV_VERSION_OAHU) { |
| 259 | HALDEBUG(ah, HAL_DEBUG_ANY, |
| 260 | "%s: Mac Chip Rev 0x%x is not supported by this driver\n" , |
| 261 | __func__, AH_PRIVATE(ah)->ah_macVersion); |
| 262 | ecode = HAL_ENOTSUPP; |
| 263 | goto bad; |
| 264 | } |
| 265 | |
| 266 | AH_PRIVATE(ah)->ah_phyRev = OS_REG_READ(ah, AR_PHY_CHIP_ID); |
| 267 | |
| 268 | if (!ar5211ChipTest(ah)) { |
| 269 | HALDEBUG(ah, HAL_DEBUG_ANY, "%s: hardware self-test failed\n" , |
| 270 | __func__); |
| 271 | ecode = HAL_ESELFTEST; |
| 272 | goto bad; |
| 273 | } |
| 274 | |
| 275 | /* Set correct Baseband to analog shift setting to access analog chips. */ |
| 276 | if (AH_PRIVATE(ah)->ah_macVersion >= AR_SREV_VERSION_OAHU) { |
| 277 | OS_REG_WRITE(ah, AR_PHY_BASE, 0x00000007); |
| 278 | } else { |
| 279 | OS_REG_WRITE(ah, AR_PHY_BASE, 0x00000047); |
| 280 | } |
| 281 | OS_DELAY(2000); |
| 282 | |
| 283 | /* Read Radio Chip Rev Extract */ |
| 284 | AH_PRIVATE(ah)->ah_analog5GhzRev = ar5211GetRadioRev(ah); |
| 285 | if ((AH_PRIVATE(ah)->ah_analog5GhzRev & 0xf0) != RAD5_SREV_MAJOR) { |
| 286 | HALDEBUG(ah, HAL_DEBUG_ANY, |
| 287 | "%s: 5G Radio Chip Rev 0x%02X is not supported by this " |
| 288 | "driver\n" , __func__, AH_PRIVATE(ah)->ah_analog5GhzRev); |
| 289 | ecode = HAL_ENOTSUPP; |
| 290 | goto bad; |
| 291 | } |
| 292 | |
| 293 | val = (OS_REG_READ(ah, AR_PCICFG) & AR_PCICFG_EEPROM_SIZE_M) >> |
| 294 | AR_PCICFG_EEPROM_SIZE_S; |
| 295 | if (val != AR_PCICFG_EEPROM_SIZE_16K) { |
| 296 | HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unsupported EEPROM size " |
| 297 | "%u (0x%x) found\n" , __func__, val, val); |
| 298 | ecode = HAL_EESIZE; |
| 299 | goto bad; |
| 300 | } |
| 301 | ecode = ath_hal_legacyEepromAttach(ah); |
| 302 | if (ecode != HAL_OK) { |
| 303 | goto bad; |
| 304 | } |
| 305 | |
| 306 | /* If Bmode and AR5211, verify 2.4 analog exists */ |
| 307 | if (AH_PRIVATE(ah)->ah_macVersion >= AR_SREV_VERSION_OAHU && |
| 308 | ath_hal_eepromGetFlag(ah, AR_EEP_BMODE)) { |
| 309 | /* Set correct Baseband to analog shift setting to access analog chips. */ |
| 310 | OS_REG_WRITE(ah, AR_PHY_BASE, 0x00004007); |
| 311 | OS_DELAY(2000); |
| 312 | AH_PRIVATE(ah)->ah_analog2GhzRev = ar5211GetRadioRev(ah); |
| 313 | |
| 314 | /* Set baseband for 5GHz chip */ |
| 315 | OS_REG_WRITE(ah, AR_PHY_BASE, 0x00000007); |
| 316 | OS_DELAY(2000); |
| 317 | if ((AH_PRIVATE(ah)->ah_analog2GhzRev & 0xF0) != RAD2_SREV_MAJOR) { |
| 318 | HALDEBUG(ah, HAL_DEBUG_ANY, |
| 319 | "%s: 2G Radio Chip Rev 0x%x is not supported by " |
| 320 | "this driver\n" , __func__, |
| 321 | AH_PRIVATE(ah)->ah_analog2GhzRev); |
| 322 | ecode = HAL_ENOTSUPP; |
| 323 | goto bad; |
| 324 | } |
| 325 | } else { |
| 326 | ath_hal_eepromSet(ah, AR_EEP_BMODE, AH_FALSE); |
| 327 | } |
| 328 | |
| 329 | ecode = ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, &eeval); |
| 330 | if (ecode != HAL_OK) { |
| 331 | HALDEBUG(ah, HAL_DEBUG_ANY, |
| 332 | "%s: cannot read regulatory domain from EEPROM\n" , |
| 333 | __func__); |
| 334 | goto bad; |
| 335 | } |
| 336 | AH_PRIVATE(ah)->ah_currentRD = eeval; |
| 337 | AH_PRIVATE(ah)->ah_getNfAdjust = ar5211GetNfAdjust; |
| 338 | |
| 339 | /* |
| 340 | * Got everything we need now to setup the capabilities. |
| 341 | */ |
| 342 | (void) ar5211FillCapabilityInfo(ah); |
| 343 | |
| 344 | /* Initialize gain ladder thermal calibration structure */ |
| 345 | ar5211InitializeGainValues(ah); |
| 346 | |
| 347 | ecode = ath_hal_eepromGet(ah, AR_EEP_MACADDR, ahp->ah_macaddr); |
| 348 | if (ecode != HAL_OK) { |
| 349 | HALDEBUG(ah, HAL_DEBUG_ANY, |
| 350 | "%s: error getting mac address from EEPROM\n" , __func__); |
| 351 | goto bad; |
| 352 | } |
| 353 | |
| 354 | HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n" , __func__); |
| 355 | |
| 356 | return ah; |
| 357 | bad: |
| 358 | if (ahp) |
| 359 | ar5211Detach((struct ath_hal *) ahp); |
| 360 | if (status) |
| 361 | *status = ecode; |
| 362 | return AH_NULL; |
| 363 | #undef N |
| 364 | } |
| 365 | |
| 366 | void |
| 367 | ar5211Detach(struct ath_hal *ah) |
| 368 | { |
| 369 | HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s:\n" , __func__); |
| 370 | |
| 371 | HALASSERT(ah != AH_NULL); |
| 372 | HALASSERT(ah->ah_magic == AR5211_MAGIC); |
| 373 | |
| 374 | ath_hal_eepromDetach(ah); |
| 375 | ath_hal_free(ah); |
| 376 | } |
| 377 | |
| 378 | static HAL_BOOL |
| 379 | ar5211ChipTest(struct ath_hal *ah) |
| 380 | { |
| 381 | uint32_t regAddr[2] = { AR_STA_ID0, AR_PHY_BASE+(8 << 2) }; |
| 382 | uint32_t regHold[2]; |
| 383 | uint32_t patternData[4] = |
| 384 | { 0x55555555, 0xaaaaaaaa, 0x66666666, 0x99999999 }; |
| 385 | int i, j; |
| 386 | |
| 387 | /* Test PHY & MAC registers */ |
| 388 | for (i = 0; i < 2; i++) { |
| 389 | uint32_t addr = regAddr[i]; |
| 390 | uint32_t wrData, rdData; |
| 391 | |
| 392 | regHold[i] = OS_REG_READ(ah, addr); |
| 393 | for (j = 0; j < 0x100; j++) { |
| 394 | wrData = (j << 16) | j; |
| 395 | OS_REG_WRITE(ah, addr, wrData); |
| 396 | rdData = OS_REG_READ(ah, addr); |
| 397 | if (rdData != wrData) { |
| 398 | HALDEBUG(ah, HAL_DEBUG_ANY, |
| 399 | "%s: address test failed addr: 0x%08x - wr:0x%08x != rd:0x%08x\n" , |
| 400 | __func__, addr, wrData, rdData); |
| 401 | return AH_FALSE; |
| 402 | } |
| 403 | } |
| 404 | for (j = 0; j < 4; j++) { |
| 405 | wrData = patternData[j]; |
| 406 | OS_REG_WRITE(ah, addr, wrData); |
| 407 | rdData = OS_REG_READ(ah, addr); |
| 408 | if (wrData != rdData) { |
| 409 | HALDEBUG(ah, HAL_DEBUG_ANY, |
| 410 | "%s: address test failed addr: 0x%08x - wr:0x%08x != rd:0x%08x\n" , |
| 411 | __func__, addr, wrData, rdData); |
| 412 | return AH_FALSE; |
| 413 | } |
| 414 | } |
| 415 | OS_REG_WRITE(ah, regAddr[i], regHold[i]); |
| 416 | } |
| 417 | OS_DELAY(100); |
| 418 | return AH_TRUE; |
| 419 | } |
| 420 | |
| 421 | /* |
| 422 | * Store the channel edges for the requested operational mode |
| 423 | */ |
| 424 | static HAL_BOOL |
| 425 | ar5211GetChannelEdges(struct ath_hal *ah, |
| 426 | uint16_t flags, uint16_t *low, uint16_t *high) |
| 427 | { |
| 428 | if (flags & CHANNEL_5GHZ) { |
| 429 | *low = 4920; |
| 430 | *high = 6100; |
| 431 | return AH_TRUE; |
| 432 | } |
| 433 | if (flags & CHANNEL_2GHZ && ath_hal_eepromGetFlag(ah, AR_EEP_BMODE)) { |
| 434 | *low = 2312; |
| 435 | *high = 2732; |
| 436 | return AH_TRUE; |
| 437 | } |
| 438 | return AH_FALSE; |
| 439 | } |
| 440 | |
| 441 | static HAL_BOOL |
| 442 | ar5211GetChipPowerLimits(struct ath_hal *ah, HAL_CHANNEL *chans, uint32_t nchans) |
| 443 | { |
| 444 | HAL_CHANNEL *chan; |
| 445 | int i; |
| 446 | |
| 447 | /* XXX fill in, this is just a placeholder */ |
| 448 | for (i = 0; i < nchans; i++) { |
| 449 | chan = &chans[i]; |
| 450 | HALDEBUG(ah, HAL_DEBUG_ATTACH, |
| 451 | "%s: no min/max power for %u/0x%x\n" , |
| 452 | __func__, chan->channel, chan->channelFlags); |
| 453 | chan->maxTxPower = MAX_RATE_POWER; |
| 454 | chan->minTxPower = 0; |
| 455 | } |
| 456 | return AH_TRUE; |
| 457 | } |
| 458 | |
| 459 | static void |
| 460 | ar5211ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore) |
| 461 | { |
| 462 | } |
| 463 | |
| 464 | static void |
| 465 | ar5211DisablePCIE(struct ath_hal *ah) |
| 466 | { |
| 467 | } |
| 468 | |
| 469 | /* |
| 470 | * Fill all software cached or static hardware state information. |
| 471 | */ |
| 472 | static HAL_BOOL |
| 473 | ar5211FillCapabilityInfo(struct ath_hal *ah) |
| 474 | { |
| 475 | struct ath_hal_private *ahpriv = AH_PRIVATE(ah); |
| 476 | HAL_CAPABILITIES *pCap = &ahpriv->ah_caps; |
| 477 | |
| 478 | /* Construct wireless mode from EEPROM */ |
| 479 | pCap->halWirelessModes = 0; |
| 480 | if (ath_hal_eepromGetFlag(ah, AR_EEP_AMODE)) { |
| 481 | pCap->halWirelessModes |= HAL_MODE_11A; |
| 482 | if (!ath_hal_eepromGetFlag(ah, AR_EEP_TURBO5DISABLE)) |
| 483 | pCap->halWirelessModes |= HAL_MODE_TURBO; |
| 484 | } |
| 485 | if (ath_hal_eepromGetFlag(ah, AR_EEP_BMODE)) |
| 486 | pCap->halWirelessModes |= HAL_MODE_11B; |
| 487 | |
| 488 | pCap->halLow2GhzChan = 2312; |
| 489 | pCap->halHigh2GhzChan = 2732; |
| 490 | pCap->halLow5GhzChan = 4920; |
| 491 | pCap->halHigh5GhzChan = 6100; |
| 492 | |
| 493 | pCap->halChanSpreadSupport = AH_TRUE; |
| 494 | pCap->halSleepAfterBeaconBroken = AH_TRUE; |
| 495 | pCap->halPSPollBroken = AH_TRUE; |
| 496 | pCap->halVEOLSupport = AH_TRUE; |
| 497 | |
| 498 | pCap->halTotalQueues = HAL_NUM_TX_QUEUES; |
| 499 | pCap->halKeyCacheSize = 128; |
| 500 | |
| 501 | /* XXX not needed */ |
| 502 | pCap->halChanHalfRate = AH_FALSE; |
| 503 | pCap->halChanQuarterRate = AH_FALSE; |
| 504 | |
| 505 | if (ath_hal_eepromGetFlag(ah, AR_EEP_RFKILL) && |
| 506 | ath_hal_eepromGet(ah, AR_EEP_RFSILENT, &ahpriv->ah_rfsilent) == HAL_OK) { |
| 507 | /* NB: enabled by default */ |
| 508 | ahpriv->ah_rfkillEnabled = AH_TRUE; |
| 509 | pCap->halRfSilentSupport = AH_TRUE; |
| 510 | } |
| 511 | |
| 512 | pCap->halTstampPrecision = 13; |
| 513 | pCap->halIntrMask = HAL_INT_COMMON |
| 514 | | HAL_INT_RX |
| 515 | | HAL_INT_TX |
| 516 | | HAL_INT_FATAL |
| 517 | | HAL_INT_BNR |
| 518 | | HAL_INT_TIM |
| 519 | ; |
| 520 | |
| 521 | /* XXX might be ok w/ some chip revs */ |
| 522 | ahpriv->ah_rxornIsFatal = AH_TRUE; |
| 523 | return AH_TRUE; |
| 524 | } |
| 525 | |
| 526 | static const char* |
| 527 | ar5211Probe(uint16_t vendorid, uint16_t devid) |
| 528 | { |
| 529 | if (vendorid == ATHEROS_VENDOR_ID) { |
| 530 | if (devid == AR5211_DEVID || devid == AR5311_DEVID || |
| 531 | devid == AR5211_DEFAULT) |
| 532 | return "Atheros 5211" ; |
| 533 | if (devid == AR5211_FPGA11B) |
| 534 | return "Atheros 5211 (FPGA)" ; |
| 535 | } |
| 536 | return AH_NULL; |
| 537 | } |
| 538 | AH_CHIP(AR5211, ar5211Probe, ar5211Attach); |
| 539 | |