ar9285_attach.c revision 235972
1190214Srpaulo/* 2190214Srpaulo * Copyright (c) 2008-2009 Sam Leffler, Errno Consulting 3190214Srpaulo * Copyright (c) 2008 Atheros Communications, Inc. 4190214Srpaulo * 5190214Srpaulo * Permission to use, copy, modify, and/or distribute this software for any 6190214Srpaulo * purpose with or without fee is hereby granted, provided that the above 7190214Srpaulo * copyright notice and this permission notice appear in all copies. 8190214Srpaulo * 9190214Srpaulo * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10190214Srpaulo * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11190214Srpaulo * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12190214Srpaulo * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13190214Srpaulo * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14190214Srpaulo * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15190214Srpaulo * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16190214Srpaulo * 17190214Srpaulo * $FreeBSD: head/sys/dev/ath/ath_hal/ar9002/ar9285_attach.c 235972 2012-05-25 05:01:27Z adrian $ 18190214Srpaulo */ 19190214Srpaulo#include "opt_ah.h" 20190214Srpaulo 21190214Srpaulo#include "ah.h" 22190214Srpaulo#include "ah_internal.h" 23190214Srpaulo#include "ah_devid.h" 24190214Srpaulo 25190214Srpaulo#include "ah_eeprom_v4k.h" /* XXX for tx/rx gain */ 26190214Srpaulo 27190214Srpaulo#include "ar9002/ar9280.h" 28190214Srpaulo#include "ar9002/ar9285.h" 29190214Srpaulo#include "ar5416/ar5416reg.h" 30190214Srpaulo#include "ar5416/ar5416phy.h" 31190214Srpaulo 32190214Srpaulo#include "ar9002/ar9285.ini" 33190214Srpaulo#include "ar9002/ar9285v2.ini" 34190214Srpaulo#include "ar9002/ar9280v2.ini" /* XXX ini for tx/rx gain */ 35190214Srpaulo 36190214Srpaulo#include "ar9002/ar9285_cal.h" 37190214Srpaulo#include "ar9002/ar9285_phy.h" 38190214Srpaulo#include "ar9002/ar9285_diversity.h" 39190214Srpaulo 40190214Srpaulostatic const HAL_PERCAL_DATA ar9280_iq_cal = { /* single sample */ 41190214Srpaulo .calName = "IQ", .calType = IQ_MISMATCH_CAL, 42190214Srpaulo .calNumSamples = MIN_CAL_SAMPLES, 43190214Srpaulo .calCountMax = PER_MAX_LOG_COUNT, 44190214Srpaulo .calCollect = ar5416IQCalCollect, 45190214Srpaulo .calPostProc = ar5416IQCalibration 46190214Srpaulo}; 47190214Srpaulostatic const HAL_PERCAL_DATA ar9280_adc_gain_cal = { /* single sample */ 48190214Srpaulo .calName = "ADC Gain", .calType = ADC_GAIN_CAL, 49190214Srpaulo .calNumSamples = MIN_CAL_SAMPLES, 50190214Srpaulo .calCountMax = PER_MIN_LOG_COUNT, 51190214Srpaulo .calCollect = ar5416AdcGainCalCollect, 52190214Srpaulo .calPostProc = ar5416AdcGainCalibration 53190214Srpaulo}; 54190214Srpaulostatic const HAL_PERCAL_DATA ar9280_adc_dc_cal = { /* single sample */ 55190214Srpaulo .calName = "ADC DC", .calType = ADC_DC_CAL, 56190214Srpaulo .calNumSamples = MIN_CAL_SAMPLES, 57190214Srpaulo .calCountMax = PER_MIN_LOG_COUNT, 58190214Srpaulo .calCollect = ar5416AdcDcCalCollect, 59214518Srpaulo .calPostProc = ar5416AdcDcCalibration 60235426Sdelphij}; 61235426Sdelphijstatic const HAL_PERCAL_DATA ar9280_adc_init_dc_cal = { 62235426Sdelphij .calName = "ADC Init DC", .calType = ADC_DC_INIT_CAL, 63235426Sdelphij .calNumSamples = MIN_CAL_SAMPLES, 64235426Sdelphij .calCountMax = INIT_LOG_COUNT, 65235426Sdelphij .calCollect = ar5416AdcDcCalCollect, 66235426Sdelphij .calPostProc = ar5416AdcDcCalibration 67214518Srpaulo}; 68235426Sdelphij 69190214Srpaulostatic void ar9285ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore, 70214518Srpaulo HAL_BOOL power_off); 71214518Srpaulostatic void ar9285DisablePCIE(struct ath_hal *ah); 72214518Srpaulostatic HAL_BOOL ar9285FillCapabilityInfo(struct ath_hal *ah); 73214518Srpaulostatic void ar9285WriteIni(struct ath_hal *ah, 74214518Srpaulo const struct ieee80211_channel *chan); 75190214Srpaulo 76190214Srpaulostatic void 77190214Srpauloar9285AniSetup(struct ath_hal *ah) 78190214Srpaulo{ 79190214Srpaulo /* 80190214Srpaulo * These are the parameters from the AR5416 ANI code; 81190214Srpaulo * they likely need quite a bit of adjustment for the 82190214Srpaulo * AR9285. 83190214Srpaulo */ 84190214Srpaulo static const struct ar5212AniParams aniparams = { 85190214Srpaulo .maxNoiseImmunityLevel = 4, /* levels 0..4 */ 86190214Srpaulo .totalSizeDesired = { -55, -55, -55, -55, -62 }, 87190214Srpaulo .coarseHigh = { -14, -14, -14, -14, -12 }, 88190214Srpaulo .coarseLow = { -64, -64, -64, -64, -70 }, 89190214Srpaulo .firpwr = { -78, -78, -78, -78, -80 }, 90190214Srpaulo .maxSpurImmunityLevel = 2, 91190214Srpaulo .cycPwrThr1 = { 2, 4, 6 }, 92190214Srpaulo .maxFirstepLevel = 2, /* levels 0..2 */ 93190214Srpaulo .firstep = { 0, 4, 8 }, 94190214Srpaulo .ofdmTrigHigh = 500, 95190214Srpaulo .ofdmTrigLow = 200, 96190214Srpaulo .cckTrigHigh = 200, 97190214Srpaulo .cckTrigLow = 100, 98190214Srpaulo .rssiThrHigh = 40, 99190214Srpaulo .rssiThrLow = 7, 100190214Srpaulo .period = 100, 101190214Srpaulo }; 102190214Srpaulo /* NB: disable ANI noise immmunity for reliable RIFS rx */ 103190214Srpaulo AH5416(ah)->ah_ani_function &= ~(1 << HAL_ANI_NOISE_IMMUNITY_LEVEL); 104190214Srpaulo 105190214Srpaulo ar5416AniAttach(ah, &aniparams, &aniparams, AH_TRUE); 106190214Srpaulo} 107190214Srpaulo 108190214Srpaulo/* 109190214Srpaulo * Attach for an AR9285 part. 110190214Srpaulo */ 111190214Srpaulostatic struct ath_hal * 112190214Srpauloar9285Attach(uint16_t devid, HAL_SOFTC sc, 113190214Srpaulo HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata, 114190214Srpaulo HAL_STATUS *status) 115190214Srpaulo{ 116190214Srpaulo struct ath_hal_9285 *ahp9285; 117190214Srpaulo struct ath_hal_5212 *ahp; 118190214Srpaulo struct ath_hal *ah; 119190214Srpaulo uint32_t val; 120276768Sdelphij HAL_STATUS ecode; 121276768Sdelphij HAL_BOOL rfStatus; 122276768Sdelphij 123276768Sdelphij HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n", 124276768Sdelphij __func__, sc, (void*) st, (void*) sh); 125276768Sdelphij 126276768Sdelphij /* NB: memory is returned zero'd */ 127276768Sdelphij ahp9285 = ath_hal_malloc(sizeof (struct ath_hal_9285)); 128276768Sdelphij if (ahp9285 == AH_NULL) { 129276768Sdelphij HALDEBUG(AH_NULL, HAL_DEBUG_ANY, 130190214Srpaulo "%s: cannot allocate memory for state block\n", __func__); 131190214Srpaulo *status = HAL_ENOMEM; 132190214Srpaulo return AH_NULL; 133190214Srpaulo } 134190214Srpaulo ahp = AH5212(ahp9285); 135190214Srpaulo ah = &ahp->ah_priv.h; 136190214Srpaulo 137190214Srpaulo ar5416InitState(AH5416(ah), devid, sc, st, sh, status); 138190214Srpaulo 139190214Srpaulo /* 140190214Srpaulo * Use the "local" EEPROM data given to us by the higher layers. 141190214Srpaulo * This is a private copy out of system flash. The Linux ath9k 142190214Srpaulo * commit for the initial AR9130 support mentions MMIO flash 143190214Srpaulo * access is "unreliable." -adrian 144190214Srpaulo */ 145190214Srpaulo if (eepromdata != AH_NULL) { 146190214Srpaulo AH_PRIVATE(ah)->ah_eepromRead = ath_hal_EepromDataRead; 147190214Srpaulo AH_PRIVATE(ah)->ah_eepromWrite = NULL; 148190214Srpaulo ah->ah_eepromdata = eepromdata; 149190214Srpaulo } 150190214Srpaulo 151190214Srpaulo /* XXX override with 9285 specific state */ 152190214Srpaulo /* override 5416 methods for our needs */ 153190214Srpaulo AH5416(ah)->ah_initPLL = ar9280InitPLL; 154190214Srpaulo 155190214Srpaulo ah->ah_setAntennaSwitch = ar9285SetAntennaSwitch; 156190214Srpaulo ah->ah_configPCIE = ar9285ConfigPCIE; 157251129Sdelphij ah->ah_disablePCIE = ar9285DisablePCIE; 158190214Srpaulo ah->ah_setTxPower = ar9285SetTransmitPower; 159190214Srpaulo ah->ah_setBoardValues = ar9285SetBoardValues; 160190214Srpaulo 161190214Srpaulo AH5416(ah)->ah_cal.iqCalData.calData = &ar9280_iq_cal; 162214518Srpaulo AH5416(ah)->ah_cal.adcGainCalData.calData = &ar9280_adc_gain_cal; 163214518Srpaulo AH5416(ah)->ah_cal.adcDcCalData.calData = &ar9280_adc_dc_cal; 164214518Srpaulo AH5416(ah)->ah_cal.adcDcCalInitData.calData = &ar9280_adc_init_dc_cal; 165190214Srpaulo AH5416(ah)->ah_cal.suppCals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL; 166214518Srpaulo 167214518Srpaulo AH5416(ah)->ah_spurMitigate = ar9280SpurMitigate; 168214518Srpaulo AH5416(ah)->ah_writeIni = ar9285WriteIni; 169214518Srpaulo AH5416(ah)->ah_rx_chainmask = AR9285_DEFAULT_RXCHAINMASK; 170214518Srpaulo AH5416(ah)->ah_tx_chainmask = AR9285_DEFAULT_TXCHAINMASK; 171190214Srpaulo 172214518Srpaulo ahp->ah_maxTxTrigLev = MAX_TX_FIFO_THRESHOLD >> 1; 173214518Srpaulo 174190214Srpaulo if (!ar5416SetResetReg(ah, HAL_RESET_POWER_ON)) { 175214518Srpaulo /* reset chip */ 176214518Srpaulo HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't reset chip\n", 177214518Srpaulo __func__); 178214518Srpaulo ecode = HAL_EIO; 179214518Srpaulo goto bad; 180214518Srpaulo } 181214518Srpaulo 182214518Srpaulo if (!ar5416SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) { 183190214Srpaulo HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't wakeup chip\n", 184190214Srpaulo __func__); 185214518Srpaulo ecode = HAL_EIO; 186214518Srpaulo goto bad; 187214518Srpaulo } 188214518Srpaulo /* Read Revisions from Chips before taking out of reset */ 189214518Srpaulo val = OS_REG_READ(ah, AR_SREV); 190214518Srpaulo HALDEBUG(ah, HAL_DEBUG_ATTACH, 191214518Srpaulo "%s: ID 0x%x VERSION 0x%x TYPE 0x%x REVISION 0x%x\n", 192214518Srpaulo __func__, MS(val, AR_XSREV_ID), MS(val, AR_XSREV_VERSION), 193214518Srpaulo MS(val, AR_XSREV_TYPE), MS(val, AR_XSREV_REVISION)); 194214518Srpaulo /* NB: include chip type to differentiate from pre-Sowl versions */ 195214518Srpaulo AH_PRIVATE(ah)->ah_macVersion = 196214518Srpaulo (val & AR_XSREV_VERSION) >> AR_XSREV_TYPE_S; 197214518Srpaulo AH_PRIVATE(ah)->ah_macRev = MS(val, AR_XSREV_REVISION); 198214518Srpaulo AH_PRIVATE(ah)->ah_ispcie = (val & AR_XSREV_TYPE_HOST_MODE) == 0; 199214518Srpaulo 200214518Srpaulo /* setup common ini data; rf backends handle remainder */ 201214518Srpaulo if (AR_SREV_KITE_12_OR_LATER(ah)) { 202214518Srpaulo HAL_INI_INIT(&ahp->ah_ini_modes, ar9285Modes_v2, 6); 203214518Srpaulo HAL_INI_INIT(&ahp->ah_ini_common, ar9285Common_v2, 2); 204214518Srpaulo HAL_INI_INIT(&AH5416(ah)->ah_ini_pcieserdes, 205214518Srpaulo ar9285PciePhy_clkreq_always_on_L1_v2, 2); 206214518Srpaulo } else { 207214518Srpaulo HAL_INI_INIT(&ahp->ah_ini_modes, ar9285Modes, 6); 208190214Srpaulo HAL_INI_INIT(&ahp->ah_ini_common, ar9285Common, 2); 209190214Srpaulo HAL_INI_INIT(&AH5416(ah)->ah_ini_pcieserdes, 210190214Srpaulo ar9285PciePhy_clkreq_always_on_L1, 2); 211190214Srpaulo } 212190214Srpaulo ar5416AttachPCIE(ah); 213276768Sdelphij 214190214Srpaulo /* Attach methods that require MAC version/revision info */ 215190214Srpaulo if (AR_SREV_KITE_12_OR_LATER(ah)) 216190214Srpaulo AH5416(ah)->ah_cal_initcal = ar9285InitCalHardware; 217190214Srpaulo if (AR_SREV_KITE_11_OR_LATER(ah)) 218276768Sdelphij AH5416(ah)->ah_cal_pacal = ar9002_hw_pa_cal; 219276768Sdelphij 220214518Srpaulo ecode = ath_hal_v4kEepromAttach(ah); 221276768Sdelphij if (ecode != HAL_OK) 222190214Srpaulo goto bad; 223190214Srpaulo 224276768Sdelphij if (!ar5416ChipReset(ah, AH_NULL)) { /* reset chip */ 225276768Sdelphij HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", 226214518Srpaulo __func__); 227214518Srpaulo ecode = HAL_EIO; 228214518Srpaulo goto bad; 229214518Srpaulo } 230214518Srpaulo 231214518Srpaulo AH_PRIVATE(ah)->ah_phyRev = OS_REG_READ(ah, AR_PHY_CHIP_ID); 232214518Srpaulo 233214518Srpaulo if (!ar5212ChipTest(ah)) { 234214518Srpaulo HALDEBUG(ah, HAL_DEBUG_ANY, "%s: hardware self-test failed\n", 235214518Srpaulo __func__); 236214518Srpaulo ecode = HAL_ESELFTEST; 237214518Srpaulo goto bad; 238214518Srpaulo } 239214518Srpaulo 240214518Srpaulo /* 241214518Srpaulo * Set correct Baseband to analog shift 242214518Srpaulo * setting to access analog chips. 243214518Srpaulo */ 244214518Srpaulo OS_REG_WRITE(ah, AR_PHY(0), 0x00000007); 245214518Srpaulo 246214518Srpaulo /* Read Radio Chip Rev Extract */ 247214518Srpaulo AH_PRIVATE(ah)->ah_analog5GhzRev = ar5416GetRadioRev(ah); 248214518Srpaulo switch (AH_PRIVATE(ah)->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR) { 249214518Srpaulo case AR_RAD2133_SREV_MAJOR: /* Sowl: 2G/3x3 */ 250214518Srpaulo case AR_RAD5133_SREV_MAJOR: /* Sowl: 2+5G/3x3 */ 251214518Srpaulo break; 252214518Srpaulo default: 253214518Srpaulo if (AH_PRIVATE(ah)->ah_analog5GhzRev == 0) { 254214518Srpaulo AH_PRIVATE(ah)->ah_analog5GhzRev = 255214518Srpaulo AR_RAD5133_SREV_MAJOR; 256214518Srpaulo break; 257214518Srpaulo } 258214518Srpaulo#ifdef AH_DEBUG 259214518Srpaulo HALDEBUG(ah, HAL_DEBUG_ANY, 260214518Srpaulo "%s: 5G Radio Chip Rev 0x%02X is not supported by " 261214518Srpaulo "this driver\n", __func__, 262214518Srpaulo AH_PRIVATE(ah)->ah_analog5GhzRev); 263214518Srpaulo ecode = HAL_ENOTSUPP; 264214518Srpaulo goto bad; 265214518Srpaulo#endif 266214518Srpaulo } 267214518Srpaulo rfStatus = ar9285RfAttach(ah, &ecode); 268214518Srpaulo if (!rfStatus) { 269214518Srpaulo HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RF setup failed, status %u\n", 270214518Srpaulo __func__, ecode); 271214518Srpaulo goto bad; 272214518Srpaulo } 273214518Srpaulo 274214518Srpaulo HAL_INI_INIT(&ahp9285->ah_ini_rxgain, ar9280Modes_original_rxgain_v2, 275214518Srpaulo 6); 276214518Srpaulo 277214518Srpaulo if (AR_SREV_9285E_20(ah)) 278214518Srpaulo ath_hal_printf(ah, "[ath] AR9285E_20 detected; using XE TX gain tables\n"); 279214518Srpaulo 280214518Srpaulo /* setup txgain table */ 281214518Srpaulo switch (ath_hal_eepromGet(ah, AR_EEP_TXGAIN_TYPE, AH_NULL)) { 282214518Srpaulo case AR5416_EEP_TXGAIN_HIGH_POWER: 283214518Srpaulo if (AR_SREV_9285E_20(ah)) 284214518Srpaulo HAL_INI_INIT(&ahp9285->ah_ini_txgain, 285214518Srpaulo ar9285Modes_XE2_0_high_power, 6); 286214518Srpaulo else 287214518Srpaulo HAL_INI_INIT(&ahp9285->ah_ini_txgain, 288214518Srpaulo ar9285Modes_high_power_tx_gain_v2, 6); 289214518Srpaulo break; 290214518Srpaulo case AR5416_EEP_TXGAIN_ORIG: 291214518Srpaulo if (AR_SREV_9285E_20(ah)) 292214518Srpaulo HAL_INI_INIT(&ahp9285->ah_ini_txgain, 293214518Srpaulo ar9285Modes_XE2_0_normal_power, 6); 294276768Sdelphij else 295214518Srpaulo HAL_INI_INIT(&ahp9285->ah_ini_txgain, 296190214Srpaulo ar9285Modes_original_tx_gain_v2, 6); 297251129Sdelphij break; 298190214Srpaulo default: 299251129Sdelphij HALASSERT(AH_FALSE); 300251129Sdelphij goto bad; /* XXX ? try to continue */ 301251129Sdelphij } 302190214Srpaulo 303190214Srpaulo /* 304251129Sdelphij * Got everything we need now to setup the capabilities. 305251129Sdelphij */ 306251129Sdelphij if (!ar9285FillCapabilityInfo(ah)) { 307251129Sdelphij ecode = HAL_EEREAD; 308251129Sdelphij goto bad; 309251129Sdelphij } 310251129Sdelphij 311251129Sdelphij /* Print out whether the EEPROM settings enable AR9285 diversity */ 312251129Sdelphij if (ar9285_check_div_comb(ah)) { 313251129Sdelphij ath_hal_printf(ah, "[ath] Enabling diversity for Kite\n"); 314251129Sdelphij ah->ah_rxAntCombDiversity = ar9285_ant_comb_scan; 315251129Sdelphij } 316251129Sdelphij 317251129Sdelphij /* Disable 11n for the AR2427 */ 318251129Sdelphij if (devid == AR2427_DEVID_PCIE) 319251129Sdelphij AH_PRIVATE(ah)->ah_caps.halHTSupport = AH_FALSE; 320251129Sdelphij 321251129Sdelphij ecode = ath_hal_eepromGet(ah, AR_EEP_MACADDR, ahp->ah_macaddr); 322251129Sdelphij if (ecode != HAL_OK) { 323251129Sdelphij HALDEBUG(ah, HAL_DEBUG_ANY, 324251129Sdelphij "%s: error getting mac address from EEPROM\n", __func__); 325251129Sdelphij goto bad; 326251129Sdelphij } 327251129Sdelphij /* XXX How about the serial number ? */ 328251129Sdelphij /* Read Reg Domain */ 329251129Sdelphij AH_PRIVATE(ah)->ah_currentRD = 330251129Sdelphij ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, AH_NULL); 331276768Sdelphij /* 332190214Srpaulo * For Kite and later chipsets, the following bits are not 333190214Srpaulo * programmed in EEPROM and so are set as enabled always. 334190214Srpaulo */ 335190214Srpaulo AH_PRIVATE(ah)->ah_currentRDext = AR9285_RDEXT_DEFAULT; 336190214Srpaulo 337190214Srpaulo /* 338190214Srpaulo * ah_miscMode is populated by ar5416FillCapabilityInfo() 339190214Srpaulo * starting from griffin. Set here to make sure that 340190214Srpaulo * AR_MISC_MODE_MIC_NEW_LOC_ENABLE is set before a GTK is 341190214Srpaulo * placed into hardware. 342276768Sdelphij */ 343190214Srpaulo if (ahp->ah_miscMode != 0) 344190214Srpaulo OS_REG_WRITE(ah, AR_MISC_MODE, OS_REG_READ(ah, AR_MISC_MODE) | ahp->ah_miscMode); 345190214Srpaulo 346190214Srpaulo ar9285AniSetup(ah); /* Anti Noise Immunity */ 347190214Srpaulo 348190214Srpaulo /* Setup noise floor min/max/nominal values */ 349190214Srpaulo AH5416(ah)->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_9285_2GHZ; 350190214Srpaulo AH5416(ah)->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_9285_2GHZ; 351235426Sdelphij AH5416(ah)->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9285_2GHZ; 352190214Srpaulo /* XXX no 5ghz values? */ 353190214Srpaulo 354190214Srpaulo ar5416InitNfHistBuff(AH5416(ah)->ah_cal.nfCalHist); 355190214Srpaulo 356190214Srpaulo HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n", __func__); 357190214Srpaulo 358276768Sdelphij return ah; 359190214Srpaulobad: 360190214Srpaulo if (ah != AH_NULL) 361190214Srpaulo ah->ah_detach(ah); 362190214Srpaulo if (status) 363190214Srpaulo *status = ecode; 364190214Srpaulo return AH_NULL; 365190214Srpaulo} 366276768Sdelphij 367190214Srpaulostatic void 368190214Srpauloar9285ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore, HAL_BOOL power_off) 369190214Srpaulo{ 370190214Srpaulo if (AH_PRIVATE(ah)->ah_ispcie && !restore) { 371190214Srpaulo ath_hal_ini_write(ah, &AH5416(ah)->ah_ini_pcieserdes, 1, 0); 372190214Srpaulo OS_DELAY(1000); 373190214Srpaulo OS_REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA); 374214518Srpaulo OS_REG_WRITE(ah, AR_WA, AR9285_WA_DEFAULT); 375190214Srpaulo } 376190214Srpaulo} 377190214Srpaulo 378190214Srpaulostatic void 379190214Srpauloar9285DisablePCIE(struct ath_hal *ah) 380214518Srpaulo{ 381190214Srpaulo /* XXX TODO */ 382190214Srpaulo} 383190214Srpaulo 384276768Sdelphijstatic void 385276768Sdelphijar9285WriteIni(struct ath_hal *ah, const struct ieee80211_channel *chan) 386276768Sdelphij{ 387190214Srpaulo u_int modesIndex, freqIndex; 388190214Srpaulo int regWrites = 0; 389190214Srpaulo 390190214Srpaulo /* Setup the indices for the next set of register array writes */ 391190214Srpaulo /* XXX Ignore 11n dynamic mode on the AR5416 for the moment */ 392190214Srpaulo freqIndex = 2; 393190214Srpaulo if (IEEE80211_IS_CHAN_HT40(chan)) 394190214Srpaulo modesIndex = 3; 395190214Srpaulo else if (IEEE80211_IS_CHAN_108G(chan)) 396190214Srpaulo modesIndex = 5; 397190214Srpaulo else 398190214Srpaulo modesIndex = 4; 399276768Sdelphij 400276768Sdelphij /* Set correct Baseband to analog shift setting to access analog chips. */ 401276768Sdelphij OS_REG_WRITE(ah, AR_PHY(0), 0x00000007); 402190214Srpaulo OS_REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC); 403190214Srpaulo regWrites = ath_hal_ini_write(ah, &AH5212(ah)->ah_ini_modes, 404190214Srpaulo modesIndex, regWrites); 405276768Sdelphij if (AR_SREV_KITE_12_OR_LATER(ah)) { 406190214Srpaulo regWrites = ath_hal_ini_write(ah, &AH9285(ah)->ah_ini_txgain, 407190214Srpaulo modesIndex, regWrites); 408190214Srpaulo } 409214518Srpaulo regWrites = ath_hal_ini_write(ah, &AH5212(ah)->ah_ini_common, 410214518Srpaulo 1, regWrites); 411214518Srpaulo} 412214518Srpaulo 413214518Srpaulo/* 414214518Srpaulo * Fill all software cached or static hardware state information. 415276768Sdelphij * Return failure if capabilities are to come from EEPROM and 416214518Srpaulo * cannot be read. 417214518Srpaulo */ 418214518Srpaulostatic HAL_BOOL 419214518Srpauloar9285FillCapabilityInfo(struct ath_hal *ah) 420214518Srpaulo{ 421214518Srpaulo HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps; 422214518Srpaulo 423214518Srpaulo if (!ar5416FillCapabilityInfo(ah)) 424190214Srpaulo return AH_FALSE; 425214518Srpaulo pCap->halNumGpioPins = 12; 426214518Srpaulo pCap->halWowSupport = AH_TRUE; 427214518Srpaulo pCap->halWowMatchPatternExact = AH_TRUE; 428214518Srpaulo#if 0 429214518Srpaulo pCap->halWowMatchPatternDword = AH_TRUE; 430214518Srpaulo#endif 431214518Srpaulo /* AR9285 has 2 antennas but is a 1x1 stream device */ 432214518Srpaulo pCap->halTxStreams = 1; 433214518Srpaulo pCap->halRxStreams = 1; 434190214Srpaulo 435190214Srpaulo pCap->halCSTSupport = AH_TRUE; 436190214Srpaulo pCap->halRifsRxSupport = AH_TRUE; 437190214Srpaulo pCap->halRifsTxSupport = AH_TRUE; 438190214Srpaulo pCap->halRtsAggrLimit = 64*1024; /* 802.11n max */ 439190214Srpaulo pCap->halExtChanDfsSupport = AH_TRUE; 440190214Srpaulo pCap->halUseCombinedRadarRssi = AH_TRUE; 441190214Srpaulo#if 0 442190214Srpaulo /* XXX bluetooth */ 443190214Srpaulo pCap->halBtCoexSupport = AH_TRUE; 444190214Srpaulo#endif 445190214Srpaulo pCap->halAutoSleepSupport = AH_FALSE; /* XXX? */ 446190214Srpaulo pCap->hal4kbSplitTransSupport = AH_FALSE; 447190214Srpaulo /* Disable this so Block-ACK works correctly */ 448190214Srpaulo pCap->halHasRxSelfLinkedTail = AH_FALSE; 449190214Srpaulo pCap->halMbssidAggrSupport = AH_TRUE; 450214518Srpaulo pCap->hal4AddrAggrSupport = AH_TRUE; 451190214Srpaulo 452190214Srpaulo if (AR_SREV_KITE_12_OR_LATER(ah)) 453190214Srpaulo pCap->halPSPollBroken = AH_FALSE; 454190214Srpaulo 455190214Srpaulo /* Only RX STBC supported */ 456190214Srpaulo pCap->halRxStbcSupport = 1; 457190214Srpaulo pCap->halTxStbcSupport = 0; 458190214Srpaulo 459190214Srpaulo return AH_TRUE; 460190214Srpaulo} 461190214Srpaulo 462190214Srpaulostatic const char* 463190214Srpauloar9285Probe(uint16_t vendorid, uint16_t devid) 464190214Srpaulo{ 465190214Srpaulo if (vendorid == ATHEROS_VENDOR_ID && devid == AR9285_DEVID_PCIE) 466190214Srpaulo return "Atheros 9285"; 467190214Srpaulo if (vendorid == ATHEROS_VENDOR_ID && (devid == AR2427_DEVID_PCIE)) 468190214Srpaulo return "Atheros 2427"; 469190214Srpaulo 470190214Srpaulo return AH_NULL; 471190214Srpaulo} 472190214SrpauloAH_CHIP(AR9285, ar9285Probe, ar9285Attach); 473190214Srpaulo