ar9285_attach.c revision 221694
1/* 2 * Copyright (c) 2008-2009 Sam Leffler, Errno Consulting 3 * Copyright (c) 2008 Atheros Communications, Inc. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 * 17 * $FreeBSD: head/sys/dev/ath/ath_hal/ar9002/ar9285_attach.c 221694 2011-05-09 15:19:49Z adrian $ 18 */ 19#include "opt_ah.h" 20 21#include "ah.h" 22#include "ah_internal.h" 23#include "ah_devid.h" 24 25#include "ah_eeprom_v4k.h" /* XXX for tx/rx gain */ 26 27#include "ar9002/ar9280.h" 28#include "ar9002/ar9285.h" 29#include "ar5416/ar5416reg.h" 30#include "ar5416/ar5416phy.h" 31 32#include "ar9002/ar9285.ini" 33#include "ar9002/ar9285v2.ini" 34#include "ar9002/ar9280v2.ini" /* XXX ini for tx/rx gain */ 35 36#include "ar9002/ar9285_cal.h" 37#include "ar9002/ar9285_phy.h" 38#include "ar9002/ar9285_diversity.h" 39 40static const HAL_PERCAL_DATA ar9280_iq_cal = { /* single sample */ 41 .calName = "IQ", .calType = IQ_MISMATCH_CAL, 42 .calNumSamples = MIN_CAL_SAMPLES, 43 .calCountMax = PER_MAX_LOG_COUNT, 44 .calCollect = ar5416IQCalCollect, 45 .calPostProc = ar5416IQCalibration 46}; 47static const HAL_PERCAL_DATA ar9280_adc_gain_cal = { /* single sample */ 48 .calName = "ADC Gain", .calType = ADC_GAIN_CAL, 49 .calNumSamples = MIN_CAL_SAMPLES, 50 .calCountMax = PER_MIN_LOG_COUNT, 51 .calCollect = ar5416AdcGainCalCollect, 52 .calPostProc = ar5416AdcGainCalibration 53}; 54static const HAL_PERCAL_DATA ar9280_adc_dc_cal = { /* single sample */ 55 .calName = "ADC DC", .calType = ADC_DC_CAL, 56 .calNumSamples = MIN_CAL_SAMPLES, 57 .calCountMax = PER_MIN_LOG_COUNT, 58 .calCollect = ar5416AdcDcCalCollect, 59 .calPostProc = ar5416AdcDcCalibration 60}; 61static const HAL_PERCAL_DATA ar9280_adc_init_dc_cal = { 62 .calName = "ADC Init DC", .calType = ADC_DC_INIT_CAL, 63 .calNumSamples = MIN_CAL_SAMPLES, 64 .calCountMax = INIT_LOG_COUNT, 65 .calCollect = ar5416AdcDcCalCollect, 66 .calPostProc = ar5416AdcDcCalibration 67}; 68 69static void ar9285ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore); 70static HAL_BOOL ar9285FillCapabilityInfo(struct ath_hal *ah); 71static void ar9285WriteIni(struct ath_hal *ah, 72 const struct ieee80211_channel *chan); 73 74static void 75ar9285AniSetup(struct ath_hal *ah) 76{ 77 /* NB: disable ANI for reliable RIFS rx */ 78 ar5416AniAttach(ah, AH_NULL, AH_NULL, AH_FALSE); 79} 80 81/* 82 * Attach for an AR9285 part. 83 */ 84static struct ath_hal * 85ar9285Attach(uint16_t devid, HAL_SOFTC sc, 86 HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata, 87 HAL_STATUS *status) 88{ 89 struct ath_hal_9285 *ahp9285; 90 struct ath_hal_5212 *ahp; 91 struct ath_hal *ah; 92 uint32_t val; 93 HAL_STATUS ecode; 94 HAL_BOOL rfStatus; 95 96 HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n", 97 __func__, sc, (void*) st, (void*) sh); 98 99 /* NB: memory is returned zero'd */ 100 ahp9285 = ath_hal_malloc(sizeof (struct ath_hal_9285)); 101 if (ahp9285 == AH_NULL) { 102 HALDEBUG(AH_NULL, HAL_DEBUG_ANY, 103 "%s: cannot allocate memory for state block\n", __func__); 104 *status = HAL_ENOMEM; 105 return AH_NULL; 106 } 107 ahp = AH5212(ahp9285); 108 ah = &ahp->ah_priv.h; 109 110 ar5416InitState(AH5416(ah), devid, sc, st, sh, status); 111 112 /* XXX override with 9285 specific state */ 113 /* override 5416 methods for our needs */ 114 ah->ah_setAntennaSwitch = ar9285SetAntennaSwitch; 115 ah->ah_configPCIE = ar9285ConfigPCIE; 116 ah->ah_setTxPower = ar9285SetTransmitPower; 117 ah->ah_setBoardValues = ar9285SetBoardValues; 118 119 AH5416(ah)->ah_cal.iqCalData.calData = &ar9280_iq_cal; 120 AH5416(ah)->ah_cal.adcGainCalData.calData = &ar9280_adc_gain_cal; 121 AH5416(ah)->ah_cal.adcDcCalData.calData = &ar9280_adc_dc_cal; 122 AH5416(ah)->ah_cal.adcDcCalInitData.calData = &ar9280_adc_init_dc_cal; 123 AH5416(ah)->ah_cal.suppCals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL; 124 125 if (AR_SREV_KITE_12_OR_LATER(ah)) 126 AH5416(ah)->ah_cal_initcal = ar9285InitCalHardware; 127 AH5416(ah)->ah_cal_pacal = ar9002_hw_pa_cal; 128 129 AH5416(ah)->ah_spurMitigate = ar9280SpurMitigate; 130 AH5416(ah)->ah_writeIni = ar9285WriteIni; 131 AH5416(ah)->ah_rx_chainmask = AR9285_DEFAULT_RXCHAINMASK; 132 AH5416(ah)->ah_tx_chainmask = AR9285_DEFAULT_TXCHAINMASK; 133 134 ahp->ah_maxTxTrigLev = MAX_TX_FIFO_THRESHOLD >> 1; 135 136 if (!ar5416SetResetReg(ah, HAL_RESET_POWER_ON)) { 137 /* reset chip */ 138 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't reset chip\n", 139 __func__); 140 ecode = HAL_EIO; 141 goto bad; 142 } 143 144 if (!ar5416SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) { 145 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't wakeup chip\n", 146 __func__); 147 ecode = HAL_EIO; 148 goto bad; 149 } 150 /* Read Revisions from Chips before taking out of reset */ 151 val = OS_REG_READ(ah, AR_SREV); 152 HALDEBUG(ah, HAL_DEBUG_ATTACH, 153 "%s: ID 0x%x VERSION 0x%x TYPE 0x%x REVISION 0x%x\n", 154 __func__, MS(val, AR_XSREV_ID), MS(val, AR_XSREV_VERSION), 155 MS(val, AR_XSREV_TYPE), MS(val, AR_XSREV_REVISION)); 156 /* NB: include chip type to differentiate from pre-Sowl versions */ 157 AH_PRIVATE(ah)->ah_macVersion = 158 (val & AR_XSREV_VERSION) >> AR_XSREV_TYPE_S; 159 AH_PRIVATE(ah)->ah_macRev = MS(val, AR_XSREV_REVISION); 160 AH_PRIVATE(ah)->ah_ispcie = (val & AR_XSREV_TYPE_HOST_MODE) == 0; 161 162 /* setup common ini data; rf backends handle remainder */ 163 if (AR_SREV_KITE_12_OR_LATER(ah)) { 164 HAL_INI_INIT(&ahp->ah_ini_modes, ar9285Modes_v2, 6); 165 HAL_INI_INIT(&ahp->ah_ini_common, ar9285Common_v2, 2); 166 HAL_INI_INIT(&AH5416(ah)->ah_ini_pcieserdes, 167 ar9285PciePhy_clkreq_always_on_L1_v2, 2); 168 } else { 169 HAL_INI_INIT(&ahp->ah_ini_modes, ar9285Modes, 6); 170 HAL_INI_INIT(&ahp->ah_ini_common, ar9285Common, 2); 171 HAL_INI_INIT(&AH5416(ah)->ah_ini_pcieserdes, 172 ar9285PciePhy_clkreq_always_on_L1, 2); 173 } 174 ar5416AttachPCIE(ah); 175 176 ecode = ath_hal_v4kEepromAttach(ah); 177 if (ecode != HAL_OK) 178 goto bad; 179 180 if (!ar5416ChipReset(ah, AH_NULL)) { /* reset chip */ 181 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", 182 __func__); 183 ecode = HAL_EIO; 184 goto bad; 185 } 186 187 AH_PRIVATE(ah)->ah_phyRev = OS_REG_READ(ah, AR_PHY_CHIP_ID); 188 189 if (!ar5212ChipTest(ah)) { 190 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: hardware self-test failed\n", 191 __func__); 192 ecode = HAL_ESELFTEST; 193 goto bad; 194 } 195 196 /* 197 * Set correct Baseband to analog shift 198 * setting to access analog chips. 199 */ 200 OS_REG_WRITE(ah, AR_PHY(0), 0x00000007); 201 202 /* Read Radio Chip Rev Extract */ 203 AH_PRIVATE(ah)->ah_analog5GhzRev = ar5416GetRadioRev(ah); 204 switch (AH_PRIVATE(ah)->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR) { 205 case AR_RAD2133_SREV_MAJOR: /* Sowl: 2G/3x3 */ 206 case AR_RAD5133_SREV_MAJOR: /* Sowl: 2+5G/3x3 */ 207 break; 208 default: 209 if (AH_PRIVATE(ah)->ah_analog5GhzRev == 0) { 210 AH_PRIVATE(ah)->ah_analog5GhzRev = 211 AR_RAD5133_SREV_MAJOR; 212 break; 213 } 214#ifdef AH_DEBUG 215 HALDEBUG(ah, HAL_DEBUG_ANY, 216 "%s: 5G Radio Chip Rev 0x%02X is not supported by " 217 "this driver\n", __func__, 218 AH_PRIVATE(ah)->ah_analog5GhzRev); 219 ecode = HAL_ENOTSUPP; 220 goto bad; 221#endif 222 } 223 rfStatus = ar9285RfAttach(ah, &ecode); 224 if (!rfStatus) { 225 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RF setup failed, status %u\n", 226 __func__, ecode); 227 goto bad; 228 } 229 230 HAL_INI_INIT(&ahp9285->ah_ini_rxgain, ar9280Modes_original_rxgain_v2, 231 6); 232 233 if (AR_SREV_9285E_20(ah)) 234 ath_hal_printf(ah, "[ath] AR9285E_20 detected; using XE TX gain tables\n"); 235 236 /* setup txgain table */ 237 switch (ath_hal_eepromGet(ah, AR_EEP_TXGAIN_TYPE, AH_NULL)) { 238 case AR5416_EEP_TXGAIN_HIGH_POWER: 239 if (AR_SREV_9285E_20(ah)) 240 HAL_INI_INIT(&ahp9285->ah_ini_txgain, 241 ar9285Modes_XE2_0_high_power, 6); 242 else 243 HAL_INI_INIT(&ahp9285->ah_ini_txgain, 244 ar9285Modes_high_power_tx_gain_v2, 6); 245 break; 246 case AR5416_EEP_TXGAIN_ORIG: 247 if (AR_SREV_9285E_20(ah)) 248 HAL_INI_INIT(&ahp9285->ah_ini_txgain, 249 ar9285Modes_XE2_0_normal_power, 6); 250 else 251 HAL_INI_INIT(&ahp9285->ah_ini_txgain, 252 ar9285Modes_original_tx_gain_v2, 6); 253 break; 254 default: 255 HALASSERT(AH_FALSE); 256 goto bad; /* XXX ? try to continue */ 257 } 258 259 /* 260 * Got everything we need now to setup the capabilities. 261 */ 262 if (!ar9285FillCapabilityInfo(ah)) { 263 ecode = HAL_EEREAD; 264 goto bad; 265 } 266 267 /* Print out whether the EEPROM settings enable AR9285 diversity */ 268 if (ar9285_check_div_comb(ah)) { 269 ath_hal_printf(ah, "[ath] Enabling diversity for Kite\n"); 270 ah->ah_rxAntCombDiversity = ar9285_ant_comb_scan; 271 } 272 273 /* Disable 11n for the AR2427 */ 274 if (devid == AR2427_DEVID_PCIE) 275 AH_PRIVATE(ah)->ah_caps.halHTSupport = AH_FALSE; 276 277 ecode = ath_hal_eepromGet(ah, AR_EEP_MACADDR, ahp->ah_macaddr); 278 if (ecode != HAL_OK) { 279 HALDEBUG(ah, HAL_DEBUG_ANY, 280 "%s: error getting mac address from EEPROM\n", __func__); 281 goto bad; 282 } 283 /* XXX How about the serial number ? */ 284 /* Read Reg Domain */ 285 AH_PRIVATE(ah)->ah_currentRD = 286 ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, AH_NULL); 287 /* 288 * For Kite and later chipsets, the following bits are not 289 * programmed in EEPROM and so are set as enabled always. 290 */ 291 AH_PRIVATE(ah)->ah_currentRDext = AR9285_RDEXT_DEFAULT; 292 293 /* 294 * ah_miscMode is populated by ar5416FillCapabilityInfo() 295 * starting from griffin. Set here to make sure that 296 * AR_MISC_MODE_MIC_NEW_LOC_ENABLE is set before a GTK is 297 * placed into hardware. 298 */ 299 if (ahp->ah_miscMode != 0) 300 OS_REG_WRITE(ah, AR_MISC_MODE, OS_REG_READ(ah, AR_MISC_MODE) | ahp->ah_miscMode); 301 302 ar9285AniSetup(ah); /* Anti Noise Immunity */ 303 304 /* Setup noise floor min/max/nominal values */ 305 AH5416(ah)->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_9285_2GHZ; 306 AH5416(ah)->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_9285_2GHZ; 307 AH5416(ah)->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9285_2GHZ; 308 /* XXX no 5ghz values? */ 309 310 ar5416InitNfHistBuff(AH5416(ah)->ah_cal.nfCalHist); 311 312 HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n", __func__); 313 314 return ah; 315bad: 316 if (ah != AH_NULL) 317 ah->ah_detach(ah); 318 if (status) 319 *status = ecode; 320 return AH_NULL; 321} 322 323static void 324ar9285ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore) 325{ 326 if (AH_PRIVATE(ah)->ah_ispcie && !restore) { 327 ath_hal_ini_write(ah, &AH5416(ah)->ah_ini_pcieserdes, 1, 0); 328 OS_DELAY(1000); 329 OS_REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA); 330 OS_REG_WRITE(ah, AR_WA, AR9285_WA_DEFAULT); 331 } 332} 333 334static void 335ar9285WriteIni(struct ath_hal *ah, const struct ieee80211_channel *chan) 336{ 337 u_int modesIndex, freqIndex; 338 int regWrites = 0; 339 340 /* Setup the indices for the next set of register array writes */ 341 /* XXX Ignore 11n dynamic mode on the AR5416 for the moment */ 342 freqIndex = 2; 343 if (IEEE80211_IS_CHAN_HT40(chan)) 344 modesIndex = 3; 345 else if (IEEE80211_IS_CHAN_108G(chan)) 346 modesIndex = 5; 347 else 348 modesIndex = 4; 349 350 /* Set correct Baseband to analog shift setting to access analog chips. */ 351 OS_REG_WRITE(ah, AR_PHY(0), 0x00000007); 352 OS_REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC); 353 regWrites = ath_hal_ini_write(ah, &AH5212(ah)->ah_ini_modes, 354 modesIndex, regWrites); 355 if (AR_SREV_KITE_12_OR_LATER(ah)) { 356 regWrites = ath_hal_ini_write(ah, &AH9285(ah)->ah_ini_txgain, 357 modesIndex, regWrites); 358 } 359 regWrites = ath_hal_ini_write(ah, &AH5212(ah)->ah_ini_common, 360 1, regWrites); 361} 362 363/* 364 * Fill all software cached or static hardware state information. 365 * Return failure if capabilities are to come from EEPROM and 366 * cannot be read. 367 */ 368static HAL_BOOL 369ar9285FillCapabilityInfo(struct ath_hal *ah) 370{ 371 HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps; 372 373 if (!ar5416FillCapabilityInfo(ah)) 374 return AH_FALSE; 375 pCap->halNumGpioPins = 12; 376 pCap->halWowSupport = AH_TRUE; 377 pCap->halWowMatchPatternExact = AH_TRUE; 378#if 0 379 pCap->halWowMatchPatternDword = AH_TRUE; 380#endif 381 /* AR9285 has 2 antennas but is a 1x1 stream device */ 382 pCap->halTxStreams = 1; 383 pCap->halRxStreams = 1; 384 385 pCap->halCSTSupport = AH_TRUE; 386 pCap->halRifsRxSupport = AH_TRUE; 387 pCap->halRifsTxSupport = AH_TRUE; 388 pCap->halRtsAggrLimit = 64*1024; /* 802.11n max */ 389 pCap->halExtChanDfsSupport = AH_TRUE; 390#if 0 391 /* XXX bluetooth */ 392 pCap->halBtCoexSupport = AH_TRUE; 393#endif 394 pCap->halAutoSleepSupport = AH_FALSE; /* XXX? */ 395 pCap->hal4kbSplitTransSupport = AH_FALSE; 396 /* Disable this so Block-ACK works correctly */ 397 pCap->halHasRxSelfLinkedTail = AH_FALSE; 398 pCap->halMbssidAggrSupport = AH_TRUE; 399 pCap->hal4AddrAggrSupport = AH_TRUE; 400 401 if (AR_SREV_KITE_12_OR_LATER(ah)) 402 pCap->halPSPollBroken = AH_FALSE; 403 404 pCap->halRxStbcSupport = 1; 405 pCap->halTxStbcSupport = 1; 406 407 return AH_TRUE; 408} 409 410static const char* 411ar9285Probe(uint16_t vendorid, uint16_t devid) 412{ 413 if (vendorid == ATHEROS_VENDOR_ID && devid == AR9285_DEVID_PCIE) 414 return "Atheros 9285"; 415 if (vendorid == ATHEROS_VENDOR_ID && (devid == AR2427_DEVID_PCIE)) 416 return "Atheros 2427"; 417 418 return AH_NULL; 419} 420AH_CHIP(AR9285, ar9285Probe, ar9285Attach); 421