ar9130_attach.c revision 272292
152419Sjulian/* 252419Sjulian * Copyright (c) 2011 Adrian Chadd, Xenion Pty Ltd 352419Sjulian * Copyright (c) 2008 Sam Leffler, Errno Consulting 452419Sjulian * Copyright (c) 2008 Atheros Communications, Inc. 552419Sjulian * 652419Sjulian * Permission to use, copy, modify, and/or distribute this software for any 752419Sjulian * purpose with or without fee is hereby granted, provided that the above 852419Sjulian * copyright notice and this permission notice appear in all copies. 952419Sjulian * 1052419Sjulian * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 1152419Sjulian * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1252419Sjulian * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 1352419Sjulian * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1452419Sjulian * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1552419Sjulian * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 1652419Sjulian * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1752419Sjulian * 1852419Sjulian * $FreeBSD: head/sys/dev/ath/ath_hal/ar9001/ar9130_attach.c 272292 2014-09-30 03:19:29Z adrian $ 1952419Sjulian */ 2052419Sjulian#include "opt_ah.h" 2152419Sjulian 2252419Sjulian#include "ah.h" 2352419Sjulian#include "ah_internal.h" 2452419Sjulian#include "ah_devid.h" 2552419Sjulian 2652419Sjulian#include "ar5416/ar5416.h" 2752419Sjulian#include "ar5416/ar5416reg.h" 2852419Sjulian#include "ar5416/ar5416phy.h" 2952419Sjulian 3052419Sjulian#include "ar9001/ar9130reg.h" 3152419Sjulian#include "ar9001/ar9130_phy.h" 3252419Sjulian#include "ar9001/ar9130_eeprom.h" 3352419Sjulian 3452419Sjulian#include "ar9001/ar9130.ini" 3552419Sjulian 3652419Sjulianstatic const HAL_PERCAL_DATA ar9130_iq_cal = { /* multi sample */ 3767506Sjulian .calName = "IQ", .calType = IQ_MISMATCH_CAL, 3852419Sjulian .calNumSamples = MAX_CAL_SAMPLES, 3952419Sjulian .calCountMax = PER_MIN_LOG_COUNT, 4052752Sjulian .calCollect = ar5416IQCalCollect, 4152419Sjulian .calPostProc = ar5416IQCalibration 4252419Sjulian}; 4352419Sjulianstatic const HAL_PERCAL_DATA ar9130_adc_gain_cal = { /* multi sample */ 4452419Sjulian .calName = "ADC Gain", .calType = ADC_GAIN_CAL, 4552419Sjulian .calNumSamples = MAX_CAL_SAMPLES, 4652419Sjulian .calCountMax = PER_MIN_LOG_COUNT, 4752419Sjulian .calCollect = ar5416AdcGainCalCollect, 4853997Sarchie .calPostProc = ar5416AdcGainCalibration 4952419Sjulian}; 5052419Sjulianstatic const HAL_PERCAL_DATA ar9130_adc_dc_cal = { /* multi sample */ 5152419Sjulian .calName = "ADC DC", .calType = ADC_DC_CAL, 5252419Sjulian .calNumSamples = MAX_CAL_SAMPLES, 5353997Sarchie .calCountMax = PER_MIN_LOG_COUNT, 5452419Sjulian .calCollect = ar5416AdcDcCalCollect, 5552419Sjulian .calPostProc = ar5416AdcDcCalibration 5652419Sjulian}; 5752419Sjulianstatic const HAL_PERCAL_DATA ar9130_adc_init_dc_cal = { 5852419Sjulian .calName = "ADC Init DC", .calType = ADC_DC_INIT_CAL, 5952419Sjulian .calNumSamples = MIN_CAL_SAMPLES, 6052419Sjulian .calCountMax = INIT_LOG_COUNT, 6152419Sjulian .calCollect = ar5416AdcDcCalCollect, 6252752Sjulian .calPostProc = ar5416AdcDcCalibration 6352752Sjulian}; 6452752Sjulian 6552752Sjulianstatic HAL_BOOL ar9130FillCapabilityInfo(struct ath_hal *ah); 6652752Sjulian 6752752Sjulian/* 6852752Sjulian * Attach for an AR9130 part. 6952419Sjulian */ 7053997Sarchiestatic struct ath_hal * 7153997Sarchiear9130Attach(uint16_t devid, HAL_SOFTC sc, 7253997Sarchie HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata, 7353997Sarchie HAL_OPS_CONFIG *ah_config, 7453997Sarchie HAL_STATUS *status) 7553997Sarchie{ 7653997Sarchie struct ath_hal_5416 *ahp5416; 7753997Sarchie struct ath_hal_5212 *ahp; 7853997Sarchie struct ath_hal *ah; 7953997Sarchie uint32_t val; 8053997Sarchie HAL_STATUS ecode; 8153997Sarchie HAL_BOOL rfStatus; 8253997Sarchie 8353997Sarchie HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n", 8453997Sarchie __func__, sc, (void*) st, (void*) sh); 8553997Sarchie 8653997Sarchie /* NB: memory is returned zero'd */ 8753997Sarchie ahp5416 = ath_hal_malloc(sizeof (struct ath_hal_5416)); 8853997Sarchie if (ahp5416 == AH_NULL) { 8953997Sarchie HALDEBUG(AH_NULL, HAL_DEBUG_ANY, 9053997Sarchie "%s: cannot allocate memory for state block\n", __func__); 9153997Sarchie *status = HAL_ENOMEM; 9253997Sarchie return AH_NULL; 9353997Sarchie } 9453997Sarchie ar5416InitState(ahp5416, devid, sc, st, sh, status); 9553997Sarchie ahp = &ahp5416->ah_5212; 9653997Sarchie ah = &ahp->ah_priv.h; 9752419Sjulian 9852419Sjulian /* XXX override with 9100 specific state */ 9952419Sjulian AH5416(ah)->ah_initPLL = ar9130InitPLL; 10052419Sjulian /* XXX should force chainmasks to 0x7, as per ath9k calibration bugs */ 10152419Sjulian 10252419Sjulian /* override 5416 methods for our needs */ 10352419Sjulian 10452419Sjulian AH5416(ah)->ah_cal.iqCalData.calData = &ar9130_iq_cal; 10552419Sjulian AH5416(ah)->ah_cal.adcGainCalData.calData = &ar9130_adc_gain_cal; 10652419Sjulian AH5416(ah)->ah_cal.adcDcCalData.calData = &ar9130_adc_dc_cal; 10752419Sjulian AH5416(ah)->ah_cal.adcDcCalInitData.calData = &ar9130_adc_init_dc_cal; 10852419Sjulian AH5416(ah)->ah_cal.suppCals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL; 10953913Sarchie 11053997Sarchie /* 11152419Sjulian * This was hard-set because the initial ath9k port of this 11252419Sjulian * code kept their runtime conditional register #defines. 11352419Sjulian * AR_SREV and the RTC registers have shifted for Howl; 11452419Sjulian * they detected this and changed the values at runtime. 11552419Sjulian * The current port doesn't yet do this; it may do at a 11652419Sjulian * later stage, so this is set early so any routines which 11752419Sjulian * manipulate the registers have ah_macVersion set to base 11852419Sjulian * the above decision upon. 11952419Sjulian */ 12052419Sjulian AH_PRIVATE((ah))->ah_macVersion = AR_XSREV_VERSION_HOWL; 12152419Sjulian 12252419Sjulian /* 12352419Sjulian * Use the "local" EEPROM data given to us by the higher layers. 12452419Sjulian * This is a private copy out of system flash. 12552419Sjulian * By this stage the SoC SPI flash may have disabled the memory- 12652419Sjulian * mapping and rely purely on port-based SPI IO. 12752419Sjulian */ 12852419Sjulian AH_PRIVATE((ah))->ah_eepromRead = ath_hal_EepromDataRead; 12952419Sjulian AH_PRIVATE((ah))->ah_eepromWrite = NULL; 13052419Sjulian ah->ah_eepromdata = eepromdata; 13152419Sjulian 13252419Sjulian if (!ar5416SetResetReg(ah, HAL_RESET_POWER_ON)) { 13352419Sjulian /* reset chip */ 13452419Sjulian HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't reset chip\n", 13552419Sjulian __func__); 13652419Sjulian ecode = HAL_EIO; 13752419Sjulian goto bad; 13852419Sjulian } 13952419Sjulian 14052419Sjulian if (!ar5416SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) { 14152419Sjulian HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't wakeup chip\n", 14252419Sjulian __func__); 14352419Sjulian ecode = HAL_EIO; 14452419Sjulian goto bad; 14552419Sjulian } 14652419Sjulian /* Read Revisions from Chips before taking out of reset */ 14752419Sjulian val = OS_REG_READ(ah, AR_SREV_CHIP_HOWL) & AR_SREV_CHIP_HOWL_ID; 14852419Sjulian 14952419Sjulian /* XXX are these values even valid for the mac/radio revision? -adrian */ 15052419Sjulian HALDEBUG(ah, HAL_DEBUG_ATTACH, 15152419Sjulian "%s: ID 0x%x VERSION 0x%x TYPE 0x%x REVISION 0x%x\n", 15252419Sjulian __func__, MS(val, AR_XSREV_ID), MS(val, AR_XSREV_VERSION), 15368876Sdwmalone MS(val, AR_XSREV_TYPE), MS(val, AR_XSREV_REVISION)); 15468876Sdwmalone AH_PRIVATE(ah)->ah_macRev = MS(val, AR_XSREV_REVISION); 15552419Sjulian AH_PRIVATE(ah)->ah_ispcie = 0; 15652419Sjulian 15752419Sjulian /* setup common ini data; rf backends handle remainder */ 15852419Sjulian HAL_INI_INIT(&ahp->ah_ini_modes, ar5416Modes_9100, 6); 15952419Sjulian HAL_INI_INIT(&ahp->ah_ini_common, ar5416Common_9100, 2); 16052419Sjulian 16152419Sjulian HAL_INI_INIT(&AH5416(ah)->ah_ini_bb_rfgain, ar5416BB_RfGain_9100, 3); 16252419Sjulian HAL_INI_INIT(&AH5416(ah)->ah_ini_bank0, ar5416Bank0_9100, 2); 16352419Sjulian HAL_INI_INIT(&AH5416(ah)->ah_ini_bank1, ar5416Bank1_9100, 2); 16452419Sjulian HAL_INI_INIT(&AH5416(ah)->ah_ini_bank2, ar5416Bank2_9100, 2); 16552419Sjulian HAL_INI_INIT(&AH5416(ah)->ah_ini_bank3, ar5416Bank3_9100, 3); 16652419Sjulian HAL_INI_INIT(&AH5416(ah)->ah_ini_bank6, ar5416Bank6TPC_9100, 3); 16752419Sjulian HAL_INI_INIT(&AH5416(ah)->ah_ini_bank7, ar5416Bank7_9100, 2); 16852419Sjulian HAL_INI_INIT(&AH5416(ah)->ah_ini_addac, ar5416Addac_9100, 2); 16952419Sjulian 17052419Sjulian ecode = ath_hal_v14EepromAttach(ah); 17152419Sjulian if (ecode != HAL_OK) 17252419Sjulian goto bad; 17352419Sjulian 17452419Sjulian if (!ar5416ChipReset(ah, AH_NULL)) { /* reset chip */ 17552419Sjulian HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__); 17652419Sjulian ecode = HAL_EIO; 17752419Sjulian goto bad; 17852419Sjulian } 17952419Sjulian 18052419Sjulian AH_PRIVATE(ah)->ah_phyRev = OS_REG_READ(ah, AR_PHY_CHIP_ID); 18152419Sjulian 18252419Sjulian if (!ar5212ChipTest(ah)) { 18352419Sjulian HALDEBUG(ah, HAL_DEBUG_ANY, "%s: hardware self-test failed\n", 18452419Sjulian __func__); 18552419Sjulian ecode = HAL_ESELFTEST; 18652419Sjulian goto bad; 18752419Sjulian } 18852419Sjulian 18952419Sjulian /* 19052419Sjulian * Set correct Baseband to analog shift 19152419Sjulian * setting to access analog chips. 19252419Sjulian */ 19352419Sjulian OS_REG_WRITE(ah, AR_PHY(0), 0x00000007); 19452419Sjulian 19552419Sjulian /* Read Radio Chip Rev Extract */ 19652419Sjulian AH_PRIVATE(ah)->ah_analog5GhzRev = ar5416GetRadioRev(ah); 19752419Sjulian switch (AH_PRIVATE(ah)->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR) { 19852419Sjulian case AR_RAD2133_SREV_MAJOR: /* Sowl: 2G/3x3 */ 19952419Sjulian case AR_RAD5133_SREV_MAJOR: /* Sowl: 2+5G/3x3 */ 20052419Sjulian break; 20152419Sjulian default: 20252419Sjulian if (AH_PRIVATE(ah)->ah_analog5GhzRev == 0) { 20352419Sjulian AH_PRIVATE(ah)->ah_analog5GhzRev = 20452419Sjulian AR_RAD5133_SREV_MAJOR; 20552816Sarchie break; 20652816Sarchie } 20753648Sarchie#ifdef AH_DEBUG 20852816Sarchie HALDEBUG(ah, HAL_DEBUG_ANY, 20952419Sjulian "%s: 5G Radio Chip Rev 0x%02X is not supported by " 21052816Sarchie "this driver\n", __func__, 21152419Sjulian AH_PRIVATE(ah)->ah_analog5GhzRev); 21252816Sarchie ecode = HAL_ENOTSUPP; 21352816Sarchie goto bad; 21452816Sarchie#endif 21552816Sarchie } 21652419Sjulian rfStatus = ar2133RfAttach(ah, &ecode); 21752419Sjulian if (!rfStatus) { 21852419Sjulian HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RF setup failed, status %u\n", 21952419Sjulian __func__, ecode); 22052419Sjulian goto bad; 22152419Sjulian } 22252419Sjulian 22352419Sjulian /* 22452419Sjulian * Got everything we need now to setup the capabilities. 22552419Sjulian */ 22652419Sjulian if (!ar9130FillCapabilityInfo(ah)) { 22752419Sjulian ecode = HAL_EEREAD; 22852419Sjulian goto bad; 22952419Sjulian } 23052419Sjulian 23152419Sjulian ecode = ath_hal_eepromGet(ah, AR_EEP_MACADDR, ahp->ah_macaddr); 23252419Sjulian if (ecode != HAL_OK) { 23352419Sjulian HALDEBUG(ah, HAL_DEBUG_ANY, 23452419Sjulian "%s: error getting mac address from EEPROM\n", __func__); 23552419Sjulian goto bad; 23652419Sjulian } 23752419Sjulian /* XXX How about the serial number ? */ 23852419Sjulian /* Read Reg Domain */ 23952419Sjulian AH_PRIVATE(ah)->ah_currentRD = 24052419Sjulian ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, AH_NULL); 24152419Sjulian AH_PRIVATE(ah)->ah_currentRDext = 24252419Sjulian ath_hal_eepromGet(ah, AR_EEP_REGDMN_1, AH_NULL); 24352419Sjulian 24452419Sjulian 24552419Sjulian /* 24652419Sjulian * ah_miscMode is populated by ar5416FillCapabilityInfo() 24752419Sjulian * starting from griffin. Set here to make sure that 24852419Sjulian * AR_MISC_MODE_MIC_NEW_LOC_ENABLE is set before a GTK is 24952419Sjulian * placed into hardware. 25052419Sjulian */ 25152419Sjulian if (ahp->ah_miscMode != 0) 25252419Sjulian OS_REG_WRITE(ah, AR_MISC_MODE, ahp->ah_miscMode); 25352419Sjulian 25452419Sjulian /* XXX no ANI for AR9130 */ 25552419Sjulian AH5416(ah)->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_5416_2GHZ; 25652419Sjulian AH5416(ah)->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_5416_2GHZ; 25752419Sjulian AH5416(ah)->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_5416_2GHZ; 25859728Sjulian AH5416(ah)->nf_5g.max = AR_PHY_CCA_MAX_GOOD_VAL_5416_5GHZ; 25959728Sjulian AH5416(ah)->nf_5g.min = AR_PHY_CCA_MIN_GOOD_VAL_5416_5GHZ; 26052419Sjulian AH5416(ah)->nf_5g.nominal = AR_PHY_CCA_NOM_VAL_5416_5GHZ; 26152419Sjulian 26252419Sjulian ar5416InitNfHistBuff(AH5416(ah)->ah_cal.nfCalHist); 26352419Sjulian 26452419Sjulian HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n", __func__); 26552419Sjulian 26652419Sjulian return ah; 26752419Sjulianbad: 26852419Sjulian if (ahp) 26952419Sjulian ar5416Detach((struct ath_hal *) ahp); 27052419Sjulian if (status) 27152419Sjulian *status = ecode; 27252419Sjulian return AH_NULL; 27352419Sjulian} 27452419Sjulian 27552419Sjulian/* 27652419Sjulian * Fill all software cached or static hardware state information. 27752419Sjulian * Return failure if capabilities are to come from EEPROM and 27852419Sjulian * cannot be read. 27952419Sjulian */ 28052419Sjulianstatic HAL_BOOL 28152419Sjulianar9130FillCapabilityInfo(struct ath_hal *ah) 28252419Sjulian{ 28352419Sjulian HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps; 28452419Sjulian 28552419Sjulian HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: begin\n", __func__); 28652419Sjulian if (!ar5416FillCapabilityInfo(ah)) 28752419Sjulian return AH_FALSE; 28852419Sjulian HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: fill'ed; now setting\n", __func__); 28952419Sjulian pCap->halCSTSupport = AH_TRUE; 29052419Sjulian pCap->halRifsRxSupport = AH_TRUE; 29152419Sjulian pCap->halRifsTxSupport = AH_TRUE; 29252419Sjulian pCap->halRtsAggrLimit = 64*1024; /* 802.11n max */ 29352419Sjulian pCap->halExtChanDfsSupport = AH_TRUE; 29452419Sjulian pCap->halUseCombinedRadarRssi = AH_TRUE; 29552419Sjulian pCap->halAutoSleepSupport = AH_FALSE; /* XXX? */ 29652419Sjulian /* 29752419Sjulian * MBSSID aggregation is broken in Howl v1.1, v1.2, v1.3 29852419Sjulian * and works fine in v1.4. 29952419Sjulian * XXX todo, enable it for v1.4. 30052419Sjulian */ 30152419Sjulian pCap->halMbssidAggrSupport = AH_FALSE; 30252419Sjulian pCap->hal4AddrAggrSupport = AH_TRUE; 30352419Sjulian /* BB Read WAR */ 30452419Sjulian pCap->halHasBBReadWar = AH_TRUE; 30552419Sjulian 30652419Sjulian /* 30752419Sjulian * Implement the PLL/config changes needed for half/quarter 30852419Sjulian * rates before re-enabling them here. 30952419Sjulian */ 31052419Sjulian pCap->halChanHalfRate = AH_FALSE; 31152419Sjulian pCap->halChanQuarterRate = AH_FALSE; 31252419Sjulian 31352419Sjulian return AH_TRUE; 31452419Sjulian} 31552419Sjulian 31652419Sjulianstatic const char* 31752419Sjulianar9130Probe(uint16_t vendorid, uint16_t devid) 31852419Sjulian{ 31969922Sjulian if (vendorid == ATHEROS_VENDOR_ID && devid == AR5416_AR9130_DEVID) 32069922Sjulian return "Atheros 9130"; 32169922Sjulian return AH_NULL; 32252419Sjulian} 32352419SjulianAH_CHIP(AR9130, ar9130Probe, ar9130Attach); 32459728Sjulian