Path: blob/main/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c
39566 views
/*-1* SPDX-License-Identifier: ISC2*3* Copyright (c) 2002-2008 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 "ah_eeprom_v14.h"2526#include "ar5416/ar5416.h"27#include "ar5416/ar5416reg.h"28#include "ar5416/ar5416phy.h"2930#include "ar5416/ar5416.ini"3132static void ar5416ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore,33HAL_BOOL power_off);34static void ar5416DisablePCIE(struct ath_hal *ah);35static void ar5416WriteIni(struct ath_hal *ah,36const struct ieee80211_channel *chan);37static void ar5416SpurMitigate(struct ath_hal *ah,38const struct ieee80211_channel *chan);3940static void41ar5416AniSetup(struct ath_hal *ah)42{43static const struct ar5212AniParams aniparams = {44.maxNoiseImmunityLevel = 4, /* levels 0..4 */45.totalSizeDesired = { -55, -55, -55, -55, -62 },46.coarseHigh = { -14, -14, -14, -14, -12 },47.coarseLow = { -64, -64, -64, -64, -70 },48.firpwr = { -78, -78, -78, -78, -80 },49.maxSpurImmunityLevel = 7,50.cycPwrThr1 = { 2, 4, 6, 8, 10, 12, 14, 16 },51.maxFirstepLevel = 2, /* levels 0..2 */52.firstep = { 0, 4, 8 },53.ofdmTrigHigh = 500,54.ofdmTrigLow = 200,55.cckTrigHigh = 200,56.cckTrigLow = 100,57.rssiThrHigh = 40,58.rssiThrLow = 7,59.period = 100,60};61/* NB: disable ANI noise immunity for reliable RIFS rx */62AH5416(ah)->ah_ani_function &= ~(1 << HAL_ANI_NOISE_IMMUNITY_LEVEL);63ar5416AniAttach(ah, &aniparams, &aniparams, AH_TRUE);64}6566/*67* AR5416 doesn't do OLC or temperature compensation.68*/69static void70ar5416olcInit(struct ath_hal *ah)71{72}7374static void75ar5416olcTempCompensation(struct ath_hal *ah)76{77}7879/*80* Attach for an AR5416 part.81*/82void83ar5416InitState(struct ath_hal_5416 *ahp5416, uint16_t devid, HAL_SOFTC sc,84HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *status)85{86struct ath_hal_5212 *ahp;87struct ath_hal *ah;8889ahp = &ahp5416->ah_5212;90ar5212InitState(ahp, devid, sc, st, sh, status);91ah = &ahp->ah_priv.h;9293/* override 5212 methods for our needs */94ah->ah_magic = AR5416_MAGIC;95ah->ah_getRateTable = ar5416GetRateTable;96ah->ah_detach = ar5416Detach;9798/* Reset functions */99ah->ah_reset = ar5416Reset;100ah->ah_phyDisable = ar5416PhyDisable;101ah->ah_disable = ar5416Disable;102ah->ah_configPCIE = ar5416ConfigPCIE;103ah->ah_disablePCIE = ar5416DisablePCIE;104ah->ah_perCalibration = ar5416PerCalibration;105ah->ah_perCalibrationN = ar5416PerCalibrationN;106ah->ah_resetCalValid = ar5416ResetCalValid;107ah->ah_setTxPowerLimit = ar5416SetTxPowerLimit;108ah->ah_setTxPower = ar5416SetTransmitPower;109ah->ah_setBoardValues = ar5416SetBoardValues;110111/* Transmit functions */112ah->ah_stopTxDma = ar5416StopTxDma;113ah->ah_setupTxDesc = ar5416SetupTxDesc;114ah->ah_setupXTxDesc = ar5416SetupXTxDesc;115ah->ah_fillTxDesc = ar5416FillTxDesc;116ah->ah_procTxDesc = ar5416ProcTxDesc;117ah->ah_getTxCompletionRates = ar5416GetTxCompletionRates;118ah->ah_setupTxQueue = ar5416SetupTxQueue;119ah->ah_resetTxQueue = ar5416ResetTxQueue;120121/* Receive Functions */122ah->ah_getRxFilter = ar5416GetRxFilter;123ah->ah_setRxFilter = ar5416SetRxFilter;124ah->ah_stopDmaReceive = ar5416StopDmaReceive;125ah->ah_startPcuReceive = ar5416StartPcuReceive;126ah->ah_stopPcuReceive = ar5416StopPcuReceive;127ah->ah_setupRxDesc = ar5416SetupRxDesc;128ah->ah_procRxDesc = ar5416ProcRxDesc;129ah->ah_rxMonitor = ar5416RxMonitor;130ah->ah_aniPoll = ar5416AniPoll;131ah->ah_procMibEvent = ar5416ProcessMibIntr;132133/* Misc Functions */134ah->ah_getCapability = ar5416GetCapability;135ah->ah_setCapability = ar5416SetCapability;136ah->ah_getDiagState = ar5416GetDiagState;137ah->ah_setLedState = ar5416SetLedState;138ah->ah_gpioCfgOutput = ar5416GpioCfgOutput;139ah->ah_gpioCfgInput = ar5416GpioCfgInput;140ah->ah_gpioGet = ar5416GpioGet;141ah->ah_gpioSet = ar5416GpioSet;142ah->ah_gpioSetIntr = ar5416GpioSetIntr;143ah->ah_getTsf64 = ar5416GetTsf64;144ah->ah_setTsf64 = ar5416SetTsf64;145ah->ah_resetTsf = ar5416ResetTsf;146ah->ah_getRfGain = ar5416GetRfgain;147ah->ah_setAntennaSwitch = ar5416SetAntennaSwitch;148ah->ah_setDecompMask = ar5416SetDecompMask;149ah->ah_setCoverageClass = ar5416SetCoverageClass;150ah->ah_setQuiet = ar5416SetQuiet;151ah->ah_getMibCycleCounts = ar5416GetMibCycleCounts;152ah->ah_setChainMasks = ar5416SetChainMasks;153154ah->ah_resetKeyCacheEntry = ar5416ResetKeyCacheEntry;155ah->ah_setKeyCacheEntry = ar5416SetKeyCacheEntry;156157/* DFS Functions */158ah->ah_enableDfs = ar5416EnableDfs;159ah->ah_getDfsThresh = ar5416GetDfsThresh;160ah->ah_getDfsDefaultThresh = ar5416GetDfsDefaultThresh;161ah->ah_procRadarEvent = ar5416ProcessRadarEvent;162ah->ah_isFastClockEnabled = ar5416IsFastClockEnabled;163164/* Spectral Scan Functions */165ah->ah_spectralConfigure = ar5416ConfigureSpectralScan;166ah->ah_spectralGetConfig = ar5416GetSpectralParams;167ah->ah_spectralStart = ar5416StartSpectralScan;168ah->ah_spectralStop = ar5416StopSpectralScan;169ah->ah_spectralIsEnabled = ar5416IsSpectralEnabled;170ah->ah_spectralIsActive = ar5416IsSpectralActive;171172/* Power Management Functions */173ah->ah_setPowerMode = ar5416SetPowerMode;174175/* Beacon Management Functions */176ah->ah_setBeaconTimers = ar5416SetBeaconTimers;177ah->ah_beaconInit = ar5416BeaconInit;178ah->ah_setStationBeaconTimers = ar5416SetStaBeaconTimers;179ah->ah_resetStationBeaconTimers = ar5416ResetStaBeaconTimers;180ah->ah_getNextTBTT = ar5416GetNextTBTT;181182/* 802.11n Functions */183ah->ah_chainTxDesc = ar5416ChainTxDesc;184ah->ah_setupFirstTxDesc = ar5416SetupFirstTxDesc;185ah->ah_setupLastTxDesc = ar5416SetupLastTxDesc;186ah->ah_set11nRateScenario = ar5416Set11nRateScenario;187ah->ah_set11nAggrFirst = ar5416Set11nAggrFirst;188ah->ah_set11nAggrMiddle = ar5416Set11nAggrMiddle;189ah->ah_set11nAggrLast = ar5416Set11nAggrLast;190ah->ah_clr11nAggr = ar5416Clr11nAggr;191ah->ah_set11nBurstDuration = ar5416Set11nBurstDuration;192ah->ah_get11nExtBusy = ar5416Get11nExtBusy;193ah->ah_set11nMac2040 = ar5416Set11nMac2040;194ah->ah_get11nRxClear = ar5416Get11nRxClear;195ah->ah_set11nRxClear = ar5416Set11nRxClear;196ah->ah_set11nVirtMoreFrag = ar5416Set11nVirtualMoreFrag;197198/* Interrupt functions */199ah->ah_isInterruptPending = ar5416IsInterruptPending;200ah->ah_getPendingInterrupts = ar5416GetPendingInterrupts;201ah->ah_setInterrupts = ar5416SetInterrupts;202203/* Bluetooth Coexistence functions */204ah->ah_btCoexSetInfo = ar5416SetBTCoexInfo;205ah->ah_btCoexSetConfig = ar5416BTCoexConfig;206ah->ah_btCoexSetQcuThresh = ar5416BTCoexSetQcuThresh;207ah->ah_btCoexSetWeights = ar5416BTCoexSetWeights;208ah->ah_btCoexSetBmissThresh = ar5416BTCoexSetupBmissThresh;209ah->ah_btCoexSetParameter = ar5416BTCoexSetParameter;210ah->ah_btCoexDisable = ar5416BTCoexDisable;211ah->ah_btCoexEnable = ar5416BTCoexEnable;212AH5416(ah)->ah_btCoexSetDiversity = ar5416BTCoexAntennaDiversity;213214ahp->ah_priv.ah_getWirelessModes= ar5416GetWirelessModes;215ahp->ah_priv.ah_eepromRead = ar5416EepromRead;216#ifdef AH_SUPPORT_WRITE_EEPROM217ahp->ah_priv.ah_eepromWrite = ar5416EepromWrite;218#endif219ahp->ah_priv.ah_getChipPowerLimits = ar5416GetChipPowerLimits;220221/* Internal ops */222AH5416(ah)->ah_writeIni = ar5416WriteIni;223AH5416(ah)->ah_spurMitigate = ar5416SpurMitigate;224225/* Internal baseband ops */226AH5416(ah)->ah_initPLL = ar5416InitPLL;227228/* Internal calibration ops */229AH5416(ah)->ah_cal_initcal = ar5416InitCalHardware;230231/* Internal TX power control related operations */232AH5416(ah)->ah_olcInit = ar5416olcInit;233AH5416(ah)->ah_olcTempCompensation = ar5416olcTempCompensation;234AH5416(ah)->ah_setPowerCalTable = ar5416SetPowerCalTable;235236/*237* Start by setting all Owl devices to 2x2238*/239AH5416(ah)->ah_rx_chainmask = AR5416_DEFAULT_RXCHAINMASK;240AH5416(ah)->ah_tx_chainmask = AR5416_DEFAULT_TXCHAINMASK;241242/* Enable all ANI functions to begin with */243AH5416(ah)->ah_ani_function = 0xffffffff;244245/* Set overridable ANI methods */246AH5212(ah)->ah_aniControl = ar5416AniControl;247248/*249* Default FIFO Trigger levels250*251* These define how filled the TX FIFO needs to be before252* the baseband begins to be given some data.253*254* To be paranoid, we ensure that the TX trigger level always255* has at least enough space for two TX DMA to occur.256* The TX DMA size is currently hard-coded to AR_TXCFG_DMASZ_128B.257* That means we need to leave at least 256 bytes available in258* the TX DMA FIFO.259*/260#define AR_FTRIG_512B 0x00000080 // 5 bits total261/*262* AR9285/AR9271 have half the size TX FIFO compared to263* other devices264*/265if (AR_SREV_KITE(ah) || AR_SREV_9271(ah)) {266AH5212(ah)->ah_txTrigLev = (AR_FTRIG_256B >> AR_FTRIG_S);267AH5212(ah)->ah_maxTxTrigLev = ((2048 / 64) - 1);268} else {269AH5212(ah)->ah_txTrigLev = (AR_FTRIG_512B >> AR_FTRIG_S);270AH5212(ah)->ah_maxTxTrigLev = ((4096 / 64) - 1);271}272#undef AR_FTRIG_512B273274/* And now leave some headspace - 256 bytes */275AH5212(ah)->ah_maxTxTrigLev -= 4;276}277278uint32_t279ar5416GetRadioRev(struct ath_hal *ah)280{281uint32_t val;282int i;283284/* Read Radio Chip Rev Extract */285OS_REG_WRITE(ah, AR_PHY(0x36), 0x00007058);286for (i = 0; i < 8; i++)287OS_REG_WRITE(ah, AR_PHY(0x20), 0x00010000);288val = (OS_REG_READ(ah, AR_PHY(256)) >> 24) & 0xff;289val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4);290return ath_hal_reverseBits(val, 8);291}292293/*294* Attach for an AR5416 part.295*/296static struct ath_hal *297ar5416Attach(uint16_t devid, HAL_SOFTC sc,298HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata,299HAL_OPS_CONFIG *ah_config, HAL_STATUS *status)300{301struct ath_hal_5416 *ahp5416;302struct ath_hal_5212 *ahp;303struct ath_hal *ah;304uint32_t val;305HAL_STATUS ecode;306HAL_BOOL rfStatus;307308HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n",309__func__, sc, (void*) st, (void*) sh);310311/* NB: memory is returned zero'd */312ahp5416 = ath_hal_malloc(sizeof (struct ath_hal_5416) +313/* extra space for Owl 2.1/2.2 WAR */314sizeof(ar5416Addac)315);316if (ahp5416 == AH_NULL) {317HALDEBUG(AH_NULL, HAL_DEBUG_ANY,318"%s: cannot allocate memory for state block\n", __func__);319*status = HAL_ENOMEM;320return AH_NULL;321}322ar5416InitState(ahp5416, devid, sc, st, sh, status);323ahp = &ahp5416->ah_5212;324ah = &ahp->ah_priv.h;325326if (!ar5416SetResetReg(ah, HAL_RESET_POWER_ON)) {327/* reset chip */328HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't reset chip\n", __func__);329ecode = HAL_EIO;330goto bad;331}332333if (!ar5416SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) {334HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't wakeup chip\n", __func__);335ecode = HAL_EIO;336goto bad;337}338/* Read Revisions from Chips before taking out of reset */339val = OS_REG_READ(ah, AR_SREV) & AR_SREV_ID;340AH_PRIVATE(ah)->ah_macVersion = val >> AR_SREV_ID_S;341AH_PRIVATE(ah)->ah_macRev = val & AR_SREV_REVISION;342AH_PRIVATE(ah)->ah_ispcie = (devid == AR5416_DEVID_PCIE);343344/* setup common ini data; rf backends handle remainder */345HAL_INI_INIT(&ahp->ah_ini_modes, ar5416Modes, 6);346HAL_INI_INIT(&ahp->ah_ini_common, ar5416Common, 2);347348HAL_INI_INIT(&AH5416(ah)->ah_ini_bb_rfgain, ar5416BB_RfGain, 3);349HAL_INI_INIT(&AH5416(ah)->ah_ini_bank0, ar5416Bank0, 2);350HAL_INI_INIT(&AH5416(ah)->ah_ini_bank1, ar5416Bank1, 2);351HAL_INI_INIT(&AH5416(ah)->ah_ini_bank2, ar5416Bank2, 2);352HAL_INI_INIT(&AH5416(ah)->ah_ini_bank3, ar5416Bank3, 3);353HAL_INI_INIT(&AH5416(ah)->ah_ini_bank6, ar5416Bank6, 3);354HAL_INI_INIT(&AH5416(ah)->ah_ini_bank7, ar5416Bank7, 2);355HAL_INI_INIT(&AH5416(ah)->ah_ini_addac, ar5416Addac, 2);356357if (! IS_5416V2_2(ah)) { /* Owl 2.1/2.0 */358ath_hal_printf(ah, "[ath] Enabling CLKDRV workaround for AR5416 < v2.2\n");359struct ini {360uint32_t *data; /* NB: !const */361int rows, cols;362};363/* override CLKDRV value */364OS_MEMCPY(&AH5416(ah)[1], ar5416Addac, sizeof(ar5416Addac));365AH5416(ah)->ah_ini_addac.data = (uint32_t *) &AH5416(ah)[1];366HAL_INI_VAL((struct ini *)&AH5416(ah)->ah_ini_addac, 31, 1) = 0;367}368369HAL_INI_INIT(&AH5416(ah)->ah_ini_pcieserdes, ar5416PciePhy, 2);370ar5416AttachPCIE(ah);371372ecode = ath_hal_v14EepromAttach(ah);373if (ecode != HAL_OK)374goto bad;375376if (!ar5416ChipReset(ah, AH_NULL, HAL_RESET_NORMAL)) { /* reset chip */377HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n",378__func__);379ecode = HAL_EIO;380goto bad;381}382383AH_PRIVATE(ah)->ah_phyRev = OS_REG_READ(ah, AR_PHY_CHIP_ID);384385if (!ar5212ChipTest(ah)) {386HALDEBUG(ah, HAL_DEBUG_ANY, "%s: hardware self-test failed\n",387__func__);388ecode = HAL_ESELFTEST;389goto bad;390}391392/*393* Set correct Baseband to analog shift394* setting to access analog chips.395*/396OS_REG_WRITE(ah, AR_PHY(0), 0x00000007);397398/* Read Radio Chip Rev Extract */399AH_PRIVATE(ah)->ah_analog5GhzRev = ar5416GetRadioRev(ah);400switch (AH_PRIVATE(ah)->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR) {401case AR_RAD5122_SREV_MAJOR: /* Fowl: 5G/2x2 */402case AR_RAD2122_SREV_MAJOR: /* Fowl: 2+5G/2x2 */403case AR_RAD2133_SREV_MAJOR: /* Fowl: 2G/3x3 */404case AR_RAD5133_SREV_MAJOR: /* Fowl: 2+5G/3x3 */405break;406default:407if (AH_PRIVATE(ah)->ah_analog5GhzRev == 0) {408/*409* When RF_Silen is used the analog chip is reset.410* So when the system boots with radio switch off411* the RF chip rev reads back as zero and we need412* to use the mac+phy revs to set the radio rev.413*/414AH_PRIVATE(ah)->ah_analog5GhzRev =415AR_RAD5133_SREV_MAJOR;416break;417}418/* NB: silently accept anything in release code per Atheros */419#ifdef AH_DEBUG420HALDEBUG(ah, HAL_DEBUG_ANY,421"%s: 5G Radio Chip Rev 0x%02X is not supported by "422"this driver\n", __func__,423AH_PRIVATE(ah)->ah_analog5GhzRev);424ecode = HAL_ENOTSUPP;425goto bad;426#endif427}428429/*430* Got everything we need now to setup the capabilities.431*/432if (!ar5416FillCapabilityInfo(ah)) {433ecode = HAL_EEREAD;434goto bad;435}436437ecode = ath_hal_eepromGet(ah, AR_EEP_MACADDR, ahp->ah_macaddr);438if (ecode != HAL_OK) {439HALDEBUG(ah, HAL_DEBUG_ANY,440"%s: error getting mac address from EEPROM\n", __func__);441goto bad;442}443/* XXX How about the serial number ? */444/* Read Reg Domain */445AH_PRIVATE(ah)->ah_currentRD =446ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, AH_NULL);447AH_PRIVATE(ah)->ah_currentRDext =448ath_hal_eepromGet(ah, AR_EEP_REGDMN_1, AH_NULL);449450/*451* ah_miscMode is populated by ar5416FillCapabilityInfo()452* starting from griffin. Set here to make sure that453* AR_MISC_MODE_MIC_NEW_LOC_ENABLE is set before a GTK is454* placed into hardware.455*/456if (ahp->ah_miscMode != 0)457OS_REG_WRITE(ah, AR_MISC_MODE, OS_REG_READ(ah, AR_MISC_MODE) | ahp->ah_miscMode);458459rfStatus = ar2133RfAttach(ah, &ecode);460if (!rfStatus) {461HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RF setup failed, status %u\n",462__func__, ecode);463goto bad;464}465466ar5416AniSetup(ah); /* Anti Noise Immunity */467468AH5416(ah)->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_5416_2GHZ;469AH5416(ah)->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_5416_2GHZ;470AH5416(ah)->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_5416_2GHZ;471AH5416(ah)->nf_5g.max = AR_PHY_CCA_MAX_GOOD_VAL_5416_5GHZ;472AH5416(ah)->nf_5g.min = AR_PHY_CCA_MIN_GOOD_VAL_5416_5GHZ;473AH5416(ah)->nf_5g.nominal = AR_PHY_CCA_NOM_VAL_5416_5GHZ;474475ar5416InitNfHistBuff(AH5416(ah)->ah_cal.nfCalHist);476477HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n", __func__);478479return ah;480bad:481if (ahp)482ar5416Detach((struct ath_hal *) ahp);483if (status)484*status = ecode;485return AH_NULL;486}487488void489ar5416Detach(struct ath_hal *ah)490{491HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s:\n", __func__);492493HALASSERT(ah != AH_NULL);494HALASSERT(ah->ah_magic == AR5416_MAGIC);495496/* Make sure that chip is awake before writing to it */497if (! ar5416SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE))498HALDEBUG(ah, HAL_DEBUG_UNMASKABLE,499"%s: failed to wake up chip\n",500__func__);501502ar5416AniDetach(ah);503ar5212RfDetach(ah);504ah->ah_disable(ah);505ar5416SetPowerMode(ah, HAL_PM_FULL_SLEEP, AH_TRUE);506ath_hal_eepromDetach(ah);507ath_hal_free(ah);508}509510void511ar5416AttachPCIE(struct ath_hal *ah)512{513if (AH_PRIVATE(ah)->ah_ispcie)514ath_hal_configPCIE(ah, AH_FALSE, AH_FALSE);515else516ath_hal_disablePCIE(ah);517}518519static void520ar5416ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore, HAL_BOOL power_off)521{522523/* This is only applicable for AR5418 (AR5416 PCIe) */524if (! AH_PRIVATE(ah)->ah_ispcie)525return;526527if (! restore) {528ath_hal_ini_write(ah, &AH5416(ah)->ah_ini_pcieserdes, 1, 0);529OS_DELAY(1000);530}531532if (power_off) { /* Power-off */533/* clear bit 19 to disable L1 */534OS_REG_CLR_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);535} else { /* Power-on */536/* Set default WAR values for Owl */537OS_REG_WRITE(ah, AR_WA, AR_WA_DEFAULT);538539/* set bit 19 to allow forcing of pcie core into L1 state */540OS_REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);541}542}543544/*545* Disable PCIe PHY if PCIe isn't used.546*/547static void548ar5416DisablePCIE(struct ath_hal *ah)549{550551/* PCIe? Don't */552if (AH_PRIVATE(ah)->ah_ispcie)553return;554555/* .. Only applicable for AR5416v2 or later */556if (! (AR_SREV_OWL(ah) && AR_SREV_OWL_20_OR_LATER(ah)))557return;558559OS_REG_WRITE_BUFFER_ENABLE(ah);560561/*562* Disable the PCIe PHY.563*/564OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00);565OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);566OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x28000029);567OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x57160824);568OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x25980579);569OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x00000000);570OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);571OS_REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);572OS_REG_WRITE(ah, AR_PCIE_SERDES, 0x000e1007);573574/* Load the new settings */575OS_REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);576577OS_REG_WRITE_BUFFER_FLUSH(ah);578OS_REG_WRITE_BUFFER_DISABLE(ah);579}580581static void582ar5416WriteIni(struct ath_hal *ah, const struct ieee80211_channel *chan)583{584u_int modesIndex, freqIndex;585int regWrites = 0;586587/* Setup the indices for the next set of register array writes */588/* XXX Ignore 11n dynamic mode on the AR5416 for the moment */589if (IEEE80211_IS_CHAN_2GHZ(chan)) {590freqIndex = 2;591if (IEEE80211_IS_CHAN_HT40(chan))592modesIndex = 3;593else if (IEEE80211_IS_CHAN_108G(chan))594modesIndex = 5;595else596modesIndex = 4;597} else {598freqIndex = 1;599if (IEEE80211_IS_CHAN_HT40(chan) ||600IEEE80211_IS_CHAN_TURBO(chan))601modesIndex = 2;602else603modesIndex = 1;604}605606/* Set correct Baseband to analog shift setting to access analog chips. */607OS_REG_WRITE(ah, AR_PHY(0), 0x00000007);608609/*610* Write addac shifts611*/612OS_REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_EXTERNAL_RADIO);613614/* NB: only required for Sowl */615if (AR_SREV_SOWL(ah))616ar5416EepromSetAddac(ah, chan);617618regWrites = ath_hal_ini_write(ah, &AH5416(ah)->ah_ini_addac, 1,619regWrites);620OS_REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC);621622regWrites = ath_hal_ini_write(ah, &AH5212(ah)->ah_ini_modes,623modesIndex, regWrites);624regWrites = ath_hal_ini_write(ah, &AH5212(ah)->ah_ini_common,6251, regWrites);626627/* XXX updated regWrites? */628AH5212(ah)->ah_rfHal->writeRegs(ah, modesIndex, freqIndex, regWrites);629}630631/*632* Convert to baseband spur frequency given input channel frequency633* and compute register settings below.634*/635636static void637ar5416SpurMitigate(struct ath_hal *ah, const struct ieee80211_channel *chan)638{639uint16_t freq = ath_hal_gethwchannel(ah, chan);640static const int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8,641AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60 };642static const int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10,643AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60 };644static const int inc[4] = { 0, 100, 0, 0 };645646int bb_spur = AR_NO_SPUR;647int bin, cur_bin;648int spur_freq_sd;649int spur_delta_phase;650int denominator;651int upper, lower, cur_vit_mask;652int tmp, new;653int i;654655int8_t mask_m[123];656int8_t mask_p[123];657int8_t mask_amt;658int tmp_mask;659int cur_bb_spur;660HAL_BOOL is2GHz = IEEE80211_IS_CHAN_2GHZ(chan);661662OS_MEMZERO(mask_m, sizeof(mask_m));663OS_MEMZERO(mask_p, sizeof(mask_p));664665/*666* Need to verify range +/- 9.5 for static ht20, otherwise spur667* is out-of-band and can be ignored.668*/669/* XXX ath9k changes */670for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) {671cur_bb_spur = ath_hal_getSpurChan(ah, i, is2GHz);672if (AR_NO_SPUR == cur_bb_spur)673break;674cur_bb_spur = cur_bb_spur - (freq * 10);675if ((cur_bb_spur > -95) && (cur_bb_spur < 95)) {676bb_spur = cur_bb_spur;677break;678}679}680if (AR_NO_SPUR == bb_spur)681return;682683bin = bb_spur * 32;684685tmp = OS_REG_READ(ah, AR_PHY_TIMING_CTRL4_CHAIN(0));686new = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI |687AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER |688AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK |689AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK);690691OS_REG_WRITE_BUFFER_ENABLE(ah);692693OS_REG_WRITE(ah, AR_PHY_TIMING_CTRL4_CHAIN(0), new);694695new = (AR_PHY_SPUR_REG_MASK_RATE_CNTL |696AR_PHY_SPUR_REG_ENABLE_MASK_PPM |697AR_PHY_SPUR_REG_MASK_RATE_SELECT |698AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI |699SM(AR5416_SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH));700OS_REG_WRITE(ah, AR_PHY_SPUR_REG, new);701/*702* Should offset bb_spur by +/- 10 MHz for dynamic 2040 MHz703* config, no offset for HT20.704* spur_delta_phase = bb_spur/40 * 2**21 for static ht20,705* /80 for dyn2040.706*/707spur_delta_phase = ((bb_spur * 524288) / 100) &708AR_PHY_TIMING11_SPUR_DELTA_PHASE;709/*710* in 11A mode the denominator of spur_freq_sd should be 40 and711* it should be 44 in 11G712*/713denominator = IEEE80211_IS_CHAN_2GHZ(chan) ? 440 : 400;714spur_freq_sd = ((bb_spur * 2048) / denominator) & 0x3ff;715716new = (AR_PHY_TIMING11_USE_SPUR_IN_AGC |717SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) |718SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE));719OS_REG_WRITE(ah, AR_PHY_TIMING11, new);720721/*722* ============================================723* pilot mask 1 [31:0] = +6..-26, no 0 bin724* pilot mask 2 [19:0] = +26..+7725*726* channel mask 1 [31:0] = +6..-26, no 0 bin727* channel mask 2 [19:0] = +26..+7728*/729//cur_bin = -26;730cur_bin = -6000;731upper = bin + 100;732lower = bin - 100;733734for (i = 0; i < 4; i++) {735int pilot_mask = 0;736int chan_mask = 0;737int bp = 0;738for (bp = 0; bp < 30; bp++) {739if ((cur_bin > lower) && (cur_bin < upper)) {740pilot_mask = pilot_mask | 0x1 << bp;741chan_mask = chan_mask | 0x1 << bp;742}743cur_bin += 100;744}745cur_bin += inc[i];746OS_REG_WRITE(ah, pilot_mask_reg[i], pilot_mask);747OS_REG_WRITE(ah, chan_mask_reg[i], chan_mask);748}749750/* =================================================751* viterbi mask 1 based on channel magnitude752* four levels 0-3753* - mask (-27 to 27) (reg 64,0x9900 to 67,0x990c)754* [1 2 2 1] for -9.6 or [1 2 1] for +16755* - enable_mask_ppm, all bins move with freq756*757* - mask_select, 8 bits for rates (reg 67,0x990c)758* - mask_rate_cntl, 8 bits for rates (reg 67,0x990c)759* choose which mask to use mask or mask2760*/761762/*763* viterbi mask 2 2nd set for per data rate puncturing764* four levels 0-3765* - mask_select, 8 bits for rates (reg 67)766* - mask (-27 to 27) (reg 98,0x9988 to 101,0x9994)767* [1 2 2 1] for -9.6 or [1 2 1] for +16768*/769cur_vit_mask = 6100;770upper = bin + 120;771lower = bin - 120;772773for (i = 0; i < 123; i++) {774if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) {775if ((abs(cur_vit_mask - bin)) < 75) {776mask_amt = 1;777} else {778mask_amt = 0;779}780if (cur_vit_mask < 0) {781mask_m[abs(cur_vit_mask / 100)] = mask_amt;782} else {783mask_p[cur_vit_mask / 100] = mask_amt;784}785}786cur_vit_mask -= 100;787}788789tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28)790| (mask_m[48] << 26) | (mask_m[49] << 24)791| (mask_m[50] << 22) | (mask_m[51] << 20)792| (mask_m[52] << 18) | (mask_m[53] << 16)793| (mask_m[54] << 14) | (mask_m[55] << 12)794| (mask_m[56] << 10) | (mask_m[57] << 8)795| (mask_m[58] << 6) | (mask_m[59] << 4)796| (mask_m[60] << 2) | (mask_m[61] << 0);797OS_REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask);798OS_REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask);799800tmp_mask = (mask_m[31] << 28)801| (mask_m[32] << 26) | (mask_m[33] << 24)802| (mask_m[34] << 22) | (mask_m[35] << 20)803| (mask_m[36] << 18) | (mask_m[37] << 16)804| (mask_m[48] << 14) | (mask_m[39] << 12)805| (mask_m[40] << 10) | (mask_m[41] << 8)806| (mask_m[42] << 6) | (mask_m[43] << 4)807| (mask_m[44] << 2) | (mask_m[45] << 0);808OS_REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask);809OS_REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask);810811tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28)812| (mask_m[18] << 26) | (mask_m[18] << 24)813| (mask_m[20] << 22) | (mask_m[20] << 20)814| (mask_m[22] << 18) | (mask_m[22] << 16)815| (mask_m[24] << 14) | (mask_m[24] << 12)816| (mask_m[25] << 10) | (mask_m[26] << 8)817| (mask_m[27] << 6) | (mask_m[28] << 4)818| (mask_m[29] << 2) | (mask_m[30] << 0);819OS_REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask);820OS_REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask);821822tmp_mask = (mask_m[ 0] << 30) | (mask_m[ 1] << 28)823| (mask_m[ 2] << 26) | (mask_m[ 3] << 24)824| (mask_m[ 4] << 22) | (mask_m[ 5] << 20)825| (mask_m[ 6] << 18) | (mask_m[ 7] << 16)826| (mask_m[ 8] << 14) | (mask_m[ 9] << 12)827| (mask_m[10] << 10) | (mask_m[11] << 8)828| (mask_m[12] << 6) | (mask_m[13] << 4)829| (mask_m[14] << 2) | (mask_m[15] << 0);830OS_REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask);831OS_REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask);832833tmp_mask = (mask_p[15] << 28)834| (mask_p[14] << 26) | (mask_p[13] << 24)835| (mask_p[12] << 22) | (mask_p[11] << 20)836| (mask_p[10] << 18) | (mask_p[ 9] << 16)837| (mask_p[ 8] << 14) | (mask_p[ 7] << 12)838| (mask_p[ 6] << 10) | (mask_p[ 5] << 8)839| (mask_p[ 4] << 6) | (mask_p[ 3] << 4)840| (mask_p[ 2] << 2) | (mask_p[ 1] << 0);841OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask);842OS_REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask);843844tmp_mask = (mask_p[30] << 28)845| (mask_p[29] << 26) | (mask_p[28] << 24)846| (mask_p[27] << 22) | (mask_p[26] << 20)847| (mask_p[25] << 18) | (mask_p[24] << 16)848| (mask_p[23] << 14) | (mask_p[22] << 12)849| (mask_p[21] << 10) | (mask_p[20] << 8)850| (mask_p[19] << 6) | (mask_p[18] << 4)851| (mask_p[17] << 2) | (mask_p[16] << 0);852OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask);853OS_REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask);854855tmp_mask = (mask_p[45] << 28)856| (mask_p[44] << 26) | (mask_p[43] << 24)857| (mask_p[42] << 22) | (mask_p[41] << 20)858| (mask_p[40] << 18) | (mask_p[39] << 16)859| (mask_p[38] << 14) | (mask_p[37] << 12)860| (mask_p[36] << 10) | (mask_p[35] << 8)861| (mask_p[34] << 6) | (mask_p[33] << 4)862| (mask_p[32] << 2) | (mask_p[31] << 0);863OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask);864OS_REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask);865866tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28)867| (mask_p[59] << 26) | (mask_p[58] << 24)868| (mask_p[57] << 22) | (mask_p[56] << 20)869| (mask_p[55] << 18) | (mask_p[54] << 16)870| (mask_p[53] << 14) | (mask_p[52] << 12)871| (mask_p[51] << 10) | (mask_p[50] << 8)872| (mask_p[49] << 6) | (mask_p[48] << 4)873| (mask_p[47] << 2) | (mask_p[46] << 0);874OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask);875OS_REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask);876877OS_REG_WRITE_BUFFER_FLUSH(ah);878OS_REG_WRITE_BUFFER_DISABLE(ah);879}880881/*882* Fill all software cached or static hardware state information.883* Return failure if capabilities are to come from EEPROM and884* cannot be read.885*/886HAL_BOOL887ar5416FillCapabilityInfo(struct ath_hal *ah)888{889struct ath_hal_private *ahpriv = AH_PRIVATE(ah);890HAL_CAPABILITIES *pCap = &ahpriv->ah_caps;891uint16_t val;892893/* Construct wireless mode from EEPROM */894pCap->halWirelessModes = 0;895if (ath_hal_eepromGetFlag(ah, AR_EEP_AMODE)) {896pCap->halWirelessModes |= HAL_MODE_11A897| HAL_MODE_11NA_HT20898| HAL_MODE_11NA_HT40PLUS899| HAL_MODE_11NA_HT40MINUS900;901}902if (ath_hal_eepromGetFlag(ah, AR_EEP_GMODE)) {903pCap->halWirelessModes |= HAL_MODE_11G904| HAL_MODE_11NG_HT20905| HAL_MODE_11NG_HT40PLUS906| HAL_MODE_11NG_HT40MINUS907;908pCap->halWirelessModes |= HAL_MODE_11A909| HAL_MODE_11NA_HT20910| HAL_MODE_11NA_HT40PLUS911| HAL_MODE_11NA_HT40MINUS912;913}914915pCap->halLow2GhzChan = 2312;916pCap->halHigh2GhzChan = 2732;917918pCap->halLow5GhzChan = 4915;919pCap->halHigh5GhzChan = 6100;920921pCap->halCipherCkipSupport = AH_FALSE;922pCap->halCipherTkipSupport = AH_TRUE;923pCap->halCipherAesCcmSupport = ath_hal_eepromGetFlag(ah, AR_EEP_AES);924925pCap->halMicCkipSupport = AH_FALSE;926pCap->halMicTkipSupport = AH_TRUE;927pCap->halMicAesCcmSupport = ath_hal_eepromGetFlag(ah, AR_EEP_AES);928/*929* Starting with Griffin TX+RX mic keys can be combined930* in one key cache slot.931*/932pCap->halTkipMicTxRxKeySupport = AH_TRUE;933pCap->halChanSpreadSupport = AH_TRUE;934pCap->halSleepAfterBeaconBroken = AH_TRUE;935936pCap->halCompressSupport = AH_FALSE;937pCap->halBurstSupport = AH_TRUE;938pCap->halFastFramesSupport = AH_TRUE;939pCap->halChapTuningSupport = AH_TRUE;940pCap->halTurboPrimeSupport = AH_TRUE;941942pCap->halTurboGSupport = pCap->halWirelessModes & HAL_MODE_108G;943944pCap->halPSPollBroken = AH_TRUE; /* XXX fixed in later revs? */945pCap->halNumMRRetries = 4; /* Hardware supports 4 MRR */946pCap->halNumTxMaps = 1; /* Single TX ptr per descr */947pCap->halVEOLSupport = AH_TRUE;948pCap->halBssIdMaskSupport = AH_TRUE;949pCap->halMcastKeySrchSupport = AH_TRUE; /* Works on AR5416 and later */950pCap->halTsfAddSupport = AH_TRUE;951pCap->hal4AddrAggrSupport = AH_FALSE; /* Broken in Owl */952pCap->halSpectralScanSupport = AH_FALSE; /* AR9280 and later */953954if (ath_hal_eepromGet(ah, AR_EEP_MAXQCU, &val) == HAL_OK)955pCap->halTotalQueues = val;956else957pCap->halTotalQueues = HAL_NUM_TX_QUEUES;958959if (ath_hal_eepromGet(ah, AR_EEP_KCENTRIES, &val) == HAL_OK)960pCap->halKeyCacheSize = val;961else962pCap->halKeyCacheSize = AR5416_KEYTABLE_SIZE;963964/* XXX Which chips? */965pCap->halChanHalfRate = AH_TRUE;966pCap->halChanQuarterRate = AH_TRUE;967968pCap->halTxTstampPrecision = 32;969pCap->halRxTstampPrecision = 32;970pCap->halHwPhyCounterSupport = AH_TRUE;971pCap->halIntrMask = HAL_INT_COMMON972| HAL_INT_RX973| HAL_INT_TX974| HAL_INT_FATAL975| HAL_INT_BNR976| HAL_INT_BMISC977| HAL_INT_DTIMSYNC978| HAL_INT_TSFOOR979| HAL_INT_CST980| HAL_INT_GTT981;982983pCap->halFastCCSupport = AH_TRUE;984pCap->halNumGpioPins = 14;985pCap->halWowSupport = AH_FALSE;986pCap->halWowMatchPatternExact = AH_FALSE;987pCap->halBtCoexSupport = AH_FALSE; /* XXX need support */988pCap->halAutoSleepSupport = AH_FALSE;989pCap->hal4kbSplitTransSupport = AH_TRUE;990/* Disable this so Block-ACK works correctly */991pCap->halHasRxSelfLinkedTail = AH_FALSE;992#if 0 /* XXX not yet */993pCap->halNumAntCfg2GHz = ar5416GetNumAntConfig(ahp, HAL_FREQ_BAND_2GHZ);994pCap->halNumAntCfg5GHz = ar5416GetNumAntConfig(ahp, HAL_FREQ_BAND_5GHZ);995#endif996pCap->halHTSupport = AH_TRUE;997pCap->halTxChainMask = ath_hal_eepromGet(ah, AR_EEP_TXMASK, AH_NULL);998/* XXX CB71 uses GPIO 0 to indicate 3 rx chains */999pCap->halRxChainMask = ath_hal_eepromGet(ah, AR_EEP_RXMASK, AH_NULL);1000/* AR5416 may have 3 antennas but is a 2x2 stream device */1001pCap->halTxStreams = 2;1002pCap->halRxStreams = 2;10031004/*1005* If the TX or RX chainmask has less than 2 chains active,1006* mark it as a 1-stream device for the relevant stream.1007*/1008if (owl_get_ntxchains(pCap->halTxChainMask) == 1)1009pCap->halTxStreams = 1;1010/* XXX Eww */1011if (owl_get_ntxchains(pCap->halRxChainMask) == 1)1012pCap->halRxStreams = 1;1013pCap->halRtsAggrLimit = 8*1024; /* Owl 2.0 limit */1014pCap->halMbssidAggrSupport = AH_FALSE; /* Broken on Owl */1015pCap->halForcePpmSupport = AH_TRUE;1016pCap->halEnhancedPmSupport = AH_TRUE;1017pCap->halBssidMatchSupport = AH_TRUE;1018pCap->halGTTSupport = AH_TRUE;1019pCap->halCSTSupport = AH_TRUE;1020pCap->halEnhancedDfsSupport = AH_FALSE;1021/*1022* BB Read WAR: this is only for AR5008/AR9001 NICs1023* It is also set individually in the AR91xx attach functions.1024*/1025if (AR_SREV_OWL(ah))1026pCap->halHasBBReadWar = AH_TRUE;10271028if (ath_hal_eepromGetFlag(ah, AR_EEP_RFKILL) &&1029ath_hal_eepromGet(ah, AR_EEP_RFSILENT, &ahpriv->ah_rfsilent) == HAL_OK) {1030/* NB: enabled by default */1031ahpriv->ah_rfkillEnabled = AH_TRUE;1032pCap->halRfSilentSupport = AH_TRUE;1033}10341035/*1036* The MAC will mark frames as RXed if there's a descriptor1037* to write them to. So if it hits a self-linked final descriptor,1038* it'll keep ACKing frames even though they're being silently1039* dropped. Thus, this particular feature of the driver can't1040* be used for 802.11n devices.1041*/1042ahpriv->ah_rxornIsFatal = AH_FALSE;10431044/*1045* If it's a PCI NIC, ask the HAL OS layer to serialise1046* register access, or SMP machines may cause the hardware1047* to hang. This is applicable to AR5416 and AR9220; I'm not1048* sure about AR9160 or AR9227.1049*/1050if (! AH_PRIVATE(ah)->ah_ispcie)1051pCap->halSerialiseRegWar = 1;10521053/*1054* AR5416 and later NICs support MYBEACON filtering.1055*/1056pCap->halRxDoMyBeacon = AH_TRUE;10571058return AH_TRUE;1059}10601061static const char*1062ar5416Probe(uint16_t vendorid, uint16_t devid)1063{1064if (vendorid == ATHEROS_VENDOR_ID) {1065if (devid == AR5416_DEVID_PCI)1066return "Atheros 5416";1067if (devid == AR5416_DEVID_PCIE)1068return "Atheros 5418";1069}1070return AH_NULL;1071}1072AH_CHIP(AR5416, ar5416Probe, ar5416Attach);107310741075