1221163Sadrian/* 2221163Sadrian * Copyright (c) 2011 Adrian Chadd, Xenion Pty Ltd 3221163Sadrian * Copyright (c) 2008 Sam Leffler, Errno Consulting 4221163Sadrian * Copyright (c) 2008 Atheros Communications, Inc. 5221163Sadrian * 6221163Sadrian * Permission to use, copy, modify, and/or distribute this software for any 7221163Sadrian * purpose with or without fee is hereby granted, provided that the above 8221163Sadrian * copyright notice and this permission notice appear in all copies. 9221163Sadrian * 10221163Sadrian * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11221163Sadrian * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12221163Sadrian * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13221163Sadrian * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14221163Sadrian * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15221163Sadrian * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16221163Sadrian * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17221163Sadrian * 18221163Sadrian * $FreeBSD: releng/11.0/sys/dev/ath/ath_hal/ar9001/ar9130_attach.c 272292 2014-09-30 03:19:29Z adrian $ 19221163Sadrian */ 20221163Sadrian#include "opt_ah.h" 21221163Sadrian 22221163Sadrian#include "ah.h" 23221163Sadrian#include "ah_internal.h" 24221163Sadrian#include "ah_devid.h" 25221163Sadrian 26221163Sadrian#include "ar5416/ar5416.h" 27221163Sadrian#include "ar5416/ar5416reg.h" 28221163Sadrian#include "ar5416/ar5416phy.h" 29221163Sadrian 30221163Sadrian#include "ar9001/ar9130reg.h" 31221163Sadrian#include "ar9001/ar9130_phy.h" 32221163Sadrian#include "ar9001/ar9130_eeprom.h" 33221163Sadrian 34221163Sadrian#include "ar9001/ar9130.ini" 35221163Sadrian 36221163Sadrianstatic const HAL_PERCAL_DATA ar9130_iq_cal = { /* multi sample */ 37221163Sadrian .calName = "IQ", .calType = IQ_MISMATCH_CAL, 38221163Sadrian .calNumSamples = MAX_CAL_SAMPLES, 39221163Sadrian .calCountMax = PER_MIN_LOG_COUNT, 40221163Sadrian .calCollect = ar5416IQCalCollect, 41221163Sadrian .calPostProc = ar5416IQCalibration 42221163Sadrian}; 43221163Sadrianstatic const HAL_PERCAL_DATA ar9130_adc_gain_cal = { /* multi sample */ 44221163Sadrian .calName = "ADC Gain", .calType = ADC_GAIN_CAL, 45221163Sadrian .calNumSamples = MAX_CAL_SAMPLES, 46221163Sadrian .calCountMax = PER_MIN_LOG_COUNT, 47221163Sadrian .calCollect = ar5416AdcGainCalCollect, 48221163Sadrian .calPostProc = ar5416AdcGainCalibration 49221163Sadrian}; 50221163Sadrianstatic const HAL_PERCAL_DATA ar9130_adc_dc_cal = { /* multi sample */ 51221163Sadrian .calName = "ADC DC", .calType = ADC_DC_CAL, 52221163Sadrian .calNumSamples = MAX_CAL_SAMPLES, 53221163Sadrian .calCountMax = PER_MIN_LOG_COUNT, 54221163Sadrian .calCollect = ar5416AdcDcCalCollect, 55221163Sadrian .calPostProc = ar5416AdcDcCalibration 56221163Sadrian}; 57221163Sadrianstatic const HAL_PERCAL_DATA ar9130_adc_init_dc_cal = { 58221163Sadrian .calName = "ADC Init DC", .calType = ADC_DC_INIT_CAL, 59221163Sadrian .calNumSamples = MIN_CAL_SAMPLES, 60221163Sadrian .calCountMax = INIT_LOG_COUNT, 61221163Sadrian .calCollect = ar5416AdcDcCalCollect, 62221163Sadrian .calPostProc = ar5416AdcDcCalibration 63221163Sadrian}; 64221163Sadrian 65221163Sadrianstatic HAL_BOOL ar9130FillCapabilityInfo(struct ath_hal *ah); 66221163Sadrian 67221163Sadrian/* 68221163Sadrian * Attach for an AR9130 part. 69221163Sadrian */ 70221163Sadrianstatic struct ath_hal * 71221163Sadrianar9130Attach(uint16_t devid, HAL_SOFTC sc, 72272292Sadrian HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata, 73272292Sadrian HAL_OPS_CONFIG *ah_config, 74272292Sadrian HAL_STATUS *status) 75221163Sadrian{ 76221163Sadrian struct ath_hal_5416 *ahp5416; 77221163Sadrian struct ath_hal_5212 *ahp; 78221163Sadrian struct ath_hal *ah; 79221163Sadrian uint32_t val; 80221163Sadrian HAL_STATUS ecode; 81221163Sadrian HAL_BOOL rfStatus; 82221163Sadrian 83225883Sadrian HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n", 84221163Sadrian __func__, sc, (void*) st, (void*) sh); 85221163Sadrian 86221163Sadrian /* NB: memory is returned zero'd */ 87221163Sadrian ahp5416 = ath_hal_malloc(sizeof (struct ath_hal_5416)); 88221163Sadrian if (ahp5416 == AH_NULL) { 89225883Sadrian HALDEBUG(AH_NULL, HAL_DEBUG_ANY, 90221163Sadrian "%s: cannot allocate memory for state block\n", __func__); 91221163Sadrian *status = HAL_ENOMEM; 92221163Sadrian return AH_NULL; 93221163Sadrian } 94221163Sadrian ar5416InitState(ahp5416, devid, sc, st, sh, status); 95221163Sadrian ahp = &ahp5416->ah_5212; 96221163Sadrian ah = &ahp->ah_priv.h; 97221163Sadrian 98221163Sadrian /* XXX override with 9100 specific state */ 99221163Sadrian AH5416(ah)->ah_initPLL = ar9130InitPLL; 100221163Sadrian /* XXX should force chainmasks to 0x7, as per ath9k calibration bugs */ 101221163Sadrian 102221163Sadrian /* override 5416 methods for our needs */ 103221163Sadrian 104221163Sadrian AH5416(ah)->ah_cal.iqCalData.calData = &ar9130_iq_cal; 105221163Sadrian AH5416(ah)->ah_cal.adcGainCalData.calData = &ar9130_adc_gain_cal; 106221163Sadrian AH5416(ah)->ah_cal.adcDcCalData.calData = &ar9130_adc_dc_cal; 107221163Sadrian AH5416(ah)->ah_cal.adcDcCalInitData.calData = &ar9130_adc_init_dc_cal; 108221163Sadrian AH5416(ah)->ah_cal.suppCals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL; 109221163Sadrian 110221163Sadrian /* 111221163Sadrian * This was hard-set because the initial ath9k port of this 112221163Sadrian * code kept their runtime conditional register #defines. 113221163Sadrian * AR_SREV and the RTC registers have shifted for Howl; 114221163Sadrian * they detected this and changed the values at runtime. 115221163Sadrian * The current port doesn't yet do this; it may do at a 116221163Sadrian * later stage, so this is set early so any routines which 117221163Sadrian * manipulate the registers have ah_macVersion set to base 118221163Sadrian * the above decision upon. 119221163Sadrian */ 120221163Sadrian AH_PRIVATE((ah))->ah_macVersion = AR_XSREV_VERSION_HOWL; 121221163Sadrian 122221163Sadrian /* 123221163Sadrian * Use the "local" EEPROM data given to us by the higher layers. 124230147Sadrian * This is a private copy out of system flash. 125230147Sadrian * By this stage the SoC SPI flash may have disabled the memory- 126230147Sadrian * mapping and rely purely on port-based SPI IO. 127221163Sadrian */ 128230147Sadrian AH_PRIVATE((ah))->ah_eepromRead = ath_hal_EepromDataRead; 129221163Sadrian AH_PRIVATE((ah))->ah_eepromWrite = NULL; 130221163Sadrian ah->ah_eepromdata = eepromdata; 131221163Sadrian 132221163Sadrian if (!ar5416SetResetReg(ah, HAL_RESET_POWER_ON)) { 133221163Sadrian /* reset chip */ 134221163Sadrian HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't reset chip\n", 135221163Sadrian __func__); 136221163Sadrian ecode = HAL_EIO; 137221163Sadrian goto bad; 138221163Sadrian } 139221163Sadrian 140221163Sadrian if (!ar5416SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) { 141221163Sadrian HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't wakeup chip\n", 142221163Sadrian __func__); 143221163Sadrian ecode = HAL_EIO; 144221163Sadrian goto bad; 145221163Sadrian } 146221163Sadrian /* Read Revisions from Chips before taking out of reset */ 147221163Sadrian val = OS_REG_READ(ah, AR_SREV_CHIP_HOWL) & AR_SREV_CHIP_HOWL_ID; 148221163Sadrian 149221163Sadrian /* XXX are these values even valid for the mac/radio revision? -adrian */ 150221163Sadrian HALDEBUG(ah, HAL_DEBUG_ATTACH, 151221163Sadrian "%s: ID 0x%x VERSION 0x%x TYPE 0x%x REVISION 0x%x\n", 152221163Sadrian __func__, MS(val, AR_XSREV_ID), MS(val, AR_XSREV_VERSION), 153221163Sadrian MS(val, AR_XSREV_TYPE), MS(val, AR_XSREV_REVISION)); 154221163Sadrian AH_PRIVATE(ah)->ah_macRev = MS(val, AR_XSREV_REVISION); 155221163Sadrian AH_PRIVATE(ah)->ah_ispcie = 0; 156221163Sadrian 157221163Sadrian /* setup common ini data; rf backends handle remainder */ 158221163Sadrian HAL_INI_INIT(&ahp->ah_ini_modes, ar5416Modes_9100, 6); 159221163Sadrian HAL_INI_INIT(&ahp->ah_ini_common, ar5416Common_9100, 2); 160221163Sadrian 161221163Sadrian HAL_INI_INIT(&AH5416(ah)->ah_ini_bb_rfgain, ar5416BB_RfGain_9100, 3); 162221163Sadrian HAL_INI_INIT(&AH5416(ah)->ah_ini_bank0, ar5416Bank0_9100, 2); 163221163Sadrian HAL_INI_INIT(&AH5416(ah)->ah_ini_bank1, ar5416Bank1_9100, 2); 164221163Sadrian HAL_INI_INIT(&AH5416(ah)->ah_ini_bank2, ar5416Bank2_9100, 2); 165221163Sadrian HAL_INI_INIT(&AH5416(ah)->ah_ini_bank3, ar5416Bank3_9100, 3); 166221163Sadrian HAL_INI_INIT(&AH5416(ah)->ah_ini_bank6, ar5416Bank6TPC_9100, 3); 167221163Sadrian HAL_INI_INIT(&AH5416(ah)->ah_ini_bank7, ar5416Bank7_9100, 2); 168221163Sadrian HAL_INI_INIT(&AH5416(ah)->ah_ini_addac, ar5416Addac_9100, 2); 169221163Sadrian 170221163Sadrian ecode = ath_hal_v14EepromAttach(ah); 171221163Sadrian if (ecode != HAL_OK) 172221163Sadrian goto bad; 173221163Sadrian 174221163Sadrian if (!ar5416ChipReset(ah, AH_NULL)) { /* reset chip */ 175221163Sadrian HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__); 176221163Sadrian ecode = HAL_EIO; 177221163Sadrian goto bad; 178221163Sadrian } 179221163Sadrian 180221163Sadrian AH_PRIVATE(ah)->ah_phyRev = OS_REG_READ(ah, AR_PHY_CHIP_ID); 181221163Sadrian 182221163Sadrian if (!ar5212ChipTest(ah)) { 183221163Sadrian HALDEBUG(ah, HAL_DEBUG_ANY, "%s: hardware self-test failed\n", 184221163Sadrian __func__); 185221163Sadrian ecode = HAL_ESELFTEST; 186221163Sadrian goto bad; 187221163Sadrian } 188221163Sadrian 189221163Sadrian /* 190221163Sadrian * Set correct Baseband to analog shift 191221163Sadrian * setting to access analog chips. 192221163Sadrian */ 193221163Sadrian OS_REG_WRITE(ah, AR_PHY(0), 0x00000007); 194221163Sadrian 195221163Sadrian /* Read Radio Chip Rev Extract */ 196221163Sadrian AH_PRIVATE(ah)->ah_analog5GhzRev = ar5416GetRadioRev(ah); 197221163Sadrian switch (AH_PRIVATE(ah)->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR) { 198221163Sadrian case AR_RAD2133_SREV_MAJOR: /* Sowl: 2G/3x3 */ 199221163Sadrian case AR_RAD5133_SREV_MAJOR: /* Sowl: 2+5G/3x3 */ 200221163Sadrian break; 201221163Sadrian default: 202221163Sadrian if (AH_PRIVATE(ah)->ah_analog5GhzRev == 0) { 203221163Sadrian AH_PRIVATE(ah)->ah_analog5GhzRev = 204221163Sadrian AR_RAD5133_SREV_MAJOR; 205221163Sadrian break; 206221163Sadrian } 207221163Sadrian#ifdef AH_DEBUG 208221163Sadrian HALDEBUG(ah, HAL_DEBUG_ANY, 209221163Sadrian "%s: 5G Radio Chip Rev 0x%02X is not supported by " 210221163Sadrian "this driver\n", __func__, 211221163Sadrian AH_PRIVATE(ah)->ah_analog5GhzRev); 212221163Sadrian ecode = HAL_ENOTSUPP; 213221163Sadrian goto bad; 214221163Sadrian#endif 215221163Sadrian } 216221163Sadrian rfStatus = ar2133RfAttach(ah, &ecode); 217221163Sadrian if (!rfStatus) { 218221163Sadrian HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RF setup failed, status %u\n", 219221163Sadrian __func__, ecode); 220221163Sadrian goto bad; 221221163Sadrian } 222221163Sadrian 223221163Sadrian /* 224221163Sadrian * Got everything we need now to setup the capabilities. 225221163Sadrian */ 226221163Sadrian if (!ar9130FillCapabilityInfo(ah)) { 227221163Sadrian ecode = HAL_EEREAD; 228221163Sadrian goto bad; 229221163Sadrian } 230221163Sadrian 231221163Sadrian ecode = ath_hal_eepromGet(ah, AR_EEP_MACADDR, ahp->ah_macaddr); 232221163Sadrian if (ecode != HAL_OK) { 233221163Sadrian HALDEBUG(ah, HAL_DEBUG_ANY, 234221163Sadrian "%s: error getting mac address from EEPROM\n", __func__); 235221163Sadrian goto bad; 236221163Sadrian } 237221163Sadrian /* XXX How about the serial number ? */ 238221163Sadrian /* Read Reg Domain */ 239221163Sadrian AH_PRIVATE(ah)->ah_currentRD = 240221163Sadrian ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, AH_NULL); 241221596Sadrian AH_PRIVATE(ah)->ah_currentRDext = 242221596Sadrian ath_hal_eepromGet(ah, AR_EEP_REGDMN_1, AH_NULL); 243221163Sadrian 244221596Sadrian 245221163Sadrian /* 246221163Sadrian * ah_miscMode is populated by ar5416FillCapabilityInfo() 247221163Sadrian * starting from griffin. Set here to make sure that 248221163Sadrian * AR_MISC_MODE_MIC_NEW_LOC_ENABLE is set before a GTK is 249221163Sadrian * placed into hardware. 250221163Sadrian */ 251221163Sadrian if (ahp->ah_miscMode != 0) 252221163Sadrian OS_REG_WRITE(ah, AR_MISC_MODE, ahp->ah_miscMode); 253221163Sadrian 254221163Sadrian /* XXX no ANI for AR9130 */ 255221163Sadrian AH5416(ah)->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_5416_2GHZ; 256221163Sadrian AH5416(ah)->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_5416_2GHZ; 257221163Sadrian AH5416(ah)->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_5416_2GHZ; 258221163Sadrian AH5416(ah)->nf_5g.max = AR_PHY_CCA_MAX_GOOD_VAL_5416_5GHZ; 259221163Sadrian AH5416(ah)->nf_5g.min = AR_PHY_CCA_MIN_GOOD_VAL_5416_5GHZ; 260221163Sadrian AH5416(ah)->nf_5g.nominal = AR_PHY_CCA_NOM_VAL_5416_5GHZ; 261221163Sadrian 262221163Sadrian ar5416InitNfHistBuff(AH5416(ah)->ah_cal.nfCalHist); 263221163Sadrian 264221163Sadrian HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n", __func__); 265221163Sadrian 266221163Sadrian return ah; 267221163Sadrianbad: 268221163Sadrian if (ahp) 269221163Sadrian ar5416Detach((struct ath_hal *) ahp); 270221163Sadrian if (status) 271221163Sadrian *status = ecode; 272221163Sadrian return AH_NULL; 273221163Sadrian} 274221163Sadrian 275221163Sadrian/* 276221163Sadrian * Fill all software cached or static hardware state information. 277221163Sadrian * Return failure if capabilities are to come from EEPROM and 278221163Sadrian * cannot be read. 279221163Sadrian */ 280221163Sadrianstatic HAL_BOOL 281221163Sadrianar9130FillCapabilityInfo(struct ath_hal *ah) 282221163Sadrian{ 283221163Sadrian HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps; 284221163Sadrian 285221163Sadrian HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: begin\n", __func__); 286221163Sadrian if (!ar5416FillCapabilityInfo(ah)) 287221163Sadrian return AH_FALSE; 288221163Sadrian HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: fill'ed; now setting\n", __func__); 289221163Sadrian pCap->halCSTSupport = AH_TRUE; 290221163Sadrian pCap->halRifsRxSupport = AH_TRUE; 291221163Sadrian pCap->halRifsTxSupport = AH_TRUE; 292221163Sadrian pCap->halRtsAggrLimit = 64*1024; /* 802.11n max */ 293221163Sadrian pCap->halExtChanDfsSupport = AH_TRUE; 294222584Sadrian pCap->halUseCombinedRadarRssi = AH_TRUE; 295221163Sadrian pCap->halAutoSleepSupport = AH_FALSE; /* XXX? */ 296221603Sadrian /* 297221603Sadrian * MBSSID aggregation is broken in Howl v1.1, v1.2, v1.3 298221603Sadrian * and works fine in v1.4. 299221603Sadrian * XXX todo, enable it for v1.4. 300221603Sadrian */ 301221603Sadrian pCap->halMbssidAggrSupport = AH_FALSE; 302221603Sadrian pCap->hal4AddrAggrSupport = AH_TRUE; 303226488Sadrian /* BB Read WAR */ 304226488Sadrian pCap->halHasBBReadWar = AH_TRUE; 305221603Sadrian 306242412Sadrian /* 307242412Sadrian * Implement the PLL/config changes needed for half/quarter 308242412Sadrian * rates before re-enabling them here. 309242412Sadrian */ 310242412Sadrian pCap->halChanHalfRate = AH_FALSE; 311242412Sadrian pCap->halChanQuarterRate = AH_FALSE; 312242412Sadrian 313221163Sadrian return AH_TRUE; 314221163Sadrian} 315221163Sadrian 316221163Sadrianstatic const char* 317221163Sadrianar9130Probe(uint16_t vendorid, uint16_t devid) 318221163Sadrian{ 319221163Sadrian if (vendorid == ATHEROS_VENDOR_ID && devid == AR5416_AR9130_DEVID) 320221163Sadrian return "Atheros 9130"; 321221163Sadrian return AH_NULL; 322221163Sadrian} 323221163SadrianAH_CHIP(AR9130, ar9130Probe, ar9130Attach); 324