1185377Ssam/* 2187831Ssam * Copyright (c) 2002-2009 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 * 17185907Ssam * $FreeBSD$ 18185377Ssam */ 19185377Ssam#include "opt_ah.h" 20185377Ssam 21185377Ssam#include "ah.h" 22185377Ssam#include "ah_internal.h" 23185377Ssam#include "ah_devid.h" 24185377Ssam#include "ah_desc.h" /* NB: for HAL_PHYERR* */ 25185377Ssam 26185377Ssam#include "ar5212/ar5212.h" 27185377Ssam#include "ar5212/ar5212reg.h" 28185377Ssam#include "ar5212/ar5212phy.h" 29185377Ssam 30185377Ssam#include "ah_eeprom_v3.h" 31185377Ssam 32185377Ssam#define AR_NUM_GPIO 6 /* 6 GPIO pins */ 33185377Ssam#define AR_GPIOD_MASK 0x0000002F /* GPIO data reg r/w mask */ 34185377Ssam 35185377Ssamvoid 36185377Ssamar5212GetMacAddress(struct ath_hal *ah, uint8_t *mac) 37185377Ssam{ 38185377Ssam struct ath_hal_5212 *ahp = AH5212(ah); 39185377Ssam 40185377Ssam OS_MEMCPY(mac, ahp->ah_macaddr, IEEE80211_ADDR_LEN); 41185377Ssam} 42185377Ssam 43185377SsamHAL_BOOL 44185377Ssamar5212SetMacAddress(struct ath_hal *ah, const uint8_t *mac) 45185377Ssam{ 46185377Ssam struct ath_hal_5212 *ahp = AH5212(ah); 47185377Ssam 48185377Ssam OS_MEMCPY(ahp->ah_macaddr, mac, IEEE80211_ADDR_LEN); 49185377Ssam return AH_TRUE; 50185377Ssam} 51185377Ssam 52185377Ssamvoid 53185377Ssamar5212GetBssIdMask(struct ath_hal *ah, uint8_t *mask) 54185377Ssam{ 55185377Ssam struct ath_hal_5212 *ahp = AH5212(ah); 56185377Ssam 57185377Ssam OS_MEMCPY(mask, ahp->ah_bssidmask, IEEE80211_ADDR_LEN); 58185377Ssam} 59185377Ssam 60185377SsamHAL_BOOL 61185377Ssamar5212SetBssIdMask(struct ath_hal *ah, const uint8_t *mask) 62185377Ssam{ 63185377Ssam struct ath_hal_5212 *ahp = AH5212(ah); 64185377Ssam 65185377Ssam /* save it since it must be rewritten on reset */ 66185377Ssam OS_MEMCPY(ahp->ah_bssidmask, mask, IEEE80211_ADDR_LEN); 67185377Ssam 68185377Ssam OS_REG_WRITE(ah, AR_BSSMSKL, LE_READ_4(ahp->ah_bssidmask)); 69185377Ssam OS_REG_WRITE(ah, AR_BSSMSKU, LE_READ_2(ahp->ah_bssidmask + 4)); 70185377Ssam return AH_TRUE; 71185377Ssam} 72185377Ssam 73185377Ssam/* 74185380Ssam * Attempt to change the cards operating regulatory domain to the given value 75185380Ssam */ 76185380SsamHAL_BOOL 77185380Ssamar5212SetRegulatoryDomain(struct ath_hal *ah, 78185380Ssam uint16_t regDomain, HAL_STATUS *status) 79185380Ssam{ 80185380Ssam HAL_STATUS ecode; 81185380Ssam 82185380Ssam if (AH_PRIVATE(ah)->ah_currentRD == regDomain) { 83185380Ssam ecode = HAL_EINVAL; 84185380Ssam goto bad; 85185380Ssam } 86185380Ssam if (ath_hal_eepromGetFlag(ah, AR_EEP_WRITEPROTECT)) { 87185380Ssam ecode = HAL_EEWRITE; 88185380Ssam goto bad; 89185380Ssam } 90185380Ssam#ifdef AH_SUPPORT_WRITE_REGDOMAIN 91185380Ssam if (ath_hal_eepromWrite(ah, AR_EEPROM_REG_DOMAIN, regDomain)) { 92185380Ssam HALDEBUG(ah, HAL_DEBUG_ANY, 93185380Ssam "%s: set regulatory domain to %u (0x%x)\n", 94185380Ssam __func__, regDomain, regDomain); 95185380Ssam AH_PRIVATE(ah)->ah_currentRD = regDomain; 96185380Ssam return AH_TRUE; 97185380Ssam } 98185380Ssam#endif 99185380Ssam ecode = HAL_EIO; 100185380Ssambad: 101185380Ssam if (status) 102185380Ssam *status = ecode; 103185380Ssam return AH_FALSE; 104185380Ssam} 105185380Ssam 106185380Ssam/* 107185377Ssam * Return the wireless modes (a,b,g,t) supported by hardware. 108185377Ssam * 109185377Ssam * This value is what is actually supported by the hardware 110185377Ssam * and is unaffected by regulatory/country code settings. 111185377Ssam */ 112185377Ssamu_int 113185377Ssamar5212GetWirelessModes(struct ath_hal *ah) 114185377Ssam{ 115185377Ssam u_int mode = 0; 116185377Ssam 117185377Ssam if (ath_hal_eepromGetFlag(ah, AR_EEP_AMODE)) { 118185377Ssam mode = HAL_MODE_11A; 119185377Ssam if (!ath_hal_eepromGetFlag(ah, AR_EEP_TURBO5DISABLE)) 120185377Ssam mode |= HAL_MODE_TURBO | HAL_MODE_108A; 121185380Ssam if (AH_PRIVATE(ah)->ah_caps.halChanHalfRate) 122185380Ssam mode |= HAL_MODE_11A_HALF_RATE; 123185380Ssam if (AH_PRIVATE(ah)->ah_caps.halChanQuarterRate) 124185380Ssam mode |= HAL_MODE_11A_QUARTER_RATE; 125185377Ssam } 126185377Ssam if (ath_hal_eepromGetFlag(ah, AR_EEP_BMODE)) 127185377Ssam mode |= HAL_MODE_11B; 128185377Ssam if (ath_hal_eepromGetFlag(ah, AR_EEP_GMODE) && 129185377Ssam AH_PRIVATE(ah)->ah_subvendorid != AR_SUBVENDOR_ID_NOG) { 130185377Ssam mode |= HAL_MODE_11G; 131185377Ssam if (!ath_hal_eepromGetFlag(ah, AR_EEP_TURBO2DISABLE)) 132185377Ssam mode |= HAL_MODE_108G; 133185380Ssam if (AH_PRIVATE(ah)->ah_caps.halChanHalfRate) 134185380Ssam mode |= HAL_MODE_11G_HALF_RATE; 135185380Ssam if (AH_PRIVATE(ah)->ah_caps.halChanQuarterRate) 136185380Ssam mode |= HAL_MODE_11G_QUARTER_RATE; 137185377Ssam } 138185377Ssam return mode; 139185377Ssam} 140185377Ssam 141185377Ssam/* 142185377Ssam * Set the interrupt and GPIO values so the ISR can disable RF 143185377Ssam * on a switch signal. Assumes GPIO port and interrupt polarity 144185377Ssam * are set prior to call. 145185377Ssam */ 146185377Ssamvoid 147185377Ssamar5212EnableRfKill(struct ath_hal *ah) 148185377Ssam{ 149185377Ssam uint16_t rfsilent = AH_PRIVATE(ah)->ah_rfsilent; 150185377Ssam int select = MS(rfsilent, AR_EEPROM_RFSILENT_GPIO_SEL); 151185377Ssam int polarity = MS(rfsilent, AR_EEPROM_RFSILENT_POLARITY); 152185377Ssam 153185377Ssam /* 154185377Ssam * Configure the desired GPIO port for input 155185377Ssam * and enable baseband rf silence. 156185377Ssam */ 157185377Ssam ath_hal_gpioCfgInput(ah, select); 158185377Ssam OS_REG_SET_BIT(ah, AR_PHY(0), 0x00002000); 159185377Ssam /* 160185377Ssam * If radio disable switch connection to GPIO bit x is enabled 161185377Ssam * program GPIO interrupt. 162185377Ssam * If rfkill bit on eeprom is 1, setupeeprommap routine has already 163185377Ssam * verified that it is a later version of eeprom, it has a place for 164185377Ssam * rfkill bit and it is set to 1, indicating that GPIO bit x hardware 165185377Ssam * connection is present. 166185377Ssam */ 167185377Ssam ath_hal_gpioSetIntr(ah, select, 168185377Ssam (ath_hal_gpioGet(ah, select) == polarity ? !polarity : polarity)); 169185377Ssam} 170185377Ssam 171185377Ssam/* 172185377Ssam * Change the LED blinking pattern to correspond to the connectivity 173185377Ssam */ 174185377Ssamvoid 175185377Ssamar5212SetLedState(struct ath_hal *ah, HAL_LED_STATE state) 176185377Ssam{ 177185377Ssam static const uint32_t ledbits[8] = { 178185377Ssam AR_PCICFG_LEDCTL_NONE, /* HAL_LED_INIT */ 179185377Ssam AR_PCICFG_LEDCTL_PEND, /* HAL_LED_SCAN */ 180185377Ssam AR_PCICFG_LEDCTL_PEND, /* HAL_LED_AUTH */ 181185377Ssam AR_PCICFG_LEDCTL_ASSOC, /* HAL_LED_ASSOC*/ 182185377Ssam AR_PCICFG_LEDCTL_ASSOC, /* HAL_LED_RUN */ 183185377Ssam AR_PCICFG_LEDCTL_NONE, 184185377Ssam AR_PCICFG_LEDCTL_NONE, 185185377Ssam AR_PCICFG_LEDCTL_NONE, 186185377Ssam }; 187185377Ssam uint32_t bits; 188185377Ssam 189185377Ssam bits = OS_REG_READ(ah, AR_PCICFG); 190185377Ssam if (IS_2417(ah)) { 191185377Ssam /* 192185377Ssam * Enable LED for Nala. There is a bit marked reserved 193185377Ssam * that must be set and we also turn on the power led. 194185377Ssam * Because we mark s/w LED control setting the control 195185377Ssam * status bits below is meangless (the driver must flash 196185377Ssam * the LED(s) using the GPIO lines). 197185377Ssam */ 198185377Ssam bits = (bits &~ AR_PCICFG_LEDMODE) 199185377Ssam | SM(AR_PCICFG_LEDMODE_POWON, AR_PCICFG_LEDMODE) 200185377Ssam#if 0 201185377Ssam | SM(AR_PCICFG_LEDMODE_NETON, AR_PCICFG_LEDMODE) 202185377Ssam#endif 203185377Ssam | 0x08000000; 204185377Ssam } 205185377Ssam bits = (bits &~ AR_PCICFG_LEDCTL) 206185377Ssam | SM(ledbits[state & 0x7], AR_PCICFG_LEDCTL); 207185377Ssam OS_REG_WRITE(ah, AR_PCICFG, bits); 208185377Ssam} 209185377Ssam 210185377Ssam/* 211185377Ssam * Change association related fields programmed into the hardware. 212185377Ssam * Writing a valid BSSID to the hardware effectively enables the hardware 213185377Ssam * to synchronize its TSF to the correct beacons and receive frames coming 214185377Ssam * from that BSSID. It is called by the SME JOIN operation. 215185377Ssam */ 216185377Ssamvoid 217185377Ssamar5212WriteAssocid(struct ath_hal *ah, const uint8_t *bssid, uint16_t assocId) 218185377Ssam{ 219185377Ssam struct ath_hal_5212 *ahp = AH5212(ah); 220185377Ssam 221226760Sadrian /* save bssid for possible re-use on reset */ 222185377Ssam OS_MEMCPY(ahp->ah_bssid, bssid, IEEE80211_ADDR_LEN); 223226760Sadrian ahp->ah_assocId = assocId; 224185377Ssam OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid)); 225185377Ssam OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid+4) | 226185377Ssam ((assocId & 0x3fff)<<AR_BSS_ID1_AID_S)); 227185377Ssam} 228185377Ssam 229185377Ssam/* 230185377Ssam * Get the current hardware tsf for stamlme 231185377Ssam */ 232185377Ssamuint64_t 233185377Ssamar5212GetTsf64(struct ath_hal *ah) 234185377Ssam{ 235185377Ssam uint32_t low1, low2, u32; 236185377Ssam 237185377Ssam /* sync multi-word read */ 238185377Ssam low1 = OS_REG_READ(ah, AR_TSF_L32); 239185377Ssam u32 = OS_REG_READ(ah, AR_TSF_U32); 240185377Ssam low2 = OS_REG_READ(ah, AR_TSF_L32); 241185377Ssam if (low2 < low1) { /* roll over */ 242185377Ssam /* 243185377Ssam * If we are not preempted this will work. If we are 244185377Ssam * then we re-reading AR_TSF_U32 does no good as the 245185377Ssam * low bits will be meaningless. Likewise reading 246185377Ssam * L32, U32, U32, then comparing the last two reads 247185380Ssam * to check for rollover doesn't help if preempted--so 248185380Ssam * we take this approach as it costs one less PCI read 249185380Ssam * which can be noticeable when doing things like 250185380Ssam * timestamping packets in monitor mode. 251185377Ssam */ 252185377Ssam u32++; 253185377Ssam } 254185377Ssam return (((uint64_t) u32) << 32) | ((uint64_t) low2); 255185377Ssam} 256185377Ssam 257185377Ssam/* 258185377Ssam * Get the current hardware tsf for stamlme 259185377Ssam */ 260185377Ssamuint32_t 261185377Ssamar5212GetTsf32(struct ath_hal *ah) 262185377Ssam{ 263185377Ssam return OS_REG_READ(ah, AR_TSF_L32); 264185377Ssam} 265185377Ssam 266219419Sadrianvoid 267219419Sadrianar5212SetTsf64(struct ath_hal *ah, uint64_t tsf64) 268219419Sadrian{ 269219419Sadrian OS_REG_WRITE(ah, AR_TSF_L32, tsf64 & 0xffffffff); 270219419Sadrian OS_REG_WRITE(ah, AR_TSF_U32, (tsf64 >> 32) & 0xffffffff); 271219419Sadrian} 272219419Sadrian 273185377Ssam/* 274185377Ssam * Reset the current hardware tsf for stamlme. 275185377Ssam */ 276185377Ssamvoid 277185377Ssamar5212ResetTsf(struct ath_hal *ah) 278185377Ssam{ 279185377Ssam 280185377Ssam uint32_t val = OS_REG_READ(ah, AR_BEACON); 281185377Ssam 282185377Ssam OS_REG_WRITE(ah, AR_BEACON, val | AR_BEACON_RESET_TSF); 283185377Ssam /* 284185377Ssam * When resetting the TSF, write twice to the 285185377Ssam * corresponding register; each write to the RESET_TSF bit toggles 286185377Ssam * the internal signal to cause a reset of the TSF - but if the signal 287185377Ssam * is left high, it will reset the TSF on the next chip reset also! 288185377Ssam * writing the bit an even number of times fixes this issue 289185377Ssam */ 290185377Ssam OS_REG_WRITE(ah, AR_BEACON, val | AR_BEACON_RESET_TSF); 291185377Ssam} 292185377Ssam 293185377Ssam/* 294185377Ssam * Set or clear hardware basic rate bit 295185377Ssam * Set hardware basic rate set if basic rate is found 296185377Ssam * and basic rate is equal or less than 2Mbps 297185377Ssam */ 298185377Ssamvoid 299185377Ssamar5212SetBasicRate(struct ath_hal *ah, HAL_RATE_SET *rs) 300185377Ssam{ 301187831Ssam const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan; 302185377Ssam uint32_t reg; 303185377Ssam uint8_t xset; 304185377Ssam int i; 305185377Ssam 306187831Ssam if (chan == AH_NULL || !IEEE80211_IS_CHAN_CCK(chan)) 307185377Ssam return; 308185377Ssam xset = 0; 309185377Ssam for (i = 0; i < rs->rs_count; i++) { 310185377Ssam uint8_t rset = rs->rs_rates[i]; 311185377Ssam /* Basic rate defined? */ 312185377Ssam if ((rset & 0x80) && (rset &= 0x7f) >= xset) 313185377Ssam xset = rset; 314185377Ssam } 315185377Ssam /* 316185377Ssam * Set the h/w bit to reflect whether or not the basic 317185377Ssam * rate is found to be equal or less than 2Mbps. 318185377Ssam */ 319185377Ssam reg = OS_REG_READ(ah, AR_STA_ID1); 320185377Ssam if (xset && xset/2 <= 2) 321185377Ssam OS_REG_WRITE(ah, AR_STA_ID1, reg | AR_STA_ID1_BASE_RATE_11B); 322185377Ssam else 323185377Ssam OS_REG_WRITE(ah, AR_STA_ID1, reg &~ AR_STA_ID1_BASE_RATE_11B); 324185377Ssam} 325185377Ssam 326185377Ssam/* 327185377Ssam * Grab a semi-random value from hardware registers - may not 328185377Ssam * change often 329185377Ssam */ 330185377Ssamuint32_t 331185377Ssamar5212GetRandomSeed(struct ath_hal *ah) 332185377Ssam{ 333185377Ssam uint32_t nf; 334185377Ssam 335185377Ssam nf = (OS_REG_READ(ah, AR_PHY(25)) >> 19) & 0x1ff; 336185377Ssam if (nf & 0x100) 337185377Ssam nf = 0 - ((nf ^ 0x1ff) + 1); 338185377Ssam return (OS_REG_READ(ah, AR_TSF_U32) ^ 339185377Ssam OS_REG_READ(ah, AR_TSF_L32) ^ nf); 340185377Ssam} 341185377Ssam 342185377Ssam/* 343185377Ssam * Detect if our card is present 344185377Ssam */ 345185377SsamHAL_BOOL 346185377Ssamar5212DetectCardPresent(struct ath_hal *ah) 347185377Ssam{ 348185377Ssam uint16_t macVersion, macRev; 349185377Ssam uint32_t v; 350185377Ssam 351185377Ssam /* 352185377Ssam * Read the Silicon Revision register and compare that 353185377Ssam * to what we read at attach time. If the same, we say 354185377Ssam * a card/device is present. 355185377Ssam */ 356185377Ssam v = OS_REG_READ(ah, AR_SREV) & AR_SREV_ID; 357185377Ssam macVersion = v >> AR_SREV_ID_S; 358185377Ssam macRev = v & AR_SREV_REVISION; 359185377Ssam return (AH_PRIVATE(ah)->ah_macVersion == macVersion && 360185377Ssam AH_PRIVATE(ah)->ah_macRev == macRev); 361185377Ssam} 362185377Ssam 363185377Ssamvoid 364185377Ssamar5212EnableMibCounters(struct ath_hal *ah) 365185377Ssam{ 366185377Ssam /* NB: this just resets the mib counter machinery */ 367185377Ssam OS_REG_WRITE(ah, AR_MIBC, 368185377Ssam ~(AR_MIBC_COW | AR_MIBC_FMC | AR_MIBC_CMC | AR_MIBC_MCS) & 0x0f); 369185377Ssam} 370185377Ssam 371185377Ssamvoid 372185377Ssamar5212DisableMibCounters(struct ath_hal *ah) 373185377Ssam{ 374185377Ssam OS_REG_WRITE(ah, AR_MIBC, AR_MIBC | AR_MIBC_CMC); 375185377Ssam} 376185377Ssam 377185377Ssam/* 378185377Ssam * Update MIB Counters 379185377Ssam */ 380185377Ssamvoid 381185377Ssamar5212UpdateMibCounters(struct ath_hal *ah, HAL_MIB_STATS* stats) 382185377Ssam{ 383185377Ssam stats->ackrcv_bad += OS_REG_READ(ah, AR_ACK_FAIL); 384185377Ssam stats->rts_bad += OS_REG_READ(ah, AR_RTS_FAIL); 385185377Ssam stats->fcs_bad += OS_REG_READ(ah, AR_FCS_FAIL); 386185377Ssam stats->rts_good += OS_REG_READ(ah, AR_RTS_OK); 387185377Ssam stats->beacons += OS_REG_READ(ah, AR_BEACON_CNT); 388185377Ssam} 389185377Ssam 390185377Ssam/* 391185377Ssam * Detect if the HW supports spreading a CCK signal on channel 14 392185377Ssam */ 393185377SsamHAL_BOOL 394185377Ssamar5212IsJapanChannelSpreadSupported(struct ath_hal *ah) 395185377Ssam{ 396185377Ssam return AH_TRUE; 397185377Ssam} 398185377Ssam 399185377Ssam/* 400185377Ssam * Get the rssi of frame curently being received. 401185377Ssam */ 402185377Ssamuint32_t 403185377Ssamar5212GetCurRssi(struct ath_hal *ah) 404185377Ssam{ 405185377Ssam return (OS_REG_READ(ah, AR_PHY_CURRENT_RSSI) & 0xff); 406185377Ssam} 407185377Ssam 408185377Ssamu_int 409185377Ssamar5212GetDefAntenna(struct ath_hal *ah) 410185377Ssam{ 411185377Ssam return (OS_REG_READ(ah, AR_DEF_ANTENNA) & 0x7); 412185377Ssam} 413185377Ssam 414185377Ssamvoid 415185377Ssamar5212SetDefAntenna(struct ath_hal *ah, u_int antenna) 416185377Ssam{ 417185377Ssam OS_REG_WRITE(ah, AR_DEF_ANTENNA, (antenna & 0x7)); 418185377Ssam} 419185377Ssam 420185377SsamHAL_ANT_SETTING 421185377Ssamar5212GetAntennaSwitch(struct ath_hal *ah) 422185377Ssam{ 423185380Ssam return AH5212(ah)->ah_antControl; 424185377Ssam} 425185377Ssam 426185377SsamHAL_BOOL 427185380Ssamar5212SetAntennaSwitch(struct ath_hal *ah, HAL_ANT_SETTING setting) 428185377Ssam{ 429185380Ssam struct ath_hal_5212 *ahp = AH5212(ah); 430187831Ssam const struct ieee80211_channel *chan = AH_PRIVATE(ah)->ah_curchan; 431185377Ssam 432187831Ssam if (!ahp->ah_phyPowerOn || chan == AH_NULL) { 433185380Ssam /* PHY powered off, just stash settings */ 434185380Ssam ahp->ah_antControl = setting; 435185380Ssam ahp->ah_diversity = (setting == HAL_ANT_VARIABLE); 436185377Ssam return AH_TRUE; 437185377Ssam } 438187831Ssam return ar5212SetAntennaSwitchInternal(ah, setting, chan); 439185377Ssam} 440185377Ssam 441185377SsamHAL_BOOL 442185377Ssamar5212IsSleepAfterBeaconBroken(struct ath_hal *ah) 443185377Ssam{ 444185377Ssam return AH_TRUE; 445185377Ssam} 446185377Ssam 447185377SsamHAL_BOOL 448185377Ssamar5212SetSifsTime(struct ath_hal *ah, u_int us) 449185377Ssam{ 450185377Ssam struct ath_hal_5212 *ahp = AH5212(ah); 451185377Ssam 452185377Ssam if (us > ath_hal_mac_usec(ah, 0xffff)) { 453185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad SIFS time %u\n", 454185377Ssam __func__, us); 455185377Ssam ahp->ah_sifstime = (u_int) -1; /* restore default handling */ 456185377Ssam return AH_FALSE; 457185377Ssam } else { 458185377Ssam /* convert to system clocks */ 459188866Ssam OS_REG_WRITE(ah, AR_D_GBL_IFS_SIFS, ath_hal_mac_clks(ah, us-2)); 460218409Sadrian ahp->ah_sifstime = us; 461185377Ssam return AH_TRUE; 462185377Ssam } 463185377Ssam} 464185377Ssam 465185377Ssamu_int 466185377Ssamar5212GetSifsTime(struct ath_hal *ah) 467185377Ssam{ 468185377Ssam u_int clks = OS_REG_READ(ah, AR_D_GBL_IFS_SIFS) & 0xffff; 469188866Ssam return ath_hal_mac_usec(ah, clks)+2; /* convert from system clocks */ 470185377Ssam} 471185377Ssam 472185377SsamHAL_BOOL 473185377Ssamar5212SetSlotTime(struct ath_hal *ah, u_int us) 474185377Ssam{ 475185377Ssam struct ath_hal_5212 *ahp = AH5212(ah); 476185377Ssam 477185377Ssam if (us < HAL_SLOT_TIME_6 || us > ath_hal_mac_usec(ah, 0xffff)) { 478185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad slot time %u\n", 479185377Ssam __func__, us); 480185377Ssam ahp->ah_slottime = (u_int) -1; /* restore default handling */ 481185377Ssam return AH_FALSE; 482185377Ssam } else { 483185377Ssam /* convert to system clocks */ 484185377Ssam OS_REG_WRITE(ah, AR_D_GBL_IFS_SLOT, ath_hal_mac_clks(ah, us)); 485185377Ssam ahp->ah_slottime = us; 486185377Ssam return AH_TRUE; 487185377Ssam } 488185377Ssam} 489185377Ssam 490185377Ssamu_int 491185377Ssamar5212GetSlotTime(struct ath_hal *ah) 492185377Ssam{ 493185377Ssam u_int clks = OS_REG_READ(ah, AR_D_GBL_IFS_SLOT) & 0xffff; 494185377Ssam return ath_hal_mac_usec(ah, clks); /* convert from system clocks */ 495185377Ssam} 496185377Ssam 497185377SsamHAL_BOOL 498185377Ssamar5212SetAckTimeout(struct ath_hal *ah, u_int us) 499185377Ssam{ 500185377Ssam struct ath_hal_5212 *ahp = AH5212(ah); 501185377Ssam 502185377Ssam if (us > ath_hal_mac_usec(ah, MS(0xffffffff, AR_TIME_OUT_ACK))) { 503185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad ack timeout %u\n", 504185377Ssam __func__, us); 505185377Ssam ahp->ah_acktimeout = (u_int) -1; /* restore default handling */ 506185377Ssam return AH_FALSE; 507185377Ssam } else { 508185377Ssam /* convert to system clocks */ 509185377Ssam OS_REG_RMW_FIELD(ah, AR_TIME_OUT, 510185377Ssam AR_TIME_OUT_ACK, ath_hal_mac_clks(ah, us)); 511185377Ssam ahp->ah_acktimeout = us; 512185377Ssam return AH_TRUE; 513185377Ssam } 514185377Ssam} 515185377Ssam 516185377Ssamu_int 517185377Ssamar5212GetAckTimeout(struct ath_hal *ah) 518185377Ssam{ 519185377Ssam u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_ACK); 520185377Ssam return ath_hal_mac_usec(ah, clks); /* convert from system clocks */ 521185377Ssam} 522185377Ssam 523185377Ssamu_int 524185377Ssamar5212GetAckCTSRate(struct ath_hal *ah) 525185377Ssam{ 526185377Ssam return ((AH5212(ah)->ah_staId1Defaults & AR_STA_ID1_ACKCTS_6MB) == 0); 527185377Ssam} 528185377Ssam 529185377SsamHAL_BOOL 530185377Ssamar5212SetAckCTSRate(struct ath_hal *ah, u_int high) 531185377Ssam{ 532185377Ssam struct ath_hal_5212 *ahp = AH5212(ah); 533185377Ssam 534185377Ssam if (high) { 535185377Ssam OS_REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_ACKCTS_6MB); 536185377Ssam ahp->ah_staId1Defaults &= ~AR_STA_ID1_ACKCTS_6MB; 537185377Ssam } else { 538185377Ssam OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_ACKCTS_6MB); 539185377Ssam ahp->ah_staId1Defaults |= AR_STA_ID1_ACKCTS_6MB; 540185377Ssam } 541185377Ssam return AH_TRUE; 542185377Ssam} 543185377Ssam 544185377SsamHAL_BOOL 545185377Ssamar5212SetCTSTimeout(struct ath_hal *ah, u_int us) 546185377Ssam{ 547185377Ssam struct ath_hal_5212 *ahp = AH5212(ah); 548185377Ssam 549185377Ssam if (us > ath_hal_mac_usec(ah, MS(0xffffffff, AR_TIME_OUT_CTS))) { 550185377Ssam HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad cts timeout %u\n", 551185377Ssam __func__, us); 552185377Ssam ahp->ah_ctstimeout = (u_int) -1; /* restore default handling */ 553185377Ssam return AH_FALSE; 554185377Ssam } else { 555185377Ssam /* convert to system clocks */ 556185377Ssam OS_REG_RMW_FIELD(ah, AR_TIME_OUT, 557185377Ssam AR_TIME_OUT_CTS, ath_hal_mac_clks(ah, us)); 558185377Ssam ahp->ah_ctstimeout = us; 559185377Ssam return AH_TRUE; 560185377Ssam } 561185377Ssam} 562185377Ssam 563185377Ssamu_int 564185377Ssamar5212GetCTSTimeout(struct ath_hal *ah) 565185377Ssam{ 566185377Ssam u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_CTS); 567185377Ssam return ath_hal_mac_usec(ah, clks); /* convert from system clocks */ 568185377Ssam} 569185377Ssam 570185377Ssam/* Setup decompression for given key index */ 571185377SsamHAL_BOOL 572185377Ssamar5212SetDecompMask(struct ath_hal *ah, uint16_t keyidx, int en) 573185377Ssam{ 574185377Ssam struct ath_hal_5212 *ahp = AH5212(ah); 575185377Ssam 576185377Ssam if (keyidx >= HAL_DECOMP_MASK_SIZE) 577228817Sadrian return AH_FALSE; 578185377Ssam OS_REG_WRITE(ah, AR_DCM_A, keyidx); 579185377Ssam OS_REG_WRITE(ah, AR_DCM_D, en ? AR_DCM_D_EN : 0); 580185377Ssam ahp->ah_decompMask[keyidx] = en; 581185377Ssam 582185377Ssam return AH_TRUE; 583185377Ssam} 584185377Ssam 585185377Ssam/* Setup coverage class */ 586185377Ssamvoid 587185377Ssamar5212SetCoverageClass(struct ath_hal *ah, uint8_t coverageclass, int now) 588185377Ssam{ 589185377Ssam uint32_t slot, timeout, eifs; 590185377Ssam u_int clkRate; 591185377Ssam 592185377Ssam AH_PRIVATE(ah)->ah_coverageClass = coverageclass; 593185377Ssam 594185377Ssam if (now) { 595185377Ssam if (AH_PRIVATE(ah)->ah_coverageClass == 0) 596185377Ssam return; 597185377Ssam 598185377Ssam /* Don't apply coverage class to non A channels */ 599187831Ssam if (!IEEE80211_IS_CHAN_A(AH_PRIVATE(ah)->ah_curchan)) 600185377Ssam return; 601185377Ssam 602185377Ssam /* Get core clock rate */ 603185377Ssam clkRate = ath_hal_mac_clks(ah, 1); 604185377Ssam 605185377Ssam /* Compute EIFS */ 606185377Ssam slot = coverageclass * 3 * clkRate; 607185377Ssam eifs = coverageclass * 6 * clkRate; 608187831Ssam if (IEEE80211_IS_CHAN_HALF(AH_PRIVATE(ah)->ah_curchan)) { 609185377Ssam slot += IFS_SLOT_HALF_RATE; 610185377Ssam eifs += IFS_EIFS_HALF_RATE; 611187831Ssam } else if (IEEE80211_IS_CHAN_QUARTER(AH_PRIVATE(ah)->ah_curchan)) { 612185377Ssam slot += IFS_SLOT_QUARTER_RATE; 613185377Ssam eifs += IFS_EIFS_QUARTER_RATE; 614185377Ssam } else { /* full rate */ 615185377Ssam slot += IFS_SLOT_FULL_RATE; 616185377Ssam eifs += IFS_EIFS_FULL_RATE; 617185377Ssam } 618185377Ssam 619185377Ssam /* 620185377Ssam * Add additional time for air propagation for ACK and CTS 621185377Ssam * timeouts. This value is in core clocks. 622185377Ssam */ 623185377Ssam timeout = ACK_CTS_TIMEOUT_11A + (coverageclass * 3 * clkRate); 624185377Ssam 625185377Ssam /* 626185377Ssam * Write the values: slot, eifs, ack/cts timeouts. 627185377Ssam */ 628185377Ssam OS_REG_WRITE(ah, AR_D_GBL_IFS_SLOT, slot); 629185377Ssam OS_REG_WRITE(ah, AR_D_GBL_IFS_EIFS, eifs); 630185377Ssam OS_REG_WRITE(ah, AR_TIME_OUT, 631185377Ssam SM(timeout, AR_TIME_OUT_CTS) 632185377Ssam | SM(timeout, AR_TIME_OUT_ACK)); 633185377Ssam } 634185377Ssam} 635185377Ssam 636222644SadrianHAL_STATUS 637222644Sadrianar5212SetQuiet(struct ath_hal *ah, uint32_t period, uint32_t duration, 638222644Sadrian uint32_t nextStart, HAL_QUIET_FLAG flag) 639222644Sadrian{ 640222644Sadrian OS_REG_WRITE(ah, AR_QUIET2, period | (duration << AR_QUIET2_QUIET_DUR_S)); 641222644Sadrian if (flag & HAL_QUIET_ENABLE) { 642222644Sadrian OS_REG_WRITE(ah, AR_QUIET1, nextStart | (1 << 16)); 643222644Sadrian } 644222644Sadrian else { 645222644Sadrian OS_REG_WRITE(ah, AR_QUIET1, nextStart); 646222644Sadrian } 647222644Sadrian return HAL_OK; 648222644Sadrian} 649222644Sadrian 650185377Ssamvoid 651185377Ssamar5212SetPCUConfig(struct ath_hal *ah) 652185377Ssam{ 653185377Ssam ar5212SetOperatingMode(ah, AH_PRIVATE(ah)->ah_opmode); 654185377Ssam} 655185377Ssam 656185377Ssam/* 657185377Ssam * Return whether an external 32KHz crystal should be used 658185377Ssam * to reduce power consumption when sleeping. We do so if 659185377Ssam * the crystal is present (obtained from EEPROM) and if we 660185377Ssam * are not running as an AP and are configured to use it. 661185377Ssam */ 662185377SsamHAL_BOOL 663185377Ssamar5212Use32KHzclock(struct ath_hal *ah, HAL_OPMODE opmode) 664185377Ssam{ 665185377Ssam if (opmode != HAL_M_HOSTAP) { 666185377Ssam struct ath_hal_5212 *ahp = AH5212(ah); 667185377Ssam return ath_hal_eepromGetFlag(ah, AR_EEP_32KHZCRYSTAL) && 668185377Ssam (ahp->ah_enable32kHzClock == USE_32KHZ || 669185377Ssam ahp->ah_enable32kHzClock == AUTO_32KHZ); 670185377Ssam } else 671185377Ssam return AH_FALSE; 672185377Ssam} 673185377Ssam 674185377Ssam/* 675185377Ssam * If 32KHz clock exists, use it to lower power consumption during sleep 676185377Ssam * 677185377Ssam * Note: If clock is set to 32 KHz, delays on accessing certain 678185377Ssam * baseband registers (27-31, 124-127) are required. 679185377Ssam */ 680185377Ssamvoid 681185377Ssamar5212SetupClock(struct ath_hal *ah, HAL_OPMODE opmode) 682185377Ssam{ 683185377Ssam if (ar5212Use32KHzclock(ah, opmode)) { 684185377Ssam /* 685185377Ssam * Enable clocks to be turned OFF in BB during sleep 686185377Ssam * and also enable turning OFF 32MHz/40MHz Refclk 687185377Ssam * from A2. 688185377Ssam */ 689185377Ssam OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_CONTROL, 0x1f); 690185380Ssam OS_REG_WRITE(ah, AR_PHY_REFCLKPD, 691185380Ssam IS_RAD5112_ANY(ah) || IS_5413(ah) ? 0x14 : 0x18); 692185377Ssam OS_REG_RMW_FIELD(ah, AR_USEC, AR_USEC_USEC32, 1); 693185377Ssam OS_REG_WRITE(ah, AR_TSF_PARM, 61); /* 32 KHz TSF incr */ 694185377Ssam OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_SEL, 1); 695185377Ssam 696185377Ssam if (IS_2413(ah) || IS_5413(ah) || IS_2417(ah)) { 697185377Ssam OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_LIMIT, 0x26); 698185377Ssam OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0d); 699185377Ssam OS_REG_WRITE(ah, AR_PHY_M_SLEEP, 0x07); 700185377Ssam OS_REG_WRITE(ah, AR_PHY_REFCLKDLY, 0x3f); 701185377Ssam /* # Set sleep clock rate to 32 KHz. */ 702185377Ssam OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_RATE_IND, 0x2); 703185377Ssam } else { 704185377Ssam OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_LIMIT, 0x0a); 705185377Ssam OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0c); 706185377Ssam OS_REG_WRITE(ah, AR_PHY_M_SLEEP, 0x03); 707185377Ssam OS_REG_WRITE(ah, AR_PHY_REFCLKDLY, 0x20); 708185377Ssam OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_RATE_IND, 0x3); 709185377Ssam } 710185377Ssam } else { 711185377Ssam OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_RATE_IND, 0x0); 712185377Ssam OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_SEL, 0); 713185377Ssam 714185377Ssam OS_REG_WRITE(ah, AR_TSF_PARM, 1); /* 32MHz TSF inc */ 715185377Ssam 716185377Ssam OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_CONTROL, 0x1f); 717185377Ssam OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_LIMIT, 0x7f); 718185377Ssam 719185377Ssam if (IS_2417(ah)) 720185377Ssam OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0a); 721185377Ssam else if (IS_HB63(ah)) 722185377Ssam OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x32); 723185377Ssam else 724185377Ssam OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0e); 725185377Ssam OS_REG_WRITE(ah, AR_PHY_M_SLEEP, 0x0c); 726185377Ssam OS_REG_WRITE(ah, AR_PHY_REFCLKDLY, 0xff); 727185377Ssam OS_REG_WRITE(ah, AR_PHY_REFCLKPD, 728185380Ssam IS_RAD5112_ANY(ah) || IS_5413(ah) || IS_2417(ah) ? 0x14 : 0x18); 729185380Ssam OS_REG_RMW_FIELD(ah, AR_USEC, AR_USEC_USEC32, 730185380Ssam IS_RAD5112_ANY(ah) || IS_5413(ah) ? 39 : 31); 731185377Ssam } 732185377Ssam} 733185377Ssam 734185377Ssam/* 735185377Ssam * If 32KHz clock exists, turn it off and turn back on the 32Mhz 736185377Ssam */ 737185377Ssamvoid 738185377Ssamar5212RestoreClock(struct ath_hal *ah, HAL_OPMODE opmode) 739185377Ssam{ 740185377Ssam if (ar5212Use32KHzclock(ah, opmode)) { 741185377Ssam /* # Set sleep clock rate back to 32 MHz. */ 742185377Ssam OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_RATE_IND, 0); 743185377Ssam OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_SEL, 0); 744185377Ssam 745185377Ssam OS_REG_WRITE(ah, AR_TSF_PARM, 1); /* 32 MHz TSF incr */ 746185380Ssam OS_REG_RMW_FIELD(ah, AR_USEC, AR_USEC_USEC32, 747185380Ssam IS_RAD5112_ANY(ah) || IS_5413(ah) ? 39 : 31); 748185377Ssam 749185377Ssam /* 750185377Ssam * Restore BB registers to power-on defaults 751185377Ssam */ 752185377Ssam OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_CONTROL, 0x1f); 753185377Ssam OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_LIMIT, 0x7f); 754185377Ssam OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0e); 755185377Ssam OS_REG_WRITE(ah, AR_PHY_M_SLEEP, 0x0c); 756185377Ssam OS_REG_WRITE(ah, AR_PHY_REFCLKDLY, 0xff); 757185380Ssam OS_REG_WRITE(ah, AR_PHY_REFCLKPD, 758185380Ssam IS_RAD5112_ANY(ah) || IS_5413(ah) ? 0x14 : 0x18); 759185377Ssam } 760185377Ssam} 761185377Ssam 762185377Ssam/* 763185377Ssam * Adjust NF based on statistical values for 5GHz frequencies. 764185377Ssam * Default method: this may be overridden by the rf backend. 765185377Ssam */ 766185377Ssamint16_t 767185377Ssamar5212GetNfAdjust(struct ath_hal *ah, const HAL_CHANNEL_INTERNAL *c) 768185377Ssam{ 769185377Ssam static const struct { 770185377Ssam uint16_t freqLow; 771185377Ssam int16_t adjust; 772185377Ssam } adjustDef[] = { 773185377Ssam { 5790, 11 }, /* NB: ordered high -> low */ 774185377Ssam { 5730, 10 }, 775185377Ssam { 5690, 9 }, 776185377Ssam { 5660, 8 }, 777185377Ssam { 5610, 7 }, 778185377Ssam { 5530, 5 }, 779185377Ssam { 5450, 4 }, 780185377Ssam { 5379, 2 }, 781185377Ssam { 5209, 0 }, 782185377Ssam { 3000, 1 }, 783185377Ssam { 0, 0 }, 784185377Ssam }; 785185377Ssam int i; 786185377Ssam 787185377Ssam for (i = 0; c->channel <= adjustDef[i].freqLow; i++) 788185377Ssam ; 789185377Ssam return adjustDef[i].adjust; 790185377Ssam} 791185377Ssam 792185377SsamHAL_STATUS 793185377Ssamar5212GetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, 794185377Ssam uint32_t capability, uint32_t *result) 795185377Ssam{ 796185377Ssam#define MACVERSION(ah) AH_PRIVATE(ah)->ah_macVersion 797185377Ssam struct ath_hal_5212 *ahp = AH5212(ah); 798185377Ssam const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps; 799185377Ssam const struct ar5212AniState *ani; 800185377Ssam 801185377Ssam switch (type) { 802185377Ssam case HAL_CAP_CIPHER: /* cipher handled in hardware */ 803185377Ssam switch (capability) { 804185377Ssam case HAL_CIPHER_AES_CCM: 805185377Ssam return pCap->halCipherAesCcmSupport ? 806185377Ssam HAL_OK : HAL_ENOTSUPP; 807185377Ssam case HAL_CIPHER_AES_OCB: 808185377Ssam case HAL_CIPHER_TKIP: 809185377Ssam case HAL_CIPHER_WEP: 810185377Ssam case HAL_CIPHER_MIC: 811185377Ssam case HAL_CIPHER_CLR: 812185377Ssam return HAL_OK; 813185377Ssam default: 814185377Ssam return HAL_ENOTSUPP; 815185377Ssam } 816185377Ssam case HAL_CAP_TKIP_MIC: /* handle TKIP MIC in hardware */ 817185377Ssam switch (capability) { 818185377Ssam case 0: /* hardware capability */ 819185377Ssam return HAL_OK; 820185377Ssam case 1: 821185377Ssam return (ahp->ah_staId1Defaults & 822185377Ssam AR_STA_ID1_CRPT_MIC_ENABLE) ? HAL_OK : HAL_ENXIO; 823185377Ssam } 824185907Ssam return HAL_EINVAL; 825185377Ssam case HAL_CAP_TKIP_SPLIT: /* hardware TKIP uses split keys */ 826185377Ssam switch (capability) { 827185377Ssam case 0: /* hardware capability */ 828185377Ssam return pCap->halTkipMicTxRxKeySupport ? 829185377Ssam HAL_ENXIO : HAL_OK; 830185377Ssam case 1: /* current setting */ 831185377Ssam return (ahp->ah_miscMode & 832185377Ssam AR_MISC_MODE_MIC_NEW_LOC_ENABLE) ? HAL_ENXIO : HAL_OK; 833185377Ssam } 834185377Ssam return HAL_EINVAL; 835185377Ssam case HAL_CAP_WME_TKIPMIC: /* hardware can do TKIP MIC w/ WMM */ 836185377Ssam /* XXX move to capability bit */ 837185377Ssam return MACVERSION(ah) > AR_SREV_VERSION_VENICE || 838185377Ssam (MACVERSION(ah) == AR_SREV_VERSION_VENICE && 839185377Ssam AH_PRIVATE(ah)->ah_macRev >= 8) ? HAL_OK : HAL_ENOTSUPP; 840185377Ssam case HAL_CAP_DIVERSITY: /* hardware supports fast diversity */ 841185377Ssam switch (capability) { 842185377Ssam case 0: /* hardware capability */ 843185377Ssam return HAL_OK; 844185377Ssam case 1: /* current setting */ 845185380Ssam return ahp->ah_diversity ? HAL_OK : HAL_ENXIO; 846239801Sadrian case HAL_CAP_STRONG_DIV: 847239801Sadrian *result = OS_REG_READ(ah, AR_PHY_RESTART); 848239801Sadrian *result = MS(*result, AR_PHY_RESTART_DIV_GC); 849239801Sadrian return HAL_OK; 850185377Ssam } 851185377Ssam return HAL_EINVAL; 852185377Ssam case HAL_CAP_DIAG: 853185377Ssam *result = AH_PRIVATE(ah)->ah_diagreg; 854185377Ssam return HAL_OK; 855185377Ssam case HAL_CAP_TPC: 856185377Ssam switch (capability) { 857185377Ssam case 0: /* hardware capability */ 858185377Ssam return HAL_OK; 859185377Ssam case 1: 860185377Ssam return ahp->ah_tpcEnabled ? HAL_OK : HAL_ENXIO; 861185377Ssam } 862185377Ssam return HAL_OK; 863185377Ssam case HAL_CAP_PHYDIAG: /* radar pulse detection capability */ 864185377Ssam switch (capability) { 865185377Ssam case HAL_CAP_RADAR: 866185377Ssam return ath_hal_eepromGetFlag(ah, AR_EEP_AMODE) ? 867185377Ssam HAL_OK: HAL_ENXIO; 868185377Ssam case HAL_CAP_AR: 869185377Ssam return (ath_hal_eepromGetFlag(ah, AR_EEP_GMODE) || 870185377Ssam ath_hal_eepromGetFlag(ah, AR_EEP_BMODE)) ? 871185377Ssam HAL_OK: HAL_ENXIO; 872185377Ssam } 873185377Ssam return HAL_ENXIO; 874185377Ssam case HAL_CAP_MCAST_KEYSRCH: /* multicast frame keycache search */ 875185377Ssam switch (capability) { 876185377Ssam case 0: /* hardware capability */ 877222027Sadrian return pCap->halMcastKeySrchSupport ? HAL_OK : HAL_ENXIO; 878185377Ssam case 1: 879185377Ssam return (ahp->ah_staId1Defaults & 880185377Ssam AR_STA_ID1_MCAST_KSRCH) ? HAL_OK : HAL_ENXIO; 881185377Ssam } 882185377Ssam return HAL_EINVAL; 883185377Ssam case HAL_CAP_TSF_ADJUST: /* hardware has beacon tsf adjust */ 884185377Ssam switch (capability) { 885185377Ssam case 0: /* hardware capability */ 886185377Ssam return pCap->halTsfAddSupport ? HAL_OK : HAL_ENOTSUPP; 887185377Ssam case 1: 888185377Ssam return (ahp->ah_miscMode & AR_MISC_MODE_TX_ADD_TSF) ? 889185377Ssam HAL_OK : HAL_ENXIO; 890185377Ssam } 891185377Ssam return HAL_EINVAL; 892185377Ssam case HAL_CAP_TPC_ACK: 893185377Ssam *result = MS(ahp->ah_macTPC, AR_TPC_ACK); 894185377Ssam return HAL_OK; 895185377Ssam case HAL_CAP_TPC_CTS: 896185377Ssam *result = MS(ahp->ah_macTPC, AR_TPC_CTS); 897185377Ssam return HAL_OK; 898185377Ssam case HAL_CAP_INTMIT: /* interference mitigation */ 899185377Ssam switch (capability) { 900222277Sadrian case HAL_CAP_INTMIT_PRESENT: /* hardware capability */ 901185377Ssam return HAL_OK; 902222277Sadrian case HAL_CAP_INTMIT_ENABLE: 903185377Ssam return (ahp->ah_procPhyErr & HAL_ANI_ENA) ? 904185377Ssam HAL_OK : HAL_ENXIO; 905222277Sadrian case HAL_CAP_INTMIT_NOISE_IMMUNITY_LEVEL: 906222277Sadrian case HAL_CAP_INTMIT_OFDM_WEAK_SIGNAL_LEVEL: 907222277Sadrian case HAL_CAP_INTMIT_CCK_WEAK_SIGNAL_THR: 908222277Sadrian case HAL_CAP_INTMIT_FIRSTEP_LEVEL: 909222277Sadrian case HAL_CAP_INTMIT_SPUR_IMMUNITY_LEVEL: 910185377Ssam ani = ar5212AniGetCurrentState(ah); 911185377Ssam if (ani == AH_NULL) 912185377Ssam return HAL_ENXIO; 913185377Ssam switch (capability) { 914185377Ssam case 2: *result = ani->noiseImmunityLevel; break; 915185377Ssam case 3: *result = !ani->ofdmWeakSigDetectOff; break; 916185377Ssam case 4: *result = ani->cckWeakSigThreshold; break; 917185377Ssam case 5: *result = ani->firstepLevel; break; 918185377Ssam case 6: *result = ani->spurImmunityLevel; break; 919185377Ssam } 920185377Ssam return HAL_OK; 921185377Ssam } 922185377Ssam return HAL_EINVAL; 923185377Ssam default: 924185377Ssam return ath_hal_getcapability(ah, type, capability, result); 925185377Ssam } 926185377Ssam#undef MACVERSION 927185377Ssam} 928185377Ssam 929185377SsamHAL_BOOL 930185377Ssamar5212SetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, 931185377Ssam uint32_t capability, uint32_t setting, HAL_STATUS *status) 932185377Ssam{ 933185377Ssam#define N(a) (sizeof(a)/sizeof(a[0])) 934185377Ssam struct ath_hal_5212 *ahp = AH5212(ah); 935185377Ssam const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps; 936185377Ssam uint32_t v; 937185377Ssam 938185377Ssam switch (type) { 939185377Ssam case HAL_CAP_TKIP_MIC: /* handle TKIP MIC in hardware */ 940185377Ssam if (setting) 941185377Ssam ahp->ah_staId1Defaults |= AR_STA_ID1_CRPT_MIC_ENABLE; 942185377Ssam else 943185377Ssam ahp->ah_staId1Defaults &= ~AR_STA_ID1_CRPT_MIC_ENABLE; 944185377Ssam return AH_TRUE; 945185377Ssam case HAL_CAP_TKIP_SPLIT: /* hardware TKIP uses split keys */ 946185377Ssam if (!pCap->halTkipMicTxRxKeySupport) 947185377Ssam return AH_FALSE; 948185377Ssam /* NB: true =>'s use split key cache layout */ 949185377Ssam if (setting) 950185377Ssam ahp->ah_miscMode &= ~AR_MISC_MODE_MIC_NEW_LOC_ENABLE; 951185377Ssam else 952185377Ssam ahp->ah_miscMode |= AR_MISC_MODE_MIC_NEW_LOC_ENABLE; 953185377Ssam /* NB: write here so keys can be setup w/o a reset */ 954219771Sadrian OS_REG_WRITE(ah, AR_MISC_MODE, OS_REG_READ(ah, AR_MISC_MODE) | ahp->ah_miscMode); 955185377Ssam return AH_TRUE; 956185377Ssam case HAL_CAP_DIVERSITY: 957239801Sadrian switch (capability) { 958239801Sadrian case 0: 959239801Sadrian return AH_FALSE; 960239801Sadrian case 1: /* setting */ 961239801Sadrian if (ahp->ah_phyPowerOn) { 962239801Sadrian if (capability == HAL_CAP_STRONG_DIV) { 963240001Sadrian v = OS_REG_READ(ah, AR_PHY_CCK_DETECT); 964240001Sadrian if (setting) 965240001Sadrian v |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV; 966240001Sadrian else 967240001Sadrian v &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV; 968240001Sadrian OS_REG_WRITE(ah, AR_PHY_CCK_DETECT, v); 969240001Sadrian } 970239801Sadrian } 971239801Sadrian ahp->ah_diversity = (setting != 0); 972239801Sadrian return AH_TRUE; 973239801Sadrian 974239801Sadrian case HAL_CAP_STRONG_DIV: 975239801Sadrian if (! ahp->ah_phyPowerOn) 976239801Sadrian return AH_FALSE; 977239801Sadrian v = OS_REG_READ(ah, AR_PHY_RESTART); 978239801Sadrian v &= ~AR_PHY_RESTART_DIV_GC; 979239801Sadrian v |= SM(setting, AR_PHY_RESTART_DIV_GC); 980239801Sadrian OS_REG_WRITE(ah, AR_PHY_RESTART, v); 981239801Sadrian return AH_TRUE; 982239801Sadrian default: 983239801Sadrian return AH_FALSE; 984185380Ssam } 985185377Ssam case HAL_CAP_DIAG: /* hardware diagnostic support */ 986185377Ssam /* 987185377Ssam * NB: could split this up into virtual capabilities, 988185377Ssam * (e.g. 1 => ACK, 2 => CTS, etc.) but it hardly 989185377Ssam * seems worth the additional complexity. 990185377Ssam */ 991185377Ssam AH_PRIVATE(ah)->ah_diagreg = setting; 992185377Ssam OS_REG_WRITE(ah, AR_DIAG_SW, AH_PRIVATE(ah)->ah_diagreg); 993185377Ssam return AH_TRUE; 994185377Ssam case HAL_CAP_TPC: 995185377Ssam ahp->ah_tpcEnabled = (setting != 0); 996185377Ssam return AH_TRUE; 997185377Ssam case HAL_CAP_MCAST_KEYSRCH: /* multicast frame keycache search */ 998185377Ssam if (setting) 999185377Ssam ahp->ah_staId1Defaults |= AR_STA_ID1_MCAST_KSRCH; 1000185377Ssam else 1001185377Ssam ahp->ah_staId1Defaults &= ~AR_STA_ID1_MCAST_KSRCH; 1002185377Ssam return AH_TRUE; 1003185377Ssam case HAL_CAP_TPC_ACK: 1004185377Ssam case HAL_CAP_TPC_CTS: 1005185377Ssam setting += ahp->ah_txPowerIndexOffset; 1006185377Ssam if (setting > 63) 1007185377Ssam setting = 63; 1008185377Ssam if (type == HAL_CAP_TPC_ACK) { 1009185377Ssam ahp->ah_macTPC &= AR_TPC_ACK; 1010185377Ssam ahp->ah_macTPC |= MS(setting, AR_TPC_ACK); 1011185377Ssam } else { 1012185377Ssam ahp->ah_macTPC &= AR_TPC_CTS; 1013185377Ssam ahp->ah_macTPC |= MS(setting, AR_TPC_CTS); 1014185377Ssam } 1015185377Ssam OS_REG_WRITE(ah, AR_TPC, ahp->ah_macTPC); 1016185377Ssam return AH_TRUE; 1017185377Ssam case HAL_CAP_INTMIT: { /* interference mitigation */ 1018222277Sadrian /* This maps the public ANI commands to the internal ANI commands */ 1019222277Sadrian /* Private: HAL_ANI_CMD; Public: HAL_CAP_INTMIT_CMD */ 1020185377Ssam static const HAL_ANI_CMD cmds[] = { 1021185377Ssam HAL_ANI_PRESENT, 1022185377Ssam HAL_ANI_MODE, 1023185377Ssam HAL_ANI_NOISE_IMMUNITY_LEVEL, 1024185377Ssam HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION, 1025185377Ssam HAL_ANI_CCK_WEAK_SIGNAL_THR, 1026185377Ssam HAL_ANI_FIRSTEP_LEVEL, 1027185377Ssam HAL_ANI_SPUR_IMMUNITY_LEVEL, 1028185377Ssam }; 1029185377Ssam return capability < N(cmds) ? 1030222265Sadrian AH5212(ah)->ah_aniControl(ah, cmds[capability], setting) : 1031185377Ssam AH_FALSE; 1032185377Ssam } 1033185377Ssam case HAL_CAP_TSF_ADJUST: /* hardware has beacon tsf adjust */ 1034185377Ssam if (pCap->halTsfAddSupport) { 1035185377Ssam if (setting) 1036185377Ssam ahp->ah_miscMode |= AR_MISC_MODE_TX_ADD_TSF; 1037185377Ssam else 1038185377Ssam ahp->ah_miscMode &= ~AR_MISC_MODE_TX_ADD_TSF; 1039185377Ssam return AH_TRUE; 1040185377Ssam } 1041185377Ssam /* fall thru... */ 1042185377Ssam default: 1043185377Ssam return ath_hal_setcapability(ah, type, capability, 1044185377Ssam setting, status); 1045185377Ssam } 1046185377Ssam#undef N 1047185377Ssam} 1048185377Ssam 1049185377SsamHAL_BOOL 1050185377Ssamar5212GetDiagState(struct ath_hal *ah, int request, 1051185377Ssam const void *args, uint32_t argsize, 1052185377Ssam void **result, uint32_t *resultsize) 1053185377Ssam{ 1054185377Ssam struct ath_hal_5212 *ahp = AH5212(ah); 1055185377Ssam 1056185377Ssam (void) ahp; 1057185377Ssam if (ath_hal_getdiagstate(ah, request, args, argsize, result, resultsize)) 1058185377Ssam return AH_TRUE; 1059185377Ssam switch (request) { 1060185377Ssam case HAL_DIAG_EEPROM: 1061185377Ssam case HAL_DIAG_EEPROM_EXP_11A: 1062185377Ssam case HAL_DIAG_EEPROM_EXP_11B: 1063185377Ssam case HAL_DIAG_EEPROM_EXP_11G: 1064185377Ssam case HAL_DIAG_RFGAIN: 1065185377Ssam return ath_hal_eepromDiag(ah, request, 1066185377Ssam args, argsize, result, resultsize); 1067185377Ssam case HAL_DIAG_RFGAIN_CURSTEP: 1068185377Ssam *result = __DECONST(void *, ahp->ah_gainValues.currStep); 1069185377Ssam *resultsize = (*result == AH_NULL) ? 1070185377Ssam 0 : sizeof(GAIN_OPTIMIZATION_STEP); 1071185377Ssam return AH_TRUE; 1072185377Ssam case HAL_DIAG_PCDAC: 1073185377Ssam *result = ahp->ah_pcdacTable; 1074185377Ssam *resultsize = ahp->ah_pcdacTableSize; 1075185377Ssam return AH_TRUE; 1076185377Ssam case HAL_DIAG_TXRATES: 1077185377Ssam *result = &ahp->ah_ratesArray[0]; 1078185377Ssam *resultsize = sizeof(ahp->ah_ratesArray); 1079185377Ssam return AH_TRUE; 1080185377Ssam case HAL_DIAG_ANI_CURRENT: 1081185377Ssam *result = ar5212AniGetCurrentState(ah); 1082185377Ssam *resultsize = (*result == AH_NULL) ? 1083185377Ssam 0 : sizeof(struct ar5212AniState); 1084185377Ssam return AH_TRUE; 1085185377Ssam case HAL_DIAG_ANI_STATS: 1086185377Ssam *result = ar5212AniGetCurrentStats(ah); 1087185377Ssam *resultsize = (*result == AH_NULL) ? 1088185377Ssam 0 : sizeof(struct ar5212Stats); 1089185377Ssam return AH_TRUE; 1090185377Ssam case HAL_DIAG_ANI_CMD: 1091185377Ssam if (argsize != 2*sizeof(uint32_t)) 1092185377Ssam return AH_FALSE; 1093222265Sadrian AH5212(ah)->ah_aniControl(ah, ((const uint32_t *)args)[0], 1094185377Ssam ((const uint32_t *)args)[1]); 1095185377Ssam return AH_TRUE; 1096185377Ssam case HAL_DIAG_ANI_PARAMS: 1097185377Ssam /* 1098185377Ssam * NB: We assume struct ar5212AniParams is identical 1099185377Ssam * to HAL_ANI_PARAMS; if they diverge then we'll need 1100185377Ssam * to handle it here 1101185377Ssam */ 1102185377Ssam if (argsize == 0 && args == AH_NULL) { 1103185377Ssam struct ar5212AniState *aniState = 1104185377Ssam ar5212AniGetCurrentState(ah); 1105185377Ssam if (aniState == AH_NULL) 1106185377Ssam return AH_FALSE; 1107185377Ssam *result = __DECONST(void *, aniState->params); 1108185377Ssam *resultsize = sizeof(struct ar5212AniParams); 1109185377Ssam return AH_TRUE; 1110185377Ssam } else { 1111185377Ssam if (argsize != sizeof(struct ar5212AniParams)) 1112185377Ssam return AH_FALSE; 1113185377Ssam return ar5212AniSetParams(ah, args, args); 1114185377Ssam } 1115234750Sadrian break; 1116234750Sadrian case HAL_DIAG_CHANSURVEY: 1117234774Sadrian *result = &ahp->ah_chansurvey; 1118234750Sadrian *resultsize = sizeof(HAL_CHANNEL_SURVEY); 1119234750Sadrian return AH_TRUE; 1120185377Ssam } 1121185377Ssam return AH_FALSE; 1122185377Ssam} 1123211206Sadrian 1124211206Sadrian/* 1125211206Sadrian * Check whether there's an in-progress NF completion. 1126211206Sadrian * 1127211206Sadrian * Returns AH_TRUE if there's a in-progress NF calibration, AH_FALSE 1128211206Sadrian * otherwise. 1129211206Sadrian */ 1130211206SadrianHAL_BOOL 1131211206Sadrianar5212IsNFCalInProgress(struct ath_hal *ah) 1132211206Sadrian{ 1133211206Sadrian if (OS_REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) 1134211206Sadrian return AH_TRUE; 1135211206Sadrian return AH_FALSE; 1136211206Sadrian} 1137211206Sadrian 1138211206Sadrian/* 1139211206Sadrian * Wait for an in-progress NF calibration to complete. 1140211206Sadrian * 1141211206Sadrian * The completion function waits "i" times 10uS. 1142211206Sadrian * It returns AH_TRUE if the NF calibration completed (or was never 1143211206Sadrian * in progress); AH_FALSE if it was still in progress after "i" checks. 1144211206Sadrian */ 1145211206SadrianHAL_BOOL 1146211206Sadrianar5212WaitNFCalComplete(struct ath_hal *ah, int i) 1147211206Sadrian{ 1148211206Sadrian int j; 1149211206Sadrian if (i <= 0) 1150211206Sadrian i = 1; /* it should run at least once */ 1151211206Sadrian for (j = 0; j < i; j++) { 1152211206Sadrian if (! ar5212IsNFCalInProgress(ah)) 1153211206Sadrian return AH_TRUE; 1154211206Sadrian OS_DELAY(10); 1155211206Sadrian } 1156211206Sadrian return AH_FALSE; 1157211206Sadrian} 1158222584Sadrian 1159222584Sadrianvoid 1160222584Sadrianar5212EnableDfs(struct ath_hal *ah, HAL_PHYERR_PARAM *pe) 1161222584Sadrian{ 1162222584Sadrian uint32_t val; 1163222584Sadrian val = OS_REG_READ(ah, AR_PHY_RADAR_0); 1164222584Sadrian 1165222584Sadrian if (pe->pe_firpwr != HAL_PHYERR_PARAM_NOVAL) { 1166222584Sadrian val &= ~AR_PHY_RADAR_0_FIRPWR; 1167222584Sadrian val |= SM(pe->pe_firpwr, AR_PHY_RADAR_0_FIRPWR); 1168222584Sadrian } 1169222584Sadrian if (pe->pe_rrssi != HAL_PHYERR_PARAM_NOVAL) { 1170222584Sadrian val &= ~AR_PHY_RADAR_0_RRSSI; 1171222584Sadrian val |= SM(pe->pe_rrssi, AR_PHY_RADAR_0_RRSSI); 1172222584Sadrian } 1173222584Sadrian if (pe->pe_height != HAL_PHYERR_PARAM_NOVAL) { 1174222584Sadrian val &= ~AR_PHY_RADAR_0_HEIGHT; 1175222584Sadrian val |= SM(pe->pe_height, AR_PHY_RADAR_0_HEIGHT); 1176222584Sadrian } 1177222584Sadrian if (pe->pe_prssi != HAL_PHYERR_PARAM_NOVAL) { 1178222584Sadrian val &= ~AR_PHY_RADAR_0_PRSSI; 1179222584Sadrian val |= SM(pe->pe_prssi, AR_PHY_RADAR_0_PRSSI); 1180222584Sadrian } 1181222584Sadrian if (pe->pe_inband != HAL_PHYERR_PARAM_NOVAL) { 1182222584Sadrian val &= ~AR_PHY_RADAR_0_INBAND; 1183222584Sadrian val |= SM(pe->pe_inband, AR_PHY_RADAR_0_INBAND); 1184222584Sadrian } 1185239657Sadrian if (pe->pe_enabled) 1186239657Sadrian val |= AR_PHY_RADAR_0_ENA; 1187239657Sadrian else 1188239657Sadrian val &= ~ AR_PHY_RADAR_0_ENA; 1189239657Sadrian 1190239801Sadrian if (IS_5413(ah)) { 1191239801Sadrian 1192239801Sadrian if (pe->pe_blockradar == 1) 1193239801Sadrian OS_REG_SET_BIT(ah, AR_PHY_RADAR_2, 1194239801Sadrian AR_PHY_RADAR_2_BLOCKOFDMWEAK); 1195239801Sadrian else 1196239801Sadrian OS_REG_CLR_BIT(ah, AR_PHY_RADAR_2, 1197239801Sadrian AR_PHY_RADAR_2_BLOCKOFDMWEAK); 1198239801Sadrian 1199239801Sadrian if (pe->pe_en_relstep_check == 1) 1200239801Sadrian OS_REG_SET_BIT(ah, AR_PHY_RADAR_2, 1201239801Sadrian AR_PHY_RADAR_2_ENRELSTEPCHK); 1202239801Sadrian else 1203239801Sadrian OS_REG_CLR_BIT(ah, AR_PHY_RADAR_2, 1204239801Sadrian AR_PHY_RADAR_2_ENRELSTEPCHK); 1205239801Sadrian 1206239801Sadrian if (pe->pe_usefir128 == 1) 1207239801Sadrian OS_REG_SET_BIT(ah, AR_PHY_RADAR_2, 1208239801Sadrian AR_PHY_RADAR_2_USEFIR128); 1209239801Sadrian else 1210239801Sadrian OS_REG_CLR_BIT(ah, AR_PHY_RADAR_2, 1211239801Sadrian AR_PHY_RADAR_2_USEFIR128); 1212239801Sadrian 1213239801Sadrian if (pe->pe_enmaxrssi == 1) 1214239801Sadrian OS_REG_SET_BIT(ah, AR_PHY_RADAR_2, 1215239801Sadrian AR_PHY_RADAR_2_ENMAXRSSI); 1216239801Sadrian else 1217239801Sadrian OS_REG_CLR_BIT(ah, AR_PHY_RADAR_2, 1218239801Sadrian AR_PHY_RADAR_2_ENMAXRSSI); 1219239801Sadrian 1220239801Sadrian if (pe->pe_enrelpwr == 1) 1221239801Sadrian OS_REG_SET_BIT(ah, AR_PHY_RADAR_2, 1222239801Sadrian AR_PHY_RADAR_2_ENRELPWRCHK); 1223239801Sadrian else 1224239801Sadrian OS_REG_CLR_BIT(ah, AR_PHY_RADAR_2, 1225239801Sadrian AR_PHY_RADAR_2_ENRELPWRCHK); 1226239801Sadrian 1227239801Sadrian if (pe->pe_relpwr != HAL_PHYERR_PARAM_NOVAL) 1228239801Sadrian OS_REG_RMW_FIELD(ah, AR_PHY_RADAR_2, 1229239801Sadrian AR_PHY_RADAR_2_RELPWR, pe->pe_relpwr); 1230239801Sadrian 1231239801Sadrian if (pe->pe_relstep != HAL_PHYERR_PARAM_NOVAL) 1232239801Sadrian OS_REG_RMW_FIELD(ah, AR_PHY_RADAR_2, 1233239801Sadrian AR_PHY_RADAR_2_RELSTEP, pe->pe_relstep); 1234239801Sadrian 1235239801Sadrian if (pe->pe_maxlen != HAL_PHYERR_PARAM_NOVAL) 1236239801Sadrian OS_REG_RMW_FIELD(ah, AR_PHY_RADAR_2, 1237239801Sadrian AR_PHY_RADAR_2_MAXLEN, pe->pe_maxlen); 1238239801Sadrian } 1239239801Sadrian 1240239657Sadrian OS_REG_WRITE(ah, AR_PHY_RADAR_0, val); 1241222584Sadrian} 1242222584Sadrian 1243239642Sadrian/* 1244239642Sadrian * Parameters for the AR5212 PHY. 1245239642Sadrian */ 1246240001Sadrian#define AR5212_DFS_FIRPWR -35 1247240001Sadrian#define AR5212_DFS_RRSSI 20 1248240001Sadrian#define AR5212_DFS_HEIGHT 14 1249240001Sadrian#define AR5212_DFS_PRSSI 6 1250240001Sadrian#define AR5212_DFS_INBAND 4 1251239642Sadrian 1252239801Sadrian/* 1253239801Sadrian * Default parameters for the AR5413 PHY. 1254239801Sadrian */ 1255239801Sadrian#define AR5413_DFS_FIRPWR -34 1256239801Sadrian#define AR5413_DFS_RRSSI 20 1257239801Sadrian#define AR5413_DFS_HEIGHT 10 1258239801Sadrian#define AR5413_DFS_PRSSI 15 1259239801Sadrian#define AR5413_DFS_INBAND 6 1260239801Sadrian#define AR5413_DFS_RELPWR 8 1261239801Sadrian#define AR5413_DFS_RELSTEP 31 1262239801Sadrian#define AR5413_DFS_MAXLEN 255 1263239801Sadrian 1264239642SadrianHAL_BOOL 1265239642Sadrianar5212GetDfsDefaultThresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe) 1266239642Sadrian{ 1267239642Sadrian 1268239801Sadrian if (IS_5413(ah)) { 1269239801Sadrian pe->pe_firpwr = AR5413_DFS_FIRPWR; 1270239801Sadrian pe->pe_rrssi = AR5413_DFS_RRSSI; 1271239801Sadrian pe->pe_height = AR5413_DFS_HEIGHT; 1272239801Sadrian pe->pe_prssi = AR5413_DFS_PRSSI; 1273239801Sadrian pe->pe_inband = AR5413_DFS_INBAND; 1274239801Sadrian pe->pe_relpwr = AR5413_DFS_RELPWR; 1275239801Sadrian pe->pe_relstep = AR5413_DFS_RELSTEP; 1276239801Sadrian pe->pe_maxlen = AR5413_DFS_MAXLEN; 1277239801Sadrian pe->pe_usefir128 = 0; 1278239801Sadrian pe->pe_blockradar = 1; 1279239801Sadrian pe->pe_enmaxrssi = 1; 1280239801Sadrian pe->pe_enrelpwr = 1; 1281239801Sadrian pe->pe_en_relstep_check = 0; 1282239801Sadrian } else { 1283239801Sadrian pe->pe_firpwr = AR5212_DFS_FIRPWR; 1284239801Sadrian pe->pe_rrssi = AR5212_DFS_RRSSI; 1285239801Sadrian pe->pe_height = AR5212_DFS_HEIGHT; 1286239801Sadrian pe->pe_prssi = AR5212_DFS_PRSSI; 1287239801Sadrian pe->pe_inband = AR5212_DFS_INBAND; 1288239801Sadrian pe->pe_relpwr = 0; 1289239801Sadrian pe->pe_relstep = 0; 1290239801Sadrian pe->pe_maxlen = 0; 1291239801Sadrian pe->pe_usefir128 = 0; 1292239801Sadrian pe->pe_blockradar = 0; 1293239801Sadrian pe->pe_enmaxrssi = 0; 1294239801Sadrian pe->pe_enrelpwr = 0; 1295239801Sadrian pe->pe_en_relstep_check = 0; 1296239801Sadrian } 1297239642Sadrian 1298239642Sadrian return (AH_TRUE); 1299239642Sadrian} 1300239642Sadrian 1301222584Sadrianvoid 1302222584Sadrianar5212GetDfsThresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe) 1303222584Sadrian{ 1304222584Sadrian uint32_t val,temp; 1305222584Sadrian 1306222584Sadrian val = OS_REG_READ(ah, AR_PHY_RADAR_0); 1307222584Sadrian 1308222584Sadrian temp = MS(val,AR_PHY_RADAR_0_FIRPWR); 1309222584Sadrian temp |= 0xFFFFFF80; 1310222584Sadrian pe->pe_firpwr = temp; 1311222584Sadrian pe->pe_rrssi = MS(val, AR_PHY_RADAR_0_RRSSI); 1312222584Sadrian pe->pe_height = MS(val, AR_PHY_RADAR_0_HEIGHT); 1313222584Sadrian pe->pe_prssi = MS(val, AR_PHY_RADAR_0_PRSSI); 1314222584Sadrian pe->pe_inband = MS(val, AR_PHY_RADAR_0_INBAND); 1315239657Sadrian pe->pe_enabled = !! (val & AR_PHY_RADAR_0_ENA); 1316222584Sadrian 1317222584Sadrian pe->pe_relpwr = 0; 1318222584Sadrian pe->pe_relstep = 0; 1319222584Sadrian pe->pe_maxlen = 0; 1320239801Sadrian pe->pe_usefir128 = 0; 1321239801Sadrian pe->pe_blockradar = 0; 1322239801Sadrian pe->pe_enmaxrssi = 0; 1323239801Sadrian pe->pe_enrelpwr = 0; 1324239801Sadrian pe->pe_en_relstep_check = 0; 1325222584Sadrian pe->pe_extchannel = AH_FALSE; 1326239801Sadrian 1327239801Sadrian if (IS_5413(ah)) { 1328239801Sadrian val = OS_REG_READ(ah, AR_PHY_RADAR_2); 1329239801Sadrian pe->pe_relpwr = !! MS(val, AR_PHY_RADAR_2_RELPWR); 1330239801Sadrian pe->pe_relstep = !! MS(val, AR_PHY_RADAR_2_RELSTEP); 1331239801Sadrian pe->pe_maxlen = !! MS(val, AR_PHY_RADAR_2_MAXLEN); 1332239801Sadrian 1333239801Sadrian pe->pe_usefir128 = !! (val & AR_PHY_RADAR_2_USEFIR128); 1334239801Sadrian pe->pe_blockradar = !! (val & AR_PHY_RADAR_2_BLOCKOFDMWEAK); 1335239801Sadrian pe->pe_enmaxrssi = !! (val & AR_PHY_RADAR_2_ENMAXRSSI); 1336239801Sadrian pe->pe_enrelpwr = !! (val & AR_PHY_RADAR_2_ENRELPWRCHK); 1337239801Sadrian pe->pe_en_relstep_check = 1338239801Sadrian !! (val & AR_PHY_RADAR_2_ENRELSTEPCHK); 1339239801Sadrian } 1340222584Sadrian} 1341222584Sadrian 1342222815Sadrian/* 1343222815Sadrian * Process the radar phy error and extract the pulse duration. 1344222815Sadrian */ 1345222815SadrianHAL_BOOL 1346222815Sadrianar5212ProcessRadarEvent(struct ath_hal *ah, struct ath_rx_status *rxs, 1347222815Sadrian uint64_t fulltsf, const char *buf, HAL_DFS_EVENT *event) 1348222815Sadrian{ 1349222815Sadrian uint8_t dur; 1350222815Sadrian uint8_t rssi; 1351222815Sadrian 1352222815Sadrian /* Check whether the given phy error is a radar event */ 1353222815Sadrian if ((rxs->rs_phyerr != HAL_PHYERR_RADAR) && 1354222815Sadrian (rxs->rs_phyerr != HAL_PHYERR_FALSE_RADAR_EXT)) 1355222815Sadrian return AH_FALSE; 1356222815Sadrian 1357222815Sadrian /* 1358222815Sadrian * The first byte is the pulse width - if there's 1359222815Sadrian * no data, simply set the duration to 0 1360222815Sadrian */ 1361222815Sadrian if (rxs->rs_datalen >= 1) 1362222815Sadrian /* The pulse width is byte 0 of the data */ 1363222815Sadrian dur = ((uint8_t) buf[0]) & 0xff; 1364222815Sadrian else 1365222815Sadrian dur = 0; 1366222815Sadrian 1367222815Sadrian /* Pulse RSSI is the normal reported RSSI */ 1368222815Sadrian rssi = (uint8_t) rxs->rs_rssi; 1369222815Sadrian 1370222815Sadrian /* 0 duration/rssi is not a valid radar event */ 1371222815Sadrian if (dur == 0 && rssi == 0) 1372222815Sadrian return AH_FALSE; 1373222815Sadrian 1374222815Sadrian HALDEBUG(ah, HAL_DEBUG_DFS, "%s: rssi=%d, dur=%d\n", 1375222815Sadrian __func__, rssi, dur); 1376222815Sadrian 1377222815Sadrian /* Record the event */ 1378222815Sadrian event->re_full_ts = fulltsf; 1379222815Sadrian event->re_ts = rxs->rs_tstamp; 1380222815Sadrian event->re_rssi = rssi; 1381222815Sadrian event->re_dur = dur; 1382222815Sadrian event->re_flags = HAL_DFS_EVENT_PRICH; 1383222815Sadrian 1384222815Sadrian return AH_TRUE; 1385222815Sadrian} 1386224709Sadrian 1387224709Sadrian/* 1388224709Sadrian * Return whether 5GHz fast-clock (44MHz) is enabled. 1389224709Sadrian * It's always disabled for AR5212 series NICs. 1390224709Sadrian */ 1391224709SadrianHAL_BOOL 1392224709Sadrianar5212IsFastClockEnabled(struct ath_hal *ah) 1393224709Sadrian{ 1394224709Sadrian return AH_FALSE; 1395224709Sadrian} 1396230791Sadrian 1397230791Sadrian/* 1398230791Sadrian * Return what percentage of the extension channel is busy. 1399230791Sadrian * This is always disabled for AR5212 series NICs. 1400230791Sadrian */ 1401230791Sadrianuint32_t 1402230791Sadrianar5212Get11nExtBusy(struct ath_hal *ah) 1403230791Sadrian{ 1404230791Sadrian return 0; 1405230791Sadrian} 1406234873Sadrian 1407234873Sadrian/* 1408256139Sadrian * Channel survey support. 1409234873Sadrian */ 1410234873SadrianHAL_BOOL 1411234873Sadrianar5212GetMibCycleCounts(struct ath_hal *ah, HAL_SURVEY_SAMPLE *hsample) 1412234873Sadrian{ 1413256139Sadrian struct ath_hal_5212 *ahp = AH5212(ah); 1414256139Sadrian u_int32_t good = AH_TRUE; 1415234873Sadrian 1416256139Sadrian /* XXX freeze/unfreeze mib counters */ 1417256139Sadrian uint32_t rc = OS_REG_READ(ah, AR_RCCNT); 1418256139Sadrian uint32_t rf = OS_REG_READ(ah, AR_RFCNT); 1419256139Sadrian uint32_t tf = OS_REG_READ(ah, AR_TFCNT); 1420256139Sadrian uint32_t cc = OS_REG_READ(ah, AR_CCCNT); /* read cycles last */ 1421256139Sadrian 1422256139Sadrian if (ahp->ah_cycleCount == 0 || ahp->ah_cycleCount > cc) { 1423256139Sadrian /* 1424256139Sadrian * Cycle counter wrap (or initial call); it's not possible 1425256139Sadrian * to accurately calculate a value because the registers 1426256139Sadrian * right shift rather than wrap--so punt and return 0. 1427256139Sadrian */ 1428256139Sadrian HALDEBUG(ah, HAL_DEBUG_ANY, 1429256139Sadrian "%s: cycle counter wrap. ExtBusy = 0\n", __func__); 1430256139Sadrian good = AH_FALSE; 1431256139Sadrian } else { 1432256139Sadrian hsample->cycle_count = cc - ahp->ah_cycleCount; 1433256139Sadrian hsample->chan_busy = rc - ahp->ah_ctlBusy; 1434256139Sadrian hsample->ext_chan_busy = 0; 1435256139Sadrian hsample->rx_busy = rf - ahp->ah_rxBusy; 1436256139Sadrian hsample->tx_busy = tf - ahp->ah_txBusy; 1437256139Sadrian } 1438256139Sadrian 1439256139Sadrian /* 1440256139Sadrian * Keep a copy of the MIB results so the next sample has something 1441256139Sadrian * to work from. 1442256139Sadrian */ 1443256139Sadrian ahp->ah_cycleCount = cc; 1444256139Sadrian ahp->ah_rxBusy = rf; 1445256139Sadrian ahp->ah_ctlBusy = rc; 1446256139Sadrian ahp->ah_txBusy = tf; 1447256139Sadrian 1448256139Sadrian return (good); 1449234873Sadrian} 1450247286Sadrian 1451247286Sadrianvoid 1452247286Sadrianar5212SetChainMasks(struct ath_hal *ah, uint32_t tx_chainmask, 1453247286Sadrian uint32_t rx_chainmask) 1454247286Sadrian{ 1455247286Sadrian} 1456