ar9280_attach.c revision 219441
11573Srgrimes/* 21573Srgrimes * Copyright (c) 2008-2009 Sam Leffler, Errno Consulting 31573Srgrimes * Copyright (c) 2008 Atheros Communications, Inc. 41573Srgrimes * 51573Srgrimes * Permission to use, copy, modify, and/or distribute this software for any 61573Srgrimes * purpose with or without fee is hereby granted, provided that the above 71573Srgrimes * copyright notice and this permission notice appear in all copies. 81573Srgrimes * 91573Srgrimes * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 101573Srgrimes * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 111573Srgrimes * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 121573Srgrimes * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 131573Srgrimes * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 141573Srgrimes * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 151573Srgrimes * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16148834Sstefanf * 171573Srgrimes * $FreeBSD: head/sys/dev/ath/ath_hal/ar9002/ar9280_attach.c 219441 2011-03-10 02:09:06Z adrian $ 181573Srgrimes */ 191573Srgrimes#include "opt_ah.h" 201573Srgrimes 211573Srgrimes#include "ah.h" 221573Srgrimes#include "ah_internal.h" 231573Srgrimes#include "ah_devid.h" 241573Srgrimes 251573Srgrimes#include "ah_eeprom_v14.h" /* XXX for tx/rx gain */ 261573Srgrimes 271573Srgrimes#include "ar9002/ar9280.h" 281573Srgrimes#include "ar5416/ar5416reg.h" 291573Srgrimes#include "ar5416/ar5416phy.h" 301573Srgrimes 3184260Sobrien#include "ar9002/ar9280v1.ini" 32237448Spfg#include "ar9002/ar9280v2.ini" 331573Srgrimes#include "ar9002/ar9280_olc.h" 341573Srgrimes 351573Srgrimesstatic const HAL_PERCAL_DATA ar9280_iq_cal = { /* single sample */ 3611678Sbde .calName = "IQ", .calType = IQ_MISMATCH_CAL, 371573Srgrimes .calNumSamples = MIN_CAL_SAMPLES, 3884260Sobrien .calCountMax = PER_MAX_LOG_COUNT, 3984260Sobrien .calCollect = ar5416IQCalCollect, 401573Srgrimes .calPostProc = ar5416IQCalibration 411573Srgrimes}; 421573Srgrimesstatic const HAL_PERCAL_DATA ar9280_adc_gain_cal = { /* single sample */ 431573Srgrimes .calName = "ADC Gain", .calType = ADC_GAIN_CAL, 441573Srgrimes .calNumSamples = MIN_CAL_SAMPLES, 451573Srgrimes .calCountMax = PER_MIN_LOG_COUNT, 461573Srgrimes .calCollect = ar5416AdcGainCalCollect, 471573Srgrimes .calPostProc = ar5416AdcGainCalibration 481573Srgrimes}; 491573Srgrimesstatic const HAL_PERCAL_DATA ar9280_adc_dc_cal = { /* single sample */ 501573Srgrimes .calName = "ADC DC", .calType = ADC_DC_CAL, 519898Sache .calNumSamples = MIN_CAL_SAMPLES, 52148834Sstefanf .calCountMax = PER_MIN_LOG_COUNT, 53148834Sstefanf .calCollect = ar5416AdcDcCalCollect, 54148834Sstefanf .calPostProc = ar5416AdcDcCalibration 551573Srgrimes}; 5617141Sjkhstatic const HAL_PERCAL_DATA ar9280_adc_init_dc_cal = { 571573Srgrimes .calName = "ADC Init DC", .calType = ADC_DC_INIT_CAL, 581573Srgrimes .calNumSamples = MIN_CAL_SAMPLES, 591573Srgrimes .calCountMax = INIT_LOG_COUNT, 601573Srgrimes .calCollect = ar5416AdcDcCalCollect, 611573Srgrimes .calPostProc = ar5416AdcDcCalibration 621573Srgrimes}; 631573Srgrimes 641573Srgrimesstatic void ar9280ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore); 651573Srgrimesstatic HAL_BOOL ar9280FillCapabilityInfo(struct ath_hal *ah); 661573Srgrimesstatic void ar9280WriteIni(struct ath_hal *ah, 6784260Sobrien const struct ieee80211_channel *chan); 681573Srgrimes 6984260Sobrienstatic void 7084260Sobrienar9280AniSetup(struct ath_hal *ah) 7184260Sobrien{ 7284260Sobrien /* 731573Srgrimes * These are the parameters from the AR5416 ANI code; 7484260Sobrien * they likely need quite a bit of adjustment for the 7584260Sobrien * AR9280. 7684260Sobrien */ 7784260Sobrien static const struct ar5212AniParams aniparams = { 7884260Sobrien .maxNoiseImmunityLevel = 4, /* levels 0..4 */ 7984260Sobrien .totalSizeDesired = { -55, -55, -55, -55, -62 }, 8084260Sobrien .coarseHigh = { -14, -14, -14, -14, -12 }, 8184260Sobrien .coarseLow = { -64, -64, -64, -64, -70 }, 8284260Sobrien .firpwr = { -78, -78, -78, -78, -80 }, 8384260Sobrien .maxSpurImmunityLevel = 2, 8484260Sobrien .cycPwrThr1 = { 2, 4, 6 }, 8584260Sobrien .maxFirstepLevel = 2, /* levels 0..2 */ 8684260Sobrien .firstep = { 0, 4, 8 }, 8784260Sobrien .ofdmTrigHigh = 500, 8884260Sobrien .ofdmTrigLow = 200, 8984260Sobrien .cckTrigHigh = 200, 9084260Sobrien .cckTrigLow = 100, 9184260Sobrien .rssiThrHigh = 40, 9284260Sobrien .rssiThrLow = 7, 9384260Sobrien .period = 100, 9484260Sobrien }; 9584260Sobrien /* NB: disable ANI noise immmunity for reliable RIFS rx */ 9684260Sobrien AH5416(ah)->ah_ani_function &= ~ HAL_ANI_NOISE_IMMUNITY_LEVEL; 9784260Sobrien 9884260Sobrien /* NB: ANI is not enabled yet */ 9984260Sobrien ar5416AniAttach(ah, &aniparams, &aniparams, AH_FALSE); 10084260Sobrien} 10184260Sobrien 10284260Sobrien/* 10384260Sobrien * Attach for an AR9280 part. 10484260Sobrien */ 10584260Sobrienstatic struct ath_hal * 10684260Sobrienar9280Attach(uint16_t devid, HAL_SOFTC sc, 10784260Sobrien HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata, 10884260Sobrien HAL_STATUS *status) 10984260Sobrien{ 11084260Sobrien struct ath_hal_9280 *ahp9280; 11184260Sobrien struct ath_hal_5212 *ahp; 11284260Sobrien struct ath_hal *ah; 11384260Sobrien uint32_t val; 11484260Sobrien HAL_STATUS ecode; 11584260Sobrien HAL_BOOL rfStatus; 11684260Sobrien int8_t pwr_table_offset; 11784260Sobrien uint8_t pwr; 11884260Sobrien 11984260Sobrien HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n", 12084260Sobrien __func__, sc, (void*) st, (void*) sh); 12184260Sobrien 12284260Sobrien /* NB: memory is returned zero'd */ 12384260Sobrien ahp9280 = ath_hal_malloc(sizeof (struct ath_hal_9280)); 12484260Sobrien if (ahp9280 == AH_NULL) { 12584260Sobrien HALDEBUG(AH_NULL, HAL_DEBUG_ANY, 12684260Sobrien "%s: cannot allocate memory for state block\n", __func__); 12784260Sobrien *status = HAL_ENOMEM; 12884260Sobrien return AH_NULL; 12984260Sobrien } 13084260Sobrien ahp = AH5212(ahp9280); 13184260Sobrien ah = &ahp->ah_priv.h; 13284260Sobrien 13384260Sobrien ar5416InitState(AH5416(ah), devid, sc, st, sh, status); 13484260Sobrien 13584260Sobrien /* XXX override with 9280 specific state */ 13684260Sobrien /* override 5416 methods for our needs */ 13784260Sobrien ah->ah_setAntennaSwitch = ar9280SetAntennaSwitch; 13884260Sobrien ah->ah_configPCIE = ar9280ConfigPCIE; 13984260Sobrien 14084260Sobrien AH5416(ah)->ah_cal.iqCalData.calData = &ar9280_iq_cal; 14184260Sobrien AH5416(ah)->ah_cal.adcGainCalData.calData = &ar9280_adc_gain_cal; 14284260Sobrien AH5416(ah)->ah_cal.adcDcCalData.calData = &ar9280_adc_dc_cal; 14384260Sobrien AH5416(ah)->ah_cal.adcDcCalInitData.calData = &ar9280_adc_init_dc_cal; 14484260Sobrien AH5416(ah)->ah_cal.suppCals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL; 14584260Sobrien 14684260Sobrien AH5416(ah)->ah_spurMitigate = ar9280SpurMitigate; 14784260Sobrien AH5416(ah)->ah_writeIni = ar9280WriteIni; 14884260Sobrien AH5416(ah)->ah_olcInit = ar9280olcInit; 1491573Srgrimes AH5416(ah)->ah_olcTempCompensation = ar9280olcTemperatureCompensation; 15084260Sobrien AH5416(ah)->ah_setPowerCalTable = ar9280SetPowerCalTable; 15184260Sobrien 15284260Sobrien AH5416(ah)->ah_rx_chainmask = AR9280_DEFAULT_RXCHAINMASK; 15384260Sobrien AH5416(ah)->ah_tx_chainmask = AR9280_DEFAULT_TXCHAINMASK; 15484260Sobrien 15584260Sobrien if (!ar5416SetResetReg(ah, HAL_RESET_POWER_ON)) { 15684260Sobrien /* reset chip */ 15784260Sobrien HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't reset chip\n", 15884260Sobrien __func__); 15984260Sobrien ecode = HAL_EIO; 16084260Sobrien goto bad; 16184260Sobrien } 1621573Srgrimes 16384260Sobrien if (!ar5416SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) { 1641573Srgrimes HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't wakeup chip\n", 16584260Sobrien __func__); 1661573Srgrimes ecode = HAL_EIO; 16784260Sobrien goto bad; 1681573Srgrimes } 16984260Sobrien /* Read Revisions from Chips before taking out of reset */ 1701573Srgrimes val = OS_REG_READ(ah, AR_SREV); 17184260Sobrien HALDEBUG(ah, HAL_DEBUG_ATTACH, 1721573Srgrimes "%s: ID 0x%x VERSION 0x%x TYPE 0x%x REVISION 0x%x\n", 17384260Sobrien __func__, MS(val, AR_XSREV_ID), MS(val, AR_XSREV_VERSION), 1741573Srgrimes MS(val, AR_XSREV_TYPE), MS(val, AR_XSREV_REVISION)); 17584260Sobrien /* NB: include chip type to differentiate from pre-Sowl versions */ 1761573Srgrimes AH_PRIVATE(ah)->ah_macVersion = 17784260Sobrien (val & AR_XSREV_VERSION) >> AR_XSREV_TYPE_S; 1788870Srgrimes AH_PRIVATE(ah)->ah_macRev = MS(val, AR_XSREV_REVISION); 17984260Sobrien AH_PRIVATE(ah)->ah_ispcie = (val & AR_XSREV_TYPE_HOST_MODE) == 0; 1801573Srgrimes 18184260Sobrien /* setup common ini data; rf backends handle remainder */ 1821573Srgrimes if (AR_SREV_MERLIN_20_OR_LATER(ah)) { 18384260Sobrien HAL_INI_INIT(&ahp->ah_ini_modes, ar9280Modes_v2, 6); 1841573Srgrimes HAL_INI_INIT(&ahp->ah_ini_common, ar9280Common_v2, 2); 18584260Sobrien HAL_INI_INIT(&AH5416(ah)->ah_ini_pcieserdes, 18684260Sobrien ar9280PciePhy_clkreq_always_on_L1_v2, 2); 18784260Sobrien HAL_INI_INIT(&ahp9280->ah_ini_xmodes, 18884260Sobrien ar9280Modes_fast_clock_v2, 3); 18984260Sobrien } else { 19084260Sobrien HAL_INI_INIT(&ahp->ah_ini_modes, ar9280Modes_v1, 6); 19184260Sobrien HAL_INI_INIT(&ahp->ah_ini_common, ar9280Common_v1, 2); 19284260Sobrien HAL_INI_INIT(&AH5416(ah)->ah_ini_pcieserdes, 19384260Sobrien ar9280PciePhy_v1, 2); 19484260Sobrien } 19584260Sobrien ar5416AttachPCIE(ah); 19684260Sobrien 19784260Sobrien ecode = ath_hal_v14EepromAttach(ah); 19884260Sobrien if (ecode != HAL_OK) 19984260Sobrien goto bad; 20084260Sobrien 20184260Sobrien if (!ar5416ChipReset(ah, AH_NULL)) { /* reset chip */ 20284260Sobrien HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__); 20384260Sobrien ecode = HAL_EIO; 20484260Sobrien goto bad; 20584260Sobrien } 20684260Sobrien 20784260Sobrien AH_PRIVATE(ah)->ah_phyRev = OS_REG_READ(ah, AR_PHY_CHIP_ID); 20884260Sobrien 20984260Sobrien if (!ar5212ChipTest(ah)) { 21084260Sobrien HALDEBUG(ah, HAL_DEBUG_ANY, "%s: hardware self-test failed\n", 21184260Sobrien __func__); 21284260Sobrien ecode = HAL_ESELFTEST; 21384260Sobrien goto bad; 21484260Sobrien } 21584260Sobrien 21684260Sobrien /* 21784260Sobrien * Set correct Baseband to analog shift 21884260Sobrien * setting to access analog chips. 21984260Sobrien */ 22084260Sobrien OS_REG_WRITE(ah, AR_PHY(0), 0x00000007); 22184260Sobrien 22284260Sobrien /* Read Radio Chip Rev Extract */ 22384260Sobrien AH_PRIVATE(ah)->ah_analog5GhzRev = ar5416GetRadioRev(ah); 22484260Sobrien switch (AH_PRIVATE(ah)->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR) { 22584260Sobrien case AR_RAD2133_SREV_MAJOR: /* Sowl: 2G/3x3 */ 226212235Sjilles case AR_RAD5133_SREV_MAJOR: /* Sowl: 2+5G/3x3 */ 227212235Sjilles break; 228212235Sjilles default: 22984260Sobrien if (AH_PRIVATE(ah)->ah_analog5GhzRev == 0) { 2301573Srgrimes AH_PRIVATE(ah)->ah_analog5GhzRev = 2311573Srgrimes AR_RAD5133_SREV_MAJOR; 23284260Sobrien break; 23384260Sobrien } 23484260Sobrien#ifdef AH_DEBUG 2351573Srgrimes HALDEBUG(ah, HAL_DEBUG_ANY, 23684260Sobrien "%s: 5G Radio Chip Rev 0x%02X is not supported by " 23784260Sobrien "this driver\n", __func__, 23884260Sobrien AH_PRIVATE(ah)->ah_analog5GhzRev); 23984260Sobrien ecode = HAL_ENOTSUPP; 24084260Sobrien goto bad; 24184260Sobrien#endif 24284260Sobrien } 24384260Sobrien rfStatus = ar9280RfAttach(ah, &ecode); 24484260Sobrien if (!rfStatus) { 24584260Sobrien HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RF setup failed, status %u\n", 24684260Sobrien __func__, ecode); 24784260Sobrien goto bad; 24884260Sobrien } 24984260Sobrien 25084260Sobrien /* Enable fixup for AR_AN_TOP2 if necessary */ 25184260Sobrien /* 25284260Sobrien * The v14 EEPROM layer returns HAL_EIO if PWDCLKIND isn't supported 25384260Sobrien * by the EEPROM version. 2541573Srgrimes * 2551573Srgrimes * ath9k checks the EEPROM minor version is >= 0x0a here, instead of 2561573Srgrimes * the abstracted EEPROM access layer. 25784260Sobrien */ 25884260Sobrien ecode = ath_hal_eepromGet(ah, AR_EEP_PWDCLKIND, &pwr); 25984260Sobrien if (AR_SREV_MERLIN_20_OR_LATER(ah) && ecode == HAL_OK && pwr == 0) { 26084260Sobrien printf("[ath] enabling AN_TOP2_FIXUP\n"); 261148834Sstefanf AH5416(ah)->ah_need_an_top2_fixup = 1; 26284260Sobrien } 26384260Sobrien 264237448Spfg /* 265237448Spfg * Check whether the power table offset isn't the default. 2661573Srgrimes * This can occur with eeprom minor V21 or greater on Merlin. 267237448Spfg */ 268237448Spfg (void) ath_hal_eepromGet(ah, AR_EEP_PWR_TABLE_OFFSET, &pwr_table_offset); 269237448Spfg if (pwr_table_offset != AR5416_PWR_TABLE_OFFSET_DB) { 270237448Spfg ath_hal_printf(ah, "ERROR: default pwr offset: %d dBm != EEPROM pwr offset: %d dBm\n", 2711573Srgrimes AR5416_PWR_TABLE_OFFSET_DB, (int) pwr_table_offset); 2721573Srgrimes ecode = HAL_ENOTSUPP; 2731573Srgrimes goto bad; 2741573Srgrimes } 2751573Srgrimes 2761573Srgrimes if (AR_SREV_MERLIN_20_OR_LATER(ah)) { 27784260Sobrien /* setup rxgain table */ 2781573Srgrimes switch (ath_hal_eepromGet(ah, AR_EEP_RXGAIN_TYPE, AH_NULL)) { 27984260Sobrien case AR5416_EEP_RXGAIN_13dB_BACKOFF: 28084260Sobrien HAL_INI_INIT(&ahp9280->ah_ini_rxgain, 28184260Sobrien ar9280Modes_backoff_13db_rxgain_v2, 6); 2821573Srgrimes break; 28384260Sobrien case AR5416_EEP_RXGAIN_23dB_BACKOFF: 28484260Sobrien HAL_INI_INIT(&ahp9280->ah_ini_rxgain, 28584260Sobrien ar9280Modes_backoff_23db_rxgain_v2, 6); 28684260Sobrien break; 28784260Sobrien case AR5416_EEP_RXGAIN_ORIG: 28884260Sobrien HAL_INI_INIT(&ahp9280->ah_ini_rxgain, 28984260Sobrien ar9280Modes_original_rxgain_v2, 6); 29084260Sobrien break; 2911573Srgrimes default: 29284260Sobrien HALASSERT(AH_FALSE); 29384260Sobrien goto bad; /* XXX ? try to continue */ 29484260Sobrien } 29584260Sobrien } 29684260Sobrien if (AR_SREV_MERLIN_20_OR_LATER(ah)) { 29784260Sobrien /* setp txgain table */ 29884260Sobrien switch (ath_hal_eepromGet(ah, AR_EEP_TXGAIN_TYPE, AH_NULL)) { 29984260Sobrien case AR5416_EEP_TXGAIN_HIGH_POWER: 3001573Srgrimes HAL_INI_INIT(&ahp9280->ah_ini_txgain, 3011573Srgrimes ar9280Modes_high_power_tx_gain_v2, 6); 3021573Srgrimes break; 30384260Sobrien case AR5416_EEP_TXGAIN_ORIG: 30484260Sobrien HAL_INI_INIT(&ahp9280->ah_ini_txgain, 30584260Sobrien ar9280Modes_original_tx_gain_v2, 6); 30684260Sobrien break; 30784260Sobrien default: 30884260Sobrien HALASSERT(AH_FALSE); 30984260Sobrien goto bad; /* XXX ? try to continue */ 31084260Sobrien } 31184260Sobrien } 31284260Sobrien 31384260Sobrien /* 31484260Sobrien * Got everything we need now to setup the capabilities. 3151573Srgrimes */ 3161573Srgrimes if (!ar9280FillCapabilityInfo(ah)) { 3171573Srgrimes ecode = HAL_EEREAD; 3181573Srgrimes goto bad; 3191573Srgrimes } 3201573Srgrimes 3211573Srgrimes ecode = ath_hal_eepromGet(ah, AR_EEP_MACADDR, ahp->ah_macaddr); 32284260Sobrien if (ecode != HAL_OK) { 3231573Srgrimes HALDEBUG(ah, HAL_DEBUG_ANY, 32484260Sobrien "%s: error getting mac address from EEPROM\n", __func__); 32584260Sobrien goto bad; 32684260Sobrien } 32784260Sobrien /* XXX How about the serial number ? */ 32884260Sobrien /* Read Reg Domain */ 32984260Sobrien AH_PRIVATE(ah)->ah_currentRD = 33084260Sobrien ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, AH_NULL); 33184260Sobrien 33284260Sobrien /* 33384260Sobrien * ah_miscMode is populated by ar5416FillCapabilityInfo() 33484260Sobrien * starting from griffin. Set here to make sure that 33584260Sobrien * AR_MISC_MODE_MIC_NEW_LOC_ENABLE is set before a GTK is 33684260Sobrien * placed into hardware. 33784260Sobrien */ 33884260Sobrien if (ahp->ah_miscMode != 0) 33984260Sobrien OS_REG_WRITE(ah, AR_MISC_MODE, ahp->ah_miscMode); 34084260Sobrien 34184260Sobrien ar9280AniSetup(ah); /* Anti Noise Immunity */ 34284260Sobrien 343238810Spfg /* Setup noise floor min/max/nominal values */ 34489735Sobrien AH5416(ah)->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_9280_2GHZ; 34584260Sobrien AH5416(ah)->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_9280_2GHZ; 3461573Srgrimes AH5416(ah)->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9280_2GHZ; 347148834Sstefanf AH5416(ah)->nf_5g.max = AR_PHY_CCA_MAX_GOOD_VAL_9280_5GHZ; 3481573Srgrimes AH5416(ah)->nf_5g.min = AR_PHY_CCA_MIN_GOOD_VAL_9280_5GHZ; 3491573Srgrimes AH5416(ah)->nf_5g.nominal = AR_PHY_CCA_NOM_VAL_9280_5GHZ; 3501573Srgrimes 3511573Srgrimes ar5416InitNfHistBuff(AH5416(ah)->ah_cal.nfCalHist); 35284260Sobrien 3531573Srgrimes HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n", __func__); 35484260Sobrien 35584260Sobrien return ah; 35684260Sobrienbad: 35784260Sobrien if (ah != AH_NULL) 35884260Sobrien ah->ah_detach(ah); 35984260Sobrien if (status) 36084260Sobrien *status = ecode; 36184260Sobrien return AH_NULL; 36284260Sobrien} 36384260Sobrien 364148834Sstefanfstatic void 365148834Sstefanfar9280ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore) 36684260Sobrien{ 3671573Srgrimes if (AH_PRIVATE(ah)->ah_ispcie && !restore) { 3681573Srgrimes ath_hal_ini_write(ah, &AH5416(ah)->ah_ini_pcieserdes, 1, 0); 3691573Srgrimes OS_DELAY(1000); 3701573Srgrimes OS_REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA); 3711573Srgrimes OS_REG_WRITE(ah, AR_WA, AR9280_WA_DEFAULT); 3721573Srgrimes } 3731573Srgrimes} 374148834Sstefanf 3751573Srgrimesstatic void 37684260Sobrienar9280WriteIni(struct ath_hal *ah, const struct ieee80211_channel *chan) 377237448Spfg{ 37884260Sobrien u_int modesIndex, freqIndex; 37984260Sobrien int regWrites = 0; 3801573Srgrimes int i; 38184260Sobrien const HAL_INI_ARRAY *ia; 38284260Sobrien 38384260Sobrien /* Setup the indices for the next set of register array writes */ 38484260Sobrien /* XXX Ignore 11n dynamic mode on the AR5416 for the moment */ 38584260Sobrien if (IEEE80211_IS_CHAN_2GHZ(chan)) { 3861573Srgrimes freqIndex = 2; 38784260Sobrien if (IEEE80211_IS_CHAN_HT40(chan)) 3881573Srgrimes modesIndex = 3; 38984260Sobrien else if (IEEE80211_IS_CHAN_108G(chan)) 39084260Sobrien modesIndex = 5; 39184260Sobrien else 39284260Sobrien modesIndex = 4; 393167457Sstefanf } else { 394167457Sstefanf freqIndex = 1; 39584260Sobrien if (IEEE80211_IS_CHAN_HT40(chan) || 39684260Sobrien IEEE80211_IS_CHAN_TURBO(chan)) 39784260Sobrien modesIndex = 2; 39884260Sobrien else 39984260Sobrien modesIndex = 1; 40084260Sobrien } 40184260Sobrien 40284260Sobrien /* Set correct Baseband to analog shift setting to access analog chips. */ 40384260Sobrien OS_REG_WRITE(ah, AR_PHY(0), 0x00000007); 404237448Spfg OS_REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC); 40584260Sobrien 40684260Sobrien /* 40784260Sobrien * This is unwound because at the moment, there's a requirement 40884260Sobrien * for Merlin (and later, perhaps) to have a specific bit fixed 40984260Sobrien * in the AR_AN_TOP2 register before writing it. 41084260Sobrien */ 41184260Sobrien ia = &AH5212(ah)->ah_ini_modes; 41284260Sobrien#if 0 41384260Sobrien regWrites = ath_hal_ini_write(ah, &AH5212(ah)->ah_ini_modes, 41484260Sobrien modesIndex, regWrites); 4151573Srgrimes#endif 41684260Sobrien HALASSERT(modesIndex < ia->cols); 41784260Sobrien for (i = 0; i < ia->rows; i++) { 41884260Sobrien uint32_t reg = HAL_INI_VAL(ia, i, 0); 41984260Sobrien uint32_t val = HAL_INI_VAL(ia, i, modesIndex); 42084260Sobrien 421237448Spfg if (reg == AR_AN_TOP2 && AH5416(ah)->ah_need_an_top2_fixup) 42284260Sobrien val &= ~AR_AN_TOP2_PWDCLKIND; 42384260Sobrien 42484260Sobrien OS_REG_WRITE(ah, reg, val); 42584260Sobrien 42684260Sobrien /* Analog shift register delay seems needed for Merlin - PR kern/154220 */ 42784260Sobrien if (reg >= 0x7800 && reg < 0x78a0) 42884260Sobrien OS_DELAY(100); 429237448Spfg 4301573Srgrimes DMA_YIELD(regWrites); 43184260Sobrien } 4321573Srgrimes 4331573Srgrimes if (AR_SREV_MERLIN_20_OR_LATER(ah)) { 4341573Srgrimes regWrites = ath_hal_ini_write(ah, &AH9280(ah)->ah_ini_rxgain, 4351573Srgrimes modesIndex, regWrites); 4361573Srgrimes regWrites = ath_hal_ini_write(ah, &AH9280(ah)->ah_ini_txgain, 43784260Sobrien modesIndex, regWrites); 43884260Sobrien } 4391573Srgrimes /* XXX Merlin 100us delay for shift registers */ 44084260Sobrien regWrites = ath_hal_ini_write(ah, &AH5212(ah)->ah_ini_common, 4411573Srgrimes 1, regWrites); 44284260Sobrien 4431573Srgrimes if (AR_SREV_MERLIN_20(ah) && IS_5GHZ_FAST_CLOCK_EN(ah, chan)) { 44484260Sobrien /* 5GHz channels w/ Fast Clock use different modal values */ 44584260Sobrien regWrites = ath_hal_ini_write(ah, &AH9280(ah)->ah_ini_xmodes, 4461573Srgrimes modesIndex, regWrites); 44784260Sobrien } 44884260Sobrien} 44984260Sobrien 45084260Sobrien#define AR_BASE_FREQ_2GHZ 2300 4511573Srgrimes#define AR_BASE_FREQ_5GHZ 4900 4521573Srgrimes#define AR_SPUR_FEEQ_BOUND_HT40 19 4531573Srgrimes#define AR_SPUR_FEEQ_BOUND_HT20 10 4541573Srgrimes 4551573Srgrimesvoid 45684260Sobrienar9280SpurMitigate(struct ath_hal *ah, const struct ieee80211_channel *chan) 45784260Sobrien{ 4581573Srgrimes static const int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8, 45984260Sobrien AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60 }; 46084260Sobrien static const int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10, 46184260Sobrien AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60 }; 4621573Srgrimes static int inc[4] = { 0, 100, 0, 0 }; 46384260Sobrien 46484260Sobrien int bb_spur = AR_NO_SPUR; 46584260Sobrien int freq; 46684260Sobrien int bin, cur_bin; 46784260Sobrien int bb_spur_off, spur_subchannel_sd; 468167457Sstefanf int spur_freq_sd; 469167457Sstefanf int spur_delta_phase; 470167457Sstefanf int denominator; 471167457Sstefanf int upper, lower, cur_vit_mask; 47284260Sobrien int tmp, newVal; 473167457Sstefanf int i; 47484260Sobrien CHAN_CENTERS centers; 47584260Sobrien 47684260Sobrien int8_t mask_m[123]; 4771573Srgrimes int8_t mask_p[123]; 47884260Sobrien int8_t mask_amt; 47984260Sobrien int tmp_mask; 48084260Sobrien int cur_bb_spur; 48184260Sobrien HAL_BOOL is2GHz = IEEE80211_IS_CHAN_2GHZ(chan); 48284260Sobrien 483167457Sstefanf OS_MEMZERO(&mask_m, sizeof(int8_t) * 123); 484167457Sstefanf OS_MEMZERO(&mask_p, sizeof(int8_t) * 123); 485167457Sstefanf 486167457Sstefanf ar5416GetChannelCenters(ah, chan, ¢ers); 48784260Sobrien freq = centers.synth_center; 488167457Sstefanf 48984260Sobrien /* 49084260Sobrien * Need to verify range +/- 9.38 for static ht20 and +/- 18.75 for ht40, 49184260Sobrien * otherwise spur is out-of-band and can be ignored. 49284260Sobrien */ 49384260Sobrien for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) { 4941573Srgrimes cur_bb_spur = ath_hal_getSpurChan(ah, i, is2GHz); 4951573Srgrimes /* Get actual spur freq in MHz from EEPROM read value */ 4961573Srgrimes if (is2GHz) { 4971573Srgrimes cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_2GHZ; 4981573Srgrimes } else { 4991573Srgrimes cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_5GHZ; 50084260Sobrien } 5011573Srgrimes 50284260Sobrien if (AR_NO_SPUR == cur_bb_spur) 50384260Sobrien break; 5041573Srgrimes cur_bb_spur = cur_bb_spur - freq; 50584260Sobrien 50684260Sobrien if (IEEE80211_IS_CHAN_HT40(chan)) { 50784260Sobrien if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT40) && 50884260Sobrien (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT40)) { 50984260Sobrien bb_spur = cur_bb_spur; 51084260Sobrien break; 51184260Sobrien } 51284260Sobrien } else if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT20) && 51384260Sobrien (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT20)) { 51484260Sobrien bb_spur = cur_bb_spur; 51584260Sobrien break; 51684260Sobrien } 51784260Sobrien } 51884260Sobrien 51984260Sobrien if (AR_NO_SPUR == bb_spur) { 5201573Srgrimes#if 1 5211573Srgrimes /* 5221573Srgrimes * MRC CCK can interfere with beacon detection and cause deaf/mute. 5231573Srgrimes * Disable MRC CCK for now. 5241573Srgrimes */ 5251573Srgrimes OS_REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK, AR_PHY_FORCE_CLKEN_CCK_MRC_MUX); 5261573Srgrimes#else 52784260Sobrien /* Enable MRC CCK if no spur is found in this channel. */ 5281573Srgrimes OS_REG_SET_BIT(ah, AR_PHY_FORCE_CLKEN_CCK, AR_PHY_FORCE_CLKEN_CCK_MRC_MUX); 52984260Sobrien#endif 5301573Srgrimes return; 53184260Sobrien } else { 53284260Sobrien /* 5331573Srgrimes * For Merlin, spur can break CCK MRC algorithm. Disable CCK MRC if spur 53484260Sobrien * is found in this channel. 5351573Srgrimes */ 53684260Sobrien OS_REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK, AR_PHY_FORCE_CLKEN_CCK_MRC_MUX); 53784260Sobrien } 5381573Srgrimes 53984260Sobrien bin = bb_spur * 320; 5401573Srgrimes 54184260Sobrien tmp = OS_REG_READ(ah, AR_PHY_TIMING_CTRL4_CHAIN(0)); 54284260Sobrien 54384260Sobrien newVal = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI | 54484260Sobrien AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER | 54584260Sobrien AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK | 54684260Sobrien AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK); 547237448Spfg OS_REG_WRITE(ah, AR_PHY_TIMING_CTRL4_CHAIN(0), newVal); 548237448Spfg 549237448Spfg newVal = (AR_PHY_SPUR_REG_MASK_RATE_CNTL | 550237448Spfg AR_PHY_SPUR_REG_ENABLE_MASK_PPM | 55184260Sobrien AR_PHY_SPUR_REG_MASK_RATE_SELECT | 55284260Sobrien AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI | 55384260Sobrien SM(AR5416_SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH)); 55484260Sobrien OS_REG_WRITE(ah, AR_PHY_SPUR_REG, newVal); 555237448Spfg 556237448Spfg /* Pick control or extn channel to cancel the spur */ 55784260Sobrien if (IEEE80211_IS_CHAN_HT40(chan)) { 55884260Sobrien if (bb_spur < 0) { 55984260Sobrien spur_subchannel_sd = 1; 560237448Spfg bb_spur_off = bb_spur + 10; 56184260Sobrien } else { 56284260Sobrien spur_subchannel_sd = 0; 56384260Sobrien bb_spur_off = bb_spur - 10; 56484260Sobrien } 56584260Sobrien } else { 56684260Sobrien spur_subchannel_sd = 0; 56784260Sobrien bb_spur_off = bb_spur; 568237448Spfg } 56984260Sobrien 57084260Sobrien /* 57184260Sobrien * spur_delta_phase = bb_spur/40 * 2**21 for static ht20, 572237448Spfg * /80 for dyn2040. 57384260Sobrien */ 5741573Srgrimes if (IEEE80211_IS_CHAN_HT40(chan)) 57584260Sobrien spur_delta_phase = ((bb_spur * 262144) / 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE; 57684260Sobrien else 5771573Srgrimes spur_delta_phase = ((bb_spur * 524288) / 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE; 5781573Srgrimes 5791573Srgrimes /* 5801573Srgrimes * in 11A mode the denominator of spur_freq_sd should be 40 and 5811573Srgrimes * it should be 44 in 11G 5821573Srgrimes */ 58384260Sobrien denominator = IEEE80211_IS_CHAN_2GHZ(chan) ? 44 : 40; 5841573Srgrimes spur_freq_sd = ((bb_spur_off * 2048) / denominator) & 0x3ff; 58584260Sobrien 5861573Srgrimes newVal = (AR_PHY_TIMING11_USE_SPUR_IN_AGC | 5871573Srgrimes SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) | 58884260Sobrien SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE)); 58984260Sobrien OS_REG_WRITE(ah, AR_PHY_TIMING11, newVal); 5901573Srgrimes 59184260Sobrien /* Choose to cancel between control and extension channels */ 5921573Srgrimes newVal = spur_subchannel_sd << AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S; 59384260Sobrien OS_REG_WRITE(ah, AR_PHY_SFCORR_EXT, newVal); 59484260Sobrien 5951573Srgrimes /* 59684260Sobrien * ============================================ 59784260Sobrien * Set Pilot and Channel Masks 59884260Sobrien * 599237448Spfg * pilot mask 1 [31:0] = +6..-26, no 0 bin 60084260Sobrien * pilot mask 2 [19:0] = +26..+7 60184260Sobrien * 60284260Sobrien * channel mask 1 [31:0] = +6..-26, no 0 bin 60384260Sobrien * channel mask 2 [19:0] = +26..+7 6041573Srgrimes */ 60584260Sobrien cur_bin = -6000; 60684260Sobrien upper = bin + 100; 607237448Spfg lower = bin - 100; 60884260Sobrien 60984260Sobrien for (i = 0; i < 4; i++) { 61084260Sobrien int pilot_mask = 0; 611237448Spfg int chan_mask = 0; 61284260Sobrien int bp = 0; 61384260Sobrien for (bp = 0; bp < 30; bp++) { 61484260Sobrien if ((cur_bin > lower) && (cur_bin < upper)) { 61584260Sobrien pilot_mask = pilot_mask | 0x1 << bp; 616237448Spfg chan_mask = chan_mask | 0x1 << bp; 61784260Sobrien } 61884260Sobrien cur_bin += 100; 61984260Sobrien } 620237448Spfg cur_bin += inc[i]; 62184260Sobrien OS_REG_WRITE(ah, pilot_mask_reg[i], pilot_mask); 622237448Spfg OS_REG_WRITE(ah, chan_mask_reg[i], chan_mask); 62384260Sobrien } 624237448Spfg 62584260Sobrien /* ================================================= 62684260Sobrien * viterbi mask 1 based on channel magnitude 62784260Sobrien * four levels 0-3 62884260Sobrien * - mask (-27 to 27) (reg 64,0x9900 to 67,0x990c) 62984260Sobrien * [1 2 2 1] for -9.6 or [1 2 1] for +16 63084260Sobrien * - enable_mask_ppm, all bins move with freq 63184260Sobrien * 63284260Sobrien * - mask_select, 8 bits for rates (reg 67,0x990c) 63384260Sobrien * - mask_rate_cntl, 8 bits for rates (reg 67,0x990c) 63484260Sobrien * choose which mask to use mask or mask2 635237448Spfg */ 636237448Spfg 637237448Spfg /* 6381573Srgrimes * viterbi mask 2 2nd set for per data rate puncturing 63984260Sobrien * four levels 0-3 64084260Sobrien * - mask_select, 8 bits for rates (reg 67) 64184260Sobrien * - mask (-27 to 27) (reg 98,0x9988 to 101,0x9994) 642237448Spfg * [1 2 2 1] for -9.6 or [1 2 1] for +16 643237448Spfg */ 64484260Sobrien cur_vit_mask = 6100; 64584260Sobrien upper = bin + 120; 64684260Sobrien lower = bin - 120; 64784260Sobrien 64884260Sobrien for (i = 0; i < 123; i++) { 64984260Sobrien if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) { 650148834Sstefanf if ((abs(cur_vit_mask - bin)) < 75) { 651148834Sstefanf mask_amt = 1; 65284260Sobrien } else { 65384260Sobrien mask_amt = 0; 654237448Spfg } 65584260Sobrien if (cur_vit_mask < 0) { 65684260Sobrien mask_m[abs(cur_vit_mask / 100)] = mask_amt; 65784260Sobrien } else { 65884260Sobrien mask_p[cur_vit_mask / 100] = mask_amt; 659237448Spfg } 66084260Sobrien } 6611573Srgrimes cur_vit_mask -= 100; 6621573Srgrimes } 66384260Sobrien 66484260Sobrien tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28) 6651573Srgrimes | (mask_m[48] << 26) | (mask_m[49] << 24) 6661573Srgrimes | (mask_m[50] << 22) | (mask_m[51] << 20) 6671573Srgrimes | (mask_m[52] << 18) | (mask_m[53] << 16) 6681573Srgrimes | (mask_m[54] << 14) | (mask_m[55] << 12) 6691573Srgrimes | (mask_m[56] << 10) | (mask_m[57] << 8) 6701573Srgrimes | (mask_m[58] << 6) | (mask_m[59] << 4) 671237448Spfg | (mask_m[60] << 2) | (mask_m[61] << 0); 6721573Srgrimes OS_REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask); 673237448Spfg OS_REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask); 674237448Spfg 6751573Srgrimes tmp_mask = (mask_m[31] << 28) 676237448Spfg | (mask_m[32] << 26) | (mask_m[33] << 24) 6771573Srgrimes | (mask_m[34] << 22) | (mask_m[35] << 20) 67884260Sobrien | (mask_m[36] << 18) | (mask_m[37] << 16) 67984260Sobrien | (mask_m[48] << 14) | (mask_m[39] << 12) 6801573Srgrimes | (mask_m[40] << 10) | (mask_m[41] << 8) 68184260Sobrien | (mask_m[42] << 6) | (mask_m[43] << 4) 68284260Sobrien | (mask_m[44] << 2) | (mask_m[45] << 0); 683237448Spfg OS_REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask); 68484260Sobrien OS_REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask); 685237448Spfg 68684260Sobrien tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28) 68784260Sobrien | (mask_m[18] << 26) | (mask_m[18] << 24) 6881573Srgrimes | (mask_m[20] << 22) | (mask_m[20] << 20) 68984260Sobrien | (mask_m[22] << 18) | (mask_m[22] << 16) 69084260Sobrien | (mask_m[24] << 14) | (mask_m[24] << 12) 69184260Sobrien | (mask_m[25] << 10) | (mask_m[26] << 8) 69284260Sobrien | (mask_m[27] << 6) | (mask_m[28] << 4) 69384260Sobrien | (mask_m[29] << 2) | (mask_m[30] << 0); 69484260Sobrien OS_REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask); 69584260Sobrien OS_REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask); 69684260Sobrien 69784260Sobrien tmp_mask = (mask_m[ 0] << 30) | (mask_m[ 1] << 28) 69884260Sobrien | (mask_m[ 2] << 26) | (mask_m[ 3] << 24) 69984260Sobrien | (mask_m[ 4] << 22) | (mask_m[ 5] << 20) 700237448Spfg | (mask_m[ 6] << 18) | (mask_m[ 7] << 16) 701237448Spfg | (mask_m[ 8] << 14) | (mask_m[ 9] << 12) 702237448Spfg | (mask_m[10] << 10) | (mask_m[11] << 8) 703237448Spfg | (mask_m[12] << 6) | (mask_m[13] << 4) 70484260Sobrien | (mask_m[14] << 2) | (mask_m[15] << 0); 70584260Sobrien OS_REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask); 706237448Spfg OS_REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask); 70784260Sobrien 70884260Sobrien tmp_mask = (mask_p[15] << 28) 7091573Srgrimes | (mask_p[14] << 26) | (mask_p[13] << 24) 7101573Srgrimes | (mask_p[12] << 22) | (mask_p[11] << 20) 7111573Srgrimes | (mask_p[10] << 18) | (mask_p[ 9] << 16) 7121573Srgrimes | (mask_p[ 8] << 14) | (mask_p[ 7] << 12) 7131573Srgrimes | (mask_p[ 6] << 10) | (mask_p[ 5] << 8) 7141573Srgrimes | (mask_p[ 4] << 6) | (mask_p[ 3] << 4) 71584260Sobrien | (mask_p[ 2] << 2) | (mask_p[ 1] << 0); 7161573Srgrimes OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask); 71784260Sobrien OS_REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask); 71884260Sobrien 7191573Srgrimes tmp_mask = (mask_p[30] << 28) 72084260Sobrien | (mask_p[29] << 26) | (mask_p[28] << 24) 7211573Srgrimes | (mask_p[27] << 22) | (mask_p[26] << 20) 72284260Sobrien | (mask_p[25] << 18) | (mask_p[24] << 16) 7231573Srgrimes | (mask_p[23] << 14) | (mask_p[22] << 12) 72484260Sobrien | (mask_p[21] << 10) | (mask_p[20] << 8) 72584260Sobrien | (mask_p[19] << 6) | (mask_p[18] << 4) 72684260Sobrien | (mask_p[17] << 2) | (mask_p[16] << 0); 7271573Srgrimes OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask); 72884260Sobrien OS_REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask); 72984260Sobrien 7301573Srgrimes tmp_mask = (mask_p[45] << 28) 73184260Sobrien | (mask_p[44] << 26) | (mask_p[43] << 24) 7321573Srgrimes | (mask_p[42] << 22) | (mask_p[41] << 20) 73384260Sobrien | (mask_p[40] << 18) | (mask_p[39] << 16) 73484260Sobrien | (mask_p[38] << 14) | (mask_p[37] << 12) 73584260Sobrien | (mask_p[36] << 10) | (mask_p[35] << 8) 736237448Spfg | (mask_p[34] << 6) | (mask_p[33] << 4) 73784260Sobrien | (mask_p[32] << 2) | (mask_p[31] << 0); 73884260Sobrien OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask); 73984260Sobrien OS_REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask); 740237448Spfg 7411573Srgrimes tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28) 74284260Sobrien | (mask_p[59] << 26) | (mask_p[58] << 24) 74384260Sobrien | (mask_p[57] << 22) | (mask_p[56] << 20) 744237448Spfg | (mask_p[55] << 18) | (mask_p[54] << 16) 7451573Srgrimes | (mask_p[53] << 14) | (mask_p[52] << 12) 74684260Sobrien | (mask_p[51] << 10) | (mask_p[50] << 8) 747237448Spfg | (mask_p[49] << 6) | (mask_p[48] << 4) 74884260Sobrien | (mask_p[47] << 2) | (mask_p[46] << 0); 7491573Srgrimes OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask); 7501573Srgrimes OS_REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask); 7511573Srgrimes} 7528870Srgrimes 7538870Srgrimes/* 7541573Srgrimes * Fill all software cached or static hardware state information. 7551573Srgrimes * Return failure if capabilities are to come from EEPROM and 75684260Sobrien * cannot be read. 7571573Srgrimes */ 75884260Sobrienstatic HAL_BOOL 75984260Sobrienar9280FillCapabilityInfo(struct ath_hal *ah) 76084260Sobrien{ 7611573Srgrimes HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps; 76284260Sobrien 7631573Srgrimes if (!ar5416FillCapabilityInfo(ah)) 76484260Sobrien return AH_FALSE; 76584260Sobrien pCap->halNumGpioPins = 10; 76684260Sobrien pCap->halWowSupport = AH_TRUE; 7671573Srgrimes pCap->halWowMatchPatternExact = AH_TRUE; 76884260Sobrien#if 0 76984260Sobrien pCap->halWowMatchPatternDword = AH_TRUE; 7701573Srgrimes#endif 77184260Sobrien /* AR9280 is a 2x2 stream device */ 7721573Srgrimes pCap->halTxStreams = 2; 77384260Sobrien pCap->halRxStreams = 2; 77484260Sobrien 77584260Sobrien pCap->halCSTSupport = AH_TRUE; 776237448Spfg pCap->halRifsRxSupport = AH_TRUE; 777237448Spfg pCap->halRifsTxSupport = AH_TRUE; 77884260Sobrien pCap->halRtsAggrLimit = 64*1024; /* 802.11n max */ 77984260Sobrien pCap->halExtChanDfsSupport = AH_TRUE; 78084260Sobrien#if 0 78184260Sobrien /* XXX bluetooth */ 782237448Spfg pCap->halBtCoexSupport = AH_TRUE; 7831573Srgrimes#endif 78484260Sobrien pCap->halAutoSleepSupport = AH_FALSE; /* XXX? */ 78584260Sobrien pCap->hal4kbSplitTransSupport = AH_FALSE; 786237448Spfg pCap->halRxStbcSupport = 1; 78784260Sobrien pCap->halTxStbcSupport = 1; 7881573Srgrimes 78984260Sobrien return AH_TRUE; 790237448Spfg} 7911573Srgrimes 792237448Spfg/* 79384260Sobrien * This has been disabled - having the HAL flip chainmasks on/off 79484260Sobrien * when attempting to implement 11n disrupts things. For now, just 79584260Sobrien * leave this flipped off and worry about implementing TX diversity 79684260Sobrien * for legacy and MCS0-7 when 11n is fully functioning. 797237448Spfg */ 7981573SrgrimesHAL_BOOL 799237448Spfgar9280SetAntennaSwitch(struct ath_hal *ah, HAL_ANT_SETTING settings) 8001573Srgrimes{ 80184260Sobrien#define ANTENNA0_CHAINMASK 0x1 8021573Srgrimes#define ANTENNA1_CHAINMASK 0x2 80384260Sobrien#if 0 804237448Spfg struct ath_hal_5416 *ahp = AH5416(ah); 80584260Sobrien 8061573Srgrimes /* Antenna selection is done by setting the tx/rx chainmasks approp. */ 80784260Sobrien switch (settings) { 80884260Sobrien case HAL_ANT_FIXED_A: 8091573Srgrimes /* Enable first antenna only */ 8101573Srgrimes ahp->ah_tx_chainmask = ANTENNA0_CHAINMASK; 8111573Srgrimes ahp->ah_rx_chainmask = ANTENNA0_CHAINMASK; 8128870Srgrimes break; 8131573Srgrimes case HAL_ANT_FIXED_B: 8141573Srgrimes /* Enable second antenna only, after checking capability */ 81584260Sobrien if (AH_PRIVATE(ah)->ah_caps.halTxChainMask > ANTENNA1_CHAINMASK) 8161573Srgrimes ahp->ah_tx_chainmask = ANTENNA1_CHAINMASK; 81784260Sobrien ahp->ah_rx_chainmask = ANTENNA1_CHAINMASK; 8181573Srgrimes break; 81984260Sobrien case HAL_ANT_VARIABLE: 820237448Spfg /* Restore original chainmask settings */ 82184260Sobrien /* XXX */ 82284260Sobrien ahp->ah_tx_chainmask = AR9280_DEFAULT_TXCHAINMASK; 823237448Spfg ahp->ah_rx_chainmask = AR9280_DEFAULT_RXCHAINMASK; 82484260Sobrien break; 82584260Sobrien } 82684260Sobrien 8271573Srgrimes HALDEBUG(ah, HAL_DEBUG_ANY, "%s: settings=%d, tx/rx chainmask=%d/%d\n", 8281573Srgrimes __func__, settings, ahp->ah_tx_chainmask, ahp->ah_rx_chainmask); 8291573Srgrimes 8308870Srgrimes#endif 8311573Srgrimes return AH_TRUE; 8321573Srgrimes#undef ANTENNA0_CHAINMASK 83384260Sobrien#undef ANTENNA1_CHAINMASK 8341573Srgrimes} 8351573Srgrimes 83684260Sobrienstatic const char* 83784260Sobrienar9280Probe(uint16_t vendorid, uint16_t devid) 838237448Spfg{ 83984260Sobrien if (vendorid == ATHEROS_VENDOR_ID && 840237448Spfg (devid == AR9280_DEVID_PCI || devid == AR9280_DEVID_PCIE)) 84184260Sobrien return "Atheros 9280"; 842237448Spfg return AH_NULL; 84384260Sobrien} 844237448SpfgAH_CHIP(AR9280, ar9280Probe, ar9280Attach); 845237448Spfg