162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * Copyright (c) 2008-2011 Atheros Communications Inc. 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Permission to use, copy, modify, and/or distribute this software for any 562306a36Sopenharmony_ci * purpose with or without fee is hereby granted, provided that the above 662306a36Sopenharmony_ci * copyright notice and this permission notice appear in all copies. 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 962306a36Sopenharmony_ci * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1062306a36Sopenharmony_ci * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 1162306a36Sopenharmony_ci * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1262306a36Sopenharmony_ci * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1362306a36Sopenharmony_ci * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 1462306a36Sopenharmony_ci * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1562306a36Sopenharmony_ci */ 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#include <linux/io.h> 1862306a36Sopenharmony_ci#include <linux/slab.h> 1962306a36Sopenharmony_ci#include <linux/module.h> 2062306a36Sopenharmony_ci#include <linux/time.h> 2162306a36Sopenharmony_ci#include <linux/bitops.h> 2262306a36Sopenharmony_ci#include <linux/etherdevice.h> 2362306a36Sopenharmony_ci#include <linux/gpio.h> 2462306a36Sopenharmony_ci#include <asm/unaligned.h> 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci#include "hw.h" 2762306a36Sopenharmony_ci#include "hw-ops.h" 2862306a36Sopenharmony_ci#include "ar9003_mac.h" 2962306a36Sopenharmony_ci#include "ar9003_mci.h" 3062306a36Sopenharmony_ci#include "ar9003_phy.h" 3162306a36Sopenharmony_ci#include "ath9k.h" 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_cistatic bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type); 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ciMODULE_AUTHOR("Atheros Communications"); 3662306a36Sopenharmony_ciMODULE_DESCRIPTION("Support for Atheros 802.11n wireless LAN cards."); 3762306a36Sopenharmony_ciMODULE_LICENSE("Dual BSD/GPL"); 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_cistatic void ath9k_hw_set_clockrate(struct ath_hw *ah) 4062306a36Sopenharmony_ci{ 4162306a36Sopenharmony_ci struct ath_common *common = ath9k_hw_common(ah); 4262306a36Sopenharmony_ci struct ath9k_channel *chan = ah->curchan; 4362306a36Sopenharmony_ci unsigned int clockrate; 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci /* AR9287 v1.3+ uses async FIFO and runs the MAC at 117 MHz */ 4662306a36Sopenharmony_ci if (AR_SREV_9287(ah) && AR_SREV_9287_13_OR_LATER(ah)) 4762306a36Sopenharmony_ci clockrate = 117; 4862306a36Sopenharmony_ci else if (!chan) /* should really check for CCK instead */ 4962306a36Sopenharmony_ci clockrate = ATH9K_CLOCK_RATE_CCK; 5062306a36Sopenharmony_ci else if (IS_CHAN_2GHZ(chan)) 5162306a36Sopenharmony_ci clockrate = ATH9K_CLOCK_RATE_2GHZ_OFDM; 5262306a36Sopenharmony_ci else if (ah->caps.hw_caps & ATH9K_HW_CAP_FASTCLOCK) 5362306a36Sopenharmony_ci clockrate = ATH9K_CLOCK_FAST_RATE_5GHZ_OFDM; 5462306a36Sopenharmony_ci else 5562306a36Sopenharmony_ci clockrate = ATH9K_CLOCK_RATE_5GHZ_OFDM; 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci if (chan) { 5862306a36Sopenharmony_ci if (IS_CHAN_HT40(chan)) 5962306a36Sopenharmony_ci clockrate *= 2; 6062306a36Sopenharmony_ci if (IS_CHAN_HALF_RATE(chan)) 6162306a36Sopenharmony_ci clockrate /= 2; 6262306a36Sopenharmony_ci if (IS_CHAN_QUARTER_RATE(chan)) 6362306a36Sopenharmony_ci clockrate /= 4; 6462306a36Sopenharmony_ci } 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci common->clockrate = clockrate; 6762306a36Sopenharmony_ci} 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_cistatic u32 ath9k_hw_mac_to_clks(struct ath_hw *ah, u32 usecs) 7062306a36Sopenharmony_ci{ 7162306a36Sopenharmony_ci struct ath_common *common = ath9k_hw_common(ah); 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci return usecs * common->clockrate; 7462306a36Sopenharmony_ci} 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_cibool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout) 7762306a36Sopenharmony_ci{ 7862306a36Sopenharmony_ci int i; 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci BUG_ON(timeout < AH_TIME_QUANTUM); 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci for (i = 0; i < (timeout / AH_TIME_QUANTUM); i++) { 8362306a36Sopenharmony_ci if ((REG_READ(ah, reg) & mask) == val) 8462306a36Sopenharmony_ci return true; 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci udelay(AH_TIME_QUANTUM); 8762306a36Sopenharmony_ci } 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci ath_dbg(ath9k_hw_common(ah), ANY, 9062306a36Sopenharmony_ci "timeout (%d us) on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n", 9162306a36Sopenharmony_ci timeout, reg, REG_READ(ah, reg), mask, val); 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci return false; 9462306a36Sopenharmony_ci} 9562306a36Sopenharmony_ciEXPORT_SYMBOL(ath9k_hw_wait); 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_civoid ath9k_hw_synth_delay(struct ath_hw *ah, struct ath9k_channel *chan, 9862306a36Sopenharmony_ci int hw_delay) 9962306a36Sopenharmony_ci{ 10062306a36Sopenharmony_ci hw_delay /= 10; 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci if (IS_CHAN_HALF_RATE(chan)) 10362306a36Sopenharmony_ci hw_delay *= 2; 10462306a36Sopenharmony_ci else if (IS_CHAN_QUARTER_RATE(chan)) 10562306a36Sopenharmony_ci hw_delay *= 4; 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci udelay(hw_delay + BASE_ACTIVATE_DELAY); 10862306a36Sopenharmony_ci} 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_civoid ath9k_hw_write_array(struct ath_hw *ah, const struct ar5416IniArray *array, 11162306a36Sopenharmony_ci int column, unsigned int *writecnt) 11262306a36Sopenharmony_ci{ 11362306a36Sopenharmony_ci int r; 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci ENABLE_REGWRITE_BUFFER(ah); 11662306a36Sopenharmony_ci for (r = 0; r < array->ia_rows; r++) { 11762306a36Sopenharmony_ci REG_WRITE(ah, INI_RA(array, r, 0), 11862306a36Sopenharmony_ci INI_RA(array, r, column)); 11962306a36Sopenharmony_ci DO_DELAY(*writecnt); 12062306a36Sopenharmony_ci } 12162306a36Sopenharmony_ci REGWRITE_BUFFER_FLUSH(ah); 12262306a36Sopenharmony_ci} 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_civoid ath9k_hw_read_array(struct ath_hw *ah, u32 array[][2], int size) 12562306a36Sopenharmony_ci{ 12662306a36Sopenharmony_ci u32 *tmp_reg_list, *tmp_data; 12762306a36Sopenharmony_ci int i; 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci tmp_reg_list = kmalloc_array(size, sizeof(u32), GFP_KERNEL); 13062306a36Sopenharmony_ci if (!tmp_reg_list) { 13162306a36Sopenharmony_ci dev_err(ah->dev, "%s: tmp_reg_list: alloc filed\n", __func__); 13262306a36Sopenharmony_ci return; 13362306a36Sopenharmony_ci } 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci tmp_data = kmalloc_array(size, sizeof(u32), GFP_KERNEL); 13662306a36Sopenharmony_ci if (!tmp_data) { 13762306a36Sopenharmony_ci dev_err(ah->dev, "%s tmp_data: alloc filed\n", __func__); 13862306a36Sopenharmony_ci goto error_tmp_data; 13962306a36Sopenharmony_ci } 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci for (i = 0; i < size; i++) 14262306a36Sopenharmony_ci tmp_reg_list[i] = array[i][0]; 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci REG_READ_MULTI(ah, tmp_reg_list, tmp_data, size); 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci for (i = 0; i < size; i++) 14762306a36Sopenharmony_ci array[i][1] = tmp_data[i]; 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci kfree(tmp_data); 15062306a36Sopenharmony_cierror_tmp_data: 15162306a36Sopenharmony_ci kfree(tmp_reg_list); 15262306a36Sopenharmony_ci} 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ciu32 ath9k_hw_reverse_bits(u32 val, u32 n) 15562306a36Sopenharmony_ci{ 15662306a36Sopenharmony_ci u32 retval; 15762306a36Sopenharmony_ci int i; 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci for (i = 0, retval = 0; i < n; i++) { 16062306a36Sopenharmony_ci retval = (retval << 1) | (val & 1); 16162306a36Sopenharmony_ci val >>= 1; 16262306a36Sopenharmony_ci } 16362306a36Sopenharmony_ci return retval; 16462306a36Sopenharmony_ci} 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ciu16 ath9k_hw_computetxtime(struct ath_hw *ah, 16762306a36Sopenharmony_ci u8 phy, int kbps, 16862306a36Sopenharmony_ci u32 frameLen, u16 rateix, 16962306a36Sopenharmony_ci bool shortPreamble) 17062306a36Sopenharmony_ci{ 17162306a36Sopenharmony_ci u32 bitsPerSymbol, numBits, numSymbols, phyTime, txTime; 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci if (kbps == 0) 17462306a36Sopenharmony_ci return 0; 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci switch (phy) { 17762306a36Sopenharmony_ci case WLAN_RC_PHY_CCK: 17862306a36Sopenharmony_ci phyTime = CCK_PREAMBLE_BITS + CCK_PLCP_BITS; 17962306a36Sopenharmony_ci if (shortPreamble) 18062306a36Sopenharmony_ci phyTime >>= 1; 18162306a36Sopenharmony_ci numBits = frameLen << 3; 18262306a36Sopenharmony_ci txTime = CCK_SIFS_TIME + phyTime + ((numBits * 1000) / kbps); 18362306a36Sopenharmony_ci break; 18462306a36Sopenharmony_ci case WLAN_RC_PHY_OFDM: 18562306a36Sopenharmony_ci if (ah->curchan && IS_CHAN_QUARTER_RATE(ah->curchan)) { 18662306a36Sopenharmony_ci bitsPerSymbol = 18762306a36Sopenharmony_ci ((kbps >> 2) * OFDM_SYMBOL_TIME_QUARTER) / 1000; 18862306a36Sopenharmony_ci numBits = OFDM_PLCP_BITS + (frameLen << 3); 18962306a36Sopenharmony_ci numSymbols = DIV_ROUND_UP(numBits, bitsPerSymbol); 19062306a36Sopenharmony_ci txTime = OFDM_SIFS_TIME_QUARTER 19162306a36Sopenharmony_ci + OFDM_PREAMBLE_TIME_QUARTER 19262306a36Sopenharmony_ci + (numSymbols * OFDM_SYMBOL_TIME_QUARTER); 19362306a36Sopenharmony_ci } else if (ah->curchan && 19462306a36Sopenharmony_ci IS_CHAN_HALF_RATE(ah->curchan)) { 19562306a36Sopenharmony_ci bitsPerSymbol = 19662306a36Sopenharmony_ci ((kbps >> 1) * OFDM_SYMBOL_TIME_HALF) / 1000; 19762306a36Sopenharmony_ci numBits = OFDM_PLCP_BITS + (frameLen << 3); 19862306a36Sopenharmony_ci numSymbols = DIV_ROUND_UP(numBits, bitsPerSymbol); 19962306a36Sopenharmony_ci txTime = OFDM_SIFS_TIME_HALF + 20062306a36Sopenharmony_ci OFDM_PREAMBLE_TIME_HALF 20162306a36Sopenharmony_ci + (numSymbols * OFDM_SYMBOL_TIME_HALF); 20262306a36Sopenharmony_ci } else { 20362306a36Sopenharmony_ci bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME) / 1000; 20462306a36Sopenharmony_ci numBits = OFDM_PLCP_BITS + (frameLen << 3); 20562306a36Sopenharmony_ci numSymbols = DIV_ROUND_UP(numBits, bitsPerSymbol); 20662306a36Sopenharmony_ci txTime = OFDM_SIFS_TIME + OFDM_PREAMBLE_TIME 20762306a36Sopenharmony_ci + (numSymbols * OFDM_SYMBOL_TIME); 20862306a36Sopenharmony_ci } 20962306a36Sopenharmony_ci break; 21062306a36Sopenharmony_ci default: 21162306a36Sopenharmony_ci ath_err(ath9k_hw_common(ah), 21262306a36Sopenharmony_ci "Unknown phy %u (rate ix %u)\n", phy, rateix); 21362306a36Sopenharmony_ci txTime = 0; 21462306a36Sopenharmony_ci break; 21562306a36Sopenharmony_ci } 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci return txTime; 21862306a36Sopenharmony_ci} 21962306a36Sopenharmony_ciEXPORT_SYMBOL(ath9k_hw_computetxtime); 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_civoid ath9k_hw_get_channel_centers(struct ath_hw *ah, 22262306a36Sopenharmony_ci struct ath9k_channel *chan, 22362306a36Sopenharmony_ci struct chan_centers *centers) 22462306a36Sopenharmony_ci{ 22562306a36Sopenharmony_ci int8_t extoff; 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci if (!IS_CHAN_HT40(chan)) { 22862306a36Sopenharmony_ci centers->ctl_center = centers->ext_center = 22962306a36Sopenharmony_ci centers->synth_center = chan->channel; 23062306a36Sopenharmony_ci return; 23162306a36Sopenharmony_ci } 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci if (IS_CHAN_HT40PLUS(chan)) { 23462306a36Sopenharmony_ci centers->synth_center = 23562306a36Sopenharmony_ci chan->channel + HT40_CHANNEL_CENTER_SHIFT; 23662306a36Sopenharmony_ci extoff = 1; 23762306a36Sopenharmony_ci } else { 23862306a36Sopenharmony_ci centers->synth_center = 23962306a36Sopenharmony_ci chan->channel - HT40_CHANNEL_CENTER_SHIFT; 24062306a36Sopenharmony_ci extoff = -1; 24162306a36Sopenharmony_ci } 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci centers->ctl_center = 24462306a36Sopenharmony_ci centers->synth_center - (extoff * HT40_CHANNEL_CENTER_SHIFT); 24562306a36Sopenharmony_ci /* 25 MHz spacing is supported by hw but not on upper layers */ 24662306a36Sopenharmony_ci centers->ext_center = 24762306a36Sopenharmony_ci centers->synth_center + (extoff * HT40_CHANNEL_CENTER_SHIFT); 24862306a36Sopenharmony_ci} 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci/******************/ 25162306a36Sopenharmony_ci/* Chip Revisions */ 25262306a36Sopenharmony_ci/******************/ 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_cistatic bool ath9k_hw_read_revisions(struct ath_hw *ah) 25562306a36Sopenharmony_ci{ 25662306a36Sopenharmony_ci u32 srev; 25762306a36Sopenharmony_ci u32 val; 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci if (ah->get_mac_revision) 26062306a36Sopenharmony_ci ah->hw_version.macRev = ah->get_mac_revision(); 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci switch (ah->hw_version.devid) { 26362306a36Sopenharmony_ci case AR5416_AR9100_DEVID: 26462306a36Sopenharmony_ci ah->hw_version.macVersion = AR_SREV_VERSION_9100; 26562306a36Sopenharmony_ci break; 26662306a36Sopenharmony_ci case AR9300_DEVID_AR9330: 26762306a36Sopenharmony_ci ah->hw_version.macVersion = AR_SREV_VERSION_9330; 26862306a36Sopenharmony_ci if (!ah->get_mac_revision) { 26962306a36Sopenharmony_ci val = REG_READ(ah, AR_SREV(ah)); 27062306a36Sopenharmony_ci ah->hw_version.macRev = MS(val, AR_SREV_REVISION2); 27162306a36Sopenharmony_ci } 27262306a36Sopenharmony_ci return true; 27362306a36Sopenharmony_ci case AR9300_DEVID_AR9340: 27462306a36Sopenharmony_ci ah->hw_version.macVersion = AR_SREV_VERSION_9340; 27562306a36Sopenharmony_ci return true; 27662306a36Sopenharmony_ci case AR9300_DEVID_QCA955X: 27762306a36Sopenharmony_ci ah->hw_version.macVersion = AR_SREV_VERSION_9550; 27862306a36Sopenharmony_ci return true; 27962306a36Sopenharmony_ci case AR9300_DEVID_AR953X: 28062306a36Sopenharmony_ci ah->hw_version.macVersion = AR_SREV_VERSION_9531; 28162306a36Sopenharmony_ci return true; 28262306a36Sopenharmony_ci case AR9300_DEVID_QCA956X: 28362306a36Sopenharmony_ci ah->hw_version.macVersion = AR_SREV_VERSION_9561; 28462306a36Sopenharmony_ci return true; 28562306a36Sopenharmony_ci } 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ci srev = REG_READ(ah, AR_SREV(ah)); 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ci if (srev == -1) { 29062306a36Sopenharmony_ci ath_err(ath9k_hw_common(ah), 29162306a36Sopenharmony_ci "Failed to read SREV register"); 29262306a36Sopenharmony_ci return false; 29362306a36Sopenharmony_ci } 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci val = srev & AR_SREV_ID(ah); 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci if (val == 0xFF) { 29862306a36Sopenharmony_ci val = srev; 29962306a36Sopenharmony_ci ah->hw_version.macVersion = 30062306a36Sopenharmony_ci (val & AR_SREV_VERSION2) >> AR_SREV_TYPE2_S; 30162306a36Sopenharmony_ci ah->hw_version.macRev = MS(val, AR_SREV_REVISION2); 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) 30462306a36Sopenharmony_ci ah->is_pciexpress = true; 30562306a36Sopenharmony_ci else 30662306a36Sopenharmony_ci ah->is_pciexpress = (val & 30762306a36Sopenharmony_ci AR_SREV_TYPE2_HOST_MODE) ? 0 : 1; 30862306a36Sopenharmony_ci } else { 30962306a36Sopenharmony_ci if (!AR_SREV_9100(ah)) 31062306a36Sopenharmony_ci ah->hw_version.macVersion = MS(val, AR_SREV_VERSION); 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci ah->hw_version.macRev = val & AR_SREV_REVISION; 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ci if (ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCIE) 31562306a36Sopenharmony_ci ah->is_pciexpress = true; 31662306a36Sopenharmony_ci } 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ci return true; 31962306a36Sopenharmony_ci} 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci/************************************/ 32262306a36Sopenharmony_ci/* HW Attach, Detach, Init Routines */ 32362306a36Sopenharmony_ci/************************************/ 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_cistatic void ath9k_hw_disablepcie(struct ath_hw *ah) 32662306a36Sopenharmony_ci{ 32762306a36Sopenharmony_ci if (!AR_SREV_5416(ah)) 32862306a36Sopenharmony_ci return; 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00); 33162306a36Sopenharmony_ci REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924); 33262306a36Sopenharmony_ci REG_WRITE(ah, AR_PCIE_SERDES, 0x28000029); 33362306a36Sopenharmony_ci REG_WRITE(ah, AR_PCIE_SERDES, 0x57160824); 33462306a36Sopenharmony_ci REG_WRITE(ah, AR_PCIE_SERDES, 0x25980579); 33562306a36Sopenharmony_ci REG_WRITE(ah, AR_PCIE_SERDES, 0x00000000); 33662306a36Sopenharmony_ci REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40); 33762306a36Sopenharmony_ci REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554); 33862306a36Sopenharmony_ci REG_WRITE(ah, AR_PCIE_SERDES, 0x000e1007); 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000); 34162306a36Sopenharmony_ci} 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_ci/* This should work for all families including legacy */ 34462306a36Sopenharmony_cistatic bool ath9k_hw_chip_test(struct ath_hw *ah) 34562306a36Sopenharmony_ci{ 34662306a36Sopenharmony_ci struct ath_common *common = ath9k_hw_common(ah); 34762306a36Sopenharmony_ci u32 regAddr[2] = { AR_STA_ID0 }; 34862306a36Sopenharmony_ci u32 regHold[2]; 34962306a36Sopenharmony_ci static const u32 patternData[4] = { 35062306a36Sopenharmony_ci 0x55555555, 0xaaaaaaaa, 0x66666666, 0x99999999 35162306a36Sopenharmony_ci }; 35262306a36Sopenharmony_ci int i, j, loop_max; 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci if (!AR_SREV_9300_20_OR_LATER(ah)) { 35562306a36Sopenharmony_ci loop_max = 2; 35662306a36Sopenharmony_ci regAddr[1] = AR_PHY_BASE + (8 << 2); 35762306a36Sopenharmony_ci } else 35862306a36Sopenharmony_ci loop_max = 1; 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_ci for (i = 0; i < loop_max; i++) { 36162306a36Sopenharmony_ci u32 addr = regAddr[i]; 36262306a36Sopenharmony_ci u32 wrData, rdData; 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_ci regHold[i] = REG_READ(ah, addr); 36562306a36Sopenharmony_ci for (j = 0; j < 0x100; j++) { 36662306a36Sopenharmony_ci wrData = (j << 16) | j; 36762306a36Sopenharmony_ci REG_WRITE(ah, addr, wrData); 36862306a36Sopenharmony_ci rdData = REG_READ(ah, addr); 36962306a36Sopenharmony_ci if (rdData != wrData) { 37062306a36Sopenharmony_ci ath_err(common, 37162306a36Sopenharmony_ci "address test failed addr: 0x%08x - wr:0x%08x != rd:0x%08x\n", 37262306a36Sopenharmony_ci addr, wrData, rdData); 37362306a36Sopenharmony_ci return false; 37462306a36Sopenharmony_ci } 37562306a36Sopenharmony_ci } 37662306a36Sopenharmony_ci for (j = 0; j < 4; j++) { 37762306a36Sopenharmony_ci wrData = patternData[j]; 37862306a36Sopenharmony_ci REG_WRITE(ah, addr, wrData); 37962306a36Sopenharmony_ci rdData = REG_READ(ah, addr); 38062306a36Sopenharmony_ci if (wrData != rdData) { 38162306a36Sopenharmony_ci ath_err(common, 38262306a36Sopenharmony_ci "address test failed addr: 0x%08x - wr:0x%08x != rd:0x%08x\n", 38362306a36Sopenharmony_ci addr, wrData, rdData); 38462306a36Sopenharmony_ci return false; 38562306a36Sopenharmony_ci } 38662306a36Sopenharmony_ci } 38762306a36Sopenharmony_ci REG_WRITE(ah, regAddr[i], regHold[i]); 38862306a36Sopenharmony_ci } 38962306a36Sopenharmony_ci udelay(100); 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_ci return true; 39262306a36Sopenharmony_ci} 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_cistatic void ath9k_hw_init_config(struct ath_hw *ah) 39562306a36Sopenharmony_ci{ 39662306a36Sopenharmony_ci struct ath_common *common = ath9k_hw_common(ah); 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_ci ah->config.dma_beacon_response_time = 1; 39962306a36Sopenharmony_ci ah->config.sw_beacon_response_time = 6; 40062306a36Sopenharmony_ci ah->config.cwm_ignore_extcca = false; 40162306a36Sopenharmony_ci ah->config.analog_shiftreg = 1; 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_ci ah->config.rx_intr_mitigation = true; 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci if (AR_SREV_9300_20_OR_LATER(ah)) { 40662306a36Sopenharmony_ci ah->config.rimt_last = 500; 40762306a36Sopenharmony_ci ah->config.rimt_first = 2000; 40862306a36Sopenharmony_ci } else { 40962306a36Sopenharmony_ci ah->config.rimt_last = 250; 41062306a36Sopenharmony_ci ah->config.rimt_first = 700; 41162306a36Sopenharmony_ci } 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ci if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) 41462306a36Sopenharmony_ci ah->config.pll_pwrsave = 7; 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_ci /* 41762306a36Sopenharmony_ci * We need this for PCI devices only (Cardbus, PCI, miniPCI) 41862306a36Sopenharmony_ci * _and_ if on non-uniprocessor systems (Multiprocessor/HT). 41962306a36Sopenharmony_ci * This means we use it for all AR5416 devices, and the few 42062306a36Sopenharmony_ci * minor PCI AR9280 devices out there. 42162306a36Sopenharmony_ci * 42262306a36Sopenharmony_ci * Serialization is required because these devices do not handle 42362306a36Sopenharmony_ci * well the case of two concurrent reads/writes due to the latency 42462306a36Sopenharmony_ci * involved. During one read/write another read/write can be issued 42562306a36Sopenharmony_ci * on another CPU while the previous read/write may still be working 42662306a36Sopenharmony_ci * on our hardware, if we hit this case the hardware poops in a loop. 42762306a36Sopenharmony_ci * We prevent this by serializing reads and writes. 42862306a36Sopenharmony_ci * 42962306a36Sopenharmony_ci * This issue is not present on PCI-Express devices or pre-AR5416 43062306a36Sopenharmony_ci * devices (legacy, 802.11abg). 43162306a36Sopenharmony_ci */ 43262306a36Sopenharmony_ci if (num_possible_cpus() > 1) 43362306a36Sopenharmony_ci ah->config.serialize_regmode = SER_REG_MODE_AUTO; 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_ci if (NR_CPUS > 1 && ah->config.serialize_regmode == SER_REG_MODE_AUTO) { 43662306a36Sopenharmony_ci if (ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCI || 43762306a36Sopenharmony_ci ((AR_SREV_9160(ah) || AR_SREV_9280(ah) || AR_SREV_9287(ah)) && 43862306a36Sopenharmony_ci !ah->is_pciexpress)) { 43962306a36Sopenharmony_ci ah->config.serialize_regmode = SER_REG_MODE_ON; 44062306a36Sopenharmony_ci } else { 44162306a36Sopenharmony_ci ah->config.serialize_regmode = SER_REG_MODE_OFF; 44262306a36Sopenharmony_ci } 44362306a36Sopenharmony_ci } 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_ci ath_dbg(common, RESET, "serialize_regmode is %d\n", 44662306a36Sopenharmony_ci ah->config.serialize_regmode); 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_ci if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) 44962306a36Sopenharmony_ci ah->config.max_txtrig_level = MAX_TX_FIFO_THRESHOLD >> 1; 45062306a36Sopenharmony_ci else 45162306a36Sopenharmony_ci ah->config.max_txtrig_level = MAX_TX_FIFO_THRESHOLD; 45262306a36Sopenharmony_ci} 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_cistatic void ath9k_hw_init_defaults(struct ath_hw *ah) 45562306a36Sopenharmony_ci{ 45662306a36Sopenharmony_ci struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_ci regulatory->country_code = CTRY_DEFAULT; 45962306a36Sopenharmony_ci regulatory->power_limit = MAX_COMBINED_POWER; 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_ci ah->hw_version.magic = AR5416_MAGIC; 46262306a36Sopenharmony_ci ah->hw_version.subvendorid = 0; 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_ci ah->sta_id1_defaults = AR_STA_ID1_CRPT_MIC_ENABLE | 46562306a36Sopenharmony_ci AR_STA_ID1_MCAST_KSRCH; 46662306a36Sopenharmony_ci if (AR_SREV_9100(ah)) 46762306a36Sopenharmony_ci ah->sta_id1_defaults |= AR_STA_ID1_AR9100_BA_FIX; 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_ci ah->slottime = 9; 47062306a36Sopenharmony_ci ah->globaltxtimeout = (u32) -1; 47162306a36Sopenharmony_ci ah->power_mode = ATH9K_PM_UNDEFINED; 47262306a36Sopenharmony_ci ah->htc_reset_init = true; 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_ci ah->tpc_enabled = false; 47562306a36Sopenharmony_ci 47662306a36Sopenharmony_ci ah->ani_function = ATH9K_ANI_ALL; 47762306a36Sopenharmony_ci if (!AR_SREV_9300_20_OR_LATER(ah)) 47862306a36Sopenharmony_ci ah->ani_function &= ~ATH9K_ANI_MRC_CCK; 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_ci if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) 48162306a36Sopenharmony_ci ah->tx_trig_level = (AR_FTRIG_256B >> AR_FTRIG_S); 48262306a36Sopenharmony_ci else 48362306a36Sopenharmony_ci ah->tx_trig_level = (AR_FTRIG_512B >> AR_FTRIG_S); 48462306a36Sopenharmony_ci} 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_cistatic void ath9k_hw_init_macaddr(struct ath_hw *ah) 48762306a36Sopenharmony_ci{ 48862306a36Sopenharmony_ci struct ath_common *common = ath9k_hw_common(ah); 48962306a36Sopenharmony_ci int i; 49062306a36Sopenharmony_ci u16 eeval; 49162306a36Sopenharmony_ci static const u32 EEP_MAC[] = { EEP_MAC_LSW, EEP_MAC_MID, EEP_MAC_MSW }; 49262306a36Sopenharmony_ci 49362306a36Sopenharmony_ci /* MAC address may already be loaded via ath9k_platform_data */ 49462306a36Sopenharmony_ci if (is_valid_ether_addr(common->macaddr)) 49562306a36Sopenharmony_ci return; 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_ci for (i = 0; i < 3; i++) { 49862306a36Sopenharmony_ci eeval = ah->eep_ops->get_eeprom(ah, EEP_MAC[i]); 49962306a36Sopenharmony_ci common->macaddr[2 * i] = eeval >> 8; 50062306a36Sopenharmony_ci common->macaddr[2 * i + 1] = eeval & 0xff; 50162306a36Sopenharmony_ci } 50262306a36Sopenharmony_ci 50362306a36Sopenharmony_ci if (is_valid_ether_addr(common->macaddr)) 50462306a36Sopenharmony_ci return; 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_ci ath_err(common, "eeprom contains invalid mac address: %pM\n", 50762306a36Sopenharmony_ci common->macaddr); 50862306a36Sopenharmony_ci 50962306a36Sopenharmony_ci eth_random_addr(common->macaddr); 51062306a36Sopenharmony_ci ath_err(common, "random mac address will be used: %pM\n", 51162306a36Sopenharmony_ci common->macaddr); 51262306a36Sopenharmony_ci 51362306a36Sopenharmony_ci return; 51462306a36Sopenharmony_ci} 51562306a36Sopenharmony_ci 51662306a36Sopenharmony_cistatic int ath9k_hw_post_init(struct ath_hw *ah) 51762306a36Sopenharmony_ci{ 51862306a36Sopenharmony_ci struct ath_common *common = ath9k_hw_common(ah); 51962306a36Sopenharmony_ci int ecode; 52062306a36Sopenharmony_ci 52162306a36Sopenharmony_ci if (common->bus_ops->ath_bus_type != ATH_USB) { 52262306a36Sopenharmony_ci if (!ath9k_hw_chip_test(ah)) 52362306a36Sopenharmony_ci return -ENODEV; 52462306a36Sopenharmony_ci } 52562306a36Sopenharmony_ci 52662306a36Sopenharmony_ci if (!AR_SREV_9300_20_OR_LATER(ah)) { 52762306a36Sopenharmony_ci ecode = ar9002_hw_rf_claim(ah); 52862306a36Sopenharmony_ci if (ecode != 0) 52962306a36Sopenharmony_ci return ecode; 53062306a36Sopenharmony_ci } 53162306a36Sopenharmony_ci 53262306a36Sopenharmony_ci ecode = ath9k_hw_eeprom_init(ah); 53362306a36Sopenharmony_ci if (ecode != 0) 53462306a36Sopenharmony_ci return ecode; 53562306a36Sopenharmony_ci 53662306a36Sopenharmony_ci ath_dbg(ath9k_hw_common(ah), CONFIG, "Eeprom VER: %d, REV: %d\n", 53762306a36Sopenharmony_ci ah->eep_ops->get_eeprom_ver(ah), 53862306a36Sopenharmony_ci ah->eep_ops->get_eeprom_rev(ah)); 53962306a36Sopenharmony_ci 54062306a36Sopenharmony_ci ath9k_hw_ani_init(ah); 54162306a36Sopenharmony_ci 54262306a36Sopenharmony_ci /* 54362306a36Sopenharmony_ci * EEPROM needs to be initialized before we do this. 54462306a36Sopenharmony_ci * This is required for regulatory compliance. 54562306a36Sopenharmony_ci */ 54662306a36Sopenharmony_ci if (AR_SREV_9300_20_OR_LATER(ah)) { 54762306a36Sopenharmony_ci u16 regdmn = ah->eep_ops->get_eeprom(ah, EEP_REG_0); 54862306a36Sopenharmony_ci if ((regdmn & 0xF0) == CTL_FCC) { 54962306a36Sopenharmony_ci ah->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_9300_FCC_2GHZ; 55062306a36Sopenharmony_ci ah->nf_5g.max = AR_PHY_CCA_MAX_GOOD_VAL_9300_FCC_5GHZ; 55162306a36Sopenharmony_ci } 55262306a36Sopenharmony_ci } 55362306a36Sopenharmony_ci 55462306a36Sopenharmony_ci return 0; 55562306a36Sopenharmony_ci} 55662306a36Sopenharmony_ci 55762306a36Sopenharmony_cistatic int ath9k_hw_attach_ops(struct ath_hw *ah) 55862306a36Sopenharmony_ci{ 55962306a36Sopenharmony_ci if (!AR_SREV_9300_20_OR_LATER(ah)) 56062306a36Sopenharmony_ci return ar9002_hw_attach_ops(ah); 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_ci ar9003_hw_attach_ops(ah); 56362306a36Sopenharmony_ci return 0; 56462306a36Sopenharmony_ci} 56562306a36Sopenharmony_ci 56662306a36Sopenharmony_ci/* Called for all hardware families */ 56762306a36Sopenharmony_cistatic int __ath9k_hw_init(struct ath_hw *ah) 56862306a36Sopenharmony_ci{ 56962306a36Sopenharmony_ci struct ath_common *common = ath9k_hw_common(ah); 57062306a36Sopenharmony_ci int r = 0; 57162306a36Sopenharmony_ci 57262306a36Sopenharmony_ci if (!ath9k_hw_read_revisions(ah)) { 57362306a36Sopenharmony_ci ath_err(common, "Could not read hardware revisions"); 57462306a36Sopenharmony_ci return -EOPNOTSUPP; 57562306a36Sopenharmony_ci } 57662306a36Sopenharmony_ci 57762306a36Sopenharmony_ci switch (ah->hw_version.macVersion) { 57862306a36Sopenharmony_ci case AR_SREV_VERSION_5416_PCI: 57962306a36Sopenharmony_ci case AR_SREV_VERSION_5416_PCIE: 58062306a36Sopenharmony_ci case AR_SREV_VERSION_9160: 58162306a36Sopenharmony_ci case AR_SREV_VERSION_9100: 58262306a36Sopenharmony_ci case AR_SREV_VERSION_9280: 58362306a36Sopenharmony_ci case AR_SREV_VERSION_9285: 58462306a36Sopenharmony_ci case AR_SREV_VERSION_9287: 58562306a36Sopenharmony_ci case AR_SREV_VERSION_9271: 58662306a36Sopenharmony_ci case AR_SREV_VERSION_9300: 58762306a36Sopenharmony_ci case AR_SREV_VERSION_9330: 58862306a36Sopenharmony_ci case AR_SREV_VERSION_9485: 58962306a36Sopenharmony_ci case AR_SREV_VERSION_9340: 59062306a36Sopenharmony_ci case AR_SREV_VERSION_9462: 59162306a36Sopenharmony_ci case AR_SREV_VERSION_9550: 59262306a36Sopenharmony_ci case AR_SREV_VERSION_9565: 59362306a36Sopenharmony_ci case AR_SREV_VERSION_9531: 59462306a36Sopenharmony_ci case AR_SREV_VERSION_9561: 59562306a36Sopenharmony_ci break; 59662306a36Sopenharmony_ci default: 59762306a36Sopenharmony_ci ath_err(common, 59862306a36Sopenharmony_ci "Mac Chip Rev 0x%02x.%x is not supported by this driver\n", 59962306a36Sopenharmony_ci ah->hw_version.macVersion, ah->hw_version.macRev); 60062306a36Sopenharmony_ci return -EOPNOTSUPP; 60162306a36Sopenharmony_ci } 60262306a36Sopenharmony_ci 60362306a36Sopenharmony_ci /* 60462306a36Sopenharmony_ci * Read back AR_WA(ah) into a permanent copy and set bits 14 and 17. 60562306a36Sopenharmony_ci * We need to do this to avoid RMW of this register. We cannot 60662306a36Sopenharmony_ci * read the reg when chip is asleep. 60762306a36Sopenharmony_ci */ 60862306a36Sopenharmony_ci if (AR_SREV_9300_20_OR_LATER(ah)) { 60962306a36Sopenharmony_ci ah->WARegVal = REG_READ(ah, AR_WA(ah)); 61062306a36Sopenharmony_ci ah->WARegVal |= (AR_WA_D3_L1_DISABLE | 61162306a36Sopenharmony_ci AR_WA_ASPM_TIMER_BASED_DISABLE); 61262306a36Sopenharmony_ci } 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_ci if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) { 61562306a36Sopenharmony_ci ath_err(common, "Couldn't reset chip\n"); 61662306a36Sopenharmony_ci return -EIO; 61762306a36Sopenharmony_ci } 61862306a36Sopenharmony_ci 61962306a36Sopenharmony_ci if (AR_SREV_9565(ah)) { 62062306a36Sopenharmony_ci ah->WARegVal |= AR_WA_BIT22; 62162306a36Sopenharmony_ci REG_WRITE(ah, AR_WA(ah), ah->WARegVal); 62262306a36Sopenharmony_ci } 62362306a36Sopenharmony_ci 62462306a36Sopenharmony_ci ath9k_hw_init_defaults(ah); 62562306a36Sopenharmony_ci ath9k_hw_init_config(ah); 62662306a36Sopenharmony_ci 62762306a36Sopenharmony_ci r = ath9k_hw_attach_ops(ah); 62862306a36Sopenharmony_ci if (r) 62962306a36Sopenharmony_ci return r; 63062306a36Sopenharmony_ci 63162306a36Sopenharmony_ci if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) { 63262306a36Sopenharmony_ci ath_err(common, "Couldn't wakeup chip\n"); 63362306a36Sopenharmony_ci return -EIO; 63462306a36Sopenharmony_ci } 63562306a36Sopenharmony_ci 63662306a36Sopenharmony_ci if (AR_SREV_9271(ah) || AR_SREV_9100(ah) || AR_SREV_9340(ah) || 63762306a36Sopenharmony_ci AR_SREV_9330(ah) || AR_SREV_9550(ah)) 63862306a36Sopenharmony_ci ah->is_pciexpress = false; 63962306a36Sopenharmony_ci 64062306a36Sopenharmony_ci ah->hw_version.phyRev = REG_READ(ah, AR_PHY_CHIP_ID); 64162306a36Sopenharmony_ci ath9k_hw_init_cal_settings(ah); 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_ci if (!ah->is_pciexpress) 64462306a36Sopenharmony_ci ath9k_hw_disablepcie(ah); 64562306a36Sopenharmony_ci 64662306a36Sopenharmony_ci r = ath9k_hw_post_init(ah); 64762306a36Sopenharmony_ci if (r) 64862306a36Sopenharmony_ci return r; 64962306a36Sopenharmony_ci 65062306a36Sopenharmony_ci ath9k_hw_init_mode_gain_regs(ah); 65162306a36Sopenharmony_ci r = ath9k_hw_fill_cap_info(ah); 65262306a36Sopenharmony_ci if (r) 65362306a36Sopenharmony_ci return r; 65462306a36Sopenharmony_ci 65562306a36Sopenharmony_ci ath9k_hw_init_macaddr(ah); 65662306a36Sopenharmony_ci ath9k_hw_init_hang_checks(ah); 65762306a36Sopenharmony_ci 65862306a36Sopenharmony_ci common->state = ATH_HW_INITIALIZED; 65962306a36Sopenharmony_ci 66062306a36Sopenharmony_ci return 0; 66162306a36Sopenharmony_ci} 66262306a36Sopenharmony_ci 66362306a36Sopenharmony_ciint ath9k_hw_init(struct ath_hw *ah) 66462306a36Sopenharmony_ci{ 66562306a36Sopenharmony_ci int ret; 66662306a36Sopenharmony_ci struct ath_common *common = ath9k_hw_common(ah); 66762306a36Sopenharmony_ci 66862306a36Sopenharmony_ci /* These are all the AR5008/AR9001/AR9002/AR9003 hardware family of chipsets */ 66962306a36Sopenharmony_ci switch (ah->hw_version.devid) { 67062306a36Sopenharmony_ci case AR5416_DEVID_PCI: 67162306a36Sopenharmony_ci case AR5416_DEVID_PCIE: 67262306a36Sopenharmony_ci case AR5416_AR9100_DEVID: 67362306a36Sopenharmony_ci case AR9160_DEVID_PCI: 67462306a36Sopenharmony_ci case AR9280_DEVID_PCI: 67562306a36Sopenharmony_ci case AR9280_DEVID_PCIE: 67662306a36Sopenharmony_ci case AR9285_DEVID_PCIE: 67762306a36Sopenharmony_ci case AR9287_DEVID_PCI: 67862306a36Sopenharmony_ci case AR9287_DEVID_PCIE: 67962306a36Sopenharmony_ci case AR2427_DEVID_PCIE: 68062306a36Sopenharmony_ci case AR9300_DEVID_PCIE: 68162306a36Sopenharmony_ci case AR9300_DEVID_AR9485_PCIE: 68262306a36Sopenharmony_ci case AR9300_DEVID_AR9330: 68362306a36Sopenharmony_ci case AR9300_DEVID_AR9340: 68462306a36Sopenharmony_ci case AR9300_DEVID_QCA955X: 68562306a36Sopenharmony_ci case AR9300_DEVID_AR9580: 68662306a36Sopenharmony_ci case AR9300_DEVID_AR9462: 68762306a36Sopenharmony_ci case AR9485_DEVID_AR1111: 68862306a36Sopenharmony_ci case AR9300_DEVID_AR9565: 68962306a36Sopenharmony_ci case AR9300_DEVID_AR953X: 69062306a36Sopenharmony_ci case AR9300_DEVID_QCA956X: 69162306a36Sopenharmony_ci break; 69262306a36Sopenharmony_ci default: 69362306a36Sopenharmony_ci if (common->bus_ops->ath_bus_type == ATH_USB) 69462306a36Sopenharmony_ci break; 69562306a36Sopenharmony_ci ath_err(common, "Hardware device ID 0x%04x not supported\n", 69662306a36Sopenharmony_ci ah->hw_version.devid); 69762306a36Sopenharmony_ci return -EOPNOTSUPP; 69862306a36Sopenharmony_ci } 69962306a36Sopenharmony_ci 70062306a36Sopenharmony_ci ret = __ath9k_hw_init(ah); 70162306a36Sopenharmony_ci if (ret) { 70262306a36Sopenharmony_ci ath_err(common, 70362306a36Sopenharmony_ci "Unable to initialize hardware; initialization status: %d\n", 70462306a36Sopenharmony_ci ret); 70562306a36Sopenharmony_ci return ret; 70662306a36Sopenharmony_ci } 70762306a36Sopenharmony_ci 70862306a36Sopenharmony_ci ath_dynack_init(ah); 70962306a36Sopenharmony_ci 71062306a36Sopenharmony_ci return 0; 71162306a36Sopenharmony_ci} 71262306a36Sopenharmony_ciEXPORT_SYMBOL(ath9k_hw_init); 71362306a36Sopenharmony_ci 71462306a36Sopenharmony_cistatic void ath9k_hw_init_qos(struct ath_hw *ah) 71562306a36Sopenharmony_ci{ 71662306a36Sopenharmony_ci ENABLE_REGWRITE_BUFFER(ah); 71762306a36Sopenharmony_ci 71862306a36Sopenharmony_ci REG_WRITE(ah, AR_MIC_QOS_CONTROL, 0x100aa); 71962306a36Sopenharmony_ci REG_WRITE(ah, AR_MIC_QOS_SELECT, 0x3210); 72062306a36Sopenharmony_ci 72162306a36Sopenharmony_ci REG_WRITE(ah, AR_QOS_NO_ACK, 72262306a36Sopenharmony_ci SM(2, AR_QOS_NO_ACK_TWO_BIT) | 72362306a36Sopenharmony_ci SM(5, AR_QOS_NO_ACK_BIT_OFF) | 72462306a36Sopenharmony_ci SM(0, AR_QOS_NO_ACK_BYTE_OFF)); 72562306a36Sopenharmony_ci 72662306a36Sopenharmony_ci REG_WRITE(ah, AR_TXOP_X, AR_TXOP_X_VAL); 72762306a36Sopenharmony_ci REG_WRITE(ah, AR_TXOP_0_3, 0xFFFFFFFF); 72862306a36Sopenharmony_ci REG_WRITE(ah, AR_TXOP_4_7, 0xFFFFFFFF); 72962306a36Sopenharmony_ci REG_WRITE(ah, AR_TXOP_8_11, 0xFFFFFFFF); 73062306a36Sopenharmony_ci REG_WRITE(ah, AR_TXOP_12_15, 0xFFFFFFFF); 73162306a36Sopenharmony_ci 73262306a36Sopenharmony_ci REGWRITE_BUFFER_FLUSH(ah); 73362306a36Sopenharmony_ci} 73462306a36Sopenharmony_ci 73562306a36Sopenharmony_ciu32 ar9003_get_pll_sqsum_dvc(struct ath_hw *ah) 73662306a36Sopenharmony_ci{ 73762306a36Sopenharmony_ci struct ath_common *common = ath9k_hw_common(ah); 73862306a36Sopenharmony_ci int i = 0; 73962306a36Sopenharmony_ci 74062306a36Sopenharmony_ci REG_CLR_BIT(ah, PLL3, PLL3_DO_MEAS_MASK); 74162306a36Sopenharmony_ci udelay(100); 74262306a36Sopenharmony_ci REG_SET_BIT(ah, PLL3, PLL3_DO_MEAS_MASK); 74362306a36Sopenharmony_ci 74462306a36Sopenharmony_ci while ((REG_READ(ah, PLL4) & PLL4_MEAS_DONE) == 0) { 74562306a36Sopenharmony_ci 74662306a36Sopenharmony_ci udelay(100); 74762306a36Sopenharmony_ci 74862306a36Sopenharmony_ci if (WARN_ON_ONCE(i >= 100)) { 74962306a36Sopenharmony_ci ath_err(common, "PLL4 measurement not done\n"); 75062306a36Sopenharmony_ci break; 75162306a36Sopenharmony_ci } 75262306a36Sopenharmony_ci 75362306a36Sopenharmony_ci i++; 75462306a36Sopenharmony_ci } 75562306a36Sopenharmony_ci 75662306a36Sopenharmony_ci return (REG_READ(ah, PLL3) & SQSUM_DVC_MASK) >> 3; 75762306a36Sopenharmony_ci} 75862306a36Sopenharmony_ciEXPORT_SYMBOL(ar9003_get_pll_sqsum_dvc); 75962306a36Sopenharmony_ci 76062306a36Sopenharmony_cistatic void ath9k_hw_init_pll(struct ath_hw *ah, 76162306a36Sopenharmony_ci struct ath9k_channel *chan) 76262306a36Sopenharmony_ci{ 76362306a36Sopenharmony_ci u32 pll; 76462306a36Sopenharmony_ci 76562306a36Sopenharmony_ci pll = ath9k_hw_compute_pll_control(ah, chan); 76662306a36Sopenharmony_ci 76762306a36Sopenharmony_ci if (AR_SREV_9485(ah) || AR_SREV_9565(ah)) { 76862306a36Sopenharmony_ci /* program BB PLL ki and kd value, ki=0x4, kd=0x40 */ 76962306a36Sopenharmony_ci REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, 77062306a36Sopenharmony_ci AR_CH0_BB_DPLL2_PLL_PWD, 0x1); 77162306a36Sopenharmony_ci REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, 77262306a36Sopenharmony_ci AR_CH0_DPLL2_KD, 0x40); 77362306a36Sopenharmony_ci REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, 77462306a36Sopenharmony_ci AR_CH0_DPLL2_KI, 0x4); 77562306a36Sopenharmony_ci 77662306a36Sopenharmony_ci REG_RMW_FIELD(ah, AR_CH0_BB_DPLL1, 77762306a36Sopenharmony_ci AR_CH0_BB_DPLL1_REFDIV, 0x5); 77862306a36Sopenharmony_ci REG_RMW_FIELD(ah, AR_CH0_BB_DPLL1, 77962306a36Sopenharmony_ci AR_CH0_BB_DPLL1_NINI, 0x58); 78062306a36Sopenharmony_ci REG_RMW_FIELD(ah, AR_CH0_BB_DPLL1, 78162306a36Sopenharmony_ci AR_CH0_BB_DPLL1_NFRAC, 0x0); 78262306a36Sopenharmony_ci 78362306a36Sopenharmony_ci REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, 78462306a36Sopenharmony_ci AR_CH0_BB_DPLL2_OUTDIV, 0x1); 78562306a36Sopenharmony_ci REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, 78662306a36Sopenharmony_ci AR_CH0_BB_DPLL2_LOCAL_PLL, 0x1); 78762306a36Sopenharmony_ci REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, 78862306a36Sopenharmony_ci AR_CH0_BB_DPLL2_EN_NEGTRIG, 0x1); 78962306a36Sopenharmony_ci 79062306a36Sopenharmony_ci /* program BB PLL phase_shift to 0x6 */ 79162306a36Sopenharmony_ci REG_RMW_FIELD(ah, AR_CH0_BB_DPLL3, 79262306a36Sopenharmony_ci AR_CH0_BB_DPLL3_PHASE_SHIFT, 0x6); 79362306a36Sopenharmony_ci 79462306a36Sopenharmony_ci REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, 79562306a36Sopenharmony_ci AR_CH0_BB_DPLL2_PLL_PWD, 0x0); 79662306a36Sopenharmony_ci udelay(1000); 79762306a36Sopenharmony_ci } else if (AR_SREV_9330(ah)) { 79862306a36Sopenharmony_ci u32 ddr_dpll2, pll_control2, kd; 79962306a36Sopenharmony_ci 80062306a36Sopenharmony_ci if (ah->is_clk_25mhz) { 80162306a36Sopenharmony_ci ddr_dpll2 = 0x18e82f01; 80262306a36Sopenharmony_ci pll_control2 = 0xe04a3d; 80362306a36Sopenharmony_ci kd = 0x1d; 80462306a36Sopenharmony_ci } else { 80562306a36Sopenharmony_ci ddr_dpll2 = 0x19e82f01; 80662306a36Sopenharmony_ci pll_control2 = 0x886666; 80762306a36Sopenharmony_ci kd = 0x3d; 80862306a36Sopenharmony_ci } 80962306a36Sopenharmony_ci 81062306a36Sopenharmony_ci /* program DDR PLL ki and kd value */ 81162306a36Sopenharmony_ci REG_WRITE(ah, AR_CH0_DDR_DPLL2, ddr_dpll2); 81262306a36Sopenharmony_ci 81362306a36Sopenharmony_ci /* program DDR PLL phase_shift */ 81462306a36Sopenharmony_ci REG_RMW_FIELD(ah, AR_CH0_DDR_DPLL3, 81562306a36Sopenharmony_ci AR_CH0_DPLL3_PHASE_SHIFT, 0x1); 81662306a36Sopenharmony_ci 81762306a36Sopenharmony_ci REG_WRITE(ah, AR_RTC_PLL_CONTROL(ah), 81862306a36Sopenharmony_ci pll | AR_RTC_9300_PLL_BYPASS); 81962306a36Sopenharmony_ci udelay(1000); 82062306a36Sopenharmony_ci 82162306a36Sopenharmony_ci /* program refdiv, nint, frac to RTC register */ 82262306a36Sopenharmony_ci REG_WRITE(ah, AR_RTC_PLL_CONTROL2, pll_control2); 82362306a36Sopenharmony_ci 82462306a36Sopenharmony_ci /* program BB PLL kd and ki value */ 82562306a36Sopenharmony_ci REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, AR_CH0_DPLL2_KD, kd); 82662306a36Sopenharmony_ci REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, AR_CH0_DPLL2_KI, 0x06); 82762306a36Sopenharmony_ci 82862306a36Sopenharmony_ci /* program BB PLL phase_shift */ 82962306a36Sopenharmony_ci REG_RMW_FIELD(ah, AR_CH0_BB_DPLL3, 83062306a36Sopenharmony_ci AR_CH0_BB_DPLL3_PHASE_SHIFT, 0x1); 83162306a36Sopenharmony_ci } else if (AR_SREV_9340(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah) || 83262306a36Sopenharmony_ci AR_SREV_9561(ah)) { 83362306a36Sopenharmony_ci u32 regval, pll2_divint, pll2_divfrac, refdiv; 83462306a36Sopenharmony_ci 83562306a36Sopenharmony_ci REG_WRITE(ah, AR_RTC_PLL_CONTROL(ah), 83662306a36Sopenharmony_ci pll | AR_RTC_9300_SOC_PLL_BYPASS); 83762306a36Sopenharmony_ci udelay(1000); 83862306a36Sopenharmony_ci 83962306a36Sopenharmony_ci REG_SET_BIT(ah, AR_PHY_PLL_MODE, 0x1 << 16); 84062306a36Sopenharmony_ci udelay(100); 84162306a36Sopenharmony_ci 84262306a36Sopenharmony_ci if (ah->is_clk_25mhz) { 84362306a36Sopenharmony_ci if (AR_SREV_9531(ah) || AR_SREV_9561(ah)) { 84462306a36Sopenharmony_ci pll2_divint = 0x1c; 84562306a36Sopenharmony_ci pll2_divfrac = 0xa3d2; 84662306a36Sopenharmony_ci refdiv = 1; 84762306a36Sopenharmony_ci } else { 84862306a36Sopenharmony_ci pll2_divint = 0x54; 84962306a36Sopenharmony_ci pll2_divfrac = 0x1eb85; 85062306a36Sopenharmony_ci refdiv = 3; 85162306a36Sopenharmony_ci } 85262306a36Sopenharmony_ci } else { 85362306a36Sopenharmony_ci if (AR_SREV_9340(ah)) { 85462306a36Sopenharmony_ci pll2_divint = 88; 85562306a36Sopenharmony_ci pll2_divfrac = 0; 85662306a36Sopenharmony_ci refdiv = 5; 85762306a36Sopenharmony_ci } else { 85862306a36Sopenharmony_ci pll2_divint = 0x11; 85962306a36Sopenharmony_ci pll2_divfrac = (AR_SREV_9531(ah) || 86062306a36Sopenharmony_ci AR_SREV_9561(ah)) ? 86162306a36Sopenharmony_ci 0x26665 : 0x26666; 86262306a36Sopenharmony_ci refdiv = 1; 86362306a36Sopenharmony_ci } 86462306a36Sopenharmony_ci } 86562306a36Sopenharmony_ci 86662306a36Sopenharmony_ci regval = REG_READ(ah, AR_PHY_PLL_MODE); 86762306a36Sopenharmony_ci if (AR_SREV_9531(ah) || AR_SREV_9561(ah)) 86862306a36Sopenharmony_ci regval |= (0x1 << 22); 86962306a36Sopenharmony_ci else 87062306a36Sopenharmony_ci regval |= (0x1 << 16); 87162306a36Sopenharmony_ci REG_WRITE(ah, AR_PHY_PLL_MODE, regval); 87262306a36Sopenharmony_ci udelay(100); 87362306a36Sopenharmony_ci 87462306a36Sopenharmony_ci REG_WRITE(ah, AR_PHY_PLL_CONTROL, (refdiv << 27) | 87562306a36Sopenharmony_ci (pll2_divint << 18) | pll2_divfrac); 87662306a36Sopenharmony_ci udelay(100); 87762306a36Sopenharmony_ci 87862306a36Sopenharmony_ci regval = REG_READ(ah, AR_PHY_PLL_MODE); 87962306a36Sopenharmony_ci if (AR_SREV_9340(ah)) 88062306a36Sopenharmony_ci regval = (regval & 0x80071fff) | 88162306a36Sopenharmony_ci (0x1 << 30) | 88262306a36Sopenharmony_ci (0x1 << 13) | 88362306a36Sopenharmony_ci (0x4 << 26) | 88462306a36Sopenharmony_ci (0x18 << 19); 88562306a36Sopenharmony_ci else if (AR_SREV_9531(ah) || AR_SREV_9561(ah)) { 88662306a36Sopenharmony_ci regval = (regval & 0x01c00fff) | 88762306a36Sopenharmony_ci (0x1 << 31) | 88862306a36Sopenharmony_ci (0x2 << 29) | 88962306a36Sopenharmony_ci (0xa << 25) | 89062306a36Sopenharmony_ci (0x1 << 19); 89162306a36Sopenharmony_ci 89262306a36Sopenharmony_ci if (AR_SREV_9531(ah)) 89362306a36Sopenharmony_ci regval |= (0x6 << 12); 89462306a36Sopenharmony_ci } else 89562306a36Sopenharmony_ci regval = (regval & 0x80071fff) | 89662306a36Sopenharmony_ci (0x3 << 30) | 89762306a36Sopenharmony_ci (0x1 << 13) | 89862306a36Sopenharmony_ci (0x4 << 26) | 89962306a36Sopenharmony_ci (0x60 << 19); 90062306a36Sopenharmony_ci REG_WRITE(ah, AR_PHY_PLL_MODE, regval); 90162306a36Sopenharmony_ci 90262306a36Sopenharmony_ci if (AR_SREV_9531(ah) || AR_SREV_9561(ah)) 90362306a36Sopenharmony_ci REG_WRITE(ah, AR_PHY_PLL_MODE, 90462306a36Sopenharmony_ci REG_READ(ah, AR_PHY_PLL_MODE) & 0xffbfffff); 90562306a36Sopenharmony_ci else 90662306a36Sopenharmony_ci REG_WRITE(ah, AR_PHY_PLL_MODE, 90762306a36Sopenharmony_ci REG_READ(ah, AR_PHY_PLL_MODE) & 0xfffeffff); 90862306a36Sopenharmony_ci 90962306a36Sopenharmony_ci udelay(1000); 91062306a36Sopenharmony_ci } 91162306a36Sopenharmony_ci 91262306a36Sopenharmony_ci if (AR_SREV_9565(ah)) 91362306a36Sopenharmony_ci pll |= 0x40000; 91462306a36Sopenharmony_ci REG_WRITE(ah, AR_RTC_PLL_CONTROL(ah), pll); 91562306a36Sopenharmony_ci 91662306a36Sopenharmony_ci if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah) || 91762306a36Sopenharmony_ci AR_SREV_9550(ah)) 91862306a36Sopenharmony_ci udelay(1000); 91962306a36Sopenharmony_ci 92062306a36Sopenharmony_ci /* Switch the core clock for ar9271 to 117Mhz */ 92162306a36Sopenharmony_ci if (AR_SREV_9271(ah)) { 92262306a36Sopenharmony_ci udelay(500); 92362306a36Sopenharmony_ci REG_WRITE(ah, 0x50040, 0x304); 92462306a36Sopenharmony_ci } 92562306a36Sopenharmony_ci 92662306a36Sopenharmony_ci udelay(RTC_PLL_SETTLE_DELAY); 92762306a36Sopenharmony_ci 92862306a36Sopenharmony_ci REG_WRITE(ah, AR_RTC_SLEEP_CLK(ah), AR_RTC_FORCE_DERIVED_CLK); 92962306a36Sopenharmony_ci} 93062306a36Sopenharmony_ci 93162306a36Sopenharmony_cistatic void ath9k_hw_init_interrupt_masks(struct ath_hw *ah, 93262306a36Sopenharmony_ci enum nl80211_iftype opmode) 93362306a36Sopenharmony_ci{ 93462306a36Sopenharmony_ci u32 sync_default = AR_INTR_SYNC_DEFAULT; 93562306a36Sopenharmony_ci u32 imr_reg = AR_IMR_TXERR | 93662306a36Sopenharmony_ci AR_IMR_TXURN | 93762306a36Sopenharmony_ci AR_IMR_RXERR | 93862306a36Sopenharmony_ci AR_IMR_RXORN | 93962306a36Sopenharmony_ci AR_IMR_BCNMISC; 94062306a36Sopenharmony_ci u32 msi_cfg = 0; 94162306a36Sopenharmony_ci 94262306a36Sopenharmony_ci if (AR_SREV_9340(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah) || 94362306a36Sopenharmony_ci AR_SREV_9561(ah)) 94462306a36Sopenharmony_ci sync_default &= ~AR_INTR_SYNC_HOST1_FATAL; 94562306a36Sopenharmony_ci 94662306a36Sopenharmony_ci if (AR_SREV_9300_20_OR_LATER(ah)) { 94762306a36Sopenharmony_ci imr_reg |= AR_IMR_RXOK_HP; 94862306a36Sopenharmony_ci if (ah->config.rx_intr_mitigation) { 94962306a36Sopenharmony_ci imr_reg |= AR_IMR_RXINTM | AR_IMR_RXMINTR; 95062306a36Sopenharmony_ci msi_cfg |= AR_INTCFG_MSI_RXINTM | AR_INTCFG_MSI_RXMINTR; 95162306a36Sopenharmony_ci } else { 95262306a36Sopenharmony_ci imr_reg |= AR_IMR_RXOK_LP; 95362306a36Sopenharmony_ci msi_cfg |= AR_INTCFG_MSI_RXOK; 95462306a36Sopenharmony_ci } 95562306a36Sopenharmony_ci } else { 95662306a36Sopenharmony_ci if (ah->config.rx_intr_mitigation) { 95762306a36Sopenharmony_ci imr_reg |= AR_IMR_RXINTM | AR_IMR_RXMINTR; 95862306a36Sopenharmony_ci msi_cfg |= AR_INTCFG_MSI_RXINTM | AR_INTCFG_MSI_RXMINTR; 95962306a36Sopenharmony_ci } else { 96062306a36Sopenharmony_ci imr_reg |= AR_IMR_RXOK; 96162306a36Sopenharmony_ci msi_cfg |= AR_INTCFG_MSI_RXOK; 96262306a36Sopenharmony_ci } 96362306a36Sopenharmony_ci } 96462306a36Sopenharmony_ci 96562306a36Sopenharmony_ci if (ah->config.tx_intr_mitigation) { 96662306a36Sopenharmony_ci imr_reg |= AR_IMR_TXINTM | AR_IMR_TXMINTR; 96762306a36Sopenharmony_ci msi_cfg |= AR_INTCFG_MSI_TXINTM | AR_INTCFG_MSI_TXMINTR; 96862306a36Sopenharmony_ci } else { 96962306a36Sopenharmony_ci imr_reg |= AR_IMR_TXOK; 97062306a36Sopenharmony_ci msi_cfg |= AR_INTCFG_MSI_TXOK; 97162306a36Sopenharmony_ci } 97262306a36Sopenharmony_ci 97362306a36Sopenharmony_ci ENABLE_REGWRITE_BUFFER(ah); 97462306a36Sopenharmony_ci 97562306a36Sopenharmony_ci REG_WRITE(ah, AR_IMR, imr_reg); 97662306a36Sopenharmony_ci ah->imrs2_reg |= AR_IMR_S2_GTT; 97762306a36Sopenharmony_ci REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg); 97862306a36Sopenharmony_ci 97962306a36Sopenharmony_ci if (ah->msi_enabled) { 98062306a36Sopenharmony_ci ah->msi_reg = REG_READ(ah, AR_PCIE_MSI(ah)); 98162306a36Sopenharmony_ci ah->msi_reg |= AR_PCIE_MSI_HW_DBI_WR_EN; 98262306a36Sopenharmony_ci ah->msi_reg &= AR_PCIE_MSI_HW_INT_PENDING_ADDR_MSI_64; 98362306a36Sopenharmony_ci REG_WRITE(ah, AR_INTCFG, msi_cfg); 98462306a36Sopenharmony_ci ath_dbg(ath9k_hw_common(ah), ANY, 98562306a36Sopenharmony_ci "value of AR_INTCFG=0x%X, msi_cfg=0x%X\n", 98662306a36Sopenharmony_ci REG_READ(ah, AR_INTCFG), msi_cfg); 98762306a36Sopenharmony_ci } 98862306a36Sopenharmony_ci 98962306a36Sopenharmony_ci if (!AR_SREV_9100(ah)) { 99062306a36Sopenharmony_ci REG_WRITE(ah, AR_INTR_SYNC_CAUSE(ah), 0xFFFFFFFF); 99162306a36Sopenharmony_ci REG_WRITE(ah, AR_INTR_SYNC_ENABLE(ah), sync_default); 99262306a36Sopenharmony_ci REG_WRITE(ah, AR_INTR_SYNC_MASK(ah), 0); 99362306a36Sopenharmony_ci } 99462306a36Sopenharmony_ci 99562306a36Sopenharmony_ci REGWRITE_BUFFER_FLUSH(ah); 99662306a36Sopenharmony_ci 99762306a36Sopenharmony_ci if (AR_SREV_9300_20_OR_LATER(ah)) { 99862306a36Sopenharmony_ci REG_WRITE(ah, AR_INTR_PRIO_ASYNC_ENABLE(ah), 0); 99962306a36Sopenharmony_ci REG_WRITE(ah, AR_INTR_PRIO_ASYNC_MASK(ah), 0); 100062306a36Sopenharmony_ci REG_WRITE(ah, AR_INTR_PRIO_SYNC_ENABLE(ah), 0); 100162306a36Sopenharmony_ci REG_WRITE(ah, AR_INTR_PRIO_SYNC_MASK(ah), 0); 100262306a36Sopenharmony_ci } 100362306a36Sopenharmony_ci} 100462306a36Sopenharmony_ci 100562306a36Sopenharmony_cistatic void ath9k_hw_set_sifs_time(struct ath_hw *ah, u32 us) 100662306a36Sopenharmony_ci{ 100762306a36Sopenharmony_ci u32 val = ath9k_hw_mac_to_clks(ah, us - 2); 100862306a36Sopenharmony_ci val = min(val, (u32) 0xFFFF); 100962306a36Sopenharmony_ci REG_WRITE(ah, AR_D_GBL_IFS_SIFS, val); 101062306a36Sopenharmony_ci} 101162306a36Sopenharmony_ci 101262306a36Sopenharmony_civoid ath9k_hw_setslottime(struct ath_hw *ah, u32 us) 101362306a36Sopenharmony_ci{ 101462306a36Sopenharmony_ci u32 val = ath9k_hw_mac_to_clks(ah, us); 101562306a36Sopenharmony_ci val = min(val, (u32) 0xFFFF); 101662306a36Sopenharmony_ci REG_WRITE(ah, AR_D_GBL_IFS_SLOT, val); 101762306a36Sopenharmony_ci} 101862306a36Sopenharmony_ci 101962306a36Sopenharmony_civoid ath9k_hw_set_ack_timeout(struct ath_hw *ah, u32 us) 102062306a36Sopenharmony_ci{ 102162306a36Sopenharmony_ci u32 val = ath9k_hw_mac_to_clks(ah, us); 102262306a36Sopenharmony_ci val = min(val, (u32) MS(0xFFFFFFFF, AR_TIME_OUT_ACK)); 102362306a36Sopenharmony_ci REG_RMW_FIELD(ah, AR_TIME_OUT, AR_TIME_OUT_ACK, val); 102462306a36Sopenharmony_ci} 102562306a36Sopenharmony_ci 102662306a36Sopenharmony_civoid ath9k_hw_set_cts_timeout(struct ath_hw *ah, u32 us) 102762306a36Sopenharmony_ci{ 102862306a36Sopenharmony_ci u32 val = ath9k_hw_mac_to_clks(ah, us); 102962306a36Sopenharmony_ci val = min(val, (u32) MS(0xFFFFFFFF, AR_TIME_OUT_CTS)); 103062306a36Sopenharmony_ci REG_RMW_FIELD(ah, AR_TIME_OUT, AR_TIME_OUT_CTS, val); 103162306a36Sopenharmony_ci} 103262306a36Sopenharmony_ci 103362306a36Sopenharmony_cistatic bool ath9k_hw_set_global_txtimeout(struct ath_hw *ah, u32 tu) 103462306a36Sopenharmony_ci{ 103562306a36Sopenharmony_ci if (tu > 0xFFFF) { 103662306a36Sopenharmony_ci ath_dbg(ath9k_hw_common(ah), XMIT, "bad global tx timeout %u\n", 103762306a36Sopenharmony_ci tu); 103862306a36Sopenharmony_ci ah->globaltxtimeout = (u32) -1; 103962306a36Sopenharmony_ci return false; 104062306a36Sopenharmony_ci } else { 104162306a36Sopenharmony_ci REG_RMW_FIELD(ah, AR_GTXTO, AR_GTXTO_TIMEOUT_LIMIT, tu); 104262306a36Sopenharmony_ci ah->globaltxtimeout = tu; 104362306a36Sopenharmony_ci return true; 104462306a36Sopenharmony_ci } 104562306a36Sopenharmony_ci} 104662306a36Sopenharmony_ci 104762306a36Sopenharmony_civoid ath9k_hw_init_global_settings(struct ath_hw *ah) 104862306a36Sopenharmony_ci{ 104962306a36Sopenharmony_ci struct ath_common *common = ath9k_hw_common(ah); 105062306a36Sopenharmony_ci const struct ath9k_channel *chan = ah->curchan; 105162306a36Sopenharmony_ci int acktimeout, ctstimeout, ack_offset = 0; 105262306a36Sopenharmony_ci int slottime; 105362306a36Sopenharmony_ci int sifstime; 105462306a36Sopenharmony_ci int rx_lat = 0, tx_lat = 0, eifs = 0, ack_shift = 0; 105562306a36Sopenharmony_ci u32 reg; 105662306a36Sopenharmony_ci 105762306a36Sopenharmony_ci ath_dbg(ath9k_hw_common(ah), RESET, "ah->misc_mode 0x%x\n", 105862306a36Sopenharmony_ci ah->misc_mode); 105962306a36Sopenharmony_ci 106062306a36Sopenharmony_ci if (!chan) 106162306a36Sopenharmony_ci return; 106262306a36Sopenharmony_ci 106362306a36Sopenharmony_ci if (ah->misc_mode != 0) 106462306a36Sopenharmony_ci REG_SET_BIT(ah, AR_PCU_MISC, ah->misc_mode); 106562306a36Sopenharmony_ci 106662306a36Sopenharmony_ci if (IS_CHAN_A_FAST_CLOCK(ah, chan)) 106762306a36Sopenharmony_ci rx_lat = 41; 106862306a36Sopenharmony_ci else 106962306a36Sopenharmony_ci rx_lat = 37; 107062306a36Sopenharmony_ci tx_lat = 54; 107162306a36Sopenharmony_ci 107262306a36Sopenharmony_ci if (IS_CHAN_5GHZ(chan)) 107362306a36Sopenharmony_ci sifstime = 16; 107462306a36Sopenharmony_ci else 107562306a36Sopenharmony_ci sifstime = 10; 107662306a36Sopenharmony_ci 107762306a36Sopenharmony_ci if (IS_CHAN_HALF_RATE(chan)) { 107862306a36Sopenharmony_ci eifs = 175; 107962306a36Sopenharmony_ci rx_lat *= 2; 108062306a36Sopenharmony_ci tx_lat *= 2; 108162306a36Sopenharmony_ci if (IS_CHAN_A_FAST_CLOCK(ah, chan)) 108262306a36Sopenharmony_ci tx_lat += 11; 108362306a36Sopenharmony_ci 108462306a36Sopenharmony_ci sifstime = 32; 108562306a36Sopenharmony_ci ack_offset = 16; 108662306a36Sopenharmony_ci ack_shift = 3; 108762306a36Sopenharmony_ci slottime = 13; 108862306a36Sopenharmony_ci } else if (IS_CHAN_QUARTER_RATE(chan)) { 108962306a36Sopenharmony_ci eifs = 340; 109062306a36Sopenharmony_ci rx_lat = (rx_lat * 4) - 1; 109162306a36Sopenharmony_ci tx_lat *= 4; 109262306a36Sopenharmony_ci if (IS_CHAN_A_FAST_CLOCK(ah, chan)) 109362306a36Sopenharmony_ci tx_lat += 22; 109462306a36Sopenharmony_ci 109562306a36Sopenharmony_ci sifstime = 64; 109662306a36Sopenharmony_ci ack_offset = 32; 109762306a36Sopenharmony_ci ack_shift = 1; 109862306a36Sopenharmony_ci slottime = 21; 109962306a36Sopenharmony_ci } else { 110062306a36Sopenharmony_ci if (AR_SREV_9287(ah) && AR_SREV_9287_13_OR_LATER(ah)) { 110162306a36Sopenharmony_ci eifs = AR_D_GBL_IFS_EIFS_ASYNC_FIFO; 110262306a36Sopenharmony_ci reg = AR_USEC_ASYNC_FIFO; 110362306a36Sopenharmony_ci } else { 110462306a36Sopenharmony_ci eifs = REG_READ(ah, AR_D_GBL_IFS_EIFS)/ 110562306a36Sopenharmony_ci common->clockrate; 110662306a36Sopenharmony_ci reg = REG_READ(ah, AR_USEC); 110762306a36Sopenharmony_ci } 110862306a36Sopenharmony_ci rx_lat = MS(reg, AR_USEC_RX_LAT); 110962306a36Sopenharmony_ci tx_lat = MS(reg, AR_USEC_TX_LAT); 111062306a36Sopenharmony_ci 111162306a36Sopenharmony_ci slottime = ah->slottime; 111262306a36Sopenharmony_ci } 111362306a36Sopenharmony_ci 111462306a36Sopenharmony_ci /* As defined by IEEE 802.11-2007 17.3.8.6 */ 111562306a36Sopenharmony_ci slottime += 3 * ah->coverage_class; 111662306a36Sopenharmony_ci acktimeout = slottime + sifstime + ack_offset; 111762306a36Sopenharmony_ci ctstimeout = acktimeout; 111862306a36Sopenharmony_ci 111962306a36Sopenharmony_ci /* 112062306a36Sopenharmony_ci * Workaround for early ACK timeouts, add an offset to match the 112162306a36Sopenharmony_ci * initval's 64us ack timeout value. Use 48us for the CTS timeout. 112262306a36Sopenharmony_ci * This was initially only meant to work around an issue with delayed 112362306a36Sopenharmony_ci * BA frames in some implementations, but it has been found to fix ACK 112462306a36Sopenharmony_ci * timeout issues in other cases as well. 112562306a36Sopenharmony_ci */ 112662306a36Sopenharmony_ci if (IS_CHAN_2GHZ(chan) && 112762306a36Sopenharmony_ci !IS_CHAN_HALF_RATE(chan) && !IS_CHAN_QUARTER_RATE(chan)) { 112862306a36Sopenharmony_ci acktimeout += 64 - sifstime - ah->slottime; 112962306a36Sopenharmony_ci ctstimeout += 48 - sifstime - ah->slottime; 113062306a36Sopenharmony_ci } 113162306a36Sopenharmony_ci 113262306a36Sopenharmony_ci if (ah->dynack.enabled) { 113362306a36Sopenharmony_ci acktimeout = ah->dynack.ackto; 113462306a36Sopenharmony_ci ctstimeout = acktimeout; 113562306a36Sopenharmony_ci slottime = (acktimeout - 3) / 2; 113662306a36Sopenharmony_ci } else { 113762306a36Sopenharmony_ci ah->dynack.ackto = acktimeout; 113862306a36Sopenharmony_ci } 113962306a36Sopenharmony_ci 114062306a36Sopenharmony_ci ath9k_hw_set_sifs_time(ah, sifstime); 114162306a36Sopenharmony_ci ath9k_hw_setslottime(ah, slottime); 114262306a36Sopenharmony_ci ath9k_hw_set_ack_timeout(ah, acktimeout); 114362306a36Sopenharmony_ci ath9k_hw_set_cts_timeout(ah, ctstimeout); 114462306a36Sopenharmony_ci if (ah->globaltxtimeout != (u32) -1) 114562306a36Sopenharmony_ci ath9k_hw_set_global_txtimeout(ah, ah->globaltxtimeout); 114662306a36Sopenharmony_ci 114762306a36Sopenharmony_ci REG_WRITE(ah, AR_D_GBL_IFS_EIFS, ath9k_hw_mac_to_clks(ah, eifs)); 114862306a36Sopenharmony_ci REG_RMW(ah, AR_USEC, 114962306a36Sopenharmony_ci (common->clockrate - 1) | 115062306a36Sopenharmony_ci SM(rx_lat, AR_USEC_RX_LAT) | 115162306a36Sopenharmony_ci SM(tx_lat, AR_USEC_TX_LAT), 115262306a36Sopenharmony_ci AR_USEC_TX_LAT | AR_USEC_RX_LAT | AR_USEC_USEC); 115362306a36Sopenharmony_ci 115462306a36Sopenharmony_ci if (IS_CHAN_HALF_RATE(chan) || IS_CHAN_QUARTER_RATE(chan)) 115562306a36Sopenharmony_ci REG_RMW(ah, AR_TXSIFS, 115662306a36Sopenharmony_ci sifstime | SM(ack_shift, AR_TXSIFS_ACK_SHIFT), 115762306a36Sopenharmony_ci (AR_TXSIFS_TIME | AR_TXSIFS_ACK_SHIFT)); 115862306a36Sopenharmony_ci} 115962306a36Sopenharmony_ciEXPORT_SYMBOL(ath9k_hw_init_global_settings); 116062306a36Sopenharmony_ci 116162306a36Sopenharmony_civoid ath9k_hw_deinit(struct ath_hw *ah) 116262306a36Sopenharmony_ci{ 116362306a36Sopenharmony_ci struct ath_common *common = ath9k_hw_common(ah); 116462306a36Sopenharmony_ci 116562306a36Sopenharmony_ci if (common->state < ATH_HW_INITIALIZED) 116662306a36Sopenharmony_ci return; 116762306a36Sopenharmony_ci 116862306a36Sopenharmony_ci ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP); 116962306a36Sopenharmony_ci} 117062306a36Sopenharmony_ciEXPORT_SYMBOL(ath9k_hw_deinit); 117162306a36Sopenharmony_ci 117262306a36Sopenharmony_ci/*******/ 117362306a36Sopenharmony_ci/* INI */ 117462306a36Sopenharmony_ci/*******/ 117562306a36Sopenharmony_ci 117662306a36Sopenharmony_ciu32 ath9k_regd_get_ctl(struct ath_regulatory *reg, struct ath9k_channel *chan) 117762306a36Sopenharmony_ci{ 117862306a36Sopenharmony_ci u32 ctl = ath_regd_get_band_ctl(reg, chan->chan->band); 117962306a36Sopenharmony_ci 118062306a36Sopenharmony_ci if (IS_CHAN_2GHZ(chan)) 118162306a36Sopenharmony_ci ctl |= CTL_11G; 118262306a36Sopenharmony_ci else 118362306a36Sopenharmony_ci ctl |= CTL_11A; 118462306a36Sopenharmony_ci 118562306a36Sopenharmony_ci return ctl; 118662306a36Sopenharmony_ci} 118762306a36Sopenharmony_ci 118862306a36Sopenharmony_ci/****************************************/ 118962306a36Sopenharmony_ci/* Reset and Channel Switching Routines */ 119062306a36Sopenharmony_ci/****************************************/ 119162306a36Sopenharmony_ci 119262306a36Sopenharmony_cistatic inline void ath9k_hw_set_dma(struct ath_hw *ah) 119362306a36Sopenharmony_ci{ 119462306a36Sopenharmony_ci struct ath_common *common = ath9k_hw_common(ah); 119562306a36Sopenharmony_ci int txbuf_size; 119662306a36Sopenharmony_ci 119762306a36Sopenharmony_ci ENABLE_REGWRITE_BUFFER(ah); 119862306a36Sopenharmony_ci 119962306a36Sopenharmony_ci /* 120062306a36Sopenharmony_ci * set AHB_MODE not to do cacheline prefetches 120162306a36Sopenharmony_ci */ 120262306a36Sopenharmony_ci if (!AR_SREV_9300_20_OR_LATER(ah)) 120362306a36Sopenharmony_ci REG_SET_BIT(ah, AR_AHB_MODE, AR_AHB_PREFETCH_RD_EN); 120462306a36Sopenharmony_ci 120562306a36Sopenharmony_ci /* 120662306a36Sopenharmony_ci * let mac dma reads be in 128 byte chunks 120762306a36Sopenharmony_ci */ 120862306a36Sopenharmony_ci REG_RMW(ah, AR_TXCFG, AR_TXCFG_DMASZ_128B, AR_TXCFG_DMASZ_MASK); 120962306a36Sopenharmony_ci 121062306a36Sopenharmony_ci REGWRITE_BUFFER_FLUSH(ah); 121162306a36Sopenharmony_ci 121262306a36Sopenharmony_ci /* 121362306a36Sopenharmony_ci * Restore TX Trigger Level to its pre-reset value. 121462306a36Sopenharmony_ci * The initial value depends on whether aggregation is enabled, and is 121562306a36Sopenharmony_ci * adjusted whenever underruns are detected. 121662306a36Sopenharmony_ci */ 121762306a36Sopenharmony_ci if (!AR_SREV_9300_20_OR_LATER(ah)) 121862306a36Sopenharmony_ci REG_RMW_FIELD(ah, AR_TXCFG, AR_FTRIG, ah->tx_trig_level); 121962306a36Sopenharmony_ci 122062306a36Sopenharmony_ci ENABLE_REGWRITE_BUFFER(ah); 122162306a36Sopenharmony_ci 122262306a36Sopenharmony_ci /* 122362306a36Sopenharmony_ci * let mac dma writes be in 128 byte chunks 122462306a36Sopenharmony_ci */ 122562306a36Sopenharmony_ci REG_RMW(ah, AR_RXCFG, AR_RXCFG_DMASZ_128B, AR_RXCFG_DMASZ_MASK); 122662306a36Sopenharmony_ci 122762306a36Sopenharmony_ci /* 122862306a36Sopenharmony_ci * Setup receive FIFO threshold to hold off TX activities 122962306a36Sopenharmony_ci */ 123062306a36Sopenharmony_ci REG_WRITE(ah, AR_RXFIFO_CFG, 0x200); 123162306a36Sopenharmony_ci 123262306a36Sopenharmony_ci if (AR_SREV_9300_20_OR_LATER(ah)) { 123362306a36Sopenharmony_ci REG_RMW_FIELD(ah, AR_RXBP_THRESH, AR_RXBP_THRESH_HP, 0x1); 123462306a36Sopenharmony_ci REG_RMW_FIELD(ah, AR_RXBP_THRESH, AR_RXBP_THRESH_LP, 0x1); 123562306a36Sopenharmony_ci 123662306a36Sopenharmony_ci ath9k_hw_set_rx_bufsize(ah, common->rx_bufsize - 123762306a36Sopenharmony_ci ah->caps.rx_status_len); 123862306a36Sopenharmony_ci } 123962306a36Sopenharmony_ci 124062306a36Sopenharmony_ci /* 124162306a36Sopenharmony_ci * reduce the number of usable entries in PCU TXBUF to avoid 124262306a36Sopenharmony_ci * wrap around issues. 124362306a36Sopenharmony_ci */ 124462306a36Sopenharmony_ci if (AR_SREV_9285(ah)) { 124562306a36Sopenharmony_ci /* For AR9285 the number of Fifos are reduced to half. 124662306a36Sopenharmony_ci * So set the usable tx buf size also to half to 124762306a36Sopenharmony_ci * avoid data/delimiter underruns 124862306a36Sopenharmony_ci */ 124962306a36Sopenharmony_ci txbuf_size = AR_9285_PCU_TXBUF_CTRL_USABLE_SIZE; 125062306a36Sopenharmony_ci } else if (AR_SREV_9340_13_OR_LATER(ah)) { 125162306a36Sopenharmony_ci /* Uses fewer entries for AR934x v1.3+ to prevent rx overruns */ 125262306a36Sopenharmony_ci txbuf_size = AR_9340_PCU_TXBUF_CTRL_USABLE_SIZE; 125362306a36Sopenharmony_ci } else { 125462306a36Sopenharmony_ci txbuf_size = AR_PCU_TXBUF_CTRL_USABLE_SIZE; 125562306a36Sopenharmony_ci } 125662306a36Sopenharmony_ci 125762306a36Sopenharmony_ci if (!AR_SREV_9271(ah)) 125862306a36Sopenharmony_ci REG_WRITE(ah, AR_PCU_TXBUF_CTRL, txbuf_size); 125962306a36Sopenharmony_ci 126062306a36Sopenharmony_ci REGWRITE_BUFFER_FLUSH(ah); 126162306a36Sopenharmony_ci 126262306a36Sopenharmony_ci if (AR_SREV_9300_20_OR_LATER(ah)) 126362306a36Sopenharmony_ci ath9k_hw_reset_txstatus_ring(ah); 126462306a36Sopenharmony_ci} 126562306a36Sopenharmony_ci 126662306a36Sopenharmony_cistatic void ath9k_hw_set_operating_mode(struct ath_hw *ah, int opmode) 126762306a36Sopenharmony_ci{ 126862306a36Sopenharmony_ci u32 mask = AR_STA_ID1_STA_AP | AR_STA_ID1_ADHOC; 126962306a36Sopenharmony_ci u32 set = AR_STA_ID1_KSRCH_MODE; 127062306a36Sopenharmony_ci 127162306a36Sopenharmony_ci ENABLE_REG_RMW_BUFFER(ah); 127262306a36Sopenharmony_ci switch (opmode) { 127362306a36Sopenharmony_ci case NL80211_IFTYPE_ADHOC: 127462306a36Sopenharmony_ci if (!AR_SREV_9340_13(ah)) { 127562306a36Sopenharmony_ci set |= AR_STA_ID1_ADHOC; 127662306a36Sopenharmony_ci REG_SET_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION); 127762306a36Sopenharmony_ci break; 127862306a36Sopenharmony_ci } 127962306a36Sopenharmony_ci fallthrough; 128062306a36Sopenharmony_ci case NL80211_IFTYPE_OCB: 128162306a36Sopenharmony_ci case NL80211_IFTYPE_MESH_POINT: 128262306a36Sopenharmony_ci case NL80211_IFTYPE_AP: 128362306a36Sopenharmony_ci set |= AR_STA_ID1_STA_AP; 128462306a36Sopenharmony_ci fallthrough; 128562306a36Sopenharmony_ci case NL80211_IFTYPE_STATION: 128662306a36Sopenharmony_ci REG_CLR_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION); 128762306a36Sopenharmony_ci break; 128862306a36Sopenharmony_ci default: 128962306a36Sopenharmony_ci if (!ah->is_monitoring) 129062306a36Sopenharmony_ci set = 0; 129162306a36Sopenharmony_ci break; 129262306a36Sopenharmony_ci } 129362306a36Sopenharmony_ci REG_RMW(ah, AR_STA_ID1, set, mask); 129462306a36Sopenharmony_ci REG_RMW_BUFFER_FLUSH(ah); 129562306a36Sopenharmony_ci} 129662306a36Sopenharmony_ci 129762306a36Sopenharmony_civoid ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, u32 coef_scaled, 129862306a36Sopenharmony_ci u32 *coef_mantissa, u32 *coef_exponent) 129962306a36Sopenharmony_ci{ 130062306a36Sopenharmony_ci u32 coef_exp, coef_man; 130162306a36Sopenharmony_ci 130262306a36Sopenharmony_ci for (coef_exp = 31; coef_exp > 0; coef_exp--) 130362306a36Sopenharmony_ci if ((coef_scaled >> coef_exp) & 0x1) 130462306a36Sopenharmony_ci break; 130562306a36Sopenharmony_ci 130662306a36Sopenharmony_ci coef_exp = 14 - (coef_exp - COEF_SCALE_S); 130762306a36Sopenharmony_ci 130862306a36Sopenharmony_ci coef_man = coef_scaled + (1 << (COEF_SCALE_S - coef_exp - 1)); 130962306a36Sopenharmony_ci 131062306a36Sopenharmony_ci *coef_mantissa = coef_man >> (COEF_SCALE_S - coef_exp); 131162306a36Sopenharmony_ci *coef_exponent = coef_exp - 16; 131262306a36Sopenharmony_ci} 131362306a36Sopenharmony_ci 131462306a36Sopenharmony_ci/* AR9330 WAR: 131562306a36Sopenharmony_ci * call external reset function to reset WMAC if: 131662306a36Sopenharmony_ci * - doing a cold reset 131762306a36Sopenharmony_ci * - we have pending frames in the TX queues. 131862306a36Sopenharmony_ci */ 131962306a36Sopenharmony_cistatic bool ath9k_hw_ar9330_reset_war(struct ath_hw *ah, int type) 132062306a36Sopenharmony_ci{ 132162306a36Sopenharmony_ci int i, npend = 0; 132262306a36Sopenharmony_ci 132362306a36Sopenharmony_ci for (i = 0; i < AR_NUM_QCU; i++) { 132462306a36Sopenharmony_ci npend = ath9k_hw_numtxpending(ah, i); 132562306a36Sopenharmony_ci if (npend) 132662306a36Sopenharmony_ci break; 132762306a36Sopenharmony_ci } 132862306a36Sopenharmony_ci 132962306a36Sopenharmony_ci if (ah->external_reset && 133062306a36Sopenharmony_ci (npend || type == ATH9K_RESET_COLD)) { 133162306a36Sopenharmony_ci int reset_err = 0; 133262306a36Sopenharmony_ci 133362306a36Sopenharmony_ci ath_dbg(ath9k_hw_common(ah), RESET, 133462306a36Sopenharmony_ci "reset MAC via external reset\n"); 133562306a36Sopenharmony_ci 133662306a36Sopenharmony_ci reset_err = ah->external_reset(); 133762306a36Sopenharmony_ci if (reset_err) { 133862306a36Sopenharmony_ci ath_err(ath9k_hw_common(ah), 133962306a36Sopenharmony_ci "External reset failed, err=%d\n", 134062306a36Sopenharmony_ci reset_err); 134162306a36Sopenharmony_ci return false; 134262306a36Sopenharmony_ci } 134362306a36Sopenharmony_ci 134462306a36Sopenharmony_ci REG_WRITE(ah, AR_RTC_RESET(ah), 1); 134562306a36Sopenharmony_ci } 134662306a36Sopenharmony_ci 134762306a36Sopenharmony_ci return true; 134862306a36Sopenharmony_ci} 134962306a36Sopenharmony_ci 135062306a36Sopenharmony_cistatic bool ath9k_hw_set_reset(struct ath_hw *ah, int type) 135162306a36Sopenharmony_ci{ 135262306a36Sopenharmony_ci u32 rst_flags; 135362306a36Sopenharmony_ci u32 tmpReg; 135462306a36Sopenharmony_ci 135562306a36Sopenharmony_ci if (AR_SREV_9100(ah)) { 135662306a36Sopenharmony_ci REG_RMW_FIELD(ah, AR_RTC_DERIVED_CLK(ah), 135762306a36Sopenharmony_ci AR_RTC_DERIVED_CLK_PERIOD, 1); 135862306a36Sopenharmony_ci (void)REG_READ(ah, AR_RTC_DERIVED_CLK(ah)); 135962306a36Sopenharmony_ci } 136062306a36Sopenharmony_ci 136162306a36Sopenharmony_ci ENABLE_REGWRITE_BUFFER(ah); 136262306a36Sopenharmony_ci 136362306a36Sopenharmony_ci if (AR_SREV_9300_20_OR_LATER(ah)) { 136462306a36Sopenharmony_ci REG_WRITE(ah, AR_WA(ah), ah->WARegVal); 136562306a36Sopenharmony_ci udelay(10); 136662306a36Sopenharmony_ci } 136762306a36Sopenharmony_ci 136862306a36Sopenharmony_ci REG_WRITE(ah, AR_RTC_FORCE_WAKE(ah), AR_RTC_FORCE_WAKE_EN | 136962306a36Sopenharmony_ci AR_RTC_FORCE_WAKE_ON_INT); 137062306a36Sopenharmony_ci 137162306a36Sopenharmony_ci if (AR_SREV_9100(ah)) { 137262306a36Sopenharmony_ci rst_flags = AR_RTC_RC_MAC_WARM | AR_RTC_RC_MAC_COLD | 137362306a36Sopenharmony_ci AR_RTC_RC_COLD_RESET | AR_RTC_RC_WARM_RESET; 137462306a36Sopenharmony_ci } else { 137562306a36Sopenharmony_ci tmpReg = REG_READ(ah, AR_INTR_SYNC_CAUSE(ah)); 137662306a36Sopenharmony_ci if (AR_SREV_9340(ah)) 137762306a36Sopenharmony_ci tmpReg &= AR9340_INTR_SYNC_LOCAL_TIMEOUT; 137862306a36Sopenharmony_ci else 137962306a36Sopenharmony_ci tmpReg &= AR_INTR_SYNC_LOCAL_TIMEOUT | 138062306a36Sopenharmony_ci AR_INTR_SYNC_RADM_CPL_TIMEOUT; 138162306a36Sopenharmony_ci 138262306a36Sopenharmony_ci if (tmpReg) { 138362306a36Sopenharmony_ci u32 val; 138462306a36Sopenharmony_ci REG_WRITE(ah, AR_INTR_SYNC_ENABLE(ah), 0); 138562306a36Sopenharmony_ci 138662306a36Sopenharmony_ci val = AR_RC_HOSTIF; 138762306a36Sopenharmony_ci if (!AR_SREV_9300_20_OR_LATER(ah)) 138862306a36Sopenharmony_ci val |= AR_RC_AHB; 138962306a36Sopenharmony_ci REG_WRITE(ah, AR_RC, val); 139062306a36Sopenharmony_ci 139162306a36Sopenharmony_ci } else if (!AR_SREV_9300_20_OR_LATER(ah)) 139262306a36Sopenharmony_ci REG_WRITE(ah, AR_RC, AR_RC_AHB); 139362306a36Sopenharmony_ci 139462306a36Sopenharmony_ci rst_flags = AR_RTC_RC_MAC_WARM; 139562306a36Sopenharmony_ci if (type == ATH9K_RESET_COLD) 139662306a36Sopenharmony_ci rst_flags |= AR_RTC_RC_MAC_COLD; 139762306a36Sopenharmony_ci } 139862306a36Sopenharmony_ci 139962306a36Sopenharmony_ci if (AR_SREV_9330(ah)) { 140062306a36Sopenharmony_ci if (!ath9k_hw_ar9330_reset_war(ah, type)) 140162306a36Sopenharmony_ci return false; 140262306a36Sopenharmony_ci } 140362306a36Sopenharmony_ci 140462306a36Sopenharmony_ci if (ath9k_hw_mci_is_enabled(ah)) 140562306a36Sopenharmony_ci ar9003_mci_check_gpm_offset(ah); 140662306a36Sopenharmony_ci 140762306a36Sopenharmony_ci /* DMA HALT added to resolve ar9300 and ar9580 bus error during 140862306a36Sopenharmony_ci * RTC_RC reg read 140962306a36Sopenharmony_ci */ 141062306a36Sopenharmony_ci if (AR_SREV_9300(ah) || AR_SREV_9580(ah)) { 141162306a36Sopenharmony_ci REG_SET_BIT(ah, AR_CFG, AR_CFG_HALT_REQ); 141262306a36Sopenharmony_ci ath9k_hw_wait(ah, AR_CFG, AR_CFG_HALT_ACK, AR_CFG_HALT_ACK, 141362306a36Sopenharmony_ci 20 * AH_WAIT_TIMEOUT); 141462306a36Sopenharmony_ci REG_CLR_BIT(ah, AR_CFG, AR_CFG_HALT_REQ); 141562306a36Sopenharmony_ci } 141662306a36Sopenharmony_ci 141762306a36Sopenharmony_ci REG_WRITE(ah, AR_RTC_RC(ah), rst_flags); 141862306a36Sopenharmony_ci 141962306a36Sopenharmony_ci REGWRITE_BUFFER_FLUSH(ah); 142062306a36Sopenharmony_ci 142162306a36Sopenharmony_ci if (AR_SREV_9300_20_OR_LATER(ah)) 142262306a36Sopenharmony_ci udelay(50); 142362306a36Sopenharmony_ci else if (AR_SREV_9100(ah)) 142462306a36Sopenharmony_ci mdelay(10); 142562306a36Sopenharmony_ci else 142662306a36Sopenharmony_ci udelay(100); 142762306a36Sopenharmony_ci 142862306a36Sopenharmony_ci REG_WRITE(ah, AR_RTC_RC(ah), 0); 142962306a36Sopenharmony_ci if (!ath9k_hw_wait(ah, AR_RTC_RC(ah), AR_RTC_RC_M, 0, AH_WAIT_TIMEOUT)) { 143062306a36Sopenharmony_ci ath_dbg(ath9k_hw_common(ah), RESET, "RTC stuck in MAC reset\n"); 143162306a36Sopenharmony_ci return false; 143262306a36Sopenharmony_ci } 143362306a36Sopenharmony_ci 143462306a36Sopenharmony_ci if (!AR_SREV_9100(ah)) 143562306a36Sopenharmony_ci REG_WRITE(ah, AR_RC, 0); 143662306a36Sopenharmony_ci 143762306a36Sopenharmony_ci if (AR_SREV_9100(ah)) 143862306a36Sopenharmony_ci udelay(50); 143962306a36Sopenharmony_ci 144062306a36Sopenharmony_ci return true; 144162306a36Sopenharmony_ci} 144262306a36Sopenharmony_ci 144362306a36Sopenharmony_cistatic bool ath9k_hw_set_reset_power_on(struct ath_hw *ah) 144462306a36Sopenharmony_ci{ 144562306a36Sopenharmony_ci ENABLE_REGWRITE_BUFFER(ah); 144662306a36Sopenharmony_ci 144762306a36Sopenharmony_ci if (AR_SREV_9300_20_OR_LATER(ah)) { 144862306a36Sopenharmony_ci REG_WRITE(ah, AR_WA(ah), ah->WARegVal); 144962306a36Sopenharmony_ci udelay(10); 145062306a36Sopenharmony_ci } 145162306a36Sopenharmony_ci 145262306a36Sopenharmony_ci REG_WRITE(ah, AR_RTC_FORCE_WAKE(ah), AR_RTC_FORCE_WAKE_EN | 145362306a36Sopenharmony_ci AR_RTC_FORCE_WAKE_ON_INT); 145462306a36Sopenharmony_ci 145562306a36Sopenharmony_ci if (!AR_SREV_9100(ah) && !AR_SREV_9300_20_OR_LATER(ah)) 145662306a36Sopenharmony_ci REG_WRITE(ah, AR_RC, AR_RC_AHB); 145762306a36Sopenharmony_ci 145862306a36Sopenharmony_ci REG_WRITE(ah, AR_RTC_RESET(ah), 0); 145962306a36Sopenharmony_ci 146062306a36Sopenharmony_ci REGWRITE_BUFFER_FLUSH(ah); 146162306a36Sopenharmony_ci 146262306a36Sopenharmony_ci udelay(2); 146362306a36Sopenharmony_ci 146462306a36Sopenharmony_ci if (!AR_SREV_9100(ah) && !AR_SREV_9300_20_OR_LATER(ah)) 146562306a36Sopenharmony_ci REG_WRITE(ah, AR_RC, 0); 146662306a36Sopenharmony_ci 146762306a36Sopenharmony_ci REG_WRITE(ah, AR_RTC_RESET(ah), 1); 146862306a36Sopenharmony_ci 146962306a36Sopenharmony_ci if (!ath9k_hw_wait(ah, 147062306a36Sopenharmony_ci AR_RTC_STATUS(ah), 147162306a36Sopenharmony_ci AR_RTC_STATUS_M(ah), 147262306a36Sopenharmony_ci AR_RTC_STATUS_ON, 147362306a36Sopenharmony_ci AH_WAIT_TIMEOUT)) { 147462306a36Sopenharmony_ci ath_dbg(ath9k_hw_common(ah), RESET, "RTC not waking up\n"); 147562306a36Sopenharmony_ci return false; 147662306a36Sopenharmony_ci } 147762306a36Sopenharmony_ci 147862306a36Sopenharmony_ci return ath9k_hw_set_reset(ah, ATH9K_RESET_WARM); 147962306a36Sopenharmony_ci} 148062306a36Sopenharmony_ci 148162306a36Sopenharmony_cistatic bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type) 148262306a36Sopenharmony_ci{ 148362306a36Sopenharmony_ci bool ret = false; 148462306a36Sopenharmony_ci 148562306a36Sopenharmony_ci if (AR_SREV_9300_20_OR_LATER(ah)) { 148662306a36Sopenharmony_ci REG_WRITE(ah, AR_WA(ah), ah->WARegVal); 148762306a36Sopenharmony_ci udelay(10); 148862306a36Sopenharmony_ci } 148962306a36Sopenharmony_ci 149062306a36Sopenharmony_ci REG_WRITE(ah, AR_RTC_FORCE_WAKE(ah), 149162306a36Sopenharmony_ci AR_RTC_FORCE_WAKE_EN | AR_RTC_FORCE_WAKE_ON_INT); 149262306a36Sopenharmony_ci 149362306a36Sopenharmony_ci if (!ah->reset_power_on) 149462306a36Sopenharmony_ci type = ATH9K_RESET_POWER_ON; 149562306a36Sopenharmony_ci 149662306a36Sopenharmony_ci switch (type) { 149762306a36Sopenharmony_ci case ATH9K_RESET_POWER_ON: 149862306a36Sopenharmony_ci ret = ath9k_hw_set_reset_power_on(ah); 149962306a36Sopenharmony_ci if (ret) 150062306a36Sopenharmony_ci ah->reset_power_on = true; 150162306a36Sopenharmony_ci break; 150262306a36Sopenharmony_ci case ATH9K_RESET_WARM: 150362306a36Sopenharmony_ci case ATH9K_RESET_COLD: 150462306a36Sopenharmony_ci ret = ath9k_hw_set_reset(ah, type); 150562306a36Sopenharmony_ci break; 150662306a36Sopenharmony_ci default: 150762306a36Sopenharmony_ci break; 150862306a36Sopenharmony_ci } 150962306a36Sopenharmony_ci 151062306a36Sopenharmony_ci return ret; 151162306a36Sopenharmony_ci} 151262306a36Sopenharmony_ci 151362306a36Sopenharmony_cistatic bool ath9k_hw_chip_reset(struct ath_hw *ah, 151462306a36Sopenharmony_ci struct ath9k_channel *chan) 151562306a36Sopenharmony_ci{ 151662306a36Sopenharmony_ci int reset_type = ATH9K_RESET_WARM; 151762306a36Sopenharmony_ci 151862306a36Sopenharmony_ci if (AR_SREV_9280(ah)) { 151962306a36Sopenharmony_ci if (ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)) 152062306a36Sopenharmony_ci reset_type = ATH9K_RESET_POWER_ON; 152162306a36Sopenharmony_ci else 152262306a36Sopenharmony_ci reset_type = ATH9K_RESET_COLD; 152362306a36Sopenharmony_ci } else if (ah->chip_fullsleep || REG_READ(ah, AR_Q_TXE) || 152462306a36Sopenharmony_ci (REG_READ(ah, AR_CR) & AR_CR_RXE(ah))) 152562306a36Sopenharmony_ci reset_type = ATH9K_RESET_COLD; 152662306a36Sopenharmony_ci 152762306a36Sopenharmony_ci if (!ath9k_hw_set_reset_reg(ah, reset_type)) 152862306a36Sopenharmony_ci return false; 152962306a36Sopenharmony_ci 153062306a36Sopenharmony_ci if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) 153162306a36Sopenharmony_ci return false; 153262306a36Sopenharmony_ci 153362306a36Sopenharmony_ci ah->chip_fullsleep = false; 153462306a36Sopenharmony_ci 153562306a36Sopenharmony_ci if (AR_SREV_9330(ah)) 153662306a36Sopenharmony_ci ar9003_hw_internal_regulator_apply(ah); 153762306a36Sopenharmony_ci ath9k_hw_init_pll(ah, chan); 153862306a36Sopenharmony_ci 153962306a36Sopenharmony_ci return true; 154062306a36Sopenharmony_ci} 154162306a36Sopenharmony_ci 154262306a36Sopenharmony_cistatic bool ath9k_hw_channel_change(struct ath_hw *ah, 154362306a36Sopenharmony_ci struct ath9k_channel *chan) 154462306a36Sopenharmony_ci{ 154562306a36Sopenharmony_ci struct ath_common *common = ath9k_hw_common(ah); 154662306a36Sopenharmony_ci struct ath9k_hw_capabilities *pCap = &ah->caps; 154762306a36Sopenharmony_ci bool band_switch = false, mode_diff = false; 154862306a36Sopenharmony_ci u8 ini_reloaded = 0; 154962306a36Sopenharmony_ci u32 qnum; 155062306a36Sopenharmony_ci int r; 155162306a36Sopenharmony_ci 155262306a36Sopenharmony_ci if (pCap->hw_caps & ATH9K_HW_CAP_FCC_BAND_SWITCH) { 155362306a36Sopenharmony_ci u32 flags_diff = chan->channelFlags ^ ah->curchan->channelFlags; 155462306a36Sopenharmony_ci band_switch = !!(flags_diff & CHANNEL_5GHZ); 155562306a36Sopenharmony_ci mode_diff = !!(flags_diff & ~CHANNEL_HT); 155662306a36Sopenharmony_ci } 155762306a36Sopenharmony_ci 155862306a36Sopenharmony_ci for (qnum = 0; qnum < AR_NUM_QCU; qnum++) { 155962306a36Sopenharmony_ci if (ath9k_hw_numtxpending(ah, qnum)) { 156062306a36Sopenharmony_ci ath_dbg(common, QUEUE, 156162306a36Sopenharmony_ci "Transmit frames pending on queue %d\n", qnum); 156262306a36Sopenharmony_ci return false; 156362306a36Sopenharmony_ci } 156462306a36Sopenharmony_ci } 156562306a36Sopenharmony_ci 156662306a36Sopenharmony_ci if (!ath9k_hw_rfbus_req(ah)) { 156762306a36Sopenharmony_ci ath_err(common, "Could not kill baseband RX\n"); 156862306a36Sopenharmony_ci return false; 156962306a36Sopenharmony_ci } 157062306a36Sopenharmony_ci 157162306a36Sopenharmony_ci if (band_switch || mode_diff) { 157262306a36Sopenharmony_ci ath9k_hw_mark_phy_inactive(ah); 157362306a36Sopenharmony_ci udelay(5); 157462306a36Sopenharmony_ci 157562306a36Sopenharmony_ci if (band_switch) 157662306a36Sopenharmony_ci ath9k_hw_init_pll(ah, chan); 157762306a36Sopenharmony_ci 157862306a36Sopenharmony_ci if (ath9k_hw_fast_chan_change(ah, chan, &ini_reloaded)) { 157962306a36Sopenharmony_ci ath_err(common, "Failed to do fast channel change\n"); 158062306a36Sopenharmony_ci return false; 158162306a36Sopenharmony_ci } 158262306a36Sopenharmony_ci } 158362306a36Sopenharmony_ci 158462306a36Sopenharmony_ci ath9k_hw_set_channel_regs(ah, chan); 158562306a36Sopenharmony_ci 158662306a36Sopenharmony_ci r = ath9k_hw_rf_set_freq(ah, chan); 158762306a36Sopenharmony_ci if (r) { 158862306a36Sopenharmony_ci ath_err(common, "Failed to set channel\n"); 158962306a36Sopenharmony_ci return false; 159062306a36Sopenharmony_ci } 159162306a36Sopenharmony_ci ath9k_hw_set_clockrate(ah); 159262306a36Sopenharmony_ci ath9k_hw_apply_txpower(ah, chan, false); 159362306a36Sopenharmony_ci 159462306a36Sopenharmony_ci ath9k_hw_set_delta_slope(ah, chan); 159562306a36Sopenharmony_ci ath9k_hw_spur_mitigate_freq(ah, chan); 159662306a36Sopenharmony_ci 159762306a36Sopenharmony_ci if (band_switch || ini_reloaded) 159862306a36Sopenharmony_ci ah->eep_ops->set_board_values(ah, chan); 159962306a36Sopenharmony_ci 160062306a36Sopenharmony_ci ath9k_hw_init_bb(ah, chan); 160162306a36Sopenharmony_ci ath9k_hw_rfbus_done(ah); 160262306a36Sopenharmony_ci 160362306a36Sopenharmony_ci if (band_switch || ini_reloaded) { 160462306a36Sopenharmony_ci ah->ah_flags |= AH_FASTCC; 160562306a36Sopenharmony_ci ath9k_hw_init_cal(ah, chan); 160662306a36Sopenharmony_ci ah->ah_flags &= ~AH_FASTCC; 160762306a36Sopenharmony_ci } 160862306a36Sopenharmony_ci 160962306a36Sopenharmony_ci return true; 161062306a36Sopenharmony_ci} 161162306a36Sopenharmony_ci 161262306a36Sopenharmony_cistatic void ath9k_hw_apply_gpio_override(struct ath_hw *ah) 161362306a36Sopenharmony_ci{ 161462306a36Sopenharmony_ci u32 gpio_mask = ah->gpio_mask; 161562306a36Sopenharmony_ci int i; 161662306a36Sopenharmony_ci 161762306a36Sopenharmony_ci for (i = 0; gpio_mask; i++, gpio_mask >>= 1) { 161862306a36Sopenharmony_ci if (!(gpio_mask & 1)) 161962306a36Sopenharmony_ci continue; 162062306a36Sopenharmony_ci 162162306a36Sopenharmony_ci ath9k_hw_gpio_request_out(ah, i, NULL, 162262306a36Sopenharmony_ci AR_GPIO_OUTPUT_MUX_AS_OUTPUT); 162362306a36Sopenharmony_ci ath9k_hw_set_gpio(ah, i, !!(ah->gpio_val & BIT(i))); 162462306a36Sopenharmony_ci } 162562306a36Sopenharmony_ci} 162662306a36Sopenharmony_ci 162762306a36Sopenharmony_civoid ath9k_hw_check_nav(struct ath_hw *ah) 162862306a36Sopenharmony_ci{ 162962306a36Sopenharmony_ci struct ath_common *common = ath9k_hw_common(ah); 163062306a36Sopenharmony_ci u32 val; 163162306a36Sopenharmony_ci 163262306a36Sopenharmony_ci val = REG_READ(ah, AR_NAV); 163362306a36Sopenharmony_ci if (val != 0xdeadbeef && val > 0x7fff) { 163462306a36Sopenharmony_ci ath_dbg(common, BSTUCK, "Abnormal NAV: 0x%x\n", val); 163562306a36Sopenharmony_ci REG_WRITE(ah, AR_NAV, 0); 163662306a36Sopenharmony_ci } 163762306a36Sopenharmony_ci} 163862306a36Sopenharmony_ciEXPORT_SYMBOL(ath9k_hw_check_nav); 163962306a36Sopenharmony_ci 164062306a36Sopenharmony_cibool ath9k_hw_check_alive(struct ath_hw *ah) 164162306a36Sopenharmony_ci{ 164262306a36Sopenharmony_ci int count = 50; 164362306a36Sopenharmony_ci u32 reg, last_val; 164462306a36Sopenharmony_ci 164562306a36Sopenharmony_ci /* Check if chip failed to wake up */ 164662306a36Sopenharmony_ci if (REG_READ(ah, AR_CFG) == 0xdeadbeef) 164762306a36Sopenharmony_ci return false; 164862306a36Sopenharmony_ci 164962306a36Sopenharmony_ci if (AR_SREV_9300(ah)) 165062306a36Sopenharmony_ci return !ath9k_hw_detect_mac_hang(ah); 165162306a36Sopenharmony_ci 165262306a36Sopenharmony_ci if (AR_SREV_9285_12_OR_LATER(ah)) 165362306a36Sopenharmony_ci return true; 165462306a36Sopenharmony_ci 165562306a36Sopenharmony_ci last_val = REG_READ(ah, AR_OBS_BUS_1); 165662306a36Sopenharmony_ci do { 165762306a36Sopenharmony_ci reg = REG_READ(ah, AR_OBS_BUS_1); 165862306a36Sopenharmony_ci if (reg != last_val) 165962306a36Sopenharmony_ci return true; 166062306a36Sopenharmony_ci 166162306a36Sopenharmony_ci udelay(1); 166262306a36Sopenharmony_ci last_val = reg; 166362306a36Sopenharmony_ci if ((reg & 0x7E7FFFEF) == 0x00702400) 166462306a36Sopenharmony_ci continue; 166562306a36Sopenharmony_ci 166662306a36Sopenharmony_ci switch (reg & 0x7E000B00) { 166762306a36Sopenharmony_ci case 0x1E000000: 166862306a36Sopenharmony_ci case 0x52000B00: 166962306a36Sopenharmony_ci case 0x18000B00: 167062306a36Sopenharmony_ci continue; 167162306a36Sopenharmony_ci default: 167262306a36Sopenharmony_ci return true; 167362306a36Sopenharmony_ci } 167462306a36Sopenharmony_ci } while (count-- > 0); 167562306a36Sopenharmony_ci 167662306a36Sopenharmony_ci return false; 167762306a36Sopenharmony_ci} 167862306a36Sopenharmony_ciEXPORT_SYMBOL(ath9k_hw_check_alive); 167962306a36Sopenharmony_ci 168062306a36Sopenharmony_cistatic void ath9k_hw_init_mfp(struct ath_hw *ah) 168162306a36Sopenharmony_ci{ 168262306a36Sopenharmony_ci /* Setup MFP options for CCMP */ 168362306a36Sopenharmony_ci if (AR_SREV_9280_20_OR_LATER(ah)) { 168462306a36Sopenharmony_ci /* Mask Retry(b11), PwrMgt(b12), MoreData(b13) to 0 in mgmt 168562306a36Sopenharmony_ci * frames when constructing CCMP AAD. */ 168662306a36Sopenharmony_ci REG_RMW_FIELD(ah, AR_AES_MUTE_MASK1, AR_AES_MUTE_MASK1_FC_MGMT, 168762306a36Sopenharmony_ci 0xc7ff); 168862306a36Sopenharmony_ci if (AR_SREV_9271(ah) || AR_DEVID_7010(ah)) 168962306a36Sopenharmony_ci ah->sw_mgmt_crypto_tx = true; 169062306a36Sopenharmony_ci else 169162306a36Sopenharmony_ci ah->sw_mgmt_crypto_tx = false; 169262306a36Sopenharmony_ci ah->sw_mgmt_crypto_rx = false; 169362306a36Sopenharmony_ci } else if (AR_SREV_9160_10_OR_LATER(ah)) { 169462306a36Sopenharmony_ci /* Disable hardware crypto for management frames */ 169562306a36Sopenharmony_ci REG_CLR_BIT(ah, AR_PCU_MISC_MODE2, 169662306a36Sopenharmony_ci AR_PCU_MISC_MODE2_MGMT_CRYPTO_ENABLE); 169762306a36Sopenharmony_ci REG_SET_BIT(ah, AR_PCU_MISC_MODE2, 169862306a36Sopenharmony_ci AR_PCU_MISC_MODE2_NO_CRYPTO_FOR_NON_DATA_PKT); 169962306a36Sopenharmony_ci ah->sw_mgmt_crypto_tx = true; 170062306a36Sopenharmony_ci ah->sw_mgmt_crypto_rx = true; 170162306a36Sopenharmony_ci } else { 170262306a36Sopenharmony_ci ah->sw_mgmt_crypto_tx = true; 170362306a36Sopenharmony_ci ah->sw_mgmt_crypto_rx = true; 170462306a36Sopenharmony_ci } 170562306a36Sopenharmony_ci} 170662306a36Sopenharmony_ci 170762306a36Sopenharmony_cistatic void ath9k_hw_reset_opmode(struct ath_hw *ah, 170862306a36Sopenharmony_ci u32 macStaId1, u32 saveDefAntenna) 170962306a36Sopenharmony_ci{ 171062306a36Sopenharmony_ci struct ath_common *common = ath9k_hw_common(ah); 171162306a36Sopenharmony_ci 171262306a36Sopenharmony_ci ENABLE_REGWRITE_BUFFER(ah); 171362306a36Sopenharmony_ci 171462306a36Sopenharmony_ci REG_RMW(ah, AR_STA_ID1, macStaId1 171562306a36Sopenharmony_ci | AR_STA_ID1_RTS_USE_DEF 171662306a36Sopenharmony_ci | ah->sta_id1_defaults, 171762306a36Sopenharmony_ci ~AR_STA_ID1_SADH_MASK); 171862306a36Sopenharmony_ci ath_hw_setbssidmask(common); 171962306a36Sopenharmony_ci REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna); 172062306a36Sopenharmony_ci ath9k_hw_write_associd(ah); 172162306a36Sopenharmony_ci REG_WRITE(ah, AR_ISR, ~0); 172262306a36Sopenharmony_ci REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR); 172362306a36Sopenharmony_ci 172462306a36Sopenharmony_ci REGWRITE_BUFFER_FLUSH(ah); 172562306a36Sopenharmony_ci 172662306a36Sopenharmony_ci ath9k_hw_set_operating_mode(ah, ah->opmode); 172762306a36Sopenharmony_ci} 172862306a36Sopenharmony_ci 172962306a36Sopenharmony_cistatic void ath9k_hw_init_queues(struct ath_hw *ah) 173062306a36Sopenharmony_ci{ 173162306a36Sopenharmony_ci int i; 173262306a36Sopenharmony_ci 173362306a36Sopenharmony_ci ENABLE_REGWRITE_BUFFER(ah); 173462306a36Sopenharmony_ci 173562306a36Sopenharmony_ci for (i = 0; i < AR_NUM_DCU; i++) 173662306a36Sopenharmony_ci REG_WRITE(ah, AR_DQCUMASK(i), 1 << i); 173762306a36Sopenharmony_ci 173862306a36Sopenharmony_ci REGWRITE_BUFFER_FLUSH(ah); 173962306a36Sopenharmony_ci 174062306a36Sopenharmony_ci ah->intr_txqs = 0; 174162306a36Sopenharmony_ci for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) 174262306a36Sopenharmony_ci ath9k_hw_resettxqueue(ah, i); 174362306a36Sopenharmony_ci} 174462306a36Sopenharmony_ci 174562306a36Sopenharmony_ci/* 174662306a36Sopenharmony_ci * For big endian systems turn on swapping for descriptors 174762306a36Sopenharmony_ci */ 174862306a36Sopenharmony_cistatic void ath9k_hw_init_desc(struct ath_hw *ah) 174962306a36Sopenharmony_ci{ 175062306a36Sopenharmony_ci struct ath_common *common = ath9k_hw_common(ah); 175162306a36Sopenharmony_ci 175262306a36Sopenharmony_ci if (AR_SREV_9100(ah)) { 175362306a36Sopenharmony_ci u32 mask; 175462306a36Sopenharmony_ci mask = REG_READ(ah, AR_CFG); 175562306a36Sopenharmony_ci if (mask & (AR_CFG_SWRB | AR_CFG_SWTB | AR_CFG_SWRG)) { 175662306a36Sopenharmony_ci ath_dbg(common, RESET, "CFG Byte Swap Set 0x%x\n", 175762306a36Sopenharmony_ci mask); 175862306a36Sopenharmony_ci } else { 175962306a36Sopenharmony_ci mask = INIT_CONFIG_STATUS | AR_CFG_SWRB | AR_CFG_SWTB; 176062306a36Sopenharmony_ci REG_WRITE(ah, AR_CFG, mask); 176162306a36Sopenharmony_ci ath_dbg(common, RESET, "Setting CFG 0x%x\n", 176262306a36Sopenharmony_ci REG_READ(ah, AR_CFG)); 176362306a36Sopenharmony_ci } 176462306a36Sopenharmony_ci } else { 176562306a36Sopenharmony_ci if (common->bus_ops->ath_bus_type == ATH_USB) { 176662306a36Sopenharmony_ci /* Configure AR9271 target WLAN */ 176762306a36Sopenharmony_ci if (AR_SREV_9271(ah)) 176862306a36Sopenharmony_ci REG_WRITE(ah, AR_CFG, AR_CFG_SWRB | AR_CFG_SWTB); 176962306a36Sopenharmony_ci else 177062306a36Sopenharmony_ci REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD); 177162306a36Sopenharmony_ci } 177262306a36Sopenharmony_ci#ifdef __BIG_ENDIAN 177362306a36Sopenharmony_ci else if (AR_SREV_9330(ah) || AR_SREV_9340(ah) || 177462306a36Sopenharmony_ci AR_SREV_9550(ah) || AR_SREV_9531(ah) || 177562306a36Sopenharmony_ci AR_SREV_9561(ah)) 177662306a36Sopenharmony_ci REG_RMW(ah, AR_CFG, AR_CFG_SWRB | AR_CFG_SWTB, 0); 177762306a36Sopenharmony_ci else 177862306a36Sopenharmony_ci REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD); 177962306a36Sopenharmony_ci#endif 178062306a36Sopenharmony_ci } 178162306a36Sopenharmony_ci} 178262306a36Sopenharmony_ci 178362306a36Sopenharmony_ci/* 178462306a36Sopenharmony_ci * Fast channel change: 178562306a36Sopenharmony_ci * (Change synthesizer based on channel freq without resetting chip) 178662306a36Sopenharmony_ci */ 178762306a36Sopenharmony_cistatic int ath9k_hw_do_fastcc(struct ath_hw *ah, struct ath9k_channel *chan) 178862306a36Sopenharmony_ci{ 178962306a36Sopenharmony_ci struct ath_common *common = ath9k_hw_common(ah); 179062306a36Sopenharmony_ci struct ath9k_hw_capabilities *pCap = &ah->caps; 179162306a36Sopenharmony_ci int ret; 179262306a36Sopenharmony_ci 179362306a36Sopenharmony_ci if (AR_SREV_9280(ah) && common->bus_ops->ath_bus_type == ATH_PCI) 179462306a36Sopenharmony_ci goto fail; 179562306a36Sopenharmony_ci 179662306a36Sopenharmony_ci if (ah->chip_fullsleep) 179762306a36Sopenharmony_ci goto fail; 179862306a36Sopenharmony_ci 179962306a36Sopenharmony_ci if (!ah->curchan) 180062306a36Sopenharmony_ci goto fail; 180162306a36Sopenharmony_ci 180262306a36Sopenharmony_ci if (chan->channel == ah->curchan->channel) 180362306a36Sopenharmony_ci goto fail; 180462306a36Sopenharmony_ci 180562306a36Sopenharmony_ci if ((ah->curchan->channelFlags | chan->channelFlags) & 180662306a36Sopenharmony_ci (CHANNEL_HALF | CHANNEL_QUARTER)) 180762306a36Sopenharmony_ci goto fail; 180862306a36Sopenharmony_ci 180962306a36Sopenharmony_ci /* 181062306a36Sopenharmony_ci * If cross-band fcc is not supoprted, bail out if channelFlags differ. 181162306a36Sopenharmony_ci */ 181262306a36Sopenharmony_ci if (!(pCap->hw_caps & ATH9K_HW_CAP_FCC_BAND_SWITCH) && 181362306a36Sopenharmony_ci ((chan->channelFlags ^ ah->curchan->channelFlags) & ~CHANNEL_HT)) 181462306a36Sopenharmony_ci goto fail; 181562306a36Sopenharmony_ci 181662306a36Sopenharmony_ci if (!ath9k_hw_check_alive(ah)) 181762306a36Sopenharmony_ci goto fail; 181862306a36Sopenharmony_ci 181962306a36Sopenharmony_ci /* 182062306a36Sopenharmony_ci * For AR9462, make sure that calibration data for 182162306a36Sopenharmony_ci * re-using are present. 182262306a36Sopenharmony_ci */ 182362306a36Sopenharmony_ci if (AR_SREV_9462(ah) && (ah->caldata && 182462306a36Sopenharmony_ci (!test_bit(TXIQCAL_DONE, &ah->caldata->cal_flags) || 182562306a36Sopenharmony_ci !test_bit(TXCLCAL_DONE, &ah->caldata->cal_flags) || 182662306a36Sopenharmony_ci !test_bit(RTT_DONE, &ah->caldata->cal_flags)))) 182762306a36Sopenharmony_ci goto fail; 182862306a36Sopenharmony_ci 182962306a36Sopenharmony_ci ath_dbg(common, RESET, "FastChannelChange for %d -> %d\n", 183062306a36Sopenharmony_ci ah->curchan->channel, chan->channel); 183162306a36Sopenharmony_ci 183262306a36Sopenharmony_ci ret = ath9k_hw_channel_change(ah, chan); 183362306a36Sopenharmony_ci if (!ret) 183462306a36Sopenharmony_ci goto fail; 183562306a36Sopenharmony_ci 183662306a36Sopenharmony_ci if (ath9k_hw_mci_is_enabled(ah)) 183762306a36Sopenharmony_ci ar9003_mci_2g5g_switch(ah, false); 183862306a36Sopenharmony_ci 183962306a36Sopenharmony_ci ath9k_hw_loadnf(ah, ah->curchan); 184062306a36Sopenharmony_ci ath9k_hw_start_nfcal(ah, true); 184162306a36Sopenharmony_ci 184262306a36Sopenharmony_ci if (AR_SREV_9271(ah)) 184362306a36Sopenharmony_ci ar9002_hw_load_ani_reg(ah, chan); 184462306a36Sopenharmony_ci 184562306a36Sopenharmony_ci return 0; 184662306a36Sopenharmony_cifail: 184762306a36Sopenharmony_ci return -EINVAL; 184862306a36Sopenharmony_ci} 184962306a36Sopenharmony_ci 185062306a36Sopenharmony_ciu32 ath9k_hw_get_tsf_offset(struct timespec64 *last, struct timespec64 *cur) 185162306a36Sopenharmony_ci{ 185262306a36Sopenharmony_ci struct timespec64 ts; 185362306a36Sopenharmony_ci s64 usec; 185462306a36Sopenharmony_ci 185562306a36Sopenharmony_ci if (!cur) { 185662306a36Sopenharmony_ci ktime_get_raw_ts64(&ts); 185762306a36Sopenharmony_ci cur = &ts; 185862306a36Sopenharmony_ci } 185962306a36Sopenharmony_ci 186062306a36Sopenharmony_ci usec = cur->tv_sec * 1000000ULL + cur->tv_nsec / 1000; 186162306a36Sopenharmony_ci usec -= last->tv_sec * 1000000ULL + last->tv_nsec / 1000; 186262306a36Sopenharmony_ci 186362306a36Sopenharmony_ci return (u32) usec; 186462306a36Sopenharmony_ci} 186562306a36Sopenharmony_ciEXPORT_SYMBOL(ath9k_hw_get_tsf_offset); 186662306a36Sopenharmony_ci 186762306a36Sopenharmony_ciint ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, 186862306a36Sopenharmony_ci struct ath9k_hw_cal_data *caldata, bool fastcc) 186962306a36Sopenharmony_ci{ 187062306a36Sopenharmony_ci struct ath_common *common = ath9k_hw_common(ah); 187162306a36Sopenharmony_ci u32 saveLedState; 187262306a36Sopenharmony_ci u32 saveDefAntenna; 187362306a36Sopenharmony_ci u32 macStaId1; 187462306a36Sopenharmony_ci struct timespec64 tsf_ts; 187562306a36Sopenharmony_ci u32 tsf_offset; 187662306a36Sopenharmony_ci u64 tsf = 0; 187762306a36Sopenharmony_ci int r; 187862306a36Sopenharmony_ci bool start_mci_reset = false; 187962306a36Sopenharmony_ci bool save_fullsleep = ah->chip_fullsleep; 188062306a36Sopenharmony_ci 188162306a36Sopenharmony_ci if (ath9k_hw_mci_is_enabled(ah)) { 188262306a36Sopenharmony_ci start_mci_reset = ar9003_mci_start_reset(ah, chan); 188362306a36Sopenharmony_ci if (start_mci_reset) 188462306a36Sopenharmony_ci return 0; 188562306a36Sopenharmony_ci } 188662306a36Sopenharmony_ci 188762306a36Sopenharmony_ci if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) 188862306a36Sopenharmony_ci return -EIO; 188962306a36Sopenharmony_ci 189062306a36Sopenharmony_ci if (ah->curchan && !ah->chip_fullsleep) 189162306a36Sopenharmony_ci ath9k_hw_getnf(ah, ah->curchan); 189262306a36Sopenharmony_ci 189362306a36Sopenharmony_ci ah->caldata = caldata; 189462306a36Sopenharmony_ci if (caldata && (chan->channel != caldata->channel || 189562306a36Sopenharmony_ci chan->channelFlags != caldata->channelFlags)) { 189662306a36Sopenharmony_ci /* Operating channel changed, reset channel calibration data */ 189762306a36Sopenharmony_ci memset(caldata, 0, sizeof(*caldata)); 189862306a36Sopenharmony_ci ath9k_init_nfcal_hist_buffer(ah, chan); 189962306a36Sopenharmony_ci } else if (caldata) { 190062306a36Sopenharmony_ci clear_bit(PAPRD_PACKET_SENT, &caldata->cal_flags); 190162306a36Sopenharmony_ci } 190262306a36Sopenharmony_ci ah->noise = ath9k_hw_getchan_noise(ah, chan, chan->noisefloor); 190362306a36Sopenharmony_ci 190462306a36Sopenharmony_ci if (fastcc) { 190562306a36Sopenharmony_ci r = ath9k_hw_do_fastcc(ah, chan); 190662306a36Sopenharmony_ci if (!r) 190762306a36Sopenharmony_ci return r; 190862306a36Sopenharmony_ci } 190962306a36Sopenharmony_ci 191062306a36Sopenharmony_ci if (ath9k_hw_mci_is_enabled(ah)) 191162306a36Sopenharmony_ci ar9003_mci_stop_bt(ah, save_fullsleep); 191262306a36Sopenharmony_ci 191362306a36Sopenharmony_ci saveDefAntenna = REG_READ(ah, AR_DEF_ANTENNA); 191462306a36Sopenharmony_ci if (saveDefAntenna == 0) 191562306a36Sopenharmony_ci saveDefAntenna = 1; 191662306a36Sopenharmony_ci 191762306a36Sopenharmony_ci macStaId1 = REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_BASE_RATE_11B; 191862306a36Sopenharmony_ci 191962306a36Sopenharmony_ci /* Save TSF before chip reset, a cold reset clears it */ 192062306a36Sopenharmony_ci ktime_get_raw_ts64(&tsf_ts); 192162306a36Sopenharmony_ci tsf = ath9k_hw_gettsf64(ah); 192262306a36Sopenharmony_ci 192362306a36Sopenharmony_ci saveLedState = REG_READ(ah, AR_CFG_LED) & 192462306a36Sopenharmony_ci (AR_CFG_LED_ASSOC_CTL | AR_CFG_LED_MODE_SEL | 192562306a36Sopenharmony_ci AR_CFG_LED_BLINK_THRESH_SEL | AR_CFG_LED_BLINK_SLOW); 192662306a36Sopenharmony_ci 192762306a36Sopenharmony_ci ath9k_hw_mark_phy_inactive(ah); 192862306a36Sopenharmony_ci 192962306a36Sopenharmony_ci ah->paprd_table_write_done = false; 193062306a36Sopenharmony_ci 193162306a36Sopenharmony_ci /* Only required on the first reset */ 193262306a36Sopenharmony_ci if (AR_SREV_9271(ah) && ah->htc_reset_init) { 193362306a36Sopenharmony_ci REG_WRITE(ah, 193462306a36Sopenharmony_ci AR9271_RESET_POWER_DOWN_CONTROL, 193562306a36Sopenharmony_ci AR9271_RADIO_RF_RST); 193662306a36Sopenharmony_ci udelay(50); 193762306a36Sopenharmony_ci } 193862306a36Sopenharmony_ci 193962306a36Sopenharmony_ci if (!ath9k_hw_chip_reset(ah, chan)) { 194062306a36Sopenharmony_ci ath_err(common, "Chip reset failed\n"); 194162306a36Sopenharmony_ci return -EINVAL; 194262306a36Sopenharmony_ci } 194362306a36Sopenharmony_ci 194462306a36Sopenharmony_ci /* Only required on the first reset */ 194562306a36Sopenharmony_ci if (AR_SREV_9271(ah) && ah->htc_reset_init) { 194662306a36Sopenharmony_ci ah->htc_reset_init = false; 194762306a36Sopenharmony_ci REG_WRITE(ah, 194862306a36Sopenharmony_ci AR9271_RESET_POWER_DOWN_CONTROL, 194962306a36Sopenharmony_ci AR9271_GATE_MAC_CTL); 195062306a36Sopenharmony_ci udelay(50); 195162306a36Sopenharmony_ci } 195262306a36Sopenharmony_ci 195362306a36Sopenharmony_ci /* Restore TSF */ 195462306a36Sopenharmony_ci tsf_offset = ath9k_hw_get_tsf_offset(&tsf_ts, NULL); 195562306a36Sopenharmony_ci ath9k_hw_settsf64(ah, tsf + tsf_offset); 195662306a36Sopenharmony_ci 195762306a36Sopenharmony_ci if (AR_SREV_9280_20_OR_LATER(ah)) 195862306a36Sopenharmony_ci REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL(ah), AR_GPIO_JTAG_DISABLE); 195962306a36Sopenharmony_ci 196062306a36Sopenharmony_ci if (!AR_SREV_9300_20_OR_LATER(ah)) 196162306a36Sopenharmony_ci ar9002_hw_enable_async_fifo(ah); 196262306a36Sopenharmony_ci 196362306a36Sopenharmony_ci r = ath9k_hw_process_ini(ah, chan); 196462306a36Sopenharmony_ci if (r) 196562306a36Sopenharmony_ci return r; 196662306a36Sopenharmony_ci 196762306a36Sopenharmony_ci ath9k_hw_set_rfmode(ah, chan); 196862306a36Sopenharmony_ci 196962306a36Sopenharmony_ci if (ath9k_hw_mci_is_enabled(ah)) 197062306a36Sopenharmony_ci ar9003_mci_reset(ah, false, IS_CHAN_2GHZ(chan), save_fullsleep); 197162306a36Sopenharmony_ci 197262306a36Sopenharmony_ci /* 197362306a36Sopenharmony_ci * Some AR91xx SoC devices frequently fail to accept TSF writes 197462306a36Sopenharmony_ci * right after the chip reset. When that happens, write a new 197562306a36Sopenharmony_ci * value after the initvals have been applied. 197662306a36Sopenharmony_ci */ 197762306a36Sopenharmony_ci if (AR_SREV_9100(ah) && (ath9k_hw_gettsf64(ah) < tsf)) { 197862306a36Sopenharmony_ci tsf_offset = ath9k_hw_get_tsf_offset(&tsf_ts, NULL); 197962306a36Sopenharmony_ci ath9k_hw_settsf64(ah, tsf + tsf_offset); 198062306a36Sopenharmony_ci } 198162306a36Sopenharmony_ci 198262306a36Sopenharmony_ci ath9k_hw_init_mfp(ah); 198362306a36Sopenharmony_ci 198462306a36Sopenharmony_ci ath9k_hw_set_delta_slope(ah, chan); 198562306a36Sopenharmony_ci ath9k_hw_spur_mitigate_freq(ah, chan); 198662306a36Sopenharmony_ci ah->eep_ops->set_board_values(ah, chan); 198762306a36Sopenharmony_ci 198862306a36Sopenharmony_ci ath9k_hw_reset_opmode(ah, macStaId1, saveDefAntenna); 198962306a36Sopenharmony_ci 199062306a36Sopenharmony_ci r = ath9k_hw_rf_set_freq(ah, chan); 199162306a36Sopenharmony_ci if (r) 199262306a36Sopenharmony_ci return r; 199362306a36Sopenharmony_ci 199462306a36Sopenharmony_ci ath9k_hw_set_clockrate(ah); 199562306a36Sopenharmony_ci 199662306a36Sopenharmony_ci ath9k_hw_init_queues(ah); 199762306a36Sopenharmony_ci ath9k_hw_init_interrupt_masks(ah, ah->opmode); 199862306a36Sopenharmony_ci ath9k_hw_ani_cache_ini_regs(ah); 199962306a36Sopenharmony_ci ath9k_hw_init_qos(ah); 200062306a36Sopenharmony_ci 200162306a36Sopenharmony_ci if (ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT) 200262306a36Sopenharmony_ci ath9k_hw_gpio_request_in(ah, ah->rfkill_gpio, "ath9k-rfkill"); 200362306a36Sopenharmony_ci 200462306a36Sopenharmony_ci ath9k_hw_init_global_settings(ah); 200562306a36Sopenharmony_ci 200662306a36Sopenharmony_ci if (AR_SREV_9287(ah) && AR_SREV_9287_13_OR_LATER(ah)) { 200762306a36Sopenharmony_ci REG_SET_BIT(ah, AR_MAC_PCU_LOGIC_ANALYZER, 200862306a36Sopenharmony_ci AR_MAC_PCU_LOGIC_ANALYZER_DISBUG20768); 200962306a36Sopenharmony_ci REG_RMW_FIELD(ah, AR_AHB_MODE, AR_AHB_CUSTOM_BURST_EN, 201062306a36Sopenharmony_ci AR_AHB_CUSTOM_BURST_ASYNC_FIFO_VAL); 201162306a36Sopenharmony_ci REG_SET_BIT(ah, AR_PCU_MISC_MODE2, 201262306a36Sopenharmony_ci AR_PCU_MISC_MODE2_ENABLE_AGGWEP); 201362306a36Sopenharmony_ci } 201462306a36Sopenharmony_ci 201562306a36Sopenharmony_ci REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PRESERVE_SEQNUM); 201662306a36Sopenharmony_ci 201762306a36Sopenharmony_ci ath9k_hw_set_dma(ah); 201862306a36Sopenharmony_ci 201962306a36Sopenharmony_ci if (!ath9k_hw_mci_is_enabled(ah)) 202062306a36Sopenharmony_ci REG_WRITE(ah, AR_OBS(ah), 8); 202162306a36Sopenharmony_ci 202262306a36Sopenharmony_ci ENABLE_REG_RMW_BUFFER(ah); 202362306a36Sopenharmony_ci if (ah->config.rx_intr_mitigation) { 202462306a36Sopenharmony_ci REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, ah->config.rimt_last); 202562306a36Sopenharmony_ci REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_FIRST, ah->config.rimt_first); 202662306a36Sopenharmony_ci } 202762306a36Sopenharmony_ci 202862306a36Sopenharmony_ci if (ah->config.tx_intr_mitigation) { 202962306a36Sopenharmony_ci REG_RMW_FIELD(ah, AR_TIMT, AR_TIMT_LAST, 300); 203062306a36Sopenharmony_ci REG_RMW_FIELD(ah, AR_TIMT, AR_TIMT_FIRST, 750); 203162306a36Sopenharmony_ci } 203262306a36Sopenharmony_ci REG_RMW_BUFFER_FLUSH(ah); 203362306a36Sopenharmony_ci 203462306a36Sopenharmony_ci ath9k_hw_init_bb(ah, chan); 203562306a36Sopenharmony_ci 203662306a36Sopenharmony_ci if (caldata) { 203762306a36Sopenharmony_ci clear_bit(TXIQCAL_DONE, &caldata->cal_flags); 203862306a36Sopenharmony_ci clear_bit(TXCLCAL_DONE, &caldata->cal_flags); 203962306a36Sopenharmony_ci } 204062306a36Sopenharmony_ci if (!ath9k_hw_init_cal(ah, chan)) 204162306a36Sopenharmony_ci return -EIO; 204262306a36Sopenharmony_ci 204362306a36Sopenharmony_ci if (ath9k_hw_mci_is_enabled(ah) && ar9003_mci_end_reset(ah, chan, caldata)) 204462306a36Sopenharmony_ci return -EIO; 204562306a36Sopenharmony_ci 204662306a36Sopenharmony_ci ENABLE_REGWRITE_BUFFER(ah); 204762306a36Sopenharmony_ci 204862306a36Sopenharmony_ci ath9k_hw_restore_chainmask(ah); 204962306a36Sopenharmony_ci REG_WRITE(ah, AR_CFG_LED, saveLedState | AR_CFG_SCLK_32KHZ); 205062306a36Sopenharmony_ci 205162306a36Sopenharmony_ci REGWRITE_BUFFER_FLUSH(ah); 205262306a36Sopenharmony_ci 205362306a36Sopenharmony_ci ath9k_hw_gen_timer_start_tsf2(ah); 205462306a36Sopenharmony_ci 205562306a36Sopenharmony_ci ath9k_hw_init_desc(ah); 205662306a36Sopenharmony_ci 205762306a36Sopenharmony_ci if (ath9k_hw_btcoex_is_enabled(ah)) 205862306a36Sopenharmony_ci ath9k_hw_btcoex_enable(ah); 205962306a36Sopenharmony_ci 206062306a36Sopenharmony_ci if (ath9k_hw_mci_is_enabled(ah)) 206162306a36Sopenharmony_ci ar9003_mci_check_bt(ah); 206262306a36Sopenharmony_ci 206362306a36Sopenharmony_ci if (AR_SREV_9300_20_OR_LATER(ah)) { 206462306a36Sopenharmony_ci ath9k_hw_loadnf(ah, chan); 206562306a36Sopenharmony_ci ath9k_hw_start_nfcal(ah, true); 206662306a36Sopenharmony_ci } 206762306a36Sopenharmony_ci 206862306a36Sopenharmony_ci if (AR_SREV_9300_20_OR_LATER(ah)) 206962306a36Sopenharmony_ci ar9003_hw_bb_watchdog_config(ah); 207062306a36Sopenharmony_ci 207162306a36Sopenharmony_ci if (ah->config.hw_hang_checks & HW_PHYRESTART_CLC_WAR) 207262306a36Sopenharmony_ci ar9003_hw_disable_phy_restart(ah); 207362306a36Sopenharmony_ci 207462306a36Sopenharmony_ci ath9k_hw_apply_gpio_override(ah); 207562306a36Sopenharmony_ci 207662306a36Sopenharmony_ci if (AR_SREV_9565(ah) && common->bt_ant_diversity) 207762306a36Sopenharmony_ci REG_SET_BIT(ah, AR_BTCOEX_WL_LNADIV, AR_BTCOEX_WL_LNADIV_FORCE_ON); 207862306a36Sopenharmony_ci 207962306a36Sopenharmony_ci if (ah->hw->conf.radar_enabled) { 208062306a36Sopenharmony_ci /* set HW specific DFS configuration */ 208162306a36Sopenharmony_ci ah->radar_conf.ext_channel = IS_CHAN_HT40(chan); 208262306a36Sopenharmony_ci ath9k_hw_set_radar_params(ah); 208362306a36Sopenharmony_ci } 208462306a36Sopenharmony_ci 208562306a36Sopenharmony_ci return 0; 208662306a36Sopenharmony_ci} 208762306a36Sopenharmony_ciEXPORT_SYMBOL(ath9k_hw_reset); 208862306a36Sopenharmony_ci 208962306a36Sopenharmony_ci/******************************/ 209062306a36Sopenharmony_ci/* Power Management (Chipset) */ 209162306a36Sopenharmony_ci/******************************/ 209262306a36Sopenharmony_ci 209362306a36Sopenharmony_ci/* 209462306a36Sopenharmony_ci * Notify Power Mgt is disabled in self-generated frames. 209562306a36Sopenharmony_ci * If requested, force chip to sleep. 209662306a36Sopenharmony_ci */ 209762306a36Sopenharmony_cistatic void ath9k_set_power_sleep(struct ath_hw *ah) 209862306a36Sopenharmony_ci{ 209962306a36Sopenharmony_ci REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); 210062306a36Sopenharmony_ci 210162306a36Sopenharmony_ci if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) { 210262306a36Sopenharmony_ci REG_CLR_BIT(ah, AR_TIMER_MODE, 0xff); 210362306a36Sopenharmony_ci REG_CLR_BIT(ah, AR_NDP2_TIMER_MODE, 0xff); 210462306a36Sopenharmony_ci REG_CLR_BIT(ah, AR_SLP32_INC, 0xfffff); 210562306a36Sopenharmony_ci /* xxx Required for WLAN only case ? */ 210662306a36Sopenharmony_ci REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_EN, 0); 210762306a36Sopenharmony_ci udelay(100); 210862306a36Sopenharmony_ci } 210962306a36Sopenharmony_ci 211062306a36Sopenharmony_ci /* 211162306a36Sopenharmony_ci * Clear the RTC force wake bit to allow the 211262306a36Sopenharmony_ci * mac to go to sleep. 211362306a36Sopenharmony_ci */ 211462306a36Sopenharmony_ci REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE(ah), AR_RTC_FORCE_WAKE_EN); 211562306a36Sopenharmony_ci 211662306a36Sopenharmony_ci if (ath9k_hw_mci_is_enabled(ah)) 211762306a36Sopenharmony_ci udelay(100); 211862306a36Sopenharmony_ci 211962306a36Sopenharmony_ci if (!AR_SREV_9100(ah) && !AR_SREV_9300_20_OR_LATER(ah)) 212062306a36Sopenharmony_ci REG_WRITE(ah, AR_RC, AR_RC_AHB | AR_RC_HOSTIF); 212162306a36Sopenharmony_ci 212262306a36Sopenharmony_ci /* Shutdown chip. Active low */ 212362306a36Sopenharmony_ci if (!AR_SREV_5416(ah) && !AR_SREV_9271(ah)) { 212462306a36Sopenharmony_ci REG_CLR_BIT(ah, AR_RTC_RESET(ah), AR_RTC_RESET_EN); 212562306a36Sopenharmony_ci udelay(2); 212662306a36Sopenharmony_ci } 212762306a36Sopenharmony_ci 212862306a36Sopenharmony_ci /* Clear Bit 14 of AR_WA(ah) after putting chip into Full Sleep mode. */ 212962306a36Sopenharmony_ci if (AR_SREV_9300_20_OR_LATER(ah)) 213062306a36Sopenharmony_ci REG_WRITE(ah, AR_WA(ah), ah->WARegVal & ~AR_WA_D3_L1_DISABLE); 213162306a36Sopenharmony_ci} 213262306a36Sopenharmony_ci 213362306a36Sopenharmony_ci/* 213462306a36Sopenharmony_ci * Notify Power Management is enabled in self-generating 213562306a36Sopenharmony_ci * frames. If request, set power mode of chip to 213662306a36Sopenharmony_ci * auto/normal. Duration in units of 128us (1/8 TU). 213762306a36Sopenharmony_ci */ 213862306a36Sopenharmony_cistatic void ath9k_set_power_network_sleep(struct ath_hw *ah) 213962306a36Sopenharmony_ci{ 214062306a36Sopenharmony_ci struct ath9k_hw_capabilities *pCap = &ah->caps; 214162306a36Sopenharmony_ci 214262306a36Sopenharmony_ci REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); 214362306a36Sopenharmony_ci 214462306a36Sopenharmony_ci if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { 214562306a36Sopenharmony_ci /* Set WakeOnInterrupt bit; clear ForceWake bit */ 214662306a36Sopenharmony_ci REG_WRITE(ah, AR_RTC_FORCE_WAKE(ah), 214762306a36Sopenharmony_ci AR_RTC_FORCE_WAKE_ON_INT); 214862306a36Sopenharmony_ci } else { 214962306a36Sopenharmony_ci 215062306a36Sopenharmony_ci /* When chip goes into network sleep, it could be waken 215162306a36Sopenharmony_ci * up by MCI_INT interrupt caused by BT's HW messages 215262306a36Sopenharmony_ci * (LNA_xxx, CONT_xxx) which chould be in a very fast 215362306a36Sopenharmony_ci * rate (~100us). This will cause chip to leave and 215462306a36Sopenharmony_ci * re-enter network sleep mode frequently, which in 215562306a36Sopenharmony_ci * consequence will have WLAN MCI HW to generate lots of 215662306a36Sopenharmony_ci * SYS_WAKING and SYS_SLEEPING messages which will make 215762306a36Sopenharmony_ci * BT CPU to busy to process. 215862306a36Sopenharmony_ci */ 215962306a36Sopenharmony_ci if (ath9k_hw_mci_is_enabled(ah)) 216062306a36Sopenharmony_ci REG_CLR_BIT(ah, AR_MCI_INTERRUPT_RX_MSG_EN, 216162306a36Sopenharmony_ci AR_MCI_INTERRUPT_RX_HW_MSG_MASK); 216262306a36Sopenharmony_ci /* 216362306a36Sopenharmony_ci * Clear the RTC force wake bit to allow the 216462306a36Sopenharmony_ci * mac to go to sleep. 216562306a36Sopenharmony_ci */ 216662306a36Sopenharmony_ci REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE(ah), AR_RTC_FORCE_WAKE_EN); 216762306a36Sopenharmony_ci 216862306a36Sopenharmony_ci if (ath9k_hw_mci_is_enabled(ah)) 216962306a36Sopenharmony_ci udelay(30); 217062306a36Sopenharmony_ci } 217162306a36Sopenharmony_ci 217262306a36Sopenharmony_ci /* Clear Bit 14 of AR_WA(ah) after putting chip into Net Sleep mode. */ 217362306a36Sopenharmony_ci if (AR_SREV_9300_20_OR_LATER(ah)) 217462306a36Sopenharmony_ci REG_WRITE(ah, AR_WA(ah), ah->WARegVal & ~AR_WA_D3_L1_DISABLE); 217562306a36Sopenharmony_ci} 217662306a36Sopenharmony_ci 217762306a36Sopenharmony_cistatic bool ath9k_hw_set_power_awake(struct ath_hw *ah) 217862306a36Sopenharmony_ci{ 217962306a36Sopenharmony_ci u32 val; 218062306a36Sopenharmony_ci int i; 218162306a36Sopenharmony_ci 218262306a36Sopenharmony_ci /* Set Bits 14 and 17 of AR_WA(ah) before powering on the chip. */ 218362306a36Sopenharmony_ci if (AR_SREV_9300_20_OR_LATER(ah)) { 218462306a36Sopenharmony_ci REG_WRITE(ah, AR_WA(ah), ah->WARegVal); 218562306a36Sopenharmony_ci udelay(10); 218662306a36Sopenharmony_ci } 218762306a36Sopenharmony_ci 218862306a36Sopenharmony_ci if ((REG_READ(ah, AR_RTC_STATUS(ah)) & 218962306a36Sopenharmony_ci AR_RTC_STATUS_M(ah)) == AR_RTC_STATUS_SHUTDOWN) { 219062306a36Sopenharmony_ci if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) { 219162306a36Sopenharmony_ci return false; 219262306a36Sopenharmony_ci } 219362306a36Sopenharmony_ci if (!AR_SREV_9300_20_OR_LATER(ah)) 219462306a36Sopenharmony_ci ath9k_hw_init_pll(ah, NULL); 219562306a36Sopenharmony_ci } 219662306a36Sopenharmony_ci if (AR_SREV_9100(ah)) 219762306a36Sopenharmony_ci REG_SET_BIT(ah, AR_RTC_RESET(ah), 219862306a36Sopenharmony_ci AR_RTC_RESET_EN); 219962306a36Sopenharmony_ci 220062306a36Sopenharmony_ci REG_SET_BIT(ah, AR_RTC_FORCE_WAKE(ah), 220162306a36Sopenharmony_ci AR_RTC_FORCE_WAKE_EN); 220262306a36Sopenharmony_ci if (AR_SREV_9100(ah)) 220362306a36Sopenharmony_ci mdelay(10); 220462306a36Sopenharmony_ci else 220562306a36Sopenharmony_ci udelay(50); 220662306a36Sopenharmony_ci 220762306a36Sopenharmony_ci for (i = POWER_UP_TIME / 50; i > 0; i--) { 220862306a36Sopenharmony_ci val = REG_READ(ah, AR_RTC_STATUS(ah)) & AR_RTC_STATUS_M(ah); 220962306a36Sopenharmony_ci if (val == AR_RTC_STATUS_ON) 221062306a36Sopenharmony_ci break; 221162306a36Sopenharmony_ci udelay(50); 221262306a36Sopenharmony_ci REG_SET_BIT(ah, AR_RTC_FORCE_WAKE(ah), 221362306a36Sopenharmony_ci AR_RTC_FORCE_WAKE_EN); 221462306a36Sopenharmony_ci } 221562306a36Sopenharmony_ci if (i == 0) { 221662306a36Sopenharmony_ci ath_err(ath9k_hw_common(ah), 221762306a36Sopenharmony_ci "Failed to wakeup in %uus\n", 221862306a36Sopenharmony_ci POWER_UP_TIME / 20); 221962306a36Sopenharmony_ci return false; 222062306a36Sopenharmony_ci } 222162306a36Sopenharmony_ci 222262306a36Sopenharmony_ci if (ath9k_hw_mci_is_enabled(ah)) 222362306a36Sopenharmony_ci ar9003_mci_set_power_awake(ah); 222462306a36Sopenharmony_ci 222562306a36Sopenharmony_ci REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); 222662306a36Sopenharmony_ci 222762306a36Sopenharmony_ci return true; 222862306a36Sopenharmony_ci} 222962306a36Sopenharmony_ci 223062306a36Sopenharmony_cibool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode) 223162306a36Sopenharmony_ci{ 223262306a36Sopenharmony_ci struct ath_common *common = ath9k_hw_common(ah); 223362306a36Sopenharmony_ci int status = true; 223462306a36Sopenharmony_ci static const char *modes[] = { 223562306a36Sopenharmony_ci "AWAKE", 223662306a36Sopenharmony_ci "FULL-SLEEP", 223762306a36Sopenharmony_ci "NETWORK SLEEP", 223862306a36Sopenharmony_ci "UNDEFINED" 223962306a36Sopenharmony_ci }; 224062306a36Sopenharmony_ci 224162306a36Sopenharmony_ci if (ah->power_mode == mode) 224262306a36Sopenharmony_ci return status; 224362306a36Sopenharmony_ci 224462306a36Sopenharmony_ci ath_dbg(common, RESET, "%s -> %s\n", 224562306a36Sopenharmony_ci modes[ah->power_mode], modes[mode]); 224662306a36Sopenharmony_ci 224762306a36Sopenharmony_ci switch (mode) { 224862306a36Sopenharmony_ci case ATH9K_PM_AWAKE: 224962306a36Sopenharmony_ci status = ath9k_hw_set_power_awake(ah); 225062306a36Sopenharmony_ci break; 225162306a36Sopenharmony_ci case ATH9K_PM_FULL_SLEEP: 225262306a36Sopenharmony_ci if (ath9k_hw_mci_is_enabled(ah)) 225362306a36Sopenharmony_ci ar9003_mci_set_full_sleep(ah); 225462306a36Sopenharmony_ci 225562306a36Sopenharmony_ci ath9k_set_power_sleep(ah); 225662306a36Sopenharmony_ci ah->chip_fullsleep = true; 225762306a36Sopenharmony_ci break; 225862306a36Sopenharmony_ci case ATH9K_PM_NETWORK_SLEEP: 225962306a36Sopenharmony_ci ath9k_set_power_network_sleep(ah); 226062306a36Sopenharmony_ci break; 226162306a36Sopenharmony_ci default: 226262306a36Sopenharmony_ci ath_err(common, "Unknown power mode %u\n", mode); 226362306a36Sopenharmony_ci return false; 226462306a36Sopenharmony_ci } 226562306a36Sopenharmony_ci ah->power_mode = mode; 226662306a36Sopenharmony_ci 226762306a36Sopenharmony_ci /* 226862306a36Sopenharmony_ci * XXX: If this warning never comes up after a while then 226962306a36Sopenharmony_ci * simply keep the ATH_DBG_WARN_ON_ONCE() but make 227062306a36Sopenharmony_ci * ath9k_hw_setpower() return type void. 227162306a36Sopenharmony_ci */ 227262306a36Sopenharmony_ci 227362306a36Sopenharmony_ci if (!(ah->ah_flags & AH_UNPLUGGED)) 227462306a36Sopenharmony_ci ATH_DBG_WARN_ON_ONCE(!status); 227562306a36Sopenharmony_ci 227662306a36Sopenharmony_ci return status; 227762306a36Sopenharmony_ci} 227862306a36Sopenharmony_ciEXPORT_SYMBOL(ath9k_hw_setpower); 227962306a36Sopenharmony_ci 228062306a36Sopenharmony_ci/*******************/ 228162306a36Sopenharmony_ci/* Beacon Handling */ 228262306a36Sopenharmony_ci/*******************/ 228362306a36Sopenharmony_ci 228462306a36Sopenharmony_civoid ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period) 228562306a36Sopenharmony_ci{ 228662306a36Sopenharmony_ci int flags = 0; 228762306a36Sopenharmony_ci 228862306a36Sopenharmony_ci ENABLE_REGWRITE_BUFFER(ah); 228962306a36Sopenharmony_ci 229062306a36Sopenharmony_ci switch (ah->opmode) { 229162306a36Sopenharmony_ci case NL80211_IFTYPE_ADHOC: 229262306a36Sopenharmony_ci REG_SET_BIT(ah, AR_TXCFG, 229362306a36Sopenharmony_ci AR_TXCFG_ADHOC_BEACON_ATIM_TX_POLICY); 229462306a36Sopenharmony_ci fallthrough; 229562306a36Sopenharmony_ci case NL80211_IFTYPE_MESH_POINT: 229662306a36Sopenharmony_ci case NL80211_IFTYPE_AP: 229762306a36Sopenharmony_ci REG_WRITE(ah, AR_NEXT_TBTT_TIMER, next_beacon); 229862306a36Sopenharmony_ci REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT, next_beacon - 229962306a36Sopenharmony_ci TU_TO_USEC(ah->config.dma_beacon_response_time)); 230062306a36Sopenharmony_ci REG_WRITE(ah, AR_NEXT_SWBA, next_beacon - 230162306a36Sopenharmony_ci TU_TO_USEC(ah->config.sw_beacon_response_time)); 230262306a36Sopenharmony_ci flags |= 230362306a36Sopenharmony_ci AR_TBTT_TIMER_EN | AR_DBA_TIMER_EN | AR_SWBA_TIMER_EN; 230462306a36Sopenharmony_ci break; 230562306a36Sopenharmony_ci default: 230662306a36Sopenharmony_ci ath_dbg(ath9k_hw_common(ah), BEACON, 230762306a36Sopenharmony_ci "%s: unsupported opmode: %d\n", __func__, ah->opmode); 230862306a36Sopenharmony_ci return; 230962306a36Sopenharmony_ci } 231062306a36Sopenharmony_ci 231162306a36Sopenharmony_ci REG_WRITE(ah, AR_BEACON_PERIOD, beacon_period); 231262306a36Sopenharmony_ci REG_WRITE(ah, AR_DMA_BEACON_PERIOD, beacon_period); 231362306a36Sopenharmony_ci REG_WRITE(ah, AR_SWBA_PERIOD, beacon_period); 231462306a36Sopenharmony_ci 231562306a36Sopenharmony_ci REGWRITE_BUFFER_FLUSH(ah); 231662306a36Sopenharmony_ci 231762306a36Sopenharmony_ci REG_SET_BIT(ah, AR_TIMER_MODE, flags); 231862306a36Sopenharmony_ci} 231962306a36Sopenharmony_ciEXPORT_SYMBOL(ath9k_hw_beaconinit); 232062306a36Sopenharmony_ci 232162306a36Sopenharmony_civoid ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, 232262306a36Sopenharmony_ci const struct ath9k_beacon_state *bs) 232362306a36Sopenharmony_ci{ 232462306a36Sopenharmony_ci u32 nextTbtt, beaconintval, dtimperiod, beacontimeout; 232562306a36Sopenharmony_ci struct ath9k_hw_capabilities *pCap = &ah->caps; 232662306a36Sopenharmony_ci struct ath_common *common = ath9k_hw_common(ah); 232762306a36Sopenharmony_ci 232862306a36Sopenharmony_ci ENABLE_REGWRITE_BUFFER(ah); 232962306a36Sopenharmony_ci 233062306a36Sopenharmony_ci REG_WRITE(ah, AR_NEXT_TBTT_TIMER, bs->bs_nexttbtt); 233162306a36Sopenharmony_ci REG_WRITE(ah, AR_BEACON_PERIOD, bs->bs_intval); 233262306a36Sopenharmony_ci REG_WRITE(ah, AR_DMA_BEACON_PERIOD, bs->bs_intval); 233362306a36Sopenharmony_ci 233462306a36Sopenharmony_ci REGWRITE_BUFFER_FLUSH(ah); 233562306a36Sopenharmony_ci 233662306a36Sopenharmony_ci REG_RMW_FIELD(ah, AR_RSSI_THR, 233762306a36Sopenharmony_ci AR_RSSI_THR_BM_THR, bs->bs_bmissthreshold); 233862306a36Sopenharmony_ci 233962306a36Sopenharmony_ci beaconintval = bs->bs_intval; 234062306a36Sopenharmony_ci 234162306a36Sopenharmony_ci if (bs->bs_sleepduration > beaconintval) 234262306a36Sopenharmony_ci beaconintval = bs->bs_sleepduration; 234362306a36Sopenharmony_ci 234462306a36Sopenharmony_ci dtimperiod = bs->bs_dtimperiod; 234562306a36Sopenharmony_ci if (bs->bs_sleepduration > dtimperiod) 234662306a36Sopenharmony_ci dtimperiod = bs->bs_sleepduration; 234762306a36Sopenharmony_ci 234862306a36Sopenharmony_ci if (beaconintval == dtimperiod) 234962306a36Sopenharmony_ci nextTbtt = bs->bs_nextdtim; 235062306a36Sopenharmony_ci else 235162306a36Sopenharmony_ci nextTbtt = bs->bs_nexttbtt; 235262306a36Sopenharmony_ci 235362306a36Sopenharmony_ci ath_dbg(common, BEACON, "next DTIM %u\n", bs->bs_nextdtim); 235462306a36Sopenharmony_ci ath_dbg(common, BEACON, "next beacon %u\n", nextTbtt); 235562306a36Sopenharmony_ci ath_dbg(common, BEACON, "beacon period %u\n", beaconintval); 235662306a36Sopenharmony_ci ath_dbg(common, BEACON, "DTIM period %u\n", dtimperiod); 235762306a36Sopenharmony_ci 235862306a36Sopenharmony_ci ENABLE_REGWRITE_BUFFER(ah); 235962306a36Sopenharmony_ci 236062306a36Sopenharmony_ci REG_WRITE(ah, AR_NEXT_DTIM, bs->bs_nextdtim - SLEEP_SLOP); 236162306a36Sopenharmony_ci REG_WRITE(ah, AR_NEXT_TIM, nextTbtt - SLEEP_SLOP); 236262306a36Sopenharmony_ci 236362306a36Sopenharmony_ci REG_WRITE(ah, AR_SLEEP1, 236462306a36Sopenharmony_ci SM((CAB_TIMEOUT_VAL << 3), AR_SLEEP1_CAB_TIMEOUT) 236562306a36Sopenharmony_ci | AR_SLEEP1_ASSUME_DTIM); 236662306a36Sopenharmony_ci 236762306a36Sopenharmony_ci if (pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP) 236862306a36Sopenharmony_ci beacontimeout = (BEACON_TIMEOUT_VAL << 3); 236962306a36Sopenharmony_ci else 237062306a36Sopenharmony_ci beacontimeout = MIN_BEACON_TIMEOUT_VAL; 237162306a36Sopenharmony_ci 237262306a36Sopenharmony_ci REG_WRITE(ah, AR_SLEEP2, 237362306a36Sopenharmony_ci SM(beacontimeout, AR_SLEEP2_BEACON_TIMEOUT)); 237462306a36Sopenharmony_ci 237562306a36Sopenharmony_ci REG_WRITE(ah, AR_TIM_PERIOD, beaconintval); 237662306a36Sopenharmony_ci REG_WRITE(ah, AR_DTIM_PERIOD, dtimperiod); 237762306a36Sopenharmony_ci 237862306a36Sopenharmony_ci REGWRITE_BUFFER_FLUSH(ah); 237962306a36Sopenharmony_ci 238062306a36Sopenharmony_ci REG_SET_BIT(ah, AR_TIMER_MODE, 238162306a36Sopenharmony_ci AR_TBTT_TIMER_EN | AR_TIM_TIMER_EN | 238262306a36Sopenharmony_ci AR_DTIM_TIMER_EN); 238362306a36Sopenharmony_ci 238462306a36Sopenharmony_ci /* TSF Out of Range Threshold */ 238562306a36Sopenharmony_ci REG_WRITE(ah, AR_TSFOOR_THRESHOLD, bs->bs_tsfoor_threshold); 238662306a36Sopenharmony_ci} 238762306a36Sopenharmony_ciEXPORT_SYMBOL(ath9k_hw_set_sta_beacon_timers); 238862306a36Sopenharmony_ci 238962306a36Sopenharmony_ci/*******************/ 239062306a36Sopenharmony_ci/* HW Capabilities */ 239162306a36Sopenharmony_ci/*******************/ 239262306a36Sopenharmony_ci 239362306a36Sopenharmony_cistatic u8 fixup_chainmask(u8 chip_chainmask, u8 eeprom_chainmask) 239462306a36Sopenharmony_ci{ 239562306a36Sopenharmony_ci eeprom_chainmask &= chip_chainmask; 239662306a36Sopenharmony_ci if (eeprom_chainmask) 239762306a36Sopenharmony_ci return eeprom_chainmask; 239862306a36Sopenharmony_ci else 239962306a36Sopenharmony_ci return chip_chainmask; 240062306a36Sopenharmony_ci} 240162306a36Sopenharmony_ci 240262306a36Sopenharmony_ci/** 240362306a36Sopenharmony_ci * ath9k_hw_dfs_tested - checks if DFS has been tested with used chipset 240462306a36Sopenharmony_ci * @ah: the atheros hardware data structure 240562306a36Sopenharmony_ci * 240662306a36Sopenharmony_ci * We enable DFS support upstream on chipsets which have passed a series 240762306a36Sopenharmony_ci * of tests. The testing requirements are going to be documented. Desired 240862306a36Sopenharmony_ci * test requirements are documented at: 240962306a36Sopenharmony_ci * 241062306a36Sopenharmony_ci * https://wireless.wiki.kernel.org/en/users/Drivers/ath9k/dfs 241162306a36Sopenharmony_ci * 241262306a36Sopenharmony_ci * Once a new chipset gets properly tested an individual commit can be used 241362306a36Sopenharmony_ci * to document the testing for DFS for that chipset. 241462306a36Sopenharmony_ci */ 241562306a36Sopenharmony_cistatic bool ath9k_hw_dfs_tested(struct ath_hw *ah) 241662306a36Sopenharmony_ci{ 241762306a36Sopenharmony_ci 241862306a36Sopenharmony_ci switch (ah->hw_version.macVersion) { 241962306a36Sopenharmony_ci /* for temporary testing DFS with 9280 */ 242062306a36Sopenharmony_ci case AR_SREV_VERSION_9280: 242162306a36Sopenharmony_ci /* AR9580 will likely be our first target to get testing on */ 242262306a36Sopenharmony_ci case AR_SREV_VERSION_9580: 242362306a36Sopenharmony_ci return true; 242462306a36Sopenharmony_ci default: 242562306a36Sopenharmony_ci return false; 242662306a36Sopenharmony_ci } 242762306a36Sopenharmony_ci} 242862306a36Sopenharmony_ci 242962306a36Sopenharmony_cistatic void ath9k_gpio_cap_init(struct ath_hw *ah) 243062306a36Sopenharmony_ci{ 243162306a36Sopenharmony_ci struct ath9k_hw_capabilities *pCap = &ah->caps; 243262306a36Sopenharmony_ci 243362306a36Sopenharmony_ci if (AR_SREV_9271(ah)) { 243462306a36Sopenharmony_ci pCap->num_gpio_pins = AR9271_NUM_GPIO; 243562306a36Sopenharmony_ci pCap->gpio_mask = AR9271_GPIO_MASK; 243662306a36Sopenharmony_ci } else if (AR_DEVID_7010(ah)) { 243762306a36Sopenharmony_ci pCap->num_gpio_pins = AR7010_NUM_GPIO; 243862306a36Sopenharmony_ci pCap->gpio_mask = AR7010_GPIO_MASK; 243962306a36Sopenharmony_ci } else if (AR_SREV_9287(ah)) { 244062306a36Sopenharmony_ci pCap->num_gpio_pins = AR9287_NUM_GPIO; 244162306a36Sopenharmony_ci pCap->gpio_mask = AR9287_GPIO_MASK; 244262306a36Sopenharmony_ci } else if (AR_SREV_9285(ah)) { 244362306a36Sopenharmony_ci pCap->num_gpio_pins = AR9285_NUM_GPIO; 244462306a36Sopenharmony_ci pCap->gpio_mask = AR9285_GPIO_MASK; 244562306a36Sopenharmony_ci } else if (AR_SREV_9280(ah)) { 244662306a36Sopenharmony_ci pCap->num_gpio_pins = AR9280_NUM_GPIO; 244762306a36Sopenharmony_ci pCap->gpio_mask = AR9280_GPIO_MASK; 244862306a36Sopenharmony_ci } else if (AR_SREV_9300(ah)) { 244962306a36Sopenharmony_ci pCap->num_gpio_pins = AR9300_NUM_GPIO; 245062306a36Sopenharmony_ci pCap->gpio_mask = AR9300_GPIO_MASK; 245162306a36Sopenharmony_ci } else if (AR_SREV_9330(ah)) { 245262306a36Sopenharmony_ci pCap->num_gpio_pins = AR9330_NUM_GPIO; 245362306a36Sopenharmony_ci pCap->gpio_mask = AR9330_GPIO_MASK; 245462306a36Sopenharmony_ci } else if (AR_SREV_9340(ah)) { 245562306a36Sopenharmony_ci pCap->num_gpio_pins = AR9340_NUM_GPIO; 245662306a36Sopenharmony_ci pCap->gpio_mask = AR9340_GPIO_MASK; 245762306a36Sopenharmony_ci } else if (AR_SREV_9462(ah)) { 245862306a36Sopenharmony_ci pCap->num_gpio_pins = AR9462_NUM_GPIO; 245962306a36Sopenharmony_ci pCap->gpio_mask = AR9462_GPIO_MASK; 246062306a36Sopenharmony_ci } else if (AR_SREV_9485(ah)) { 246162306a36Sopenharmony_ci pCap->num_gpio_pins = AR9485_NUM_GPIO; 246262306a36Sopenharmony_ci pCap->gpio_mask = AR9485_GPIO_MASK; 246362306a36Sopenharmony_ci } else if (AR_SREV_9531(ah)) { 246462306a36Sopenharmony_ci pCap->num_gpio_pins = AR9531_NUM_GPIO; 246562306a36Sopenharmony_ci pCap->gpio_mask = AR9531_GPIO_MASK; 246662306a36Sopenharmony_ci } else if (AR_SREV_9550(ah)) { 246762306a36Sopenharmony_ci pCap->num_gpio_pins = AR9550_NUM_GPIO; 246862306a36Sopenharmony_ci pCap->gpio_mask = AR9550_GPIO_MASK; 246962306a36Sopenharmony_ci } else if (AR_SREV_9561(ah)) { 247062306a36Sopenharmony_ci pCap->num_gpio_pins = AR9561_NUM_GPIO; 247162306a36Sopenharmony_ci pCap->gpio_mask = AR9561_GPIO_MASK; 247262306a36Sopenharmony_ci } else if (AR_SREV_9565(ah)) { 247362306a36Sopenharmony_ci pCap->num_gpio_pins = AR9565_NUM_GPIO; 247462306a36Sopenharmony_ci pCap->gpio_mask = AR9565_GPIO_MASK; 247562306a36Sopenharmony_ci } else if (AR_SREV_9580(ah)) { 247662306a36Sopenharmony_ci pCap->num_gpio_pins = AR9580_NUM_GPIO; 247762306a36Sopenharmony_ci pCap->gpio_mask = AR9580_GPIO_MASK; 247862306a36Sopenharmony_ci } else { 247962306a36Sopenharmony_ci pCap->num_gpio_pins = AR_NUM_GPIO; 248062306a36Sopenharmony_ci pCap->gpio_mask = AR_GPIO_MASK; 248162306a36Sopenharmony_ci } 248262306a36Sopenharmony_ci} 248362306a36Sopenharmony_ci 248462306a36Sopenharmony_ciint ath9k_hw_fill_cap_info(struct ath_hw *ah) 248562306a36Sopenharmony_ci{ 248662306a36Sopenharmony_ci struct ath9k_hw_capabilities *pCap = &ah->caps; 248762306a36Sopenharmony_ci struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); 248862306a36Sopenharmony_ci struct ath_common *common = ath9k_hw_common(ah); 248962306a36Sopenharmony_ci 249062306a36Sopenharmony_ci u16 eeval; 249162306a36Sopenharmony_ci u8 ant_div_ctl1, tx_chainmask, rx_chainmask; 249262306a36Sopenharmony_ci 249362306a36Sopenharmony_ci eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_0); 249462306a36Sopenharmony_ci regulatory->current_rd = eeval; 249562306a36Sopenharmony_ci 249662306a36Sopenharmony_ci if (ah->opmode != NL80211_IFTYPE_AP && 249762306a36Sopenharmony_ci ah->hw_version.subvendorid == AR_SUBVENDOR_ID_NEW_A) { 249862306a36Sopenharmony_ci if (regulatory->current_rd == 0x64 || 249962306a36Sopenharmony_ci regulatory->current_rd == 0x65) 250062306a36Sopenharmony_ci regulatory->current_rd += 5; 250162306a36Sopenharmony_ci else if (regulatory->current_rd == 0x41) 250262306a36Sopenharmony_ci regulatory->current_rd = 0x43; 250362306a36Sopenharmony_ci ath_dbg(common, REGULATORY, "regdomain mapped to 0x%x\n", 250462306a36Sopenharmony_ci regulatory->current_rd); 250562306a36Sopenharmony_ci } 250662306a36Sopenharmony_ci 250762306a36Sopenharmony_ci eeval = ah->eep_ops->get_eeprom(ah, EEP_OP_MODE); 250862306a36Sopenharmony_ci 250962306a36Sopenharmony_ci if (eeval & AR5416_OPFLAGS_11A) { 251062306a36Sopenharmony_ci if (ah->disable_5ghz) 251162306a36Sopenharmony_ci ath_warn(common, "disabling 5GHz band\n"); 251262306a36Sopenharmony_ci else 251362306a36Sopenharmony_ci pCap->hw_caps |= ATH9K_HW_CAP_5GHZ; 251462306a36Sopenharmony_ci } 251562306a36Sopenharmony_ci 251662306a36Sopenharmony_ci if (eeval & AR5416_OPFLAGS_11G) { 251762306a36Sopenharmony_ci if (ah->disable_2ghz) 251862306a36Sopenharmony_ci ath_warn(common, "disabling 2GHz band\n"); 251962306a36Sopenharmony_ci else 252062306a36Sopenharmony_ci pCap->hw_caps |= ATH9K_HW_CAP_2GHZ; 252162306a36Sopenharmony_ci } 252262306a36Sopenharmony_ci 252362306a36Sopenharmony_ci if ((pCap->hw_caps & (ATH9K_HW_CAP_2GHZ | ATH9K_HW_CAP_5GHZ)) == 0) { 252462306a36Sopenharmony_ci ath_err(common, "both bands are disabled\n"); 252562306a36Sopenharmony_ci return -EINVAL; 252662306a36Sopenharmony_ci } 252762306a36Sopenharmony_ci 252862306a36Sopenharmony_ci ath9k_gpio_cap_init(ah); 252962306a36Sopenharmony_ci 253062306a36Sopenharmony_ci if (AR_SREV_9485(ah) || 253162306a36Sopenharmony_ci AR_SREV_9285(ah) || 253262306a36Sopenharmony_ci AR_SREV_9330(ah) || 253362306a36Sopenharmony_ci AR_SREV_9565(ah)) 253462306a36Sopenharmony_ci pCap->chip_chainmask = 1; 253562306a36Sopenharmony_ci else if (!AR_SREV_9280_20_OR_LATER(ah)) 253662306a36Sopenharmony_ci pCap->chip_chainmask = 7; 253762306a36Sopenharmony_ci else if (!AR_SREV_9300_20_OR_LATER(ah) || 253862306a36Sopenharmony_ci AR_SREV_9340(ah) || 253962306a36Sopenharmony_ci AR_SREV_9462(ah) || 254062306a36Sopenharmony_ci AR_SREV_9531(ah)) 254162306a36Sopenharmony_ci pCap->chip_chainmask = 3; 254262306a36Sopenharmony_ci else 254362306a36Sopenharmony_ci pCap->chip_chainmask = 7; 254462306a36Sopenharmony_ci 254562306a36Sopenharmony_ci pCap->tx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_TX_MASK); 254662306a36Sopenharmony_ci /* 254762306a36Sopenharmony_ci * For AR9271 we will temporarilly uses the rx chainmax as read from 254862306a36Sopenharmony_ci * the EEPROM. 254962306a36Sopenharmony_ci */ 255062306a36Sopenharmony_ci if ((ah->hw_version.devid == AR5416_DEVID_PCI) && 255162306a36Sopenharmony_ci !(eeval & AR5416_OPFLAGS_11A) && 255262306a36Sopenharmony_ci !(AR_SREV_9271(ah))) 255362306a36Sopenharmony_ci /* CB71: GPIO 0 is pulled down to indicate 3 rx chains */ 255462306a36Sopenharmony_ci pCap->rx_chainmask = ath9k_hw_gpio_get(ah, 0) ? 0x5 : 0x7; 255562306a36Sopenharmony_ci else if (AR_SREV_9100(ah)) 255662306a36Sopenharmony_ci pCap->rx_chainmask = 0x7; 255762306a36Sopenharmony_ci else 255862306a36Sopenharmony_ci /* Use rx_chainmask from EEPROM. */ 255962306a36Sopenharmony_ci pCap->rx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_RX_MASK); 256062306a36Sopenharmony_ci 256162306a36Sopenharmony_ci pCap->tx_chainmask = fixup_chainmask(pCap->chip_chainmask, pCap->tx_chainmask); 256262306a36Sopenharmony_ci pCap->rx_chainmask = fixup_chainmask(pCap->chip_chainmask, pCap->rx_chainmask); 256362306a36Sopenharmony_ci ah->txchainmask = pCap->tx_chainmask; 256462306a36Sopenharmony_ci ah->rxchainmask = pCap->rx_chainmask; 256562306a36Sopenharmony_ci 256662306a36Sopenharmony_ci ah->misc_mode |= AR_PCU_MIC_NEW_LOC_ENA; 256762306a36Sopenharmony_ci 256862306a36Sopenharmony_ci /* enable key search for every frame in an aggregate */ 256962306a36Sopenharmony_ci if (AR_SREV_9300_20_OR_LATER(ah)) 257062306a36Sopenharmony_ci ah->misc_mode |= AR_PCU_ALWAYS_PERFORM_KEYSEARCH; 257162306a36Sopenharmony_ci 257262306a36Sopenharmony_ci common->crypt_caps |= ATH_CRYPT_CAP_CIPHER_AESCCM; 257362306a36Sopenharmony_ci 257462306a36Sopenharmony_ci if (ah->hw_version.devid != AR2427_DEVID_PCIE) 257562306a36Sopenharmony_ci pCap->hw_caps |= ATH9K_HW_CAP_HT; 257662306a36Sopenharmony_ci else 257762306a36Sopenharmony_ci pCap->hw_caps &= ~ATH9K_HW_CAP_HT; 257862306a36Sopenharmony_ci 257962306a36Sopenharmony_ci if (AR_SREV_9160_10_OR_LATER(ah) || AR_SREV_9100(ah)) 258062306a36Sopenharmony_ci pCap->rts_aggr_limit = ATH_AMPDU_LIMIT_MAX; 258162306a36Sopenharmony_ci else 258262306a36Sopenharmony_ci pCap->rts_aggr_limit = (8 * 1024); 258362306a36Sopenharmony_ci 258462306a36Sopenharmony_ci#ifdef CONFIG_ATH9K_RFKILL 258562306a36Sopenharmony_ci ah->rfsilent = ah->eep_ops->get_eeprom(ah, EEP_RF_SILENT); 258662306a36Sopenharmony_ci if (ah->rfsilent & EEP_RFSILENT_ENABLED) { 258762306a36Sopenharmony_ci ah->rfkill_gpio = 258862306a36Sopenharmony_ci MS(ah->rfsilent, EEP_RFSILENT_GPIO_SEL); 258962306a36Sopenharmony_ci ah->rfkill_polarity = 259062306a36Sopenharmony_ci MS(ah->rfsilent, EEP_RFSILENT_POLARITY); 259162306a36Sopenharmony_ci 259262306a36Sopenharmony_ci pCap->hw_caps |= ATH9K_HW_CAP_RFSILENT; 259362306a36Sopenharmony_ci } 259462306a36Sopenharmony_ci#endif 259562306a36Sopenharmony_ci if (AR_SREV_9271(ah) || AR_SREV_9300_20_OR_LATER(ah)) 259662306a36Sopenharmony_ci pCap->hw_caps |= ATH9K_HW_CAP_AUTOSLEEP; 259762306a36Sopenharmony_ci else 259862306a36Sopenharmony_ci pCap->hw_caps &= ~ATH9K_HW_CAP_AUTOSLEEP; 259962306a36Sopenharmony_ci 260062306a36Sopenharmony_ci if (AR_SREV_9280(ah) || AR_SREV_9285(ah)) 260162306a36Sopenharmony_ci pCap->hw_caps &= ~ATH9K_HW_CAP_4KB_SPLITTRANS; 260262306a36Sopenharmony_ci else 260362306a36Sopenharmony_ci pCap->hw_caps |= ATH9K_HW_CAP_4KB_SPLITTRANS; 260462306a36Sopenharmony_ci 260562306a36Sopenharmony_ci if (AR_SREV_9300_20_OR_LATER(ah)) { 260662306a36Sopenharmony_ci pCap->hw_caps |= ATH9K_HW_CAP_EDMA | ATH9K_HW_CAP_FASTCLOCK; 260762306a36Sopenharmony_ci if (!AR_SREV_9330(ah) && !AR_SREV_9485(ah) && 260862306a36Sopenharmony_ci !AR_SREV_9561(ah) && !AR_SREV_9565(ah)) 260962306a36Sopenharmony_ci pCap->hw_caps |= ATH9K_HW_CAP_LDPC; 261062306a36Sopenharmony_ci 261162306a36Sopenharmony_ci pCap->rx_hp_qdepth = ATH9K_HW_RX_HP_QDEPTH; 261262306a36Sopenharmony_ci pCap->rx_lp_qdepth = ATH9K_HW_RX_LP_QDEPTH; 261362306a36Sopenharmony_ci pCap->rx_status_len = sizeof(struct ar9003_rxs); 261462306a36Sopenharmony_ci pCap->tx_desc_len = sizeof(struct ar9003_txc); 261562306a36Sopenharmony_ci pCap->txs_len = sizeof(struct ar9003_txs); 261662306a36Sopenharmony_ci } else { 261762306a36Sopenharmony_ci pCap->tx_desc_len = sizeof(struct ath_desc); 261862306a36Sopenharmony_ci if (AR_SREV_9280_20(ah)) 261962306a36Sopenharmony_ci pCap->hw_caps |= ATH9K_HW_CAP_FASTCLOCK; 262062306a36Sopenharmony_ci } 262162306a36Sopenharmony_ci 262262306a36Sopenharmony_ci if (AR_SREV_9300_20_OR_LATER(ah)) 262362306a36Sopenharmony_ci pCap->hw_caps |= ATH9K_HW_CAP_RAC_SUPPORTED; 262462306a36Sopenharmony_ci 262562306a36Sopenharmony_ci if (AR_SREV_9561(ah)) 262662306a36Sopenharmony_ci ah->ent_mode = 0x3BDA000; 262762306a36Sopenharmony_ci else if (AR_SREV_9300_20_OR_LATER(ah)) 262862306a36Sopenharmony_ci ah->ent_mode = REG_READ(ah, AR_ENT_OTP); 262962306a36Sopenharmony_ci 263062306a36Sopenharmony_ci if (AR_SREV_9287_11_OR_LATER(ah) || AR_SREV_9271(ah)) 263162306a36Sopenharmony_ci pCap->hw_caps |= ATH9K_HW_CAP_SGI_20; 263262306a36Sopenharmony_ci 263362306a36Sopenharmony_ci if (AR_SREV_9285(ah)) { 263462306a36Sopenharmony_ci if (ah->eep_ops->get_eeprom(ah, EEP_MODAL_VER) >= 3) { 263562306a36Sopenharmony_ci ant_div_ctl1 = 263662306a36Sopenharmony_ci ah->eep_ops->get_eeprom(ah, EEP_ANT_DIV_CTL1); 263762306a36Sopenharmony_ci if ((ant_div_ctl1 & 0x1) && ((ant_div_ctl1 >> 3) & 0x1)) { 263862306a36Sopenharmony_ci pCap->hw_caps |= ATH9K_HW_CAP_ANT_DIV_COMB; 263962306a36Sopenharmony_ci ath_info(common, "Enable LNA combining\n"); 264062306a36Sopenharmony_ci } 264162306a36Sopenharmony_ci } 264262306a36Sopenharmony_ci } 264362306a36Sopenharmony_ci 264462306a36Sopenharmony_ci if (AR_SREV_9300_20_OR_LATER(ah)) { 264562306a36Sopenharmony_ci if (ah->eep_ops->get_eeprom(ah, EEP_CHAIN_MASK_REDUCE)) 264662306a36Sopenharmony_ci pCap->hw_caps |= ATH9K_HW_CAP_APM; 264762306a36Sopenharmony_ci } 264862306a36Sopenharmony_ci 264962306a36Sopenharmony_ci if (AR_SREV_9330(ah) || AR_SREV_9485(ah) || AR_SREV_9565(ah)) { 265062306a36Sopenharmony_ci ant_div_ctl1 = ah->eep_ops->get_eeprom(ah, EEP_ANT_DIV_CTL1); 265162306a36Sopenharmony_ci if ((ant_div_ctl1 >> 0x6) == 0x3) { 265262306a36Sopenharmony_ci pCap->hw_caps |= ATH9K_HW_CAP_ANT_DIV_COMB; 265362306a36Sopenharmony_ci ath_info(common, "Enable LNA combining\n"); 265462306a36Sopenharmony_ci } 265562306a36Sopenharmony_ci } 265662306a36Sopenharmony_ci 265762306a36Sopenharmony_ci if (ath9k_hw_dfs_tested(ah)) 265862306a36Sopenharmony_ci pCap->hw_caps |= ATH9K_HW_CAP_DFS; 265962306a36Sopenharmony_ci 266062306a36Sopenharmony_ci tx_chainmask = pCap->tx_chainmask; 266162306a36Sopenharmony_ci rx_chainmask = pCap->rx_chainmask; 266262306a36Sopenharmony_ci while (tx_chainmask || rx_chainmask) { 266362306a36Sopenharmony_ci if (tx_chainmask & BIT(0)) 266462306a36Sopenharmony_ci pCap->max_txchains++; 266562306a36Sopenharmony_ci if (rx_chainmask & BIT(0)) 266662306a36Sopenharmony_ci pCap->max_rxchains++; 266762306a36Sopenharmony_ci 266862306a36Sopenharmony_ci tx_chainmask >>= 1; 266962306a36Sopenharmony_ci rx_chainmask >>= 1; 267062306a36Sopenharmony_ci } 267162306a36Sopenharmony_ci 267262306a36Sopenharmony_ci if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) { 267362306a36Sopenharmony_ci if (!(ah->ent_mode & AR_ENT_OTP_49GHZ_DISABLE)) 267462306a36Sopenharmony_ci pCap->hw_caps |= ATH9K_HW_CAP_MCI; 267562306a36Sopenharmony_ci 267662306a36Sopenharmony_ci if (AR_SREV_9462_20_OR_LATER(ah)) 267762306a36Sopenharmony_ci pCap->hw_caps |= ATH9K_HW_CAP_RTT; 267862306a36Sopenharmony_ci } 267962306a36Sopenharmony_ci 268062306a36Sopenharmony_ci if (AR_SREV_9300_20_OR_LATER(ah) && 268162306a36Sopenharmony_ci ah->eep_ops->get_eeprom(ah, EEP_PAPRD)) 268262306a36Sopenharmony_ci pCap->hw_caps |= ATH9K_HW_CAP_PAPRD; 268362306a36Sopenharmony_ci 268462306a36Sopenharmony_ci#ifdef CONFIG_ATH9K_WOW 268562306a36Sopenharmony_ci if (AR_SREV_9462_20_OR_LATER(ah) || AR_SREV_9565_11_OR_LATER(ah)) 268662306a36Sopenharmony_ci ah->wow.max_patterns = MAX_NUM_PATTERN; 268762306a36Sopenharmony_ci else 268862306a36Sopenharmony_ci ah->wow.max_patterns = MAX_NUM_PATTERN_LEGACY; 268962306a36Sopenharmony_ci#endif 269062306a36Sopenharmony_ci 269162306a36Sopenharmony_ci return 0; 269262306a36Sopenharmony_ci} 269362306a36Sopenharmony_ci 269462306a36Sopenharmony_ci/****************************/ 269562306a36Sopenharmony_ci/* GPIO / RFKILL / Antennae */ 269662306a36Sopenharmony_ci/****************************/ 269762306a36Sopenharmony_ci 269862306a36Sopenharmony_cistatic void ath9k_hw_gpio_cfg_output_mux(struct ath_hw *ah, u32 gpio, u32 type) 269962306a36Sopenharmony_ci{ 270062306a36Sopenharmony_ci int addr; 270162306a36Sopenharmony_ci u32 gpio_shift, tmp; 270262306a36Sopenharmony_ci 270362306a36Sopenharmony_ci if (gpio > 11) 270462306a36Sopenharmony_ci addr = AR_GPIO_OUTPUT_MUX3(ah); 270562306a36Sopenharmony_ci else if (gpio > 5) 270662306a36Sopenharmony_ci addr = AR_GPIO_OUTPUT_MUX2(ah); 270762306a36Sopenharmony_ci else 270862306a36Sopenharmony_ci addr = AR_GPIO_OUTPUT_MUX1(ah); 270962306a36Sopenharmony_ci 271062306a36Sopenharmony_ci gpio_shift = (gpio % 6) * 5; 271162306a36Sopenharmony_ci 271262306a36Sopenharmony_ci if (AR_SREV_9280_20_OR_LATER(ah) || 271362306a36Sopenharmony_ci (addr != AR_GPIO_OUTPUT_MUX1(ah))) { 271462306a36Sopenharmony_ci REG_RMW(ah, addr, (type << gpio_shift), 271562306a36Sopenharmony_ci (0x1f << gpio_shift)); 271662306a36Sopenharmony_ci } else { 271762306a36Sopenharmony_ci tmp = REG_READ(ah, addr); 271862306a36Sopenharmony_ci tmp = ((tmp & 0x1F0) << 1) | (tmp & ~0x1F0); 271962306a36Sopenharmony_ci tmp &= ~(0x1f << gpio_shift); 272062306a36Sopenharmony_ci tmp |= (type << gpio_shift); 272162306a36Sopenharmony_ci REG_WRITE(ah, addr, tmp); 272262306a36Sopenharmony_ci } 272362306a36Sopenharmony_ci} 272462306a36Sopenharmony_ci 272562306a36Sopenharmony_ci/* BSP should set the corresponding MUX register correctly. 272662306a36Sopenharmony_ci */ 272762306a36Sopenharmony_cistatic void ath9k_hw_gpio_cfg_soc(struct ath_hw *ah, u32 gpio, bool out, 272862306a36Sopenharmony_ci const char *label) 272962306a36Sopenharmony_ci{ 273062306a36Sopenharmony_ci int err; 273162306a36Sopenharmony_ci 273262306a36Sopenharmony_ci if (ah->caps.gpio_requested & BIT(gpio)) 273362306a36Sopenharmony_ci return; 273462306a36Sopenharmony_ci 273562306a36Sopenharmony_ci err = gpio_request_one(gpio, out ? GPIOF_OUT_INIT_LOW : GPIOF_IN, label); 273662306a36Sopenharmony_ci if (err) { 273762306a36Sopenharmony_ci ath_err(ath9k_hw_common(ah), "request GPIO%d failed:%d\n", 273862306a36Sopenharmony_ci gpio, err); 273962306a36Sopenharmony_ci return; 274062306a36Sopenharmony_ci } 274162306a36Sopenharmony_ci 274262306a36Sopenharmony_ci ah->caps.gpio_requested |= BIT(gpio); 274362306a36Sopenharmony_ci} 274462306a36Sopenharmony_ci 274562306a36Sopenharmony_cistatic void ath9k_hw_gpio_cfg_wmac(struct ath_hw *ah, u32 gpio, bool out, 274662306a36Sopenharmony_ci u32 ah_signal_type) 274762306a36Sopenharmony_ci{ 274862306a36Sopenharmony_ci u32 gpio_set, gpio_shift = gpio; 274962306a36Sopenharmony_ci 275062306a36Sopenharmony_ci if (AR_DEVID_7010(ah)) { 275162306a36Sopenharmony_ci gpio_set = out ? 275262306a36Sopenharmony_ci AR7010_GPIO_OE_AS_OUTPUT : AR7010_GPIO_OE_AS_INPUT; 275362306a36Sopenharmony_ci REG_RMW(ah, AR7010_GPIO_OE, gpio_set << gpio_shift, 275462306a36Sopenharmony_ci AR7010_GPIO_OE_MASK << gpio_shift); 275562306a36Sopenharmony_ci } else if (AR_SREV_SOC(ah)) { 275662306a36Sopenharmony_ci gpio_set = out ? 1 : 0; 275762306a36Sopenharmony_ci REG_RMW(ah, AR_GPIO_OE_OUT(ah), gpio_set << gpio_shift, 275862306a36Sopenharmony_ci gpio_set << gpio_shift); 275962306a36Sopenharmony_ci } else { 276062306a36Sopenharmony_ci gpio_shift = gpio << 1; 276162306a36Sopenharmony_ci gpio_set = out ? 276262306a36Sopenharmony_ci AR_GPIO_OE_OUT_DRV_ALL : AR_GPIO_OE_OUT_DRV_NO; 276362306a36Sopenharmony_ci REG_RMW(ah, AR_GPIO_OE_OUT(ah), gpio_set << gpio_shift, 276462306a36Sopenharmony_ci AR_GPIO_OE_OUT_DRV << gpio_shift); 276562306a36Sopenharmony_ci 276662306a36Sopenharmony_ci if (out) 276762306a36Sopenharmony_ci ath9k_hw_gpio_cfg_output_mux(ah, gpio, ah_signal_type); 276862306a36Sopenharmony_ci } 276962306a36Sopenharmony_ci} 277062306a36Sopenharmony_ci 277162306a36Sopenharmony_cistatic void ath9k_hw_gpio_request(struct ath_hw *ah, u32 gpio, bool out, 277262306a36Sopenharmony_ci const char *label, u32 ah_signal_type) 277362306a36Sopenharmony_ci{ 277462306a36Sopenharmony_ci WARN_ON(gpio >= ah->caps.num_gpio_pins); 277562306a36Sopenharmony_ci 277662306a36Sopenharmony_ci if (BIT(gpio) & ah->caps.gpio_mask) 277762306a36Sopenharmony_ci ath9k_hw_gpio_cfg_wmac(ah, gpio, out, ah_signal_type); 277862306a36Sopenharmony_ci else if (AR_SREV_SOC(ah)) 277962306a36Sopenharmony_ci ath9k_hw_gpio_cfg_soc(ah, gpio, out, label); 278062306a36Sopenharmony_ci else 278162306a36Sopenharmony_ci WARN_ON(1); 278262306a36Sopenharmony_ci} 278362306a36Sopenharmony_ci 278462306a36Sopenharmony_civoid ath9k_hw_gpio_request_in(struct ath_hw *ah, u32 gpio, const char *label) 278562306a36Sopenharmony_ci{ 278662306a36Sopenharmony_ci ath9k_hw_gpio_request(ah, gpio, false, label, 0); 278762306a36Sopenharmony_ci} 278862306a36Sopenharmony_ciEXPORT_SYMBOL(ath9k_hw_gpio_request_in); 278962306a36Sopenharmony_ci 279062306a36Sopenharmony_civoid ath9k_hw_gpio_request_out(struct ath_hw *ah, u32 gpio, const char *label, 279162306a36Sopenharmony_ci u32 ah_signal_type) 279262306a36Sopenharmony_ci{ 279362306a36Sopenharmony_ci ath9k_hw_gpio_request(ah, gpio, true, label, ah_signal_type); 279462306a36Sopenharmony_ci} 279562306a36Sopenharmony_ciEXPORT_SYMBOL(ath9k_hw_gpio_request_out); 279662306a36Sopenharmony_ci 279762306a36Sopenharmony_civoid ath9k_hw_gpio_free(struct ath_hw *ah, u32 gpio) 279862306a36Sopenharmony_ci{ 279962306a36Sopenharmony_ci if (!AR_SREV_SOC(ah)) 280062306a36Sopenharmony_ci return; 280162306a36Sopenharmony_ci 280262306a36Sopenharmony_ci WARN_ON(gpio >= ah->caps.num_gpio_pins); 280362306a36Sopenharmony_ci 280462306a36Sopenharmony_ci if (ah->caps.gpio_requested & BIT(gpio)) { 280562306a36Sopenharmony_ci gpio_free(gpio); 280662306a36Sopenharmony_ci ah->caps.gpio_requested &= ~BIT(gpio); 280762306a36Sopenharmony_ci } 280862306a36Sopenharmony_ci} 280962306a36Sopenharmony_ciEXPORT_SYMBOL(ath9k_hw_gpio_free); 281062306a36Sopenharmony_ci 281162306a36Sopenharmony_ciu32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio) 281262306a36Sopenharmony_ci{ 281362306a36Sopenharmony_ci u32 val = 0xffffffff; 281462306a36Sopenharmony_ci 281562306a36Sopenharmony_ci#define MS_REG_READ(x, y) \ 281662306a36Sopenharmony_ci (MS(REG_READ(ah, AR_GPIO_IN_OUT(ah)), x##_GPIO_IN_VAL) & BIT(y)) 281762306a36Sopenharmony_ci 281862306a36Sopenharmony_ci WARN_ON(gpio >= ah->caps.num_gpio_pins); 281962306a36Sopenharmony_ci 282062306a36Sopenharmony_ci if (BIT(gpio) & ah->caps.gpio_mask) { 282162306a36Sopenharmony_ci if (AR_SREV_9271(ah)) 282262306a36Sopenharmony_ci val = MS_REG_READ(AR9271, gpio); 282362306a36Sopenharmony_ci else if (AR_SREV_9287(ah)) 282462306a36Sopenharmony_ci val = MS_REG_READ(AR9287, gpio); 282562306a36Sopenharmony_ci else if (AR_SREV_9285(ah)) 282662306a36Sopenharmony_ci val = MS_REG_READ(AR9285, gpio); 282762306a36Sopenharmony_ci else if (AR_SREV_9280(ah)) 282862306a36Sopenharmony_ci val = MS_REG_READ(AR928X, gpio); 282962306a36Sopenharmony_ci else if (AR_DEVID_7010(ah)) 283062306a36Sopenharmony_ci val = REG_READ(ah, AR7010_GPIO_IN) & BIT(gpio); 283162306a36Sopenharmony_ci else if (AR_SREV_9300_20_OR_LATER(ah)) 283262306a36Sopenharmony_ci val = REG_READ(ah, AR_GPIO_IN(ah)) & BIT(gpio); 283362306a36Sopenharmony_ci else 283462306a36Sopenharmony_ci val = MS_REG_READ(AR, gpio); 283562306a36Sopenharmony_ci } else if (BIT(gpio) & ah->caps.gpio_requested) { 283662306a36Sopenharmony_ci val = gpio_get_value(gpio) & BIT(gpio); 283762306a36Sopenharmony_ci } else { 283862306a36Sopenharmony_ci WARN_ON(1); 283962306a36Sopenharmony_ci } 284062306a36Sopenharmony_ci 284162306a36Sopenharmony_ci return !!val; 284262306a36Sopenharmony_ci} 284362306a36Sopenharmony_ciEXPORT_SYMBOL(ath9k_hw_gpio_get); 284462306a36Sopenharmony_ci 284562306a36Sopenharmony_civoid ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val) 284662306a36Sopenharmony_ci{ 284762306a36Sopenharmony_ci WARN_ON(gpio >= ah->caps.num_gpio_pins); 284862306a36Sopenharmony_ci 284962306a36Sopenharmony_ci if (AR_DEVID_7010(ah) || AR_SREV_9271(ah)) 285062306a36Sopenharmony_ci val = !val; 285162306a36Sopenharmony_ci else 285262306a36Sopenharmony_ci val = !!val; 285362306a36Sopenharmony_ci 285462306a36Sopenharmony_ci if (BIT(gpio) & ah->caps.gpio_mask) { 285562306a36Sopenharmony_ci u32 out_addr = AR_DEVID_7010(ah) ? 285662306a36Sopenharmony_ci AR7010_GPIO_OUT : AR_GPIO_IN_OUT(ah); 285762306a36Sopenharmony_ci 285862306a36Sopenharmony_ci REG_RMW(ah, out_addr, val << gpio, BIT(gpio)); 285962306a36Sopenharmony_ci } else if (BIT(gpio) & ah->caps.gpio_requested) { 286062306a36Sopenharmony_ci gpio_set_value(gpio, val); 286162306a36Sopenharmony_ci } else { 286262306a36Sopenharmony_ci WARN_ON(1); 286362306a36Sopenharmony_ci } 286462306a36Sopenharmony_ci} 286562306a36Sopenharmony_ciEXPORT_SYMBOL(ath9k_hw_set_gpio); 286662306a36Sopenharmony_ci 286762306a36Sopenharmony_civoid ath9k_hw_setantenna(struct ath_hw *ah, u32 antenna) 286862306a36Sopenharmony_ci{ 286962306a36Sopenharmony_ci REG_WRITE(ah, AR_DEF_ANTENNA, (antenna & 0x7)); 287062306a36Sopenharmony_ci} 287162306a36Sopenharmony_ciEXPORT_SYMBOL(ath9k_hw_setantenna); 287262306a36Sopenharmony_ci 287362306a36Sopenharmony_ci/*********************/ 287462306a36Sopenharmony_ci/* General Operation */ 287562306a36Sopenharmony_ci/*********************/ 287662306a36Sopenharmony_ci 287762306a36Sopenharmony_ciu32 ath9k_hw_getrxfilter(struct ath_hw *ah) 287862306a36Sopenharmony_ci{ 287962306a36Sopenharmony_ci u32 bits = REG_READ(ah, AR_RX_FILTER); 288062306a36Sopenharmony_ci u32 phybits = REG_READ(ah, AR_PHY_ERR); 288162306a36Sopenharmony_ci 288262306a36Sopenharmony_ci if (phybits & AR_PHY_ERR_RADAR) 288362306a36Sopenharmony_ci bits |= ATH9K_RX_FILTER_PHYRADAR; 288462306a36Sopenharmony_ci if (phybits & (AR_PHY_ERR_OFDM_TIMING | AR_PHY_ERR_CCK_TIMING)) 288562306a36Sopenharmony_ci bits |= ATH9K_RX_FILTER_PHYERR; 288662306a36Sopenharmony_ci 288762306a36Sopenharmony_ci return bits; 288862306a36Sopenharmony_ci} 288962306a36Sopenharmony_ciEXPORT_SYMBOL(ath9k_hw_getrxfilter); 289062306a36Sopenharmony_ci 289162306a36Sopenharmony_civoid ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits) 289262306a36Sopenharmony_ci{ 289362306a36Sopenharmony_ci u32 phybits; 289462306a36Sopenharmony_ci 289562306a36Sopenharmony_ci ENABLE_REGWRITE_BUFFER(ah); 289662306a36Sopenharmony_ci 289762306a36Sopenharmony_ci REG_WRITE(ah, AR_RX_FILTER, bits); 289862306a36Sopenharmony_ci 289962306a36Sopenharmony_ci phybits = 0; 290062306a36Sopenharmony_ci if (bits & ATH9K_RX_FILTER_PHYRADAR) 290162306a36Sopenharmony_ci phybits |= AR_PHY_ERR_RADAR; 290262306a36Sopenharmony_ci if (bits & ATH9K_RX_FILTER_PHYERR) 290362306a36Sopenharmony_ci phybits |= AR_PHY_ERR_OFDM_TIMING | AR_PHY_ERR_CCK_TIMING; 290462306a36Sopenharmony_ci REG_WRITE(ah, AR_PHY_ERR, phybits); 290562306a36Sopenharmony_ci 290662306a36Sopenharmony_ci if (phybits) 290762306a36Sopenharmony_ci REG_SET_BIT(ah, AR_RXCFG, AR_RXCFG_ZLFDMA); 290862306a36Sopenharmony_ci else 290962306a36Sopenharmony_ci REG_CLR_BIT(ah, AR_RXCFG, AR_RXCFG_ZLFDMA); 291062306a36Sopenharmony_ci 291162306a36Sopenharmony_ci REGWRITE_BUFFER_FLUSH(ah); 291262306a36Sopenharmony_ci} 291362306a36Sopenharmony_ciEXPORT_SYMBOL(ath9k_hw_setrxfilter); 291462306a36Sopenharmony_ci 291562306a36Sopenharmony_cibool ath9k_hw_phy_disable(struct ath_hw *ah) 291662306a36Sopenharmony_ci{ 291762306a36Sopenharmony_ci if (ath9k_hw_mci_is_enabled(ah)) 291862306a36Sopenharmony_ci ar9003_mci_bt_gain_ctrl(ah); 291962306a36Sopenharmony_ci 292062306a36Sopenharmony_ci if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM)) 292162306a36Sopenharmony_ci return false; 292262306a36Sopenharmony_ci 292362306a36Sopenharmony_ci ath9k_hw_init_pll(ah, NULL); 292462306a36Sopenharmony_ci ah->htc_reset_init = true; 292562306a36Sopenharmony_ci return true; 292662306a36Sopenharmony_ci} 292762306a36Sopenharmony_ciEXPORT_SYMBOL(ath9k_hw_phy_disable); 292862306a36Sopenharmony_ci 292962306a36Sopenharmony_cibool ath9k_hw_disable(struct ath_hw *ah) 293062306a36Sopenharmony_ci{ 293162306a36Sopenharmony_ci if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) 293262306a36Sopenharmony_ci return false; 293362306a36Sopenharmony_ci 293462306a36Sopenharmony_ci if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_COLD)) 293562306a36Sopenharmony_ci return false; 293662306a36Sopenharmony_ci 293762306a36Sopenharmony_ci ath9k_hw_init_pll(ah, NULL); 293862306a36Sopenharmony_ci return true; 293962306a36Sopenharmony_ci} 294062306a36Sopenharmony_ciEXPORT_SYMBOL(ath9k_hw_disable); 294162306a36Sopenharmony_ci 294262306a36Sopenharmony_cistatic int get_antenna_gain(struct ath_hw *ah, struct ath9k_channel *chan) 294362306a36Sopenharmony_ci{ 294462306a36Sopenharmony_ci enum eeprom_param gain_param; 294562306a36Sopenharmony_ci 294662306a36Sopenharmony_ci if (IS_CHAN_2GHZ(chan)) 294762306a36Sopenharmony_ci gain_param = EEP_ANTENNA_GAIN_2G; 294862306a36Sopenharmony_ci else 294962306a36Sopenharmony_ci gain_param = EEP_ANTENNA_GAIN_5G; 295062306a36Sopenharmony_ci 295162306a36Sopenharmony_ci return ah->eep_ops->get_eeprom(ah, gain_param); 295262306a36Sopenharmony_ci} 295362306a36Sopenharmony_ci 295462306a36Sopenharmony_civoid ath9k_hw_apply_txpower(struct ath_hw *ah, struct ath9k_channel *chan, 295562306a36Sopenharmony_ci bool test) 295662306a36Sopenharmony_ci{ 295762306a36Sopenharmony_ci struct ath_regulatory *reg = ath9k_hw_regulatory(ah); 295862306a36Sopenharmony_ci struct ieee80211_channel *channel; 295962306a36Sopenharmony_ci int chan_pwr, new_pwr; 296062306a36Sopenharmony_ci u16 ctl = NO_CTL; 296162306a36Sopenharmony_ci 296262306a36Sopenharmony_ci if (!chan) 296362306a36Sopenharmony_ci return; 296462306a36Sopenharmony_ci 296562306a36Sopenharmony_ci if (!test) 296662306a36Sopenharmony_ci ctl = ath9k_regd_get_ctl(reg, chan); 296762306a36Sopenharmony_ci 296862306a36Sopenharmony_ci channel = chan->chan; 296962306a36Sopenharmony_ci chan_pwr = min_t(int, channel->max_power * 2, MAX_COMBINED_POWER); 297062306a36Sopenharmony_ci new_pwr = min_t(int, chan_pwr, reg->power_limit); 297162306a36Sopenharmony_ci 297262306a36Sopenharmony_ci ah->eep_ops->set_txpower(ah, chan, ctl, 297362306a36Sopenharmony_ci get_antenna_gain(ah, chan), new_pwr, test); 297462306a36Sopenharmony_ci} 297562306a36Sopenharmony_ci 297662306a36Sopenharmony_civoid ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test) 297762306a36Sopenharmony_ci{ 297862306a36Sopenharmony_ci struct ath_regulatory *reg = ath9k_hw_regulatory(ah); 297962306a36Sopenharmony_ci struct ath9k_channel *chan = ah->curchan; 298062306a36Sopenharmony_ci struct ieee80211_channel *channel = chan->chan; 298162306a36Sopenharmony_ci 298262306a36Sopenharmony_ci reg->power_limit = min_t(u32, limit, MAX_COMBINED_POWER); 298362306a36Sopenharmony_ci if (test) 298462306a36Sopenharmony_ci channel->max_power = MAX_COMBINED_POWER / 2; 298562306a36Sopenharmony_ci 298662306a36Sopenharmony_ci ath9k_hw_apply_txpower(ah, chan, test); 298762306a36Sopenharmony_ci 298862306a36Sopenharmony_ci if (test) 298962306a36Sopenharmony_ci channel->max_power = DIV_ROUND_UP(reg->max_power_level, 2); 299062306a36Sopenharmony_ci} 299162306a36Sopenharmony_ciEXPORT_SYMBOL(ath9k_hw_set_txpowerlimit); 299262306a36Sopenharmony_ci 299362306a36Sopenharmony_civoid ath9k_hw_setopmode(struct ath_hw *ah) 299462306a36Sopenharmony_ci{ 299562306a36Sopenharmony_ci ath9k_hw_set_operating_mode(ah, ah->opmode); 299662306a36Sopenharmony_ci} 299762306a36Sopenharmony_ciEXPORT_SYMBOL(ath9k_hw_setopmode); 299862306a36Sopenharmony_ci 299962306a36Sopenharmony_civoid ath9k_hw_setmcastfilter(struct ath_hw *ah, u32 filter0, u32 filter1) 300062306a36Sopenharmony_ci{ 300162306a36Sopenharmony_ci REG_WRITE(ah, AR_MCAST_FIL0, filter0); 300262306a36Sopenharmony_ci REG_WRITE(ah, AR_MCAST_FIL1, filter1); 300362306a36Sopenharmony_ci} 300462306a36Sopenharmony_ciEXPORT_SYMBOL(ath9k_hw_setmcastfilter); 300562306a36Sopenharmony_ci 300662306a36Sopenharmony_civoid ath9k_hw_write_associd(struct ath_hw *ah) 300762306a36Sopenharmony_ci{ 300862306a36Sopenharmony_ci struct ath_common *common = ath9k_hw_common(ah); 300962306a36Sopenharmony_ci 301062306a36Sopenharmony_ci REG_WRITE(ah, AR_BSS_ID0, get_unaligned_le32(common->curbssid)); 301162306a36Sopenharmony_ci REG_WRITE(ah, AR_BSS_ID1, get_unaligned_le16(common->curbssid + 4) | 301262306a36Sopenharmony_ci ((common->curaid & 0x3fff) << AR_BSS_ID1_AID_S)); 301362306a36Sopenharmony_ci} 301462306a36Sopenharmony_ciEXPORT_SYMBOL(ath9k_hw_write_associd); 301562306a36Sopenharmony_ci 301662306a36Sopenharmony_ci#define ATH9K_MAX_TSF_READ 10 301762306a36Sopenharmony_ci 301862306a36Sopenharmony_ciu64 ath9k_hw_gettsf64(struct ath_hw *ah) 301962306a36Sopenharmony_ci{ 302062306a36Sopenharmony_ci u32 tsf_lower, tsf_upper1, tsf_upper2; 302162306a36Sopenharmony_ci int i; 302262306a36Sopenharmony_ci 302362306a36Sopenharmony_ci tsf_upper1 = REG_READ(ah, AR_TSF_U32); 302462306a36Sopenharmony_ci for (i = 0; i < ATH9K_MAX_TSF_READ; i++) { 302562306a36Sopenharmony_ci tsf_lower = REG_READ(ah, AR_TSF_L32); 302662306a36Sopenharmony_ci tsf_upper2 = REG_READ(ah, AR_TSF_U32); 302762306a36Sopenharmony_ci if (tsf_upper2 == tsf_upper1) 302862306a36Sopenharmony_ci break; 302962306a36Sopenharmony_ci tsf_upper1 = tsf_upper2; 303062306a36Sopenharmony_ci } 303162306a36Sopenharmony_ci 303262306a36Sopenharmony_ci WARN_ON( i == ATH9K_MAX_TSF_READ ); 303362306a36Sopenharmony_ci 303462306a36Sopenharmony_ci return (((u64)tsf_upper1 << 32) | tsf_lower); 303562306a36Sopenharmony_ci} 303662306a36Sopenharmony_ciEXPORT_SYMBOL(ath9k_hw_gettsf64); 303762306a36Sopenharmony_ci 303862306a36Sopenharmony_civoid ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64) 303962306a36Sopenharmony_ci{ 304062306a36Sopenharmony_ci REG_WRITE(ah, AR_TSF_L32, tsf64 & 0xffffffff); 304162306a36Sopenharmony_ci REG_WRITE(ah, AR_TSF_U32, (tsf64 >> 32) & 0xffffffff); 304262306a36Sopenharmony_ci} 304362306a36Sopenharmony_ciEXPORT_SYMBOL(ath9k_hw_settsf64); 304462306a36Sopenharmony_ci 304562306a36Sopenharmony_civoid ath9k_hw_reset_tsf(struct ath_hw *ah) 304662306a36Sopenharmony_ci{ 304762306a36Sopenharmony_ci if (!ath9k_hw_wait(ah, AR_SLP32_MODE, AR_SLP32_TSF_WRITE_STATUS, 0, 304862306a36Sopenharmony_ci AH_TSF_WRITE_TIMEOUT)) 304962306a36Sopenharmony_ci ath_dbg(ath9k_hw_common(ah), RESET, 305062306a36Sopenharmony_ci "AR_SLP32_TSF_WRITE_STATUS limit exceeded\n"); 305162306a36Sopenharmony_ci 305262306a36Sopenharmony_ci REG_WRITE(ah, AR_RESET_TSF, AR_RESET_TSF_ONCE); 305362306a36Sopenharmony_ci} 305462306a36Sopenharmony_ciEXPORT_SYMBOL(ath9k_hw_reset_tsf); 305562306a36Sopenharmony_ci 305662306a36Sopenharmony_civoid ath9k_hw_set_tsfadjust(struct ath_hw *ah, bool set) 305762306a36Sopenharmony_ci{ 305862306a36Sopenharmony_ci if (set) 305962306a36Sopenharmony_ci ah->misc_mode |= AR_PCU_TX_ADD_TSF; 306062306a36Sopenharmony_ci else 306162306a36Sopenharmony_ci ah->misc_mode &= ~AR_PCU_TX_ADD_TSF; 306262306a36Sopenharmony_ci} 306362306a36Sopenharmony_ciEXPORT_SYMBOL(ath9k_hw_set_tsfadjust); 306462306a36Sopenharmony_ci 306562306a36Sopenharmony_civoid ath9k_hw_set11nmac2040(struct ath_hw *ah, struct ath9k_channel *chan) 306662306a36Sopenharmony_ci{ 306762306a36Sopenharmony_ci u32 macmode; 306862306a36Sopenharmony_ci 306962306a36Sopenharmony_ci if (IS_CHAN_HT40(chan) && !ah->config.cwm_ignore_extcca) 307062306a36Sopenharmony_ci macmode = AR_2040_JOINED_RX_CLEAR; 307162306a36Sopenharmony_ci else 307262306a36Sopenharmony_ci macmode = 0; 307362306a36Sopenharmony_ci 307462306a36Sopenharmony_ci REG_WRITE(ah, AR_2040_MODE, macmode); 307562306a36Sopenharmony_ci} 307662306a36Sopenharmony_ci 307762306a36Sopenharmony_ci/* HW Generic timers configuration */ 307862306a36Sopenharmony_ci 307962306a36Sopenharmony_cistatic const struct ath_gen_timer_configuration gen_tmr_configuration[] = 308062306a36Sopenharmony_ci{ 308162306a36Sopenharmony_ci {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080}, 308262306a36Sopenharmony_ci {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080}, 308362306a36Sopenharmony_ci {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080}, 308462306a36Sopenharmony_ci {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080}, 308562306a36Sopenharmony_ci {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080}, 308662306a36Sopenharmony_ci {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080}, 308762306a36Sopenharmony_ci {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080}, 308862306a36Sopenharmony_ci {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080}, 308962306a36Sopenharmony_ci {AR_NEXT_NDP2_TIMER, AR_NDP2_PERIOD, AR_NDP2_TIMER_MODE, 0x0001}, 309062306a36Sopenharmony_ci {AR_NEXT_NDP2_TIMER + 1*4, AR_NDP2_PERIOD + 1*4, 309162306a36Sopenharmony_ci AR_NDP2_TIMER_MODE, 0x0002}, 309262306a36Sopenharmony_ci {AR_NEXT_NDP2_TIMER + 2*4, AR_NDP2_PERIOD + 2*4, 309362306a36Sopenharmony_ci AR_NDP2_TIMER_MODE, 0x0004}, 309462306a36Sopenharmony_ci {AR_NEXT_NDP2_TIMER + 3*4, AR_NDP2_PERIOD + 3*4, 309562306a36Sopenharmony_ci AR_NDP2_TIMER_MODE, 0x0008}, 309662306a36Sopenharmony_ci {AR_NEXT_NDP2_TIMER + 4*4, AR_NDP2_PERIOD + 4*4, 309762306a36Sopenharmony_ci AR_NDP2_TIMER_MODE, 0x0010}, 309862306a36Sopenharmony_ci {AR_NEXT_NDP2_TIMER + 5*4, AR_NDP2_PERIOD + 5*4, 309962306a36Sopenharmony_ci AR_NDP2_TIMER_MODE, 0x0020}, 310062306a36Sopenharmony_ci {AR_NEXT_NDP2_TIMER + 6*4, AR_NDP2_PERIOD + 6*4, 310162306a36Sopenharmony_ci AR_NDP2_TIMER_MODE, 0x0040}, 310262306a36Sopenharmony_ci {AR_NEXT_NDP2_TIMER + 7*4, AR_NDP2_PERIOD + 7*4, 310362306a36Sopenharmony_ci AR_NDP2_TIMER_MODE, 0x0080} 310462306a36Sopenharmony_ci}; 310562306a36Sopenharmony_ci 310662306a36Sopenharmony_ci/* HW generic timer primitives */ 310762306a36Sopenharmony_ci 310862306a36Sopenharmony_ciu32 ath9k_hw_gettsf32(struct ath_hw *ah) 310962306a36Sopenharmony_ci{ 311062306a36Sopenharmony_ci return REG_READ(ah, AR_TSF_L32); 311162306a36Sopenharmony_ci} 311262306a36Sopenharmony_ciEXPORT_SYMBOL(ath9k_hw_gettsf32); 311362306a36Sopenharmony_ci 311462306a36Sopenharmony_civoid ath9k_hw_gen_timer_start_tsf2(struct ath_hw *ah) 311562306a36Sopenharmony_ci{ 311662306a36Sopenharmony_ci struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers; 311762306a36Sopenharmony_ci 311862306a36Sopenharmony_ci if (timer_table->tsf2_enabled) { 311962306a36Sopenharmony_ci REG_SET_BIT(ah, AR_DIRECT_CONNECT, AR_DC_AP_STA_EN); 312062306a36Sopenharmony_ci REG_SET_BIT(ah, AR_RESET_TSF, AR_RESET_TSF2_ONCE); 312162306a36Sopenharmony_ci } 312262306a36Sopenharmony_ci} 312362306a36Sopenharmony_ci 312462306a36Sopenharmony_cistruct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah, 312562306a36Sopenharmony_ci void (*trigger)(void *), 312662306a36Sopenharmony_ci void (*overflow)(void *), 312762306a36Sopenharmony_ci void *arg, 312862306a36Sopenharmony_ci u8 timer_index) 312962306a36Sopenharmony_ci{ 313062306a36Sopenharmony_ci struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers; 313162306a36Sopenharmony_ci struct ath_gen_timer *timer; 313262306a36Sopenharmony_ci 313362306a36Sopenharmony_ci if ((timer_index < AR_FIRST_NDP_TIMER) || 313462306a36Sopenharmony_ci (timer_index >= ATH_MAX_GEN_TIMER)) 313562306a36Sopenharmony_ci return NULL; 313662306a36Sopenharmony_ci 313762306a36Sopenharmony_ci if ((timer_index > AR_FIRST_NDP_TIMER) && 313862306a36Sopenharmony_ci !AR_SREV_9300_20_OR_LATER(ah)) 313962306a36Sopenharmony_ci return NULL; 314062306a36Sopenharmony_ci 314162306a36Sopenharmony_ci timer = kzalloc(sizeof(struct ath_gen_timer), GFP_KERNEL); 314262306a36Sopenharmony_ci if (timer == NULL) 314362306a36Sopenharmony_ci return NULL; 314462306a36Sopenharmony_ci 314562306a36Sopenharmony_ci /* allocate a hardware generic timer slot */ 314662306a36Sopenharmony_ci timer_table->timers[timer_index] = timer; 314762306a36Sopenharmony_ci timer->index = timer_index; 314862306a36Sopenharmony_ci timer->trigger = trigger; 314962306a36Sopenharmony_ci timer->overflow = overflow; 315062306a36Sopenharmony_ci timer->arg = arg; 315162306a36Sopenharmony_ci 315262306a36Sopenharmony_ci if ((timer_index > AR_FIRST_NDP_TIMER) && !timer_table->tsf2_enabled) { 315362306a36Sopenharmony_ci timer_table->tsf2_enabled = true; 315462306a36Sopenharmony_ci ath9k_hw_gen_timer_start_tsf2(ah); 315562306a36Sopenharmony_ci } 315662306a36Sopenharmony_ci 315762306a36Sopenharmony_ci return timer; 315862306a36Sopenharmony_ci} 315962306a36Sopenharmony_ciEXPORT_SYMBOL(ath_gen_timer_alloc); 316062306a36Sopenharmony_ci 316162306a36Sopenharmony_civoid ath9k_hw_gen_timer_start(struct ath_hw *ah, 316262306a36Sopenharmony_ci struct ath_gen_timer *timer, 316362306a36Sopenharmony_ci u32 timer_next, 316462306a36Sopenharmony_ci u32 timer_period) 316562306a36Sopenharmony_ci{ 316662306a36Sopenharmony_ci struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers; 316762306a36Sopenharmony_ci u32 mask = 0; 316862306a36Sopenharmony_ci 316962306a36Sopenharmony_ci timer_table->timer_mask |= BIT(timer->index); 317062306a36Sopenharmony_ci 317162306a36Sopenharmony_ci /* 317262306a36Sopenharmony_ci * Program generic timer registers 317362306a36Sopenharmony_ci */ 317462306a36Sopenharmony_ci REG_WRITE(ah, gen_tmr_configuration[timer->index].next_addr, 317562306a36Sopenharmony_ci timer_next); 317662306a36Sopenharmony_ci REG_WRITE(ah, gen_tmr_configuration[timer->index].period_addr, 317762306a36Sopenharmony_ci timer_period); 317862306a36Sopenharmony_ci REG_SET_BIT(ah, gen_tmr_configuration[timer->index].mode_addr, 317962306a36Sopenharmony_ci gen_tmr_configuration[timer->index].mode_mask); 318062306a36Sopenharmony_ci 318162306a36Sopenharmony_ci if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) { 318262306a36Sopenharmony_ci /* 318362306a36Sopenharmony_ci * Starting from AR9462, each generic timer can select which tsf 318462306a36Sopenharmony_ci * to use. But we still follow the old rule, 0 - 7 use tsf and 318562306a36Sopenharmony_ci * 8 - 15 use tsf2. 318662306a36Sopenharmony_ci */ 318762306a36Sopenharmony_ci if ((timer->index < AR_GEN_TIMER_BANK_1_LEN)) 318862306a36Sopenharmony_ci REG_CLR_BIT(ah, AR_MAC_PCU_GEN_TIMER_TSF_SEL, 318962306a36Sopenharmony_ci (1 << timer->index)); 319062306a36Sopenharmony_ci else 319162306a36Sopenharmony_ci REG_SET_BIT(ah, AR_MAC_PCU_GEN_TIMER_TSF_SEL, 319262306a36Sopenharmony_ci (1 << timer->index)); 319362306a36Sopenharmony_ci } 319462306a36Sopenharmony_ci 319562306a36Sopenharmony_ci if (timer->trigger) 319662306a36Sopenharmony_ci mask |= SM(AR_GENTMR_BIT(timer->index), 319762306a36Sopenharmony_ci AR_IMR_S5_GENTIMER_TRIG); 319862306a36Sopenharmony_ci if (timer->overflow) 319962306a36Sopenharmony_ci mask |= SM(AR_GENTMR_BIT(timer->index), 320062306a36Sopenharmony_ci AR_IMR_S5_GENTIMER_THRESH); 320162306a36Sopenharmony_ci 320262306a36Sopenharmony_ci REG_SET_BIT(ah, AR_IMR_S5, mask); 320362306a36Sopenharmony_ci 320462306a36Sopenharmony_ci if ((ah->imask & ATH9K_INT_GENTIMER) == 0) { 320562306a36Sopenharmony_ci ah->imask |= ATH9K_INT_GENTIMER; 320662306a36Sopenharmony_ci ath9k_hw_set_interrupts(ah); 320762306a36Sopenharmony_ci } 320862306a36Sopenharmony_ci} 320962306a36Sopenharmony_ciEXPORT_SYMBOL(ath9k_hw_gen_timer_start); 321062306a36Sopenharmony_ci 321162306a36Sopenharmony_civoid ath9k_hw_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer) 321262306a36Sopenharmony_ci{ 321362306a36Sopenharmony_ci struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers; 321462306a36Sopenharmony_ci 321562306a36Sopenharmony_ci /* Clear generic timer enable bits. */ 321662306a36Sopenharmony_ci REG_CLR_BIT(ah, gen_tmr_configuration[timer->index].mode_addr, 321762306a36Sopenharmony_ci gen_tmr_configuration[timer->index].mode_mask); 321862306a36Sopenharmony_ci 321962306a36Sopenharmony_ci if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) { 322062306a36Sopenharmony_ci /* 322162306a36Sopenharmony_ci * Need to switch back to TSF if it was using TSF2. 322262306a36Sopenharmony_ci */ 322362306a36Sopenharmony_ci if ((timer->index >= AR_GEN_TIMER_BANK_1_LEN)) { 322462306a36Sopenharmony_ci REG_CLR_BIT(ah, AR_MAC_PCU_GEN_TIMER_TSF_SEL, 322562306a36Sopenharmony_ci (1 << timer->index)); 322662306a36Sopenharmony_ci } 322762306a36Sopenharmony_ci } 322862306a36Sopenharmony_ci 322962306a36Sopenharmony_ci /* Disable both trigger and thresh interrupt masks */ 323062306a36Sopenharmony_ci REG_CLR_BIT(ah, AR_IMR_S5, 323162306a36Sopenharmony_ci (SM(AR_GENTMR_BIT(timer->index), AR_IMR_S5_GENTIMER_THRESH) | 323262306a36Sopenharmony_ci SM(AR_GENTMR_BIT(timer->index), AR_IMR_S5_GENTIMER_TRIG))); 323362306a36Sopenharmony_ci 323462306a36Sopenharmony_ci timer_table->timer_mask &= ~BIT(timer->index); 323562306a36Sopenharmony_ci 323662306a36Sopenharmony_ci if (timer_table->timer_mask == 0) { 323762306a36Sopenharmony_ci ah->imask &= ~ATH9K_INT_GENTIMER; 323862306a36Sopenharmony_ci ath9k_hw_set_interrupts(ah); 323962306a36Sopenharmony_ci } 324062306a36Sopenharmony_ci} 324162306a36Sopenharmony_ciEXPORT_SYMBOL(ath9k_hw_gen_timer_stop); 324262306a36Sopenharmony_ci 324362306a36Sopenharmony_civoid ath_gen_timer_free(struct ath_hw *ah, struct ath_gen_timer *timer) 324462306a36Sopenharmony_ci{ 324562306a36Sopenharmony_ci struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers; 324662306a36Sopenharmony_ci 324762306a36Sopenharmony_ci /* free the hardware generic timer slot */ 324862306a36Sopenharmony_ci timer_table->timers[timer->index] = NULL; 324962306a36Sopenharmony_ci kfree(timer); 325062306a36Sopenharmony_ci} 325162306a36Sopenharmony_ciEXPORT_SYMBOL(ath_gen_timer_free); 325262306a36Sopenharmony_ci 325362306a36Sopenharmony_ci/* 325462306a36Sopenharmony_ci * Generic Timer Interrupts handling 325562306a36Sopenharmony_ci */ 325662306a36Sopenharmony_civoid ath_gen_timer_isr(struct ath_hw *ah) 325762306a36Sopenharmony_ci{ 325862306a36Sopenharmony_ci struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers; 325962306a36Sopenharmony_ci struct ath_gen_timer *timer; 326062306a36Sopenharmony_ci unsigned long trigger_mask, thresh_mask; 326162306a36Sopenharmony_ci unsigned int index; 326262306a36Sopenharmony_ci 326362306a36Sopenharmony_ci /* get hardware generic timer interrupt status */ 326462306a36Sopenharmony_ci trigger_mask = ah->intr_gen_timer_trigger; 326562306a36Sopenharmony_ci thresh_mask = ah->intr_gen_timer_thresh; 326662306a36Sopenharmony_ci trigger_mask &= timer_table->timer_mask; 326762306a36Sopenharmony_ci thresh_mask &= timer_table->timer_mask; 326862306a36Sopenharmony_ci 326962306a36Sopenharmony_ci for_each_set_bit(index, &thresh_mask, ARRAY_SIZE(timer_table->timers)) { 327062306a36Sopenharmony_ci timer = timer_table->timers[index]; 327162306a36Sopenharmony_ci if (!timer) 327262306a36Sopenharmony_ci continue; 327362306a36Sopenharmony_ci if (!timer->overflow) 327462306a36Sopenharmony_ci continue; 327562306a36Sopenharmony_ci 327662306a36Sopenharmony_ci trigger_mask &= ~BIT(index); 327762306a36Sopenharmony_ci timer->overflow(timer->arg); 327862306a36Sopenharmony_ci } 327962306a36Sopenharmony_ci 328062306a36Sopenharmony_ci for_each_set_bit(index, &trigger_mask, ARRAY_SIZE(timer_table->timers)) { 328162306a36Sopenharmony_ci timer = timer_table->timers[index]; 328262306a36Sopenharmony_ci if (!timer) 328362306a36Sopenharmony_ci continue; 328462306a36Sopenharmony_ci if (!timer->trigger) 328562306a36Sopenharmony_ci continue; 328662306a36Sopenharmony_ci timer->trigger(timer->arg); 328762306a36Sopenharmony_ci } 328862306a36Sopenharmony_ci} 328962306a36Sopenharmony_ciEXPORT_SYMBOL(ath_gen_timer_isr); 329062306a36Sopenharmony_ci 329162306a36Sopenharmony_ci/********/ 329262306a36Sopenharmony_ci/* HTC */ 329362306a36Sopenharmony_ci/********/ 329462306a36Sopenharmony_ci 329562306a36Sopenharmony_cistatic struct { 329662306a36Sopenharmony_ci u32 version; 329762306a36Sopenharmony_ci const char * name; 329862306a36Sopenharmony_ci} ath_mac_bb_names[] = { 329962306a36Sopenharmony_ci /* Devices with external radios */ 330062306a36Sopenharmony_ci { AR_SREV_VERSION_5416_PCI, "5416" }, 330162306a36Sopenharmony_ci { AR_SREV_VERSION_5416_PCIE, "5418" }, 330262306a36Sopenharmony_ci { AR_SREV_VERSION_9100, "9100" }, 330362306a36Sopenharmony_ci { AR_SREV_VERSION_9160, "9160" }, 330462306a36Sopenharmony_ci /* Single-chip solutions */ 330562306a36Sopenharmony_ci { AR_SREV_VERSION_9280, "9280" }, 330662306a36Sopenharmony_ci { AR_SREV_VERSION_9285, "9285" }, 330762306a36Sopenharmony_ci { AR_SREV_VERSION_9287, "9287" }, 330862306a36Sopenharmony_ci { AR_SREV_VERSION_9271, "9271" }, 330962306a36Sopenharmony_ci { AR_SREV_VERSION_9300, "9300" }, 331062306a36Sopenharmony_ci { AR_SREV_VERSION_9330, "9330" }, 331162306a36Sopenharmony_ci { AR_SREV_VERSION_9340, "9340" }, 331262306a36Sopenharmony_ci { AR_SREV_VERSION_9485, "9485" }, 331362306a36Sopenharmony_ci { AR_SREV_VERSION_9462, "9462" }, 331462306a36Sopenharmony_ci { AR_SREV_VERSION_9550, "9550" }, 331562306a36Sopenharmony_ci { AR_SREV_VERSION_9565, "9565" }, 331662306a36Sopenharmony_ci { AR_SREV_VERSION_9531, "9531" }, 331762306a36Sopenharmony_ci { AR_SREV_VERSION_9561, "9561" }, 331862306a36Sopenharmony_ci}; 331962306a36Sopenharmony_ci 332062306a36Sopenharmony_ci/* For devices with external radios */ 332162306a36Sopenharmony_cistatic struct { 332262306a36Sopenharmony_ci u16 version; 332362306a36Sopenharmony_ci const char * name; 332462306a36Sopenharmony_ci} ath_rf_names[] = { 332562306a36Sopenharmony_ci { 0, "5133" }, 332662306a36Sopenharmony_ci { AR_RAD5133_SREV_MAJOR, "5133" }, 332762306a36Sopenharmony_ci { AR_RAD5122_SREV_MAJOR, "5122" }, 332862306a36Sopenharmony_ci { AR_RAD2133_SREV_MAJOR, "2133" }, 332962306a36Sopenharmony_ci { AR_RAD2122_SREV_MAJOR, "2122" } 333062306a36Sopenharmony_ci}; 333162306a36Sopenharmony_ci 333262306a36Sopenharmony_ci/* 333362306a36Sopenharmony_ci * Return the MAC/BB name. "????" is returned if the MAC/BB is unknown. 333462306a36Sopenharmony_ci */ 333562306a36Sopenharmony_cistatic const char *ath9k_hw_mac_bb_name(u32 mac_bb_version) 333662306a36Sopenharmony_ci{ 333762306a36Sopenharmony_ci int i; 333862306a36Sopenharmony_ci 333962306a36Sopenharmony_ci for (i=0; i<ARRAY_SIZE(ath_mac_bb_names); i++) { 334062306a36Sopenharmony_ci if (ath_mac_bb_names[i].version == mac_bb_version) { 334162306a36Sopenharmony_ci return ath_mac_bb_names[i].name; 334262306a36Sopenharmony_ci } 334362306a36Sopenharmony_ci } 334462306a36Sopenharmony_ci 334562306a36Sopenharmony_ci return "????"; 334662306a36Sopenharmony_ci} 334762306a36Sopenharmony_ci 334862306a36Sopenharmony_ci/* 334962306a36Sopenharmony_ci * Return the RF name. "????" is returned if the RF is unknown. 335062306a36Sopenharmony_ci * Used for devices with external radios. 335162306a36Sopenharmony_ci */ 335262306a36Sopenharmony_cistatic const char *ath9k_hw_rf_name(u16 rf_version) 335362306a36Sopenharmony_ci{ 335462306a36Sopenharmony_ci int i; 335562306a36Sopenharmony_ci 335662306a36Sopenharmony_ci for (i=0; i<ARRAY_SIZE(ath_rf_names); i++) { 335762306a36Sopenharmony_ci if (ath_rf_names[i].version == rf_version) { 335862306a36Sopenharmony_ci return ath_rf_names[i].name; 335962306a36Sopenharmony_ci } 336062306a36Sopenharmony_ci } 336162306a36Sopenharmony_ci 336262306a36Sopenharmony_ci return "????"; 336362306a36Sopenharmony_ci} 336462306a36Sopenharmony_ci 336562306a36Sopenharmony_civoid ath9k_hw_name(struct ath_hw *ah, char *hw_name, size_t len) 336662306a36Sopenharmony_ci{ 336762306a36Sopenharmony_ci int used; 336862306a36Sopenharmony_ci 336962306a36Sopenharmony_ci /* chipsets >= AR9280 are single-chip */ 337062306a36Sopenharmony_ci if (AR_SREV_9280_20_OR_LATER(ah)) { 337162306a36Sopenharmony_ci used = scnprintf(hw_name, len, 337262306a36Sopenharmony_ci "Atheros AR%s Rev:%x", 337362306a36Sopenharmony_ci ath9k_hw_mac_bb_name(ah->hw_version.macVersion), 337462306a36Sopenharmony_ci ah->hw_version.macRev); 337562306a36Sopenharmony_ci } 337662306a36Sopenharmony_ci else { 337762306a36Sopenharmony_ci used = scnprintf(hw_name, len, 337862306a36Sopenharmony_ci "Atheros AR%s MAC/BB Rev:%x AR%s RF Rev:%x", 337962306a36Sopenharmony_ci ath9k_hw_mac_bb_name(ah->hw_version.macVersion), 338062306a36Sopenharmony_ci ah->hw_version.macRev, 338162306a36Sopenharmony_ci ath9k_hw_rf_name((ah->hw_version.analog5GhzRev 338262306a36Sopenharmony_ci & AR_RADIO_SREV_MAJOR)), 338362306a36Sopenharmony_ci ah->hw_version.phyRev); 338462306a36Sopenharmony_ci } 338562306a36Sopenharmony_ci 338662306a36Sopenharmony_ci hw_name[used] = '\0'; 338762306a36Sopenharmony_ci} 338862306a36Sopenharmony_ciEXPORT_SYMBOL(ath9k_hw_name); 3389