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 <asm/unaligned.h>
1862306a36Sopenharmony_ci#include "hw.h"
1962306a36Sopenharmony_ci#include "ar9002_phy.h"
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_cistatic int ath9k_hw_4k_get_eeprom_ver(struct ath_hw *ah)
2262306a36Sopenharmony_ci{
2362306a36Sopenharmony_ci	u16 version = le16_to_cpu(ah->eeprom.map4k.baseEepHeader.version);
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci	return (version & AR5416_EEP_VER_MAJOR_MASK) >>
2662306a36Sopenharmony_ci		AR5416_EEP_VER_MAJOR_SHIFT;
2762306a36Sopenharmony_ci}
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_cistatic int ath9k_hw_4k_get_eeprom_rev(struct ath_hw *ah)
3062306a36Sopenharmony_ci{
3162306a36Sopenharmony_ci	u16 version = le16_to_cpu(ah->eeprom.map4k.baseEepHeader.version);
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci	return version & AR5416_EEP_VER_MINOR_MASK;
3462306a36Sopenharmony_ci}
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci#define SIZE_EEPROM_4K (sizeof(struct ar5416_eeprom_4k) / sizeof(u16))
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_cistatic bool __ath9k_hw_4k_fill_eeprom(struct ath_hw *ah)
3962306a36Sopenharmony_ci{
4062306a36Sopenharmony_ci	u16 *eep_data = (u16 *)&ah->eeprom.map4k;
4162306a36Sopenharmony_ci	int addr, eep_start_loc = 64;
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci	for (addr = 0; addr < SIZE_EEPROM_4K; addr++) {
4462306a36Sopenharmony_ci		if (!ath9k_hw_nvram_read(ah, addr + eep_start_loc, eep_data))
4562306a36Sopenharmony_ci			return false;
4662306a36Sopenharmony_ci		eep_data++;
4762306a36Sopenharmony_ci	}
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci	return true;
5062306a36Sopenharmony_ci}
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_cistatic bool __ath9k_hw_usb_4k_fill_eeprom(struct ath_hw *ah)
5362306a36Sopenharmony_ci{
5462306a36Sopenharmony_ci	u16 *eep_data = (u16 *)&ah->eeprom.map4k;
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci	ath9k_hw_usb_gen_fill_eeprom(ah, eep_data, 64, SIZE_EEPROM_4K);
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci	return true;
5962306a36Sopenharmony_ci}
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_cistatic bool ath9k_hw_4k_fill_eeprom(struct ath_hw *ah)
6262306a36Sopenharmony_ci{
6362306a36Sopenharmony_ci	struct ath_common *common = ath9k_hw_common(ah);
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci	if (!ath9k_hw_use_flash(ah)) {
6662306a36Sopenharmony_ci		ath_dbg(common, EEPROM, "Reading from EEPROM, not flash\n");
6762306a36Sopenharmony_ci	}
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci	if (common->bus_ops->ath_bus_type == ATH_USB)
7062306a36Sopenharmony_ci		return __ath9k_hw_usb_4k_fill_eeprom(ah);
7162306a36Sopenharmony_ci	else
7262306a36Sopenharmony_ci		return __ath9k_hw_4k_fill_eeprom(ah);
7362306a36Sopenharmony_ci}
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ci#ifdef CONFIG_ATH9K_COMMON_DEBUG
7662306a36Sopenharmony_cistatic u32 ath9k_dump_4k_modal_eeprom(char *buf, u32 len, u32 size,
7762306a36Sopenharmony_ci				      struct modal_eep_4k_header *modal_hdr)
7862306a36Sopenharmony_ci{
7962306a36Sopenharmony_ci	PR_EEP("Chain0 Ant. Control", le16_to_cpu(modal_hdr->antCtrlChain[0]));
8062306a36Sopenharmony_ci	PR_EEP("Ant. Common Control", le32_to_cpu(modal_hdr->antCtrlCommon));
8162306a36Sopenharmony_ci	PR_EEP("Chain0 Ant. Gain", modal_hdr->antennaGainCh[0]);
8262306a36Sopenharmony_ci	PR_EEP("Switch Settle", modal_hdr->switchSettling);
8362306a36Sopenharmony_ci	PR_EEP("Chain0 TxRxAtten", modal_hdr->txRxAttenCh[0]);
8462306a36Sopenharmony_ci	PR_EEP("Chain0 RxTxMargin", modal_hdr->rxTxMarginCh[0]);
8562306a36Sopenharmony_ci	PR_EEP("ADC Desired size", modal_hdr->adcDesiredSize);
8662306a36Sopenharmony_ci	PR_EEP("PGA Desired size", modal_hdr->pgaDesiredSize);
8762306a36Sopenharmony_ci	PR_EEP("Chain0 xlna Gain", modal_hdr->xlnaGainCh[0]);
8862306a36Sopenharmony_ci	PR_EEP("txEndToXpaOff", modal_hdr->txEndToXpaOff);
8962306a36Sopenharmony_ci	PR_EEP("txEndToRxOn", modal_hdr->txEndToRxOn);
9062306a36Sopenharmony_ci	PR_EEP("txFrameToXpaOn", modal_hdr->txFrameToXpaOn);
9162306a36Sopenharmony_ci	PR_EEP("CCA Threshold)", modal_hdr->thresh62);
9262306a36Sopenharmony_ci	PR_EEP("Chain0 NF Threshold", modal_hdr->noiseFloorThreshCh[0]);
9362306a36Sopenharmony_ci	PR_EEP("xpdGain", modal_hdr->xpdGain);
9462306a36Sopenharmony_ci	PR_EEP("External PD", modal_hdr->xpd);
9562306a36Sopenharmony_ci	PR_EEP("Chain0 I Coefficient", modal_hdr->iqCalICh[0]);
9662306a36Sopenharmony_ci	PR_EEP("Chain0 Q Coefficient", modal_hdr->iqCalQCh[0]);
9762306a36Sopenharmony_ci	PR_EEP("pdGainOverlap", modal_hdr->pdGainOverlap);
9862306a36Sopenharmony_ci	PR_EEP("O/D Bias Version", modal_hdr->version);
9962306a36Sopenharmony_ci	PR_EEP("CCK OutputBias", modal_hdr->ob_0);
10062306a36Sopenharmony_ci	PR_EEP("BPSK OutputBias", modal_hdr->ob_1);
10162306a36Sopenharmony_ci	PR_EEP("QPSK OutputBias", modal_hdr->ob_2);
10262306a36Sopenharmony_ci	PR_EEP("16QAM OutputBias", modal_hdr->ob_3);
10362306a36Sopenharmony_ci	PR_EEP("64QAM OutputBias", modal_hdr->ob_4);
10462306a36Sopenharmony_ci	PR_EEP("CCK Driver1_Bias", modal_hdr->db1_0);
10562306a36Sopenharmony_ci	PR_EEP("BPSK Driver1_Bias", modal_hdr->db1_1);
10662306a36Sopenharmony_ci	PR_EEP("QPSK Driver1_Bias", modal_hdr->db1_2);
10762306a36Sopenharmony_ci	PR_EEP("16QAM Driver1_Bias", modal_hdr->db1_3);
10862306a36Sopenharmony_ci	PR_EEP("64QAM Driver1_Bias", modal_hdr->db1_4);
10962306a36Sopenharmony_ci	PR_EEP("CCK Driver2_Bias", modal_hdr->db2_0);
11062306a36Sopenharmony_ci	PR_EEP("BPSK Driver2_Bias", modal_hdr->db2_1);
11162306a36Sopenharmony_ci	PR_EEP("QPSK Driver2_Bias", modal_hdr->db2_2);
11262306a36Sopenharmony_ci	PR_EEP("16QAM Driver2_Bias", modal_hdr->db2_3);
11362306a36Sopenharmony_ci	PR_EEP("64QAM Driver2_Bias", modal_hdr->db2_4);
11462306a36Sopenharmony_ci	PR_EEP("xPA Bias Level", modal_hdr->xpaBiasLvl);
11562306a36Sopenharmony_ci	PR_EEP("txFrameToDataStart", modal_hdr->txFrameToDataStart);
11662306a36Sopenharmony_ci	PR_EEP("txFrameToPaOn", modal_hdr->txFrameToPaOn);
11762306a36Sopenharmony_ci	PR_EEP("HT40 Power Inc.", modal_hdr->ht40PowerIncForPdadc);
11862306a36Sopenharmony_ci	PR_EEP("Chain0 bswAtten", modal_hdr->bswAtten[0]);
11962306a36Sopenharmony_ci	PR_EEP("Chain0 bswMargin", modal_hdr->bswMargin[0]);
12062306a36Sopenharmony_ci	PR_EEP("HT40 Switch Settle", modal_hdr->swSettleHt40);
12162306a36Sopenharmony_ci	PR_EEP("Chain0 xatten2Db", modal_hdr->xatten2Db[0]);
12262306a36Sopenharmony_ci	PR_EEP("Chain0 xatten2Margin", modal_hdr->xatten2Margin[0]);
12362306a36Sopenharmony_ci	PR_EEP("Ant. Diversity ctl1", modal_hdr->antdiv_ctl1);
12462306a36Sopenharmony_ci	PR_EEP("Ant. Diversity ctl2", modal_hdr->antdiv_ctl2);
12562306a36Sopenharmony_ci	PR_EEP("TX Diversity", modal_hdr->tx_diversity);
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci	return len;
12862306a36Sopenharmony_ci}
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_cistatic u32 ath9k_hw_4k_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
13162306a36Sopenharmony_ci				       u8 *buf, u32 len, u32 size)
13262306a36Sopenharmony_ci{
13362306a36Sopenharmony_ci	struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
13462306a36Sopenharmony_ci	struct base_eep_header_4k *pBase = &eep->baseEepHeader;
13562306a36Sopenharmony_ci	u32 binBuildNumber = le32_to_cpu(pBase->binBuildNumber);
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ci	if (!dump_base_hdr) {
13862306a36Sopenharmony_ci		len += scnprintf(buf + len, size - len,
13962306a36Sopenharmony_ci				 "%20s :\n", "2GHz modal Header");
14062306a36Sopenharmony_ci		len = ath9k_dump_4k_modal_eeprom(buf, len, size,
14162306a36Sopenharmony_ci						 &eep->modalHeader);
14262306a36Sopenharmony_ci		goto out;
14362306a36Sopenharmony_ci	}
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci	PR_EEP("Major Version", ath9k_hw_4k_get_eeprom_ver(ah));
14662306a36Sopenharmony_ci	PR_EEP("Minor Version", ath9k_hw_4k_get_eeprom_rev(ah));
14762306a36Sopenharmony_ci	PR_EEP("Checksum", le16_to_cpu(pBase->checksum));
14862306a36Sopenharmony_ci	PR_EEP("Length", le16_to_cpu(pBase->length));
14962306a36Sopenharmony_ci	PR_EEP("RegDomain1", le16_to_cpu(pBase->regDmn[0]));
15062306a36Sopenharmony_ci	PR_EEP("RegDomain2", le16_to_cpu(pBase->regDmn[1]));
15162306a36Sopenharmony_ci	PR_EEP("TX Mask", pBase->txMask);
15262306a36Sopenharmony_ci	PR_EEP("RX Mask", pBase->rxMask);
15362306a36Sopenharmony_ci	PR_EEP("Allow 5GHz", !!(pBase->opCapFlags & AR5416_OPFLAGS_11A));
15462306a36Sopenharmony_ci	PR_EEP("Allow 2GHz", !!(pBase->opCapFlags & AR5416_OPFLAGS_11G));
15562306a36Sopenharmony_ci	PR_EEP("Disable 2GHz HT20", !!(pBase->opCapFlags &
15662306a36Sopenharmony_ci					AR5416_OPFLAGS_N_2G_HT20));
15762306a36Sopenharmony_ci	PR_EEP("Disable 2GHz HT40", !!(pBase->opCapFlags &
15862306a36Sopenharmony_ci					AR5416_OPFLAGS_N_2G_HT40));
15962306a36Sopenharmony_ci	PR_EEP("Disable 5Ghz HT20", !!(pBase->opCapFlags &
16062306a36Sopenharmony_ci					AR5416_OPFLAGS_N_5G_HT20));
16162306a36Sopenharmony_ci	PR_EEP("Disable 5Ghz HT40", !!(pBase->opCapFlags &
16262306a36Sopenharmony_ci					AR5416_OPFLAGS_N_5G_HT40));
16362306a36Sopenharmony_ci	PR_EEP("Big Endian", !!(pBase->eepMisc & AR5416_EEPMISC_BIG_ENDIAN));
16462306a36Sopenharmony_ci	PR_EEP("Cal Bin Major Ver", (binBuildNumber >> 24) & 0xFF);
16562306a36Sopenharmony_ci	PR_EEP("Cal Bin Minor Ver", (binBuildNumber >> 16) & 0xFF);
16662306a36Sopenharmony_ci	PR_EEP("Cal Bin Build", (binBuildNumber >> 8) & 0xFF);
16762306a36Sopenharmony_ci	PR_EEP("TX Gain type", pBase->txGainType);
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_ci	len += scnprintf(buf + len, size - len, "%20s : %pM\n", "MacAddress",
17062306a36Sopenharmony_ci			 pBase->macAddr);
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_ciout:
17362306a36Sopenharmony_ci	if (len > size)
17462306a36Sopenharmony_ci		len = size;
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci	return len;
17762306a36Sopenharmony_ci}
17862306a36Sopenharmony_ci#else
17962306a36Sopenharmony_cistatic u32 ath9k_hw_4k_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
18062306a36Sopenharmony_ci				       u8 *buf, u32 len, u32 size)
18162306a36Sopenharmony_ci{
18262306a36Sopenharmony_ci	return 0;
18362306a36Sopenharmony_ci}
18462306a36Sopenharmony_ci#endif
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_cistatic int ath9k_hw_4k_check_eeprom(struct ath_hw *ah)
18762306a36Sopenharmony_ci{
18862306a36Sopenharmony_ci	struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
18962306a36Sopenharmony_ci	u32 el;
19062306a36Sopenharmony_ci	bool need_swap;
19162306a36Sopenharmony_ci	int i, err;
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_ci	err = ath9k_hw_nvram_swap_data(ah, &need_swap, SIZE_EEPROM_4K);
19462306a36Sopenharmony_ci	if (err)
19562306a36Sopenharmony_ci		return err;
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_ci	if (need_swap)
19862306a36Sopenharmony_ci		el = swab16((__force u16)eep->baseEepHeader.length);
19962306a36Sopenharmony_ci	else
20062306a36Sopenharmony_ci		el = le16_to_cpu(eep->baseEepHeader.length);
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ci	el = min(el / sizeof(u16), SIZE_EEPROM_4K);
20362306a36Sopenharmony_ci	if (!ath9k_hw_nvram_validate_checksum(ah, el))
20462306a36Sopenharmony_ci		return -EINVAL;
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_ci	if (need_swap) {
20762306a36Sopenharmony_ci		EEPROM_FIELD_SWAB16(eep->baseEepHeader.length);
20862306a36Sopenharmony_ci		EEPROM_FIELD_SWAB16(eep->baseEepHeader.checksum);
20962306a36Sopenharmony_ci		EEPROM_FIELD_SWAB16(eep->baseEepHeader.version);
21062306a36Sopenharmony_ci		EEPROM_FIELD_SWAB16(eep->baseEepHeader.regDmn[0]);
21162306a36Sopenharmony_ci		EEPROM_FIELD_SWAB16(eep->baseEepHeader.regDmn[1]);
21262306a36Sopenharmony_ci		EEPROM_FIELD_SWAB16(eep->baseEepHeader.rfSilent);
21362306a36Sopenharmony_ci		EEPROM_FIELD_SWAB16(eep->baseEepHeader.blueToothOptions);
21462306a36Sopenharmony_ci		EEPROM_FIELD_SWAB16(eep->baseEepHeader.deviceCap);
21562306a36Sopenharmony_ci		EEPROM_FIELD_SWAB32(eep->modalHeader.antCtrlCommon);
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_ci		for (i = 0; i < AR5416_EEP4K_MAX_CHAINS; i++)
21862306a36Sopenharmony_ci			EEPROM_FIELD_SWAB32(eep->modalHeader.antCtrlChain[i]);
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_ci		for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++)
22162306a36Sopenharmony_ci			EEPROM_FIELD_SWAB16(
22262306a36Sopenharmony_ci				eep->modalHeader.spurChans[i].spurChan);
22362306a36Sopenharmony_ci	}
22462306a36Sopenharmony_ci
22562306a36Sopenharmony_ci	if (!ath9k_hw_nvram_check_version(ah, AR5416_EEP_VER,
22662306a36Sopenharmony_ci	    AR5416_EEP_NO_BACK_VER))
22762306a36Sopenharmony_ci		return -EINVAL;
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_ci	return 0;
23062306a36Sopenharmony_ci}
23162306a36Sopenharmony_ci
23262306a36Sopenharmony_ci#undef SIZE_EEPROM_4K
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_cistatic u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah,
23562306a36Sopenharmony_ci				  enum eeprom_param param)
23662306a36Sopenharmony_ci{
23762306a36Sopenharmony_ci	struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
23862306a36Sopenharmony_ci	struct modal_eep_4k_header *pModal = &eep->modalHeader;
23962306a36Sopenharmony_ci	struct base_eep_header_4k *pBase = &eep->baseEepHeader;
24062306a36Sopenharmony_ci
24162306a36Sopenharmony_ci	switch (param) {
24262306a36Sopenharmony_ci	case EEP_NFTHRESH_2:
24362306a36Sopenharmony_ci		return pModal->noiseFloorThreshCh[0];
24462306a36Sopenharmony_ci	case EEP_MAC_LSW:
24562306a36Sopenharmony_ci		return get_unaligned_be16(pBase->macAddr);
24662306a36Sopenharmony_ci	case EEP_MAC_MID:
24762306a36Sopenharmony_ci		return get_unaligned_be16(pBase->macAddr + 2);
24862306a36Sopenharmony_ci	case EEP_MAC_MSW:
24962306a36Sopenharmony_ci		return get_unaligned_be16(pBase->macAddr + 4);
25062306a36Sopenharmony_ci	case EEP_REG_0:
25162306a36Sopenharmony_ci		return le16_to_cpu(pBase->regDmn[0]);
25262306a36Sopenharmony_ci	case EEP_OP_CAP:
25362306a36Sopenharmony_ci		return le16_to_cpu(pBase->deviceCap);
25462306a36Sopenharmony_ci	case EEP_OP_MODE:
25562306a36Sopenharmony_ci		return pBase->opCapFlags;
25662306a36Sopenharmony_ci	case EEP_RF_SILENT:
25762306a36Sopenharmony_ci		return le16_to_cpu(pBase->rfSilent);
25862306a36Sopenharmony_ci	case EEP_OB_2:
25962306a36Sopenharmony_ci		return pModal->ob_0;
26062306a36Sopenharmony_ci	case EEP_DB_2:
26162306a36Sopenharmony_ci		return pModal->db1_1;
26262306a36Sopenharmony_ci	case EEP_TX_MASK:
26362306a36Sopenharmony_ci		return pBase->txMask;
26462306a36Sopenharmony_ci	case EEP_RX_MASK:
26562306a36Sopenharmony_ci		return pBase->rxMask;
26662306a36Sopenharmony_ci	case EEP_FRAC_N_5G:
26762306a36Sopenharmony_ci		return 0;
26862306a36Sopenharmony_ci	case EEP_PWR_TABLE_OFFSET:
26962306a36Sopenharmony_ci		return AR5416_PWR_TABLE_OFFSET_DB;
27062306a36Sopenharmony_ci	case EEP_MODAL_VER:
27162306a36Sopenharmony_ci		return pModal->version;
27262306a36Sopenharmony_ci	case EEP_ANT_DIV_CTL1:
27362306a36Sopenharmony_ci		return pModal->antdiv_ctl1;
27462306a36Sopenharmony_ci	case EEP_TXGAIN_TYPE:
27562306a36Sopenharmony_ci		return pBase->txGainType;
27662306a36Sopenharmony_ci	case EEP_ANTENNA_GAIN_2G:
27762306a36Sopenharmony_ci		return pModal->antennaGainCh[0];
27862306a36Sopenharmony_ci	default:
27962306a36Sopenharmony_ci		return 0;
28062306a36Sopenharmony_ci	}
28162306a36Sopenharmony_ci}
28262306a36Sopenharmony_ci
28362306a36Sopenharmony_cistatic void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah,
28462306a36Sopenharmony_ci				  struct ath9k_channel *chan)
28562306a36Sopenharmony_ci{
28662306a36Sopenharmony_ci	struct ath_common *common = ath9k_hw_common(ah);
28762306a36Sopenharmony_ci	struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
28862306a36Sopenharmony_ci	struct cal_data_per_freq_4k *pRawDataset;
28962306a36Sopenharmony_ci	u8 *pCalBChans = NULL;
29062306a36Sopenharmony_ci	u16 pdGainOverlap_t2;
29162306a36Sopenharmony_ci	static u8 pdadcValues[AR5416_NUM_PDADC_VALUES];
29262306a36Sopenharmony_ci	u16 gainBoundaries[AR5416_PD_GAINS_IN_MASK];
29362306a36Sopenharmony_ci	u16 numPiers, i, j;
29462306a36Sopenharmony_ci	u16 numXpdGain, xpdMask;
29562306a36Sopenharmony_ci	u16 xpdGainValues[AR5416_EEP4K_NUM_PD_GAINS] = { 0, 0 };
29662306a36Sopenharmony_ci	u32 reg32, regOffset, regChainOffset;
29762306a36Sopenharmony_ci
29862306a36Sopenharmony_ci	xpdMask = pEepData->modalHeader.xpdGain;
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_ci	if (ath9k_hw_4k_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_2)
30162306a36Sopenharmony_ci		pdGainOverlap_t2 =
30262306a36Sopenharmony_ci			pEepData->modalHeader.pdGainOverlap;
30362306a36Sopenharmony_ci	else
30462306a36Sopenharmony_ci		pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5),
30562306a36Sopenharmony_ci					    AR_PHY_TPCRG5_PD_GAIN_OVERLAP));
30662306a36Sopenharmony_ci
30762306a36Sopenharmony_ci	pCalBChans = pEepData->calFreqPier2G;
30862306a36Sopenharmony_ci	numPiers = AR5416_EEP4K_NUM_2G_CAL_PIERS;
30962306a36Sopenharmony_ci
31062306a36Sopenharmony_ci	numXpdGain = 0;
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_ci	for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) {
31362306a36Sopenharmony_ci		if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) {
31462306a36Sopenharmony_ci			if (numXpdGain >= AR5416_EEP4K_NUM_PD_GAINS)
31562306a36Sopenharmony_ci				break;
31662306a36Sopenharmony_ci			xpdGainValues[numXpdGain] =
31762306a36Sopenharmony_ci				(u16)(AR5416_PD_GAINS_IN_MASK - i);
31862306a36Sopenharmony_ci			numXpdGain++;
31962306a36Sopenharmony_ci		}
32062306a36Sopenharmony_ci	}
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_ci	ENABLE_REG_RMW_BUFFER(ah);
32362306a36Sopenharmony_ci	REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN,
32462306a36Sopenharmony_ci		      (numXpdGain - 1) & 0x3);
32562306a36Sopenharmony_ci	REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1,
32662306a36Sopenharmony_ci		      xpdGainValues[0]);
32762306a36Sopenharmony_ci	REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2,
32862306a36Sopenharmony_ci		      xpdGainValues[1]);
32962306a36Sopenharmony_ci	REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3, 0);
33062306a36Sopenharmony_ci	REG_RMW_BUFFER_FLUSH(ah);
33162306a36Sopenharmony_ci
33262306a36Sopenharmony_ci	for (i = 0; i < AR5416_EEP4K_MAX_CHAINS; i++) {
33362306a36Sopenharmony_ci		regChainOffset = i * 0x1000;
33462306a36Sopenharmony_ci
33562306a36Sopenharmony_ci		if (pEepData->baseEepHeader.txMask & (1 << i)) {
33662306a36Sopenharmony_ci			pRawDataset = pEepData->calPierData2G[i];
33762306a36Sopenharmony_ci
33862306a36Sopenharmony_ci			ath9k_hw_get_gain_boundaries_pdadcs(ah, chan,
33962306a36Sopenharmony_ci					    pRawDataset, pCalBChans,
34062306a36Sopenharmony_ci					    numPiers, pdGainOverlap_t2,
34162306a36Sopenharmony_ci					    gainBoundaries,
34262306a36Sopenharmony_ci					    pdadcValues, numXpdGain);
34362306a36Sopenharmony_ci
34462306a36Sopenharmony_ci			ENABLE_REGWRITE_BUFFER(ah);
34562306a36Sopenharmony_ci
34662306a36Sopenharmony_ci			REG_WRITE(ah, AR_PHY_TPCRG5 + regChainOffset,
34762306a36Sopenharmony_ci				  SM(pdGainOverlap_t2,
34862306a36Sopenharmony_ci				     AR_PHY_TPCRG5_PD_GAIN_OVERLAP)
34962306a36Sopenharmony_ci				  | SM(gainBoundaries[0],
35062306a36Sopenharmony_ci				       AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1)
35162306a36Sopenharmony_ci				  | SM(gainBoundaries[1],
35262306a36Sopenharmony_ci				       AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2)
35362306a36Sopenharmony_ci				  | SM(gainBoundaries[2],
35462306a36Sopenharmony_ci				       AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3)
35562306a36Sopenharmony_ci				  | SM(gainBoundaries[3],
35662306a36Sopenharmony_ci			       AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4));
35762306a36Sopenharmony_ci
35862306a36Sopenharmony_ci			regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset;
35962306a36Sopenharmony_ci			for (j = 0; j < 32; j++) {
36062306a36Sopenharmony_ci				reg32 = get_unaligned_le32(&pdadcValues[4 * j]);
36162306a36Sopenharmony_ci				REG_WRITE(ah, regOffset, reg32);
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_ci				ath_dbg(common, EEPROM,
36462306a36Sopenharmony_ci					"PDADC (%d,%4x): %4.4x %8.8x\n",
36562306a36Sopenharmony_ci					i, regChainOffset, regOffset,
36662306a36Sopenharmony_ci					reg32);
36762306a36Sopenharmony_ci				ath_dbg(common, EEPROM,
36862306a36Sopenharmony_ci					"PDADC: Chain %d | "
36962306a36Sopenharmony_ci					"PDADC %3d Value %3d | "
37062306a36Sopenharmony_ci					"PDADC %3d Value %3d | "
37162306a36Sopenharmony_ci					"PDADC %3d Value %3d | "
37262306a36Sopenharmony_ci					"PDADC %3d Value %3d |\n",
37362306a36Sopenharmony_ci					i, 4 * j, pdadcValues[4 * j],
37462306a36Sopenharmony_ci					4 * j + 1, pdadcValues[4 * j + 1],
37562306a36Sopenharmony_ci					4 * j + 2, pdadcValues[4 * j + 2],
37662306a36Sopenharmony_ci					4 * j + 3, pdadcValues[4 * j + 3]);
37762306a36Sopenharmony_ci
37862306a36Sopenharmony_ci				regOffset += 4;
37962306a36Sopenharmony_ci			}
38062306a36Sopenharmony_ci
38162306a36Sopenharmony_ci			REGWRITE_BUFFER_FLUSH(ah);
38262306a36Sopenharmony_ci		}
38362306a36Sopenharmony_ci	}
38462306a36Sopenharmony_ci}
38562306a36Sopenharmony_ci
38662306a36Sopenharmony_cistatic void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah,
38762306a36Sopenharmony_ci						 struct ath9k_channel *chan,
38862306a36Sopenharmony_ci						 int16_t *ratesArray,
38962306a36Sopenharmony_ci						 u16 cfgCtl,
39062306a36Sopenharmony_ci						 u16 antenna_reduction,
39162306a36Sopenharmony_ci						 u16 powerLimit)
39262306a36Sopenharmony_ci{
39362306a36Sopenharmony_ci#define CMP_TEST_GRP \
39462306a36Sopenharmony_ci	(((cfgCtl & ~CTL_MODE_M)| (pCtlMode[ctlMode] & CTL_MODE_M)) ==	\
39562306a36Sopenharmony_ci	 pEepData->ctlIndex[i])						\
39662306a36Sopenharmony_ci	|| (((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == \
39762306a36Sopenharmony_ci	    ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL))
39862306a36Sopenharmony_ci
39962306a36Sopenharmony_ci	int i;
40062306a36Sopenharmony_ci	u16 twiceMinEdgePower;
40162306a36Sopenharmony_ci	u16 twiceMaxEdgePower;
40262306a36Sopenharmony_ci	u16 scaledPower = 0, minCtlPower;
40362306a36Sopenharmony_ci	u16 numCtlModes;
40462306a36Sopenharmony_ci	const u16 *pCtlMode;
40562306a36Sopenharmony_ci	u16 ctlMode, freq;
40662306a36Sopenharmony_ci	struct chan_centers centers;
40762306a36Sopenharmony_ci	struct cal_ctl_data_4k *rep;
40862306a36Sopenharmony_ci	struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
40962306a36Sopenharmony_ci	struct cal_target_power_leg targetPowerOfdm, targetPowerCck = {
41062306a36Sopenharmony_ci		0, { 0, 0, 0, 0}
41162306a36Sopenharmony_ci	};
41262306a36Sopenharmony_ci	struct cal_target_power_leg targetPowerOfdmExt = {
41362306a36Sopenharmony_ci		0, { 0, 0, 0, 0} }, targetPowerCckExt = {
41462306a36Sopenharmony_ci		0, { 0, 0, 0, 0 }
41562306a36Sopenharmony_ci	};
41662306a36Sopenharmony_ci	struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = {
41762306a36Sopenharmony_ci		0, {0, 0, 0, 0}
41862306a36Sopenharmony_ci	};
41962306a36Sopenharmony_ci	static const u16 ctlModesFor11g[] = {
42062306a36Sopenharmony_ci		CTL_11B, CTL_11G, CTL_2GHT20,
42162306a36Sopenharmony_ci		CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40
42262306a36Sopenharmony_ci	};
42362306a36Sopenharmony_ci
42462306a36Sopenharmony_ci	ath9k_hw_get_channel_centers(ah, chan, &centers);
42562306a36Sopenharmony_ci
42662306a36Sopenharmony_ci	scaledPower = powerLimit - antenna_reduction;
42762306a36Sopenharmony_ci	scaledPower = min_t(u16, scaledPower, MAX_RATE_POWER);
42862306a36Sopenharmony_ci	numCtlModes = ARRAY_SIZE(ctlModesFor11g) - SUB_NUM_CTL_MODES_AT_2G_40;
42962306a36Sopenharmony_ci	pCtlMode = ctlModesFor11g;
43062306a36Sopenharmony_ci
43162306a36Sopenharmony_ci	ath9k_hw_get_legacy_target_powers(ah, chan,
43262306a36Sopenharmony_ci			pEepData->calTargetPowerCck,
43362306a36Sopenharmony_ci			AR5416_NUM_2G_CCK_TARGET_POWERS,
43462306a36Sopenharmony_ci			&targetPowerCck, 4, false);
43562306a36Sopenharmony_ci	ath9k_hw_get_legacy_target_powers(ah, chan,
43662306a36Sopenharmony_ci			pEepData->calTargetPower2G,
43762306a36Sopenharmony_ci			AR5416_NUM_2G_20_TARGET_POWERS,
43862306a36Sopenharmony_ci			&targetPowerOfdm, 4, false);
43962306a36Sopenharmony_ci	ath9k_hw_get_target_powers(ah, chan,
44062306a36Sopenharmony_ci			pEepData->calTargetPower2GHT20,
44162306a36Sopenharmony_ci			AR5416_NUM_2G_20_TARGET_POWERS,
44262306a36Sopenharmony_ci			&targetPowerHt20, 8, false);
44362306a36Sopenharmony_ci
44462306a36Sopenharmony_ci	if (IS_CHAN_HT40(chan)) {
44562306a36Sopenharmony_ci		numCtlModes = ARRAY_SIZE(ctlModesFor11g);
44662306a36Sopenharmony_ci		ath9k_hw_get_target_powers(ah, chan,
44762306a36Sopenharmony_ci				pEepData->calTargetPower2GHT40,
44862306a36Sopenharmony_ci				AR5416_NUM_2G_40_TARGET_POWERS,
44962306a36Sopenharmony_ci				&targetPowerHt40, 8, true);
45062306a36Sopenharmony_ci		ath9k_hw_get_legacy_target_powers(ah, chan,
45162306a36Sopenharmony_ci				pEepData->calTargetPowerCck,
45262306a36Sopenharmony_ci				AR5416_NUM_2G_CCK_TARGET_POWERS,
45362306a36Sopenharmony_ci				&targetPowerCckExt, 4, true);
45462306a36Sopenharmony_ci		ath9k_hw_get_legacy_target_powers(ah, chan,
45562306a36Sopenharmony_ci				pEepData->calTargetPower2G,
45662306a36Sopenharmony_ci				AR5416_NUM_2G_20_TARGET_POWERS,
45762306a36Sopenharmony_ci				&targetPowerOfdmExt, 4, true);
45862306a36Sopenharmony_ci	}
45962306a36Sopenharmony_ci
46062306a36Sopenharmony_ci	for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) {
46162306a36Sopenharmony_ci		bool isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) ||
46262306a36Sopenharmony_ci			(pCtlMode[ctlMode] == CTL_2GHT40);
46362306a36Sopenharmony_ci
46462306a36Sopenharmony_ci		if (isHt40CtlMode)
46562306a36Sopenharmony_ci			freq = centers.synth_center;
46662306a36Sopenharmony_ci		else if (pCtlMode[ctlMode] & EXT_ADDITIVE)
46762306a36Sopenharmony_ci			freq = centers.ext_center;
46862306a36Sopenharmony_ci		else
46962306a36Sopenharmony_ci			freq = centers.ctl_center;
47062306a36Sopenharmony_ci
47162306a36Sopenharmony_ci		twiceMaxEdgePower = MAX_RATE_POWER;
47262306a36Sopenharmony_ci
47362306a36Sopenharmony_ci		for (i = 0; (i < AR5416_EEP4K_NUM_CTLS) &&
47462306a36Sopenharmony_ci			     pEepData->ctlIndex[i]; i++) {
47562306a36Sopenharmony_ci
47662306a36Sopenharmony_ci			if (CMP_TEST_GRP) {
47762306a36Sopenharmony_ci				rep = &(pEepData->ctlData[i]);
47862306a36Sopenharmony_ci
47962306a36Sopenharmony_ci				twiceMinEdgePower = ath9k_hw_get_max_edge_power(
48062306a36Sopenharmony_ci					freq,
48162306a36Sopenharmony_ci					rep->ctlEdges[
48262306a36Sopenharmony_ci					ar5416_get_ntxchains(ah->txchainmask) - 1],
48362306a36Sopenharmony_ci					IS_CHAN_2GHZ(chan),
48462306a36Sopenharmony_ci					AR5416_EEP4K_NUM_BAND_EDGES);
48562306a36Sopenharmony_ci
48662306a36Sopenharmony_ci				if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) {
48762306a36Sopenharmony_ci					twiceMaxEdgePower =
48862306a36Sopenharmony_ci						min(twiceMaxEdgePower,
48962306a36Sopenharmony_ci						    twiceMinEdgePower);
49062306a36Sopenharmony_ci				} else {
49162306a36Sopenharmony_ci					twiceMaxEdgePower = twiceMinEdgePower;
49262306a36Sopenharmony_ci					break;
49362306a36Sopenharmony_ci				}
49462306a36Sopenharmony_ci			}
49562306a36Sopenharmony_ci		}
49662306a36Sopenharmony_ci
49762306a36Sopenharmony_ci		minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower);
49862306a36Sopenharmony_ci
49962306a36Sopenharmony_ci		switch (pCtlMode[ctlMode]) {
50062306a36Sopenharmony_ci		case CTL_11B:
50162306a36Sopenharmony_ci			for (i = 0; i < ARRAY_SIZE(targetPowerCck.tPow2x); i++) {
50262306a36Sopenharmony_ci				targetPowerCck.tPow2x[i] =
50362306a36Sopenharmony_ci					min((u16)targetPowerCck.tPow2x[i],
50462306a36Sopenharmony_ci					    minCtlPower);
50562306a36Sopenharmony_ci			}
50662306a36Sopenharmony_ci			break;
50762306a36Sopenharmony_ci		case CTL_11G:
50862306a36Sopenharmony_ci			for (i = 0; i < ARRAY_SIZE(targetPowerOfdm.tPow2x); i++) {
50962306a36Sopenharmony_ci				targetPowerOfdm.tPow2x[i] =
51062306a36Sopenharmony_ci					min((u16)targetPowerOfdm.tPow2x[i],
51162306a36Sopenharmony_ci					    minCtlPower);
51262306a36Sopenharmony_ci			}
51362306a36Sopenharmony_ci			break;
51462306a36Sopenharmony_ci		case CTL_2GHT20:
51562306a36Sopenharmony_ci			for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++) {
51662306a36Sopenharmony_ci				targetPowerHt20.tPow2x[i] =
51762306a36Sopenharmony_ci					min((u16)targetPowerHt20.tPow2x[i],
51862306a36Sopenharmony_ci					    minCtlPower);
51962306a36Sopenharmony_ci			}
52062306a36Sopenharmony_ci			break;
52162306a36Sopenharmony_ci		case CTL_11B_EXT:
52262306a36Sopenharmony_ci			targetPowerCckExt.tPow2x[0] =
52362306a36Sopenharmony_ci				min((u16)targetPowerCckExt.tPow2x[0],
52462306a36Sopenharmony_ci				    minCtlPower);
52562306a36Sopenharmony_ci			break;
52662306a36Sopenharmony_ci		case CTL_11G_EXT:
52762306a36Sopenharmony_ci			targetPowerOfdmExt.tPow2x[0] =
52862306a36Sopenharmony_ci				min((u16)targetPowerOfdmExt.tPow2x[0],
52962306a36Sopenharmony_ci				    minCtlPower);
53062306a36Sopenharmony_ci			break;
53162306a36Sopenharmony_ci		case CTL_2GHT40:
53262306a36Sopenharmony_ci			for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {
53362306a36Sopenharmony_ci				targetPowerHt40.tPow2x[i] =
53462306a36Sopenharmony_ci					min((u16)targetPowerHt40.tPow2x[i],
53562306a36Sopenharmony_ci					    minCtlPower);
53662306a36Sopenharmony_ci			}
53762306a36Sopenharmony_ci			break;
53862306a36Sopenharmony_ci		default:
53962306a36Sopenharmony_ci			break;
54062306a36Sopenharmony_ci		}
54162306a36Sopenharmony_ci	}
54262306a36Sopenharmony_ci
54362306a36Sopenharmony_ci	ratesArray[rate6mb] =
54462306a36Sopenharmony_ci	ratesArray[rate9mb] =
54562306a36Sopenharmony_ci	ratesArray[rate12mb] =
54662306a36Sopenharmony_ci	ratesArray[rate18mb] =
54762306a36Sopenharmony_ci	ratesArray[rate24mb] =
54862306a36Sopenharmony_ci	targetPowerOfdm.tPow2x[0];
54962306a36Sopenharmony_ci
55062306a36Sopenharmony_ci	ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1];
55162306a36Sopenharmony_ci	ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2];
55262306a36Sopenharmony_ci	ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3];
55362306a36Sopenharmony_ci	ratesArray[rateXr] = targetPowerOfdm.tPow2x[0];
55462306a36Sopenharmony_ci
55562306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++)
55662306a36Sopenharmony_ci		ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i];
55762306a36Sopenharmony_ci
55862306a36Sopenharmony_ci	ratesArray[rate1l] = targetPowerCck.tPow2x[0];
55962306a36Sopenharmony_ci	ratesArray[rate2s] = ratesArray[rate2l] = targetPowerCck.tPow2x[1];
56062306a36Sopenharmony_ci	ratesArray[rate5_5s] = ratesArray[rate5_5l] = targetPowerCck.tPow2x[2];
56162306a36Sopenharmony_ci	ratesArray[rate11s] = ratesArray[rate11l] = targetPowerCck.tPow2x[3];
56262306a36Sopenharmony_ci
56362306a36Sopenharmony_ci	if (IS_CHAN_HT40(chan)) {
56462306a36Sopenharmony_ci		for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {
56562306a36Sopenharmony_ci			ratesArray[rateHt40_0 + i] =
56662306a36Sopenharmony_ci				targetPowerHt40.tPow2x[i];
56762306a36Sopenharmony_ci		}
56862306a36Sopenharmony_ci		ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0];
56962306a36Sopenharmony_ci		ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0];
57062306a36Sopenharmony_ci		ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0];
57162306a36Sopenharmony_ci		ratesArray[rateExtCck] = targetPowerCckExt.tPow2x[0];
57262306a36Sopenharmony_ci	}
57362306a36Sopenharmony_ci
57462306a36Sopenharmony_ci#undef CMP_TEST_GRP
57562306a36Sopenharmony_ci}
57662306a36Sopenharmony_ci
57762306a36Sopenharmony_cistatic void ath9k_hw_4k_set_txpower(struct ath_hw *ah,
57862306a36Sopenharmony_ci				    struct ath9k_channel *chan,
57962306a36Sopenharmony_ci				    u16 cfgCtl,
58062306a36Sopenharmony_ci				    u8 twiceAntennaReduction,
58162306a36Sopenharmony_ci				    u8 powerLimit, bool test)
58262306a36Sopenharmony_ci{
58362306a36Sopenharmony_ci	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
58462306a36Sopenharmony_ci	struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
58562306a36Sopenharmony_ci	struct modal_eep_4k_header *pModal = &pEepData->modalHeader;
58662306a36Sopenharmony_ci	int16_t ratesArray[Ar5416RateSize];
58762306a36Sopenharmony_ci	u8 ht40PowerIncForPdadc = 2;
58862306a36Sopenharmony_ci	int i;
58962306a36Sopenharmony_ci
59062306a36Sopenharmony_ci	memset(ratesArray, 0, sizeof(ratesArray));
59162306a36Sopenharmony_ci
59262306a36Sopenharmony_ci	if (ath9k_hw_4k_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_2)
59362306a36Sopenharmony_ci		ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
59462306a36Sopenharmony_ci
59562306a36Sopenharmony_ci	ath9k_hw_set_4k_power_per_rate_table(ah, chan,
59662306a36Sopenharmony_ci					     &ratesArray[0], cfgCtl,
59762306a36Sopenharmony_ci					     twiceAntennaReduction,
59862306a36Sopenharmony_ci					     powerLimit);
59962306a36Sopenharmony_ci
60062306a36Sopenharmony_ci	ath9k_hw_set_4k_power_cal_table(ah, chan);
60162306a36Sopenharmony_ci
60262306a36Sopenharmony_ci	regulatory->max_power_level = 0;
60362306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
60462306a36Sopenharmony_ci		if (ratesArray[i] > MAX_RATE_POWER)
60562306a36Sopenharmony_ci			ratesArray[i] = MAX_RATE_POWER;
60662306a36Sopenharmony_ci
60762306a36Sopenharmony_ci		if (ratesArray[i] > regulatory->max_power_level)
60862306a36Sopenharmony_ci			regulatory->max_power_level = ratesArray[i];
60962306a36Sopenharmony_ci	}
61062306a36Sopenharmony_ci
61162306a36Sopenharmony_ci	if (test)
61262306a36Sopenharmony_ci	    return;
61362306a36Sopenharmony_ci
61462306a36Sopenharmony_ci	for (i = 0; i < Ar5416RateSize; i++)
61562306a36Sopenharmony_ci		ratesArray[i] -= AR5416_PWR_TABLE_OFFSET_DB * 2;
61662306a36Sopenharmony_ci
61762306a36Sopenharmony_ci	ENABLE_REGWRITE_BUFFER(ah);
61862306a36Sopenharmony_ci
61962306a36Sopenharmony_ci	/* OFDM power per rate */
62062306a36Sopenharmony_ci	REG_WRITE(ah, AR_PHY_POWER_TX_RATE1,
62162306a36Sopenharmony_ci		  ATH9K_POW_SM(ratesArray[rate18mb], 24)
62262306a36Sopenharmony_ci		  | ATH9K_POW_SM(ratesArray[rate12mb], 16)
62362306a36Sopenharmony_ci		  | ATH9K_POW_SM(ratesArray[rate9mb], 8)
62462306a36Sopenharmony_ci		  | ATH9K_POW_SM(ratesArray[rate6mb], 0));
62562306a36Sopenharmony_ci	REG_WRITE(ah, AR_PHY_POWER_TX_RATE2,
62662306a36Sopenharmony_ci		  ATH9K_POW_SM(ratesArray[rate54mb], 24)
62762306a36Sopenharmony_ci		  | ATH9K_POW_SM(ratesArray[rate48mb], 16)
62862306a36Sopenharmony_ci		  | ATH9K_POW_SM(ratesArray[rate36mb], 8)
62962306a36Sopenharmony_ci		  | ATH9K_POW_SM(ratesArray[rate24mb], 0));
63062306a36Sopenharmony_ci
63162306a36Sopenharmony_ci	/* CCK power per rate */
63262306a36Sopenharmony_ci	REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
63362306a36Sopenharmony_ci		  ATH9K_POW_SM(ratesArray[rate2s], 24)
63462306a36Sopenharmony_ci		  | ATH9K_POW_SM(ratesArray[rate2l], 16)
63562306a36Sopenharmony_ci		  | ATH9K_POW_SM(ratesArray[rateXr], 8)
63662306a36Sopenharmony_ci		  | ATH9K_POW_SM(ratesArray[rate1l], 0));
63762306a36Sopenharmony_ci	REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
63862306a36Sopenharmony_ci		  ATH9K_POW_SM(ratesArray[rate11s], 24)
63962306a36Sopenharmony_ci		  | ATH9K_POW_SM(ratesArray[rate11l], 16)
64062306a36Sopenharmony_ci		  | ATH9K_POW_SM(ratesArray[rate5_5s], 8)
64162306a36Sopenharmony_ci		  | ATH9K_POW_SM(ratesArray[rate5_5l], 0));
64262306a36Sopenharmony_ci
64362306a36Sopenharmony_ci	/* HT20 power per rate */
64462306a36Sopenharmony_ci	REG_WRITE(ah, AR_PHY_POWER_TX_RATE5,
64562306a36Sopenharmony_ci		  ATH9K_POW_SM(ratesArray[rateHt20_3], 24)
64662306a36Sopenharmony_ci		  | ATH9K_POW_SM(ratesArray[rateHt20_2], 16)
64762306a36Sopenharmony_ci		  | ATH9K_POW_SM(ratesArray[rateHt20_1], 8)
64862306a36Sopenharmony_ci		  | ATH9K_POW_SM(ratesArray[rateHt20_0], 0));
64962306a36Sopenharmony_ci	REG_WRITE(ah, AR_PHY_POWER_TX_RATE6,
65062306a36Sopenharmony_ci		  ATH9K_POW_SM(ratesArray[rateHt20_7], 24)
65162306a36Sopenharmony_ci		  | ATH9K_POW_SM(ratesArray[rateHt20_6], 16)
65262306a36Sopenharmony_ci		  | ATH9K_POW_SM(ratesArray[rateHt20_5], 8)
65362306a36Sopenharmony_ci		  | ATH9K_POW_SM(ratesArray[rateHt20_4], 0));
65462306a36Sopenharmony_ci
65562306a36Sopenharmony_ci	/* HT40 power per rate */
65662306a36Sopenharmony_ci	if (IS_CHAN_HT40(chan)) {
65762306a36Sopenharmony_ci		REG_WRITE(ah, AR_PHY_POWER_TX_RATE7,
65862306a36Sopenharmony_ci			  ATH9K_POW_SM(ratesArray[rateHt40_3] +
65962306a36Sopenharmony_ci				       ht40PowerIncForPdadc, 24)
66062306a36Sopenharmony_ci			  | ATH9K_POW_SM(ratesArray[rateHt40_2] +
66162306a36Sopenharmony_ci					 ht40PowerIncForPdadc, 16)
66262306a36Sopenharmony_ci			  | ATH9K_POW_SM(ratesArray[rateHt40_1] +
66362306a36Sopenharmony_ci					 ht40PowerIncForPdadc, 8)
66462306a36Sopenharmony_ci			  | ATH9K_POW_SM(ratesArray[rateHt40_0] +
66562306a36Sopenharmony_ci					 ht40PowerIncForPdadc, 0));
66662306a36Sopenharmony_ci		REG_WRITE(ah, AR_PHY_POWER_TX_RATE8,
66762306a36Sopenharmony_ci			  ATH9K_POW_SM(ratesArray[rateHt40_7] +
66862306a36Sopenharmony_ci				       ht40PowerIncForPdadc, 24)
66962306a36Sopenharmony_ci			  | ATH9K_POW_SM(ratesArray[rateHt40_6] +
67062306a36Sopenharmony_ci					 ht40PowerIncForPdadc, 16)
67162306a36Sopenharmony_ci			  | ATH9K_POW_SM(ratesArray[rateHt40_5] +
67262306a36Sopenharmony_ci					 ht40PowerIncForPdadc, 8)
67362306a36Sopenharmony_ci			  | ATH9K_POW_SM(ratesArray[rateHt40_4] +
67462306a36Sopenharmony_ci					 ht40PowerIncForPdadc, 0));
67562306a36Sopenharmony_ci		REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
67662306a36Sopenharmony_ci			  ATH9K_POW_SM(ratesArray[rateExtOfdm], 24)
67762306a36Sopenharmony_ci			  | ATH9K_POW_SM(ratesArray[rateExtCck], 16)
67862306a36Sopenharmony_ci			  | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
67962306a36Sopenharmony_ci			  | ATH9K_POW_SM(ratesArray[rateDupCck], 0));
68062306a36Sopenharmony_ci	}
68162306a36Sopenharmony_ci
68262306a36Sopenharmony_ci	/* TPC initializations */
68362306a36Sopenharmony_ci	if (ah->tpc_enabled) {
68462306a36Sopenharmony_ci		int ht40_delta;
68562306a36Sopenharmony_ci
68662306a36Sopenharmony_ci		ht40_delta = (IS_CHAN_HT40(chan)) ? ht40PowerIncForPdadc : 0;
68762306a36Sopenharmony_ci		ar5008_hw_init_rate_txpower(ah, ratesArray, chan, ht40_delta);
68862306a36Sopenharmony_ci		/* Enable TPC */
68962306a36Sopenharmony_ci		REG_WRITE(ah, AR_PHY_POWER_TX_RATE_MAX,
69062306a36Sopenharmony_ci			MAX_RATE_POWER | AR_PHY_POWER_TX_RATE_MAX_TPC_ENABLE);
69162306a36Sopenharmony_ci	} else {
69262306a36Sopenharmony_ci		/* Disable TPC */
69362306a36Sopenharmony_ci		REG_WRITE(ah, AR_PHY_POWER_TX_RATE_MAX, MAX_RATE_POWER);
69462306a36Sopenharmony_ci	}
69562306a36Sopenharmony_ci
69662306a36Sopenharmony_ci	REGWRITE_BUFFER_FLUSH(ah);
69762306a36Sopenharmony_ci}
69862306a36Sopenharmony_ci
69962306a36Sopenharmony_cistatic void ath9k_hw_4k_set_gain(struct ath_hw *ah,
70062306a36Sopenharmony_ci				 struct modal_eep_4k_header *pModal,
70162306a36Sopenharmony_ci				 struct ar5416_eeprom_4k *eep,
70262306a36Sopenharmony_ci				 u8 txRxAttenLocal)
70362306a36Sopenharmony_ci{
70462306a36Sopenharmony_ci	ENABLE_REG_RMW_BUFFER(ah);
70562306a36Sopenharmony_ci	REG_RMW(ah, AR_PHY_SWITCH_CHAIN_0,
70662306a36Sopenharmony_ci		le32_to_cpu(pModal->antCtrlChain[0]), 0);
70762306a36Sopenharmony_ci
70862306a36Sopenharmony_ci	REG_RMW(ah, AR_PHY_TIMING_CTRL4(0),
70962306a36Sopenharmony_ci		SM(pModal->iqCalICh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) |
71062306a36Sopenharmony_ci		SM(pModal->iqCalQCh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF),
71162306a36Sopenharmony_ci		AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF | AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF);
71262306a36Sopenharmony_ci
71362306a36Sopenharmony_ci	if (ath9k_hw_4k_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_3) {
71462306a36Sopenharmony_ci		txRxAttenLocal = pModal->txRxAttenCh[0];
71562306a36Sopenharmony_ci
71662306a36Sopenharmony_ci		REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ,
71762306a36Sopenharmony_ci			      AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, pModal->bswMargin[0]);
71862306a36Sopenharmony_ci		REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ,
71962306a36Sopenharmony_ci			      AR_PHY_GAIN_2GHZ_XATTEN1_DB, pModal->bswAtten[0]);
72062306a36Sopenharmony_ci		REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ,
72162306a36Sopenharmony_ci			      AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,
72262306a36Sopenharmony_ci			      pModal->xatten2Margin[0]);
72362306a36Sopenharmony_ci		REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ,
72462306a36Sopenharmony_ci			      AR_PHY_GAIN_2GHZ_XATTEN2_DB, pModal->xatten2Db[0]);
72562306a36Sopenharmony_ci
72662306a36Sopenharmony_ci		/* Set the block 1 value to block 0 value */
72762306a36Sopenharmony_ci		REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000,
72862306a36Sopenharmony_ci			      AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN,
72962306a36Sopenharmony_ci			      pModal->bswMargin[0]);
73062306a36Sopenharmony_ci		REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000,
73162306a36Sopenharmony_ci			      AR_PHY_GAIN_2GHZ_XATTEN1_DB, pModal->bswAtten[0]);
73262306a36Sopenharmony_ci		REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000,
73362306a36Sopenharmony_ci			      AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,
73462306a36Sopenharmony_ci			      pModal->xatten2Margin[0]);
73562306a36Sopenharmony_ci		REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000,
73662306a36Sopenharmony_ci			      AR_PHY_GAIN_2GHZ_XATTEN2_DB,
73762306a36Sopenharmony_ci			      pModal->xatten2Db[0]);
73862306a36Sopenharmony_ci	}
73962306a36Sopenharmony_ci
74062306a36Sopenharmony_ci	REG_RMW_FIELD(ah, AR_PHY_RXGAIN,
74162306a36Sopenharmony_ci		      AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal);
74262306a36Sopenharmony_ci	REG_RMW_FIELD(ah, AR_PHY_RXGAIN,
74362306a36Sopenharmony_ci		      AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[0]);
74462306a36Sopenharmony_ci
74562306a36Sopenharmony_ci	REG_RMW_FIELD(ah, AR_PHY_RXGAIN + 0x1000,
74662306a36Sopenharmony_ci		      AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal);
74762306a36Sopenharmony_ci	REG_RMW_FIELD(ah, AR_PHY_RXGAIN + 0x1000,
74862306a36Sopenharmony_ci		      AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[0]);
74962306a36Sopenharmony_ci	REG_RMW_BUFFER_FLUSH(ah);
75062306a36Sopenharmony_ci}
75162306a36Sopenharmony_ci
75262306a36Sopenharmony_ci/*
75362306a36Sopenharmony_ci * Read EEPROM header info and program the device for correct operation
75462306a36Sopenharmony_ci * given the channel value.
75562306a36Sopenharmony_ci */
75662306a36Sopenharmony_cistatic void ath9k_hw_4k_set_board_values(struct ath_hw *ah,
75762306a36Sopenharmony_ci					 struct ath9k_channel *chan)
75862306a36Sopenharmony_ci{
75962306a36Sopenharmony_ci	struct ath9k_hw_capabilities *pCap = &ah->caps;
76062306a36Sopenharmony_ci	struct modal_eep_4k_header *pModal;
76162306a36Sopenharmony_ci	struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
76262306a36Sopenharmony_ci	struct base_eep_header_4k *pBase = &eep->baseEepHeader;
76362306a36Sopenharmony_ci	u8 txRxAttenLocal;
76462306a36Sopenharmony_ci	u8 ob[5], db1[5], db2[5];
76562306a36Sopenharmony_ci	u8 ant_div_control1, ant_div_control2;
76662306a36Sopenharmony_ci	u8 bb_desired_scale;
76762306a36Sopenharmony_ci	u32 regVal;
76862306a36Sopenharmony_ci
76962306a36Sopenharmony_ci	pModal = &eep->modalHeader;
77062306a36Sopenharmony_ci	txRxAttenLocal = 23;
77162306a36Sopenharmony_ci
77262306a36Sopenharmony_ci	REG_WRITE(ah, AR_PHY_SWITCH_COM, le32_to_cpu(pModal->antCtrlCommon));
77362306a36Sopenharmony_ci
77462306a36Sopenharmony_ci	/* Single chain for 4K EEPROM*/
77562306a36Sopenharmony_ci	ath9k_hw_4k_set_gain(ah, pModal, eep, txRxAttenLocal);
77662306a36Sopenharmony_ci
77762306a36Sopenharmony_ci	/* Initialize Ant Diversity settings from EEPROM */
77862306a36Sopenharmony_ci	if (pModal->version >= 3) {
77962306a36Sopenharmony_ci		ant_div_control1 = pModal->antdiv_ctl1;
78062306a36Sopenharmony_ci		ant_div_control2 = pModal->antdiv_ctl2;
78162306a36Sopenharmony_ci
78262306a36Sopenharmony_ci		regVal = REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL);
78362306a36Sopenharmony_ci		regVal &= (~(AR_PHY_9285_ANT_DIV_CTL_ALL));
78462306a36Sopenharmony_ci
78562306a36Sopenharmony_ci		regVal |= SM(ant_div_control1,
78662306a36Sopenharmony_ci			     AR_PHY_9285_ANT_DIV_CTL);
78762306a36Sopenharmony_ci		regVal |= SM(ant_div_control2,
78862306a36Sopenharmony_ci			     AR_PHY_9285_ANT_DIV_ALT_LNACONF);
78962306a36Sopenharmony_ci		regVal |= SM((ant_div_control2 >> 2),
79062306a36Sopenharmony_ci			     AR_PHY_9285_ANT_DIV_MAIN_LNACONF);
79162306a36Sopenharmony_ci		regVal |= SM((ant_div_control1 >> 1),
79262306a36Sopenharmony_ci			     AR_PHY_9285_ANT_DIV_ALT_GAINTB);
79362306a36Sopenharmony_ci		regVal |= SM((ant_div_control1 >> 2),
79462306a36Sopenharmony_ci			     AR_PHY_9285_ANT_DIV_MAIN_GAINTB);
79562306a36Sopenharmony_ci
79662306a36Sopenharmony_ci
79762306a36Sopenharmony_ci		REG_WRITE(ah, AR_PHY_MULTICHAIN_GAIN_CTL, regVal);
79862306a36Sopenharmony_ci		regVal = REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL);
79962306a36Sopenharmony_ci		regVal = REG_READ(ah, AR_PHY_CCK_DETECT);
80062306a36Sopenharmony_ci		regVal &= (~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV);
80162306a36Sopenharmony_ci		regVal |= SM((ant_div_control1 >> 3),
80262306a36Sopenharmony_ci			     AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV);
80362306a36Sopenharmony_ci
80462306a36Sopenharmony_ci		REG_WRITE(ah, AR_PHY_CCK_DETECT, regVal);
80562306a36Sopenharmony_ci		regVal = REG_READ(ah, AR_PHY_CCK_DETECT);
80662306a36Sopenharmony_ci
80762306a36Sopenharmony_ci		if (pCap->hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) {
80862306a36Sopenharmony_ci			/*
80962306a36Sopenharmony_ci			 * If diversity combining is enabled,
81062306a36Sopenharmony_ci			 * set MAIN to LNA1 and ALT to LNA2 initially.
81162306a36Sopenharmony_ci			 */
81262306a36Sopenharmony_ci			regVal = REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL);
81362306a36Sopenharmony_ci			regVal &= (~(AR_PHY_9285_ANT_DIV_MAIN_LNACONF |
81462306a36Sopenharmony_ci				     AR_PHY_9285_ANT_DIV_ALT_LNACONF));
81562306a36Sopenharmony_ci
81662306a36Sopenharmony_ci			regVal |= (ATH_ANT_DIV_COMB_LNA1 <<
81762306a36Sopenharmony_ci				   AR_PHY_9285_ANT_DIV_MAIN_LNACONF_S);
81862306a36Sopenharmony_ci			regVal |= (ATH_ANT_DIV_COMB_LNA2 <<
81962306a36Sopenharmony_ci				   AR_PHY_9285_ANT_DIV_ALT_LNACONF_S);
82062306a36Sopenharmony_ci			regVal &= (~(AR_PHY_9285_FAST_DIV_BIAS));
82162306a36Sopenharmony_ci			regVal |= (0 << AR_PHY_9285_FAST_DIV_BIAS_S);
82262306a36Sopenharmony_ci			REG_WRITE(ah, AR_PHY_MULTICHAIN_GAIN_CTL, regVal);
82362306a36Sopenharmony_ci		}
82462306a36Sopenharmony_ci	}
82562306a36Sopenharmony_ci
82662306a36Sopenharmony_ci	if (pModal->version >= 2) {
82762306a36Sopenharmony_ci		ob[0] = pModal->ob_0;
82862306a36Sopenharmony_ci		ob[1] = pModal->ob_1;
82962306a36Sopenharmony_ci		ob[2] = pModal->ob_2;
83062306a36Sopenharmony_ci		ob[3] = pModal->ob_3;
83162306a36Sopenharmony_ci		ob[4] = pModal->ob_4;
83262306a36Sopenharmony_ci
83362306a36Sopenharmony_ci		db1[0] = pModal->db1_0;
83462306a36Sopenharmony_ci		db1[1] = pModal->db1_1;
83562306a36Sopenharmony_ci		db1[2] = pModal->db1_2;
83662306a36Sopenharmony_ci		db1[3] = pModal->db1_3;
83762306a36Sopenharmony_ci		db1[4] = pModal->db1_4;
83862306a36Sopenharmony_ci
83962306a36Sopenharmony_ci		db2[0] = pModal->db2_0;
84062306a36Sopenharmony_ci		db2[1] = pModal->db2_1;
84162306a36Sopenharmony_ci		db2[2] = pModal->db2_2;
84262306a36Sopenharmony_ci		db2[3] = pModal->db2_3;
84362306a36Sopenharmony_ci		db2[4] = pModal->db2_4;
84462306a36Sopenharmony_ci	} else if (pModal->version == 1) {
84562306a36Sopenharmony_ci		ob[0] = pModal->ob_0;
84662306a36Sopenharmony_ci		ob[1] = ob[2] = ob[3] = ob[4] = pModal->ob_1;
84762306a36Sopenharmony_ci		db1[0] = pModal->db1_0;
84862306a36Sopenharmony_ci		db1[1] = db1[2] = db1[3] = db1[4] = pModal->db1_1;
84962306a36Sopenharmony_ci		db2[0] = pModal->db2_0;
85062306a36Sopenharmony_ci		db2[1] = db2[2] = db2[3] = db2[4] = pModal->db2_1;
85162306a36Sopenharmony_ci	} else {
85262306a36Sopenharmony_ci		int i;
85362306a36Sopenharmony_ci
85462306a36Sopenharmony_ci		for (i = 0; i < 5; i++) {
85562306a36Sopenharmony_ci			ob[i] = pModal->ob_0;
85662306a36Sopenharmony_ci			db1[i] = pModal->db1_0;
85762306a36Sopenharmony_ci			db2[i] = pModal->db1_0;
85862306a36Sopenharmony_ci		}
85962306a36Sopenharmony_ci	}
86062306a36Sopenharmony_ci
86162306a36Sopenharmony_ci	ENABLE_REG_RMW_BUFFER(ah);
86262306a36Sopenharmony_ci	if (AR_SREV_9271(ah)) {
86362306a36Sopenharmony_ci		ath9k_hw_analog_shift_rmw(ah,
86462306a36Sopenharmony_ci					  AR9285_AN_RF2G3,
86562306a36Sopenharmony_ci					  AR9271_AN_RF2G3_OB_cck,
86662306a36Sopenharmony_ci					  AR9271_AN_RF2G3_OB_cck_S,
86762306a36Sopenharmony_ci					  ob[0]);
86862306a36Sopenharmony_ci		ath9k_hw_analog_shift_rmw(ah,
86962306a36Sopenharmony_ci					  AR9285_AN_RF2G3,
87062306a36Sopenharmony_ci					  AR9271_AN_RF2G3_OB_psk,
87162306a36Sopenharmony_ci					  AR9271_AN_RF2G3_OB_psk_S,
87262306a36Sopenharmony_ci					  ob[1]);
87362306a36Sopenharmony_ci		ath9k_hw_analog_shift_rmw(ah,
87462306a36Sopenharmony_ci					  AR9285_AN_RF2G3,
87562306a36Sopenharmony_ci					  AR9271_AN_RF2G3_OB_qam,
87662306a36Sopenharmony_ci					  AR9271_AN_RF2G3_OB_qam_S,
87762306a36Sopenharmony_ci					  ob[2]);
87862306a36Sopenharmony_ci		ath9k_hw_analog_shift_rmw(ah,
87962306a36Sopenharmony_ci					  AR9285_AN_RF2G3,
88062306a36Sopenharmony_ci					  AR9271_AN_RF2G3_DB_1,
88162306a36Sopenharmony_ci					  AR9271_AN_RF2G3_DB_1_S,
88262306a36Sopenharmony_ci					  db1[0]);
88362306a36Sopenharmony_ci		ath9k_hw_analog_shift_rmw(ah,
88462306a36Sopenharmony_ci					  AR9285_AN_RF2G4,
88562306a36Sopenharmony_ci					  AR9271_AN_RF2G4_DB_2,
88662306a36Sopenharmony_ci					  AR9271_AN_RF2G4_DB_2_S,
88762306a36Sopenharmony_ci					  db2[0]);
88862306a36Sopenharmony_ci	} else {
88962306a36Sopenharmony_ci		ath9k_hw_analog_shift_rmw(ah,
89062306a36Sopenharmony_ci					  AR9285_AN_RF2G3,
89162306a36Sopenharmony_ci					  AR9285_AN_RF2G3_OB_0,
89262306a36Sopenharmony_ci					  AR9285_AN_RF2G3_OB_0_S,
89362306a36Sopenharmony_ci					  ob[0]);
89462306a36Sopenharmony_ci		ath9k_hw_analog_shift_rmw(ah,
89562306a36Sopenharmony_ci					  AR9285_AN_RF2G3,
89662306a36Sopenharmony_ci					  AR9285_AN_RF2G3_OB_1,
89762306a36Sopenharmony_ci					  AR9285_AN_RF2G3_OB_1_S,
89862306a36Sopenharmony_ci					  ob[1]);
89962306a36Sopenharmony_ci		ath9k_hw_analog_shift_rmw(ah,
90062306a36Sopenharmony_ci					  AR9285_AN_RF2G3,
90162306a36Sopenharmony_ci					  AR9285_AN_RF2G3_OB_2,
90262306a36Sopenharmony_ci					  AR9285_AN_RF2G3_OB_2_S,
90362306a36Sopenharmony_ci					  ob[2]);
90462306a36Sopenharmony_ci		ath9k_hw_analog_shift_rmw(ah,
90562306a36Sopenharmony_ci					  AR9285_AN_RF2G3,
90662306a36Sopenharmony_ci					  AR9285_AN_RF2G3_OB_3,
90762306a36Sopenharmony_ci					  AR9285_AN_RF2G3_OB_3_S,
90862306a36Sopenharmony_ci					  ob[3]);
90962306a36Sopenharmony_ci		ath9k_hw_analog_shift_rmw(ah,
91062306a36Sopenharmony_ci					  AR9285_AN_RF2G3,
91162306a36Sopenharmony_ci					  AR9285_AN_RF2G3_OB_4,
91262306a36Sopenharmony_ci					  AR9285_AN_RF2G3_OB_4_S,
91362306a36Sopenharmony_ci					  ob[4]);
91462306a36Sopenharmony_ci
91562306a36Sopenharmony_ci		ath9k_hw_analog_shift_rmw(ah,
91662306a36Sopenharmony_ci					  AR9285_AN_RF2G3,
91762306a36Sopenharmony_ci					  AR9285_AN_RF2G3_DB1_0,
91862306a36Sopenharmony_ci					  AR9285_AN_RF2G3_DB1_0_S,
91962306a36Sopenharmony_ci					  db1[0]);
92062306a36Sopenharmony_ci		ath9k_hw_analog_shift_rmw(ah,
92162306a36Sopenharmony_ci					  AR9285_AN_RF2G3,
92262306a36Sopenharmony_ci					  AR9285_AN_RF2G3_DB1_1,
92362306a36Sopenharmony_ci					  AR9285_AN_RF2G3_DB1_1_S,
92462306a36Sopenharmony_ci					  db1[1]);
92562306a36Sopenharmony_ci		ath9k_hw_analog_shift_rmw(ah,
92662306a36Sopenharmony_ci					  AR9285_AN_RF2G3,
92762306a36Sopenharmony_ci					  AR9285_AN_RF2G3_DB1_2,
92862306a36Sopenharmony_ci					  AR9285_AN_RF2G3_DB1_2_S,
92962306a36Sopenharmony_ci					  db1[2]);
93062306a36Sopenharmony_ci		ath9k_hw_analog_shift_rmw(ah,
93162306a36Sopenharmony_ci					  AR9285_AN_RF2G4,
93262306a36Sopenharmony_ci					  AR9285_AN_RF2G4_DB1_3,
93362306a36Sopenharmony_ci					  AR9285_AN_RF2G4_DB1_3_S,
93462306a36Sopenharmony_ci					  db1[3]);
93562306a36Sopenharmony_ci		ath9k_hw_analog_shift_rmw(ah,
93662306a36Sopenharmony_ci					  AR9285_AN_RF2G4,
93762306a36Sopenharmony_ci					  AR9285_AN_RF2G4_DB1_4,
93862306a36Sopenharmony_ci					  AR9285_AN_RF2G4_DB1_4_S, db1[4]);
93962306a36Sopenharmony_ci
94062306a36Sopenharmony_ci		ath9k_hw_analog_shift_rmw(ah,
94162306a36Sopenharmony_ci					  AR9285_AN_RF2G4,
94262306a36Sopenharmony_ci					  AR9285_AN_RF2G4_DB2_0,
94362306a36Sopenharmony_ci					  AR9285_AN_RF2G4_DB2_0_S,
94462306a36Sopenharmony_ci					  db2[0]);
94562306a36Sopenharmony_ci		ath9k_hw_analog_shift_rmw(ah,
94662306a36Sopenharmony_ci					  AR9285_AN_RF2G4,
94762306a36Sopenharmony_ci					  AR9285_AN_RF2G4_DB2_1,
94862306a36Sopenharmony_ci					  AR9285_AN_RF2G4_DB2_1_S,
94962306a36Sopenharmony_ci					  db2[1]);
95062306a36Sopenharmony_ci		ath9k_hw_analog_shift_rmw(ah,
95162306a36Sopenharmony_ci					  AR9285_AN_RF2G4,
95262306a36Sopenharmony_ci					  AR9285_AN_RF2G4_DB2_2,
95362306a36Sopenharmony_ci					  AR9285_AN_RF2G4_DB2_2_S,
95462306a36Sopenharmony_ci					  db2[2]);
95562306a36Sopenharmony_ci		ath9k_hw_analog_shift_rmw(ah,
95662306a36Sopenharmony_ci					  AR9285_AN_RF2G4,
95762306a36Sopenharmony_ci					  AR9285_AN_RF2G4_DB2_3,
95862306a36Sopenharmony_ci					  AR9285_AN_RF2G4_DB2_3_S,
95962306a36Sopenharmony_ci					  db2[3]);
96062306a36Sopenharmony_ci		ath9k_hw_analog_shift_rmw(ah,
96162306a36Sopenharmony_ci					  AR9285_AN_RF2G4,
96262306a36Sopenharmony_ci					  AR9285_AN_RF2G4_DB2_4,
96362306a36Sopenharmony_ci					  AR9285_AN_RF2G4_DB2_4_S,
96462306a36Sopenharmony_ci					  db2[4]);
96562306a36Sopenharmony_ci	}
96662306a36Sopenharmony_ci	REG_RMW_BUFFER_FLUSH(ah);
96762306a36Sopenharmony_ci
96862306a36Sopenharmony_ci	ENABLE_REG_RMW_BUFFER(ah);
96962306a36Sopenharmony_ci	REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH,
97062306a36Sopenharmony_ci		      pModal->switchSettling);
97162306a36Sopenharmony_ci	REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC,
97262306a36Sopenharmony_ci		      pModal->adcDesiredSize);
97362306a36Sopenharmony_ci
97462306a36Sopenharmony_ci	REG_RMW(ah, AR_PHY_RF_CTL4,
97562306a36Sopenharmony_ci		SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF) |
97662306a36Sopenharmony_ci		SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAB_OFF) |
97762306a36Sopenharmony_ci		SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAA_ON)  |
97862306a36Sopenharmony_ci		SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAB_ON), 0);
97962306a36Sopenharmony_ci
98062306a36Sopenharmony_ci	REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON,
98162306a36Sopenharmony_ci		      pModal->txEndToRxOn);
98262306a36Sopenharmony_ci
98362306a36Sopenharmony_ci	if (AR_SREV_9271_10(ah))
98462306a36Sopenharmony_ci		REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON,
98562306a36Sopenharmony_ci			      pModal->txEndToRxOn);
98662306a36Sopenharmony_ci	REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62,
98762306a36Sopenharmony_ci		      pModal->thresh62);
98862306a36Sopenharmony_ci	REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, AR_PHY_EXT_CCA0_THRESH62,
98962306a36Sopenharmony_ci		      pModal->thresh62);
99062306a36Sopenharmony_ci
99162306a36Sopenharmony_ci	if (ath9k_hw_4k_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_2) {
99262306a36Sopenharmony_ci		REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_DATA_START,
99362306a36Sopenharmony_ci			      pModal->txFrameToDataStart);
99462306a36Sopenharmony_ci		REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_PA_ON,
99562306a36Sopenharmony_ci			      pModal->txFrameToPaOn);
99662306a36Sopenharmony_ci	}
99762306a36Sopenharmony_ci
99862306a36Sopenharmony_ci	if (ath9k_hw_4k_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_3) {
99962306a36Sopenharmony_ci		if (IS_CHAN_HT40(chan))
100062306a36Sopenharmony_ci			REG_RMW_FIELD(ah, AR_PHY_SETTLING,
100162306a36Sopenharmony_ci				      AR_PHY_SETTLING_SWITCH,
100262306a36Sopenharmony_ci				      pModal->swSettleHt40);
100362306a36Sopenharmony_ci	}
100462306a36Sopenharmony_ci
100562306a36Sopenharmony_ci	REG_RMW_BUFFER_FLUSH(ah);
100662306a36Sopenharmony_ci
100762306a36Sopenharmony_ci	bb_desired_scale = (pModal->bb_scale_smrt_antenna &
100862306a36Sopenharmony_ci			EEP_4K_BB_DESIRED_SCALE_MASK);
100962306a36Sopenharmony_ci	if ((pBase->txGainType == 0) && (bb_desired_scale != 0)) {
101062306a36Sopenharmony_ci		u32 pwrctrl, mask, clr;
101162306a36Sopenharmony_ci
101262306a36Sopenharmony_ci		mask = BIT(0)|BIT(5)|BIT(10)|BIT(15)|BIT(20)|BIT(25);
101362306a36Sopenharmony_ci		pwrctrl = mask * bb_desired_scale;
101462306a36Sopenharmony_ci		clr = mask * 0x1f;
101562306a36Sopenharmony_ci		ENABLE_REG_RMW_BUFFER(ah);
101662306a36Sopenharmony_ci		REG_RMW(ah, AR_PHY_TX_PWRCTRL8, pwrctrl, clr);
101762306a36Sopenharmony_ci		REG_RMW(ah, AR_PHY_TX_PWRCTRL10, pwrctrl, clr);
101862306a36Sopenharmony_ci		REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL12, pwrctrl, clr);
101962306a36Sopenharmony_ci
102062306a36Sopenharmony_ci		mask = BIT(0)|BIT(5)|BIT(15);
102162306a36Sopenharmony_ci		pwrctrl = mask * bb_desired_scale;
102262306a36Sopenharmony_ci		clr = mask * 0x1f;
102362306a36Sopenharmony_ci		REG_RMW(ah, AR_PHY_TX_PWRCTRL9, pwrctrl, clr);
102462306a36Sopenharmony_ci
102562306a36Sopenharmony_ci		mask = BIT(0)|BIT(5);
102662306a36Sopenharmony_ci		pwrctrl = mask * bb_desired_scale;
102762306a36Sopenharmony_ci		clr = mask * 0x1f;
102862306a36Sopenharmony_ci		REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL11, pwrctrl, clr);
102962306a36Sopenharmony_ci		REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL13, pwrctrl, clr);
103062306a36Sopenharmony_ci		REG_RMW_BUFFER_FLUSH(ah);
103162306a36Sopenharmony_ci	}
103262306a36Sopenharmony_ci}
103362306a36Sopenharmony_ci
103462306a36Sopenharmony_cistatic u16 ath9k_hw_4k_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz)
103562306a36Sopenharmony_ci{
103662306a36Sopenharmony_ci	return le16_to_cpu(ah->eeprom.map4k.modalHeader.spurChans[i].spurChan);
103762306a36Sopenharmony_ci}
103862306a36Sopenharmony_ci
103962306a36Sopenharmony_cistatic u8 ath9k_hw_4k_get_eepmisc(struct ath_hw *ah)
104062306a36Sopenharmony_ci{
104162306a36Sopenharmony_ci	return ah->eeprom.map4k.baseEepHeader.eepMisc;
104262306a36Sopenharmony_ci}
104362306a36Sopenharmony_ci
104462306a36Sopenharmony_ciconst struct eeprom_ops eep_4k_ops = {
104562306a36Sopenharmony_ci	.check_eeprom		= ath9k_hw_4k_check_eeprom,
104662306a36Sopenharmony_ci	.get_eeprom		= ath9k_hw_4k_get_eeprom,
104762306a36Sopenharmony_ci	.fill_eeprom		= ath9k_hw_4k_fill_eeprom,
104862306a36Sopenharmony_ci	.dump_eeprom		= ath9k_hw_4k_dump_eeprom,
104962306a36Sopenharmony_ci	.get_eeprom_ver		= ath9k_hw_4k_get_eeprom_ver,
105062306a36Sopenharmony_ci	.get_eeprom_rev		= ath9k_hw_4k_get_eeprom_rev,
105162306a36Sopenharmony_ci	.set_board_values	= ath9k_hw_4k_set_board_values,
105262306a36Sopenharmony_ci	.set_txpower		= ath9k_hw_4k_set_txpower,
105362306a36Sopenharmony_ci	.get_spur_channel	= ath9k_hw_4k_get_spur_channel,
105462306a36Sopenharmony_ci	.get_eepmisc		= ath9k_hw_4k_get_eepmisc
105562306a36Sopenharmony_ci};
1056