ar5416_attach.c revision 188979
1185377Ssam/* 2185377Ssam * Copyright (c) 2002-2008 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 * 17188970Ssam * $FreeBSD: head/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c 188979 2009-02-24 01:07:06Z sam $ 18185377Ssam */ 19185377Ssam#include "opt_ah.h" 20185377Ssam 21185377Ssam#include "ah.h" 22185377Ssam#include "ah_internal.h" 23185377Ssam#include "ah_devid.h" 24185377Ssam 25185377Ssam#include "ar5416/ar5416.h" 26185377Ssam#include "ar5416/ar5416reg.h" 27185377Ssam#include "ar5416/ar5416phy.h" 28185377Ssam 29185377Ssam#include "ar5416/ar5416.ini" 30185377Ssam 31188979Ssamstatic void ar5416ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore); 32188979Ssam 33185377Ssamstatic void 34185377Ssamar5416AniSetup(struct ath_hal *ah) 35185377Ssam{ 36185377Ssam static const struct ar5212AniParams aniparams = { 37185377Ssam .maxNoiseImmunityLevel = 4, /* levels 0..4 */ 38185377Ssam .totalSizeDesired = { -55, -55, -55, -55, -62 }, 39185377Ssam .coarseHigh = { -14, -14, -14, -14, -12 }, 40185377Ssam .coarseLow = { -64, -64, -64, -64, -70 }, 41185377Ssam .firpwr = { -78, -78, -78, -78, -80 }, 42185377Ssam .maxSpurImmunityLevel = 2, 43185377Ssam .cycPwrThr1 = { 2, 4, 6 }, 44185377Ssam .maxFirstepLevel = 2, /* levels 0..2 */ 45185377Ssam .firstep = { 0, 4, 8 }, 46185377Ssam .ofdmTrigHigh = 500, 47185377Ssam .ofdmTrigLow = 200, 48185377Ssam .cckTrigHigh = 200, 49185377Ssam .cckTrigLow = 100, 50185377Ssam .rssiThrHigh = 40, 51185377Ssam .rssiThrLow = 7, 52185377Ssam .period = 100, 53185377Ssam }; 54185377Ssam /* NB: ANI is not enabled yet */ 55185377Ssam ar5212AniAttach(ah, &aniparams, &aniparams, AH_FALSE); 56185377Ssam} 57185377Ssam 58185377Ssam/* 59185377Ssam * Attach for an AR5416 part. 60185377Ssam */ 61185377Ssamvoid 62185377Ssamar5416InitState(struct ath_hal_5416 *ahp5416, uint16_t devid, HAL_SOFTC sc, 63185377Ssam HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *status) 64185377Ssam{ 65185377Ssam struct ath_hal_5212 *ahp; 66185377Ssam struct ath_hal *ah; 67185377Ssam 68185377Ssam ahp = &ahp5416->ah_5212; 69185377Ssam ar5212InitState(ahp, devid, sc, st, sh, status); 70185377Ssam ah = &ahp->ah_priv.h; 71185377Ssam 72185377Ssam /* override 5212 methods for our needs */ 73185377Ssam ah->ah_magic = AR5416_MAGIC; 74185377Ssam ah->ah_getRateTable = ar5416GetRateTable; 75185377Ssam ah->ah_detach = ar5416Detach; 76185377Ssam 77185377Ssam /* Reset functions */ 78185377Ssam ah->ah_reset = ar5416Reset; 79185377Ssam ah->ah_phyDisable = ar5416PhyDisable; 80185377Ssam ah->ah_disable = ar5416Disable; 81188979Ssam ah->ah_configPCIE = ar5416ConfigPCIE; 82185377Ssam ah->ah_perCalibration = ar5416PerCalibration; 83185380Ssam ah->ah_perCalibrationN = ar5416PerCalibrationN, 84185380Ssam ah->ah_resetCalValid = ar5416ResetCalValid, 85185377Ssam ah->ah_setTxPowerLimit = ar5416SetTxPowerLimit; 86185377Ssam 87185377Ssam /* Transmit functions */ 88185377Ssam ah->ah_stopTxDma = ar5416StopTxDma; 89185377Ssam ah->ah_setupTxDesc = ar5416SetupTxDesc; 90185377Ssam ah->ah_setupXTxDesc = ar5416SetupXTxDesc; 91185377Ssam ah->ah_fillTxDesc = ar5416FillTxDesc; 92185377Ssam ah->ah_procTxDesc = ar5416ProcTxDesc; 93185377Ssam 94185377Ssam /* Receive Functions */ 95185377Ssam ah->ah_startPcuReceive = ar5416StartPcuReceive; 96185377Ssam ah->ah_stopPcuReceive = ar5416StopPcuReceive; 97185377Ssam ah->ah_setupRxDesc = ar5416SetupRxDesc; 98185377Ssam ah->ah_procRxDesc = ar5416ProcRxDesc; 99185380Ssam ah->ah_rxMonitor = ar5416AniPoll, 100185380Ssam ah->ah_procMibEvent = ar5416ProcessMibIntr, 101185377Ssam 102185377Ssam /* Misc Functions */ 103185377Ssam ah->ah_getDiagState = ar5416GetDiagState; 104185377Ssam ah->ah_setLedState = ar5416SetLedState; 105185377Ssam ah->ah_gpioCfgOutput = ar5416GpioCfgOutput; 106185377Ssam ah->ah_gpioCfgInput = ar5416GpioCfgInput; 107185377Ssam ah->ah_gpioGet = ar5416GpioGet; 108185377Ssam ah->ah_gpioSet = ar5416GpioSet; 109185377Ssam ah->ah_gpioSetIntr = ar5416GpioSetIntr; 110185377Ssam ah->ah_resetTsf = ar5416ResetTsf; 111185377Ssam ah->ah_getRfGain = ar5416GetRfgain; 112185377Ssam ah->ah_setAntennaSwitch = ar5416SetAntennaSwitch; 113185377Ssam ah->ah_setDecompMask = ar5416SetDecompMask; 114185377Ssam ah->ah_setCoverageClass = ar5416SetCoverageClass; 115185377Ssam 116185377Ssam ah->ah_resetKeyCacheEntry = ar5416ResetKeyCacheEntry; 117185377Ssam ah->ah_setKeyCacheEntry = ar5416SetKeyCacheEntry; 118185377Ssam 119185377Ssam /* Power Management Functions */ 120185377Ssam ah->ah_setPowerMode = ar5416SetPowerMode; 121185377Ssam 122185377Ssam /* Beacon Management Functions */ 123185377Ssam ah->ah_setBeaconTimers = ar5416SetBeaconTimers; 124185377Ssam ah->ah_beaconInit = ar5416BeaconInit; 125185377Ssam ah->ah_setStationBeaconTimers = ar5416SetStaBeaconTimers; 126185377Ssam ah->ah_resetStationBeaconTimers = ar5416ResetStaBeaconTimers; 127185377Ssam 128185377Ssam /* XXX 802.11n Functions */ 129185377Ssam#if 0 130185377Ssam ah->ah_chainTxDesc = ar5416ChainTxDesc; 131185377Ssam ah->ah_setupFirstTxDesc = ar5416SetupFirstTxDesc; 132185377Ssam ah->ah_setupLastTxDesc = ar5416SetupLastTxDesc; 133185377Ssam ah->ah_set11nRateScenario = ar5416Set11nRateScenario; 134185377Ssam ah->ah_set11nAggrMiddle = ar5416Set11nAggrMiddle; 135185377Ssam ah->ah_clr11nAggr = ar5416Clr11nAggr; 136185377Ssam ah->ah_set11nBurstDuration = ar5416Set11nBurstDuration; 137185377Ssam ah->ah_get11nExtBusy = ar5416Get11nExtBusy; 138185377Ssam ah->ah_set11nMac2040 = ar5416Set11nMac2040; 139185377Ssam ah->ah_get11nRxClear = ar5416Get11nRxClear; 140185377Ssam ah->ah_set11nRxClear = ar5416Set11nRxClear; 141185377Ssam#endif 142185377Ssam 143185377Ssam /* Interrupt functions */ 144185377Ssam ah->ah_isInterruptPending = ar5416IsInterruptPending; 145185377Ssam ah->ah_getPendingInterrupts = ar5416GetPendingInterrupts; 146185377Ssam ah->ah_setInterrupts = ar5416SetInterrupts; 147185377Ssam 148185377Ssam ahp->ah_priv.ah_getWirelessModes= ar5416GetWirelessModes; 149185377Ssam ahp->ah_priv.ah_eepromRead = ar5416EepromRead; 150185377Ssam#ifdef AH_SUPPORT_WRITE_EEPROM 151185377Ssam ahp->ah_priv.ah_eepromWrite = ar5416EepromWrite; 152185377Ssam#endif 153185377Ssam ahp->ah_priv.ah_getChipPowerLimits = ar5416GetChipPowerLimits; 154185377Ssam 155185377Ssam /* 156185377Ssam * Start by setting all Owl devices to 2x2 157185377Ssam */ 158185377Ssam AH5416(ah)->ah_rx_chainmask = AR5416_DEFAULT_RXCHAINMASK; 159185377Ssam AH5416(ah)->ah_tx_chainmask = AR5416_DEFAULT_TXCHAINMASK; 160185377Ssam} 161185377Ssam 162188971Ssamuint32_t 163188971Ssamar5416GetRadioRev(struct ath_hal *ah) 164188971Ssam{ 165188971Ssam uint32_t val; 166188971Ssam int i; 167188971Ssam 168188971Ssam /* Read Radio Chip Rev Extract */ 169188971Ssam OS_REG_WRITE(ah, AR_PHY(0x36), 0x00007058); 170188971Ssam for (i = 0; i < 8; i++) 171188971Ssam OS_REG_WRITE(ah, AR_PHY(0x20), 0x00010000); 172188971Ssam val = (OS_REG_READ(ah, AR_PHY(256)) >> 24) & 0xff; 173188971Ssam val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4); 174188971Ssam return ath_hal_reverseBits(val, 8); 175188971Ssam} 176188971Ssam 177185377Ssam/* 178185377Ssam * Attach for an AR5416 part. 179185377Ssam */ 180188972Ssamstatic struct ath_hal * 181185377Ssamar5416Attach(uint16_t devid, HAL_SOFTC sc, 182185377Ssam HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *status) 183185377Ssam{ 184185377Ssam struct ath_hal_5416 *ahp5416; 185185377Ssam struct ath_hal_5212 *ahp; 186185377Ssam struct ath_hal *ah; 187185377Ssam uint32_t val; 188185377Ssam HAL_STATUS ecode; 189185377Ssam HAL_BOOL rfStatus; 190185377Ssam 191185377Ssam HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n", 192185377Ssam __func__, sc, (void*) st, (void*) sh); 193185377Ssam 194185377Ssam /* NB: memory is returned zero'd */ 195185377Ssam ahp5416 = ath_hal_malloc(sizeof (struct ath_hal_5416) + 196185377Ssam /* extra space for Owl 2.1/2.2 WAR */ 197185377Ssam sizeof(ar5416Addac) 198185377Ssam ); 199185377Ssam if (ahp5416 == AH_NULL) { 200185377Ssam HALDEBUG(AH_NULL, HAL_DEBUG_ANY, 201185377Ssam "%s: cannot allocate memory for state block\n", __func__); 202185377Ssam *status = HAL_ENOMEM; 203185377Ssam return AH_NULL; 204185377Ssam } 205185377Ssam ar5416InitState(ahp5416, devid, sc, st, sh, status); 206185377Ssam ahp = &ahp5416->ah_5212; 207185377Ssam ah = &ahp->ah_priv.h; 208185377Ssam 209185377Ssam if (!ar5416SetResetReg(ah, HAL_RESET_POWER_ON)) { 210185377Ssam /* reset chip */ 211185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't reset chip\n", __func__); 212185377Ssam ecode = HAL_EIO; 213185377Ssam goto bad; 214185377Ssam } 215185377Ssam 216185377Ssam if (!ar5416SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) { 217185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't wakeup chip\n", __func__); 218185377Ssam ecode = HAL_EIO; 219185377Ssam goto bad; 220185377Ssam } 221185377Ssam /* Read Revisions from Chips before taking out of reset */ 222185377Ssam val = OS_REG_READ(ah, AR_SREV) & AR_SREV_ID; 223185377Ssam AH_PRIVATE(ah)->ah_macVersion = val >> AR_SREV_ID_S; 224185377Ssam AH_PRIVATE(ah)->ah_macRev = val & AR_SREV_REVISION; 225188979Ssam AH_PRIVATE(ah)->ah_ispcie = (devid == AR5416_DEVID_PCIE); 226185377Ssam 227185377Ssam /* setup common ini data; rf backends handle remainder */ 228185377Ssam HAL_INI_INIT(&ahp->ah_ini_modes, ar5416Modes, 6); 229185377Ssam HAL_INI_INIT(&ahp->ah_ini_common, ar5416Common, 2); 230185377Ssam 231185377Ssam HAL_INI_INIT(&AH5416(ah)->ah_ini_bb_rfgain, ar5416BB_RfGain, 3); 232185377Ssam HAL_INI_INIT(&AH5416(ah)->ah_ini_bank0, ar5416Bank0, 2); 233185377Ssam HAL_INI_INIT(&AH5416(ah)->ah_ini_bank1, ar5416Bank1, 2); 234185377Ssam HAL_INI_INIT(&AH5416(ah)->ah_ini_bank2, ar5416Bank2, 2); 235185377Ssam HAL_INI_INIT(&AH5416(ah)->ah_ini_bank3, ar5416Bank3, 3); 236185377Ssam HAL_INI_INIT(&AH5416(ah)->ah_ini_bank6, ar5416Bank6, 3); 237185377Ssam HAL_INI_INIT(&AH5416(ah)->ah_ini_bank7, ar5416Bank7, 2); 238185377Ssam HAL_INI_INIT(&AH5416(ah)->ah_ini_addac, ar5416Addac, 2); 239185377Ssam 240185377Ssam if (!IS_5416V2_2(ah)) { /* Owl 2.1/2.0 */ 241185377Ssam struct ini { 242185377Ssam uint32_t *data; /* NB: !const */ 243185377Ssam int rows, cols; 244185377Ssam }; 245185377Ssam /* override CLKDRV value */ 246185377Ssam OS_MEMCPY(&AH5416(ah)[1], ar5416Addac, sizeof(ar5416Addac)); 247185377Ssam AH5416(ah)->ah_ini_addac.data = (uint32_t *) &AH5416(ah)[1]; 248185377Ssam HAL_INI_VAL((struct ini *)&AH5416(ah)->ah_ini_addac, 31, 1) = 0; 249185377Ssam } 250185377Ssam 251188979Ssam HAL_INI_INIT(&AH5416(ah)->ah_ini_pcieserdes, ar5416PciePhy, 2); 252188979Ssam ar5416AttachPCIE(ah); 253188979Ssam 254188973Ssam ecode = ath_hal_v14EepromAttach(ah); 255188973Ssam if (ecode != HAL_OK) 256188973Ssam goto bad; 257188973Ssam 258185377Ssam if (!ar5416ChipReset(ah, AH_NULL)) { /* reset chip */ 259185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", 260185377Ssam __func__); 261185377Ssam ecode = HAL_EIO; 262185377Ssam goto bad; 263185377Ssam } 264185377Ssam 265185377Ssam AH_PRIVATE(ah)->ah_phyRev = OS_REG_READ(ah, AR_PHY_CHIP_ID); 266185377Ssam 267185377Ssam if (!ar5212ChipTest(ah)) { 268185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, "%s: hardware self-test failed\n", 269185377Ssam __func__); 270185377Ssam ecode = HAL_ESELFTEST; 271185377Ssam goto bad; 272185377Ssam } 273185377Ssam 274185377Ssam /* 275185377Ssam * Set correct Baseband to analog shift 276185377Ssam * setting to access analog chips. 277185377Ssam */ 278185377Ssam OS_REG_WRITE(ah, AR_PHY(0), 0x00000007); 279185377Ssam 280185377Ssam /* Read Radio Chip Rev Extract */ 281185377Ssam AH_PRIVATE(ah)->ah_analog5GhzRev = ar5212GetRadioRev(ah); 282185377Ssam switch (AH_PRIVATE(ah)->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR) { 283185377Ssam case AR_RAD5122_SREV_MAJOR: /* Fowl: 5G/2x2 */ 284185377Ssam case AR_RAD2122_SREV_MAJOR: /* Fowl: 2+5G/2x2 */ 285185377Ssam case AR_RAD2133_SREV_MAJOR: /* Fowl: 2G/3x3 */ 286185377Ssam case AR_RAD5133_SREV_MAJOR: /* Fowl: 2+5G/3x3 */ 287185377Ssam break; 288185377Ssam default: 289185377Ssam if (AH_PRIVATE(ah)->ah_analog5GhzRev == 0) { 290185377Ssam /* 291185377Ssam * When RF_Silen is used the analog chip is reset. 292185377Ssam * So when the system boots with radio switch off 293185377Ssam * the RF chip rev reads back as zero and we need 294185377Ssam * to use the mac+phy revs to set the radio rev. 295185377Ssam */ 296185377Ssam AH_PRIVATE(ah)->ah_analog5GhzRev = 297185377Ssam AR_RAD5133_SREV_MAJOR; 298185377Ssam break; 299185377Ssam } 300185377Ssam /* NB: silently accept anything in release code per Atheros */ 301185377Ssam#ifdef AH_DEBUG 302185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, 303185377Ssam "%s: 5G Radio Chip Rev 0x%02X is not supported by " 304185377Ssam "this driver\n", __func__, 305185377Ssam AH_PRIVATE(ah)->ah_analog5GhzRev); 306185377Ssam ecode = HAL_ENOTSUPP; 307185377Ssam goto bad; 308185377Ssam#endif 309185377Ssam } 310185377Ssam 311185377Ssam /* 312185377Ssam * Got everything we need now to setup the capabilities. 313185377Ssam */ 314185377Ssam if (!ar5416FillCapabilityInfo(ah)) { 315185377Ssam ecode = HAL_EEREAD; 316185377Ssam goto bad; 317185377Ssam } 318185377Ssam 319185377Ssam ecode = ath_hal_eepromGet(ah, AR_EEP_MACADDR, ahp->ah_macaddr); 320185377Ssam if (ecode != HAL_OK) { 321185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, 322185377Ssam "%s: error getting mac address from EEPROM\n", __func__); 323185377Ssam goto bad; 324185377Ssam } 325185377Ssam /* XXX How about the serial number ? */ 326185377Ssam /* Read Reg Domain */ 327185377Ssam AH_PRIVATE(ah)->ah_currentRD = 328185377Ssam ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, AH_NULL); 329185377Ssam 330185377Ssam /* 331185377Ssam * ah_miscMode is populated by ar5416FillCapabilityInfo() 332185377Ssam * starting from griffin. Set here to make sure that 333185377Ssam * AR_MISC_MODE_MIC_NEW_LOC_ENABLE is set before a GTK is 334185380Ssam * placed into hardware. 335185377Ssam */ 336185377Ssam if (ahp->ah_miscMode != 0) 337185377Ssam OS_REG_WRITE(ah, AR_MISC_MODE, ahp->ah_miscMode); 338185377Ssam 339185377Ssam HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: Attaching AR2133 radio\n", 340185377Ssam __func__); 341185377Ssam rfStatus = ar2133RfAttach(ah, &ecode); 342185377Ssam if (!rfStatus) { 343185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RF setup failed, status %u\n", 344185377Ssam __func__, ecode); 345185377Ssam goto bad; 346185377Ssam } 347185377Ssam 348185377Ssam ar5416AniSetup(ah); /* Anti Noise Immunity */ 349185380Ssam ar5416InitNfHistBuff(AH5416(ah)->ah_cal.nfCalHist); 350185377Ssam 351185377Ssam HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n", __func__); 352185377Ssam 353185377Ssam return ah; 354185377Ssambad: 355185377Ssam if (ahp) 356185377Ssam ar5416Detach((struct ath_hal *) ahp); 357185377Ssam if (status) 358185377Ssam *status = ecode; 359185377Ssam return AH_NULL; 360185377Ssam} 361185377Ssam 362185377Ssamvoid 363185377Ssamar5416Detach(struct ath_hal *ah) 364185377Ssam{ 365185377Ssam HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s:\n", __func__); 366185377Ssam 367185377Ssam HALASSERT(ah != AH_NULL); 368185377Ssam HALASSERT(ah->ah_magic == AR5416_MAGIC); 369185377Ssam 370185380Ssam ar5416AniDetach(ah); 371185377Ssam ar5212RfDetach(ah); 372185377Ssam ah->ah_disable(ah); 373185377Ssam ar5416SetPowerMode(ah, HAL_PM_FULL_SLEEP, AH_TRUE); 374185377Ssam ath_hal_eepromDetach(ah); 375185377Ssam ath_hal_free(ah); 376185377Ssam} 377185377Ssam 378188979Ssamvoid 379188979Ssamar5416AttachPCIE(struct ath_hal *ah) 380188979Ssam{ 381188979Ssam if (AH_PRIVATE(ah)->ah_ispcie) 382188979Ssam ath_hal_configPCIE(ah, AH_FALSE); 383188979Ssam else 384188979Ssam ath_hal_disablePCIE(ah); 385188979Ssam} 386188979Ssam 387188979Ssamstatic void 388188979Ssamar5416ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore) 389188979Ssam{ 390188979Ssam if (AH_PRIVATE(ah)->ah_ispcie && !restore) { 391188979Ssam ath_hal_ini_write(ah, &AH5416(ah)->ah_ini_pcieserdes, 1, 0); 392188979Ssam OS_DELAY(1000); 393188979Ssam OS_REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA); 394188979Ssam OS_REG_WRITE(ah, AR_WA, AR_WA_DEFAULT); 395188979Ssam } 396188979Ssam} 397188979Ssam 398185377Ssam/* 399185377Ssam * Fill all software cached or static hardware state information. 400185377Ssam * Return failure if capabilities are to come from EEPROM and 401185377Ssam * cannot be read. 402185377Ssam */ 403185377SsamHAL_BOOL 404185377Ssamar5416FillCapabilityInfo(struct ath_hal *ah) 405185377Ssam{ 406185377Ssam struct ath_hal_private *ahpriv = AH_PRIVATE(ah); 407185377Ssam HAL_CAPABILITIES *pCap = &ahpriv->ah_caps; 408185377Ssam uint16_t val; 409185377Ssam 410185377Ssam /* Construct wireless mode from EEPROM */ 411185377Ssam pCap->halWirelessModes = 0; 412185377Ssam if (ath_hal_eepromGetFlag(ah, AR_EEP_AMODE)) { 413185377Ssam pCap->halWirelessModes |= HAL_MODE_11A 414185377Ssam | HAL_MODE_11NA_HT20 415185377Ssam | HAL_MODE_11NA_HT40PLUS 416185377Ssam | HAL_MODE_11NA_HT40MINUS 417185377Ssam ; 418185377Ssam } 419185377Ssam if (ath_hal_eepromGetFlag(ah, AR_EEP_GMODE)) { 420185377Ssam pCap->halWirelessModes |= HAL_MODE_11G 421185377Ssam | HAL_MODE_11NG_HT20 422185377Ssam | HAL_MODE_11NG_HT40PLUS 423185377Ssam | HAL_MODE_11NG_HT40MINUS 424185377Ssam ; 425185377Ssam pCap->halWirelessModes |= HAL_MODE_11A 426185377Ssam | HAL_MODE_11NA_HT20 427185377Ssam | HAL_MODE_11NA_HT40PLUS 428185377Ssam | HAL_MODE_11NA_HT40MINUS 429185377Ssam ; 430185377Ssam } 431185377Ssam 432185377Ssam pCap->halLow2GhzChan = 2312; 433185377Ssam pCap->halHigh2GhzChan = 2732; 434185377Ssam 435185377Ssam pCap->halLow5GhzChan = 4915; 436185377Ssam pCap->halHigh5GhzChan = 6100; 437185377Ssam 438185377Ssam pCap->halCipherCkipSupport = AH_FALSE; 439185377Ssam pCap->halCipherTkipSupport = AH_TRUE; 440185377Ssam pCap->halCipherAesCcmSupport = ath_hal_eepromGetFlag(ah, AR_EEP_AES); 441185377Ssam 442185377Ssam pCap->halMicCkipSupport = AH_FALSE; 443185377Ssam pCap->halMicTkipSupport = AH_TRUE; 444185377Ssam pCap->halMicAesCcmSupport = ath_hal_eepromGetFlag(ah, AR_EEP_AES); 445185377Ssam /* 446185377Ssam * Starting with Griffin TX+RX mic keys can be combined 447185377Ssam * in one key cache slot. 448185377Ssam */ 449185377Ssam pCap->halTkipMicTxRxKeySupport = AH_TRUE; 450185377Ssam pCap->halChanSpreadSupport = AH_TRUE; 451185377Ssam pCap->halSleepAfterBeaconBroken = AH_TRUE; 452185377Ssam 453185377Ssam pCap->halCompressSupport = AH_FALSE; 454185377Ssam pCap->halBurstSupport = AH_TRUE; 455185377Ssam pCap->halFastFramesSupport = AH_FALSE; /* XXX? */ 456185377Ssam pCap->halChapTuningSupport = AH_TRUE; 457185377Ssam pCap->halTurboPrimeSupport = AH_TRUE; 458185377Ssam 459185377Ssam pCap->halTurboGSupport = pCap->halWirelessModes & HAL_MODE_108G; 460185377Ssam 461185377Ssam pCap->halPSPollBroken = AH_TRUE; /* XXX fixed in later revs? */ 462185377Ssam pCap->halVEOLSupport = AH_TRUE; 463185377Ssam pCap->halBssIdMaskSupport = AH_TRUE; 464185377Ssam pCap->halMcastKeySrchSupport = AH_FALSE; 465185377Ssam pCap->halTsfAddSupport = AH_TRUE; 466185377Ssam 467185377Ssam if (ath_hal_eepromGet(ah, AR_EEP_MAXQCU, &val) == HAL_OK) 468185377Ssam pCap->halTotalQueues = val; 469185377Ssam else 470185377Ssam pCap->halTotalQueues = HAL_NUM_TX_QUEUES; 471185377Ssam 472185377Ssam if (ath_hal_eepromGet(ah, AR_EEP_KCENTRIES, &val) == HAL_OK) 473185377Ssam pCap->halKeyCacheSize = val; 474185377Ssam else 475185377Ssam pCap->halKeyCacheSize = AR5416_KEYTABLE_SIZE; 476185377Ssam 477185377Ssam /* XXX not needed */ 478185377Ssam pCap->halChanHalfRate = AH_FALSE; /* XXX ? */ 479185377Ssam pCap->halChanQuarterRate = AH_FALSE; /* XXX ? */ 480185377Ssam 481185377Ssam pCap->halTstampPrecision = 32; 482185377Ssam pCap->halHwPhyCounterSupport = AH_TRUE; 483185377Ssam 484185377Ssam pCap->halFastCCSupport = AH_TRUE; 485185377Ssam pCap->halNumGpioPins = 6; 486185377Ssam pCap->halWowSupport = AH_FALSE; 487185377Ssam pCap->halWowMatchPatternExact = AH_FALSE; 488185377Ssam pCap->halBtCoexSupport = AH_FALSE; /* XXX need support */ 489185377Ssam pCap->halAutoSleepSupport = AH_FALSE; 490185377Ssam#if 0 /* XXX not yet */ 491185377Ssam pCap->halNumAntCfg2GHz = ar5416GetNumAntConfig(ahp, HAL_FREQ_BAND_2GHZ); 492185377Ssam pCap->halNumAntCfg5GHz = ar5416GetNumAntConfig(ahp, HAL_FREQ_BAND_5GHZ); 493185377Ssam#endif 494185377Ssam pCap->halHTSupport = AH_TRUE; 495185377Ssam pCap->halTxChainMask = ath_hal_eepromGet(ah, AR_EEP_TXMASK, AH_NULL); 496185377Ssam /* XXX CB71 uses GPIO 0 to indicate 3 rx chains */ 497185377Ssam pCap->halRxChainMask = ath_hal_eepromGet(ah, AR_EEP_RXMASK, AH_NULL); 498185377Ssam pCap->halRtsAggrLimit = 8*1024; /* Owl 2.0 limit */ 499185377Ssam pCap->halMbssidAggrSupport = AH_TRUE; 500185377Ssam pCap->halForcePpmSupport = AH_TRUE; 501185377Ssam pCap->halEnhancedPmSupport = AH_TRUE; 502185377Ssam 503185377Ssam if (ath_hal_eepromGetFlag(ah, AR_EEP_RFKILL) && 504185377Ssam ath_hal_eepromGet(ah, AR_EEP_RFSILENT, &ahpriv->ah_rfsilent) == HAL_OK) { 505185377Ssam /* NB: enabled by default */ 506185377Ssam ahpriv->ah_rfkillEnabled = AH_TRUE; 507185377Ssam pCap->halRfSilentSupport = AH_TRUE; 508185377Ssam } 509185377Ssam 510185377Ssam ahpriv->ah_rxornIsFatal = AH_FALSE; 511185377Ssam 512185377Ssam return AH_TRUE; 513185377Ssam} 514185406Ssam 515185406Ssamstatic const char* 516185406Ssamar5416Probe(uint16_t vendorid, uint16_t devid) 517185406Ssam{ 518185406Ssam if (vendorid == ATHEROS_VENDOR_ID && 519185406Ssam (devid == AR5416_DEVID_PCI || devid == AR5416_DEVID_PCIE)) 520185406Ssam return "Atheros 5416"; 521185406Ssam return AH_NULL; 522185406Ssam} 523185418SsamAH_CHIP(AR5416, ar5416Probe, ar5416Attach); 524