1 1.1 alc /* 2 1.1 alc * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting 3 1.1 alc * Copyright (c) 2002-2008 Atheros Communications, Inc. 4 1.1 alc * 5 1.1 alc * Permission to use, copy, modify, and/or distribute this software for any 6 1.1 alc * purpose with or without fee is hereby granted, provided that the above 7 1.1 alc * copyright notice and this permission notice appear in all copies. 8 1.1 alc * 9 1.1 alc * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 1.1 alc * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 1.1 alc * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 1.1 alc * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 1.1 alc * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 1.1 alc * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 1.1 alc * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 1.1 alc * 17 1.3 wiz * $Id: ar5212_misc.c,v 1.3 2012/02/12 13:48:45 wiz Exp $ 18 1.1 alc */ 19 1.1 alc #include "opt_ah.h" 20 1.1 alc 21 1.1 alc #include "ah.h" 22 1.1 alc #include "ah_internal.h" 23 1.1 alc #include "ah_devid.h" 24 1.1 alc #ifdef AH_DEBUG 25 1.1 alc #include "ah_desc.h" /* NB: for HAL_PHYERR* */ 26 1.1 alc #endif 27 1.1 alc 28 1.1 alc #include "ar5212/ar5212.h" 29 1.1 alc #include "ar5212/ar5212reg.h" 30 1.1 alc #include "ar5212/ar5212phy.h" 31 1.1 alc 32 1.1 alc #include "ah_eeprom_v3.h" 33 1.1 alc 34 1.1 alc #define AR_NUM_GPIO 6 /* 6 GPIO pins */ 35 1.1 alc #define AR_GPIOD_MASK 0x0000002F /* GPIO data reg r/w mask */ 36 1.1 alc 37 1.1 alc extern void ar5212SetRateDurationTable(struct ath_hal *, HAL_CHANNEL *); 38 1.1 alc 39 1.1 alc void 40 1.1 alc ar5212GetMacAddress(struct ath_hal *ah, uint8_t *mac) 41 1.1 alc { 42 1.1 alc struct ath_hal_5212 *ahp = AH5212(ah); 43 1.1 alc 44 1.1 alc OS_MEMCPY(mac, ahp->ah_macaddr, IEEE80211_ADDR_LEN); 45 1.1 alc } 46 1.1 alc 47 1.1 alc HAL_BOOL 48 1.1 alc ar5212SetMacAddress(struct ath_hal *ah, const uint8_t *mac) 49 1.1 alc { 50 1.1 alc struct ath_hal_5212 *ahp = AH5212(ah); 51 1.1 alc 52 1.1 alc OS_MEMCPY(ahp->ah_macaddr, mac, IEEE80211_ADDR_LEN); 53 1.1 alc return AH_TRUE; 54 1.1 alc } 55 1.1 alc 56 1.1 alc void 57 1.1 alc ar5212GetBssIdMask(struct ath_hal *ah, uint8_t *mask) 58 1.1 alc { 59 1.1 alc struct ath_hal_5212 *ahp = AH5212(ah); 60 1.1 alc 61 1.1 alc OS_MEMCPY(mask, ahp->ah_bssidmask, IEEE80211_ADDR_LEN); 62 1.1 alc } 63 1.1 alc 64 1.1 alc HAL_BOOL 65 1.1 alc ar5212SetBssIdMask(struct ath_hal *ah, const uint8_t *mask) 66 1.1 alc { 67 1.1 alc struct ath_hal_5212 *ahp = AH5212(ah); 68 1.1 alc 69 1.1 alc /* save it since it must be rewritten on reset */ 70 1.1 alc OS_MEMCPY(ahp->ah_bssidmask, mask, IEEE80211_ADDR_LEN); 71 1.1 alc 72 1.1 alc OS_REG_WRITE(ah, AR_BSSMSKL, LE_READ_4(ahp->ah_bssidmask)); 73 1.1 alc OS_REG_WRITE(ah, AR_BSSMSKU, LE_READ_2(ahp->ah_bssidmask + 4)); 74 1.1 alc return AH_TRUE; 75 1.1 alc } 76 1.1 alc 77 1.1 alc /* 78 1.1 alc * Attempt to change the cards operating regulatory domain to the given value 79 1.1 alc */ 80 1.1 alc HAL_BOOL 81 1.1 alc ar5212SetRegulatoryDomain(struct ath_hal *ah, 82 1.1 alc uint16_t regDomain, HAL_STATUS *status) 83 1.1 alc { 84 1.1 alc HAL_STATUS ecode; 85 1.1 alc 86 1.1 alc if (AH_PRIVATE(ah)->ah_currentRD == regDomain) { 87 1.1 alc ecode = HAL_EINVAL; 88 1.1 alc goto bad; 89 1.1 alc } 90 1.1 alc if (ath_hal_eepromGetFlag(ah, AR_EEP_WRITEPROTECT)) { 91 1.1 alc ecode = HAL_EEWRITE; 92 1.1 alc goto bad; 93 1.1 alc } 94 1.1 alc #ifdef AH_SUPPORT_WRITE_REGDOMAIN 95 1.1 alc if (ath_hal_eepromWrite(ah, AR_EEPROM_REG_DOMAIN, regDomain)) { 96 1.1 alc HALDEBUG(ah, HAL_DEBUG_ANY, 97 1.1 alc "%s: set regulatory domain to %u (0x%x)\n", 98 1.1 alc __func__, regDomain, regDomain); 99 1.1 alc AH_PRIVATE(ah)->ah_currentRD = regDomain; 100 1.1 alc return AH_TRUE; 101 1.1 alc } 102 1.1 alc #endif 103 1.1 alc ecode = HAL_EIO; 104 1.1 alc bad: 105 1.1 alc if (status) 106 1.1 alc *status = ecode; 107 1.1 alc return AH_FALSE; 108 1.1 alc } 109 1.1 alc 110 1.1 alc /* 111 1.1 alc * Return the wireless modes (a,b,g,t) supported by hardware. 112 1.1 alc * 113 1.1 alc * This value is what is actually supported by the hardware 114 1.1 alc * and is unaffected by regulatory/country code settings. 115 1.1 alc */ 116 1.1 alc u_int 117 1.1 alc ar5212GetWirelessModes(struct ath_hal *ah) 118 1.1 alc { 119 1.1 alc u_int mode = 0; 120 1.1 alc 121 1.1 alc if (ath_hal_eepromGetFlag(ah, AR_EEP_AMODE)) { 122 1.1 alc mode = HAL_MODE_11A; 123 1.1 alc if (!ath_hal_eepromGetFlag(ah, AR_EEP_TURBO5DISABLE)) 124 1.1 alc mode |= HAL_MODE_TURBO | HAL_MODE_108A; 125 1.1 alc if (AH_PRIVATE(ah)->ah_caps.halChanHalfRate) 126 1.1 alc mode |= HAL_MODE_11A_HALF_RATE; 127 1.1 alc if (AH_PRIVATE(ah)->ah_caps.halChanQuarterRate) 128 1.1 alc mode |= HAL_MODE_11A_QUARTER_RATE; 129 1.1 alc } 130 1.1 alc if (ath_hal_eepromGetFlag(ah, AR_EEP_BMODE)) 131 1.1 alc mode |= HAL_MODE_11B; 132 1.1 alc if (ath_hal_eepromGetFlag(ah, AR_EEP_GMODE) && 133 1.1 alc AH_PRIVATE(ah)->ah_subvendorid != AR_SUBVENDOR_ID_NOG) { 134 1.1 alc mode |= HAL_MODE_11G; 135 1.1 alc if (!ath_hal_eepromGetFlag(ah, AR_EEP_TURBO2DISABLE)) 136 1.1 alc mode |= HAL_MODE_108G; 137 1.1 alc if (AH_PRIVATE(ah)->ah_caps.halChanHalfRate) 138 1.1 alc mode |= HAL_MODE_11G_HALF_RATE; 139 1.1 alc if (AH_PRIVATE(ah)->ah_caps.halChanQuarterRate) 140 1.1 alc mode |= HAL_MODE_11G_QUARTER_RATE; 141 1.1 alc } 142 1.1 alc return mode; 143 1.1 alc } 144 1.1 alc 145 1.1 alc /* 146 1.1 alc * Set the interrupt and GPIO values so the ISR can disable RF 147 1.1 alc * on a switch signal. Assumes GPIO port and interrupt polarity 148 1.1 alc * are set prior to call. 149 1.1 alc */ 150 1.1 alc void 151 1.1 alc ar5212EnableRfKill(struct ath_hal *ah) 152 1.1 alc { 153 1.1 alc uint16_t rfsilent = AH_PRIVATE(ah)->ah_rfsilent; 154 1.1 alc int select = MS(rfsilent, AR_EEPROM_RFSILENT_GPIO_SEL); 155 1.1 alc int polarity = MS(rfsilent, AR_EEPROM_RFSILENT_POLARITY); 156 1.1 alc 157 1.1 alc /* 158 1.1 alc * Configure the desired GPIO port for input 159 1.1 alc * and enable baseband rf silence. 160 1.1 alc */ 161 1.1 alc ath_hal_gpioCfgInput(ah, select); 162 1.1 alc OS_REG_SET_BIT(ah, AR_PHY(0), 0x00002000); 163 1.1 alc /* 164 1.1 alc * If radio disable switch connection to GPIO bit x is enabled 165 1.1 alc * program GPIO interrupt. 166 1.1 alc * If rfkill bit on eeprom is 1, setupeeprommap routine has already 167 1.1 alc * verified that it is a later version of eeprom, it has a place for 168 1.1 alc * rfkill bit and it is set to 1, indicating that GPIO bit x hardware 169 1.1 alc * connection is present. 170 1.1 alc */ 171 1.1 alc ath_hal_gpioSetIntr(ah, select, 172 1.1 alc (ath_hal_gpioGet(ah, select) == polarity ? !polarity : polarity)); 173 1.1 alc } 174 1.1 alc 175 1.1 alc /* 176 1.1 alc * Change the LED blinking pattern to correspond to the connectivity 177 1.1 alc */ 178 1.1 alc void 179 1.1 alc ar5212SetLedState(struct ath_hal *ah, HAL_LED_STATE state) 180 1.1 alc { 181 1.1 alc static const uint32_t ledbits[8] = { 182 1.1 alc AR_PCICFG_LEDCTL_NONE, /* HAL_LED_INIT */ 183 1.1 alc AR_PCICFG_LEDCTL_PEND, /* HAL_LED_SCAN */ 184 1.1 alc AR_PCICFG_LEDCTL_PEND, /* HAL_LED_AUTH */ 185 1.1 alc AR_PCICFG_LEDCTL_ASSOC, /* HAL_LED_ASSOC*/ 186 1.1 alc AR_PCICFG_LEDCTL_ASSOC, /* HAL_LED_RUN */ 187 1.1 alc AR_PCICFG_LEDCTL_NONE, 188 1.1 alc AR_PCICFG_LEDCTL_NONE, 189 1.1 alc AR_PCICFG_LEDCTL_NONE, 190 1.1 alc }; 191 1.1 alc uint32_t bits; 192 1.1 alc 193 1.1 alc bits = OS_REG_READ(ah, AR_PCICFG); 194 1.1 alc if (IS_2417(ah)) { 195 1.1 alc /* 196 1.1 alc * Enable LED for Nala. There is a bit marked reserved 197 1.1 alc * that must be set and we also turn on the power led. 198 1.1 alc * Because we mark s/w LED control setting the control 199 1.1 alc * status bits below is meangless (the driver must flash 200 1.1 alc * the LED(s) using the GPIO lines). 201 1.1 alc */ 202 1.1 alc bits = (bits &~ AR_PCICFG_LEDMODE) 203 1.1 alc | SM(AR_PCICFG_LEDMODE_POWON, AR_PCICFG_LEDMODE) 204 1.1 alc #if 0 205 1.1 alc | SM(AR_PCICFG_LEDMODE_NETON, AR_PCICFG_LEDMODE) 206 1.1 alc #endif 207 1.1 alc | 0x08000000; 208 1.1 alc } 209 1.1 alc bits = (bits &~ AR_PCICFG_LEDCTL) 210 1.1 alc | SM(ledbits[state & 0x7], AR_PCICFG_LEDCTL); 211 1.1 alc OS_REG_WRITE(ah, AR_PCICFG, bits); 212 1.1 alc } 213 1.1 alc 214 1.1 alc /* 215 1.1 alc * Change association related fields programmed into the hardware. 216 1.1 alc * Writing a valid BSSID to the hardware effectively enables the hardware 217 1.1 alc * to synchronize its TSF to the correct beacons and receive frames coming 218 1.1 alc * from that BSSID. It is called by the SME JOIN operation. 219 1.1 alc */ 220 1.1 alc void 221 1.1 alc ar5212WriteAssocid(struct ath_hal *ah, const uint8_t *bssid, uint16_t assocId) 222 1.1 alc { 223 1.1 alc struct ath_hal_5212 *ahp = AH5212(ah); 224 1.1 alc 225 1.1 alc /* XXX save bssid for possible re-use on reset */ 226 1.1 alc OS_MEMCPY(ahp->ah_bssid, bssid, IEEE80211_ADDR_LEN); 227 1.1 alc OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid)); 228 1.1 alc OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid+4) | 229 1.1 alc ((assocId & 0x3fff)<<AR_BSS_ID1_AID_S)); 230 1.1 alc } 231 1.1 alc 232 1.1 alc /* 233 1.1 alc * Get the current hardware tsf for stamlme 234 1.1 alc */ 235 1.1 alc uint64_t 236 1.1 alc ar5212GetTsf64(struct ath_hal *ah) 237 1.1 alc { 238 1.1 alc uint32_t low1, low2, u32; 239 1.1 alc 240 1.1 alc /* sync multi-word read */ 241 1.1 alc low1 = OS_REG_READ(ah, AR_TSF_L32); 242 1.1 alc u32 = OS_REG_READ(ah, AR_TSF_U32); 243 1.1 alc low2 = OS_REG_READ(ah, AR_TSF_L32); 244 1.1 alc if (low2 < low1) { /* roll over */ 245 1.1 alc /* 246 1.1 alc * If we are not preempted this will work. If we are 247 1.1 alc * then we re-reading AR_TSF_U32 does no good as the 248 1.1 alc * low bits will be meaningless. Likewise reading 249 1.1 alc * L32, U32, U32, then comparing the last two reads 250 1.1 alc * to check for rollover doesn't help if preempted--so 251 1.1 alc * we take this approach as it costs one less PCI read 252 1.1 alc * which can be noticeable when doing things like 253 1.1 alc * timestamping packets in monitor mode. 254 1.1 alc */ 255 1.1 alc u32++; 256 1.1 alc } 257 1.1 alc return (((uint64_t) u32) << 32) | ((uint64_t) low2); 258 1.1 alc } 259 1.1 alc 260 1.1 alc /* 261 1.1 alc * Get the current hardware tsf for stamlme 262 1.1 alc */ 263 1.1 alc uint32_t 264 1.1 alc ar5212GetTsf32(struct ath_hal *ah) 265 1.1 alc { 266 1.1 alc return OS_REG_READ(ah, AR_TSF_L32); 267 1.1 alc } 268 1.1 alc 269 1.1 alc /* 270 1.1 alc * Reset the current hardware tsf for stamlme. 271 1.1 alc */ 272 1.1 alc void 273 1.1 alc ar5212ResetTsf(struct ath_hal *ah) 274 1.1 alc { 275 1.1 alc 276 1.1 alc uint32_t val = OS_REG_READ(ah, AR_BEACON); 277 1.1 alc 278 1.1 alc OS_REG_WRITE(ah, AR_BEACON, val | AR_BEACON_RESET_TSF); 279 1.1 alc /* 280 1.1 alc * When resetting the TSF, write twice to the 281 1.1 alc * corresponding register; each write to the RESET_TSF bit toggles 282 1.1 alc * the internal signal to cause a reset of the TSF - but if the signal 283 1.1 alc * is left high, it will reset the TSF on the next chip reset also! 284 1.1 alc * writing the bit an even number of times fixes this issue 285 1.1 alc */ 286 1.1 alc OS_REG_WRITE(ah, AR_BEACON, val | AR_BEACON_RESET_TSF); 287 1.1 alc } 288 1.1 alc 289 1.1 alc /* 290 1.1 alc * Set or clear hardware basic rate bit 291 1.1 alc * Set hardware basic rate set if basic rate is found 292 1.1 alc * and basic rate is equal or less than 2Mbps 293 1.1 alc */ 294 1.1 alc void 295 1.1 alc ar5212SetBasicRate(struct ath_hal *ah, HAL_RATE_SET *rs) 296 1.1 alc { 297 1.1 alc HAL_CHANNEL_INTERNAL *chan = AH_PRIVATE(ah)->ah_curchan; 298 1.1 alc uint32_t reg; 299 1.1 alc uint8_t xset; 300 1.1 alc int i; 301 1.1 alc 302 1.1 alc if (chan == AH_NULL || !IS_CHAN_CCK(chan)) 303 1.1 alc return; 304 1.1 alc xset = 0; 305 1.1 alc for (i = 0; i < rs->rs_count; i++) { 306 1.1 alc uint8_t rset = rs->rs_rates[i]; 307 1.1 alc /* Basic rate defined? */ 308 1.1 alc if ((rset & 0x80) && (rset &= 0x7f) >= xset) 309 1.1 alc xset = rset; 310 1.1 alc } 311 1.1 alc /* 312 1.1 alc * Set the h/w bit to reflect whether or not the basic 313 1.1 alc * rate is found to be equal or less than 2Mbps. 314 1.1 alc */ 315 1.1 alc reg = OS_REG_READ(ah, AR_STA_ID1); 316 1.1 alc if (xset && xset/2 <= 2) 317 1.1 alc OS_REG_WRITE(ah, AR_STA_ID1, reg | AR_STA_ID1_BASE_RATE_11B); 318 1.1 alc else 319 1.1 alc OS_REG_WRITE(ah, AR_STA_ID1, reg &~ AR_STA_ID1_BASE_RATE_11B); 320 1.1 alc } 321 1.1 alc 322 1.1 alc /* 323 1.1 alc * Grab a semi-random value from hardware registers - may not 324 1.1 alc * change often 325 1.1 alc */ 326 1.1 alc uint32_t 327 1.1 alc ar5212GetRandomSeed(struct ath_hal *ah) 328 1.1 alc { 329 1.1 alc uint32_t nf; 330 1.1 alc 331 1.1 alc nf = (OS_REG_READ(ah, AR_PHY(25)) >> 19) & 0x1ff; 332 1.1 alc if (nf & 0x100) 333 1.1 alc nf = 0 - ((nf ^ 0x1ff) + 1); 334 1.1 alc return (OS_REG_READ(ah, AR_TSF_U32) ^ 335 1.1 alc OS_REG_READ(ah, AR_TSF_L32) ^ nf); 336 1.1 alc } 337 1.1 alc 338 1.1 alc /* 339 1.1 alc * Detect if our card is present 340 1.1 alc */ 341 1.1 alc HAL_BOOL 342 1.1 alc ar5212DetectCardPresent(struct ath_hal *ah) 343 1.1 alc { 344 1.1 alc uint16_t macVersion, macRev; 345 1.1 alc uint32_t v; 346 1.1 alc 347 1.1 alc /* 348 1.1 alc * Read the Silicon Revision register and compare that 349 1.1 alc * to what we read at attach time. If the same, we say 350 1.1 alc * a card/device is present. 351 1.1 alc */ 352 1.1 alc v = OS_REG_READ(ah, AR_SREV) & AR_SREV_ID; 353 1.1 alc macVersion = v >> AR_SREV_ID_S; 354 1.1 alc macRev = v & AR_SREV_REVISION; 355 1.1 alc return (AH_PRIVATE(ah)->ah_macVersion == macVersion && 356 1.1 alc AH_PRIVATE(ah)->ah_macRev == macRev); 357 1.1 alc } 358 1.1 alc 359 1.1 alc void 360 1.1 alc ar5212EnableMibCounters(struct ath_hal *ah) 361 1.1 alc { 362 1.1 alc /* NB: this just resets the mib counter machinery */ 363 1.1 alc OS_REG_WRITE(ah, AR_MIBC, 364 1.1 alc ~(AR_MIBC_COW | AR_MIBC_FMC | AR_MIBC_CMC | AR_MIBC_MCS) & 0x0f); 365 1.1 alc } 366 1.1 alc 367 1.1 alc void 368 1.1 alc ar5212DisableMibCounters(struct ath_hal *ah) 369 1.1 alc { 370 1.1 alc OS_REG_WRITE(ah, AR_MIBC, AR_MIBC | AR_MIBC_CMC); 371 1.1 alc } 372 1.1 alc 373 1.1 alc /* 374 1.1 alc * Update MIB Counters 375 1.1 alc */ 376 1.1 alc void 377 1.1 alc ar5212UpdateMibCounters(struct ath_hal *ah, HAL_MIB_STATS* stats) 378 1.1 alc { 379 1.1 alc stats->ackrcv_bad += OS_REG_READ(ah, AR_ACK_FAIL); 380 1.1 alc stats->rts_bad += OS_REG_READ(ah, AR_RTS_FAIL); 381 1.1 alc stats->fcs_bad += OS_REG_READ(ah, AR_FCS_FAIL); 382 1.1 alc stats->rts_good += OS_REG_READ(ah, AR_RTS_OK); 383 1.1 alc stats->beacons += OS_REG_READ(ah, AR_BEACON_CNT); 384 1.1 alc } 385 1.1 alc 386 1.1 alc /* 387 1.1 alc * Detect if the HW supports spreading a CCK signal on channel 14 388 1.1 alc */ 389 1.1 alc HAL_BOOL 390 1.1 alc ar5212IsJapanChannelSpreadSupported(struct ath_hal *ah) 391 1.1 alc { 392 1.1 alc return AH_TRUE; 393 1.1 alc } 394 1.1 alc 395 1.1 alc /* 396 1.1 alc * Get the rssi of frame curently being received. 397 1.1 alc */ 398 1.1 alc uint32_t 399 1.1 alc ar5212GetCurRssi(struct ath_hal *ah) 400 1.1 alc { 401 1.1 alc return (OS_REG_READ(ah, AR_PHY_CURRENT_RSSI) & 0xff); 402 1.1 alc } 403 1.1 alc 404 1.1 alc u_int 405 1.1 alc ar5212GetDefAntenna(struct ath_hal *ah) 406 1.1 alc { 407 1.1 alc return (OS_REG_READ(ah, AR_DEF_ANTENNA) & 0x7); 408 1.1 alc } 409 1.1 alc 410 1.1 alc void 411 1.1 alc ar5212SetDefAntenna(struct ath_hal *ah, u_int antenna) 412 1.1 alc { 413 1.1 alc OS_REG_WRITE(ah, AR_DEF_ANTENNA, (antenna & 0x7)); 414 1.1 alc } 415 1.1 alc 416 1.1 alc HAL_ANT_SETTING 417 1.1 alc ar5212GetAntennaSwitch(struct ath_hal *ah) 418 1.1 alc { 419 1.1 alc return AH5212(ah)->ah_antControl; 420 1.1 alc } 421 1.1 alc 422 1.1 alc HAL_BOOL 423 1.1 alc ar5212SetAntennaSwitch(struct ath_hal *ah, HAL_ANT_SETTING setting) 424 1.1 alc { 425 1.1 alc struct ath_hal_5212 *ahp = AH5212(ah); 426 1.1 alc const HAL_CHANNEL_INTERNAL *ichan = AH_PRIVATE(ah)->ah_curchan; 427 1.1 alc 428 1.1 alc if (!ahp->ah_phyPowerOn || ichan == AH_NULL) { 429 1.1 alc /* PHY powered off, just stash settings */ 430 1.1 alc ahp->ah_antControl = setting; 431 1.1 alc ahp->ah_diversity = (setting == HAL_ANT_VARIABLE); 432 1.1 alc return AH_TRUE; 433 1.1 alc } 434 1.1 alc return ar5212SetAntennaSwitchInternal(ah, setting, ichan); 435 1.1 alc } 436 1.1 alc 437 1.1 alc HAL_BOOL 438 1.1 alc ar5212IsSleepAfterBeaconBroken(struct ath_hal *ah) 439 1.1 alc { 440 1.1 alc return AH_TRUE; 441 1.1 alc } 442 1.1 alc 443 1.1 alc HAL_BOOL 444 1.1 alc ar5212SetSifsTime(struct ath_hal *ah, u_int us) 445 1.1 alc { 446 1.1 alc struct ath_hal_5212 *ahp = AH5212(ah); 447 1.1 alc 448 1.1 alc if (us > ath_hal_mac_usec(ah, 0xffff)) { 449 1.1 alc HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad SIFS time %u\n", 450 1.1 alc __func__, us); 451 1.1 alc ahp->ah_sifstime = (u_int) -1; /* restore default handling */ 452 1.1 alc return AH_FALSE; 453 1.1 alc } else { 454 1.1 alc /* convert to system clocks */ 455 1.2 cegger OS_REG_WRITE(ah, AR_D_GBL_IFS_SIFS, ath_hal_mac_clks(ah, us-2)); 456 1.1 alc ahp->ah_slottime = us; 457 1.1 alc return AH_TRUE; 458 1.1 alc } 459 1.1 alc } 460 1.1 alc 461 1.1 alc u_int 462 1.1 alc ar5212GetSifsTime(struct ath_hal *ah) 463 1.1 alc { 464 1.1 alc u_int clks = OS_REG_READ(ah, AR_D_GBL_IFS_SIFS) & 0xffff; 465 1.2 cegger return ath_hal_mac_usec(ah, clks)+2; /* convert from system clocks */ 466 1.1 alc } 467 1.1 alc 468 1.1 alc HAL_BOOL 469 1.1 alc ar5212SetSlotTime(struct ath_hal *ah, u_int us) 470 1.1 alc { 471 1.1 alc struct ath_hal_5212 *ahp = AH5212(ah); 472 1.1 alc 473 1.1 alc if (us < HAL_SLOT_TIME_6 || us > ath_hal_mac_usec(ah, 0xffff)) { 474 1.1 alc HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad slot time %u\n", 475 1.1 alc __func__, us); 476 1.1 alc ahp->ah_slottime = (u_int) -1; /* restore default handling */ 477 1.1 alc return AH_FALSE; 478 1.1 alc } else { 479 1.1 alc /* convert to system clocks */ 480 1.1 alc OS_REG_WRITE(ah, AR_D_GBL_IFS_SLOT, ath_hal_mac_clks(ah, us)); 481 1.1 alc ahp->ah_slottime = us; 482 1.1 alc return AH_TRUE; 483 1.1 alc } 484 1.1 alc } 485 1.1 alc 486 1.1 alc u_int 487 1.1 alc ar5212GetSlotTime(struct ath_hal *ah) 488 1.1 alc { 489 1.1 alc u_int clks = OS_REG_READ(ah, AR_D_GBL_IFS_SLOT) & 0xffff; 490 1.1 alc return ath_hal_mac_usec(ah, clks); /* convert from system clocks */ 491 1.1 alc } 492 1.1 alc 493 1.1 alc HAL_BOOL 494 1.1 alc ar5212SetAckTimeout(struct ath_hal *ah, u_int us) 495 1.1 alc { 496 1.1 alc struct ath_hal_5212 *ahp = AH5212(ah); 497 1.1 alc 498 1.1 alc if (us > ath_hal_mac_usec(ah, MS(0xffffffff, AR_TIME_OUT_ACK))) { 499 1.1 alc HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad ack timeout %u\n", 500 1.1 alc __func__, us); 501 1.1 alc ahp->ah_acktimeout = (u_int) -1; /* restore default handling */ 502 1.1 alc return AH_FALSE; 503 1.1 alc } else { 504 1.1 alc /* convert to system clocks */ 505 1.1 alc OS_REG_RMW_FIELD(ah, AR_TIME_OUT, 506 1.1 alc AR_TIME_OUT_ACK, ath_hal_mac_clks(ah, us)); 507 1.1 alc ahp->ah_acktimeout = us; 508 1.1 alc return AH_TRUE; 509 1.1 alc } 510 1.1 alc } 511 1.1 alc 512 1.1 alc u_int 513 1.1 alc ar5212GetAckTimeout(struct ath_hal *ah) 514 1.1 alc { 515 1.1 alc u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_ACK); 516 1.1 alc return ath_hal_mac_usec(ah, clks); /* convert from system clocks */ 517 1.1 alc } 518 1.1 alc 519 1.1 alc u_int 520 1.1 alc ar5212GetAckCTSRate(struct ath_hal *ah) 521 1.1 alc { 522 1.1 alc return ((AH5212(ah)->ah_staId1Defaults & AR_STA_ID1_ACKCTS_6MB) == 0); 523 1.1 alc } 524 1.1 alc 525 1.1 alc HAL_BOOL 526 1.1 alc ar5212SetAckCTSRate(struct ath_hal *ah, u_int high) 527 1.1 alc { 528 1.1 alc struct ath_hal_5212 *ahp = AH5212(ah); 529 1.1 alc 530 1.1 alc if (high) { 531 1.1 alc OS_REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_ACKCTS_6MB); 532 1.1 alc ahp->ah_staId1Defaults &= ~AR_STA_ID1_ACKCTS_6MB; 533 1.1 alc } else { 534 1.1 alc OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_ACKCTS_6MB); 535 1.1 alc ahp->ah_staId1Defaults |= AR_STA_ID1_ACKCTS_6MB; 536 1.1 alc } 537 1.1 alc return AH_TRUE; 538 1.1 alc } 539 1.1 alc 540 1.1 alc HAL_BOOL 541 1.1 alc ar5212SetCTSTimeout(struct ath_hal *ah, u_int us) 542 1.1 alc { 543 1.1 alc struct ath_hal_5212 *ahp = AH5212(ah); 544 1.1 alc 545 1.1 alc if (us > ath_hal_mac_usec(ah, MS(0xffffffff, AR_TIME_OUT_CTS))) { 546 1.1 alc HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad cts timeout %u\n", 547 1.1 alc __func__, us); 548 1.1 alc ahp->ah_ctstimeout = (u_int) -1; /* restore default handling */ 549 1.1 alc return AH_FALSE; 550 1.1 alc } else { 551 1.1 alc /* convert to system clocks */ 552 1.1 alc OS_REG_RMW_FIELD(ah, AR_TIME_OUT, 553 1.1 alc AR_TIME_OUT_CTS, ath_hal_mac_clks(ah, us)); 554 1.1 alc ahp->ah_ctstimeout = us; 555 1.1 alc return AH_TRUE; 556 1.1 alc } 557 1.1 alc } 558 1.1 alc 559 1.1 alc u_int 560 1.1 alc ar5212GetCTSTimeout(struct ath_hal *ah) 561 1.1 alc { 562 1.1 alc u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_CTS); 563 1.1 alc return ath_hal_mac_usec(ah, clks); /* convert from system clocks */ 564 1.1 alc } 565 1.1 alc 566 1.1 alc /* Setup decompression for given key index */ 567 1.1 alc HAL_BOOL 568 1.1 alc ar5212SetDecompMask(struct ath_hal *ah, uint16_t keyidx, int en) 569 1.1 alc { 570 1.1 alc struct ath_hal_5212 *ahp = AH5212(ah); 571 1.1 alc 572 1.1 alc if (keyidx >= HAL_DECOMP_MASK_SIZE) 573 1.3 wiz return AH_FALSE; 574 1.1 alc OS_REG_WRITE(ah, AR_DCM_A, keyidx); 575 1.1 alc OS_REG_WRITE(ah, AR_DCM_D, en ? AR_DCM_D_EN : 0); 576 1.1 alc ahp->ah_decompMask[keyidx] = en; 577 1.1 alc 578 1.1 alc return AH_TRUE; 579 1.1 alc } 580 1.1 alc 581 1.1 alc /* Setup coverage class */ 582 1.1 alc void 583 1.1 alc ar5212SetCoverageClass(struct ath_hal *ah, uint8_t coverageclass, int now) 584 1.1 alc { 585 1.1 alc uint32_t slot, timeout, eifs; 586 1.1 alc u_int clkRate; 587 1.1 alc 588 1.1 alc AH_PRIVATE(ah)->ah_coverageClass = coverageclass; 589 1.1 alc 590 1.1 alc if (now) { 591 1.1 alc if (AH_PRIVATE(ah)->ah_coverageClass == 0) 592 1.1 alc return; 593 1.1 alc 594 1.1 alc /* Don't apply coverage class to non A channels */ 595 1.1 alc if (!IS_CHAN_A(AH_PRIVATE(ah)->ah_curchan)) 596 1.1 alc return; 597 1.1 alc 598 1.1 alc /* Get core clock rate */ 599 1.1 alc clkRate = ath_hal_mac_clks(ah, 1); 600 1.1 alc 601 1.1 alc /* Compute EIFS */ 602 1.1 alc slot = coverageclass * 3 * clkRate; 603 1.1 alc eifs = coverageclass * 6 * clkRate; 604 1.1 alc if (IS_CHAN_HALF_RATE(AH_PRIVATE(ah)->ah_curchan)) { 605 1.1 alc slot += IFS_SLOT_HALF_RATE; 606 1.1 alc eifs += IFS_EIFS_HALF_RATE; 607 1.1 alc } else if (IS_CHAN_QUARTER_RATE(AH_PRIVATE(ah)->ah_curchan)) { 608 1.1 alc slot += IFS_SLOT_QUARTER_RATE; 609 1.1 alc eifs += IFS_EIFS_QUARTER_RATE; 610 1.1 alc } else { /* full rate */ 611 1.1 alc slot += IFS_SLOT_FULL_RATE; 612 1.1 alc eifs += IFS_EIFS_FULL_RATE; 613 1.1 alc } 614 1.1 alc 615 1.1 alc /* 616 1.1 alc * Add additional time for air propagation for ACK and CTS 617 1.1 alc * timeouts. This value is in core clocks. 618 1.1 alc */ 619 1.1 alc timeout = ACK_CTS_TIMEOUT_11A + (coverageclass * 3 * clkRate); 620 1.1 alc 621 1.1 alc /* 622 1.1 alc * Write the values: slot, eifs, ack/cts timeouts. 623 1.1 alc */ 624 1.1 alc OS_REG_WRITE(ah, AR_D_GBL_IFS_SLOT, slot); 625 1.1 alc OS_REG_WRITE(ah, AR_D_GBL_IFS_EIFS, eifs); 626 1.1 alc OS_REG_WRITE(ah, AR_TIME_OUT, 627 1.1 alc SM(timeout, AR_TIME_OUT_CTS) 628 1.1 alc | SM(timeout, AR_TIME_OUT_ACK)); 629 1.1 alc } 630 1.1 alc } 631 1.1 alc 632 1.1 alc void 633 1.1 alc ar5212SetPCUConfig(struct ath_hal *ah) 634 1.1 alc { 635 1.1 alc ar5212SetOperatingMode(ah, AH_PRIVATE(ah)->ah_opmode); 636 1.1 alc } 637 1.1 alc 638 1.1 alc /* 639 1.1 alc * Return whether an external 32KHz crystal should be used 640 1.1 alc * to reduce power consumption when sleeping. We do so if 641 1.1 alc * the crystal is present (obtained from EEPROM) and if we 642 1.1 alc * are not running as an AP and are configured to use it. 643 1.1 alc */ 644 1.1 alc HAL_BOOL 645 1.1 alc ar5212Use32KHzclock(struct ath_hal *ah, HAL_OPMODE opmode) 646 1.1 alc { 647 1.1 alc if (opmode != HAL_M_HOSTAP) { 648 1.1 alc struct ath_hal_5212 *ahp = AH5212(ah); 649 1.1 alc return ath_hal_eepromGetFlag(ah, AR_EEP_32KHZCRYSTAL) && 650 1.1 alc (ahp->ah_enable32kHzClock == USE_32KHZ || 651 1.1 alc ahp->ah_enable32kHzClock == AUTO_32KHZ); 652 1.1 alc } else 653 1.1 alc return AH_FALSE; 654 1.1 alc } 655 1.1 alc 656 1.1 alc /* 657 1.1 alc * If 32KHz clock exists, use it to lower power consumption during sleep 658 1.1 alc * 659 1.1 alc * Note: If clock is set to 32 KHz, delays on accessing certain 660 1.1 alc * baseband registers (27-31, 124-127) are required. 661 1.1 alc */ 662 1.1 alc void 663 1.1 alc ar5212SetupClock(struct ath_hal *ah, HAL_OPMODE opmode) 664 1.1 alc { 665 1.1 alc if (ar5212Use32KHzclock(ah, opmode)) { 666 1.1 alc /* 667 1.1 alc * Enable clocks to be turned OFF in BB during sleep 668 1.1 alc * and also enable turning OFF 32MHz/40MHz Refclk 669 1.1 alc * from A2. 670 1.1 alc */ 671 1.1 alc OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_CONTROL, 0x1f); 672 1.1 alc OS_REG_WRITE(ah, AR_PHY_REFCLKPD, 673 1.1 alc IS_RAD5112_ANY(ah) || IS_5413(ah) ? 0x14 : 0x18); 674 1.1 alc OS_REG_RMW_FIELD(ah, AR_USEC, AR_USEC_USEC32, 1); 675 1.1 alc OS_REG_WRITE(ah, AR_TSF_PARM, 61); /* 32 KHz TSF incr */ 676 1.1 alc OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_SEL, 1); 677 1.1 alc 678 1.1 alc if (IS_2413(ah) || IS_5413(ah) || IS_2417(ah)) { 679 1.1 alc OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_LIMIT, 0x26); 680 1.1 alc OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0d); 681 1.1 alc OS_REG_WRITE(ah, AR_PHY_M_SLEEP, 0x07); 682 1.1 alc OS_REG_WRITE(ah, AR_PHY_REFCLKDLY, 0x3f); 683 1.1 alc /* # Set sleep clock rate to 32 KHz. */ 684 1.1 alc OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_RATE_IND, 0x2); 685 1.1 alc } else { 686 1.1 alc OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_LIMIT, 0x0a); 687 1.1 alc OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0c); 688 1.1 alc OS_REG_WRITE(ah, AR_PHY_M_SLEEP, 0x03); 689 1.1 alc OS_REG_WRITE(ah, AR_PHY_REFCLKDLY, 0x20); 690 1.1 alc OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_RATE_IND, 0x3); 691 1.1 alc } 692 1.1 alc } else { 693 1.1 alc OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_RATE_IND, 0x0); 694 1.1 alc OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_SEL, 0); 695 1.1 alc 696 1.1 alc OS_REG_WRITE(ah, AR_TSF_PARM, 1); /* 32MHz TSF inc */ 697 1.1 alc 698 1.1 alc OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_CONTROL, 0x1f); 699 1.1 alc OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_LIMIT, 0x7f); 700 1.1 alc 701 1.1 alc if (IS_2417(ah)) 702 1.1 alc OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0a); 703 1.1 alc else if (IS_HB63(ah)) 704 1.1 alc OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x32); 705 1.1 alc else 706 1.1 alc OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0e); 707 1.1 alc OS_REG_WRITE(ah, AR_PHY_M_SLEEP, 0x0c); 708 1.1 alc OS_REG_WRITE(ah, AR_PHY_REFCLKDLY, 0xff); 709 1.1 alc OS_REG_WRITE(ah, AR_PHY_REFCLKPD, 710 1.1 alc IS_RAD5112_ANY(ah) || IS_5413(ah) || IS_2417(ah) ? 0x14 : 0x18); 711 1.1 alc OS_REG_RMW_FIELD(ah, AR_USEC, AR_USEC_USEC32, 712 1.1 alc IS_RAD5112_ANY(ah) || IS_5413(ah) ? 39 : 31); 713 1.1 alc } 714 1.1 alc } 715 1.1 alc 716 1.1 alc /* 717 1.1 alc * If 32KHz clock exists, turn it off and turn back on the 32Mhz 718 1.1 alc */ 719 1.1 alc void 720 1.1 alc ar5212RestoreClock(struct ath_hal *ah, HAL_OPMODE opmode) 721 1.1 alc { 722 1.1 alc if (ar5212Use32KHzclock(ah, opmode)) { 723 1.1 alc /* # Set sleep clock rate back to 32 MHz. */ 724 1.1 alc OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_RATE_IND, 0); 725 1.1 alc OS_REG_RMW_FIELD(ah, AR_PCICFG, AR_PCICFG_SCLK_SEL, 0); 726 1.1 alc 727 1.1 alc OS_REG_WRITE(ah, AR_TSF_PARM, 1); /* 32 MHz TSF incr */ 728 1.1 alc OS_REG_RMW_FIELD(ah, AR_USEC, AR_USEC_USEC32, 729 1.1 alc IS_RAD5112_ANY(ah) || IS_5413(ah) ? 39 : 31); 730 1.1 alc 731 1.1 alc /* 732 1.1 alc * Restore BB registers to power-on defaults 733 1.1 alc */ 734 1.1 alc OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_CONTROL, 0x1f); 735 1.1 alc OS_REG_WRITE(ah, AR_PHY_SLEEP_CTR_LIMIT, 0x7f); 736 1.1 alc OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0e); 737 1.1 alc OS_REG_WRITE(ah, AR_PHY_M_SLEEP, 0x0c); 738 1.1 alc OS_REG_WRITE(ah, AR_PHY_REFCLKDLY, 0xff); 739 1.1 alc OS_REG_WRITE(ah, AR_PHY_REFCLKPD, 740 1.1 alc IS_RAD5112_ANY(ah) || IS_5413(ah) ? 0x14 : 0x18); 741 1.1 alc } 742 1.1 alc } 743 1.1 alc 744 1.1 alc /* 745 1.1 alc * Adjust NF based on statistical values for 5GHz frequencies. 746 1.1 alc * Default method: this may be overridden by the rf backend. 747 1.1 alc */ 748 1.1 alc int16_t 749 1.1 alc ar5212GetNfAdjust(struct ath_hal *ah, const HAL_CHANNEL_INTERNAL *c) 750 1.1 alc { 751 1.1 alc static const struct { 752 1.1 alc uint16_t freqLow; 753 1.1 alc int16_t adjust; 754 1.1 alc } adjustDef[] = { 755 1.1 alc { 5790, 11 }, /* NB: ordered high -> low */ 756 1.1 alc { 5730, 10 }, 757 1.1 alc { 5690, 9 }, 758 1.1 alc { 5660, 8 }, 759 1.1 alc { 5610, 7 }, 760 1.1 alc { 5530, 5 }, 761 1.1 alc { 5450, 4 }, 762 1.1 alc { 5379, 2 }, 763 1.1 alc { 5209, 0 }, 764 1.1 alc { 3000, 1 }, 765 1.1 alc { 0, 0 }, 766 1.1 alc }; 767 1.1 alc int i; 768 1.1 alc 769 1.1 alc for (i = 0; c->channel <= adjustDef[i].freqLow; i++) 770 1.1 alc ; 771 1.1 alc return adjustDef[i].adjust; 772 1.1 alc } 773 1.1 alc 774 1.1 alc HAL_STATUS 775 1.1 alc ar5212GetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, 776 1.1 alc uint32_t capability, uint32_t *result) 777 1.1 alc { 778 1.1 alc #define MACVERSION(ah) AH_PRIVATE(ah)->ah_macVersion 779 1.1 alc struct ath_hal_5212 *ahp = AH5212(ah); 780 1.1 alc const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps; 781 1.1 alc const struct ar5212AniState *ani; 782 1.1 alc 783 1.1 alc switch (type) { 784 1.1 alc case HAL_CAP_CIPHER: /* cipher handled in hardware */ 785 1.1 alc switch (capability) { 786 1.1 alc case HAL_CIPHER_AES_CCM: 787 1.1 alc return pCap->halCipherAesCcmSupport ? 788 1.1 alc HAL_OK : HAL_ENOTSUPP; 789 1.1 alc case HAL_CIPHER_AES_OCB: 790 1.1 alc case HAL_CIPHER_TKIP: 791 1.1 alc case HAL_CIPHER_WEP: 792 1.1 alc case HAL_CIPHER_MIC: 793 1.1 alc case HAL_CIPHER_CLR: 794 1.1 alc return HAL_OK; 795 1.1 alc default: 796 1.1 alc return HAL_ENOTSUPP; 797 1.1 alc } 798 1.1 alc case HAL_CAP_TKIP_MIC: /* handle TKIP MIC in hardware */ 799 1.1 alc switch (capability) { 800 1.1 alc case 0: /* hardware capability */ 801 1.1 alc return HAL_OK; 802 1.1 alc case 1: 803 1.1 alc return (ahp->ah_staId1Defaults & 804 1.1 alc AR_STA_ID1_CRPT_MIC_ENABLE) ? HAL_OK : HAL_ENXIO; 805 1.1 alc } 806 1.2 cegger return HAL_EINVAL; 807 1.1 alc case HAL_CAP_TKIP_SPLIT: /* hardware TKIP uses split keys */ 808 1.1 alc switch (capability) { 809 1.1 alc case 0: /* hardware capability */ 810 1.1 alc return pCap->halTkipMicTxRxKeySupport ? 811 1.1 alc HAL_ENXIO : HAL_OK; 812 1.1 alc case 1: /* current setting */ 813 1.1 alc return (ahp->ah_miscMode & 814 1.1 alc AR_MISC_MODE_MIC_NEW_LOC_ENABLE) ? HAL_ENXIO : HAL_OK; 815 1.1 alc } 816 1.1 alc return HAL_EINVAL; 817 1.1 alc case HAL_CAP_WME_TKIPMIC: /* hardware can do TKIP MIC w/ WMM */ 818 1.1 alc /* XXX move to capability bit */ 819 1.1 alc return MACVERSION(ah) > AR_SREV_VERSION_VENICE || 820 1.1 alc (MACVERSION(ah) == AR_SREV_VERSION_VENICE && 821 1.1 alc AH_PRIVATE(ah)->ah_macRev >= 8) ? HAL_OK : HAL_ENOTSUPP; 822 1.1 alc case HAL_CAP_DIVERSITY: /* hardware supports fast diversity */ 823 1.1 alc switch (capability) { 824 1.1 alc case 0: /* hardware capability */ 825 1.1 alc return HAL_OK; 826 1.1 alc case 1: /* current setting */ 827 1.1 alc return ahp->ah_diversity ? HAL_OK : HAL_ENXIO; 828 1.1 alc } 829 1.1 alc return HAL_EINVAL; 830 1.1 alc case HAL_CAP_DIAG: 831 1.1 alc *result = AH_PRIVATE(ah)->ah_diagreg; 832 1.1 alc return HAL_OK; 833 1.1 alc case HAL_CAP_TPC: 834 1.1 alc switch (capability) { 835 1.1 alc case 0: /* hardware capability */ 836 1.1 alc return HAL_OK; 837 1.1 alc case 1: 838 1.1 alc return ahp->ah_tpcEnabled ? HAL_OK : HAL_ENXIO; 839 1.1 alc } 840 1.1 alc return HAL_OK; 841 1.1 alc case HAL_CAP_PHYDIAG: /* radar pulse detection capability */ 842 1.1 alc switch (capability) { 843 1.1 alc case HAL_CAP_RADAR: 844 1.1 alc return ath_hal_eepromGetFlag(ah, AR_EEP_AMODE) ? 845 1.1 alc HAL_OK: HAL_ENXIO; 846 1.1 alc case HAL_CAP_AR: 847 1.1 alc return (ath_hal_eepromGetFlag(ah, AR_EEP_GMODE) || 848 1.1 alc ath_hal_eepromGetFlag(ah, AR_EEP_BMODE)) ? 849 1.1 alc HAL_OK: HAL_ENXIO; 850 1.1 alc } 851 1.1 alc return HAL_ENXIO; 852 1.1 alc case HAL_CAP_MCAST_KEYSRCH: /* multicast frame keycache search */ 853 1.1 alc switch (capability) { 854 1.1 alc case 0: /* hardware capability */ 855 1.1 alc return HAL_OK; 856 1.1 alc case 1: 857 1.1 alc return (ahp->ah_staId1Defaults & 858 1.1 alc AR_STA_ID1_MCAST_KSRCH) ? HAL_OK : HAL_ENXIO; 859 1.1 alc } 860 1.1 alc return HAL_EINVAL; 861 1.1 alc case HAL_CAP_TSF_ADJUST: /* hardware has beacon tsf adjust */ 862 1.1 alc switch (capability) { 863 1.1 alc case 0: /* hardware capability */ 864 1.1 alc return pCap->halTsfAddSupport ? HAL_OK : HAL_ENOTSUPP; 865 1.1 alc case 1: 866 1.1 alc return (ahp->ah_miscMode & AR_MISC_MODE_TX_ADD_TSF) ? 867 1.1 alc HAL_OK : HAL_ENXIO; 868 1.1 alc } 869 1.1 alc return HAL_EINVAL; 870 1.1 alc case HAL_CAP_TPC_ACK: 871 1.1 alc *result = MS(ahp->ah_macTPC, AR_TPC_ACK); 872 1.1 alc return HAL_OK; 873 1.1 alc case HAL_CAP_TPC_CTS: 874 1.1 alc *result = MS(ahp->ah_macTPC, AR_TPC_CTS); 875 1.1 alc return HAL_OK; 876 1.1 alc case HAL_CAP_INTMIT: /* interference mitigation */ 877 1.1 alc switch (capability) { 878 1.1 alc case 0: /* hardware capability */ 879 1.1 alc return HAL_OK; 880 1.1 alc case 1: 881 1.1 alc return (ahp->ah_procPhyErr & HAL_ANI_ENA) ? 882 1.1 alc HAL_OK : HAL_ENXIO; 883 1.1 alc case 2: /* HAL_ANI_NOISE_IMMUNITY_LEVEL */ 884 1.1 alc case 3: /* HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION */ 885 1.1 alc case 4: /* HAL_ANI_CCK_WEAK_SIGNAL_THR */ 886 1.1 alc case 5: /* HAL_ANI_FIRSTEP_LEVEL */ 887 1.1 alc case 6: /* HAL_ANI_SPUR_IMMUNITY_LEVEL */ 888 1.1 alc ani = ar5212AniGetCurrentState(ah); 889 1.1 alc if (ani == AH_NULL) 890 1.1 alc return HAL_ENXIO; 891 1.1 alc switch (capability) { 892 1.1 alc case 2: *result = ani->noiseImmunityLevel; break; 893 1.1 alc case 3: *result = !ani->ofdmWeakSigDetectOff; break; 894 1.1 alc case 4: *result = ani->cckWeakSigThreshold; break; 895 1.1 alc case 5: *result = ani->firstepLevel; break; 896 1.1 alc case 6: *result = ani->spurImmunityLevel; break; 897 1.1 alc } 898 1.1 alc return HAL_OK; 899 1.1 alc } 900 1.1 alc return HAL_EINVAL; 901 1.1 alc default: 902 1.1 alc return ath_hal_getcapability(ah, type, capability, result); 903 1.1 alc } 904 1.1 alc #undef MACVERSION 905 1.1 alc } 906 1.1 alc 907 1.1 alc HAL_BOOL 908 1.1 alc ar5212SetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, 909 1.1 alc uint32_t capability, uint32_t setting, HAL_STATUS *status) 910 1.1 alc { 911 1.1 alc #define N(a) (sizeof(a)/sizeof(a[0])) 912 1.1 alc struct ath_hal_5212 *ahp = AH5212(ah); 913 1.1 alc const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps; 914 1.1 alc uint32_t v; 915 1.1 alc 916 1.1 alc switch (type) { 917 1.1 alc case HAL_CAP_TKIP_MIC: /* handle TKIP MIC in hardware */ 918 1.1 alc if (setting) 919 1.1 alc ahp->ah_staId1Defaults |= AR_STA_ID1_CRPT_MIC_ENABLE; 920 1.1 alc else 921 1.1 alc ahp->ah_staId1Defaults &= ~AR_STA_ID1_CRPT_MIC_ENABLE; 922 1.1 alc return AH_TRUE; 923 1.1 alc case HAL_CAP_TKIP_SPLIT: /* hardware TKIP uses split keys */ 924 1.1 alc if (!pCap->halTkipMicTxRxKeySupport) 925 1.1 alc return AH_FALSE; 926 1.1 alc /* NB: true =>'s use split key cache layout */ 927 1.1 alc if (setting) 928 1.1 alc ahp->ah_miscMode &= ~AR_MISC_MODE_MIC_NEW_LOC_ENABLE; 929 1.1 alc else 930 1.1 alc ahp->ah_miscMode |= AR_MISC_MODE_MIC_NEW_LOC_ENABLE; 931 1.1 alc /* NB: write here so keys can be setup w/o a reset */ 932 1.1 alc OS_REG_WRITE(ah, AR_MISC_MODE, ahp->ah_miscMode); 933 1.1 alc return AH_TRUE; 934 1.1 alc case HAL_CAP_DIVERSITY: 935 1.1 alc if (ahp->ah_phyPowerOn) { 936 1.1 alc v = OS_REG_READ(ah, AR_PHY_CCK_DETECT); 937 1.1 alc if (setting) 938 1.1 alc v |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV; 939 1.1 alc else 940 1.1 alc v &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV; 941 1.1 alc OS_REG_WRITE(ah, AR_PHY_CCK_DETECT, v); 942 1.1 alc } 943 1.1 alc ahp->ah_diversity = (setting != 0); 944 1.1 alc return AH_TRUE; 945 1.1 alc case HAL_CAP_DIAG: /* hardware diagnostic support */ 946 1.1 alc /* 947 1.1 alc * NB: could split this up into virtual capabilities, 948 1.1 alc * (e.g. 1 => ACK, 2 => CTS, etc.) but it hardly 949 1.1 alc * seems worth the additional complexity. 950 1.1 alc */ 951 1.1 alc AH_PRIVATE(ah)->ah_diagreg = setting; 952 1.1 alc OS_REG_WRITE(ah, AR_DIAG_SW, AH_PRIVATE(ah)->ah_diagreg); 953 1.1 alc return AH_TRUE; 954 1.1 alc case HAL_CAP_TPC: 955 1.1 alc ahp->ah_tpcEnabled = (setting != 0); 956 1.1 alc return AH_TRUE; 957 1.1 alc case HAL_CAP_MCAST_KEYSRCH: /* multicast frame keycache search */ 958 1.1 alc if (setting) 959 1.1 alc ahp->ah_staId1Defaults |= AR_STA_ID1_MCAST_KSRCH; 960 1.1 alc else 961 1.1 alc ahp->ah_staId1Defaults &= ~AR_STA_ID1_MCAST_KSRCH; 962 1.1 alc return AH_TRUE; 963 1.1 alc case HAL_CAP_TPC_ACK: 964 1.1 alc case HAL_CAP_TPC_CTS: 965 1.1 alc setting += ahp->ah_txPowerIndexOffset; 966 1.1 alc if (setting > 63) 967 1.1 alc setting = 63; 968 1.1 alc if (type == HAL_CAP_TPC_ACK) { 969 1.1 alc ahp->ah_macTPC &= AR_TPC_ACK; 970 1.1 alc ahp->ah_macTPC |= MS(setting, AR_TPC_ACK); 971 1.1 alc } else { 972 1.1 alc ahp->ah_macTPC &= AR_TPC_CTS; 973 1.1 alc ahp->ah_macTPC |= MS(setting, AR_TPC_CTS); 974 1.1 alc } 975 1.1 alc OS_REG_WRITE(ah, AR_TPC, ahp->ah_macTPC); 976 1.1 alc return AH_TRUE; 977 1.1 alc case HAL_CAP_INTMIT: { /* interference mitigation */ 978 1.1 alc static const HAL_ANI_CMD cmds[] = { 979 1.1 alc HAL_ANI_PRESENT, 980 1.1 alc HAL_ANI_MODE, 981 1.1 alc HAL_ANI_NOISE_IMMUNITY_LEVEL, 982 1.1 alc HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION, 983 1.1 alc HAL_ANI_CCK_WEAK_SIGNAL_THR, 984 1.1 alc HAL_ANI_FIRSTEP_LEVEL, 985 1.1 alc HAL_ANI_SPUR_IMMUNITY_LEVEL, 986 1.1 alc }; 987 1.1 alc return capability < N(cmds) ? 988 1.1 alc ar5212AniControl(ah, cmds[capability], setting) : 989 1.1 alc AH_FALSE; 990 1.1 alc } 991 1.1 alc case HAL_CAP_TSF_ADJUST: /* hardware has beacon tsf adjust */ 992 1.1 alc if (pCap->halTsfAddSupport) { 993 1.1 alc if (setting) 994 1.1 alc ahp->ah_miscMode |= AR_MISC_MODE_TX_ADD_TSF; 995 1.1 alc else 996 1.1 alc ahp->ah_miscMode &= ~AR_MISC_MODE_TX_ADD_TSF; 997 1.1 alc return AH_TRUE; 998 1.1 alc } 999 1.1 alc /* fall thru... */ 1000 1.1 alc default: 1001 1.1 alc return ath_hal_setcapability(ah, type, capability, 1002 1.1 alc setting, status); 1003 1.1 alc } 1004 1.1 alc #undef N 1005 1.1 alc } 1006 1.1 alc 1007 1.1 alc HAL_BOOL 1008 1.1 alc ar5212GetDiagState(struct ath_hal *ah, int request, 1009 1.1 alc const void *args, uint32_t argsize, 1010 1.1 alc void **result, uint32_t *resultsize) 1011 1.1 alc { 1012 1.1 alc struct ath_hal_5212 *ahp = AH5212(ah); 1013 1.1 alc 1014 1.1 alc (void) ahp; 1015 1.1 alc if (ath_hal_getdiagstate(ah, request, args, argsize, result, resultsize)) 1016 1.1 alc return AH_TRUE; 1017 1.1 alc switch (request) { 1018 1.1 alc case HAL_DIAG_EEPROM: 1019 1.1 alc case HAL_DIAG_EEPROM_EXP_11A: 1020 1.1 alc case HAL_DIAG_EEPROM_EXP_11B: 1021 1.1 alc case HAL_DIAG_EEPROM_EXP_11G: 1022 1.1 alc case HAL_DIAG_RFGAIN: 1023 1.1 alc return ath_hal_eepromDiag(ah, request, 1024 1.1 alc args, argsize, result, resultsize); 1025 1.1 alc case HAL_DIAG_RFGAIN_CURSTEP: 1026 1.1 alc *result = __DECONST(void *, ahp->ah_gainValues.currStep); 1027 1.1 alc *resultsize = (*result == AH_NULL) ? 1028 1.1 alc 0 : sizeof(GAIN_OPTIMIZATION_STEP); 1029 1.1 alc return AH_TRUE; 1030 1.1 alc case HAL_DIAG_PCDAC: 1031 1.1 alc *result = ahp->ah_pcdacTable; 1032 1.1 alc *resultsize = ahp->ah_pcdacTableSize; 1033 1.1 alc return AH_TRUE; 1034 1.1 alc case HAL_DIAG_TXRATES: 1035 1.1 alc *result = &ahp->ah_ratesArray[0]; 1036 1.1 alc *resultsize = sizeof(ahp->ah_ratesArray); 1037 1.1 alc return AH_TRUE; 1038 1.1 alc case HAL_DIAG_ANI_CURRENT: 1039 1.1 alc *result = ar5212AniGetCurrentState(ah); 1040 1.1 alc *resultsize = (*result == AH_NULL) ? 1041 1.1 alc 0 : sizeof(struct ar5212AniState); 1042 1.1 alc return AH_TRUE; 1043 1.1 alc case HAL_DIAG_ANI_STATS: 1044 1.1 alc *result = ar5212AniGetCurrentStats(ah); 1045 1.1 alc *resultsize = (*result == AH_NULL) ? 1046 1.1 alc 0 : sizeof(struct ar5212Stats); 1047 1.1 alc return AH_TRUE; 1048 1.1 alc case HAL_DIAG_ANI_CMD: 1049 1.1 alc if (argsize != 2*sizeof(uint32_t)) 1050 1.1 alc return AH_FALSE; 1051 1.1 alc ar5212AniControl(ah, ((const uint32_t *)args)[0], 1052 1.1 alc ((const uint32_t *)args)[1]); 1053 1.1 alc return AH_TRUE; 1054 1.1 alc case HAL_DIAG_ANI_PARAMS: 1055 1.1 alc /* 1056 1.1 alc * NB: We assume struct ar5212AniParams is identical 1057 1.1 alc * to HAL_ANI_PARAMS; if they diverge then we'll need 1058 1.1 alc * to handle it here 1059 1.1 alc */ 1060 1.1 alc if (argsize == 0 && args == AH_NULL) { 1061 1.1 alc struct ar5212AniState *aniState = 1062 1.1 alc ar5212AniGetCurrentState(ah); 1063 1.1 alc if (aniState == AH_NULL) 1064 1.1 alc return AH_FALSE; 1065 1.1 alc *result = __DECONST(void *, aniState->params); 1066 1.1 alc *resultsize = sizeof(struct ar5212AniParams); 1067 1.1 alc return AH_TRUE; 1068 1.1 alc } else { 1069 1.1 alc if (argsize != sizeof(struct ar5212AniParams)) 1070 1.1 alc return AH_FALSE; 1071 1.1 alc return ar5212AniSetParams(ah, args, args); 1072 1.1 alc } 1073 1.1 alc } 1074 1.1 alc return AH_FALSE; 1075 1.1 alc } 1076 1.2 cegger 1077 1.2 cegger /* 1078 1.2 cegger * Check whether there's an in-progress NF completion. 1079 1.2 cegger * 1080 1.2 cegger * Returns AH_TRUE if there's a in-progress NF calibration, AH_FALSE 1081 1.2 cegger * otherwise. 1082 1.2 cegger */ 1083 1.2 cegger HAL_BOOL 1084 1.2 cegger ar5212IsNFCalInProgress(struct ath_hal *ah) 1085 1.2 cegger { 1086 1.2 cegger if (OS_REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) 1087 1.2 cegger return AH_TRUE; 1088 1.2 cegger return AH_FALSE; 1089 1.2 cegger } 1090 1.2 cegger 1091 1.2 cegger /* 1092 1.2 cegger * Wait for an in-progress NF calibration to complete. 1093 1.2 cegger * 1094 1.2 cegger * The completion function waits "i" times 10uS. 1095 1.2 cegger * It returns AH_TRUE if the NF calibration completed (or was never 1096 1.2 cegger * in progress); AH_FALSE if it was still in progress after "i" checks. 1097 1.2 cegger */ 1098 1.2 cegger HAL_BOOL 1099 1.2 cegger ar5212WaitNFCalComplete(struct ath_hal *ah, int i) 1100 1.2 cegger { 1101 1.2 cegger int j; 1102 1.2 cegger 1103 1.2 cegger if (i <= 0) 1104 1.2 cegger i = 1; /* it should run at least once */ 1105 1.2 cegger for (j = 0; j < i; i++) { 1106 1.2 cegger if (! ar5212IsNFCalInProgress(ah)) 1107 1.2 cegger return AH_TRUE; 1108 1.2 cegger OS_DELAY(10); 1109 1.2 cegger } 1110 1.2 cegger return AH_FALSE; 1111 1.2 cegger } 1112