1185377Ssam/* 2185377Ssam * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting 3185377Ssam * Copyright (c) 2002-2008 Atheros Communications, Inc. 4185377Ssam * 5185377Ssam * Permission to use, copy, modify, and/or distribute this software for any 6185377Ssam * purpose with or without fee is hereby granted, provided that the above 7185377Ssam * copyright notice and this permission notice appear in all copies. 8185377Ssam * 9185377Ssam * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10185377Ssam * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11185377Ssam * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12185377Ssam * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13185377Ssam * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14185377Ssam * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15185377Ssam * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16185377Ssam * 17186015Ssam * $FreeBSD$ 18185377Ssam */ 19185377Ssam#include "opt_ah.h" 20185377Ssam 21185377Ssam#include "ah.h" 22185377Ssam#include "ah_internal.h" 23185377Ssam#include "ah_devid.h" 24185377Ssam 25185377Ssam#include "ar5312/ar5312.h" 26185377Ssam#include "ar5312/ar5312reg.h" 27185377Ssam#include "ar5312/ar5312phy.h" 28185377Ssam 29185377Ssam/* Add static register initialization vectors */ 30185377Ssam#define AH_5212_COMMON 31185377Ssam#include "ar5212/ar5212.ini" 32185377Ssam 33185377Ssamstatic HAL_BOOL ar5312GetMacAddr(struct ath_hal *ah); 34185377Ssam 35185377Ssamstatic void 36185377Ssamar5312AniSetup(struct ath_hal *ah) 37185377Ssam{ 38185377Ssam static const struct ar5212AniParams aniparams = { 39185377Ssam .maxNoiseImmunityLevel = 4, /* levels 0..4 */ 40185377Ssam .totalSizeDesired = { -41, -41, -48, -48, -48 }, 41185377Ssam .coarseHigh = { -18, -18, -16, -14, -12 }, 42185377Ssam .coarseLow = { -56, -56, -60, -60, -60 }, 43185377Ssam .firpwr = { -72, -72, -75, -78, -80 }, 44185377Ssam .maxSpurImmunityLevel = 2, 45185377Ssam .cycPwrThr1 = { 2, 4, 6 }, 46185377Ssam .maxFirstepLevel = 2, /* levels 0..2 */ 47185377Ssam .firstep = { 0, 4, 8 }, 48185377Ssam .ofdmTrigHigh = 500, 49185377Ssam .ofdmTrigLow = 200, 50185377Ssam .cckTrigHigh = 200, 51185377Ssam .cckTrigLow = 100, 52185377Ssam .rssiThrHigh = 40, 53185377Ssam .rssiThrLow = 7, 54185377Ssam .period = 100, 55185377Ssam }; 56185377Ssam ar5212AniAttach(ah, &aniparams, &aniparams, AH_TRUE); 57185377Ssam} 58185377Ssam 59185377Ssam/* 60185406Ssam * Attach for an AR5312 part. 61185377Ssam */ 62185406Ssamstatic struct ath_hal * 63185377Ssamar5312Attach(uint16_t devid, HAL_SOFTC sc, 64217624Sadrian HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata, 65217624Sadrian HAL_STATUS *status) 66185377Ssam{ 67185377Ssam struct ath_hal_5212 *ahp = AH_NULL; 68185377Ssam struct ath_hal *ah; 69185406Ssam struct ath_hal_rf *rf; 70185377Ssam uint32_t val; 71185377Ssam uint16_t eeval; 72185377Ssam HAL_STATUS ecode; 73185377Ssam 74225883Sadrian HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n", 75185377Ssam __func__, sc, st, (void*) sh); 76185377Ssam 77185377Ssam /* NB: memory is returned zero'd */ 78185377Ssam ahp = ath_hal_malloc(sizeof (struct ath_hal_5212)); 79185377Ssam if (ahp == AH_NULL) { 80225883Sadrian HALDEBUG(AH_NULL, HAL_DEBUG_ANY, 81185377Ssam "%s: cannot allocate memory for state block\n", __func__); 82185377Ssam *status = HAL_ENOMEM; 83185377Ssam return AH_NULL; 84185377Ssam } 85185377Ssam ar5212InitState(ahp, devid, sc, st, sh, status); 86185377Ssam ah = &ahp->ah_priv.h; 87185377Ssam 88185377Ssam /* override 5212 methods for our needs */ 89185377Ssam ah->ah_reset = ar5312Reset; 90185377Ssam ah->ah_phyDisable = ar5312PhyDisable; 91185377Ssam ah->ah_setLedState = ar5312SetLedState; 92185377Ssam ah->ah_detectCardPresent = ar5312DetectCardPresent; 93185377Ssam ah->ah_setPowerMode = ar5312SetPowerMode; 94185377Ssam ah->ah_getPowerMode = ar5312GetPowerMode; 95185377Ssam ah->ah_isInterruptPending = ar5312IsInterruptPending; 96185377Ssam 97185377Ssam ahp->ah_priv.ah_eepromRead = ar5312EepromRead; 98185377Ssam#ifdef AH_SUPPORT_WRITE_EEPROM 99185377Ssam ahp->ah_priv.ah_eepromWrite = ar5312EepromWrite; 100185377Ssam#endif 101185377Ssam#if ( AH_SUPPORT_2316 || AH_SUPPORT_2317) 102185377Ssam if (IS_5315(ah)) { 103185377Ssam ahp->ah_priv.ah_gpioCfgOutput = ar5315GpioCfgOutput; 104185377Ssam ahp->ah_priv.ah_gpioCfgInput = ar5315GpioCfgInput; 105185377Ssam ahp->ah_priv.ah_gpioGet = ar5315GpioGet; 106185377Ssam ahp->ah_priv.ah_gpioSet = ar5315GpioSet; 107185377Ssam ahp->ah_priv.ah_gpioSetIntr = ar5315GpioSetIntr; 108185377Ssam } else 109185377Ssam#endif 110185377Ssam { 111185377Ssam ahp->ah_priv.ah_gpioCfgOutput = ar5312GpioCfgOutput; 112185377Ssam ahp->ah_priv.ah_gpioCfgInput = ar5312GpioCfgInput; 113185377Ssam ahp->ah_priv.ah_gpioGet = ar5312GpioGet; 114185377Ssam ahp->ah_priv.ah_gpioSet = ar5312GpioSet; 115185377Ssam ahp->ah_priv.ah_gpioSetIntr = ar5312GpioSetIntr; 116185377Ssam } 117185377Ssam 118185377Ssam ah->ah_gpioCfgInput = ahp->ah_priv.ah_gpioCfgInput; 119185377Ssam ah->ah_gpioCfgOutput = ahp->ah_priv.ah_gpioCfgOutput; 120185377Ssam ah->ah_gpioGet = ahp->ah_priv.ah_gpioGet; 121185377Ssam ah->ah_gpioSet = ahp->ah_priv.ah_gpioSet; 122185377Ssam ah->ah_gpioSetIntr = ahp->ah_priv.ah_gpioSetIntr; 123185377Ssam 124185377Ssam /* setup common ini data; rf backends handle remainder */ 125185377Ssam HAL_INI_INIT(&ahp->ah_ini_modes, ar5212Modes, 6); 126186098Ssam HAL_INI_INIT(&ahp->ah_ini_common, ar5212Common, 2); 127185377Ssam 128185377Ssam if (!ar5312ChipReset(ah, AH_NULL)) { /* reset chip */ 129185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__); 130185377Ssam ecode = HAL_EIO; 131185377Ssam goto bad; 132185377Ssam } 133185377Ssam 134185377Ssam#if ( AH_SUPPORT_2316 || AH_SUPPORT_2317) 135185377Ssam if ((devid == AR5212_AR2315_REV6) || 136185377Ssam (devid == AR5212_AR2315_REV7) || 137185377Ssam (devid == AR5212_AR2317_REV1) || 138185377Ssam (devid == AR5212_AR2317_REV2) ) { 139185377Ssam val = ((OS_REG_READ(ah, (AR5315_RSTIMER_BASE -((uint32_t) sh)) + AR5315_WREV)) >> AR5315_WREV_S) 140185377Ssam & AR5315_WREV_ID; 141185377Ssam AH_PRIVATE(ah)->ah_macVersion = val >> AR5315_WREV_ID_S; 142185377Ssam AH_PRIVATE(ah)->ah_macRev = val & AR5315_WREV_REVISION; 143185377Ssam HALDEBUG(ah, HAL_DEBUG_ATTACH, 144185377Ssam "%s: Mac Chip Rev 0x%02x.%x\n" , __func__, 145185377Ssam AH_PRIVATE(ah)->ah_macVersion, AH_PRIVATE(ah)->ah_macRev); 146185377Ssam } else 147185377Ssam#endif 148185377Ssam { 149185377Ssam val = OS_REG_READ(ah, (AR5312_RSTIMER_BASE - ((uint32_t) sh)) + 0x0020); 150185377Ssam val = OS_REG_READ(ah, (AR5312_RSTIMER_BASE - ((uint32_t) sh)) + 0x0080); 151185377Ssam /* Read Revisions from Chips */ 152185377Ssam val = ((OS_REG_READ(ah, (AR5312_RSTIMER_BASE - ((uint32_t) sh)) + AR5312_WREV)) >> AR5312_WREV_S) & AR5312_WREV_ID; 153185377Ssam AH_PRIVATE(ah)->ah_macVersion = val >> AR5312_WREV_ID_S; 154185377Ssam AH_PRIVATE(ah)->ah_macRev = val & AR5312_WREV_REVISION; 155185377Ssam } 156185377Ssam /* XXX - THIS IS WRONG. NEEDS TO BE FIXED */ 157185377Ssam if (((AH_PRIVATE(ah)->ah_macVersion != AR_SREV_VERSION_VENICE && 158185377Ssam AH_PRIVATE(ah)->ah_macVersion != AR_SREV_VERSION_VENICE) || 159185377Ssam AH_PRIVATE(ah)->ah_macRev < AR_SREV_D2PLUS) && 160185377Ssam AH_PRIVATE(ah)->ah_macVersion != AR_SREV_VERSION_COBRA) { 161185377Ssam#ifdef AH_DEBUG 162185377Ssam ath_hal_printf(ah, "%s: Mac Chip Rev 0x%02x.%x is not supported by " 163185377Ssam "this driver\n", __func__, 164185377Ssam AH_PRIVATE(ah)->ah_macVersion, 165185377Ssam AH_PRIVATE(ah)->ah_macRev); 166185377Ssam#endif 167185377Ssam ecode = HAL_ENOTSUPP; 168185377Ssam goto bad; 169185377Ssam } 170185377Ssam 171185377Ssam AH_PRIVATE(ah)->ah_phyRev = OS_REG_READ(ah, AR_PHY_CHIP_ID); 172185377Ssam 173185377Ssam if (!ar5212ChipTest(ah)) { 174185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, "%s: hardware self-test failed\n", 175185377Ssam __func__); 176185377Ssam ecode = HAL_ESELFTEST; 177185377Ssam goto bad; 178185377Ssam } 179185377Ssam 180185377Ssam /* 181185377Ssam * Set correct Baseband to analog shift 182185377Ssam * setting to access analog chips. 183185377Ssam */ 184185377Ssam OS_REG_WRITE(ah, AR_PHY(0), 0x00000007); 185185377Ssam 186185377Ssam /* Read Radio Chip Rev Extract */ 187185377Ssam AH_PRIVATE(ah)->ah_analog5GhzRev = ar5212GetRadioRev(ah); 188185406Ssam 189185406Ssam rf = ath_hal_rfprobe(ah, &ecode); 190185406Ssam if (rf == AH_NULL) 191185377Ssam goto bad; 192185380Ssam if (IS_RAD5112(ah) && !IS_RADX112_REV2(ah)) { 193185377Ssam#ifdef AH_DEBUG 194185377Ssam ath_hal_printf(ah, "%s: 5112 Rev 1 is not supported by this " 195185377Ssam "driver (analog5GhzRev 0x%x)\n", __func__, 196185377Ssam AH_PRIVATE(ah)->ah_analog5GhzRev); 197185377Ssam#endif 198185377Ssam ecode = HAL_ENOTSUPP; 199185377Ssam goto bad; 200185377Ssam } 201185377Ssam 202185377Ssam ecode = ath_hal_legacyEepromAttach(ah); 203185377Ssam if (ecode != HAL_OK) { 204185377Ssam goto bad; 205185377Ssam } 206185377Ssam 207185377Ssam /* 208185377Ssam * If Bmode and AR5212, verify 2.4 analog exists 209185377Ssam */ 210185377Ssam if (ath_hal_eepromGetFlag(ah, AR_EEP_BMODE) && 211185377Ssam (AH_PRIVATE(ah)->ah_analog5GhzRev & 0xF0) == AR_RAD5111_SREV_MAJOR) { 212185377Ssam /* 213185377Ssam * Set correct Baseband to analog shift 214185377Ssam * setting to access analog chips. 215185377Ssam */ 216185377Ssam OS_REG_WRITE(ah, AR_PHY(0), 0x00004007); 217185377Ssam OS_DELAY(2000); 218185377Ssam AH_PRIVATE(ah)->ah_analog2GhzRev = ar5212GetRadioRev(ah); 219185377Ssam 220185377Ssam /* Set baseband for 5GHz chip */ 221185377Ssam OS_REG_WRITE(ah, AR_PHY(0), 0x00000007); 222185377Ssam OS_DELAY(2000); 223185377Ssam if ((AH_PRIVATE(ah)->ah_analog2GhzRev & 0xF0) != AR_RAD2111_SREV_MAJOR) { 224185377Ssam#ifdef AH_DEBUG 225185377Ssam ath_hal_printf(ah, "%s: 2G Radio Chip Rev 0x%02X is not " 226185377Ssam "supported by this driver\n", __func__, 227185377Ssam AH_PRIVATE(ah)->ah_analog2GhzRev); 228185377Ssam#endif 229185377Ssam ecode = HAL_ENOTSUPP; 230185377Ssam goto bad; 231185377Ssam } 232185377Ssam } 233185377Ssam 234185377Ssam ecode = ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, &eeval); 235185377Ssam if (ecode != HAL_OK) { 236185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, 237185377Ssam "%s: cannot read regulatory domain from EEPROM\n", 238185377Ssam __func__); 239185377Ssam goto bad; 240185377Ssam } 241185377Ssam AH_PRIVATE(ah)->ah_currentRD = eeval; 242185377Ssam /* XXX record serial number */ 243185377Ssam 244185377Ssam /* XXX other capabilities */ 245185377Ssam /* 246185377Ssam * Got everything we need now to setup the capabilities. 247185377Ssam */ 248185377Ssam if (!ar5212FillCapabilityInfo(ah)) { 249185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, 250185377Ssam "%s: failed ar5212FillCapabilityInfo\n", __func__); 251185377Ssam ecode = HAL_EEREAD; 252185377Ssam goto bad; 253185377Ssam } 254185377Ssam 255185406Ssam if (!rf->attach(ah, &ecode)) { 256185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RF setup failed, status %u\n", 257185377Ssam __func__, ecode); 258185377Ssam goto bad; 259185377Ssam } 260185377Ssam /* arrange a direct call instead of thunking */ 261185377Ssam AH_PRIVATE(ah)->ah_getNfAdjust = ahp->ah_rfHal->getNfAdjust; 262185377Ssam 263185377Ssam /* Initialize gain ladder thermal calibration structure */ 264185377Ssam ar5212InitializeGainValues(ah); 265185377Ssam 266185377Ssam /* BSP specific call for MAC address of this WMAC device */ 267185377Ssam if (!ar5312GetMacAddr(ah)) { 268185377Ssam ecode = HAL_EEBADMAC; 269185377Ssam goto bad; 270185377Ssam } 271185377Ssam 272185377Ssam ar5312AniSetup(ah); 273185377Ssam ar5212InitNfCalHistBuffer(ah); 274185377Ssam 275185377Ssam /* XXX EAR stuff goes here */ 276185377Ssam return ah; 277185377Ssam 278185377Ssambad: 279185377Ssam if (ahp) 280185377Ssam ar5212Detach((struct ath_hal *) ahp); 281185377Ssam if (status) 282185377Ssam *status = ecode; 283185377Ssam return AH_NULL; 284185377Ssam} 285185377Ssam 286185377Ssamstatic HAL_BOOL 287185377Ssamar5312GetMacAddr(struct ath_hal *ah) 288185377Ssam{ 289185377Ssam const struct ar531x_boarddata *board = AR5312_BOARDCONFIG(ah); 290185377Ssam int wlanNum = AR5312_UNIT(ah); 291185377Ssam const uint8_t *macAddr; 292185377Ssam 293185377Ssam switch (wlanNum) { 294185377Ssam case 0: 295185377Ssam macAddr = board->wlan0Mac; 296185377Ssam break; 297185377Ssam case 1: 298185377Ssam macAddr = board->wlan1Mac; 299185377Ssam break; 300185377Ssam default: 301185377Ssam#ifdef AH_DEBUG 302185377Ssam ath_hal_printf(ah, "Invalid WLAN wmac index (%d)\n", 303185377Ssam wlanNum); 304185377Ssam#endif 305185377Ssam return AH_FALSE; 306185377Ssam } 307185377Ssam OS_MEMCPY(AH5212(ah)->ah_macaddr, macAddr, 6); 308185377Ssam return AH_TRUE; 309185377Ssam} 310185406Ssam 311185406Ssamstatic const char* 312185406Ssamar5312Probe(uint16_t vendorid, uint16_t devid) 313185406Ssam{ 314185406Ssam if (vendorid == ATHEROS_VENDOR_ID) { 315185406Ssam switch (devid) { 316185406Ssam case AR5212_AR5312_REV2: 317185406Ssam case AR5212_AR5312_REV7: 318185406Ssam return "Atheros 5312 WiSoC"; 319185406Ssam case AR5212_AR2313_REV8: 320185406Ssam return "Atheros 2313 WiSoC"; 321185406Ssam case AR5212_AR2315_REV6: 322185406Ssam case AR5212_AR2315_REV7: 323185406Ssam return "Atheros 2315 WiSoC"; 324185406Ssam case AR5212_AR2317_REV1: 325188549Ssam case AR5212_AR2317_REV2: 326185406Ssam return "Atheros 2317 WiSoC"; 327185406Ssam case AR5212_AR2413: 328185406Ssam return "Atheros 2413"; 329185406Ssam case AR5212_AR2417: 330185406Ssam return "Atheros 2417"; 331185406Ssam } 332185406Ssam } 333185406Ssam return AH_NULL; 334185406Ssam} 335185418SsamAH_CHIP(AR5312, ar5312Probe, ar5312Attach); 336