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 void ath9k_get_txgain_index(struct ath_hw *ah,
2262306a36Sopenharmony_ci		struct ath9k_channel *chan,
2362306a36Sopenharmony_ci		struct calDataPerFreqOpLoop *rawDatasetOpLoop,
2462306a36Sopenharmony_ci		u8 *calChans,  u16 availPiers, u8 *pwr, u8 *pcdacIdx)
2562306a36Sopenharmony_ci{
2662306a36Sopenharmony_ci	u8 pcdac, i = 0;
2762306a36Sopenharmony_ci	u16 idxL = 0, idxR = 0, numPiers;
2862306a36Sopenharmony_ci	bool match;
2962306a36Sopenharmony_ci	struct chan_centers centers;
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci	ath9k_hw_get_channel_centers(ah, chan, &centers);
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci	for (numPiers = 0; numPiers < availPiers; numPiers++)
3462306a36Sopenharmony_ci		if (calChans[numPiers] == AR5416_BCHAN_UNUSED)
3562306a36Sopenharmony_ci			break;
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci	match = ath9k_hw_get_lower_upper_index(
3862306a36Sopenharmony_ci			(u8)FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan)),
3962306a36Sopenharmony_ci			calChans, numPiers, &idxL, &idxR);
4062306a36Sopenharmony_ci	if (match) {
4162306a36Sopenharmony_ci		pcdac = rawDatasetOpLoop[idxL].pcdac[0][0];
4262306a36Sopenharmony_ci		*pwr = rawDatasetOpLoop[idxL].pwrPdg[0][0];
4362306a36Sopenharmony_ci	} else {
4462306a36Sopenharmony_ci		pcdac = rawDatasetOpLoop[idxR].pcdac[0][0];
4562306a36Sopenharmony_ci		*pwr = (rawDatasetOpLoop[idxL].pwrPdg[0][0] +
4662306a36Sopenharmony_ci				rawDatasetOpLoop[idxR].pwrPdg[0][0])/2;
4762306a36Sopenharmony_ci	}
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci	while (pcdac > ah->originalGain[i] &&
5062306a36Sopenharmony_ci			i < (AR9280_TX_GAIN_TABLE_SIZE - 1))
5162306a36Sopenharmony_ci		i++;
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci	*pcdacIdx = i;
5462306a36Sopenharmony_ci}
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_cistatic void ath9k_olc_get_pdadcs(struct ath_hw *ah,
5762306a36Sopenharmony_ci				u32 initTxGain,
5862306a36Sopenharmony_ci				int txPower,
5962306a36Sopenharmony_ci				u8 *pPDADCValues)
6062306a36Sopenharmony_ci{
6162306a36Sopenharmony_ci	u32 i;
6262306a36Sopenharmony_ci	u32 offset;
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci	REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL6_0,
6562306a36Sopenharmony_ci			AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3);
6662306a36Sopenharmony_ci	REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL6_1,
6762306a36Sopenharmony_ci			AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3);
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci	REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL7,
7062306a36Sopenharmony_ci			AR_PHY_TX_PWRCTRL_INIT_TX_GAIN, initTxGain);
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci	offset = txPower;
7362306a36Sopenharmony_ci	for (i = 0; i < AR5416_NUM_PDADC_VALUES; i++)
7462306a36Sopenharmony_ci		if (i < offset)
7562306a36Sopenharmony_ci			pPDADCValues[i] = 0x0;
7662306a36Sopenharmony_ci		else
7762306a36Sopenharmony_ci			pPDADCValues[i] = 0xFF;
7862306a36Sopenharmony_ci}
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_cistatic int ath9k_hw_def_get_eeprom_ver(struct ath_hw *ah)
8162306a36Sopenharmony_ci{
8262306a36Sopenharmony_ci	u16 version = le16_to_cpu(ah->eeprom.def.baseEepHeader.version);
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_ci	return (version & AR5416_EEP_VER_MAJOR_MASK) >>
8562306a36Sopenharmony_ci		AR5416_EEP_VER_MAJOR_SHIFT;
8662306a36Sopenharmony_ci}
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_cistatic int ath9k_hw_def_get_eeprom_rev(struct ath_hw *ah)
8962306a36Sopenharmony_ci{
9062306a36Sopenharmony_ci	u16 version = le16_to_cpu(ah->eeprom.def.baseEepHeader.version);
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci	return version & AR5416_EEP_VER_MINOR_MASK;
9362306a36Sopenharmony_ci}
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci#define SIZE_EEPROM_DEF (sizeof(struct ar5416_eeprom_def) / sizeof(u16))
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_cistatic bool __ath9k_hw_def_fill_eeprom(struct ath_hw *ah)
9862306a36Sopenharmony_ci{
9962306a36Sopenharmony_ci	u16 *eep_data = (u16 *)&ah->eeprom.def;
10062306a36Sopenharmony_ci	int addr, ar5416_eep_start_loc = 0x100;
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ci	for (addr = 0; addr < SIZE_EEPROM_DEF; addr++) {
10362306a36Sopenharmony_ci		if (!ath9k_hw_nvram_read(ah, addr + ar5416_eep_start_loc,
10462306a36Sopenharmony_ci					 eep_data))
10562306a36Sopenharmony_ci			return false;
10662306a36Sopenharmony_ci		eep_data++;
10762306a36Sopenharmony_ci	}
10862306a36Sopenharmony_ci	return true;
10962306a36Sopenharmony_ci}
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_cistatic bool __ath9k_hw_usb_def_fill_eeprom(struct ath_hw *ah)
11262306a36Sopenharmony_ci{
11362306a36Sopenharmony_ci	u16 *eep_data = (u16 *)&ah->eeprom.def;
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ci	ath9k_hw_usb_gen_fill_eeprom(ah, eep_data,
11662306a36Sopenharmony_ci				     0x100, SIZE_EEPROM_DEF);
11762306a36Sopenharmony_ci	return true;
11862306a36Sopenharmony_ci}
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_cistatic bool ath9k_hw_def_fill_eeprom(struct ath_hw *ah)
12162306a36Sopenharmony_ci{
12262306a36Sopenharmony_ci	struct ath_common *common = ath9k_hw_common(ah);
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci	if (!ath9k_hw_use_flash(ah)) {
12562306a36Sopenharmony_ci		ath_dbg(common, EEPROM, "Reading from EEPROM, not flash\n");
12662306a36Sopenharmony_ci	}
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_ci	if (common->bus_ops->ath_bus_type == ATH_USB)
12962306a36Sopenharmony_ci		return __ath9k_hw_usb_def_fill_eeprom(ah);
13062306a36Sopenharmony_ci	else
13162306a36Sopenharmony_ci		return __ath9k_hw_def_fill_eeprom(ah);
13262306a36Sopenharmony_ci}
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci#ifdef CONFIG_ATH9K_COMMON_DEBUG
13562306a36Sopenharmony_cistatic u32 ath9k_def_dump_modal_eeprom(char *buf, u32 len, u32 size,
13662306a36Sopenharmony_ci				       struct modal_eep_header *modal_hdr)
13762306a36Sopenharmony_ci{
13862306a36Sopenharmony_ci	PR_EEP("Chain0 Ant. Control", le16_to_cpu(modal_hdr->antCtrlChain[0]));
13962306a36Sopenharmony_ci	PR_EEP("Chain1 Ant. Control", le16_to_cpu(modal_hdr->antCtrlChain[1]));
14062306a36Sopenharmony_ci	PR_EEP("Chain2 Ant. Control", le16_to_cpu(modal_hdr->antCtrlChain[2]));
14162306a36Sopenharmony_ci	PR_EEP("Ant. Common Control", le32_to_cpu(modal_hdr->antCtrlCommon));
14262306a36Sopenharmony_ci	PR_EEP("Chain0 Ant. Gain", modal_hdr->antennaGainCh[0]);
14362306a36Sopenharmony_ci	PR_EEP("Chain1 Ant. Gain", modal_hdr->antennaGainCh[1]);
14462306a36Sopenharmony_ci	PR_EEP("Chain2 Ant. Gain", modal_hdr->antennaGainCh[2]);
14562306a36Sopenharmony_ci	PR_EEP("Switch Settle", modal_hdr->switchSettling);
14662306a36Sopenharmony_ci	PR_EEP("Chain0 TxRxAtten", modal_hdr->txRxAttenCh[0]);
14762306a36Sopenharmony_ci	PR_EEP("Chain1 TxRxAtten", modal_hdr->txRxAttenCh[1]);
14862306a36Sopenharmony_ci	PR_EEP("Chain2 TxRxAtten", modal_hdr->txRxAttenCh[2]);
14962306a36Sopenharmony_ci	PR_EEP("Chain0 RxTxMargin", modal_hdr->rxTxMarginCh[0]);
15062306a36Sopenharmony_ci	PR_EEP("Chain1 RxTxMargin", modal_hdr->rxTxMarginCh[1]);
15162306a36Sopenharmony_ci	PR_EEP("Chain2 RxTxMargin", modal_hdr->rxTxMarginCh[2]);
15262306a36Sopenharmony_ci	PR_EEP("ADC Desired size", modal_hdr->adcDesiredSize);
15362306a36Sopenharmony_ci	PR_EEP("PGA Desired size", modal_hdr->pgaDesiredSize);
15462306a36Sopenharmony_ci	PR_EEP("Chain0 xlna Gain", modal_hdr->xlnaGainCh[0]);
15562306a36Sopenharmony_ci	PR_EEP("Chain1 xlna Gain", modal_hdr->xlnaGainCh[1]);
15662306a36Sopenharmony_ci	PR_EEP("Chain2 xlna Gain", modal_hdr->xlnaGainCh[2]);
15762306a36Sopenharmony_ci	PR_EEP("txEndToXpaOff", modal_hdr->txEndToXpaOff);
15862306a36Sopenharmony_ci	PR_EEP("txEndToRxOn", modal_hdr->txEndToRxOn);
15962306a36Sopenharmony_ci	PR_EEP("txFrameToXpaOn", modal_hdr->txFrameToXpaOn);
16062306a36Sopenharmony_ci	PR_EEP("CCA Threshold)", modal_hdr->thresh62);
16162306a36Sopenharmony_ci	PR_EEP("Chain0 NF Threshold", modal_hdr->noiseFloorThreshCh[0]);
16262306a36Sopenharmony_ci	PR_EEP("Chain1 NF Threshold", modal_hdr->noiseFloorThreshCh[1]);
16362306a36Sopenharmony_ci	PR_EEP("Chain2 NF Threshold", modal_hdr->noiseFloorThreshCh[2]);
16462306a36Sopenharmony_ci	PR_EEP("xpdGain", modal_hdr->xpdGain);
16562306a36Sopenharmony_ci	PR_EEP("External PD", modal_hdr->xpd);
16662306a36Sopenharmony_ci	PR_EEP("Chain0 I Coefficient", modal_hdr->iqCalICh[0]);
16762306a36Sopenharmony_ci	PR_EEP("Chain1 I Coefficient", modal_hdr->iqCalICh[1]);
16862306a36Sopenharmony_ci	PR_EEP("Chain2 I Coefficient", modal_hdr->iqCalICh[2]);
16962306a36Sopenharmony_ci	PR_EEP("Chain0 Q Coefficient", modal_hdr->iqCalQCh[0]);
17062306a36Sopenharmony_ci	PR_EEP("Chain1 Q Coefficient", modal_hdr->iqCalQCh[1]);
17162306a36Sopenharmony_ci	PR_EEP("Chain2 Q Coefficient", modal_hdr->iqCalQCh[2]);
17262306a36Sopenharmony_ci	PR_EEP("pdGainOverlap", modal_hdr->pdGainOverlap);
17362306a36Sopenharmony_ci	PR_EEP("Chain0 OutputBias", modal_hdr->ob);
17462306a36Sopenharmony_ci	PR_EEP("Chain0 DriverBias", modal_hdr->db);
17562306a36Sopenharmony_ci	PR_EEP("xPA Bias Level", modal_hdr->xpaBiasLvl);
17662306a36Sopenharmony_ci	PR_EEP("2chain pwr decrease", modal_hdr->pwrDecreaseFor2Chain);
17762306a36Sopenharmony_ci	PR_EEP("3chain pwr decrease", modal_hdr->pwrDecreaseFor3Chain);
17862306a36Sopenharmony_ci	PR_EEP("txFrameToDataStart", modal_hdr->txFrameToDataStart);
17962306a36Sopenharmony_ci	PR_EEP("txFrameToPaOn", modal_hdr->txFrameToPaOn);
18062306a36Sopenharmony_ci	PR_EEP("HT40 Power Inc.", modal_hdr->ht40PowerIncForPdadc);
18162306a36Sopenharmony_ci	PR_EEP("Chain0 bswAtten", modal_hdr->bswAtten[0]);
18262306a36Sopenharmony_ci	PR_EEP("Chain1 bswAtten", modal_hdr->bswAtten[1]);
18362306a36Sopenharmony_ci	PR_EEP("Chain2 bswAtten", modal_hdr->bswAtten[2]);
18462306a36Sopenharmony_ci	PR_EEP("Chain0 bswMargin", modal_hdr->bswMargin[0]);
18562306a36Sopenharmony_ci	PR_EEP("Chain1 bswMargin", modal_hdr->bswMargin[1]);
18662306a36Sopenharmony_ci	PR_EEP("Chain2 bswMargin", modal_hdr->bswMargin[2]);
18762306a36Sopenharmony_ci	PR_EEP("HT40 Switch Settle", modal_hdr->swSettleHt40);
18862306a36Sopenharmony_ci	PR_EEP("Chain0 xatten2Db", modal_hdr->xatten2Db[0]);
18962306a36Sopenharmony_ci	PR_EEP("Chain1 xatten2Db", modal_hdr->xatten2Db[1]);
19062306a36Sopenharmony_ci	PR_EEP("Chain2 xatten2Db", modal_hdr->xatten2Db[2]);
19162306a36Sopenharmony_ci	PR_EEP("Chain0 xatten2Margin", modal_hdr->xatten2Margin[0]);
19262306a36Sopenharmony_ci	PR_EEP("Chain1 xatten2Margin", modal_hdr->xatten2Margin[1]);
19362306a36Sopenharmony_ci	PR_EEP("Chain2 xatten2Margin", modal_hdr->xatten2Margin[2]);
19462306a36Sopenharmony_ci	PR_EEP("Chain1 OutputBias", modal_hdr->ob_ch1);
19562306a36Sopenharmony_ci	PR_EEP("Chain1 DriverBias", modal_hdr->db_ch1);
19662306a36Sopenharmony_ci	PR_EEP("LNA Control", modal_hdr->lna_ctl);
19762306a36Sopenharmony_ci	PR_EEP("XPA Bias Freq0", le16_to_cpu(modal_hdr->xpaBiasLvlFreq[0]));
19862306a36Sopenharmony_ci	PR_EEP("XPA Bias Freq1", le16_to_cpu(modal_hdr->xpaBiasLvlFreq[1]));
19962306a36Sopenharmony_ci	PR_EEP("XPA Bias Freq2", le16_to_cpu(modal_hdr->xpaBiasLvlFreq[2]));
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_ci	return len;
20262306a36Sopenharmony_ci}
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_cistatic u32 ath9k_hw_def_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
20562306a36Sopenharmony_ci				    u8 *buf, u32 len, u32 size)
20662306a36Sopenharmony_ci{
20762306a36Sopenharmony_ci	struct ar5416_eeprom_def *eep = &ah->eeprom.def;
20862306a36Sopenharmony_ci	struct base_eep_header *pBase = &eep->baseEepHeader;
20962306a36Sopenharmony_ci	u32 binBuildNumber = le32_to_cpu(pBase->binBuildNumber);
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_ci	if (!dump_base_hdr) {
21262306a36Sopenharmony_ci		len += scnprintf(buf + len, size - len,
21362306a36Sopenharmony_ci				 "%20s :\n", "2GHz modal Header");
21462306a36Sopenharmony_ci		len = ath9k_def_dump_modal_eeprom(buf, len, size,
21562306a36Sopenharmony_ci						   &eep->modalHeader[0]);
21662306a36Sopenharmony_ci		len += scnprintf(buf + len, size - len,
21762306a36Sopenharmony_ci				 "%20s :\n", "5GHz modal Header");
21862306a36Sopenharmony_ci		len = ath9k_def_dump_modal_eeprom(buf, len, size,
21962306a36Sopenharmony_ci						   &eep->modalHeader[1]);
22062306a36Sopenharmony_ci		goto out;
22162306a36Sopenharmony_ci	}
22262306a36Sopenharmony_ci
22362306a36Sopenharmony_ci	PR_EEP("Major Version", ath9k_hw_def_get_eeprom_ver(ah));
22462306a36Sopenharmony_ci	PR_EEP("Minor Version", ath9k_hw_def_get_eeprom_rev(ah));
22562306a36Sopenharmony_ci	PR_EEP("Checksum", le16_to_cpu(pBase->checksum));
22662306a36Sopenharmony_ci	PR_EEP("Length", le16_to_cpu(pBase->length));
22762306a36Sopenharmony_ci	PR_EEP("RegDomain1", le16_to_cpu(pBase->regDmn[0]));
22862306a36Sopenharmony_ci	PR_EEP("RegDomain2", le16_to_cpu(pBase->regDmn[1]));
22962306a36Sopenharmony_ci	PR_EEP("TX Mask", pBase->txMask);
23062306a36Sopenharmony_ci	PR_EEP("RX Mask", pBase->rxMask);
23162306a36Sopenharmony_ci	PR_EEP("Allow 5GHz", !!(pBase->opCapFlags & AR5416_OPFLAGS_11A));
23262306a36Sopenharmony_ci	PR_EEP("Allow 2GHz", !!(pBase->opCapFlags & AR5416_OPFLAGS_11G));
23362306a36Sopenharmony_ci	PR_EEP("Disable 2GHz HT20", !!(pBase->opCapFlags &
23462306a36Sopenharmony_ci					AR5416_OPFLAGS_N_2G_HT20));
23562306a36Sopenharmony_ci	PR_EEP("Disable 2GHz HT40", !!(pBase->opCapFlags &
23662306a36Sopenharmony_ci					AR5416_OPFLAGS_N_2G_HT40));
23762306a36Sopenharmony_ci	PR_EEP("Disable 5Ghz HT20", !!(pBase->opCapFlags &
23862306a36Sopenharmony_ci					AR5416_OPFLAGS_N_5G_HT20));
23962306a36Sopenharmony_ci	PR_EEP("Disable 5Ghz HT40", !!(pBase->opCapFlags &
24062306a36Sopenharmony_ci					AR5416_OPFLAGS_N_5G_HT40));
24162306a36Sopenharmony_ci	PR_EEP("Big Endian", !!(pBase->eepMisc & AR5416_EEPMISC_BIG_ENDIAN));
24262306a36Sopenharmony_ci	PR_EEP("Cal Bin Major Ver", (binBuildNumber >> 24) & 0xFF);
24362306a36Sopenharmony_ci	PR_EEP("Cal Bin Minor Ver", (binBuildNumber >> 16) & 0xFF);
24462306a36Sopenharmony_ci	PR_EEP("Cal Bin Build", (binBuildNumber >> 8) & 0xFF);
24562306a36Sopenharmony_ci	PR_EEP("OpenLoop Power Ctrl", pBase->openLoopPwrCntl);
24662306a36Sopenharmony_ci
24762306a36Sopenharmony_ci	len += scnprintf(buf + len, size - len, "%20s : %pM\n", "MacAddress",
24862306a36Sopenharmony_ci			 pBase->macAddr);
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_ciout:
25162306a36Sopenharmony_ci	if (len > size)
25262306a36Sopenharmony_ci		len = size;
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_ci	return len;
25562306a36Sopenharmony_ci}
25662306a36Sopenharmony_ci#else
25762306a36Sopenharmony_cistatic u32 ath9k_hw_def_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
25862306a36Sopenharmony_ci				    u8 *buf, u32 len, u32 size)
25962306a36Sopenharmony_ci{
26062306a36Sopenharmony_ci	return 0;
26162306a36Sopenharmony_ci}
26262306a36Sopenharmony_ci#endif
26362306a36Sopenharmony_ci
26462306a36Sopenharmony_cistatic int ath9k_hw_def_check_eeprom(struct ath_hw *ah)
26562306a36Sopenharmony_ci{
26662306a36Sopenharmony_ci	struct ar5416_eeprom_def *eep = &ah->eeprom.def;
26762306a36Sopenharmony_ci	struct ath_common *common = ath9k_hw_common(ah);
26862306a36Sopenharmony_ci	u32 el;
26962306a36Sopenharmony_ci	bool need_swap;
27062306a36Sopenharmony_ci	int i, err;
27162306a36Sopenharmony_ci
27262306a36Sopenharmony_ci	err = ath9k_hw_nvram_swap_data(ah, &need_swap, SIZE_EEPROM_DEF);
27362306a36Sopenharmony_ci	if (err)
27462306a36Sopenharmony_ci		return err;
27562306a36Sopenharmony_ci
27662306a36Sopenharmony_ci	if (need_swap)
27762306a36Sopenharmony_ci		el = swab16((__force u16)eep->baseEepHeader.length);
27862306a36Sopenharmony_ci	else
27962306a36Sopenharmony_ci		el = le16_to_cpu(eep->baseEepHeader.length);
28062306a36Sopenharmony_ci
28162306a36Sopenharmony_ci	el = min(el / sizeof(u16), SIZE_EEPROM_DEF);
28262306a36Sopenharmony_ci	if (!ath9k_hw_nvram_validate_checksum(ah, el))
28362306a36Sopenharmony_ci		return -EINVAL;
28462306a36Sopenharmony_ci
28562306a36Sopenharmony_ci	if (need_swap) {
28662306a36Sopenharmony_ci		u32 j;
28762306a36Sopenharmony_ci
28862306a36Sopenharmony_ci		EEPROM_FIELD_SWAB16(eep->baseEepHeader.length);
28962306a36Sopenharmony_ci		EEPROM_FIELD_SWAB16(eep->baseEepHeader.checksum);
29062306a36Sopenharmony_ci		EEPROM_FIELD_SWAB16(eep->baseEepHeader.version);
29162306a36Sopenharmony_ci		EEPROM_FIELD_SWAB16(eep->baseEepHeader.regDmn[0]);
29262306a36Sopenharmony_ci		EEPROM_FIELD_SWAB16(eep->baseEepHeader.regDmn[1]);
29362306a36Sopenharmony_ci		EEPROM_FIELD_SWAB16(eep->baseEepHeader.rfSilent);
29462306a36Sopenharmony_ci		EEPROM_FIELD_SWAB16(eep->baseEepHeader.blueToothOptions);
29562306a36Sopenharmony_ci		EEPROM_FIELD_SWAB16(eep->baseEepHeader.deviceCap);
29662306a36Sopenharmony_ci
29762306a36Sopenharmony_ci		for (j = 0; j < ARRAY_SIZE(eep->modalHeader); j++) {
29862306a36Sopenharmony_ci			struct modal_eep_header *pModal =
29962306a36Sopenharmony_ci				&eep->modalHeader[j];
30062306a36Sopenharmony_ci			EEPROM_FIELD_SWAB32(pModal->antCtrlCommon);
30162306a36Sopenharmony_ci
30262306a36Sopenharmony_ci			for (i = 0; i < AR5416_MAX_CHAINS; i++)
30362306a36Sopenharmony_ci				EEPROM_FIELD_SWAB32(pModal->antCtrlChain[i]);
30462306a36Sopenharmony_ci
30562306a36Sopenharmony_ci			for (i = 0; i < 3; i++)
30662306a36Sopenharmony_ci				EEPROM_FIELD_SWAB16(pModal->xpaBiasLvlFreq[i]);
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_ci			for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++)
30962306a36Sopenharmony_ci				EEPROM_FIELD_SWAB16(
31062306a36Sopenharmony_ci					pModal->spurChans[i].spurChan);
31162306a36Sopenharmony_ci		}
31262306a36Sopenharmony_ci	}
31362306a36Sopenharmony_ci
31462306a36Sopenharmony_ci	if (!ath9k_hw_nvram_check_version(ah, AR5416_EEP_VER,
31562306a36Sopenharmony_ci	    AR5416_EEP_NO_BACK_VER))
31662306a36Sopenharmony_ci		return -EINVAL;
31762306a36Sopenharmony_ci
31862306a36Sopenharmony_ci	/* Enable fixup for AR_AN_TOP2 if necessary */
31962306a36Sopenharmony_ci	if ((ah->hw_version.devid == AR9280_DEVID_PCI) &&
32062306a36Sopenharmony_ci	    ((le16_to_cpu(eep->baseEepHeader.version) & 0xff) > 0x0a) &&
32162306a36Sopenharmony_ci	    (eep->baseEepHeader.pwdclkind == 0))
32262306a36Sopenharmony_ci		ah->need_an_top2_fixup = true;
32362306a36Sopenharmony_ci
32462306a36Sopenharmony_ci	if ((common->bus_ops->ath_bus_type == ATH_USB) &&
32562306a36Sopenharmony_ci	    (AR_SREV_9280(ah)))
32662306a36Sopenharmony_ci		eep->modalHeader[0].xpaBiasLvl = 0;
32762306a36Sopenharmony_ci
32862306a36Sopenharmony_ci	return 0;
32962306a36Sopenharmony_ci}
33062306a36Sopenharmony_ci
33162306a36Sopenharmony_ci#undef SIZE_EEPROM_DEF
33262306a36Sopenharmony_ci
33362306a36Sopenharmony_cistatic u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah,
33462306a36Sopenharmony_ci				   enum eeprom_param param)
33562306a36Sopenharmony_ci{
33662306a36Sopenharmony_ci	struct ar5416_eeprom_def *eep = &ah->eeprom.def;
33762306a36Sopenharmony_ci	struct modal_eep_header *pModal = eep->modalHeader;
33862306a36Sopenharmony_ci	struct base_eep_header *pBase = &eep->baseEepHeader;
33962306a36Sopenharmony_ci	int band = 0;
34062306a36Sopenharmony_ci
34162306a36Sopenharmony_ci	switch (param) {
34262306a36Sopenharmony_ci	case EEP_NFTHRESH_5:
34362306a36Sopenharmony_ci		return pModal[0].noiseFloorThreshCh[0];
34462306a36Sopenharmony_ci	case EEP_NFTHRESH_2:
34562306a36Sopenharmony_ci		return pModal[1].noiseFloorThreshCh[0];
34662306a36Sopenharmony_ci	case EEP_MAC_LSW:
34762306a36Sopenharmony_ci		return get_unaligned_be16(pBase->macAddr);
34862306a36Sopenharmony_ci	case EEP_MAC_MID:
34962306a36Sopenharmony_ci		return get_unaligned_be16(pBase->macAddr + 2);
35062306a36Sopenharmony_ci	case EEP_MAC_MSW:
35162306a36Sopenharmony_ci		return get_unaligned_be16(pBase->macAddr + 4);
35262306a36Sopenharmony_ci	case EEP_REG_0:
35362306a36Sopenharmony_ci		return le16_to_cpu(pBase->regDmn[0]);
35462306a36Sopenharmony_ci	case EEP_OP_CAP:
35562306a36Sopenharmony_ci		return le16_to_cpu(pBase->deviceCap);
35662306a36Sopenharmony_ci	case EEP_OP_MODE:
35762306a36Sopenharmony_ci		return pBase->opCapFlags;
35862306a36Sopenharmony_ci	case EEP_RF_SILENT:
35962306a36Sopenharmony_ci		return le16_to_cpu(pBase->rfSilent);
36062306a36Sopenharmony_ci	case EEP_OB_5:
36162306a36Sopenharmony_ci		return pModal[0].ob;
36262306a36Sopenharmony_ci	case EEP_DB_5:
36362306a36Sopenharmony_ci		return pModal[0].db;
36462306a36Sopenharmony_ci	case EEP_OB_2:
36562306a36Sopenharmony_ci		return pModal[1].ob;
36662306a36Sopenharmony_ci	case EEP_DB_2:
36762306a36Sopenharmony_ci		return pModal[1].db;
36862306a36Sopenharmony_ci	case EEP_TX_MASK:
36962306a36Sopenharmony_ci		return pBase->txMask;
37062306a36Sopenharmony_ci	case EEP_RX_MASK:
37162306a36Sopenharmony_ci		return pBase->rxMask;
37262306a36Sopenharmony_ci	case EEP_FSTCLK_5G:
37362306a36Sopenharmony_ci		return pBase->fastClk5g;
37462306a36Sopenharmony_ci	case EEP_RXGAIN_TYPE:
37562306a36Sopenharmony_ci		return pBase->rxGainType;
37662306a36Sopenharmony_ci	case EEP_TXGAIN_TYPE:
37762306a36Sopenharmony_ci		return pBase->txGainType;
37862306a36Sopenharmony_ci	case EEP_OL_PWRCTRL:
37962306a36Sopenharmony_ci		if (ath9k_hw_def_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_19)
38062306a36Sopenharmony_ci			return pBase->openLoopPwrCntl ? true : false;
38162306a36Sopenharmony_ci		else
38262306a36Sopenharmony_ci			return false;
38362306a36Sopenharmony_ci	case EEP_RC_CHAIN_MASK:
38462306a36Sopenharmony_ci		if (ath9k_hw_def_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_19)
38562306a36Sopenharmony_ci			return pBase->rcChainMask;
38662306a36Sopenharmony_ci		else
38762306a36Sopenharmony_ci			return 0;
38862306a36Sopenharmony_ci	case EEP_DAC_HPWR_5G:
38962306a36Sopenharmony_ci		if (ath9k_hw_def_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_20)
39062306a36Sopenharmony_ci			return pBase->dacHiPwrMode_5G;
39162306a36Sopenharmony_ci		else
39262306a36Sopenharmony_ci			return 0;
39362306a36Sopenharmony_ci	case EEP_FRAC_N_5G:
39462306a36Sopenharmony_ci		if (ath9k_hw_def_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_22)
39562306a36Sopenharmony_ci			return pBase->frac_n_5g;
39662306a36Sopenharmony_ci		else
39762306a36Sopenharmony_ci			return 0;
39862306a36Sopenharmony_ci	case EEP_PWR_TABLE_OFFSET:
39962306a36Sopenharmony_ci		if (ath9k_hw_def_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_21)
40062306a36Sopenharmony_ci			return pBase->pwr_table_offset;
40162306a36Sopenharmony_ci		else
40262306a36Sopenharmony_ci			return AR5416_PWR_TABLE_OFFSET_DB;
40362306a36Sopenharmony_ci	case EEP_ANTENNA_GAIN_2G:
40462306a36Sopenharmony_ci		band = 1;
40562306a36Sopenharmony_ci		fallthrough;
40662306a36Sopenharmony_ci	case EEP_ANTENNA_GAIN_5G:
40762306a36Sopenharmony_ci		return max_t(u8, max_t(u8,
40862306a36Sopenharmony_ci			pModal[band].antennaGainCh[0],
40962306a36Sopenharmony_ci			pModal[band].antennaGainCh[1]),
41062306a36Sopenharmony_ci			pModal[band].antennaGainCh[2]);
41162306a36Sopenharmony_ci	default:
41262306a36Sopenharmony_ci		return 0;
41362306a36Sopenharmony_ci	}
41462306a36Sopenharmony_ci}
41562306a36Sopenharmony_ci
41662306a36Sopenharmony_cistatic void ath9k_hw_def_set_gain(struct ath_hw *ah,
41762306a36Sopenharmony_ci				  struct modal_eep_header *pModal,
41862306a36Sopenharmony_ci				  struct ar5416_eeprom_def *eep,
41962306a36Sopenharmony_ci				  u8 txRxAttenLocal, int regChainOffset, int i)
42062306a36Sopenharmony_ci{
42162306a36Sopenharmony_ci	ENABLE_REG_RMW_BUFFER(ah);
42262306a36Sopenharmony_ci	if (ath9k_hw_def_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_3) {
42362306a36Sopenharmony_ci		txRxAttenLocal = pModal->txRxAttenCh[i];
42462306a36Sopenharmony_ci
42562306a36Sopenharmony_ci		if (AR_SREV_9280_20_OR_LATER(ah)) {
42662306a36Sopenharmony_ci			REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
42762306a36Sopenharmony_ci			      AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN,
42862306a36Sopenharmony_ci			      pModal->bswMargin[i]);
42962306a36Sopenharmony_ci			REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
43062306a36Sopenharmony_ci			      AR_PHY_GAIN_2GHZ_XATTEN1_DB,
43162306a36Sopenharmony_ci			      pModal->bswAtten[i]);
43262306a36Sopenharmony_ci			REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
43362306a36Sopenharmony_ci			      AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,
43462306a36Sopenharmony_ci			      pModal->xatten2Margin[i]);
43562306a36Sopenharmony_ci			REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
43662306a36Sopenharmony_ci			      AR_PHY_GAIN_2GHZ_XATTEN2_DB,
43762306a36Sopenharmony_ci			      pModal->xatten2Db[i]);
43862306a36Sopenharmony_ci		} else {
43962306a36Sopenharmony_ci			REG_RMW(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
44062306a36Sopenharmony_ci				SM(pModal-> bswMargin[i], AR_PHY_GAIN_2GHZ_BSW_MARGIN),
44162306a36Sopenharmony_ci				AR_PHY_GAIN_2GHZ_BSW_MARGIN);
44262306a36Sopenharmony_ci			REG_RMW(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
44362306a36Sopenharmony_ci				SM(pModal->bswAtten[i], AR_PHY_GAIN_2GHZ_BSW_ATTEN),
44462306a36Sopenharmony_ci				AR_PHY_GAIN_2GHZ_BSW_ATTEN);
44562306a36Sopenharmony_ci		}
44662306a36Sopenharmony_ci	}
44762306a36Sopenharmony_ci
44862306a36Sopenharmony_ci	if (AR_SREV_9280_20_OR_LATER(ah)) {
44962306a36Sopenharmony_ci		REG_RMW_FIELD(ah,
45062306a36Sopenharmony_ci		      AR_PHY_RXGAIN + regChainOffset,
45162306a36Sopenharmony_ci		      AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal);
45262306a36Sopenharmony_ci		REG_RMW_FIELD(ah,
45362306a36Sopenharmony_ci		      AR_PHY_RXGAIN + regChainOffset,
45462306a36Sopenharmony_ci		      AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[i]);
45562306a36Sopenharmony_ci	} else {
45662306a36Sopenharmony_ci		REG_RMW(ah, AR_PHY_RXGAIN + regChainOffset,
45762306a36Sopenharmony_ci			SM(txRxAttenLocal, AR_PHY_RXGAIN_TXRX_ATTEN),
45862306a36Sopenharmony_ci			AR_PHY_RXGAIN_TXRX_ATTEN);
45962306a36Sopenharmony_ci		REG_RMW(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
46062306a36Sopenharmony_ci			SM(pModal->rxTxMarginCh[i], AR_PHY_GAIN_2GHZ_RXTX_MARGIN),
46162306a36Sopenharmony_ci			AR_PHY_GAIN_2GHZ_RXTX_MARGIN);
46262306a36Sopenharmony_ci	}
46362306a36Sopenharmony_ci	REG_RMW_BUFFER_FLUSH(ah);
46462306a36Sopenharmony_ci}
46562306a36Sopenharmony_ci
46662306a36Sopenharmony_cistatic void ath9k_hw_def_set_board_values(struct ath_hw *ah,
46762306a36Sopenharmony_ci					  struct ath9k_channel *chan)
46862306a36Sopenharmony_ci{
46962306a36Sopenharmony_ci	struct modal_eep_header *pModal;
47062306a36Sopenharmony_ci	struct ar5416_eeprom_def *eep = &ah->eeprom.def;
47162306a36Sopenharmony_ci	int i, regChainOffset;
47262306a36Sopenharmony_ci	u8 txRxAttenLocal;
47362306a36Sopenharmony_ci	u32 antCtrlCommon;
47462306a36Sopenharmony_ci
47562306a36Sopenharmony_ci	pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
47662306a36Sopenharmony_ci	txRxAttenLocal = IS_CHAN_2GHZ(chan) ? 23 : 44;
47762306a36Sopenharmony_ci	antCtrlCommon = le32_to_cpu(pModal->antCtrlCommon);
47862306a36Sopenharmony_ci
47962306a36Sopenharmony_ci	REG_WRITE(ah, AR_PHY_SWITCH_COM, antCtrlCommon & 0xffff);
48062306a36Sopenharmony_ci
48162306a36Sopenharmony_ci	for (i = 0; i < AR5416_MAX_CHAINS; i++) {
48262306a36Sopenharmony_ci		if (AR_SREV_9280(ah)) {
48362306a36Sopenharmony_ci			if (i >= 2)
48462306a36Sopenharmony_ci				break;
48562306a36Sopenharmony_ci		}
48662306a36Sopenharmony_ci
48762306a36Sopenharmony_ci		if ((ah->rxchainmask == 5 || ah->txchainmask == 5) && (i != 0))
48862306a36Sopenharmony_ci			regChainOffset = (i == 1) ? 0x2000 : 0x1000;
48962306a36Sopenharmony_ci		else
49062306a36Sopenharmony_ci			regChainOffset = i * 0x1000;
49162306a36Sopenharmony_ci
49262306a36Sopenharmony_ci		REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset,
49362306a36Sopenharmony_ci			  le32_to_cpu(pModal->antCtrlChain[i]));
49462306a36Sopenharmony_ci
49562306a36Sopenharmony_ci		REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset,
49662306a36Sopenharmony_ci			  (REG_READ(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset) &
49762306a36Sopenharmony_ci			   ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF |
49862306a36Sopenharmony_ci			     AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) |
49962306a36Sopenharmony_ci			  SM(pModal->iqCalICh[i],
50062306a36Sopenharmony_ci			     AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) |
50162306a36Sopenharmony_ci			  SM(pModal->iqCalQCh[i],
50262306a36Sopenharmony_ci			     AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF));
50362306a36Sopenharmony_ci
50462306a36Sopenharmony_ci		ath9k_hw_def_set_gain(ah, pModal, eep, txRxAttenLocal,
50562306a36Sopenharmony_ci				      regChainOffset, i);
50662306a36Sopenharmony_ci	}
50762306a36Sopenharmony_ci
50862306a36Sopenharmony_ci	if (AR_SREV_9280_20_OR_LATER(ah)) {
50962306a36Sopenharmony_ci		if (IS_CHAN_2GHZ(chan)) {
51062306a36Sopenharmony_ci			ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0,
51162306a36Sopenharmony_ci						  AR_AN_RF2G1_CH0_OB,
51262306a36Sopenharmony_ci						  AR_AN_RF2G1_CH0_OB_S,
51362306a36Sopenharmony_ci						  pModal->ob);
51462306a36Sopenharmony_ci			ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0,
51562306a36Sopenharmony_ci						  AR_AN_RF2G1_CH0_DB,
51662306a36Sopenharmony_ci						  AR_AN_RF2G1_CH0_DB_S,
51762306a36Sopenharmony_ci						  pModal->db);
51862306a36Sopenharmony_ci			ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH1,
51962306a36Sopenharmony_ci						  AR_AN_RF2G1_CH1_OB,
52062306a36Sopenharmony_ci						  AR_AN_RF2G1_CH1_OB_S,
52162306a36Sopenharmony_ci						  pModal->ob_ch1);
52262306a36Sopenharmony_ci			ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH1,
52362306a36Sopenharmony_ci						  AR_AN_RF2G1_CH1_DB,
52462306a36Sopenharmony_ci						  AR_AN_RF2G1_CH1_DB_S,
52562306a36Sopenharmony_ci						  pModal->db_ch1);
52662306a36Sopenharmony_ci		} else {
52762306a36Sopenharmony_ci			ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH0,
52862306a36Sopenharmony_ci						  AR_AN_RF5G1_CH0_OB5,
52962306a36Sopenharmony_ci						  AR_AN_RF5G1_CH0_OB5_S,
53062306a36Sopenharmony_ci						  pModal->ob);
53162306a36Sopenharmony_ci			ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH0,
53262306a36Sopenharmony_ci						  AR_AN_RF5G1_CH0_DB5,
53362306a36Sopenharmony_ci						  AR_AN_RF5G1_CH0_DB5_S,
53462306a36Sopenharmony_ci						  pModal->db);
53562306a36Sopenharmony_ci			ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH1,
53662306a36Sopenharmony_ci						  AR_AN_RF5G1_CH1_OB5,
53762306a36Sopenharmony_ci						  AR_AN_RF5G1_CH1_OB5_S,
53862306a36Sopenharmony_ci						  pModal->ob_ch1);
53962306a36Sopenharmony_ci			ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH1,
54062306a36Sopenharmony_ci						  AR_AN_RF5G1_CH1_DB5,
54162306a36Sopenharmony_ci						  AR_AN_RF5G1_CH1_DB5_S,
54262306a36Sopenharmony_ci						  pModal->db_ch1);
54362306a36Sopenharmony_ci		}
54462306a36Sopenharmony_ci		ath9k_hw_analog_shift_rmw(ah, AR_AN_TOP2,
54562306a36Sopenharmony_ci					  AR_AN_TOP2_XPABIAS_LVL,
54662306a36Sopenharmony_ci					  AR_AN_TOP2_XPABIAS_LVL_S,
54762306a36Sopenharmony_ci					  pModal->xpaBiasLvl);
54862306a36Sopenharmony_ci		ath9k_hw_analog_shift_rmw(ah, AR_AN_TOP2,
54962306a36Sopenharmony_ci					  AR_AN_TOP2_LOCALBIAS,
55062306a36Sopenharmony_ci					  AR_AN_TOP2_LOCALBIAS_S,
55162306a36Sopenharmony_ci					  !!(pModal->lna_ctl &
55262306a36Sopenharmony_ci					     LNA_CTL_LOCAL_BIAS));
55362306a36Sopenharmony_ci		REG_RMW_FIELD(ah, AR_PHY_XPA_CFG, AR_PHY_FORCE_XPA_CFG,
55462306a36Sopenharmony_ci			      !!(pModal->lna_ctl & LNA_CTL_FORCE_XPA));
55562306a36Sopenharmony_ci	}
55662306a36Sopenharmony_ci
55762306a36Sopenharmony_ci	REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH,
55862306a36Sopenharmony_ci		      pModal->switchSettling);
55962306a36Sopenharmony_ci	REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC,
56062306a36Sopenharmony_ci		      pModal->adcDesiredSize);
56162306a36Sopenharmony_ci
56262306a36Sopenharmony_ci	if (!AR_SREV_9280_20_OR_LATER(ah))
56362306a36Sopenharmony_ci		REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
56462306a36Sopenharmony_ci			      AR_PHY_DESIRED_SZ_PGA,
56562306a36Sopenharmony_ci			      pModal->pgaDesiredSize);
56662306a36Sopenharmony_ci
56762306a36Sopenharmony_ci	REG_WRITE(ah, AR_PHY_RF_CTL4,
56862306a36Sopenharmony_ci		  SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF)
56962306a36Sopenharmony_ci		  | SM(pModal->txEndToXpaOff,
57062306a36Sopenharmony_ci		       AR_PHY_RF_CTL4_TX_END_XPAB_OFF)
57162306a36Sopenharmony_ci		  | SM(pModal->txFrameToXpaOn,
57262306a36Sopenharmony_ci		       AR_PHY_RF_CTL4_FRAME_XPAA_ON)
57362306a36Sopenharmony_ci		  | SM(pModal->txFrameToXpaOn,
57462306a36Sopenharmony_ci		       AR_PHY_RF_CTL4_FRAME_XPAB_ON));
57562306a36Sopenharmony_ci
57662306a36Sopenharmony_ci	REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON,
57762306a36Sopenharmony_ci		      pModal->txEndToRxOn);
57862306a36Sopenharmony_ci
57962306a36Sopenharmony_ci	if (AR_SREV_9280_20_OR_LATER(ah)) {
58062306a36Sopenharmony_ci		REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62,
58162306a36Sopenharmony_ci			      pModal->thresh62);
58262306a36Sopenharmony_ci		REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0,
58362306a36Sopenharmony_ci			      AR_PHY_EXT_CCA0_THRESH62,
58462306a36Sopenharmony_ci			      pModal->thresh62);
58562306a36Sopenharmony_ci	} else {
58662306a36Sopenharmony_ci		REG_RMW_FIELD(ah, AR_PHY_CCA, AR_PHY_CCA_THRESH62,
58762306a36Sopenharmony_ci			      pModal->thresh62);
58862306a36Sopenharmony_ci		REG_RMW_FIELD(ah, AR_PHY_EXT_CCA,
58962306a36Sopenharmony_ci			      AR_PHY_EXT_CCA_THRESH62,
59062306a36Sopenharmony_ci			      pModal->thresh62);
59162306a36Sopenharmony_ci	}
59262306a36Sopenharmony_ci
59362306a36Sopenharmony_ci	if (ath9k_hw_def_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_2) {
59462306a36Sopenharmony_ci		REG_RMW_FIELD(ah, AR_PHY_RF_CTL2,
59562306a36Sopenharmony_ci			      AR_PHY_TX_END_DATA_START,
59662306a36Sopenharmony_ci			      pModal->txFrameToDataStart);
59762306a36Sopenharmony_ci		REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_PA_ON,
59862306a36Sopenharmony_ci			      pModal->txFrameToPaOn);
59962306a36Sopenharmony_ci	}
60062306a36Sopenharmony_ci
60162306a36Sopenharmony_ci	if (ath9k_hw_def_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_3) {
60262306a36Sopenharmony_ci		if (IS_CHAN_HT40(chan))
60362306a36Sopenharmony_ci			REG_RMW_FIELD(ah, AR_PHY_SETTLING,
60462306a36Sopenharmony_ci				      AR_PHY_SETTLING_SWITCH,
60562306a36Sopenharmony_ci				      pModal->swSettleHt40);
60662306a36Sopenharmony_ci	}
60762306a36Sopenharmony_ci
60862306a36Sopenharmony_ci	if (AR_SREV_9280_20_OR_LATER(ah) &&
60962306a36Sopenharmony_ci	    ath9k_hw_def_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_19)
61062306a36Sopenharmony_ci		REG_RMW_FIELD(ah, AR_PHY_CCK_TX_CTRL,
61162306a36Sopenharmony_ci			      AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK,
61262306a36Sopenharmony_ci			      pModal->miscBits);
61362306a36Sopenharmony_ci
61462306a36Sopenharmony_ci
61562306a36Sopenharmony_ci	if (AR_SREV_9280_20(ah) &&
61662306a36Sopenharmony_ci	    ath9k_hw_def_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_20) {
61762306a36Sopenharmony_ci		if (IS_CHAN_2GHZ(chan))
61862306a36Sopenharmony_ci			REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE,
61962306a36Sopenharmony_ci					eep->baseEepHeader.dacLpMode);
62062306a36Sopenharmony_ci		else if (eep->baseEepHeader.dacHiPwrMode_5G)
62162306a36Sopenharmony_ci			REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE, 0);
62262306a36Sopenharmony_ci		else
62362306a36Sopenharmony_ci			REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE,
62462306a36Sopenharmony_ci				      eep->baseEepHeader.dacLpMode);
62562306a36Sopenharmony_ci
62662306a36Sopenharmony_ci		udelay(100);
62762306a36Sopenharmony_ci
62862306a36Sopenharmony_ci		REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL, AR_PHY_FRAME_CTL_TX_CLIP,
62962306a36Sopenharmony_ci			      pModal->miscBits >> 2);
63062306a36Sopenharmony_ci
63162306a36Sopenharmony_ci		REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL9,
63262306a36Sopenharmony_ci			      AR_PHY_TX_DESIRED_SCALE_CCK,
63362306a36Sopenharmony_ci			      eep->baseEepHeader.desiredScaleCCK);
63462306a36Sopenharmony_ci	}
63562306a36Sopenharmony_ci}
63662306a36Sopenharmony_ci
63762306a36Sopenharmony_cistatic void ath9k_hw_def_set_addac(struct ath_hw *ah,
63862306a36Sopenharmony_ci				   struct ath9k_channel *chan)
63962306a36Sopenharmony_ci{
64062306a36Sopenharmony_ci#define XPA_LVL_FREQ(cnt) (le16_to_cpu(pModal->xpaBiasLvlFreq[cnt]))
64162306a36Sopenharmony_ci	struct modal_eep_header *pModal;
64262306a36Sopenharmony_ci	struct ar5416_eeprom_def *eep = &ah->eeprom.def;
64362306a36Sopenharmony_ci	u8 biaslevel;
64462306a36Sopenharmony_ci
64562306a36Sopenharmony_ci	if (ah->hw_version.macVersion != AR_SREV_VERSION_9160)
64662306a36Sopenharmony_ci		return;
64762306a36Sopenharmony_ci
64862306a36Sopenharmony_ci	if (ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_MINOR_VER_7)
64962306a36Sopenharmony_ci		return;
65062306a36Sopenharmony_ci
65162306a36Sopenharmony_ci	pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
65262306a36Sopenharmony_ci
65362306a36Sopenharmony_ci	if (pModal->xpaBiasLvl != 0xff) {
65462306a36Sopenharmony_ci		biaslevel = pModal->xpaBiasLvl;
65562306a36Sopenharmony_ci	} else {
65662306a36Sopenharmony_ci		u16 resetFreqBin, freqBin, freqCount = 0;
65762306a36Sopenharmony_ci		struct chan_centers centers;
65862306a36Sopenharmony_ci
65962306a36Sopenharmony_ci		ath9k_hw_get_channel_centers(ah, chan, &centers);
66062306a36Sopenharmony_ci
66162306a36Sopenharmony_ci		resetFreqBin = FREQ2FBIN(centers.synth_center,
66262306a36Sopenharmony_ci					 IS_CHAN_2GHZ(chan));
66362306a36Sopenharmony_ci		freqBin = XPA_LVL_FREQ(0) & 0xff;
66462306a36Sopenharmony_ci		biaslevel = (u8) (XPA_LVL_FREQ(0) >> 14);
66562306a36Sopenharmony_ci
66662306a36Sopenharmony_ci		freqCount++;
66762306a36Sopenharmony_ci
66862306a36Sopenharmony_ci		while (freqCount < 3) {
66962306a36Sopenharmony_ci			if (XPA_LVL_FREQ(freqCount) == 0x0)
67062306a36Sopenharmony_ci				break;
67162306a36Sopenharmony_ci
67262306a36Sopenharmony_ci			freqBin = XPA_LVL_FREQ(freqCount) & 0xff;
67362306a36Sopenharmony_ci			if (resetFreqBin >= freqBin)
67462306a36Sopenharmony_ci				biaslevel = (u8)(XPA_LVL_FREQ(freqCount) >> 14);
67562306a36Sopenharmony_ci			else
67662306a36Sopenharmony_ci				break;
67762306a36Sopenharmony_ci			freqCount++;
67862306a36Sopenharmony_ci		}
67962306a36Sopenharmony_ci	}
68062306a36Sopenharmony_ci
68162306a36Sopenharmony_ci	if (IS_CHAN_2GHZ(chan)) {
68262306a36Sopenharmony_ci		INI_RA(&ah->iniAddac, 7, 1) = (INI_RA(&ah->iniAddac,
68362306a36Sopenharmony_ci					7, 1) & (~0x18)) | biaslevel << 3;
68462306a36Sopenharmony_ci	} else {
68562306a36Sopenharmony_ci		INI_RA(&ah->iniAddac, 6, 1) = (INI_RA(&ah->iniAddac,
68662306a36Sopenharmony_ci					6, 1) & (~0xc0)) | biaslevel << 6;
68762306a36Sopenharmony_ci	}
68862306a36Sopenharmony_ci#undef XPA_LVL_FREQ
68962306a36Sopenharmony_ci}
69062306a36Sopenharmony_ci
69162306a36Sopenharmony_cistatic int16_t ath9k_change_gain_boundary_setting(struct ath_hw *ah,
69262306a36Sopenharmony_ci				u16 *gb,
69362306a36Sopenharmony_ci				u16 numXpdGain,
69462306a36Sopenharmony_ci				u16 pdGainOverlap_t2,
69562306a36Sopenharmony_ci				int8_t pwr_table_offset,
69662306a36Sopenharmony_ci				int16_t *diff)
69762306a36Sopenharmony_ci
69862306a36Sopenharmony_ci{
69962306a36Sopenharmony_ci	u16 k;
70062306a36Sopenharmony_ci
70162306a36Sopenharmony_ci	/* Prior to writing the boundaries or the pdadc vs. power table
70262306a36Sopenharmony_ci	 * into the chip registers the default starting point on the pdadc
70362306a36Sopenharmony_ci	 * vs. power table needs to be checked and the curve boundaries
70462306a36Sopenharmony_ci	 * adjusted accordingly
70562306a36Sopenharmony_ci	 */
70662306a36Sopenharmony_ci	if (AR_SREV_9280_20_OR_LATER(ah)) {
70762306a36Sopenharmony_ci		u16 gb_limit;
70862306a36Sopenharmony_ci
70962306a36Sopenharmony_ci		if (AR5416_PWR_TABLE_OFFSET_DB != pwr_table_offset) {
71062306a36Sopenharmony_ci			/* get the difference in dB */
71162306a36Sopenharmony_ci			*diff = (u16)(pwr_table_offset - AR5416_PWR_TABLE_OFFSET_DB);
71262306a36Sopenharmony_ci			/* get the number of half dB steps */
71362306a36Sopenharmony_ci			*diff *= 2;
71462306a36Sopenharmony_ci			/* change the original gain boundary settings
71562306a36Sopenharmony_ci			 * by the number of half dB steps
71662306a36Sopenharmony_ci			 */
71762306a36Sopenharmony_ci			for (k = 0; k < numXpdGain; k++)
71862306a36Sopenharmony_ci				gb[k] = (u16)(gb[k] - *diff);
71962306a36Sopenharmony_ci		}
72062306a36Sopenharmony_ci		/* Because of a hardware limitation, ensure the gain boundary
72162306a36Sopenharmony_ci		 * is not larger than (63 - overlap)
72262306a36Sopenharmony_ci		 */
72362306a36Sopenharmony_ci		gb_limit = (u16)(MAX_RATE_POWER - pdGainOverlap_t2);
72462306a36Sopenharmony_ci
72562306a36Sopenharmony_ci		for (k = 0; k < numXpdGain; k++)
72662306a36Sopenharmony_ci			gb[k] = (u16)min(gb_limit, gb[k]);
72762306a36Sopenharmony_ci	}
72862306a36Sopenharmony_ci
72962306a36Sopenharmony_ci	return *diff;
73062306a36Sopenharmony_ci}
73162306a36Sopenharmony_ci
73262306a36Sopenharmony_cistatic void ath9k_adjust_pdadc_values(struct ath_hw *ah,
73362306a36Sopenharmony_ci				      int8_t pwr_table_offset,
73462306a36Sopenharmony_ci				      int16_t diff,
73562306a36Sopenharmony_ci				      u8 *pdadcValues)
73662306a36Sopenharmony_ci{
73762306a36Sopenharmony_ci#define NUM_PDADC(diff) (AR5416_NUM_PDADC_VALUES - diff)
73862306a36Sopenharmony_ci	u16 k;
73962306a36Sopenharmony_ci
74062306a36Sopenharmony_ci	/* If this is a board that has a pwrTableOffset that differs from
74162306a36Sopenharmony_ci	 * the default AR5416_PWR_TABLE_OFFSET_DB then the start of the
74262306a36Sopenharmony_ci	 * pdadc vs pwr table needs to be adjusted prior to writing to the
74362306a36Sopenharmony_ci	 * chip.
74462306a36Sopenharmony_ci	 */
74562306a36Sopenharmony_ci	if (AR_SREV_9280_20_OR_LATER(ah)) {
74662306a36Sopenharmony_ci		if (AR5416_PWR_TABLE_OFFSET_DB != pwr_table_offset) {
74762306a36Sopenharmony_ci			/* shift the table to start at the new offset */
74862306a36Sopenharmony_ci			for (k = 0; k < (u16)NUM_PDADC(diff); k++ ) {
74962306a36Sopenharmony_ci				pdadcValues[k] = pdadcValues[k + diff];
75062306a36Sopenharmony_ci			}
75162306a36Sopenharmony_ci
75262306a36Sopenharmony_ci			/* fill the back of the table */
75362306a36Sopenharmony_ci			for (k = (u16)NUM_PDADC(diff); k < NUM_PDADC(0); k++) {
75462306a36Sopenharmony_ci				pdadcValues[k] = pdadcValues[NUM_PDADC(diff)];
75562306a36Sopenharmony_ci			}
75662306a36Sopenharmony_ci		}
75762306a36Sopenharmony_ci	}
75862306a36Sopenharmony_ci#undef NUM_PDADC
75962306a36Sopenharmony_ci}
76062306a36Sopenharmony_ci
76162306a36Sopenharmony_cistatic void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah,
76262306a36Sopenharmony_ci				  struct ath9k_channel *chan)
76362306a36Sopenharmony_ci{
76462306a36Sopenharmony_ci#define SM_PD_GAIN(x) SM(0x38, AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_##x)
76562306a36Sopenharmony_ci#define SM_PDGAIN_B(x, y) \
76662306a36Sopenharmony_ci		SM((gainBoundaries[x]), AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_##y)
76762306a36Sopenharmony_ci	struct ath_common *common = ath9k_hw_common(ah);
76862306a36Sopenharmony_ci	struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;
76962306a36Sopenharmony_ci	struct cal_data_per_freq *pRawDataset;
77062306a36Sopenharmony_ci	u8 *pCalBChans = NULL;
77162306a36Sopenharmony_ci	u16 pdGainOverlap_t2;
77262306a36Sopenharmony_ci	static u8 pdadcValues[AR5416_NUM_PDADC_VALUES];
77362306a36Sopenharmony_ci	u16 gainBoundaries[AR5416_PD_GAINS_IN_MASK];
77462306a36Sopenharmony_ci	u16 numPiers, i, j;
77562306a36Sopenharmony_ci	int16_t diff = 0;
77662306a36Sopenharmony_ci	u16 numXpdGain, xpdMask;
77762306a36Sopenharmony_ci	u16 xpdGainValues[AR5416_NUM_PD_GAINS] = { 0, 0, 0, 0 };
77862306a36Sopenharmony_ci	u32 reg32, regOffset, regChainOffset;
77962306a36Sopenharmony_ci	int16_t modalIdx;
78062306a36Sopenharmony_ci	int8_t pwr_table_offset;
78162306a36Sopenharmony_ci
78262306a36Sopenharmony_ci	modalIdx = IS_CHAN_2GHZ(chan) ? 1 : 0;
78362306a36Sopenharmony_ci	xpdMask = pEepData->modalHeader[modalIdx].xpdGain;
78462306a36Sopenharmony_ci
78562306a36Sopenharmony_ci	pwr_table_offset = ah->eep_ops->get_eeprom(ah, EEP_PWR_TABLE_OFFSET);
78662306a36Sopenharmony_ci
78762306a36Sopenharmony_ci	if (ath9k_hw_def_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_2) {
78862306a36Sopenharmony_ci		pdGainOverlap_t2 =
78962306a36Sopenharmony_ci			pEepData->modalHeader[modalIdx].pdGainOverlap;
79062306a36Sopenharmony_ci	} else {
79162306a36Sopenharmony_ci		pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5),
79262306a36Sopenharmony_ci					    AR_PHY_TPCRG5_PD_GAIN_OVERLAP));
79362306a36Sopenharmony_ci	}
79462306a36Sopenharmony_ci
79562306a36Sopenharmony_ci	if (IS_CHAN_2GHZ(chan)) {
79662306a36Sopenharmony_ci		pCalBChans = pEepData->calFreqPier2G;
79762306a36Sopenharmony_ci		numPiers = AR5416_NUM_2G_CAL_PIERS;
79862306a36Sopenharmony_ci	} else {
79962306a36Sopenharmony_ci		pCalBChans = pEepData->calFreqPier5G;
80062306a36Sopenharmony_ci		numPiers = AR5416_NUM_5G_CAL_PIERS;
80162306a36Sopenharmony_ci	}
80262306a36Sopenharmony_ci
80362306a36Sopenharmony_ci	if (OLC_FOR_AR9280_20_LATER(ah) && IS_CHAN_2GHZ(chan)) {
80462306a36Sopenharmony_ci		pRawDataset = pEepData->calPierData2G[0];
80562306a36Sopenharmony_ci		ah->initPDADC = ((struct calDataPerFreqOpLoop *)
80662306a36Sopenharmony_ci				 pRawDataset)->vpdPdg[0][0];
80762306a36Sopenharmony_ci	}
80862306a36Sopenharmony_ci
80962306a36Sopenharmony_ci	numXpdGain = 0;
81062306a36Sopenharmony_ci
81162306a36Sopenharmony_ci	for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) {
81262306a36Sopenharmony_ci		if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) {
81362306a36Sopenharmony_ci			if (numXpdGain >= AR5416_NUM_PD_GAINS)
81462306a36Sopenharmony_ci				break;
81562306a36Sopenharmony_ci			xpdGainValues[numXpdGain] =
81662306a36Sopenharmony_ci				(u16)(AR5416_PD_GAINS_IN_MASK - i);
81762306a36Sopenharmony_ci			numXpdGain++;
81862306a36Sopenharmony_ci		}
81962306a36Sopenharmony_ci	}
82062306a36Sopenharmony_ci
82162306a36Sopenharmony_ci	REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN,
82262306a36Sopenharmony_ci		      (numXpdGain - 1) & 0x3);
82362306a36Sopenharmony_ci	REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1,
82462306a36Sopenharmony_ci		      xpdGainValues[0]);
82562306a36Sopenharmony_ci	REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2,
82662306a36Sopenharmony_ci		      xpdGainValues[1]);
82762306a36Sopenharmony_ci	REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3,
82862306a36Sopenharmony_ci		      xpdGainValues[2]);
82962306a36Sopenharmony_ci
83062306a36Sopenharmony_ci	for (i = 0; i < AR5416_MAX_CHAINS; i++) {
83162306a36Sopenharmony_ci		if ((ah->rxchainmask == 5 || ah->txchainmask == 5) &&
83262306a36Sopenharmony_ci		    (i != 0)) {
83362306a36Sopenharmony_ci			regChainOffset = (i == 1) ? 0x2000 : 0x1000;
83462306a36Sopenharmony_ci		} else
83562306a36Sopenharmony_ci			regChainOffset = i * 0x1000;
83662306a36Sopenharmony_ci
83762306a36Sopenharmony_ci		if (pEepData->baseEepHeader.txMask & (1 << i)) {
83862306a36Sopenharmony_ci			if (IS_CHAN_2GHZ(chan))
83962306a36Sopenharmony_ci				pRawDataset = pEepData->calPierData2G[i];
84062306a36Sopenharmony_ci			else
84162306a36Sopenharmony_ci				pRawDataset = pEepData->calPierData5G[i];
84262306a36Sopenharmony_ci
84362306a36Sopenharmony_ci
84462306a36Sopenharmony_ci			if (OLC_FOR_AR9280_20_LATER(ah)) {
84562306a36Sopenharmony_ci				u8 pcdacIdx;
84662306a36Sopenharmony_ci				u8 txPower;
84762306a36Sopenharmony_ci
84862306a36Sopenharmony_ci				ath9k_get_txgain_index(ah, chan,
84962306a36Sopenharmony_ci				(struct calDataPerFreqOpLoop *)pRawDataset,
85062306a36Sopenharmony_ci				pCalBChans, numPiers, &txPower, &pcdacIdx);
85162306a36Sopenharmony_ci				ath9k_olc_get_pdadcs(ah, pcdacIdx,
85262306a36Sopenharmony_ci						     txPower/2, pdadcValues);
85362306a36Sopenharmony_ci			} else {
85462306a36Sopenharmony_ci				ath9k_hw_get_gain_boundaries_pdadcs(ah,
85562306a36Sopenharmony_ci							chan, pRawDataset,
85662306a36Sopenharmony_ci							pCalBChans, numPiers,
85762306a36Sopenharmony_ci							pdGainOverlap_t2,
85862306a36Sopenharmony_ci							gainBoundaries,
85962306a36Sopenharmony_ci							pdadcValues,
86062306a36Sopenharmony_ci							numXpdGain);
86162306a36Sopenharmony_ci			}
86262306a36Sopenharmony_ci
86362306a36Sopenharmony_ci			diff = ath9k_change_gain_boundary_setting(ah,
86462306a36Sopenharmony_ci							   gainBoundaries,
86562306a36Sopenharmony_ci							   numXpdGain,
86662306a36Sopenharmony_ci							   pdGainOverlap_t2,
86762306a36Sopenharmony_ci							   pwr_table_offset,
86862306a36Sopenharmony_ci							   &diff);
86962306a36Sopenharmony_ci
87062306a36Sopenharmony_ci			ENABLE_REGWRITE_BUFFER(ah);
87162306a36Sopenharmony_ci
87262306a36Sopenharmony_ci			if (OLC_FOR_AR9280_20_LATER(ah)) {
87362306a36Sopenharmony_ci				REG_WRITE(ah,
87462306a36Sopenharmony_ci					AR_PHY_TPCRG5 + regChainOffset,
87562306a36Sopenharmony_ci					SM(0x6,
87662306a36Sopenharmony_ci					AR_PHY_TPCRG5_PD_GAIN_OVERLAP) |
87762306a36Sopenharmony_ci					SM_PD_GAIN(1) | SM_PD_GAIN(2) |
87862306a36Sopenharmony_ci					SM_PD_GAIN(3) | SM_PD_GAIN(4));
87962306a36Sopenharmony_ci			} else {
88062306a36Sopenharmony_ci				REG_WRITE(ah,
88162306a36Sopenharmony_ci					AR_PHY_TPCRG5 + regChainOffset,
88262306a36Sopenharmony_ci					SM(pdGainOverlap_t2,
88362306a36Sopenharmony_ci					AR_PHY_TPCRG5_PD_GAIN_OVERLAP)|
88462306a36Sopenharmony_ci					SM_PDGAIN_B(0, 1) |
88562306a36Sopenharmony_ci					SM_PDGAIN_B(1, 2) |
88662306a36Sopenharmony_ci					SM_PDGAIN_B(2, 3) |
88762306a36Sopenharmony_ci					SM_PDGAIN_B(3, 4));
88862306a36Sopenharmony_ci			}
88962306a36Sopenharmony_ci
89062306a36Sopenharmony_ci			ath9k_adjust_pdadc_values(ah, pwr_table_offset,
89162306a36Sopenharmony_ci						  diff, pdadcValues);
89262306a36Sopenharmony_ci
89362306a36Sopenharmony_ci			regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset;
89462306a36Sopenharmony_ci			for (j = 0; j < 32; j++) {
89562306a36Sopenharmony_ci				reg32 = get_unaligned_le32(&pdadcValues[4 * j]);
89662306a36Sopenharmony_ci				REG_WRITE(ah, regOffset, reg32);
89762306a36Sopenharmony_ci
89862306a36Sopenharmony_ci				ath_dbg(common, EEPROM,
89962306a36Sopenharmony_ci					"PDADC (%d,%4x): %4.4x %8.8x\n",
90062306a36Sopenharmony_ci					i, regChainOffset, regOffset,
90162306a36Sopenharmony_ci					reg32);
90262306a36Sopenharmony_ci				ath_dbg(common, EEPROM,
90362306a36Sopenharmony_ci					"PDADC: Chain %d | PDADC %3d Value %3d | PDADC %3d Value %3d | PDADC %3d Value %3d | PDADC %3d Value %3d |\n",
90462306a36Sopenharmony_ci					i, 4 * j, pdadcValues[4 * j],
90562306a36Sopenharmony_ci					4 * j + 1, pdadcValues[4 * j + 1],
90662306a36Sopenharmony_ci					4 * j + 2, pdadcValues[4 * j + 2],
90762306a36Sopenharmony_ci					4 * j + 3, pdadcValues[4 * j + 3]);
90862306a36Sopenharmony_ci
90962306a36Sopenharmony_ci				regOffset += 4;
91062306a36Sopenharmony_ci			}
91162306a36Sopenharmony_ci			REGWRITE_BUFFER_FLUSH(ah);
91262306a36Sopenharmony_ci		}
91362306a36Sopenharmony_ci	}
91462306a36Sopenharmony_ci
91562306a36Sopenharmony_ci#undef SM_PD_GAIN
91662306a36Sopenharmony_ci#undef SM_PDGAIN_B
91762306a36Sopenharmony_ci}
91862306a36Sopenharmony_ci
91962306a36Sopenharmony_cistatic void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah,
92062306a36Sopenharmony_ci						  struct ath9k_channel *chan,
92162306a36Sopenharmony_ci						  int16_t *ratesArray,
92262306a36Sopenharmony_ci						  u16 cfgCtl,
92362306a36Sopenharmony_ci						  u16 antenna_reduction,
92462306a36Sopenharmony_ci						  u16 powerLimit)
92562306a36Sopenharmony_ci{
92662306a36Sopenharmony_ci	struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;
92762306a36Sopenharmony_ci	u16 twiceMaxEdgePower;
92862306a36Sopenharmony_ci	int i;
92962306a36Sopenharmony_ci	struct cal_ctl_data *rep;
93062306a36Sopenharmony_ci	struct cal_target_power_leg targetPowerOfdm, targetPowerCck = {
93162306a36Sopenharmony_ci		0, { 0, 0, 0, 0}
93262306a36Sopenharmony_ci	};
93362306a36Sopenharmony_ci	struct cal_target_power_leg targetPowerOfdmExt = {
93462306a36Sopenharmony_ci		0, { 0, 0, 0, 0} }, targetPowerCckExt = {
93562306a36Sopenharmony_ci		0, { 0, 0, 0, 0 }
93662306a36Sopenharmony_ci	};
93762306a36Sopenharmony_ci	struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = {
93862306a36Sopenharmony_ci		0, {0, 0, 0, 0}
93962306a36Sopenharmony_ci	};
94062306a36Sopenharmony_ci	u16 scaledPower = 0, minCtlPower;
94162306a36Sopenharmony_ci	static const u16 ctlModesFor11a[] = {
94262306a36Sopenharmony_ci		CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40
94362306a36Sopenharmony_ci	};
94462306a36Sopenharmony_ci	static const u16 ctlModesFor11g[] = {
94562306a36Sopenharmony_ci		CTL_11B, CTL_11G, CTL_2GHT20,
94662306a36Sopenharmony_ci		CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40
94762306a36Sopenharmony_ci	};
94862306a36Sopenharmony_ci	u16 numCtlModes;
94962306a36Sopenharmony_ci	const u16 *pCtlMode;
95062306a36Sopenharmony_ci	u16 ctlMode, freq;
95162306a36Sopenharmony_ci	struct chan_centers centers;
95262306a36Sopenharmony_ci	int tx_chainmask;
95362306a36Sopenharmony_ci	u16 twiceMinEdgePower;
95462306a36Sopenharmony_ci
95562306a36Sopenharmony_ci	tx_chainmask = ah->txchainmask;
95662306a36Sopenharmony_ci
95762306a36Sopenharmony_ci	ath9k_hw_get_channel_centers(ah, chan, &centers);
95862306a36Sopenharmony_ci
95962306a36Sopenharmony_ci	scaledPower = ath9k_hw_get_scaled_power(ah, powerLimit,
96062306a36Sopenharmony_ci						antenna_reduction);
96162306a36Sopenharmony_ci
96262306a36Sopenharmony_ci	if (IS_CHAN_2GHZ(chan)) {
96362306a36Sopenharmony_ci		numCtlModes = ARRAY_SIZE(ctlModesFor11g) -
96462306a36Sopenharmony_ci			SUB_NUM_CTL_MODES_AT_2G_40;
96562306a36Sopenharmony_ci		pCtlMode = ctlModesFor11g;
96662306a36Sopenharmony_ci
96762306a36Sopenharmony_ci		ath9k_hw_get_legacy_target_powers(ah, chan,
96862306a36Sopenharmony_ci			pEepData->calTargetPowerCck,
96962306a36Sopenharmony_ci			AR5416_NUM_2G_CCK_TARGET_POWERS,
97062306a36Sopenharmony_ci			&targetPowerCck, 4, false);
97162306a36Sopenharmony_ci		ath9k_hw_get_legacy_target_powers(ah, chan,
97262306a36Sopenharmony_ci			pEepData->calTargetPower2G,
97362306a36Sopenharmony_ci			AR5416_NUM_2G_20_TARGET_POWERS,
97462306a36Sopenharmony_ci			&targetPowerOfdm, 4, false);
97562306a36Sopenharmony_ci		ath9k_hw_get_target_powers(ah, chan,
97662306a36Sopenharmony_ci			pEepData->calTargetPower2GHT20,
97762306a36Sopenharmony_ci			AR5416_NUM_2G_20_TARGET_POWERS,
97862306a36Sopenharmony_ci			&targetPowerHt20, 8, false);
97962306a36Sopenharmony_ci
98062306a36Sopenharmony_ci		if (IS_CHAN_HT40(chan)) {
98162306a36Sopenharmony_ci			numCtlModes = ARRAY_SIZE(ctlModesFor11g);
98262306a36Sopenharmony_ci			ath9k_hw_get_target_powers(ah, chan,
98362306a36Sopenharmony_ci				pEepData->calTargetPower2GHT40,
98462306a36Sopenharmony_ci				AR5416_NUM_2G_40_TARGET_POWERS,
98562306a36Sopenharmony_ci				&targetPowerHt40, 8, true);
98662306a36Sopenharmony_ci			ath9k_hw_get_legacy_target_powers(ah, chan,
98762306a36Sopenharmony_ci				pEepData->calTargetPowerCck,
98862306a36Sopenharmony_ci				AR5416_NUM_2G_CCK_TARGET_POWERS,
98962306a36Sopenharmony_ci				&targetPowerCckExt, 4, true);
99062306a36Sopenharmony_ci			ath9k_hw_get_legacy_target_powers(ah, chan,
99162306a36Sopenharmony_ci				pEepData->calTargetPower2G,
99262306a36Sopenharmony_ci				AR5416_NUM_2G_20_TARGET_POWERS,
99362306a36Sopenharmony_ci				&targetPowerOfdmExt, 4, true);
99462306a36Sopenharmony_ci		}
99562306a36Sopenharmony_ci	} else {
99662306a36Sopenharmony_ci		numCtlModes = ARRAY_SIZE(ctlModesFor11a) -
99762306a36Sopenharmony_ci			SUB_NUM_CTL_MODES_AT_5G_40;
99862306a36Sopenharmony_ci		pCtlMode = ctlModesFor11a;
99962306a36Sopenharmony_ci
100062306a36Sopenharmony_ci		ath9k_hw_get_legacy_target_powers(ah, chan,
100162306a36Sopenharmony_ci			pEepData->calTargetPower5G,
100262306a36Sopenharmony_ci			AR5416_NUM_5G_20_TARGET_POWERS,
100362306a36Sopenharmony_ci			&targetPowerOfdm, 4, false);
100462306a36Sopenharmony_ci		ath9k_hw_get_target_powers(ah, chan,
100562306a36Sopenharmony_ci			pEepData->calTargetPower5GHT20,
100662306a36Sopenharmony_ci			AR5416_NUM_5G_20_TARGET_POWERS,
100762306a36Sopenharmony_ci			&targetPowerHt20, 8, false);
100862306a36Sopenharmony_ci
100962306a36Sopenharmony_ci		if (IS_CHAN_HT40(chan)) {
101062306a36Sopenharmony_ci			numCtlModes = ARRAY_SIZE(ctlModesFor11a);
101162306a36Sopenharmony_ci			ath9k_hw_get_target_powers(ah, chan,
101262306a36Sopenharmony_ci				pEepData->calTargetPower5GHT40,
101362306a36Sopenharmony_ci				AR5416_NUM_5G_40_TARGET_POWERS,
101462306a36Sopenharmony_ci				&targetPowerHt40, 8, true);
101562306a36Sopenharmony_ci			ath9k_hw_get_legacy_target_powers(ah, chan,
101662306a36Sopenharmony_ci				pEepData->calTargetPower5G,
101762306a36Sopenharmony_ci				AR5416_NUM_5G_20_TARGET_POWERS,
101862306a36Sopenharmony_ci				&targetPowerOfdmExt, 4, true);
101962306a36Sopenharmony_ci		}
102062306a36Sopenharmony_ci	}
102162306a36Sopenharmony_ci
102262306a36Sopenharmony_ci	for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) {
102362306a36Sopenharmony_ci		bool isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) ||
102462306a36Sopenharmony_ci			(pCtlMode[ctlMode] == CTL_2GHT40);
102562306a36Sopenharmony_ci		if (isHt40CtlMode)
102662306a36Sopenharmony_ci			freq = centers.synth_center;
102762306a36Sopenharmony_ci		else if (pCtlMode[ctlMode] & EXT_ADDITIVE)
102862306a36Sopenharmony_ci			freq = centers.ext_center;
102962306a36Sopenharmony_ci		else
103062306a36Sopenharmony_ci			freq = centers.ctl_center;
103162306a36Sopenharmony_ci
103262306a36Sopenharmony_ci		twiceMaxEdgePower = MAX_RATE_POWER;
103362306a36Sopenharmony_ci
103462306a36Sopenharmony_ci		for (i = 0; (i < AR5416_NUM_CTLS) && pEepData->ctlIndex[i]; i++) {
103562306a36Sopenharmony_ci			if ((((cfgCtl & ~CTL_MODE_M) |
103662306a36Sopenharmony_ci			      (pCtlMode[ctlMode] & CTL_MODE_M)) ==
103762306a36Sopenharmony_ci			     pEepData->ctlIndex[i]) ||
103862306a36Sopenharmony_ci			    (((cfgCtl & ~CTL_MODE_M) |
103962306a36Sopenharmony_ci			      (pCtlMode[ctlMode] & CTL_MODE_M)) ==
104062306a36Sopenharmony_ci			     ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL))) {
104162306a36Sopenharmony_ci				rep = &(pEepData->ctlData[i]);
104262306a36Sopenharmony_ci
104362306a36Sopenharmony_ci				twiceMinEdgePower = ath9k_hw_get_max_edge_power(freq,
104462306a36Sopenharmony_ci				rep->ctlEdges[ar5416_get_ntxchains(tx_chainmask) - 1],
104562306a36Sopenharmony_ci				IS_CHAN_2GHZ(chan), AR5416_NUM_BAND_EDGES);
104662306a36Sopenharmony_ci
104762306a36Sopenharmony_ci				if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) {
104862306a36Sopenharmony_ci					twiceMaxEdgePower = min(twiceMaxEdgePower,
104962306a36Sopenharmony_ci								twiceMinEdgePower);
105062306a36Sopenharmony_ci				} else {
105162306a36Sopenharmony_ci					twiceMaxEdgePower = twiceMinEdgePower;
105262306a36Sopenharmony_ci					break;
105362306a36Sopenharmony_ci				}
105462306a36Sopenharmony_ci			}
105562306a36Sopenharmony_ci		}
105662306a36Sopenharmony_ci
105762306a36Sopenharmony_ci		minCtlPower = min(twiceMaxEdgePower, scaledPower);
105862306a36Sopenharmony_ci
105962306a36Sopenharmony_ci		switch (pCtlMode[ctlMode]) {
106062306a36Sopenharmony_ci		case CTL_11B:
106162306a36Sopenharmony_ci			for (i = 0; i < ARRAY_SIZE(targetPowerCck.tPow2x); i++) {
106262306a36Sopenharmony_ci				targetPowerCck.tPow2x[i] =
106362306a36Sopenharmony_ci					min((u16)targetPowerCck.tPow2x[i],
106462306a36Sopenharmony_ci					    minCtlPower);
106562306a36Sopenharmony_ci			}
106662306a36Sopenharmony_ci			break;
106762306a36Sopenharmony_ci		case CTL_11A:
106862306a36Sopenharmony_ci		case CTL_11G:
106962306a36Sopenharmony_ci			for (i = 0; i < ARRAY_SIZE(targetPowerOfdm.tPow2x); i++) {
107062306a36Sopenharmony_ci				targetPowerOfdm.tPow2x[i] =
107162306a36Sopenharmony_ci					min((u16)targetPowerOfdm.tPow2x[i],
107262306a36Sopenharmony_ci					    minCtlPower);
107362306a36Sopenharmony_ci			}
107462306a36Sopenharmony_ci			break;
107562306a36Sopenharmony_ci		case CTL_5GHT20:
107662306a36Sopenharmony_ci		case CTL_2GHT20:
107762306a36Sopenharmony_ci			for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++) {
107862306a36Sopenharmony_ci				targetPowerHt20.tPow2x[i] =
107962306a36Sopenharmony_ci					min((u16)targetPowerHt20.tPow2x[i],
108062306a36Sopenharmony_ci					    minCtlPower);
108162306a36Sopenharmony_ci			}
108262306a36Sopenharmony_ci			break;
108362306a36Sopenharmony_ci		case CTL_11B_EXT:
108462306a36Sopenharmony_ci			targetPowerCckExt.tPow2x[0] = min((u16)
108562306a36Sopenharmony_ci					targetPowerCckExt.tPow2x[0],
108662306a36Sopenharmony_ci					minCtlPower);
108762306a36Sopenharmony_ci			break;
108862306a36Sopenharmony_ci		case CTL_11A_EXT:
108962306a36Sopenharmony_ci		case CTL_11G_EXT:
109062306a36Sopenharmony_ci			targetPowerOfdmExt.tPow2x[0] = min((u16)
109162306a36Sopenharmony_ci					targetPowerOfdmExt.tPow2x[0],
109262306a36Sopenharmony_ci					minCtlPower);
109362306a36Sopenharmony_ci			break;
109462306a36Sopenharmony_ci		case CTL_5GHT40:
109562306a36Sopenharmony_ci		case CTL_2GHT40:
109662306a36Sopenharmony_ci			for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {
109762306a36Sopenharmony_ci				targetPowerHt40.tPow2x[i] =
109862306a36Sopenharmony_ci					min((u16)targetPowerHt40.tPow2x[i],
109962306a36Sopenharmony_ci					    minCtlPower);
110062306a36Sopenharmony_ci			}
110162306a36Sopenharmony_ci			break;
110262306a36Sopenharmony_ci		default:
110362306a36Sopenharmony_ci			break;
110462306a36Sopenharmony_ci		}
110562306a36Sopenharmony_ci	}
110662306a36Sopenharmony_ci
110762306a36Sopenharmony_ci	ratesArray[rate6mb] = ratesArray[rate9mb] = ratesArray[rate12mb] =
110862306a36Sopenharmony_ci		ratesArray[rate18mb] = ratesArray[rate24mb] =
110962306a36Sopenharmony_ci		targetPowerOfdm.tPow2x[0];
111062306a36Sopenharmony_ci	ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1];
111162306a36Sopenharmony_ci	ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2];
111262306a36Sopenharmony_ci	ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3];
111362306a36Sopenharmony_ci	ratesArray[rateXr] = targetPowerOfdm.tPow2x[0];
111462306a36Sopenharmony_ci
111562306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++)
111662306a36Sopenharmony_ci		ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i];
111762306a36Sopenharmony_ci
111862306a36Sopenharmony_ci	if (IS_CHAN_2GHZ(chan)) {
111962306a36Sopenharmony_ci		ratesArray[rate1l] = targetPowerCck.tPow2x[0];
112062306a36Sopenharmony_ci		ratesArray[rate2s] = ratesArray[rate2l] =
112162306a36Sopenharmony_ci			targetPowerCck.tPow2x[1];
112262306a36Sopenharmony_ci		ratesArray[rate5_5s] = ratesArray[rate5_5l] =
112362306a36Sopenharmony_ci			targetPowerCck.tPow2x[2];
112462306a36Sopenharmony_ci		ratesArray[rate11s] = ratesArray[rate11l] =
112562306a36Sopenharmony_ci			targetPowerCck.tPow2x[3];
112662306a36Sopenharmony_ci	}
112762306a36Sopenharmony_ci	if (IS_CHAN_HT40(chan)) {
112862306a36Sopenharmony_ci		for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {
112962306a36Sopenharmony_ci			ratesArray[rateHt40_0 + i] =
113062306a36Sopenharmony_ci				targetPowerHt40.tPow2x[i];
113162306a36Sopenharmony_ci		}
113262306a36Sopenharmony_ci		ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0];
113362306a36Sopenharmony_ci		ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0];
113462306a36Sopenharmony_ci		ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0];
113562306a36Sopenharmony_ci		if (IS_CHAN_2GHZ(chan)) {
113662306a36Sopenharmony_ci			ratesArray[rateExtCck] =
113762306a36Sopenharmony_ci				targetPowerCckExt.tPow2x[0];
113862306a36Sopenharmony_ci		}
113962306a36Sopenharmony_ci	}
114062306a36Sopenharmony_ci}
114162306a36Sopenharmony_ci
114262306a36Sopenharmony_cistatic void ath9k_hw_def_set_txpower(struct ath_hw *ah,
114362306a36Sopenharmony_ci				    struct ath9k_channel *chan,
114462306a36Sopenharmony_ci				    u16 cfgCtl,
114562306a36Sopenharmony_ci				    u8 twiceAntennaReduction,
114662306a36Sopenharmony_ci				    u8 powerLimit, bool test)
114762306a36Sopenharmony_ci{
114862306a36Sopenharmony_ci#define RT_AR_DELTA(x) (ratesArray[x] - cck_ofdm_delta)
114962306a36Sopenharmony_ci	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
115062306a36Sopenharmony_ci	struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;
115162306a36Sopenharmony_ci	struct modal_eep_header *pModal =
115262306a36Sopenharmony_ci		&(pEepData->modalHeader[IS_CHAN_2GHZ(chan)]);
115362306a36Sopenharmony_ci	int16_t ratesArray[Ar5416RateSize];
115462306a36Sopenharmony_ci	u8 ht40PowerIncForPdadc = 2;
115562306a36Sopenharmony_ci	int i, cck_ofdm_delta = 0;
115662306a36Sopenharmony_ci
115762306a36Sopenharmony_ci	memset(ratesArray, 0, sizeof(ratesArray));
115862306a36Sopenharmony_ci
115962306a36Sopenharmony_ci	if (ath9k_hw_def_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_2)
116062306a36Sopenharmony_ci		ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
116162306a36Sopenharmony_ci
116262306a36Sopenharmony_ci	ath9k_hw_set_def_power_per_rate_table(ah, chan,
116362306a36Sopenharmony_ci					       &ratesArray[0], cfgCtl,
116462306a36Sopenharmony_ci					       twiceAntennaReduction,
116562306a36Sopenharmony_ci					       powerLimit);
116662306a36Sopenharmony_ci
116762306a36Sopenharmony_ci	ath9k_hw_set_def_power_cal_table(ah, chan);
116862306a36Sopenharmony_ci
116962306a36Sopenharmony_ci	regulatory->max_power_level = 0;
117062306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
117162306a36Sopenharmony_ci		if (ratesArray[i] > MAX_RATE_POWER)
117262306a36Sopenharmony_ci			ratesArray[i] = MAX_RATE_POWER;
117362306a36Sopenharmony_ci		if (ratesArray[i] > regulatory->max_power_level)
117462306a36Sopenharmony_ci			regulatory->max_power_level = ratesArray[i];
117562306a36Sopenharmony_ci	}
117662306a36Sopenharmony_ci
117762306a36Sopenharmony_ci	ath9k_hw_update_regulatory_maxpower(ah);
117862306a36Sopenharmony_ci
117962306a36Sopenharmony_ci	if (test)
118062306a36Sopenharmony_ci		return;
118162306a36Sopenharmony_ci
118262306a36Sopenharmony_ci	if (AR_SREV_9280_20_OR_LATER(ah)) {
118362306a36Sopenharmony_ci		for (i = 0; i < Ar5416RateSize; i++) {
118462306a36Sopenharmony_ci			int8_t pwr_table_offset;
118562306a36Sopenharmony_ci
118662306a36Sopenharmony_ci			pwr_table_offset = ah->eep_ops->get_eeprom(ah,
118762306a36Sopenharmony_ci							EEP_PWR_TABLE_OFFSET);
118862306a36Sopenharmony_ci			ratesArray[i] -= pwr_table_offset * 2;
118962306a36Sopenharmony_ci		}
119062306a36Sopenharmony_ci	}
119162306a36Sopenharmony_ci
119262306a36Sopenharmony_ci	ENABLE_REGWRITE_BUFFER(ah);
119362306a36Sopenharmony_ci
119462306a36Sopenharmony_ci	REG_WRITE(ah, AR_PHY_POWER_TX_RATE1,
119562306a36Sopenharmony_ci		  ATH9K_POW_SM(ratesArray[rate18mb], 24)
119662306a36Sopenharmony_ci		  | ATH9K_POW_SM(ratesArray[rate12mb], 16)
119762306a36Sopenharmony_ci		  | ATH9K_POW_SM(ratesArray[rate9mb], 8)
119862306a36Sopenharmony_ci		  | ATH9K_POW_SM(ratesArray[rate6mb], 0));
119962306a36Sopenharmony_ci	REG_WRITE(ah, AR_PHY_POWER_TX_RATE2,
120062306a36Sopenharmony_ci		  ATH9K_POW_SM(ratesArray[rate54mb], 24)
120162306a36Sopenharmony_ci		  | ATH9K_POW_SM(ratesArray[rate48mb], 16)
120262306a36Sopenharmony_ci		  | ATH9K_POW_SM(ratesArray[rate36mb], 8)
120362306a36Sopenharmony_ci		  | ATH9K_POW_SM(ratesArray[rate24mb], 0));
120462306a36Sopenharmony_ci
120562306a36Sopenharmony_ci	if (IS_CHAN_2GHZ(chan)) {
120662306a36Sopenharmony_ci		if (OLC_FOR_AR9280_20_LATER(ah)) {
120762306a36Sopenharmony_ci			cck_ofdm_delta = 2;
120862306a36Sopenharmony_ci			REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
120962306a36Sopenharmony_ci				ATH9K_POW_SM(RT_AR_DELTA(rate2s), 24)
121062306a36Sopenharmony_ci				| ATH9K_POW_SM(RT_AR_DELTA(rate2l), 16)
121162306a36Sopenharmony_ci				| ATH9K_POW_SM(ratesArray[rateXr], 8)
121262306a36Sopenharmony_ci				| ATH9K_POW_SM(RT_AR_DELTA(rate1l), 0));
121362306a36Sopenharmony_ci			REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
121462306a36Sopenharmony_ci				ATH9K_POW_SM(RT_AR_DELTA(rate11s), 24)
121562306a36Sopenharmony_ci				| ATH9K_POW_SM(RT_AR_DELTA(rate11l), 16)
121662306a36Sopenharmony_ci				| ATH9K_POW_SM(RT_AR_DELTA(rate5_5s), 8)
121762306a36Sopenharmony_ci				| ATH9K_POW_SM(RT_AR_DELTA(rate5_5l), 0));
121862306a36Sopenharmony_ci		} else {
121962306a36Sopenharmony_ci			REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
122062306a36Sopenharmony_ci				ATH9K_POW_SM(ratesArray[rate2s], 24)
122162306a36Sopenharmony_ci				| ATH9K_POW_SM(ratesArray[rate2l], 16)
122262306a36Sopenharmony_ci				| ATH9K_POW_SM(ratesArray[rateXr], 8)
122362306a36Sopenharmony_ci				| ATH9K_POW_SM(ratesArray[rate1l], 0));
122462306a36Sopenharmony_ci			REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
122562306a36Sopenharmony_ci				ATH9K_POW_SM(ratesArray[rate11s], 24)
122662306a36Sopenharmony_ci				| ATH9K_POW_SM(ratesArray[rate11l], 16)
122762306a36Sopenharmony_ci				| ATH9K_POW_SM(ratesArray[rate5_5s], 8)
122862306a36Sopenharmony_ci				| ATH9K_POW_SM(ratesArray[rate5_5l], 0));
122962306a36Sopenharmony_ci		}
123062306a36Sopenharmony_ci	}
123162306a36Sopenharmony_ci
123262306a36Sopenharmony_ci	REG_WRITE(ah, AR_PHY_POWER_TX_RATE5,
123362306a36Sopenharmony_ci		  ATH9K_POW_SM(ratesArray[rateHt20_3], 24)
123462306a36Sopenharmony_ci		  | ATH9K_POW_SM(ratesArray[rateHt20_2], 16)
123562306a36Sopenharmony_ci		  | ATH9K_POW_SM(ratesArray[rateHt20_1], 8)
123662306a36Sopenharmony_ci		  | ATH9K_POW_SM(ratesArray[rateHt20_0], 0));
123762306a36Sopenharmony_ci	REG_WRITE(ah, AR_PHY_POWER_TX_RATE6,
123862306a36Sopenharmony_ci		  ATH9K_POW_SM(ratesArray[rateHt20_7], 24)
123962306a36Sopenharmony_ci		  | ATH9K_POW_SM(ratesArray[rateHt20_6], 16)
124062306a36Sopenharmony_ci		  | ATH9K_POW_SM(ratesArray[rateHt20_5], 8)
124162306a36Sopenharmony_ci		  | ATH9K_POW_SM(ratesArray[rateHt20_4], 0));
124262306a36Sopenharmony_ci
124362306a36Sopenharmony_ci	if (IS_CHAN_HT40(chan)) {
124462306a36Sopenharmony_ci		REG_WRITE(ah, AR_PHY_POWER_TX_RATE7,
124562306a36Sopenharmony_ci			  ATH9K_POW_SM(ratesArray[rateHt40_3] +
124662306a36Sopenharmony_ci				       ht40PowerIncForPdadc, 24)
124762306a36Sopenharmony_ci			  | ATH9K_POW_SM(ratesArray[rateHt40_2] +
124862306a36Sopenharmony_ci					 ht40PowerIncForPdadc, 16)
124962306a36Sopenharmony_ci			  | ATH9K_POW_SM(ratesArray[rateHt40_1] +
125062306a36Sopenharmony_ci					 ht40PowerIncForPdadc, 8)
125162306a36Sopenharmony_ci			  | ATH9K_POW_SM(ratesArray[rateHt40_0] +
125262306a36Sopenharmony_ci					 ht40PowerIncForPdadc, 0));
125362306a36Sopenharmony_ci		REG_WRITE(ah, AR_PHY_POWER_TX_RATE8,
125462306a36Sopenharmony_ci			  ATH9K_POW_SM(ratesArray[rateHt40_7] +
125562306a36Sopenharmony_ci				       ht40PowerIncForPdadc, 24)
125662306a36Sopenharmony_ci			  | ATH9K_POW_SM(ratesArray[rateHt40_6] +
125762306a36Sopenharmony_ci					 ht40PowerIncForPdadc, 16)
125862306a36Sopenharmony_ci			  | ATH9K_POW_SM(ratesArray[rateHt40_5] +
125962306a36Sopenharmony_ci					 ht40PowerIncForPdadc, 8)
126062306a36Sopenharmony_ci			  | ATH9K_POW_SM(ratesArray[rateHt40_4] +
126162306a36Sopenharmony_ci					 ht40PowerIncForPdadc, 0));
126262306a36Sopenharmony_ci		if (OLC_FOR_AR9280_20_LATER(ah)) {
126362306a36Sopenharmony_ci			REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
126462306a36Sopenharmony_ci				ATH9K_POW_SM(ratesArray[rateExtOfdm], 24)
126562306a36Sopenharmony_ci				| ATH9K_POW_SM(RT_AR_DELTA(rateExtCck), 16)
126662306a36Sopenharmony_ci				| ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
126762306a36Sopenharmony_ci				| ATH9K_POW_SM(RT_AR_DELTA(rateDupCck), 0));
126862306a36Sopenharmony_ci		} else {
126962306a36Sopenharmony_ci			REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
127062306a36Sopenharmony_ci				ATH9K_POW_SM(ratesArray[rateExtOfdm], 24)
127162306a36Sopenharmony_ci				| ATH9K_POW_SM(ratesArray[rateExtCck], 16)
127262306a36Sopenharmony_ci				| ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
127362306a36Sopenharmony_ci				| ATH9K_POW_SM(ratesArray[rateDupCck], 0));
127462306a36Sopenharmony_ci		}
127562306a36Sopenharmony_ci	}
127662306a36Sopenharmony_ci
127762306a36Sopenharmony_ci	REG_WRITE(ah, AR_PHY_POWER_TX_SUB,
127862306a36Sopenharmony_ci		  ATH9K_POW_SM(pModal->pwrDecreaseFor3Chain, 6)
127962306a36Sopenharmony_ci		  | ATH9K_POW_SM(pModal->pwrDecreaseFor2Chain, 0));
128062306a36Sopenharmony_ci
128162306a36Sopenharmony_ci	/* TPC initializations */
128262306a36Sopenharmony_ci	if (ah->tpc_enabled) {
128362306a36Sopenharmony_ci		int ht40_delta;
128462306a36Sopenharmony_ci
128562306a36Sopenharmony_ci		ht40_delta = (IS_CHAN_HT40(chan)) ? ht40PowerIncForPdadc : 0;
128662306a36Sopenharmony_ci		ar5008_hw_init_rate_txpower(ah, ratesArray, chan, ht40_delta);
128762306a36Sopenharmony_ci		/* Enable TPC */
128862306a36Sopenharmony_ci		REG_WRITE(ah, AR_PHY_POWER_TX_RATE_MAX,
128962306a36Sopenharmony_ci			MAX_RATE_POWER | AR_PHY_POWER_TX_RATE_MAX_TPC_ENABLE);
129062306a36Sopenharmony_ci	} else {
129162306a36Sopenharmony_ci		/* Disable TPC */
129262306a36Sopenharmony_ci		REG_WRITE(ah, AR_PHY_POWER_TX_RATE_MAX, MAX_RATE_POWER);
129362306a36Sopenharmony_ci	}
129462306a36Sopenharmony_ci
129562306a36Sopenharmony_ci	REGWRITE_BUFFER_FLUSH(ah);
129662306a36Sopenharmony_ci}
129762306a36Sopenharmony_ci
129862306a36Sopenharmony_cistatic u16 ath9k_hw_def_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz)
129962306a36Sopenharmony_ci{
130062306a36Sopenharmony_ci	__le16 spch = ah->eeprom.def.modalHeader[is2GHz].spurChans[i].spurChan;
130162306a36Sopenharmony_ci
130262306a36Sopenharmony_ci	return le16_to_cpu(spch);
130362306a36Sopenharmony_ci}
130462306a36Sopenharmony_ci
130562306a36Sopenharmony_cistatic u8 ath9k_hw_def_get_eepmisc(struct ath_hw *ah)
130662306a36Sopenharmony_ci{
130762306a36Sopenharmony_ci	return ah->eeprom.def.baseEepHeader.eepMisc;
130862306a36Sopenharmony_ci}
130962306a36Sopenharmony_ci
131062306a36Sopenharmony_ciconst struct eeprom_ops eep_def_ops = {
131162306a36Sopenharmony_ci	.check_eeprom		= ath9k_hw_def_check_eeprom,
131262306a36Sopenharmony_ci	.get_eeprom		= ath9k_hw_def_get_eeprom,
131362306a36Sopenharmony_ci	.fill_eeprom		= ath9k_hw_def_fill_eeprom,
131462306a36Sopenharmony_ci	.dump_eeprom		= ath9k_hw_def_dump_eeprom,
131562306a36Sopenharmony_ci	.get_eeprom_ver		= ath9k_hw_def_get_eeprom_ver,
131662306a36Sopenharmony_ci	.get_eeprom_rev		= ath9k_hw_def_get_eeprom_rev,
131762306a36Sopenharmony_ci	.set_board_values	= ath9k_hw_def_set_board_values,
131862306a36Sopenharmony_ci	.set_addac		= ath9k_hw_def_set_addac,
131962306a36Sopenharmony_ci	.set_txpower		= ath9k_hw_def_set_txpower,
132062306a36Sopenharmony_ci	.get_spur_channel	= ath9k_hw_def_get_spur_channel,
132162306a36Sopenharmony_ci	.get_eepmisc		= ath9k_hw_def_get_eepmisc
132262306a36Sopenharmony_ci};
1323