1/*- 2 * SPDX-License-Identifier: ISC 3 * 4 * Copyright (c) 2011 Adrian Chadd, Xenion Pty Ltd 5 * Copyright (c) 2008 Sam Leffler, Errno Consulting 6 * Copyright (c) 2008 Atheros Communications, Inc. 7 * 8 * Permission to use, copy, modify, and/or distribute this software for any 9 * purpose with or without fee is hereby granted, provided that the above 10 * copyright notice and this permission notice appear in all copies. 11 * 12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 19 * 20 * $FreeBSD: releng/12.0/sys/dev/ath/ath_hal/ar9001/ar9130_attach.c 326695 2017-12-08 15:57:29Z pfg $ 21 */ 22#include "opt_ah.h" 23 24#include "ah.h" 25#include "ah_internal.h" 26#include "ah_devid.h" 27 28#include "ar5416/ar5416.h" 29#include "ar5416/ar5416reg.h" 30#include "ar5416/ar5416phy.h" 31 32#include "ar9001/ar9130reg.h" 33#include "ar9001/ar9130_phy.h" 34#include "ar9001/ar9130_eeprom.h" 35 36#include "ar9001/ar9130.ini" 37 38static const HAL_PERCAL_DATA ar9130_iq_cal = { /* multi sample */ 39 .calName = "IQ", .calType = IQ_MISMATCH_CAL, 40 .calNumSamples = MAX_CAL_SAMPLES, 41 .calCountMax = PER_MIN_LOG_COUNT, 42 .calCollect = ar5416IQCalCollect, 43 .calPostProc = ar5416IQCalibration 44}; 45static const HAL_PERCAL_DATA ar9130_adc_gain_cal = { /* multi sample */ 46 .calName = "ADC Gain", .calType = ADC_GAIN_CAL, 47 .calNumSamples = MAX_CAL_SAMPLES, 48 .calCountMax = PER_MIN_LOG_COUNT, 49 .calCollect = ar5416AdcGainCalCollect, 50 .calPostProc = ar5416AdcGainCalibration 51}; 52static const HAL_PERCAL_DATA ar9130_adc_dc_cal = { /* multi sample */ 53 .calName = "ADC DC", .calType = ADC_DC_CAL, 54 .calNumSamples = MAX_CAL_SAMPLES, 55 .calCountMax = PER_MIN_LOG_COUNT, 56 .calCollect = ar5416AdcDcCalCollect, 57 .calPostProc = ar5416AdcDcCalibration 58}; 59static const HAL_PERCAL_DATA ar9130_adc_init_dc_cal = { 60 .calName = "ADC Init DC", .calType = ADC_DC_INIT_CAL, 61 .calNumSamples = MIN_CAL_SAMPLES, 62 .calCountMax = INIT_LOG_COUNT, 63 .calCollect = ar5416AdcDcCalCollect, 64 .calPostProc = ar5416AdcDcCalibration 65}; 66 67static HAL_BOOL ar9130FillCapabilityInfo(struct ath_hal *ah); 68 69/* 70 * Attach for an AR9130 part. 71 */ 72static struct ath_hal * 73ar9130Attach(uint16_t devid, HAL_SOFTC sc, 74 HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata, 75 HAL_OPS_CONFIG *ah_config, 76 HAL_STATUS *status) 77{ 78 struct ath_hal_5416 *ahp5416; 79 struct ath_hal_5212 *ahp; 80 struct ath_hal *ah; 81 uint32_t val; 82 HAL_STATUS ecode; 83 HAL_BOOL rfStatus; 84 85 HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n", 86 __func__, sc, (void*) st, (void*) sh); 87 88 /* NB: memory is returned zero'd */ 89 ahp5416 = ath_hal_malloc(sizeof (struct ath_hal_5416)); 90 if (ahp5416 == AH_NULL) { 91 HALDEBUG(AH_NULL, HAL_DEBUG_ANY, 92 "%s: cannot allocate memory for state block\n", __func__); 93 *status = HAL_ENOMEM; 94 return AH_NULL; 95 } 96 ar5416InitState(ahp5416, devid, sc, st, sh, status); 97 ahp = &ahp5416->ah_5212; 98 ah = &ahp->ah_priv.h; 99 100 /* XXX override with 9100 specific state */ 101 AH5416(ah)->ah_initPLL = ar9130InitPLL; 102 /* XXX should force chainmasks to 0x7, as per ath9k calibration bugs */ 103 104 /* override 5416 methods for our needs */ 105 106 AH5416(ah)->ah_cal.iqCalData.calData = &ar9130_iq_cal; 107 AH5416(ah)->ah_cal.adcGainCalData.calData = &ar9130_adc_gain_cal; 108 AH5416(ah)->ah_cal.adcDcCalData.calData = &ar9130_adc_dc_cal; 109 AH5416(ah)->ah_cal.adcDcCalInitData.calData = &ar9130_adc_init_dc_cal; 110 AH5416(ah)->ah_cal.suppCals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL; 111 112 /* 113 * This was hard-set because the initial ath9k port of this 114 * code kept their runtime conditional register #defines. 115 * AR_SREV and the RTC registers have shifted for Howl; 116 * they detected this and changed the values at runtime. 117 * The current port doesn't yet do this; it may do at a 118 * later stage, so this is set early so any routines which 119 * manipulate the registers have ah_macVersion set to base 120 * the above decision upon. 121 */ 122 AH_PRIVATE((ah))->ah_macVersion = AR_XSREV_VERSION_HOWL; 123 124 /* 125 * Use the "local" EEPROM data given to us by the higher layers. 126 * This is a private copy out of system flash. 127 * By this stage the SoC SPI flash may have disabled the memory- 128 * mapping and rely purely on port-based SPI IO. 129 */ 130 AH_PRIVATE((ah))->ah_eepromRead = ath_hal_EepromDataRead; 131 AH_PRIVATE((ah))->ah_eepromWrite = NULL; 132 ah->ah_eepromdata = eepromdata; 133 134 if (!ar5416SetResetReg(ah, HAL_RESET_POWER_ON)) { 135 /* reset chip */ 136 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't reset chip\n", 137 __func__); 138 ecode = HAL_EIO; 139 goto bad; 140 } 141 142 if (!ar5416SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) { 143 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't wakeup chip\n", 144 __func__); 145 ecode = HAL_EIO; 146 goto bad; 147 } 148 /* Read Revisions from Chips before taking out of reset */ 149 val = OS_REG_READ(ah, AR_SREV_CHIP_HOWL) & AR_SREV_CHIP_HOWL_ID; 150 151 /* XXX are these values even valid for the mac/radio revision? -adrian */ 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 AH_PRIVATE(ah)->ah_macRev = MS(val, AR_XSREV_REVISION); 157 AH_PRIVATE(ah)->ah_ispcie = 0; 158 159 /* setup common ini data; rf backends handle remainder */ 160 HAL_INI_INIT(&ahp->ah_ini_modes, ar5416Modes_9100, 6); 161 HAL_INI_INIT(&ahp->ah_ini_common, ar5416Common_9100, 2); 162 163 HAL_INI_INIT(&AH5416(ah)->ah_ini_bb_rfgain, ar5416BB_RfGain_9100, 3); 164 HAL_INI_INIT(&AH5416(ah)->ah_ini_bank0, ar5416Bank0_9100, 2); 165 HAL_INI_INIT(&AH5416(ah)->ah_ini_bank1, ar5416Bank1_9100, 2); 166 HAL_INI_INIT(&AH5416(ah)->ah_ini_bank2, ar5416Bank2_9100, 2); 167 HAL_INI_INIT(&AH5416(ah)->ah_ini_bank3, ar5416Bank3_9100, 3); 168 HAL_INI_INIT(&AH5416(ah)->ah_ini_bank6, ar5416Bank6TPC_9100, 3); 169 HAL_INI_INIT(&AH5416(ah)->ah_ini_bank7, ar5416Bank7_9100, 2); 170 HAL_INI_INIT(&AH5416(ah)->ah_ini_addac, ar5416Addac_9100, 2); 171 172 ecode = ath_hal_v14EepromAttach(ah); 173 if (ecode != HAL_OK) 174 goto bad; 175 176 if (!ar5416ChipReset(ah, AH_NULL, HAL_RESET_NORMAL)) { /* reset chip */ 177 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__); 178 ecode = HAL_EIO; 179 goto bad; 180 } 181 182 AH_PRIVATE(ah)->ah_phyRev = OS_REG_READ(ah, AR_PHY_CHIP_ID); 183 184 if (!ar5212ChipTest(ah)) { 185 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: hardware self-test failed\n", 186 __func__); 187 ecode = HAL_ESELFTEST; 188 goto bad; 189 } 190 191 /* 192 * Set correct Baseband to analog shift 193 * setting to access analog chips. 194 */ 195 OS_REG_WRITE(ah, AR_PHY(0), 0x00000007); 196 197 /* Read Radio Chip Rev Extract */ 198 AH_PRIVATE(ah)->ah_analog5GhzRev = ar5416GetRadioRev(ah); 199 switch (AH_PRIVATE(ah)->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR) { 200 case AR_RAD2133_SREV_MAJOR: /* Sowl: 2G/3x3 */ 201 case AR_RAD5133_SREV_MAJOR: /* Sowl: 2+5G/3x3 */ 202 break; 203 default: 204 if (AH_PRIVATE(ah)->ah_analog5GhzRev == 0) { 205 AH_PRIVATE(ah)->ah_analog5GhzRev = 206 AR_RAD5133_SREV_MAJOR; 207 break; 208 } 209#ifdef AH_DEBUG 210 HALDEBUG(ah, HAL_DEBUG_ANY, 211 "%s: 5G Radio Chip Rev 0x%02X is not supported by " 212 "this driver\n", __func__, 213 AH_PRIVATE(ah)->ah_analog5GhzRev); 214 ecode = HAL_ENOTSUPP; 215 goto bad; 216#endif 217 } 218 rfStatus = ar2133RfAttach(ah, &ecode); 219 if (!rfStatus) { 220 HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RF setup failed, status %u\n", 221 __func__, ecode); 222 goto bad; 223 } 224 225 /* 226 * Got everything we need now to setup the capabilities. 227 */ 228 if (!ar9130FillCapabilityInfo(ah)) { 229 ecode = HAL_EEREAD; 230 goto bad; 231 } 232 233 ecode = ath_hal_eepromGet(ah, AR_EEP_MACADDR, ahp->ah_macaddr); 234 if (ecode != HAL_OK) { 235 HALDEBUG(ah, HAL_DEBUG_ANY, 236 "%s: error getting mac address from EEPROM\n", __func__); 237 goto bad; 238 } 239 /* XXX How about the serial number ? */ 240 /* Read Reg Domain */ 241 AH_PRIVATE(ah)->ah_currentRD = 242 ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, AH_NULL); 243 AH_PRIVATE(ah)->ah_currentRDext = 244 ath_hal_eepromGet(ah, AR_EEP_REGDMN_1, AH_NULL); 245 246 /* 247 * ah_miscMode is populated by ar5416FillCapabilityInfo() 248 * starting from griffin. Set here to make sure that 249 * AR_MISC_MODE_MIC_NEW_LOC_ENABLE is set before a GTK is 250 * placed into hardware. 251 */ 252 if (ahp->ah_miscMode != 0) 253 OS_REG_WRITE(ah, AR_MISC_MODE, ahp->ah_miscMode); 254 255 /* XXX no ANI for AR9130 */ 256 AH5416(ah)->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_5416_2GHZ; 257 AH5416(ah)->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_5416_2GHZ; 258 AH5416(ah)->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_5416_2GHZ; 259 AH5416(ah)->nf_5g.max = AR_PHY_CCA_MAX_GOOD_VAL_5416_5GHZ; 260 AH5416(ah)->nf_5g.min = AR_PHY_CCA_MIN_GOOD_VAL_5416_5GHZ; 261 AH5416(ah)->nf_5g.nominal = AR_PHY_CCA_NOM_VAL_5416_5GHZ; 262 263 ar5416InitNfHistBuff(AH5416(ah)->ah_cal.nfCalHist); 264 265 HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n", __func__); 266 267 return ah; 268bad: 269 if (ahp) 270 ar5416Detach((struct ath_hal *) ahp); 271 if (status) 272 *status = ecode; 273 return AH_NULL; 274} 275 276/* 277 * Fill all software cached or static hardware state information. 278 * Return failure if capabilities are to come from EEPROM and 279 * cannot be read. 280 */ 281static HAL_BOOL 282ar9130FillCapabilityInfo(struct ath_hal *ah) 283{ 284 HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps; 285 286 HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: begin\n", __func__); 287 if (!ar5416FillCapabilityInfo(ah)) 288 return AH_FALSE; 289 HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: fill'ed; now setting\n", __func__); 290 pCap->halCSTSupport = AH_TRUE; 291 pCap->halRifsRxSupport = AH_TRUE; 292 pCap->halRifsTxSupport = AH_TRUE; 293 pCap->halRtsAggrLimit = 64*1024; /* 802.11n max */ 294 pCap->halExtChanDfsSupport = AH_TRUE; 295 pCap->halUseCombinedRadarRssi = AH_TRUE; 296 pCap->halAutoSleepSupport = AH_FALSE; /* XXX? */ 297 /* 298 * MBSSID aggregation is broken in Howl v1.1, v1.2, v1.3 299 * and works fine in v1.4. 300 * XXX todo, enable it for v1.4. 301 */ 302 pCap->halMbssidAggrSupport = AH_FALSE; 303 pCap->hal4AddrAggrSupport = AH_TRUE; 304 /* BB Read WAR */ 305 pCap->halHasBBReadWar = AH_TRUE; 306 307 /* 308 * Implement the PLL/config changes needed for half/quarter 309 * rates before re-enabling them here. 310 */ 311 pCap->halChanHalfRate = AH_FALSE; 312 pCap->halChanQuarterRate = AH_FALSE; 313 314 return AH_TRUE; 315} 316 317static const char* 318ar9130Probe(uint16_t vendorid, uint16_t devid) 319{ 320 if (vendorid == ATHEROS_VENDOR_ID && devid == AR5416_AR9130_DEVID) 321 return "Atheros 9130"; 322 return AH_NULL; 323} 324AH_CHIP(AR9130, ar9130Probe, ar9130Attach); 325