Path: blob/main/sys/dev/ath/ath_hal/ar5212/ar5212_attach.c
39566 views
/*-1* SPDX-License-Identifier: ISC2*3* Copyright (c) 2002-2009 Sam Leffler, Errno Consulting4* Copyright (c) 2002-2008 Atheros Communications, Inc.5*6* Permission to use, copy, modify, and/or distribute this software for any7* purpose with or without fee is hereby granted, provided that the above8* copyright notice and this permission notice appear in all copies.9*10* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES11* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF12* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR13* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES14* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN15* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF16* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.17*/18#include "opt_ah.h"1920#include "ah.h"21#include "ah_internal.h"22#include "ah_devid.h"2324#include "ar5212/ar5212.h"25#include "ar5212/ar5212reg.h"26#include "ar5212/ar5212phy.h"2728#define AH_5212_COMMON29#include "ar5212/ar5212.ini"3031static void ar5212ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore,32HAL_BOOL power_off);33static void ar5212DisablePCIE(struct ath_hal *ah);3435static const struct ath_hal_private ar5212hal = {{36.ah_magic = AR5212_MAGIC,3738.ah_getRateTable = ar5212GetRateTable,39.ah_detach = ar5212Detach,4041/* Reset Functions */42.ah_reset = ar5212Reset,43.ah_phyDisable = ar5212PhyDisable,44.ah_disable = ar5212Disable,45.ah_configPCIE = ar5212ConfigPCIE,46.ah_disablePCIE = ar5212DisablePCIE,47.ah_setPCUConfig = ar5212SetPCUConfig,48.ah_perCalibration = ar5212PerCalibration,49.ah_perCalibrationN = ar5212PerCalibrationN,50.ah_resetCalValid = ar5212ResetCalValid,51.ah_setTxPowerLimit = ar5212SetTxPowerLimit,52.ah_getChanNoise = ath_hal_getChanNoise,5354/* Transmit functions */55.ah_updateTxTrigLevel = ar5212UpdateTxTrigLevel,56.ah_setupTxQueue = ar5212SetupTxQueue,57.ah_setTxQueueProps = ar5212SetTxQueueProps,58.ah_getTxQueueProps = ar5212GetTxQueueProps,59.ah_releaseTxQueue = ar5212ReleaseTxQueue,60.ah_resetTxQueue = ar5212ResetTxQueue,61.ah_getTxDP = ar5212GetTxDP,62.ah_setTxDP = ar5212SetTxDP,63.ah_numTxPending = ar5212NumTxPending,64.ah_startTxDma = ar5212StartTxDma,65.ah_stopTxDma = ar5212StopTxDma,66.ah_setupTxDesc = ar5212SetupTxDesc,67.ah_setupXTxDesc = ar5212SetupXTxDesc,68.ah_fillTxDesc = ar5212FillTxDesc,69.ah_procTxDesc = ar5212ProcTxDesc,70.ah_getTxIntrQueue = ar5212GetTxIntrQueue,71.ah_reqTxIntrDesc = ar5212IntrReqTxDesc,72.ah_getTxCompletionRates = ar5212GetTxCompletionRates,73.ah_setTxDescLink = ar5212SetTxDescLink,74.ah_getTxDescLink = ar5212GetTxDescLink,75.ah_getTxDescLinkPtr = ar5212GetTxDescLinkPtr,7677/* RX Functions */78.ah_getRxDP = ar5212GetRxDP,79.ah_setRxDP = ar5212SetRxDP,80.ah_enableReceive = ar5212EnableReceive,81.ah_stopDmaReceive = ar5212StopDmaReceive,82.ah_startPcuReceive = ar5212StartPcuReceive,83.ah_stopPcuReceive = ar5212StopPcuReceive,84.ah_setMulticastFilter = ar5212SetMulticastFilter,85.ah_setMulticastFilterIndex = ar5212SetMulticastFilterIndex,86.ah_clrMulticastFilterIndex = ar5212ClrMulticastFilterIndex,87.ah_getRxFilter = ar5212GetRxFilter,88.ah_setRxFilter = ar5212SetRxFilter,89.ah_setupRxDesc = ar5212SetupRxDesc,90.ah_procRxDesc = ar5212ProcRxDesc,91.ah_rxMonitor = ar5212RxMonitor,92.ah_aniPoll = ar5212AniPoll,93.ah_procMibEvent = ar5212ProcessMibIntr,9495/* Misc Functions */96.ah_getCapability = ar5212GetCapability,97.ah_setCapability = ar5212SetCapability,98.ah_getDiagState = ar5212GetDiagState,99.ah_getMacAddress = ar5212GetMacAddress,100.ah_setMacAddress = ar5212SetMacAddress,101.ah_getBssIdMask = ar5212GetBssIdMask,102.ah_setBssIdMask = ar5212SetBssIdMask,103.ah_setRegulatoryDomain = ar5212SetRegulatoryDomain,104.ah_setLedState = ar5212SetLedState,105.ah_writeAssocid = ar5212WriteAssocid,106.ah_gpioCfgInput = ar5212GpioCfgInput,107.ah_gpioCfgOutput = ar5212GpioCfgOutput,108.ah_gpioGet = ar5212GpioGet,109.ah_gpioSet = ar5212GpioSet,110.ah_gpioSetIntr = ar5212GpioSetIntr,111.ah_getTsf32 = ar5212GetTsf32,112.ah_getTsf64 = ar5212GetTsf64,113.ah_setTsf64 = ar5212SetTsf64,114.ah_resetTsf = ar5212ResetTsf,115.ah_detectCardPresent = ar5212DetectCardPresent,116.ah_updateMibCounters = ar5212UpdateMibCounters,117.ah_getRfGain = ar5212GetRfgain,118.ah_getDefAntenna = ar5212GetDefAntenna,119.ah_setDefAntenna = ar5212SetDefAntenna,120.ah_getAntennaSwitch = ar5212GetAntennaSwitch,121.ah_setAntennaSwitch = ar5212SetAntennaSwitch,122.ah_setSifsTime = ar5212SetSifsTime,123.ah_getSifsTime = ar5212GetSifsTime,124.ah_setSlotTime = ar5212SetSlotTime,125.ah_getSlotTime = ar5212GetSlotTime,126.ah_setAckTimeout = ar5212SetAckTimeout,127.ah_getAckTimeout = ar5212GetAckTimeout,128.ah_setAckCTSRate = ar5212SetAckCTSRate,129.ah_getAckCTSRate = ar5212GetAckCTSRate,130.ah_setCTSTimeout = ar5212SetCTSTimeout,131.ah_getCTSTimeout = ar5212GetCTSTimeout,132.ah_setDecompMask = ar5212SetDecompMask,133.ah_setCoverageClass = ar5212SetCoverageClass,134.ah_setQuiet = ar5212SetQuiet,135.ah_getMibCycleCounts = ar5212GetMibCycleCounts,136.ah_setChainMasks = ar5212SetChainMasks,137.ah_getNav = ar5212GetNav,138.ah_setNav = ar5212SetNav,139140/* DFS Functions */141.ah_enableDfs = ar5212EnableDfs,142.ah_getDfsThresh = ar5212GetDfsThresh,143.ah_getDfsDefaultThresh = ar5212GetDfsDefaultThresh,144.ah_procRadarEvent = ar5212ProcessRadarEvent,145.ah_isFastClockEnabled = ar5212IsFastClockEnabled,146.ah_get11nExtBusy = ar5212Get11nExtBusy,147148/* Key Cache Functions */149.ah_getKeyCacheSize = ar5212GetKeyCacheSize,150.ah_resetKeyCacheEntry = ar5212ResetKeyCacheEntry,151.ah_isKeyCacheEntryValid = ar5212IsKeyCacheEntryValid,152.ah_setKeyCacheEntry = ar5212SetKeyCacheEntry,153.ah_setKeyCacheEntryMac = ar5212SetKeyCacheEntryMac,154155/* Power Management Functions */156.ah_setPowerMode = ar5212SetPowerMode,157.ah_getPowerMode = ar5212GetPowerMode,158159/* Beacon Functions */160.ah_setBeaconTimers = ar5212SetBeaconTimers,161.ah_beaconInit = ar5212BeaconInit,162.ah_setStationBeaconTimers = ar5212SetStaBeaconTimers,163.ah_resetStationBeaconTimers = ar5212ResetStaBeaconTimers,164.ah_getNextTBTT = ar5212GetNextTBTT,165166/* Interrupt Functions */167.ah_isInterruptPending = ar5212IsInterruptPending,168.ah_getPendingInterrupts = ar5212GetPendingInterrupts,169.ah_getInterrupts = ar5212GetInterrupts,170.ah_setInterrupts = ar5212SetInterrupts },171172.ah_getChannelEdges = ar5212GetChannelEdges,173.ah_getWirelessModes = ar5212GetWirelessModes,174.ah_eepromRead = ar5212EepromRead,175#ifdef AH_SUPPORT_WRITE_EEPROM176.ah_eepromWrite = ar5212EepromWrite,177#endif178.ah_getChipPowerLimits = ar5212GetChipPowerLimits,179};180181uint32_t182ar5212GetRadioRev(struct ath_hal *ah)183{184uint32_t val;185int i;186187/* Read Radio Chip Rev Extract */188OS_REG_WRITE(ah, AR_PHY(0x34), 0x00001c16);189for (i = 0; i < 8; i++)190OS_REG_WRITE(ah, AR_PHY(0x20), 0x00010000);191val = (OS_REG_READ(ah, AR_PHY(256)) >> 24) & 0xff;192val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4);193return ath_hal_reverseBits(val, 8);194}195196static void197ar5212AniSetup(struct ath_hal *ah)198{199static const struct ar5212AniParams aniparams = {200.maxNoiseImmunityLevel = 4, /* levels 0..4 */201.totalSizeDesired = { -55, -55, -55, -55, -62 },202.coarseHigh = { -14, -14, -14, -14, -12 },203.coarseLow = { -64, -64, -64, -64, -70 },204.firpwr = { -78, -78, -78, -78, -80 },205.maxSpurImmunityLevel = 2, /* NB: depends on chip rev */206.cycPwrThr1 = { 2, 4, 6, 8, 10, 12, 14, 16 },207.maxFirstepLevel = 2, /* levels 0..2 */208.firstep = { 0, 4, 8 },209.ofdmTrigHigh = 500,210.ofdmTrigLow = 200,211.cckTrigHigh = 200,212.cckTrigLow = 100,213.rssiThrHigh = 40,214.rssiThrLow = 7,215.period = 100,216};217if (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_GRIFFIN) {218struct ar5212AniParams tmp;219OS_MEMCPY(&tmp, &aniparams, sizeof(struct ar5212AniParams));220tmp.maxSpurImmunityLevel = 7; /* Venice and earlier */221ar5212AniAttach(ah, &tmp, &tmp, AH_TRUE);222} else223ar5212AniAttach(ah, &aniparams, &aniparams, AH_TRUE);224225/* Set overridable ANI methods */226AH5212(ah)->ah_aniControl = ar5212AniControl;227}228229/*230* Attach for an AR5212 part.231*/232void233ar5212InitState(struct ath_hal_5212 *ahp, uint16_t devid, HAL_SOFTC sc,234HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *status)235{236#define N(a) (sizeof(a)/sizeof(a[0]))237static const uint8_t defbssidmask[IEEE80211_ADDR_LEN] =238{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };239struct ath_hal *ah;240241ah = &ahp->ah_priv.h;242/* set initial values */243OS_MEMCPY(&ahp->ah_priv, &ar5212hal, sizeof(struct ath_hal_private));244ah->ah_sc = sc;245ah->ah_st = st;246ah->ah_sh = sh;247248ah->ah_devid = devid; /* NB: for alq */249AH_PRIVATE(ah)->ah_devid = devid;250AH_PRIVATE(ah)->ah_subvendorid = 0; /* XXX */251252AH_PRIVATE(ah)->ah_powerLimit = MAX_RATE_POWER;253AH_PRIVATE(ah)->ah_tpScale = HAL_TP_SCALE_MAX; /* no scaling */254255ahp->ah_antControl = HAL_ANT_VARIABLE;256ahp->ah_diversity = AH_TRUE;257ahp->ah_bIQCalibration = AH_FALSE;258/*259* Enable MIC handling.260*/261ahp->ah_staId1Defaults = AR_STA_ID1_CRPT_MIC_ENABLE;262ahp->ah_rssiThr = INIT_RSSI_THR;263ahp->ah_tpcEnabled = AH_FALSE; /* disabled by default */264ahp->ah_phyPowerOn = AH_FALSE;265ahp->ah_macTPC = SM(MAX_RATE_POWER, AR_TPC_ACK)266| SM(MAX_RATE_POWER, AR_TPC_CTS)267| SM(MAX_RATE_POWER, AR_TPC_CHIRP);268ahp->ah_beaconInterval = 100; /* XXX [20..1000] */269ahp->ah_enable32kHzClock = DONT_USE_32KHZ;/* XXX */270ahp->ah_slottime = (u_int) -1;271ahp->ah_acktimeout = (u_int) -1;272ahp->ah_ctstimeout = (u_int) -1;273ahp->ah_sifstime = (u_int) -1;274ahp->ah_txTrigLev = INIT_TX_FIFO_THRESHOLD;275ahp->ah_maxTxTrigLev = MAX_TX_FIFO_THRESHOLD;276277OS_MEMCPY(&ahp->ah_bssidmask, defbssidmask, IEEE80211_ADDR_LEN);278#undef N279}280281/*282* Validate MAC version and revision.283*/284static HAL_BOOL285ar5212IsMacSupported(uint8_t macVersion, uint8_t macRev)286{287#define N(a) (sizeof(a)/sizeof(a[0]))288static const struct {289uint8_t version;290uint8_t revMin, revMax;291} macs[] = {292{ AR_SREV_VERSION_VENICE,293AR_SREV_D2PLUS, AR_SREV_REVISION_MAX },294{ AR_SREV_VERSION_GRIFFIN,295AR_SREV_D2PLUS, AR_SREV_REVISION_MAX },296{ AR_SREV_5413,297AR_SREV_REVISION_MIN, AR_SREV_REVISION_MAX },298{ AR_SREV_5424,299AR_SREV_REVISION_MIN, AR_SREV_REVISION_MAX },300{ AR_SREV_2425,301AR_SREV_REVISION_MIN, AR_SREV_REVISION_MAX },302{ AR_SREV_2417,303AR_SREV_REVISION_MIN, AR_SREV_REVISION_MAX },304};305int i;306307for (i = 0; i < N(macs); i++)308if (macs[i].version == macVersion &&309macs[i].revMin <= macRev && macRev <= macs[i].revMax)310return AH_TRUE;311return AH_FALSE;312#undef N313}314315/*316* Attach for an AR5212 part.317*/318static struct ath_hal *319ar5212Attach(uint16_t devid, HAL_SOFTC sc,320HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata,321HAL_OPS_CONFIG *ah_config, HAL_STATUS *status)322{323#define AH_EEPROM_PROTECT(ah) \324(AH_PRIVATE(ah)->ah_ispcie)? AR_EEPROM_PROTECT_PCIE : AR_EEPROM_PROTECT)325struct ath_hal_5212 *ahp;326struct ath_hal *ah;327struct ath_hal_rf *rf;328uint32_t val;329uint16_t eeval;330HAL_STATUS ecode;331332HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n",333__func__, sc, (void*) st, (void*) sh);334335/* NB: memory is returned zero'd */336ahp = ath_hal_malloc(sizeof (struct ath_hal_5212));337if (ahp == AH_NULL) {338HALDEBUG(AH_NULL, HAL_DEBUG_ANY,339"%s: cannot allocate memory for state block\n", __func__);340*status = HAL_ENOMEM;341return AH_NULL;342}343ar5212InitState(ahp, devid, sc, st, sh, status);344ah = &ahp->ah_priv.h;345346if (!ar5212SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) {347HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't wakeup chip\n",348__func__);349ecode = HAL_EIO;350goto bad;351}352/* Read Revisions from Chips before taking out of reset */353val = OS_REG_READ(ah, AR_SREV) & AR_SREV_ID;354AH_PRIVATE(ah)->ah_macVersion = val >> AR_SREV_ID_S;355AH_PRIVATE(ah)->ah_macRev = val & AR_SREV_REVISION;356AH_PRIVATE(ah)->ah_ispcie = IS_5424(ah) || IS_2425(ah);357358if (!ar5212IsMacSupported(AH_PRIVATE(ah)->ah_macVersion, AH_PRIVATE(ah)->ah_macRev)) {359HALDEBUG(ah, HAL_DEBUG_ANY,360"%s: Mac Chip Rev 0x%02x.%x not supported\n" ,361__func__, AH_PRIVATE(ah)->ah_macVersion,362AH_PRIVATE(ah)->ah_macRev);363ecode = HAL_ENOTSUPP;364goto bad;365}366367/* setup common ini data; rf backends handle remainder */368HAL_INI_INIT(&ahp->ah_ini_modes, ar5212Modes, 6);369HAL_INI_INIT(&ahp->ah_ini_common, ar5212Common, 2);370371if (!ar5212ChipReset(ah, AH_NULL)) { /* reset chip */372HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__);373ecode = HAL_EIO;374goto bad;375}376377AH_PRIVATE(ah)->ah_phyRev = OS_REG_READ(ah, AR_PHY_CHIP_ID);378379if (AH_PRIVATE(ah)->ah_ispcie) {380/* XXX: build flag to disable this? */381ath_hal_configPCIE(ah, AH_FALSE, AH_FALSE);382}383384if (!ar5212ChipTest(ah)) {385HALDEBUG(ah, HAL_DEBUG_ANY, "%s: hardware self-test failed\n",386__func__);387ecode = HAL_ESELFTEST;388goto bad;389}390391/* Enable PCI core retry fix in software for Hainan and up */392if (AH_PRIVATE(ah)->ah_macVersion >= AR_SREV_VERSION_VENICE)393OS_REG_SET_BIT(ah, AR_PCICFG, AR_PCICFG_RETRYFIXEN);394395/*396* Set correct Baseband to analog shift397* setting to access analog chips.398*/399OS_REG_WRITE(ah, AR_PHY(0), 0x00000007);400401/* Read Radio Chip Rev Extract */402AH_PRIVATE(ah)->ah_analog5GhzRev = ar5212GetRadioRev(ah);403404rf = ath_hal_rfprobe(ah, &ecode);405if (rf == AH_NULL)406goto bad;407408/* NB: silently accept anything in release code per Atheros */409switch (AH_PRIVATE(ah)->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR) {410case AR_RAD5111_SREV_MAJOR:411case AR_RAD5112_SREV_MAJOR:412case AR_RAD2112_SREV_MAJOR:413case AR_RAD2111_SREV_MAJOR:414case AR_RAD2413_SREV_MAJOR:415case AR_RAD5413_SREV_MAJOR:416case AR_RAD5424_SREV_MAJOR:417break;418default:419if (AH_PRIVATE(ah)->ah_analog5GhzRev == 0) {420/*421* When RF_Silent is used, the422* analog chip is reset. So when the system boots423* up with the radio switch off we cannot determine424* the RF chip rev. To workaround this check the425* mac+phy revs and if Hainan, set the radio rev426* to Derby.427*/428if (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_VENICE &&429AH_PRIVATE(ah)->ah_macRev == AR_SREV_HAINAN &&430AH_PRIVATE(ah)->ah_phyRev == AR_PHYREV_HAINAN) {431AH_PRIVATE(ah)->ah_analog5GhzRev = AR_ANALOG5REV_HAINAN;432break;433}434if (IS_2413(ah)) { /* Griffin */435AH_PRIVATE(ah)->ah_analog5GhzRev =436AR_RAD2413_SREV_MAJOR | 0x1;437break;438}439if (IS_5413(ah)) { /* Eagle */440AH_PRIVATE(ah)->ah_analog5GhzRev =441AR_RAD5413_SREV_MAJOR | 0x2;442break;443}444if (IS_2425(ah) || IS_2417(ah)) {/* Swan or Nala */445AH_PRIVATE(ah)->ah_analog5GhzRev =446AR_RAD5424_SREV_MAJOR | 0x2;447break;448}449}450#ifdef AH_DEBUG451HALDEBUG(ah, HAL_DEBUG_ANY,452"%s: 5G Radio Chip Rev 0x%02X is not supported by "453"this driver\n",454__func__, AH_PRIVATE(ah)->ah_analog5GhzRev);455ecode = HAL_ENOTSUPP;456goto bad;457#endif458}459if (IS_RAD5112_REV1(ah)) {460HALDEBUG(ah, HAL_DEBUG_ANY,461"%s: 5112 Rev 1 is not supported by this "462"driver (analog5GhzRev 0x%x)\n", __func__,463AH_PRIVATE(ah)->ah_analog5GhzRev);464ecode = HAL_ENOTSUPP;465goto bad;466}467468val = OS_REG_READ(ah, AR_PCICFG);469val = MS(val, AR_PCICFG_EEPROM_SIZE);470if (val == 0) {471if (!AH_PRIVATE(ah)->ah_ispcie) {472HALDEBUG(ah, HAL_DEBUG_ANY,473"%s: unsupported EEPROM size %u (0x%x) found\n",474__func__, val, val);475ecode = HAL_EESIZE;476goto bad;477}478/* XXX AH_PRIVATE(ah)->ah_isPciExpress = AH_TRUE; */479} else if (val != AR_PCICFG_EEPROM_SIZE_16K) {480if (AR_PCICFG_EEPROM_SIZE_FAILED == val) {481HALDEBUG(ah, HAL_DEBUG_ANY,482"%s: unsupported EEPROM size %u (0x%x) found\n",483__func__, val, val);484ecode = HAL_EESIZE;485goto bad;486}487HALDEBUG(ah, HAL_DEBUG_ANY,488"%s: EEPROM size = %d. Must be %d (16k).\n",489__func__, val, AR_PCICFG_EEPROM_SIZE_16K);490ecode = HAL_EESIZE;491goto bad;492}493ecode = ath_hal_legacyEepromAttach(ah);494if (ecode != HAL_OK) {495goto bad;496}497ahp->ah_isHb63 = IS_2425(ah) && ath_hal_eepromGetFlag(ah, AR_EEP_ISTALON);498499/*500* If Bmode and AR5212, verify 2.4 analog exists501*/502if (ath_hal_eepromGetFlag(ah, AR_EEP_BMODE) &&503(AH_PRIVATE(ah)->ah_analog5GhzRev & 0xF0) == AR_RAD5111_SREV_MAJOR) {504/*505* Set correct Baseband to analog shift506* setting to access analog chips.507*/508OS_REG_WRITE(ah, AR_PHY(0), 0x00004007);509OS_DELAY(2000);510AH_PRIVATE(ah)->ah_analog2GhzRev = ar5212GetRadioRev(ah);511512/* Set baseband for 5GHz chip */513OS_REG_WRITE(ah, AR_PHY(0), 0x00000007);514OS_DELAY(2000);515if ((AH_PRIVATE(ah)->ah_analog2GhzRev & 0xF0) != AR_RAD2111_SREV_MAJOR) {516HALDEBUG(ah, HAL_DEBUG_ANY,517"%s: 2G Radio Chip Rev 0x%02X is not "518"supported by this driver\n", __func__,519AH_PRIVATE(ah)->ah_analog2GhzRev);520ecode = HAL_ENOTSUPP;521goto bad;522}523}524525ecode = ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, &eeval);526if (ecode != HAL_OK) {527HALDEBUG(ah, HAL_DEBUG_ANY,528"%s: cannot read regulatory domain from EEPROM\n",529__func__);530goto bad;531}532AH_PRIVATE(ah)->ah_currentRD = eeval;533/* XXX record serial number */534535/*536* Got everything we need now to setup the capabilities.537*/538if (!ar5212FillCapabilityInfo(ah)) {539HALDEBUG(ah, HAL_DEBUG_ANY,540"%s: failed ar5212FillCapabilityInfo\n", __func__);541ecode = HAL_EEREAD;542goto bad;543}544545if (!rf->attach(ah, &ecode)) {546HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RF setup failed, status %u\n",547__func__, ecode);548goto bad;549}550/*551* Set noise floor adjust method; we arrange a552* direct call instead of thunking.553*/554AH_PRIVATE(ah)->ah_getNfAdjust = ahp->ah_rfHal->getNfAdjust;555556/* Initialize gain ladder thermal calibration structure */557ar5212InitializeGainValues(ah);558559ecode = ath_hal_eepromGet(ah, AR_EEP_MACADDR, ahp->ah_macaddr);560if (ecode != HAL_OK) {561HALDEBUG(ah, HAL_DEBUG_ANY,562"%s: error getting mac address from EEPROM\n", __func__);563goto bad;564}565566ar5212AniSetup(ah);567/* Setup of Radar/AR structures happens in ath_hal_initchannels*/568ar5212InitNfCalHistBuffer(ah);569570/* XXX EAR stuff goes here */571572HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n", __func__);573574return ah;575576bad:577if (ahp)578ar5212Detach((struct ath_hal *) ahp);579if (status)580*status = ecode;581return AH_NULL;582#undef AH_EEPROM_PROTECT583}584585void586ar5212Detach(struct ath_hal *ah)587{588HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s:\n", __func__);589590HALASSERT(ah != AH_NULL);591HALASSERT(ah->ah_magic == AR5212_MAGIC);592593ar5212AniDetach(ah);594ar5212RfDetach(ah);595ar5212Disable(ah);596ar5212SetPowerMode(ah, HAL_PM_FULL_SLEEP, AH_TRUE);597598ath_hal_eepromDetach(ah);599ath_hal_free(ah);600}601602HAL_BOOL603ar5212ChipTest(struct ath_hal *ah)604{605uint32_t regAddr[2] = { AR_STA_ID0, AR_PHY_BASE+(8 << 2) };606uint32_t regHold[2];607uint32_t patternData[4] =608{ 0x55555555, 0xaaaaaaaa, 0x66666666, 0x99999999 };609int i, j;610611/* Test PHY & MAC registers */612for (i = 0; i < 2; i++) {613uint32_t addr = regAddr[i];614uint32_t wrData, rdData;615616regHold[i] = OS_REG_READ(ah, addr);617for (j = 0; j < 0x100; j++) {618wrData = (j << 16) | j;619OS_REG_WRITE(ah, addr, wrData);620rdData = OS_REG_READ(ah, addr);621if (rdData != wrData) {622HALDEBUG(ah, HAL_DEBUG_ANY,623"%s: address test failed addr: 0x%08x - wr:0x%08x != rd:0x%08x\n",624__func__, addr, wrData, rdData);625return AH_FALSE;626}627}628for (j = 0; j < 4; j++) {629wrData = patternData[j];630OS_REG_WRITE(ah, addr, wrData);631rdData = OS_REG_READ(ah, addr);632if (wrData != rdData) {633HALDEBUG(ah, HAL_DEBUG_ANY,634"%s: address test failed addr: 0x%08x - wr:0x%08x != rd:0x%08x\n",635__func__, addr, wrData, rdData);636return AH_FALSE;637}638}639OS_REG_WRITE(ah, regAddr[i], regHold[i]);640}641OS_DELAY(100);642return AH_TRUE;643}644645/*646* Store the channel edges for the requested operational mode647*/648HAL_BOOL649ar5212GetChannelEdges(struct ath_hal *ah,650uint16_t flags, uint16_t *low, uint16_t *high)651{652if (flags & IEEE80211_CHAN_5GHZ) {653*low = 4915;654*high = 6100;655return AH_TRUE;656}657if ((flags & IEEE80211_CHAN_2GHZ) &&658(ath_hal_eepromGetFlag(ah, AR_EEP_BMODE) ||659ath_hal_eepromGetFlag(ah, AR_EEP_GMODE))) {660*low = 2312;661*high = 2732;662return AH_TRUE;663}664return AH_FALSE;665}666667/*668* Disable PLL when in L0s as well as receiver clock when in L1.669* This power saving option must be enabled through the Serdes.670*671* Programming the Serdes must go through the same 288 bit serial shift672* register as the other analog registers. Hence the 9 writes.673*674* XXX Clean up the magic numbers.675*/676static void677ar5212ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore, HAL_BOOL power_off)678{679OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00);680OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);681682/* RX shut off when elecidle is asserted */683OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x28000039);684OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x53160824);685OS_REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980579);686687/* Shut off PLL and CLKREQ active in L1 */688OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x001defff);689OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);690OS_REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);691OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x000e3007);692693/* Load the new settings */694OS_REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);695}696697static void698ar5212DisablePCIE(struct ath_hal *ah)699{700/* NB: fill in for 9100 */701}702703/*704* Fill all software cached or static hardware state information.705* Return failure if capabilities are to come from EEPROM and706* cannot be read.707*/708HAL_BOOL709ar5212FillCapabilityInfo(struct ath_hal *ah)710{711#define AR_KEYTABLE_SIZE 128712#define IS_GRIFFIN_LITE(ah) \713(AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_GRIFFIN && \714AH_PRIVATE(ah)->ah_macRev == AR_SREV_GRIFFIN_LITE)715#define IS_COBRA(ah) \716(AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_COBRA)717#define IS_2112(ah) \718((AH_PRIVATE(ah)->ah_analog5GhzRev & 0xF0) == AR_RAD2112_SREV_MAJOR)719720struct ath_hal_private *ahpriv = AH_PRIVATE(ah);721HAL_CAPABILITIES *pCap = &ahpriv->ah_caps;722uint16_t capField, val;723724/* Read the capability EEPROM location */725if (ath_hal_eepromGet(ah, AR_EEP_OPCAP, &capField) != HAL_OK) {726HALDEBUG(ah, HAL_DEBUG_ANY,727"%s: unable to read caps from eeprom\n", __func__);728return AH_FALSE;729}730if (IS_2112(ah))731ath_hal_eepromSet(ah, AR_EEP_AMODE, AH_FALSE);732if (capField == 0 && IS_GRIFFIN_LITE(ah)) {733/*734* For griffin-lite cards with unprogrammed capabilities.735*/736ath_hal_eepromSet(ah, AR_EEP_COMPRESS, AH_FALSE);737ath_hal_eepromSet(ah, AR_EEP_FASTFRAME, AH_FALSE);738ath_hal_eepromSet(ah, AR_EEP_TURBO5DISABLE, AH_TRUE);739ath_hal_eepromSet(ah, AR_EEP_TURBO2DISABLE, AH_TRUE);740HALDEBUG(ah, HAL_DEBUG_ATTACH,741"%s: override caps for griffin-lite, now 0x%x (+!turbo)\n",742__func__, capField);743}744745/* Modify reg domain on newer cards that need to work with older sw */746if (ahpriv->ah_opmode != HAL_M_HOSTAP &&747ahpriv->ah_subvendorid == AR_SUBVENDOR_ID_NEW_A) {748if (ahpriv->ah_currentRD == 0x64 ||749ahpriv->ah_currentRD == 0x65)750ahpriv->ah_currentRD += 5;751else if (ahpriv->ah_currentRD == 0x41)752ahpriv->ah_currentRD = 0x43;753HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: regdomain mapped to 0x%x\n",754__func__, ahpriv->ah_currentRD);755}756757if (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_2417 ||758AH_PRIVATE(ah)->ah_macVersion == AR_SREV_2425) {759HALDEBUG(ah, HAL_DEBUG_ATTACH,760"%s: enable Bmode and disable turbo for Swan/Nala\n",761__func__);762ath_hal_eepromSet(ah, AR_EEP_BMODE, AH_TRUE);763ath_hal_eepromSet(ah, AR_EEP_COMPRESS, AH_FALSE);764ath_hal_eepromSet(ah, AR_EEP_FASTFRAME, AH_FALSE);765ath_hal_eepromSet(ah, AR_EEP_TURBO5DISABLE, AH_TRUE);766ath_hal_eepromSet(ah, AR_EEP_TURBO2DISABLE, AH_TRUE);767}768769/* Construct wireless mode from EEPROM */770pCap->halWirelessModes = 0;771if (ath_hal_eepromGetFlag(ah, AR_EEP_AMODE)) {772pCap->halWirelessModes |= HAL_MODE_11A;773if (!ath_hal_eepromGetFlag(ah, AR_EEP_TURBO5DISABLE))774pCap->halWirelessModes |= HAL_MODE_TURBO;775}776if (ath_hal_eepromGetFlag(ah, AR_EEP_BMODE))777pCap->halWirelessModes |= HAL_MODE_11B;778if (ath_hal_eepromGetFlag(ah, AR_EEP_GMODE) &&779ahpriv->ah_subvendorid != AR_SUBVENDOR_ID_NOG) {780pCap->halWirelessModes |= HAL_MODE_11G;781if (!ath_hal_eepromGetFlag(ah, AR_EEP_TURBO2DISABLE))782pCap->halWirelessModes |= HAL_MODE_108G;783}784785pCap->halLow2GhzChan = 2312;786/* XXX 2417 too? */787if (IS_RAD5112_ANY(ah) || IS_5413(ah) || IS_2425(ah) || IS_2417(ah))788pCap->halHigh2GhzChan = 2500;789else790pCap->halHigh2GhzChan = 2732;791792/*793* For AR5111 version < 4, the lowest centre frequency supported is794* 5130MHz. For AR5111 version 4, the 4.9GHz channels are supported795* but only in 10MHz increments.796*797* In addition, the programming method is wrong - it uses the IEEE798* channel number to calculate the frequency, rather than the799* channel centre. Since half/quarter rates re-use some of the800* 5GHz channel IEEE numbers, this will result in a badly programmed801* synth.802*803* Until the relevant support is written, just limit lower frequency804* support for AR5111 so things aren't incorrectly programmed.805*806* XXX It's also possible this code doesn't correctly limit the807* centre frequencies of potential channels; this is very important808* for half/quarter rate!809*/810if (AH_RADIO_MAJOR(ah) == AR_RAD5111_SREV_MAJOR) {811pCap->halLow5GhzChan = 5120; /* XXX lowest centre = 5130MHz */812} else {813pCap->halLow5GhzChan = 4915;814}815pCap->halHigh5GhzChan = 6100;816817pCap->halCipherCkipSupport = AH_FALSE;818pCap->halCipherTkipSupport = AH_TRUE;819pCap->halCipherAesCcmSupport =820(ath_hal_eepromGetFlag(ah, AR_EEP_AES) &&821((AH_PRIVATE(ah)->ah_macVersion > AR_SREV_VERSION_VENICE) ||822((AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_VENICE) &&823(AH_PRIVATE(ah)->ah_macRev >= AR_SREV_VERSION_OAHU))));824825pCap->halMicCkipSupport = AH_FALSE;826pCap->halMicTkipSupport = AH_TRUE;827pCap->halMicAesCcmSupport = ath_hal_eepromGetFlag(ah, AR_EEP_AES);828/*829* Starting with Griffin TX+RX mic keys can be combined830* in one key cache slot.831*/832if (AH_PRIVATE(ah)->ah_macVersion >= AR_SREV_VERSION_GRIFFIN)833pCap->halTkipMicTxRxKeySupport = AH_TRUE;834else835pCap->halTkipMicTxRxKeySupport = AH_FALSE;836pCap->halChanSpreadSupport = AH_TRUE;837pCap->halSleepAfterBeaconBroken = AH_TRUE;838839if (ahpriv->ah_macRev > 1 || IS_COBRA(ah)) {840pCap->halCompressSupport =841ath_hal_eepromGetFlag(ah, AR_EEP_COMPRESS) &&842(pCap->halWirelessModes & (HAL_MODE_11A|HAL_MODE_11G)) != 0;843pCap->halBurstSupport = ath_hal_eepromGetFlag(ah, AR_EEP_BURST);844pCap->halFastFramesSupport =845ath_hal_eepromGetFlag(ah, AR_EEP_FASTFRAME) &&846(pCap->halWirelessModes & (HAL_MODE_11A|HAL_MODE_11G)) != 0;847pCap->halChapTuningSupport = AH_TRUE;848pCap->halTurboPrimeSupport = AH_TRUE;849}850pCap->halTurboGSupport = pCap->halWirelessModes & HAL_MODE_108G;851852pCap->halPSPollBroken = AH_TRUE; /* XXX fixed in later revs? */853pCap->halNumMRRetries = 4; /* Hardware supports 4 MRR */854pCap->halNumTxMaps = 1; /* Single TX ptr per descr */855pCap->halVEOLSupport = AH_TRUE;856pCap->halBssIdMaskSupport = AH_TRUE;857pCap->halMcastKeySrchSupport = AH_TRUE;858if ((ahpriv->ah_macVersion == AR_SREV_VERSION_VENICE &&859ahpriv->ah_macRev == 8) ||860ahpriv->ah_macVersion > AR_SREV_VERSION_VENICE)861pCap->halTsfAddSupport = AH_TRUE;862863if (ath_hal_eepromGet(ah, AR_EEP_MAXQCU, &val) == HAL_OK)864pCap->halTotalQueues = val;865else866pCap->halTotalQueues = HAL_NUM_TX_QUEUES;867868if (ath_hal_eepromGet(ah, AR_EEP_KCENTRIES, &val) == HAL_OK)869pCap->halKeyCacheSize = val;870else871pCap->halKeyCacheSize = AR_KEYTABLE_SIZE;872873pCap->halChanHalfRate = AH_TRUE;874pCap->halChanQuarterRate = AH_TRUE;875876/*877* RSSI uses the combined field; some 11n NICs may use878* the control chain RSSI.879*/880pCap->halUseCombinedRadarRssi = AH_TRUE;881882if (ath_hal_eepromGetFlag(ah, AR_EEP_RFKILL) &&883ath_hal_eepromGet(ah, AR_EEP_RFSILENT, &ahpriv->ah_rfsilent) == HAL_OK) {884/* NB: enabled by default */885ahpriv->ah_rfkillEnabled = AH_TRUE;886pCap->halRfSilentSupport = AH_TRUE;887}888889/* NB: this is a guess, no one seems to know the answer */890ahpriv->ah_rxornIsFatal =891(AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_VENICE);892893/* enable features that first appeared in Hainan */894if ((AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_VENICE &&895AH_PRIVATE(ah)->ah_macRev == AR_SREV_HAINAN) ||896AH_PRIVATE(ah)->ah_macVersion > AR_SREV_VERSION_VENICE) {897/* h/w phy counters */898pCap->halHwPhyCounterSupport = AH_TRUE;899/* bssid match disable */900pCap->halBssidMatchSupport = AH_TRUE;901}902903pCap->halRxTstampPrecision = 15;904pCap->halTxTstampPrecision = 16;905pCap->halIntrMask = HAL_INT_COMMON906| HAL_INT_RX907| HAL_INT_TX908| HAL_INT_FATAL909| HAL_INT_BNR910| HAL_INT_BMISC911;912if (AH_PRIVATE(ah)->ah_macVersion < AR_SREV_VERSION_GRIFFIN)913pCap->halIntrMask &= ~HAL_INT_TBTT;914915pCap->hal4kbSplitTransSupport = AH_TRUE;916pCap->halHasRxSelfLinkedTail = AH_TRUE;917918return AH_TRUE;919#undef IS_COBRA920#undef IS_GRIFFIN_LITE921#undef AR_KEYTABLE_SIZE922}923924static const char*925ar5212Probe(uint16_t vendorid, uint16_t devid)926{927if (vendorid == ATHEROS_VENDOR_ID ||928vendorid == ATHEROS_3COM_VENDOR_ID ||929vendorid == ATHEROS_3COM2_VENDOR_ID) {930switch (devid) {931case AR5212_FPGA:932return "Atheros 5212 (FPGA)";933case AR5212_DEVID:934case AR5212_DEVID_IBM:935case AR5212_DEFAULT:936return "Atheros 5212";937case AR5212_AR2413:938return "Atheros 2413";939case AR5212_AR2417:940return "Atheros 2417";941case AR5212_AR5413:942return "Atheros 5413";943case AR5212_AR5424:944return "Atheros 5424/2424";945}946}947return AH_NULL;948}949AH_CHIP(AR5212, ar5212Probe, ar5212Attach);950951952