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_ci#define SIZE_EEPROM_AR9287 (sizeof(struct ar9287_eeprom) / sizeof(u16))
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_cistatic int ath9k_hw_ar9287_get_eeprom_ver(struct ath_hw *ah)
2462306a36Sopenharmony_ci{
2562306a36Sopenharmony_ci	u16 version = le16_to_cpu(ah->eeprom.map9287.baseEepHeader.version);
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci	return (version & AR5416_EEP_VER_MAJOR_MASK) >>
2862306a36Sopenharmony_ci		AR5416_EEP_VER_MAJOR_SHIFT;
2962306a36Sopenharmony_ci}
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_cistatic int ath9k_hw_ar9287_get_eeprom_rev(struct ath_hw *ah)
3262306a36Sopenharmony_ci{
3362306a36Sopenharmony_ci	u16 version = le16_to_cpu(ah->eeprom.map9287.baseEepHeader.version);
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci	return version & AR5416_EEP_VER_MINOR_MASK;
3662306a36Sopenharmony_ci}
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_cistatic bool __ath9k_hw_ar9287_fill_eeprom(struct ath_hw *ah)
3962306a36Sopenharmony_ci{
4062306a36Sopenharmony_ci	struct ar9287_eeprom *eep = &ah->eeprom.map9287;
4162306a36Sopenharmony_ci	u16 *eep_data;
4262306a36Sopenharmony_ci	int addr, eep_start_loc = AR9287_EEP_START_LOC;
4362306a36Sopenharmony_ci	eep_data = (u16 *)eep;
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci	for (addr = 0; addr < SIZE_EEPROM_AR9287; addr++) {
4662306a36Sopenharmony_ci		if (!ath9k_hw_nvram_read(ah, addr + eep_start_loc, eep_data))
4762306a36Sopenharmony_ci			return false;
4862306a36Sopenharmony_ci		eep_data++;
4962306a36Sopenharmony_ci	}
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci	return true;
5262306a36Sopenharmony_ci}
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_cistatic bool __ath9k_hw_usb_ar9287_fill_eeprom(struct ath_hw *ah)
5562306a36Sopenharmony_ci{
5662306a36Sopenharmony_ci	u16 *eep_data = (u16 *)&ah->eeprom.map9287;
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci	ath9k_hw_usb_gen_fill_eeprom(ah, eep_data,
5962306a36Sopenharmony_ci				     AR9287_HTC_EEP_START_LOC,
6062306a36Sopenharmony_ci				     SIZE_EEPROM_AR9287);
6162306a36Sopenharmony_ci	return true;
6262306a36Sopenharmony_ci}
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_cistatic bool ath9k_hw_ar9287_fill_eeprom(struct ath_hw *ah)
6562306a36Sopenharmony_ci{
6662306a36Sopenharmony_ci	struct ath_common *common = ath9k_hw_common(ah);
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci	if (!ath9k_hw_use_flash(ah)) {
6962306a36Sopenharmony_ci		ath_dbg(common, EEPROM, "Reading from EEPROM, not flash\n");
7062306a36Sopenharmony_ci	}
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci	if (common->bus_ops->ath_bus_type == ATH_USB)
7362306a36Sopenharmony_ci		return __ath9k_hw_usb_ar9287_fill_eeprom(ah);
7462306a36Sopenharmony_ci	else
7562306a36Sopenharmony_ci		return __ath9k_hw_ar9287_fill_eeprom(ah);
7662306a36Sopenharmony_ci}
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci#ifdef CONFIG_ATH9K_COMMON_DEBUG
7962306a36Sopenharmony_cistatic u32 ar9287_dump_modal_eeprom(char *buf, u32 len, u32 size,
8062306a36Sopenharmony_ci				    struct modal_eep_ar9287_header *modal_hdr)
8162306a36Sopenharmony_ci{
8262306a36Sopenharmony_ci	PR_EEP("Chain0 Ant. Control", le16_to_cpu(modal_hdr->antCtrlChain[0]));
8362306a36Sopenharmony_ci	PR_EEP("Chain1 Ant. Control", le16_to_cpu(modal_hdr->antCtrlChain[1]));
8462306a36Sopenharmony_ci	PR_EEP("Ant. Common Control", le32_to_cpu(modal_hdr->antCtrlCommon));
8562306a36Sopenharmony_ci	PR_EEP("Chain0 Ant. Gain", modal_hdr->antennaGainCh[0]);
8662306a36Sopenharmony_ci	PR_EEP("Chain1 Ant. Gain", modal_hdr->antennaGainCh[1]);
8762306a36Sopenharmony_ci	PR_EEP("Switch Settle", modal_hdr->switchSettling);
8862306a36Sopenharmony_ci	PR_EEP("Chain0 TxRxAtten", modal_hdr->txRxAttenCh[0]);
8962306a36Sopenharmony_ci	PR_EEP("Chain1 TxRxAtten", modal_hdr->txRxAttenCh[1]);
9062306a36Sopenharmony_ci	PR_EEP("Chain0 RxTxMargin", modal_hdr->rxTxMarginCh[0]);
9162306a36Sopenharmony_ci	PR_EEP("Chain1 RxTxMargin", modal_hdr->rxTxMarginCh[1]);
9262306a36Sopenharmony_ci	PR_EEP("ADC Desired size", modal_hdr->adcDesiredSize);
9362306a36Sopenharmony_ci	PR_EEP("txEndToXpaOff", modal_hdr->txEndToXpaOff);
9462306a36Sopenharmony_ci	PR_EEP("txEndToRxOn", modal_hdr->txEndToRxOn);
9562306a36Sopenharmony_ci	PR_EEP("txFrameToXpaOn", modal_hdr->txFrameToXpaOn);
9662306a36Sopenharmony_ci	PR_EEP("CCA Threshold)", modal_hdr->thresh62);
9762306a36Sopenharmony_ci	PR_EEP("Chain0 NF Threshold", modal_hdr->noiseFloorThreshCh[0]);
9862306a36Sopenharmony_ci	PR_EEP("Chain1 NF Threshold", modal_hdr->noiseFloorThreshCh[1]);
9962306a36Sopenharmony_ci	PR_EEP("xpdGain", modal_hdr->xpdGain);
10062306a36Sopenharmony_ci	PR_EEP("External PD", modal_hdr->xpd);
10162306a36Sopenharmony_ci	PR_EEP("Chain0 I Coefficient", modal_hdr->iqCalICh[0]);
10262306a36Sopenharmony_ci	PR_EEP("Chain1 I Coefficient", modal_hdr->iqCalICh[1]);
10362306a36Sopenharmony_ci	PR_EEP("Chain0 Q Coefficient", modal_hdr->iqCalQCh[0]);
10462306a36Sopenharmony_ci	PR_EEP("Chain1 Q Coefficient", modal_hdr->iqCalQCh[1]);
10562306a36Sopenharmony_ci	PR_EEP("pdGainOverlap", modal_hdr->pdGainOverlap);
10662306a36Sopenharmony_ci	PR_EEP("xPA Bias Level", modal_hdr->xpaBiasLvl);
10762306a36Sopenharmony_ci	PR_EEP("txFrameToDataStart", modal_hdr->txFrameToDataStart);
10862306a36Sopenharmony_ci	PR_EEP("txFrameToPaOn", modal_hdr->txFrameToPaOn);
10962306a36Sopenharmony_ci	PR_EEP("HT40 Power Inc.", modal_hdr->ht40PowerIncForPdadc);
11062306a36Sopenharmony_ci	PR_EEP("Chain0 bswAtten", modal_hdr->bswAtten[0]);
11162306a36Sopenharmony_ci	PR_EEP("Chain1 bswAtten", modal_hdr->bswAtten[1]);
11262306a36Sopenharmony_ci	PR_EEP("Chain0 bswMargin", modal_hdr->bswMargin[0]);
11362306a36Sopenharmony_ci	PR_EEP("Chain1 bswMargin", modal_hdr->bswMargin[1]);
11462306a36Sopenharmony_ci	PR_EEP("HT40 Switch Settle", modal_hdr->swSettleHt40);
11562306a36Sopenharmony_ci	PR_EEP("AR92x7 Version", modal_hdr->version);
11662306a36Sopenharmony_ci	PR_EEP("DriverBias1", modal_hdr->db1);
11762306a36Sopenharmony_ci	PR_EEP("DriverBias2", modal_hdr->db1);
11862306a36Sopenharmony_ci	PR_EEP("CCK OutputBias", modal_hdr->ob_cck);
11962306a36Sopenharmony_ci	PR_EEP("PSK OutputBias", modal_hdr->ob_psk);
12062306a36Sopenharmony_ci	PR_EEP("QAM OutputBias", modal_hdr->ob_qam);
12162306a36Sopenharmony_ci	PR_EEP("PAL_OFF OutputBias", modal_hdr->ob_pal_off);
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ci	return len;
12462306a36Sopenharmony_ci}
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_cistatic u32 ath9k_hw_ar9287_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
12762306a36Sopenharmony_ci				       u8 *buf, u32 len, u32 size)
12862306a36Sopenharmony_ci{
12962306a36Sopenharmony_ci	struct ar9287_eeprom *eep = &ah->eeprom.map9287;
13062306a36Sopenharmony_ci	struct base_eep_ar9287_header *pBase = &eep->baseEepHeader;
13162306a36Sopenharmony_ci	u32 binBuildNumber = le32_to_cpu(pBase->binBuildNumber);
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci	if (!dump_base_hdr) {
13462306a36Sopenharmony_ci		len += scnprintf(buf + len, size - len,
13562306a36Sopenharmony_ci				 "%20s :\n", "2GHz modal Header");
13662306a36Sopenharmony_ci		len = ar9287_dump_modal_eeprom(buf, len, size,
13762306a36Sopenharmony_ci						&eep->modalHeader);
13862306a36Sopenharmony_ci		goto out;
13962306a36Sopenharmony_ci	}
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_ci	PR_EEP("Major Version", ath9k_hw_ar9287_get_eeprom_ver(ah));
14262306a36Sopenharmony_ci	PR_EEP("Minor Version", ath9k_hw_ar9287_get_eeprom_rev(ah));
14362306a36Sopenharmony_ci	PR_EEP("Checksum", le16_to_cpu(pBase->checksum));
14462306a36Sopenharmony_ci	PR_EEP("Length", le16_to_cpu(pBase->length));
14562306a36Sopenharmony_ci	PR_EEP("RegDomain1", le16_to_cpu(pBase->regDmn[0]));
14662306a36Sopenharmony_ci	PR_EEP("RegDomain2", le16_to_cpu(pBase->regDmn[1]));
14762306a36Sopenharmony_ci	PR_EEP("TX Mask", pBase->txMask);
14862306a36Sopenharmony_ci	PR_EEP("RX Mask", pBase->rxMask);
14962306a36Sopenharmony_ci	PR_EEP("Allow 5GHz", !!(pBase->opCapFlags & AR5416_OPFLAGS_11A));
15062306a36Sopenharmony_ci	PR_EEP("Allow 2GHz", !!(pBase->opCapFlags & AR5416_OPFLAGS_11G));
15162306a36Sopenharmony_ci	PR_EEP("Disable 2GHz HT20", !!(pBase->opCapFlags &
15262306a36Sopenharmony_ci					AR5416_OPFLAGS_N_2G_HT20));
15362306a36Sopenharmony_ci	PR_EEP("Disable 2GHz HT40", !!(pBase->opCapFlags &
15462306a36Sopenharmony_ci					AR5416_OPFLAGS_N_2G_HT40));
15562306a36Sopenharmony_ci	PR_EEP("Disable 5Ghz HT20", !!(pBase->opCapFlags &
15662306a36Sopenharmony_ci					AR5416_OPFLAGS_N_5G_HT20));
15762306a36Sopenharmony_ci	PR_EEP("Disable 5Ghz HT40", !!(pBase->opCapFlags &
15862306a36Sopenharmony_ci					AR5416_OPFLAGS_N_5G_HT40));
15962306a36Sopenharmony_ci	PR_EEP("Big Endian", !!(pBase->eepMisc & AR5416_EEPMISC_BIG_ENDIAN));
16062306a36Sopenharmony_ci	PR_EEP("Cal Bin Major Ver", (binBuildNumber >> 24) & 0xFF);
16162306a36Sopenharmony_ci	PR_EEP("Cal Bin Minor Ver", (binBuildNumber >> 16) & 0xFF);
16262306a36Sopenharmony_ci	PR_EEP("Cal Bin Build", (binBuildNumber >> 8) & 0xFF);
16362306a36Sopenharmony_ci	PR_EEP("Power Table Offset", pBase->pwrTableOffset);
16462306a36Sopenharmony_ci	PR_EEP("OpenLoop Power Ctrl", pBase->openLoopPwrCntl);
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_ci	len += scnprintf(buf + len, size - len, "%20s : %pM\n", "MacAddress",
16762306a36Sopenharmony_ci			 pBase->macAddr);
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_ciout:
17062306a36Sopenharmony_ci	if (len > size)
17162306a36Sopenharmony_ci		len = size;
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_ci	return len;
17462306a36Sopenharmony_ci}
17562306a36Sopenharmony_ci#else
17662306a36Sopenharmony_cistatic u32 ath9k_hw_ar9287_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
17762306a36Sopenharmony_ci				       u8 *buf, u32 len, u32 size)
17862306a36Sopenharmony_ci{
17962306a36Sopenharmony_ci	return 0;
18062306a36Sopenharmony_ci}
18162306a36Sopenharmony_ci#endif
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_cistatic int ath9k_hw_ar9287_check_eeprom(struct ath_hw *ah)
18562306a36Sopenharmony_ci{
18662306a36Sopenharmony_ci	u32 el;
18762306a36Sopenharmony_ci	int i, err;
18862306a36Sopenharmony_ci	bool need_swap;
18962306a36Sopenharmony_ci	struct ar9287_eeprom *eep = &ah->eeprom.map9287;
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ci	err = ath9k_hw_nvram_swap_data(ah, &need_swap, SIZE_EEPROM_AR9287);
19262306a36Sopenharmony_ci	if (err)
19362306a36Sopenharmony_ci		return err;
19462306a36Sopenharmony_ci
19562306a36Sopenharmony_ci	if (need_swap)
19662306a36Sopenharmony_ci		el = swab16((__force u16)eep->baseEepHeader.length);
19762306a36Sopenharmony_ci	else
19862306a36Sopenharmony_ci		el = le16_to_cpu(eep->baseEepHeader.length);
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ci	el = min(el / sizeof(u16), SIZE_EEPROM_AR9287);
20162306a36Sopenharmony_ci	if (!ath9k_hw_nvram_validate_checksum(ah, el))
20262306a36Sopenharmony_ci		return -EINVAL;
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_ci	if (need_swap) {
20562306a36Sopenharmony_ci		EEPROM_FIELD_SWAB16(eep->baseEepHeader.length);
20662306a36Sopenharmony_ci		EEPROM_FIELD_SWAB16(eep->baseEepHeader.checksum);
20762306a36Sopenharmony_ci		EEPROM_FIELD_SWAB16(eep->baseEepHeader.version);
20862306a36Sopenharmony_ci		EEPROM_FIELD_SWAB16(eep->baseEepHeader.regDmn[0]);
20962306a36Sopenharmony_ci		EEPROM_FIELD_SWAB16(eep->baseEepHeader.regDmn[1]);
21062306a36Sopenharmony_ci		EEPROM_FIELD_SWAB16(eep->baseEepHeader.rfSilent);
21162306a36Sopenharmony_ci		EEPROM_FIELD_SWAB16(eep->baseEepHeader.blueToothOptions);
21262306a36Sopenharmony_ci		EEPROM_FIELD_SWAB16(eep->baseEepHeader.deviceCap);
21362306a36Sopenharmony_ci		EEPROM_FIELD_SWAB32(eep->modalHeader.antCtrlCommon);
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_ci		for (i = 0; i < AR9287_MAX_CHAINS; i++)
21662306a36Sopenharmony_ci			EEPROM_FIELD_SWAB32(eep->modalHeader.antCtrlChain[i]);
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci		for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++)
21962306a36Sopenharmony_ci			EEPROM_FIELD_SWAB16(
22062306a36Sopenharmony_ci				eep->modalHeader.spurChans[i].spurChan);
22162306a36Sopenharmony_ci	}
22262306a36Sopenharmony_ci
22362306a36Sopenharmony_ci	if (!ath9k_hw_nvram_check_version(ah, AR9287_EEP_VER,
22462306a36Sopenharmony_ci	    AR5416_EEP_NO_BACK_VER))
22562306a36Sopenharmony_ci		return -EINVAL;
22662306a36Sopenharmony_ci
22762306a36Sopenharmony_ci	return 0;
22862306a36Sopenharmony_ci}
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_ci#undef SIZE_EEPROM_AR9287
23162306a36Sopenharmony_ci
23262306a36Sopenharmony_cistatic u32 ath9k_hw_ar9287_get_eeprom(struct ath_hw *ah,
23362306a36Sopenharmony_ci				      enum eeprom_param param)
23462306a36Sopenharmony_ci{
23562306a36Sopenharmony_ci	struct ar9287_eeprom *eep = &ah->eeprom.map9287;
23662306a36Sopenharmony_ci	struct modal_eep_ar9287_header *pModal = &eep->modalHeader;
23762306a36Sopenharmony_ci	struct base_eep_ar9287_header *pBase = &eep->baseEepHeader;
23862306a36Sopenharmony_ci	u16 ver_minor = ath9k_hw_ar9287_get_eeprom_rev(ah);
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_ci	switch (param) {
24162306a36Sopenharmony_ci	case EEP_NFTHRESH_2:
24262306a36Sopenharmony_ci		return pModal->noiseFloorThreshCh[0];
24362306a36Sopenharmony_ci	case EEP_MAC_LSW:
24462306a36Sopenharmony_ci		return get_unaligned_be16(pBase->macAddr);
24562306a36Sopenharmony_ci	case EEP_MAC_MID:
24662306a36Sopenharmony_ci		return get_unaligned_be16(pBase->macAddr + 2);
24762306a36Sopenharmony_ci	case EEP_MAC_MSW:
24862306a36Sopenharmony_ci		return get_unaligned_be16(pBase->macAddr + 4);
24962306a36Sopenharmony_ci	case EEP_REG_0:
25062306a36Sopenharmony_ci		return le16_to_cpu(pBase->regDmn[0]);
25162306a36Sopenharmony_ci	case EEP_OP_CAP:
25262306a36Sopenharmony_ci		return le16_to_cpu(pBase->deviceCap);
25362306a36Sopenharmony_ci	case EEP_OP_MODE:
25462306a36Sopenharmony_ci		return pBase->opCapFlags;
25562306a36Sopenharmony_ci	case EEP_RF_SILENT:
25662306a36Sopenharmony_ci		return le16_to_cpu(pBase->rfSilent);
25762306a36Sopenharmony_ci	case EEP_TX_MASK:
25862306a36Sopenharmony_ci		return pBase->txMask;
25962306a36Sopenharmony_ci	case EEP_RX_MASK:
26062306a36Sopenharmony_ci		return pBase->rxMask;
26162306a36Sopenharmony_ci	case EEP_DEV_TYPE:
26262306a36Sopenharmony_ci		return pBase->deviceType;
26362306a36Sopenharmony_ci	case EEP_OL_PWRCTRL:
26462306a36Sopenharmony_ci		return pBase->openLoopPwrCntl;
26562306a36Sopenharmony_ci	case EEP_TEMPSENSE_SLOPE:
26662306a36Sopenharmony_ci		if (ver_minor >= AR9287_EEP_MINOR_VER_2)
26762306a36Sopenharmony_ci			return pBase->tempSensSlope;
26862306a36Sopenharmony_ci		else
26962306a36Sopenharmony_ci			return 0;
27062306a36Sopenharmony_ci	case EEP_TEMPSENSE_SLOPE_PAL_ON:
27162306a36Sopenharmony_ci		if (ver_minor >= AR9287_EEP_MINOR_VER_3)
27262306a36Sopenharmony_ci			return pBase->tempSensSlopePalOn;
27362306a36Sopenharmony_ci		else
27462306a36Sopenharmony_ci			return 0;
27562306a36Sopenharmony_ci	case EEP_ANTENNA_GAIN_2G:
27662306a36Sopenharmony_ci		return max_t(u8, pModal->antennaGainCh[0],
27762306a36Sopenharmony_ci				 pModal->antennaGainCh[1]);
27862306a36Sopenharmony_ci	default:
27962306a36Sopenharmony_ci		return 0;
28062306a36Sopenharmony_ci	}
28162306a36Sopenharmony_ci}
28262306a36Sopenharmony_ci
28362306a36Sopenharmony_cistatic void ar9287_eeprom_get_tx_gain_index(struct ath_hw *ah,
28462306a36Sopenharmony_ci			    struct ath9k_channel *chan,
28562306a36Sopenharmony_ci			    struct cal_data_op_loop_ar9287 *pRawDatasetOpLoop,
28662306a36Sopenharmony_ci			    u8 *pCalChans,  u16 availPiers, int8_t *pPwr)
28762306a36Sopenharmony_ci{
28862306a36Sopenharmony_ci	u16 idxL = 0, idxR = 0, numPiers;
28962306a36Sopenharmony_ci	bool match;
29062306a36Sopenharmony_ci	struct chan_centers centers;
29162306a36Sopenharmony_ci
29262306a36Sopenharmony_ci	ath9k_hw_get_channel_centers(ah, chan, &centers);
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_ci	for (numPiers = 0; numPiers < availPiers; numPiers++) {
29562306a36Sopenharmony_ci		if (pCalChans[numPiers] == AR5416_BCHAN_UNUSED)
29662306a36Sopenharmony_ci			break;
29762306a36Sopenharmony_ci	}
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_ci	match = ath9k_hw_get_lower_upper_index(
30062306a36Sopenharmony_ci		(u8)FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan)),
30162306a36Sopenharmony_ci		pCalChans, numPiers, &idxL, &idxR);
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_ci	if (match) {
30462306a36Sopenharmony_ci		*pPwr = (int8_t) pRawDatasetOpLoop[idxL].pwrPdg[0][0];
30562306a36Sopenharmony_ci	} else {
30662306a36Sopenharmony_ci		*pPwr = ((int8_t) pRawDatasetOpLoop[idxL].pwrPdg[0][0] +
30762306a36Sopenharmony_ci			 (int8_t) pRawDatasetOpLoop[idxR].pwrPdg[0][0])/2;
30862306a36Sopenharmony_ci	}
30962306a36Sopenharmony_ci
31062306a36Sopenharmony_ci}
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_cistatic void ar9287_eeprom_olpc_set_pdadcs(struct ath_hw *ah,
31362306a36Sopenharmony_ci					  int32_t txPower, u16 chain)
31462306a36Sopenharmony_ci{
31562306a36Sopenharmony_ci	u32 tmpVal;
31662306a36Sopenharmony_ci	u32 a;
31762306a36Sopenharmony_ci
31862306a36Sopenharmony_ci	/* Enable OLPC for chain 0 */
31962306a36Sopenharmony_ci
32062306a36Sopenharmony_ci	tmpVal = REG_READ(ah, 0xa270);
32162306a36Sopenharmony_ci	tmpVal = tmpVal & 0xFCFFFFFF;
32262306a36Sopenharmony_ci	tmpVal = tmpVal | (0x3 << 24);
32362306a36Sopenharmony_ci	REG_WRITE(ah, 0xa270, tmpVal);
32462306a36Sopenharmony_ci
32562306a36Sopenharmony_ci	/* Enable OLPC for chain 1 */
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_ci	tmpVal = REG_READ(ah, 0xb270);
32862306a36Sopenharmony_ci	tmpVal = tmpVal & 0xFCFFFFFF;
32962306a36Sopenharmony_ci	tmpVal = tmpVal | (0x3 << 24);
33062306a36Sopenharmony_ci	REG_WRITE(ah, 0xb270, tmpVal);
33162306a36Sopenharmony_ci
33262306a36Sopenharmony_ci	/* Write the OLPC ref power for chain 0 */
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_ci	if (chain == 0) {
33562306a36Sopenharmony_ci		tmpVal = REG_READ(ah, 0xa398);
33662306a36Sopenharmony_ci		tmpVal = tmpVal & 0xff00ffff;
33762306a36Sopenharmony_ci		a = (txPower)&0xff;
33862306a36Sopenharmony_ci		tmpVal = tmpVal | (a << 16);
33962306a36Sopenharmony_ci		REG_WRITE(ah, 0xa398, tmpVal);
34062306a36Sopenharmony_ci	}
34162306a36Sopenharmony_ci
34262306a36Sopenharmony_ci	/* Write the OLPC ref power for chain 1 */
34362306a36Sopenharmony_ci
34462306a36Sopenharmony_ci	if (chain == 1) {
34562306a36Sopenharmony_ci		tmpVal = REG_READ(ah, 0xb398);
34662306a36Sopenharmony_ci		tmpVal = tmpVal & 0xff00ffff;
34762306a36Sopenharmony_ci		a = (txPower)&0xff;
34862306a36Sopenharmony_ci		tmpVal = tmpVal | (a << 16);
34962306a36Sopenharmony_ci		REG_WRITE(ah, 0xb398, tmpVal);
35062306a36Sopenharmony_ci	}
35162306a36Sopenharmony_ci}
35262306a36Sopenharmony_ci
35362306a36Sopenharmony_cistatic void ath9k_hw_set_ar9287_power_cal_table(struct ath_hw *ah,
35462306a36Sopenharmony_ci						struct ath9k_channel *chan)
35562306a36Sopenharmony_ci{
35662306a36Sopenharmony_ci	struct cal_data_per_freq_ar9287 *pRawDataset;
35762306a36Sopenharmony_ci	struct cal_data_op_loop_ar9287 *pRawDatasetOpenLoop;
35862306a36Sopenharmony_ci	u8 *pCalBChans = NULL;
35962306a36Sopenharmony_ci	u16 pdGainOverlap_t2;
36062306a36Sopenharmony_ci	u8 pdadcValues[AR5416_NUM_PDADC_VALUES];
36162306a36Sopenharmony_ci	u16 gainBoundaries[AR5416_PD_GAINS_IN_MASK];
36262306a36Sopenharmony_ci	u16 numPiers = 0, i, j;
36362306a36Sopenharmony_ci	u16 numXpdGain, xpdMask;
36462306a36Sopenharmony_ci	u16 xpdGainValues[AR5416_NUM_PD_GAINS] = {0, 0, 0, 0};
36562306a36Sopenharmony_ci	u32 reg32, regOffset, regChainOffset, regval;
36662306a36Sopenharmony_ci	int16_t diff = 0;
36762306a36Sopenharmony_ci	struct ar9287_eeprom *pEepData = &ah->eeprom.map9287;
36862306a36Sopenharmony_ci
36962306a36Sopenharmony_ci	xpdMask = pEepData->modalHeader.xpdGain;
37062306a36Sopenharmony_ci
37162306a36Sopenharmony_ci	if (ath9k_hw_ar9287_get_eeprom_rev(ah) >= AR9287_EEP_MINOR_VER_2)
37262306a36Sopenharmony_ci		pdGainOverlap_t2 = pEepData->modalHeader.pdGainOverlap;
37362306a36Sopenharmony_ci	else
37462306a36Sopenharmony_ci		pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5),
37562306a36Sopenharmony_ci					    AR_PHY_TPCRG5_PD_GAIN_OVERLAP));
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_ci	if (IS_CHAN_2GHZ(chan)) {
37862306a36Sopenharmony_ci		pCalBChans = pEepData->calFreqPier2G;
37962306a36Sopenharmony_ci		numPiers = AR9287_NUM_2G_CAL_PIERS;
38062306a36Sopenharmony_ci		if (ath9k_hw_ar9287_get_eeprom(ah, EEP_OL_PWRCTRL)) {
38162306a36Sopenharmony_ci			pRawDatasetOpenLoop =
38262306a36Sopenharmony_ci			(struct cal_data_op_loop_ar9287 *)pEepData->calPierData2G[0];
38362306a36Sopenharmony_ci			ah->initPDADC = pRawDatasetOpenLoop->vpdPdg[0][0];
38462306a36Sopenharmony_ci		}
38562306a36Sopenharmony_ci	}
38662306a36Sopenharmony_ci
38762306a36Sopenharmony_ci	numXpdGain = 0;
38862306a36Sopenharmony_ci
38962306a36Sopenharmony_ci	/* Calculate the value of xpdgains from the xpdGain Mask */
39062306a36Sopenharmony_ci	for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) {
39162306a36Sopenharmony_ci		if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) {
39262306a36Sopenharmony_ci			if (numXpdGain >= AR5416_NUM_PD_GAINS)
39362306a36Sopenharmony_ci				break;
39462306a36Sopenharmony_ci			xpdGainValues[numXpdGain] =
39562306a36Sopenharmony_ci				(u16)(AR5416_PD_GAINS_IN_MASK-i);
39662306a36Sopenharmony_ci			numXpdGain++;
39762306a36Sopenharmony_ci		}
39862306a36Sopenharmony_ci	}
39962306a36Sopenharmony_ci
40062306a36Sopenharmony_ci	REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN,
40162306a36Sopenharmony_ci		      (numXpdGain - 1) & 0x3);
40262306a36Sopenharmony_ci	REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1,
40362306a36Sopenharmony_ci		      xpdGainValues[0]);
40462306a36Sopenharmony_ci	REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2,
40562306a36Sopenharmony_ci		      xpdGainValues[1]);
40662306a36Sopenharmony_ci	REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3,
40762306a36Sopenharmony_ci		      xpdGainValues[2]);
40862306a36Sopenharmony_ci
40962306a36Sopenharmony_ci	for (i = 0; i < AR9287_MAX_CHAINS; i++)	{
41062306a36Sopenharmony_ci		regChainOffset = i * 0x1000;
41162306a36Sopenharmony_ci
41262306a36Sopenharmony_ci		if (pEepData->baseEepHeader.txMask & (1 << i)) {
41362306a36Sopenharmony_ci			pRawDatasetOpenLoop =
41462306a36Sopenharmony_ci			(struct cal_data_op_loop_ar9287 *)pEepData->calPierData2G[i];
41562306a36Sopenharmony_ci
41662306a36Sopenharmony_ci			if (ath9k_hw_ar9287_get_eeprom(ah, EEP_OL_PWRCTRL)) {
41762306a36Sopenharmony_ci				int8_t txPower;
41862306a36Sopenharmony_ci				ar9287_eeprom_get_tx_gain_index(ah, chan,
41962306a36Sopenharmony_ci							pRawDatasetOpenLoop,
42062306a36Sopenharmony_ci							pCalBChans, numPiers,
42162306a36Sopenharmony_ci							&txPower);
42262306a36Sopenharmony_ci				ar9287_eeprom_olpc_set_pdadcs(ah, txPower, i);
42362306a36Sopenharmony_ci			} else {
42462306a36Sopenharmony_ci				pRawDataset =
42562306a36Sopenharmony_ci					(struct cal_data_per_freq_ar9287 *)
42662306a36Sopenharmony_ci					pEepData->calPierData2G[i];
42762306a36Sopenharmony_ci
42862306a36Sopenharmony_ci				ath9k_hw_get_gain_boundaries_pdadcs(ah, chan,
42962306a36Sopenharmony_ci							   pRawDataset,
43062306a36Sopenharmony_ci							   pCalBChans, numPiers,
43162306a36Sopenharmony_ci							   pdGainOverlap_t2,
43262306a36Sopenharmony_ci							   gainBoundaries,
43362306a36Sopenharmony_ci							   pdadcValues,
43462306a36Sopenharmony_ci							   numXpdGain);
43562306a36Sopenharmony_ci			}
43662306a36Sopenharmony_ci
43762306a36Sopenharmony_ci			ENABLE_REGWRITE_BUFFER(ah);
43862306a36Sopenharmony_ci
43962306a36Sopenharmony_ci			if (i == 0) {
44062306a36Sopenharmony_ci				if (!ath9k_hw_ar9287_get_eeprom(ah,
44162306a36Sopenharmony_ci							EEP_OL_PWRCTRL)) {
44262306a36Sopenharmony_ci
44362306a36Sopenharmony_ci					regval = SM(pdGainOverlap_t2,
44462306a36Sopenharmony_ci						    AR_PHY_TPCRG5_PD_GAIN_OVERLAP)
44562306a36Sopenharmony_ci						| SM(gainBoundaries[0],
44662306a36Sopenharmony_ci						     AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1)
44762306a36Sopenharmony_ci						| SM(gainBoundaries[1],
44862306a36Sopenharmony_ci						     AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2)
44962306a36Sopenharmony_ci						| SM(gainBoundaries[2],
45062306a36Sopenharmony_ci						     AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3)
45162306a36Sopenharmony_ci						| SM(gainBoundaries[3],
45262306a36Sopenharmony_ci						     AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4);
45362306a36Sopenharmony_ci
45462306a36Sopenharmony_ci					REG_WRITE(ah,
45562306a36Sopenharmony_ci						  AR_PHY_TPCRG5 + regChainOffset,
45662306a36Sopenharmony_ci						  regval);
45762306a36Sopenharmony_ci				}
45862306a36Sopenharmony_ci			}
45962306a36Sopenharmony_ci
46062306a36Sopenharmony_ci			if ((int32_t)AR9287_PWR_TABLE_OFFSET_DB !=
46162306a36Sopenharmony_ci			    pEepData->baseEepHeader.pwrTableOffset) {
46262306a36Sopenharmony_ci				diff = (u16)(pEepData->baseEepHeader.pwrTableOffset -
46362306a36Sopenharmony_ci					     (int32_t)AR9287_PWR_TABLE_OFFSET_DB);
46462306a36Sopenharmony_ci				diff *= 2;
46562306a36Sopenharmony_ci
46662306a36Sopenharmony_ci				for (j = 0; j < ((u16)AR5416_NUM_PDADC_VALUES-diff); j++)
46762306a36Sopenharmony_ci					pdadcValues[j] = pdadcValues[j+diff];
46862306a36Sopenharmony_ci
46962306a36Sopenharmony_ci				for (j = (u16)(AR5416_NUM_PDADC_VALUES-diff);
47062306a36Sopenharmony_ci				     j < AR5416_NUM_PDADC_VALUES; j++)
47162306a36Sopenharmony_ci					pdadcValues[j] =
47262306a36Sopenharmony_ci					  pdadcValues[AR5416_NUM_PDADC_VALUES-diff];
47362306a36Sopenharmony_ci			}
47462306a36Sopenharmony_ci
47562306a36Sopenharmony_ci			if (!ath9k_hw_ar9287_get_eeprom(ah, EEP_OL_PWRCTRL)) {
47662306a36Sopenharmony_ci				regOffset = AR_PHY_BASE +
47762306a36Sopenharmony_ci					(672 << 2) + regChainOffset;
47862306a36Sopenharmony_ci
47962306a36Sopenharmony_ci				for (j = 0; j < 32; j++) {
48062306a36Sopenharmony_ci					reg32 = get_unaligned_le32(&pdadcValues[4 * j]);
48162306a36Sopenharmony_ci
48262306a36Sopenharmony_ci					REG_WRITE(ah, regOffset, reg32);
48362306a36Sopenharmony_ci					regOffset += 4;
48462306a36Sopenharmony_ci				}
48562306a36Sopenharmony_ci			}
48662306a36Sopenharmony_ci			REGWRITE_BUFFER_FLUSH(ah);
48762306a36Sopenharmony_ci		}
48862306a36Sopenharmony_ci	}
48962306a36Sopenharmony_ci}
49062306a36Sopenharmony_ci
49162306a36Sopenharmony_cistatic void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah,
49262306a36Sopenharmony_ci						     struct ath9k_channel *chan,
49362306a36Sopenharmony_ci						     int16_t *ratesArray,
49462306a36Sopenharmony_ci						     u16 cfgCtl,
49562306a36Sopenharmony_ci						     u16 antenna_reduction,
49662306a36Sopenharmony_ci						     u16 powerLimit)
49762306a36Sopenharmony_ci{
49862306a36Sopenharmony_ci#define CMP_CTL \
49962306a36Sopenharmony_ci	(((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == \
50062306a36Sopenharmony_ci	 pEepData->ctlIndex[i])
50162306a36Sopenharmony_ci
50262306a36Sopenharmony_ci#define CMP_NO_CTL \
50362306a36Sopenharmony_ci	(((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == \
50462306a36Sopenharmony_ci	 ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL))
50562306a36Sopenharmony_ci
50662306a36Sopenharmony_ci	u16 twiceMaxEdgePower;
50762306a36Sopenharmony_ci	int i;
50862306a36Sopenharmony_ci	struct cal_ctl_data_ar9287 *rep;
50962306a36Sopenharmony_ci	struct cal_target_power_leg targetPowerOfdm = {0, {0, 0, 0, 0} },
51062306a36Sopenharmony_ci				    targetPowerCck = {0, {0, 0, 0, 0} };
51162306a36Sopenharmony_ci	struct cal_target_power_leg targetPowerOfdmExt = {0, {0, 0, 0, 0} },
51262306a36Sopenharmony_ci				    targetPowerCckExt = {0, {0, 0, 0, 0} };
51362306a36Sopenharmony_ci	struct cal_target_power_ht targetPowerHt20,
51462306a36Sopenharmony_ci				    targetPowerHt40 = {0, {0, 0, 0, 0} };
51562306a36Sopenharmony_ci	u16 scaledPower = 0, minCtlPower;
51662306a36Sopenharmony_ci	static const u16 ctlModesFor11g[] = {
51762306a36Sopenharmony_ci		CTL_11B, CTL_11G, CTL_2GHT20,
51862306a36Sopenharmony_ci		CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40
51962306a36Sopenharmony_ci	};
52062306a36Sopenharmony_ci	u16 numCtlModes = 0;
52162306a36Sopenharmony_ci	const u16 *pCtlMode = NULL;
52262306a36Sopenharmony_ci	u16 ctlMode, freq;
52362306a36Sopenharmony_ci	struct chan_centers centers;
52462306a36Sopenharmony_ci	int tx_chainmask;
52562306a36Sopenharmony_ci	u16 twiceMinEdgePower;
52662306a36Sopenharmony_ci	struct ar9287_eeprom *pEepData = &ah->eeprom.map9287;
52762306a36Sopenharmony_ci	tx_chainmask = ah->txchainmask;
52862306a36Sopenharmony_ci
52962306a36Sopenharmony_ci	ath9k_hw_get_channel_centers(ah, chan, &centers);
53062306a36Sopenharmony_ci	scaledPower = ath9k_hw_get_scaled_power(ah, powerLimit,
53162306a36Sopenharmony_ci						antenna_reduction);
53262306a36Sopenharmony_ci
53362306a36Sopenharmony_ci	/*
53462306a36Sopenharmony_ci	 * Get TX power from EEPROM.
53562306a36Sopenharmony_ci	 */
53662306a36Sopenharmony_ci	if (IS_CHAN_2GHZ(chan))	{
53762306a36Sopenharmony_ci		/* CTL_11B, CTL_11G, CTL_2GHT20 */
53862306a36Sopenharmony_ci		numCtlModes =
53962306a36Sopenharmony_ci			ARRAY_SIZE(ctlModesFor11g) - SUB_NUM_CTL_MODES_AT_2G_40;
54062306a36Sopenharmony_ci
54162306a36Sopenharmony_ci		pCtlMode = ctlModesFor11g;
54262306a36Sopenharmony_ci
54362306a36Sopenharmony_ci		ath9k_hw_get_legacy_target_powers(ah, chan,
54462306a36Sopenharmony_ci						  pEepData->calTargetPowerCck,
54562306a36Sopenharmony_ci						  AR9287_NUM_2G_CCK_TARGET_POWERS,
54662306a36Sopenharmony_ci						  &targetPowerCck, 4, false);
54762306a36Sopenharmony_ci		ath9k_hw_get_legacy_target_powers(ah, chan,
54862306a36Sopenharmony_ci						  pEepData->calTargetPower2G,
54962306a36Sopenharmony_ci						  AR9287_NUM_2G_20_TARGET_POWERS,
55062306a36Sopenharmony_ci						  &targetPowerOfdm, 4, false);
55162306a36Sopenharmony_ci		ath9k_hw_get_target_powers(ah, chan,
55262306a36Sopenharmony_ci					   pEepData->calTargetPower2GHT20,
55362306a36Sopenharmony_ci					   AR9287_NUM_2G_20_TARGET_POWERS,
55462306a36Sopenharmony_ci					   &targetPowerHt20, 8, false);
55562306a36Sopenharmony_ci
55662306a36Sopenharmony_ci		if (IS_CHAN_HT40(chan))	{
55762306a36Sopenharmony_ci			/* All 2G CTLs */
55862306a36Sopenharmony_ci			numCtlModes = ARRAY_SIZE(ctlModesFor11g);
55962306a36Sopenharmony_ci			ath9k_hw_get_target_powers(ah, chan,
56062306a36Sopenharmony_ci						   pEepData->calTargetPower2GHT40,
56162306a36Sopenharmony_ci						   AR9287_NUM_2G_40_TARGET_POWERS,
56262306a36Sopenharmony_ci						   &targetPowerHt40, 8, true);
56362306a36Sopenharmony_ci			ath9k_hw_get_legacy_target_powers(ah, chan,
56462306a36Sopenharmony_ci						  pEepData->calTargetPowerCck,
56562306a36Sopenharmony_ci						  AR9287_NUM_2G_CCK_TARGET_POWERS,
56662306a36Sopenharmony_ci						  &targetPowerCckExt, 4, true);
56762306a36Sopenharmony_ci			ath9k_hw_get_legacy_target_powers(ah, chan,
56862306a36Sopenharmony_ci						  pEepData->calTargetPower2G,
56962306a36Sopenharmony_ci						  AR9287_NUM_2G_20_TARGET_POWERS,
57062306a36Sopenharmony_ci						  &targetPowerOfdmExt, 4, true);
57162306a36Sopenharmony_ci		}
57262306a36Sopenharmony_ci	}
57362306a36Sopenharmony_ci
57462306a36Sopenharmony_ci	for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) {
57562306a36Sopenharmony_ci		bool isHt40CtlMode = pCtlMode[ctlMode] == CTL_2GHT40;
57662306a36Sopenharmony_ci
57762306a36Sopenharmony_ci		if (isHt40CtlMode)
57862306a36Sopenharmony_ci			freq = centers.synth_center;
57962306a36Sopenharmony_ci		else if (pCtlMode[ctlMode] & EXT_ADDITIVE)
58062306a36Sopenharmony_ci			freq = centers.ext_center;
58162306a36Sopenharmony_ci		else
58262306a36Sopenharmony_ci			freq = centers.ctl_center;
58362306a36Sopenharmony_ci
58462306a36Sopenharmony_ci		twiceMaxEdgePower = MAX_RATE_POWER;
58562306a36Sopenharmony_ci		/* Walk through the CTL indices stored in EEPROM */
58662306a36Sopenharmony_ci		for (i = 0; (i < AR9287_NUM_CTLS) && pEepData->ctlIndex[i]; i++) {
58762306a36Sopenharmony_ci			struct cal_ctl_edges *pRdEdgesPower;
58862306a36Sopenharmony_ci
58962306a36Sopenharmony_ci			/*
59062306a36Sopenharmony_ci			 * Compare test group from regulatory channel list
59162306a36Sopenharmony_ci			 * with test mode from pCtlMode list
59262306a36Sopenharmony_ci			 */
59362306a36Sopenharmony_ci			if (CMP_CTL || CMP_NO_CTL) {
59462306a36Sopenharmony_ci				rep = &(pEepData->ctlData[i]);
59562306a36Sopenharmony_ci				pRdEdgesPower =
59662306a36Sopenharmony_ci				rep->ctlEdges[ar5416_get_ntxchains(tx_chainmask) - 1];
59762306a36Sopenharmony_ci
59862306a36Sopenharmony_ci				twiceMinEdgePower = ath9k_hw_get_max_edge_power(freq,
59962306a36Sopenharmony_ci								pRdEdgesPower,
60062306a36Sopenharmony_ci								IS_CHAN_2GHZ(chan),
60162306a36Sopenharmony_ci								AR5416_NUM_BAND_EDGES);
60262306a36Sopenharmony_ci
60362306a36Sopenharmony_ci				if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) {
60462306a36Sopenharmony_ci					twiceMaxEdgePower = min(twiceMaxEdgePower,
60562306a36Sopenharmony_ci								twiceMinEdgePower);
60662306a36Sopenharmony_ci				} else {
60762306a36Sopenharmony_ci					twiceMaxEdgePower = twiceMinEdgePower;
60862306a36Sopenharmony_ci					break;
60962306a36Sopenharmony_ci				}
61062306a36Sopenharmony_ci			}
61162306a36Sopenharmony_ci		}
61262306a36Sopenharmony_ci
61362306a36Sopenharmony_ci		minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower);
61462306a36Sopenharmony_ci
61562306a36Sopenharmony_ci		/* Apply ctl mode to correct target power set */
61662306a36Sopenharmony_ci		switch (pCtlMode[ctlMode]) {
61762306a36Sopenharmony_ci		case CTL_11B:
61862306a36Sopenharmony_ci			for (i = 0; i < ARRAY_SIZE(targetPowerCck.tPow2x); i++) {
61962306a36Sopenharmony_ci				targetPowerCck.tPow2x[i] =
62062306a36Sopenharmony_ci					(u8)min((u16)targetPowerCck.tPow2x[i],
62162306a36Sopenharmony_ci						minCtlPower);
62262306a36Sopenharmony_ci			}
62362306a36Sopenharmony_ci			break;
62462306a36Sopenharmony_ci		case CTL_11A:
62562306a36Sopenharmony_ci		case CTL_11G:
62662306a36Sopenharmony_ci			for (i = 0; i < ARRAY_SIZE(targetPowerOfdm.tPow2x); i++) {
62762306a36Sopenharmony_ci				targetPowerOfdm.tPow2x[i] =
62862306a36Sopenharmony_ci					(u8)min((u16)targetPowerOfdm.tPow2x[i],
62962306a36Sopenharmony_ci						minCtlPower);
63062306a36Sopenharmony_ci			}
63162306a36Sopenharmony_ci			break;
63262306a36Sopenharmony_ci		case CTL_5GHT20:
63362306a36Sopenharmony_ci		case CTL_2GHT20:
63462306a36Sopenharmony_ci			for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++) {
63562306a36Sopenharmony_ci				targetPowerHt20.tPow2x[i] =
63662306a36Sopenharmony_ci					(u8)min((u16)targetPowerHt20.tPow2x[i],
63762306a36Sopenharmony_ci						minCtlPower);
63862306a36Sopenharmony_ci			}
63962306a36Sopenharmony_ci			break;
64062306a36Sopenharmony_ci		case CTL_11B_EXT:
64162306a36Sopenharmony_ci			targetPowerCckExt.tPow2x[0] =
64262306a36Sopenharmony_ci				(u8)min((u16)targetPowerCckExt.tPow2x[0],
64362306a36Sopenharmony_ci					minCtlPower);
64462306a36Sopenharmony_ci			break;
64562306a36Sopenharmony_ci		case CTL_11A_EXT:
64662306a36Sopenharmony_ci		case CTL_11G_EXT:
64762306a36Sopenharmony_ci			targetPowerOfdmExt.tPow2x[0] =
64862306a36Sopenharmony_ci				(u8)min((u16)targetPowerOfdmExt.tPow2x[0],
64962306a36Sopenharmony_ci					minCtlPower);
65062306a36Sopenharmony_ci			break;
65162306a36Sopenharmony_ci		case CTL_5GHT40:
65262306a36Sopenharmony_ci		case CTL_2GHT40:
65362306a36Sopenharmony_ci			for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {
65462306a36Sopenharmony_ci				targetPowerHt40.tPow2x[i] =
65562306a36Sopenharmony_ci					(u8)min((u16)targetPowerHt40.tPow2x[i],
65662306a36Sopenharmony_ci						minCtlPower);
65762306a36Sopenharmony_ci			}
65862306a36Sopenharmony_ci			break;
65962306a36Sopenharmony_ci		default:
66062306a36Sopenharmony_ci			break;
66162306a36Sopenharmony_ci		}
66262306a36Sopenharmony_ci	}
66362306a36Sopenharmony_ci
66462306a36Sopenharmony_ci	/* Now set the rates array */
66562306a36Sopenharmony_ci
66662306a36Sopenharmony_ci	ratesArray[rate6mb] =
66762306a36Sopenharmony_ci	ratesArray[rate9mb] =
66862306a36Sopenharmony_ci	ratesArray[rate12mb] =
66962306a36Sopenharmony_ci	ratesArray[rate18mb] =
67062306a36Sopenharmony_ci	ratesArray[rate24mb] = targetPowerOfdm.tPow2x[0];
67162306a36Sopenharmony_ci
67262306a36Sopenharmony_ci	ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1];
67362306a36Sopenharmony_ci	ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2];
67462306a36Sopenharmony_ci	ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3];
67562306a36Sopenharmony_ci	ratesArray[rateXr] = targetPowerOfdm.tPow2x[0];
67662306a36Sopenharmony_ci
67762306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++)
67862306a36Sopenharmony_ci		ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i];
67962306a36Sopenharmony_ci
68062306a36Sopenharmony_ci	if (IS_CHAN_2GHZ(chan))	{
68162306a36Sopenharmony_ci		ratesArray[rate1l] = targetPowerCck.tPow2x[0];
68262306a36Sopenharmony_ci		ratesArray[rate2s] =
68362306a36Sopenharmony_ci		ratesArray[rate2l] = targetPowerCck.tPow2x[1];
68462306a36Sopenharmony_ci		ratesArray[rate5_5s] =
68562306a36Sopenharmony_ci		ratesArray[rate5_5l] = targetPowerCck.tPow2x[2];
68662306a36Sopenharmony_ci		ratesArray[rate11s] =
68762306a36Sopenharmony_ci		ratesArray[rate11l] = targetPowerCck.tPow2x[3];
68862306a36Sopenharmony_ci	}
68962306a36Sopenharmony_ci	if (IS_CHAN_HT40(chan))	{
69062306a36Sopenharmony_ci		for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++)
69162306a36Sopenharmony_ci			ratesArray[rateHt40_0 + i] = targetPowerHt40.tPow2x[i];
69262306a36Sopenharmony_ci
69362306a36Sopenharmony_ci		ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0];
69462306a36Sopenharmony_ci		ratesArray[rateDupCck]  = targetPowerHt40.tPow2x[0];
69562306a36Sopenharmony_ci		ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0];
69662306a36Sopenharmony_ci
69762306a36Sopenharmony_ci		if (IS_CHAN_2GHZ(chan))
69862306a36Sopenharmony_ci			ratesArray[rateExtCck] = targetPowerCckExt.tPow2x[0];
69962306a36Sopenharmony_ci	}
70062306a36Sopenharmony_ci
70162306a36Sopenharmony_ci#undef CMP_CTL
70262306a36Sopenharmony_ci#undef CMP_NO_CTL
70362306a36Sopenharmony_ci}
70462306a36Sopenharmony_ci
70562306a36Sopenharmony_cistatic void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah,
70662306a36Sopenharmony_ci					struct ath9k_channel *chan, u16 cfgCtl,
70762306a36Sopenharmony_ci					u8 twiceAntennaReduction,
70862306a36Sopenharmony_ci					u8 powerLimit, bool test)
70962306a36Sopenharmony_ci{
71062306a36Sopenharmony_ci	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
71162306a36Sopenharmony_ci	struct ar9287_eeprom *pEepData = &ah->eeprom.map9287;
71262306a36Sopenharmony_ci	struct modal_eep_ar9287_header *pModal = &pEepData->modalHeader;
71362306a36Sopenharmony_ci	int16_t ratesArray[Ar5416RateSize];
71462306a36Sopenharmony_ci	u8 ht40PowerIncForPdadc = 2;
71562306a36Sopenharmony_ci	int i;
71662306a36Sopenharmony_ci
71762306a36Sopenharmony_ci	memset(ratesArray, 0, sizeof(ratesArray));
71862306a36Sopenharmony_ci
71962306a36Sopenharmony_ci	if (ath9k_hw_ar9287_get_eeprom_rev(ah) >= AR9287_EEP_MINOR_VER_2)
72062306a36Sopenharmony_ci		ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
72162306a36Sopenharmony_ci
72262306a36Sopenharmony_ci	ath9k_hw_set_ar9287_power_per_rate_table(ah, chan,
72362306a36Sopenharmony_ci						 &ratesArray[0], cfgCtl,
72462306a36Sopenharmony_ci						 twiceAntennaReduction,
72562306a36Sopenharmony_ci						 powerLimit);
72662306a36Sopenharmony_ci
72762306a36Sopenharmony_ci	ath9k_hw_set_ar9287_power_cal_table(ah, chan);
72862306a36Sopenharmony_ci
72962306a36Sopenharmony_ci	regulatory->max_power_level = 0;
73062306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
73162306a36Sopenharmony_ci		if (ratesArray[i] > MAX_RATE_POWER)
73262306a36Sopenharmony_ci			ratesArray[i] = MAX_RATE_POWER;
73362306a36Sopenharmony_ci
73462306a36Sopenharmony_ci		if (ratesArray[i] > regulatory->max_power_level)
73562306a36Sopenharmony_ci			regulatory->max_power_level = ratesArray[i];
73662306a36Sopenharmony_ci	}
73762306a36Sopenharmony_ci
73862306a36Sopenharmony_ci	ath9k_hw_update_regulatory_maxpower(ah);
73962306a36Sopenharmony_ci
74062306a36Sopenharmony_ci	if (test)
74162306a36Sopenharmony_ci		return;
74262306a36Sopenharmony_ci
74362306a36Sopenharmony_ci	for (i = 0; i < Ar5416RateSize; i++)
74462306a36Sopenharmony_ci		ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2;
74562306a36Sopenharmony_ci
74662306a36Sopenharmony_ci	ENABLE_REGWRITE_BUFFER(ah);
74762306a36Sopenharmony_ci
74862306a36Sopenharmony_ci	/* OFDM power per rate */
74962306a36Sopenharmony_ci	REG_WRITE(ah, AR_PHY_POWER_TX_RATE1,
75062306a36Sopenharmony_ci		  ATH9K_POW_SM(ratesArray[rate18mb], 24)
75162306a36Sopenharmony_ci		  | ATH9K_POW_SM(ratesArray[rate12mb], 16)
75262306a36Sopenharmony_ci		  | ATH9K_POW_SM(ratesArray[rate9mb], 8)
75362306a36Sopenharmony_ci		  | ATH9K_POW_SM(ratesArray[rate6mb], 0));
75462306a36Sopenharmony_ci
75562306a36Sopenharmony_ci	REG_WRITE(ah, AR_PHY_POWER_TX_RATE2,
75662306a36Sopenharmony_ci		  ATH9K_POW_SM(ratesArray[rate54mb], 24)
75762306a36Sopenharmony_ci		  | ATH9K_POW_SM(ratesArray[rate48mb], 16)
75862306a36Sopenharmony_ci		  | ATH9K_POW_SM(ratesArray[rate36mb], 8)
75962306a36Sopenharmony_ci		  | ATH9K_POW_SM(ratesArray[rate24mb], 0));
76062306a36Sopenharmony_ci
76162306a36Sopenharmony_ci	/* CCK power per rate */
76262306a36Sopenharmony_ci	if (IS_CHAN_2GHZ(chan))	{
76362306a36Sopenharmony_ci		REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
76462306a36Sopenharmony_ci			  ATH9K_POW_SM(ratesArray[rate2s], 24)
76562306a36Sopenharmony_ci			  | ATH9K_POW_SM(ratesArray[rate2l], 16)
76662306a36Sopenharmony_ci			  | ATH9K_POW_SM(ratesArray[rateXr], 8)
76762306a36Sopenharmony_ci			  | ATH9K_POW_SM(ratesArray[rate1l], 0));
76862306a36Sopenharmony_ci		REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
76962306a36Sopenharmony_ci			  ATH9K_POW_SM(ratesArray[rate11s], 24)
77062306a36Sopenharmony_ci			  | ATH9K_POW_SM(ratesArray[rate11l], 16)
77162306a36Sopenharmony_ci			  | ATH9K_POW_SM(ratesArray[rate5_5s], 8)
77262306a36Sopenharmony_ci			  | ATH9K_POW_SM(ratesArray[rate5_5l], 0));
77362306a36Sopenharmony_ci	}
77462306a36Sopenharmony_ci
77562306a36Sopenharmony_ci	/* HT20 power per rate */
77662306a36Sopenharmony_ci	REG_WRITE(ah, AR_PHY_POWER_TX_RATE5,
77762306a36Sopenharmony_ci		  ATH9K_POW_SM(ratesArray[rateHt20_3], 24)
77862306a36Sopenharmony_ci		  | ATH9K_POW_SM(ratesArray[rateHt20_2], 16)
77962306a36Sopenharmony_ci		  | ATH9K_POW_SM(ratesArray[rateHt20_1], 8)
78062306a36Sopenharmony_ci		  | ATH9K_POW_SM(ratesArray[rateHt20_0], 0));
78162306a36Sopenharmony_ci
78262306a36Sopenharmony_ci	REG_WRITE(ah, AR_PHY_POWER_TX_RATE6,
78362306a36Sopenharmony_ci		  ATH9K_POW_SM(ratesArray[rateHt20_7], 24)
78462306a36Sopenharmony_ci		  | ATH9K_POW_SM(ratesArray[rateHt20_6], 16)
78562306a36Sopenharmony_ci		  | ATH9K_POW_SM(ratesArray[rateHt20_5], 8)
78662306a36Sopenharmony_ci		  | ATH9K_POW_SM(ratesArray[rateHt20_4], 0));
78762306a36Sopenharmony_ci
78862306a36Sopenharmony_ci	/* HT40 power per rate */
78962306a36Sopenharmony_ci	if (IS_CHAN_HT40(chan))	{
79062306a36Sopenharmony_ci		if (ath9k_hw_ar9287_get_eeprom(ah, EEP_OL_PWRCTRL)) {
79162306a36Sopenharmony_ci			REG_WRITE(ah, AR_PHY_POWER_TX_RATE7,
79262306a36Sopenharmony_ci				  ATH9K_POW_SM(ratesArray[rateHt40_3], 24)
79362306a36Sopenharmony_ci				  | ATH9K_POW_SM(ratesArray[rateHt40_2], 16)
79462306a36Sopenharmony_ci				  | ATH9K_POW_SM(ratesArray[rateHt40_1], 8)
79562306a36Sopenharmony_ci				  | ATH9K_POW_SM(ratesArray[rateHt40_0], 0));
79662306a36Sopenharmony_ci
79762306a36Sopenharmony_ci			REG_WRITE(ah, AR_PHY_POWER_TX_RATE8,
79862306a36Sopenharmony_ci				  ATH9K_POW_SM(ratesArray[rateHt40_7], 24)
79962306a36Sopenharmony_ci				  | ATH9K_POW_SM(ratesArray[rateHt40_6], 16)
80062306a36Sopenharmony_ci				  | ATH9K_POW_SM(ratesArray[rateHt40_5], 8)
80162306a36Sopenharmony_ci				  | ATH9K_POW_SM(ratesArray[rateHt40_4], 0));
80262306a36Sopenharmony_ci		} else {
80362306a36Sopenharmony_ci			REG_WRITE(ah, AR_PHY_POWER_TX_RATE7,
80462306a36Sopenharmony_ci				  ATH9K_POW_SM(ratesArray[rateHt40_3] +
80562306a36Sopenharmony_ci					       ht40PowerIncForPdadc, 24)
80662306a36Sopenharmony_ci				  | ATH9K_POW_SM(ratesArray[rateHt40_2] +
80762306a36Sopenharmony_ci						 ht40PowerIncForPdadc, 16)
80862306a36Sopenharmony_ci				  | ATH9K_POW_SM(ratesArray[rateHt40_1] +
80962306a36Sopenharmony_ci						 ht40PowerIncForPdadc, 8)
81062306a36Sopenharmony_ci				  | ATH9K_POW_SM(ratesArray[rateHt40_0] +
81162306a36Sopenharmony_ci						 ht40PowerIncForPdadc, 0));
81262306a36Sopenharmony_ci
81362306a36Sopenharmony_ci			REG_WRITE(ah, AR_PHY_POWER_TX_RATE8,
81462306a36Sopenharmony_ci				  ATH9K_POW_SM(ratesArray[rateHt40_7] +
81562306a36Sopenharmony_ci					       ht40PowerIncForPdadc, 24)
81662306a36Sopenharmony_ci				  | ATH9K_POW_SM(ratesArray[rateHt40_6] +
81762306a36Sopenharmony_ci						 ht40PowerIncForPdadc, 16)
81862306a36Sopenharmony_ci				  | ATH9K_POW_SM(ratesArray[rateHt40_5] +
81962306a36Sopenharmony_ci						 ht40PowerIncForPdadc, 8)
82062306a36Sopenharmony_ci				  | ATH9K_POW_SM(ratesArray[rateHt40_4] +
82162306a36Sopenharmony_ci						 ht40PowerIncForPdadc, 0));
82262306a36Sopenharmony_ci		}
82362306a36Sopenharmony_ci
82462306a36Sopenharmony_ci		/* Dup/Ext power per rate */
82562306a36Sopenharmony_ci		REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
82662306a36Sopenharmony_ci			  ATH9K_POW_SM(ratesArray[rateExtOfdm], 24)
82762306a36Sopenharmony_ci			  | ATH9K_POW_SM(ratesArray[rateExtCck], 16)
82862306a36Sopenharmony_ci			  | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
82962306a36Sopenharmony_ci			  | ATH9K_POW_SM(ratesArray[rateDupCck], 0));
83062306a36Sopenharmony_ci	}
83162306a36Sopenharmony_ci
83262306a36Sopenharmony_ci	/* TPC initializations */
83362306a36Sopenharmony_ci	if (ah->tpc_enabled) {
83462306a36Sopenharmony_ci		int ht40_delta;
83562306a36Sopenharmony_ci
83662306a36Sopenharmony_ci		ht40_delta = (IS_CHAN_HT40(chan)) ? ht40PowerIncForPdadc : 0;
83762306a36Sopenharmony_ci		ar5008_hw_init_rate_txpower(ah, ratesArray, chan, ht40_delta);
83862306a36Sopenharmony_ci		/* Enable TPC */
83962306a36Sopenharmony_ci		REG_WRITE(ah, AR_PHY_POWER_TX_RATE_MAX,
84062306a36Sopenharmony_ci			MAX_RATE_POWER | AR_PHY_POWER_TX_RATE_MAX_TPC_ENABLE);
84162306a36Sopenharmony_ci	} else {
84262306a36Sopenharmony_ci		/* Disable TPC */
84362306a36Sopenharmony_ci		REG_WRITE(ah, AR_PHY_POWER_TX_RATE_MAX, MAX_RATE_POWER);
84462306a36Sopenharmony_ci	}
84562306a36Sopenharmony_ci
84662306a36Sopenharmony_ci	REGWRITE_BUFFER_FLUSH(ah);
84762306a36Sopenharmony_ci}
84862306a36Sopenharmony_ci
84962306a36Sopenharmony_cistatic void ath9k_hw_ar9287_set_board_values(struct ath_hw *ah,
85062306a36Sopenharmony_ci					     struct ath9k_channel *chan)
85162306a36Sopenharmony_ci{
85262306a36Sopenharmony_ci	struct ar9287_eeprom *eep = &ah->eeprom.map9287;
85362306a36Sopenharmony_ci	struct modal_eep_ar9287_header *pModal = &eep->modalHeader;
85462306a36Sopenharmony_ci	u32 regChainOffset, regval;
85562306a36Sopenharmony_ci	u8 txRxAttenLocal;
85662306a36Sopenharmony_ci	int i;
85762306a36Sopenharmony_ci
85862306a36Sopenharmony_ci	pModal = &eep->modalHeader;
85962306a36Sopenharmony_ci
86062306a36Sopenharmony_ci	REG_WRITE(ah, AR_PHY_SWITCH_COM, le32_to_cpu(pModal->antCtrlCommon));
86162306a36Sopenharmony_ci
86262306a36Sopenharmony_ci	for (i = 0; i < AR9287_MAX_CHAINS; i++)	{
86362306a36Sopenharmony_ci		regChainOffset = i * 0x1000;
86462306a36Sopenharmony_ci
86562306a36Sopenharmony_ci		REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset,
86662306a36Sopenharmony_ci			  le32_to_cpu(pModal->antCtrlChain[i]));
86762306a36Sopenharmony_ci
86862306a36Sopenharmony_ci		REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset,
86962306a36Sopenharmony_ci			  (REG_READ(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset)
87062306a36Sopenharmony_ci			   & ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF |
87162306a36Sopenharmony_ci			       AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) |
87262306a36Sopenharmony_ci			  SM(pModal->iqCalICh[i],
87362306a36Sopenharmony_ci			     AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) |
87462306a36Sopenharmony_ci			  SM(pModal->iqCalQCh[i],
87562306a36Sopenharmony_ci			     AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF));
87662306a36Sopenharmony_ci
87762306a36Sopenharmony_ci		txRxAttenLocal = pModal->txRxAttenCh[i];
87862306a36Sopenharmony_ci
87962306a36Sopenharmony_ci		REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
88062306a36Sopenharmony_ci			      AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN,
88162306a36Sopenharmony_ci			      pModal->bswMargin[i]);
88262306a36Sopenharmony_ci		REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
88362306a36Sopenharmony_ci			      AR_PHY_GAIN_2GHZ_XATTEN1_DB,
88462306a36Sopenharmony_ci			      pModal->bswAtten[i]);
88562306a36Sopenharmony_ci		REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset,
88662306a36Sopenharmony_ci			      AR9280_PHY_RXGAIN_TXRX_ATTEN,
88762306a36Sopenharmony_ci			      txRxAttenLocal);
88862306a36Sopenharmony_ci		REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset,
88962306a36Sopenharmony_ci			      AR9280_PHY_RXGAIN_TXRX_MARGIN,
89062306a36Sopenharmony_ci			      pModal->rxTxMarginCh[i]);
89162306a36Sopenharmony_ci	}
89262306a36Sopenharmony_ci
89362306a36Sopenharmony_ci
89462306a36Sopenharmony_ci	if (IS_CHAN_HT40(chan))
89562306a36Sopenharmony_ci		REG_RMW_FIELD(ah, AR_PHY_SETTLING,
89662306a36Sopenharmony_ci			      AR_PHY_SETTLING_SWITCH, pModal->swSettleHt40);
89762306a36Sopenharmony_ci	else
89862306a36Sopenharmony_ci		REG_RMW_FIELD(ah, AR_PHY_SETTLING,
89962306a36Sopenharmony_ci			      AR_PHY_SETTLING_SWITCH, pModal->switchSettling);
90062306a36Sopenharmony_ci
90162306a36Sopenharmony_ci	REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
90262306a36Sopenharmony_ci		      AR_PHY_DESIRED_SZ_ADC, pModal->adcDesiredSize);
90362306a36Sopenharmony_ci
90462306a36Sopenharmony_ci	REG_WRITE(ah, AR_PHY_RF_CTL4,
90562306a36Sopenharmony_ci		  SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF)
90662306a36Sopenharmony_ci		  | SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAB_OFF)
90762306a36Sopenharmony_ci		  | SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAA_ON)
90862306a36Sopenharmony_ci		  | SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAB_ON));
90962306a36Sopenharmony_ci
91062306a36Sopenharmony_ci	REG_RMW_FIELD(ah, AR_PHY_RF_CTL3,
91162306a36Sopenharmony_ci		      AR_PHY_TX_END_TO_A2_RX_ON, pModal->txEndToRxOn);
91262306a36Sopenharmony_ci
91362306a36Sopenharmony_ci	REG_RMW_FIELD(ah, AR_PHY_CCA,
91462306a36Sopenharmony_ci		      AR9280_PHY_CCA_THRESH62, pModal->thresh62);
91562306a36Sopenharmony_ci	REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0,
91662306a36Sopenharmony_ci		      AR_PHY_EXT_CCA0_THRESH62, pModal->thresh62);
91762306a36Sopenharmony_ci
91862306a36Sopenharmony_ci	regval = REG_READ(ah, AR9287_AN_RF2G3_CH0);
91962306a36Sopenharmony_ci	regval &= ~(AR9287_AN_RF2G3_DB1 |
92062306a36Sopenharmony_ci		    AR9287_AN_RF2G3_DB2 |
92162306a36Sopenharmony_ci		    AR9287_AN_RF2G3_OB_CCK |
92262306a36Sopenharmony_ci		    AR9287_AN_RF2G3_OB_PSK |
92362306a36Sopenharmony_ci		    AR9287_AN_RF2G3_OB_QAM |
92462306a36Sopenharmony_ci		    AR9287_AN_RF2G3_OB_PAL_OFF);
92562306a36Sopenharmony_ci	regval |= (SM(pModal->db1, AR9287_AN_RF2G3_DB1) |
92662306a36Sopenharmony_ci		   SM(pModal->db2, AR9287_AN_RF2G3_DB2) |
92762306a36Sopenharmony_ci		   SM(pModal->ob_cck, AR9287_AN_RF2G3_OB_CCK) |
92862306a36Sopenharmony_ci		   SM(pModal->ob_psk, AR9287_AN_RF2G3_OB_PSK) |
92962306a36Sopenharmony_ci		   SM(pModal->ob_qam, AR9287_AN_RF2G3_OB_QAM) |
93062306a36Sopenharmony_ci		   SM(pModal->ob_pal_off, AR9287_AN_RF2G3_OB_PAL_OFF));
93162306a36Sopenharmony_ci
93262306a36Sopenharmony_ci	ath9k_hw_analog_shift_regwrite(ah, AR9287_AN_RF2G3_CH0, regval);
93362306a36Sopenharmony_ci
93462306a36Sopenharmony_ci	regval = REG_READ(ah, AR9287_AN_RF2G3_CH1);
93562306a36Sopenharmony_ci	regval &= ~(AR9287_AN_RF2G3_DB1 |
93662306a36Sopenharmony_ci		    AR9287_AN_RF2G3_DB2 |
93762306a36Sopenharmony_ci		    AR9287_AN_RF2G3_OB_CCK |
93862306a36Sopenharmony_ci		    AR9287_AN_RF2G3_OB_PSK |
93962306a36Sopenharmony_ci		    AR9287_AN_RF2G3_OB_QAM |
94062306a36Sopenharmony_ci		    AR9287_AN_RF2G3_OB_PAL_OFF);
94162306a36Sopenharmony_ci	regval |= (SM(pModal->db1, AR9287_AN_RF2G3_DB1) |
94262306a36Sopenharmony_ci		   SM(pModal->db2, AR9287_AN_RF2G3_DB2) |
94362306a36Sopenharmony_ci		   SM(pModal->ob_cck, AR9287_AN_RF2G3_OB_CCK) |
94462306a36Sopenharmony_ci		   SM(pModal->ob_psk, AR9287_AN_RF2G3_OB_PSK) |
94562306a36Sopenharmony_ci		   SM(pModal->ob_qam, AR9287_AN_RF2G3_OB_QAM) |
94662306a36Sopenharmony_ci		   SM(pModal->ob_pal_off, AR9287_AN_RF2G3_OB_PAL_OFF));
94762306a36Sopenharmony_ci
94862306a36Sopenharmony_ci	ath9k_hw_analog_shift_regwrite(ah, AR9287_AN_RF2G3_CH1, regval);
94962306a36Sopenharmony_ci
95062306a36Sopenharmony_ci	REG_RMW_FIELD(ah, AR_PHY_RF_CTL2,
95162306a36Sopenharmony_ci		      AR_PHY_TX_END_DATA_START, pModal->txFrameToDataStart);
95262306a36Sopenharmony_ci	REG_RMW_FIELD(ah, AR_PHY_RF_CTL2,
95362306a36Sopenharmony_ci		      AR_PHY_TX_END_PA_ON, pModal->txFrameToPaOn);
95462306a36Sopenharmony_ci
95562306a36Sopenharmony_ci	ath9k_hw_analog_shift_rmw(ah, AR9287_AN_TOP2,
95662306a36Sopenharmony_ci				  AR9287_AN_TOP2_XPABIAS_LVL,
95762306a36Sopenharmony_ci				  AR9287_AN_TOP2_XPABIAS_LVL_S,
95862306a36Sopenharmony_ci				  pModal->xpaBiasLvl);
95962306a36Sopenharmony_ci}
96062306a36Sopenharmony_ci
96162306a36Sopenharmony_cistatic u16 ath9k_hw_ar9287_get_spur_channel(struct ath_hw *ah,
96262306a36Sopenharmony_ci					    u16 i, bool is2GHz)
96362306a36Sopenharmony_ci{
96462306a36Sopenharmony_ci	__le16 spur_ch = ah->eeprom.map9287.modalHeader.spurChans[i].spurChan;
96562306a36Sopenharmony_ci
96662306a36Sopenharmony_ci	return le16_to_cpu(spur_ch);
96762306a36Sopenharmony_ci}
96862306a36Sopenharmony_ci
96962306a36Sopenharmony_cistatic u8 ath9k_hw_ar9287_get_eepmisc(struct ath_hw *ah)
97062306a36Sopenharmony_ci{
97162306a36Sopenharmony_ci	return ah->eeprom.map9287.baseEepHeader.eepMisc;
97262306a36Sopenharmony_ci}
97362306a36Sopenharmony_ci
97462306a36Sopenharmony_ciconst struct eeprom_ops eep_ar9287_ops = {
97562306a36Sopenharmony_ci	.check_eeprom		= ath9k_hw_ar9287_check_eeprom,
97662306a36Sopenharmony_ci	.get_eeprom		= ath9k_hw_ar9287_get_eeprom,
97762306a36Sopenharmony_ci	.fill_eeprom		= ath9k_hw_ar9287_fill_eeprom,
97862306a36Sopenharmony_ci	.dump_eeprom		= ath9k_hw_ar9287_dump_eeprom,
97962306a36Sopenharmony_ci	.get_eeprom_ver		= ath9k_hw_ar9287_get_eeprom_ver,
98062306a36Sopenharmony_ci	.get_eeprom_rev		= ath9k_hw_ar9287_get_eeprom_rev,
98162306a36Sopenharmony_ci	.set_board_values	= ath9k_hw_ar9287_set_board_values,
98262306a36Sopenharmony_ci	.set_txpower		= ath9k_hw_ar9287_set_txpower,
98362306a36Sopenharmony_ci	.get_spur_channel	= ath9k_hw_ar9287_get_spur_channel,
98462306a36Sopenharmony_ci	.get_eepmisc		= ath9k_hw_ar9287_get_eepmisc
98562306a36Sopenharmony_ci};
986