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