xref: /openbmc/linux/drivers/net/wireless/ath/ath9k/eeprom_9287.c (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
1b5aec950SSujith /*
25b68138eSSujith Manoharan  * Copyright (c) 2008-2011 Atheros Communications Inc.
3b5aec950SSujith  *
4b5aec950SSujith  * Permission to use, copy, modify, and/or distribute this software for any
5b5aec950SSujith  * purpose with or without fee is hereby granted, provided that the above
6b5aec950SSujith  * copyright notice and this permission notice appear in all copies.
7b5aec950SSujith  *
8b5aec950SSujith  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9b5aec950SSujith  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10b5aec950SSujith  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11b5aec950SSujith  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12b5aec950SSujith  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13b5aec950SSujith  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14b5aec950SSujith  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15b5aec950SSujith  */
16b5aec950SSujith 
1778fa99abSPavel Roskin #include <asm/unaligned.h>
18c46917bbSLuis R. Rodriguez #include "hw.h"
198fe65368SLuis R. Rodriguez #include "ar9002_phy.h"
20b5aec950SSujith 
2104cf53f4SSujith Manoharan #define SIZE_EEPROM_AR9287 (sizeof(struct ar9287_eeprom) / sizeof(u16))
2216c94ac6SSujith 
ath9k_hw_ar9287_get_eeprom_ver(struct ath_hw * ah)2316c94ac6SSujith static int ath9k_hw_ar9287_get_eeprom_ver(struct ath_hw *ah)
24b5aec950SSujith {
254bca5303SMartin Blumenstingl 	u16 version = le16_to_cpu(ah->eeprom.map9287.baseEepHeader.version);
269bff7428SMartin Blumenstingl 
279bff7428SMartin Blumenstingl 	return (version & AR5416_EEP_VER_MAJOR_MASK) >>
289bff7428SMartin Blumenstingl 		AR5416_EEP_VER_MAJOR_SHIFT;
29b5aec950SSujith }
30b5aec950SSujith 
ath9k_hw_ar9287_get_eeprom_rev(struct ath_hw * ah)3116c94ac6SSujith static int ath9k_hw_ar9287_get_eeprom_rev(struct ath_hw *ah)
32b5aec950SSujith {
334bca5303SMartin Blumenstingl 	u16 version = le16_to_cpu(ah->eeprom.map9287.baseEepHeader.version);
349bff7428SMartin Blumenstingl 
359bff7428SMartin Blumenstingl 	return version & AR5416_EEP_VER_MINOR_MASK;
36b5aec950SSujith }
37b5aec950SSujith 
__ath9k_hw_ar9287_fill_eeprom(struct ath_hw * ah)3804cf53f4SSujith Manoharan static bool __ath9k_hw_ar9287_fill_eeprom(struct ath_hw *ah)
39b5aec950SSujith {
40b5aec950SSujith 	struct ar9287_eeprom *eep = &ah->eeprom.map9287;
41b5aec950SSujith 	u16 *eep_data;
4204cf53f4SSujith Manoharan 	int addr, eep_start_loc = AR9287_EEP_START_LOC;
43b5aec950SSujith 	eep_data = (u16 *)eep;
44b5aec950SSujith 
4504cf53f4SSujith Manoharan 	for (addr = 0; addr < SIZE_EEPROM_AR9287; addr++) {
460e4b9f2fSGabor Juhos 		if (!ath9k_hw_nvram_read(ah, addr + eep_start_loc, eep_data))
47b5aec950SSujith 			return false;
48b5aec950SSujith 		eep_data++;
49b5aec950SSujith 	}
5016c94ac6SSujith 
51b5aec950SSujith 	return true;
52b5aec950SSujith }
53b5aec950SSujith 
__ath9k_hw_usb_ar9287_fill_eeprom(struct ath_hw * ah)5404cf53f4SSujith Manoharan static bool __ath9k_hw_usb_ar9287_fill_eeprom(struct ath_hw *ah)
5504cf53f4SSujith Manoharan {
5604cf53f4SSujith Manoharan 	u16 *eep_data = (u16 *)&ah->eeprom.map9287;
5704cf53f4SSujith Manoharan 
5804cf53f4SSujith Manoharan 	ath9k_hw_usb_gen_fill_eeprom(ah, eep_data,
5904cf53f4SSujith Manoharan 				     AR9287_HTC_EEP_START_LOC,
6004cf53f4SSujith Manoharan 				     SIZE_EEPROM_AR9287);
6104cf53f4SSujith Manoharan 	return true;
6204cf53f4SSujith Manoharan }
6304cf53f4SSujith Manoharan 
ath9k_hw_ar9287_fill_eeprom(struct ath_hw * ah)6404cf53f4SSujith Manoharan static bool ath9k_hw_ar9287_fill_eeprom(struct ath_hw *ah)
6504cf53f4SSujith Manoharan {
6604cf53f4SSujith Manoharan 	struct ath_common *common = ath9k_hw_common(ah);
6704cf53f4SSujith Manoharan 
6804cf53f4SSujith Manoharan 	if (!ath9k_hw_use_flash(ah)) {
69d2182b69SJoe Perches 		ath_dbg(common, EEPROM, "Reading from EEPROM, not flash\n");
7004cf53f4SSujith Manoharan 	}
7104cf53f4SSujith Manoharan 
7204cf53f4SSujith Manoharan 	if (common->bus_ops->ath_bus_type == ATH_USB)
7304cf53f4SSujith Manoharan 		return __ath9k_hw_usb_ar9287_fill_eeprom(ah);
7404cf53f4SSujith Manoharan 	else
7504cf53f4SSujith Manoharan 		return __ath9k_hw_ar9287_fill_eeprom(ah);
7604cf53f4SSujith Manoharan }
7704cf53f4SSujith Manoharan 
781077ec47SChristian Lamparter #ifdef CONFIG_ATH9K_COMMON_DEBUG
ar9287_dump_modal_eeprom(char * buf,u32 len,u32 size,struct modal_eep_ar9287_header * modal_hdr)7949c99520SRajkumar Manoharan static u32 ar9287_dump_modal_eeprom(char *buf, u32 len, u32 size,
8049c99520SRajkumar Manoharan 				    struct modal_eep_ar9287_header *modal_hdr)
8149c99520SRajkumar Manoharan {
824bca5303SMartin Blumenstingl 	PR_EEP("Chain0 Ant. Control", le16_to_cpu(modal_hdr->antCtrlChain[0]));
834bca5303SMartin Blumenstingl 	PR_EEP("Chain1 Ant. Control", le16_to_cpu(modal_hdr->antCtrlChain[1]));
844bca5303SMartin Blumenstingl 	PR_EEP("Ant. Common Control", le32_to_cpu(modal_hdr->antCtrlCommon));
8549c99520SRajkumar Manoharan 	PR_EEP("Chain0 Ant. Gain", modal_hdr->antennaGainCh[0]);
8649c99520SRajkumar Manoharan 	PR_EEP("Chain1 Ant. Gain", modal_hdr->antennaGainCh[1]);
8749c99520SRajkumar Manoharan 	PR_EEP("Switch Settle", modal_hdr->switchSettling);
8849c99520SRajkumar Manoharan 	PR_EEP("Chain0 TxRxAtten", modal_hdr->txRxAttenCh[0]);
8949c99520SRajkumar Manoharan 	PR_EEP("Chain1 TxRxAtten", modal_hdr->txRxAttenCh[1]);
9049c99520SRajkumar Manoharan 	PR_EEP("Chain0 RxTxMargin", modal_hdr->rxTxMarginCh[0]);
9149c99520SRajkumar Manoharan 	PR_EEP("Chain1 RxTxMargin", modal_hdr->rxTxMarginCh[1]);
9249c99520SRajkumar Manoharan 	PR_EEP("ADC Desired size", modal_hdr->adcDesiredSize);
9349c99520SRajkumar Manoharan 	PR_EEP("txEndToXpaOff", modal_hdr->txEndToXpaOff);
9449c99520SRajkumar Manoharan 	PR_EEP("txEndToRxOn", modal_hdr->txEndToRxOn);
9549c99520SRajkumar Manoharan 	PR_EEP("txFrameToXpaOn", modal_hdr->txFrameToXpaOn);
9649c99520SRajkumar Manoharan 	PR_EEP("CCA Threshold)", modal_hdr->thresh62);
9749c99520SRajkumar Manoharan 	PR_EEP("Chain0 NF Threshold", modal_hdr->noiseFloorThreshCh[0]);
9849c99520SRajkumar Manoharan 	PR_EEP("Chain1 NF Threshold", modal_hdr->noiseFloorThreshCh[1]);
9949c99520SRajkumar Manoharan 	PR_EEP("xpdGain", modal_hdr->xpdGain);
10049c99520SRajkumar Manoharan 	PR_EEP("External PD", modal_hdr->xpd);
10149c99520SRajkumar Manoharan 	PR_EEP("Chain0 I Coefficient", modal_hdr->iqCalICh[0]);
10249c99520SRajkumar Manoharan 	PR_EEP("Chain1 I Coefficient", modal_hdr->iqCalICh[1]);
10349c99520SRajkumar Manoharan 	PR_EEP("Chain0 Q Coefficient", modal_hdr->iqCalQCh[0]);
10449c99520SRajkumar Manoharan 	PR_EEP("Chain1 Q Coefficient", modal_hdr->iqCalQCh[1]);
10549c99520SRajkumar Manoharan 	PR_EEP("pdGainOverlap", modal_hdr->pdGainOverlap);
10649c99520SRajkumar Manoharan 	PR_EEP("xPA Bias Level", modal_hdr->xpaBiasLvl);
10749c99520SRajkumar Manoharan 	PR_EEP("txFrameToDataStart", modal_hdr->txFrameToDataStart);
10849c99520SRajkumar Manoharan 	PR_EEP("txFrameToPaOn", modal_hdr->txFrameToPaOn);
10949c99520SRajkumar Manoharan 	PR_EEP("HT40 Power Inc.", modal_hdr->ht40PowerIncForPdadc);
11049c99520SRajkumar Manoharan 	PR_EEP("Chain0 bswAtten", modal_hdr->bswAtten[0]);
11149c99520SRajkumar Manoharan 	PR_EEP("Chain1 bswAtten", modal_hdr->bswAtten[1]);
11249c99520SRajkumar Manoharan 	PR_EEP("Chain0 bswMargin", modal_hdr->bswMargin[0]);
11349c99520SRajkumar Manoharan 	PR_EEP("Chain1 bswMargin", modal_hdr->bswMargin[1]);
11449c99520SRajkumar Manoharan 	PR_EEP("HT40 Switch Settle", modal_hdr->swSettleHt40);
11549c99520SRajkumar Manoharan 	PR_EEP("AR92x7 Version", modal_hdr->version);
11649c99520SRajkumar Manoharan 	PR_EEP("DriverBias1", modal_hdr->db1);
11749c99520SRajkumar Manoharan 	PR_EEP("DriverBias2", modal_hdr->db1);
11849c99520SRajkumar Manoharan 	PR_EEP("CCK OutputBias", modal_hdr->ob_cck);
11949c99520SRajkumar Manoharan 	PR_EEP("PSK OutputBias", modal_hdr->ob_psk);
12049c99520SRajkumar Manoharan 	PR_EEP("QAM OutputBias", modal_hdr->ob_qam);
12149c99520SRajkumar Manoharan 	PR_EEP("PAL_OFF OutputBias", modal_hdr->ob_pal_off);
12249c99520SRajkumar Manoharan 
12349c99520SRajkumar Manoharan 	return len;
12449c99520SRajkumar Manoharan }
12549c99520SRajkumar Manoharan 
ath9k_hw_ar9287_dump_eeprom(struct ath_hw * ah,bool dump_base_hdr,u8 * buf,u32 len,u32 size)12649c99520SRajkumar Manoharan static u32 ath9k_hw_ar9287_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
12749c99520SRajkumar Manoharan 				       u8 *buf, u32 len, u32 size)
12849c99520SRajkumar Manoharan {
12949c99520SRajkumar Manoharan 	struct ar9287_eeprom *eep = &ah->eeprom.map9287;
13049c99520SRajkumar Manoharan 	struct base_eep_ar9287_header *pBase = &eep->baseEepHeader;
1314bca5303SMartin Blumenstingl 	u32 binBuildNumber = le32_to_cpu(pBase->binBuildNumber);
13249c99520SRajkumar Manoharan 
13349c99520SRajkumar Manoharan 	if (!dump_base_hdr) {
1345e88ba62SZefir Kurtisi 		len += scnprintf(buf + len, size - len,
13549c99520SRajkumar Manoharan 				 "%20s :\n", "2GHz modal Header");
136d25360b1SMohammed Shafi Shajakhan 		len = ar9287_dump_modal_eeprom(buf, len, size,
13749c99520SRajkumar Manoharan 						&eep->modalHeader);
13849c99520SRajkumar Manoharan 		goto out;
13949c99520SRajkumar Manoharan 	}
14049c99520SRajkumar Manoharan 
1419bff7428SMartin Blumenstingl 	PR_EEP("Major Version", ath9k_hw_ar9287_get_eeprom_ver(ah));
1429bff7428SMartin Blumenstingl 	PR_EEP("Minor Version", ath9k_hw_ar9287_get_eeprom_rev(ah));
1434bca5303SMartin Blumenstingl 	PR_EEP("Checksum", le16_to_cpu(pBase->checksum));
1444bca5303SMartin Blumenstingl 	PR_EEP("Length", le16_to_cpu(pBase->length));
1454bca5303SMartin Blumenstingl 	PR_EEP("RegDomain1", le16_to_cpu(pBase->regDmn[0]));
1464bca5303SMartin Blumenstingl 	PR_EEP("RegDomain2", le16_to_cpu(pBase->regDmn[1]));
14749c99520SRajkumar Manoharan 	PR_EEP("TX Mask", pBase->txMask);
14849c99520SRajkumar Manoharan 	PR_EEP("RX Mask", pBase->rxMask);
14949c99520SRajkumar Manoharan 	PR_EEP("Allow 5GHz", !!(pBase->opCapFlags & AR5416_OPFLAGS_11A));
15049c99520SRajkumar Manoharan 	PR_EEP("Allow 2GHz", !!(pBase->opCapFlags & AR5416_OPFLAGS_11G));
15149c99520SRajkumar Manoharan 	PR_EEP("Disable 2GHz HT20", !!(pBase->opCapFlags &
15249c99520SRajkumar Manoharan 					AR5416_OPFLAGS_N_2G_HT20));
15349c99520SRajkumar Manoharan 	PR_EEP("Disable 2GHz HT40", !!(pBase->opCapFlags &
15449c99520SRajkumar Manoharan 					AR5416_OPFLAGS_N_2G_HT40));
15549c99520SRajkumar Manoharan 	PR_EEP("Disable 5Ghz HT20", !!(pBase->opCapFlags &
15649c99520SRajkumar Manoharan 					AR5416_OPFLAGS_N_5G_HT20));
15749c99520SRajkumar Manoharan 	PR_EEP("Disable 5Ghz HT40", !!(pBase->opCapFlags &
15849c99520SRajkumar Manoharan 					AR5416_OPFLAGS_N_5G_HT40));
15981a834e3SMartin Blumenstingl 	PR_EEP("Big Endian", !!(pBase->eepMisc & AR5416_EEPMISC_BIG_ENDIAN));
1604bca5303SMartin Blumenstingl 	PR_EEP("Cal Bin Major Ver", (binBuildNumber >> 24) & 0xFF);
1614bca5303SMartin Blumenstingl 	PR_EEP("Cal Bin Minor Ver", (binBuildNumber >> 16) & 0xFF);
1624bca5303SMartin Blumenstingl 	PR_EEP("Cal Bin Build", (binBuildNumber >> 8) & 0xFF);
16349c99520SRajkumar Manoharan 	PR_EEP("Power Table Offset", pBase->pwrTableOffset);
16449c99520SRajkumar Manoharan 	PR_EEP("OpenLoop Power Ctrl", pBase->openLoopPwrCntl);
16549c99520SRajkumar Manoharan 
1665e88ba62SZefir Kurtisi 	len += scnprintf(buf + len, size - len, "%20s : %pM\n", "MacAddress",
16749c99520SRajkumar Manoharan 			 pBase->macAddr);
16849c99520SRajkumar Manoharan 
16949c99520SRajkumar Manoharan out:
17049c99520SRajkumar Manoharan 	if (len > size)
17149c99520SRajkumar Manoharan 		len = size;
17249c99520SRajkumar Manoharan 
17349c99520SRajkumar Manoharan 	return len;
17449c99520SRajkumar Manoharan }
17549c99520SRajkumar Manoharan #else
ath9k_hw_ar9287_dump_eeprom(struct ath_hw * ah,bool dump_base_hdr,u8 * buf,u32 len,u32 size)17649c99520SRajkumar Manoharan static u32 ath9k_hw_ar9287_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
17749c99520SRajkumar Manoharan 				       u8 *buf, u32 len, u32 size)
17849c99520SRajkumar Manoharan {
17949c99520SRajkumar Manoharan 	return 0;
18049c99520SRajkumar Manoharan }
18149c99520SRajkumar Manoharan #endif
18249c99520SRajkumar Manoharan 
18349c99520SRajkumar Manoharan 
ath9k_hw_ar9287_check_eeprom(struct ath_hw * ah)18416c94ac6SSujith static int ath9k_hw_ar9287_check_eeprom(struct ath_hw *ah)
185b5aec950SSujith {
1864bca5303SMartin Blumenstingl 	u32 el;
1876fa658fdSMartin Blumenstingl 	int i, err;
1886fa658fdSMartin Blumenstingl 	bool need_swap;
189b5aec950SSujith 	struct ar9287_eeprom *eep = &ah->eeprom.map9287;
190b5aec950SSujith 
1916fa658fdSMartin Blumenstingl 	err = ath9k_hw_nvram_swap_data(ah, &need_swap, SIZE_EEPROM_AR9287);
1926fa658fdSMartin Blumenstingl 	if (err)
1936fa658fdSMartin Blumenstingl 		return err;
194b5aec950SSujith 
195b5aec950SSujith 	if (need_swap)
1964bca5303SMartin Blumenstingl 		el = swab16((__force u16)eep->baseEepHeader.length);
197b5aec950SSujith 	else
1984bca5303SMartin Blumenstingl 		el = le16_to_cpu(eep->baseEepHeader.length);
199b5aec950SSujith 
2006fa658fdSMartin Blumenstingl 	el = min(el / sizeof(u16), SIZE_EEPROM_AR9287);
2016fa658fdSMartin Blumenstingl 	if (!ath9k_hw_nvram_validate_checksum(ah, el))
2026fa658fdSMartin Blumenstingl 		return -EINVAL;
203b5aec950SSujith 
204b5aec950SSujith 	if (need_swap) {
2054bca5303SMartin Blumenstingl 		EEPROM_FIELD_SWAB16(eep->baseEepHeader.length);
2064bca5303SMartin Blumenstingl 		EEPROM_FIELD_SWAB16(eep->baseEepHeader.checksum);
2074bca5303SMartin Blumenstingl 		EEPROM_FIELD_SWAB16(eep->baseEepHeader.version);
2084bca5303SMartin Blumenstingl 		EEPROM_FIELD_SWAB16(eep->baseEepHeader.regDmn[0]);
2094bca5303SMartin Blumenstingl 		EEPROM_FIELD_SWAB16(eep->baseEepHeader.regDmn[1]);
2104bca5303SMartin Blumenstingl 		EEPROM_FIELD_SWAB16(eep->baseEepHeader.rfSilent);
2114bca5303SMartin Blumenstingl 		EEPROM_FIELD_SWAB16(eep->baseEepHeader.blueToothOptions);
2124bca5303SMartin Blumenstingl 		EEPROM_FIELD_SWAB16(eep->baseEepHeader.deviceCap);
2134bca5303SMartin Blumenstingl 		EEPROM_FIELD_SWAB32(eep->modalHeader.antCtrlCommon);
214b5aec950SSujith 
2154bca5303SMartin Blumenstingl 		for (i = 0; i < AR9287_MAX_CHAINS; i++)
2164bca5303SMartin Blumenstingl 			EEPROM_FIELD_SWAB32(eep->modalHeader.antCtrlChain[i]);
217b5aec950SSujith 
2184bca5303SMartin Blumenstingl 		for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++)
2194bca5303SMartin Blumenstingl 			EEPROM_FIELD_SWAB16(
2204bca5303SMartin Blumenstingl 				eep->modalHeader.spurChans[i].spurChan);
221b5aec950SSujith 	}
222b5aec950SSujith 
2236fa658fdSMartin Blumenstingl 	if (!ath9k_hw_nvram_check_version(ah, AR9287_EEP_VER,
2246fa658fdSMartin Blumenstingl 	    AR5416_EEP_NO_BACK_VER))
225b5aec950SSujith 		return -EINVAL;
226b5aec950SSujith 
227b5aec950SSujith 	return 0;
228b5aec950SSujith }
229b5aec950SSujith 
2306fa658fdSMartin Blumenstingl #undef SIZE_EEPROM_AR9287
2316fa658fdSMartin Blumenstingl 
ath9k_hw_ar9287_get_eeprom(struct ath_hw * ah,enum eeprom_param param)23216c94ac6SSujith static u32 ath9k_hw_ar9287_get_eeprom(struct ath_hw *ah,
233b5aec950SSujith 				      enum eeprom_param param)
234b5aec950SSujith {
235b5aec950SSujith 	struct ar9287_eeprom *eep = &ah->eeprom.map9287;
236b5aec950SSujith 	struct modal_eep_ar9287_header *pModal = &eep->modalHeader;
237b5aec950SSujith 	struct base_eep_ar9287_header *pBase = &eep->baseEepHeader;
2387d7dc538SMartin Blumenstingl 	u16 ver_minor = ath9k_hw_ar9287_get_eeprom_rev(ah);
23916c94ac6SSujith 
240b5aec950SSujith 	switch (param) {
241b5aec950SSujith 	case EEP_NFTHRESH_2:
242b5aec950SSujith 		return pModal->noiseFloorThreshCh[0];
24349101676SLuis R. Rodriguez 	case EEP_MAC_LSW:
24478fa99abSPavel Roskin 		return get_unaligned_be16(pBase->macAddr);
24549101676SLuis R. Rodriguez 	case EEP_MAC_MID:
24678fa99abSPavel Roskin 		return get_unaligned_be16(pBase->macAddr + 2);
24749101676SLuis R. Rodriguez 	case EEP_MAC_MSW:
24878fa99abSPavel Roskin 		return get_unaligned_be16(pBase->macAddr + 4);
249b5aec950SSujith 	case EEP_REG_0:
2504bca5303SMartin Blumenstingl 		return le16_to_cpu(pBase->regDmn[0]);
251b5aec950SSujith 	case EEP_OP_CAP:
2524bca5303SMartin Blumenstingl 		return le16_to_cpu(pBase->deviceCap);
253b5aec950SSujith 	case EEP_OP_MODE:
254b5aec950SSujith 		return pBase->opCapFlags;
255b5aec950SSujith 	case EEP_RF_SILENT:
2564bca5303SMartin Blumenstingl 		return le16_to_cpu(pBase->rfSilent);
257b5aec950SSujith 	case EEP_TX_MASK:
258b5aec950SSujith 		return pBase->txMask;
259b5aec950SSujith 	case EEP_RX_MASK:
260b5aec950SSujith 		return pBase->rxMask;
261b5aec950SSujith 	case EEP_DEV_TYPE:
262b5aec950SSujith 		return pBase->deviceType;
263b5aec950SSujith 	case EEP_OL_PWRCTRL:
264b5aec950SSujith 		return pBase->openLoopPwrCntl;
265b5aec950SSujith 	case EEP_TEMPSENSE_SLOPE:
266b5aec950SSujith 		if (ver_minor >= AR9287_EEP_MINOR_VER_2)
267b5aec950SSujith 			return pBase->tempSensSlope;
268b5aec950SSujith 		else
269b5aec950SSujith 			return 0;
270b5aec950SSujith 	case EEP_TEMPSENSE_SLOPE_PAL_ON:
271b5aec950SSujith 		if (ver_minor >= AR9287_EEP_MINOR_VER_3)
272b5aec950SSujith 			return pBase->tempSensSlopePalOn;
273b5aec950SSujith 		else
274b5aec950SSujith 			return 0;
275ca2c68ccSFelix Fietkau 	case EEP_ANTENNA_GAIN_2G:
276ca2c68ccSFelix Fietkau 		return max_t(u8, pModal->antennaGainCh[0],
277ca2c68ccSFelix Fietkau 				 pModal->antennaGainCh[1]);
278b5aec950SSujith 	default:
279b5aec950SSujith 		return 0;
280b5aec950SSujith 	}
281b5aec950SSujith }
282b5aec950SSujith 
ar9287_eeprom_get_tx_gain_index(struct ath_hw * ah,struct ath9k_channel * chan,struct cal_data_op_loop_ar9287 * pRawDatasetOpLoop,u8 * pCalChans,u16 availPiers,int8_t * pPwr)283b5aec950SSujith static void ar9287_eeprom_get_tx_gain_index(struct ath_hw *ah,
284b5aec950SSujith 			    struct ath9k_channel *chan,
285b5aec950SSujith 			    struct cal_data_op_loop_ar9287 *pRawDatasetOpLoop,
28616c94ac6SSujith 			    u8 *pCalChans,  u16 availPiers, int8_t *pPwr)
287b5aec950SSujith {
288b5aec950SSujith 	u16 idxL = 0, idxR = 0, numPiers;
289b5aec950SSujith 	bool match;
290b5aec950SSujith 	struct chan_centers centers;
291b5aec950SSujith 
292b5aec950SSujith 	ath9k_hw_get_channel_centers(ah, chan, &centers);
293b5aec950SSujith 
294b5aec950SSujith 	for (numPiers = 0; numPiers < availPiers; numPiers++) {
2954ddfcd7dSFelix Fietkau 		if (pCalChans[numPiers] == AR5416_BCHAN_UNUSED)
296b5aec950SSujith 			break;
297b5aec950SSujith 	}
298b5aec950SSujith 
299b5aec950SSujith 	match = ath9k_hw_get_lower_upper_index(
300b5aec950SSujith 		(u8)FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan)),
30116c94ac6SSujith 		pCalChans, numPiers, &idxL, &idxR);
302b5aec950SSujith 
303b5aec950SSujith 	if (match) {
304d4fe5afaSVivek Natarajan 		*pPwr = (int8_t) pRawDatasetOpLoop[idxL].pwrPdg[0][0];
305b5aec950SSujith 	} else {
306d4fe5afaSVivek Natarajan 		*pPwr = ((int8_t) pRawDatasetOpLoop[idxL].pwrPdg[0][0] +
307d4fe5afaSVivek Natarajan 			 (int8_t) pRawDatasetOpLoop[idxR].pwrPdg[0][0])/2;
308b5aec950SSujith 	}
309b5aec950SSujith 
310b5aec950SSujith }
311b5aec950SSujith 
ar9287_eeprom_olpc_set_pdadcs(struct ath_hw * ah,int32_t txPower,u16 chain)312b5aec950SSujith static void ar9287_eeprom_olpc_set_pdadcs(struct ath_hw *ah,
313b5aec950SSujith 					  int32_t txPower, u16 chain)
314b5aec950SSujith {
315b5aec950SSujith 	u32 tmpVal;
316b5aec950SSujith 	u32 a;
317b5aec950SSujith 
31816c94ac6SSujith 	/* Enable OLPC for chain 0 */
31916c94ac6SSujith 
320b5aec950SSujith 	tmpVal = REG_READ(ah, 0xa270);
321b5aec950SSujith 	tmpVal = tmpVal & 0xFCFFFFFF;
322b5aec950SSujith 	tmpVal = tmpVal | (0x3 << 24);
323b5aec950SSujith 	REG_WRITE(ah, 0xa270, tmpVal);
324b5aec950SSujith 
32516c94ac6SSujith 	/* Enable OLPC for chain 1 */
32616c94ac6SSujith 
327b5aec950SSujith 	tmpVal = REG_READ(ah, 0xb270);
328b5aec950SSujith 	tmpVal = tmpVal & 0xFCFFFFFF;
329b5aec950SSujith 	tmpVal = tmpVal | (0x3 << 24);
330b5aec950SSujith 	REG_WRITE(ah, 0xb270, tmpVal);
331b5aec950SSujith 
33216c94ac6SSujith 	/* Write the OLPC ref power for chain 0 */
33316c94ac6SSujith 
334b5aec950SSujith 	if (chain == 0) {
335b5aec950SSujith 		tmpVal = REG_READ(ah, 0xa398);
336b5aec950SSujith 		tmpVal = tmpVal & 0xff00ffff;
337b5aec950SSujith 		a = (txPower)&0xff;
338b5aec950SSujith 		tmpVal = tmpVal | (a << 16);
339b5aec950SSujith 		REG_WRITE(ah, 0xa398, tmpVal);
340b5aec950SSujith 	}
341b5aec950SSujith 
34216c94ac6SSujith 	/* Write the OLPC ref power for chain 1 */
34316c94ac6SSujith 
344b5aec950SSujith 	if (chain == 1) {
345b5aec950SSujith 		tmpVal = REG_READ(ah, 0xb398);
346b5aec950SSujith 		tmpVal = tmpVal & 0xff00ffff;
347b5aec950SSujith 		a = (txPower)&0xff;
348b5aec950SSujith 		tmpVal = tmpVal | (a << 16);
349b5aec950SSujith 		REG_WRITE(ah, 0xb398, tmpVal);
350b5aec950SSujith 	}
351b5aec950SSujith }
352b5aec950SSujith 
ath9k_hw_set_ar9287_power_cal_table(struct ath_hw * ah,struct ath9k_channel * chan)35316c94ac6SSujith static void ath9k_hw_set_ar9287_power_cal_table(struct ath_hw *ah,
354e832bf10SFelix Fietkau 						struct ath9k_channel *chan)
355b5aec950SSujith {
356b5aec950SSujith 	struct cal_data_per_freq_ar9287 *pRawDataset;
357b5aec950SSujith 	struct cal_data_op_loop_ar9287 *pRawDatasetOpenLoop;
358b5aec950SSujith 	u8 *pCalBChans = NULL;
359b5aec950SSujith 	u16 pdGainOverlap_t2;
3604ddfcd7dSFelix Fietkau 	u8 pdadcValues[AR5416_NUM_PDADC_VALUES];
3614ddfcd7dSFelix Fietkau 	u16 gainBoundaries[AR5416_PD_GAINS_IN_MASK];
362b5aec950SSujith 	u16 numPiers = 0, i, j;
363b5aec950SSujith 	u16 numXpdGain, xpdMask;
3644ddfcd7dSFelix Fietkau 	u16 xpdGainValues[AR5416_NUM_PD_GAINS] = {0, 0, 0, 0};
365a55f8588SSujith 	u32 reg32, regOffset, regChainOffset, regval;
3660ff2b5c0SSujith Manoharan 	int16_t diff = 0;
367b5aec950SSujith 	struct ar9287_eeprom *pEepData = &ah->eeprom.map9287;
36816c94ac6SSujith 
369b5aec950SSujith 	xpdMask = pEepData->modalHeader.xpdGain;
37016c94ac6SSujith 
3719bff7428SMartin Blumenstingl 	if (ath9k_hw_ar9287_get_eeprom_rev(ah) >= AR9287_EEP_MINOR_VER_2)
372b5aec950SSujith 		pdGainOverlap_t2 = pEepData->modalHeader.pdGainOverlap;
373b5aec950SSujith 	else
374b5aec950SSujith 		pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5),
375b5aec950SSujith 					    AR_PHY_TPCRG5_PD_GAIN_OVERLAP));
376b5aec950SSujith 
377b5aec950SSujith 	if (IS_CHAN_2GHZ(chan)) {
378b5aec950SSujith 		pCalBChans = pEepData->calFreqPier2G;
379b5aec950SSujith 		numPiers = AR9287_NUM_2G_CAL_PIERS;
38016c94ac6SSujith 		if (ath9k_hw_ar9287_get_eeprom(ah, EEP_OL_PWRCTRL)) {
381b5aec950SSujith 			pRawDatasetOpenLoop =
382a55f8588SSujith 			(struct cal_data_op_loop_ar9287 *)pEepData->calPierData2G[0];
383b5aec950SSujith 			ah->initPDADC = pRawDatasetOpenLoop->vpdPdg[0][0];
384b5aec950SSujith 		}
385b5aec950SSujith 	}
386b5aec950SSujith 
387b5aec950SSujith 	numXpdGain = 0;
38816c94ac6SSujith 
389a55f8588SSujith 	/* Calculate the value of xpdgains from the xpdGain Mask */
3904ddfcd7dSFelix Fietkau 	for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) {
3914ddfcd7dSFelix Fietkau 		if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) {
3924ddfcd7dSFelix Fietkau 			if (numXpdGain >= AR5416_NUM_PD_GAINS)
393b5aec950SSujith 				break;
394b5aec950SSujith 			xpdGainValues[numXpdGain] =
3954ddfcd7dSFelix Fietkau 				(u16)(AR5416_PD_GAINS_IN_MASK-i);
396b5aec950SSujith 			numXpdGain++;
397b5aec950SSujith 		}
398b5aec950SSujith 	}
399b5aec950SSujith 
400b5aec950SSujith 	REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN,
401b5aec950SSujith 		      (numXpdGain - 1) & 0x3);
402b5aec950SSujith 	REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1,
403b5aec950SSujith 		      xpdGainValues[0]);
404b5aec950SSujith 	REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2,
405b5aec950SSujith 		      xpdGainValues[1]);
406b5aec950SSujith 	REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3,
407b5aec950SSujith 		      xpdGainValues[2]);
408b5aec950SSujith 
409b5aec950SSujith 	for (i = 0; i < AR9287_MAX_CHAINS; i++)	{
410b5aec950SSujith 		regChainOffset = i * 0x1000;
411a55f8588SSujith 
412b5aec950SSujith 		if (pEepData->baseEepHeader.txMask & (1 << i)) {
413a55f8588SSujith 			pRawDatasetOpenLoop =
414a55f8588SSujith 			(struct cal_data_op_loop_ar9287 *)pEepData->calPierData2G[i];
415a55f8588SSujith 
41616c94ac6SSujith 			if (ath9k_hw_ar9287_get_eeprom(ah, EEP_OL_PWRCTRL)) {
417b5aec950SSujith 				int8_t txPower;
418b5aec950SSujith 				ar9287_eeprom_get_tx_gain_index(ah, chan,
419b5aec950SSujith 							pRawDatasetOpenLoop,
420b5aec950SSujith 							pCalBChans, numPiers,
421b5aec950SSujith 							&txPower);
422b5aec950SSujith 				ar9287_eeprom_olpc_set_pdadcs(ah, txPower, i);
423b5aec950SSujith 			} else {
424b5aec950SSujith 				pRawDataset =
425b5aec950SSujith 					(struct cal_data_per_freq_ar9287 *)
426b5aec950SSujith 					pEepData->calPierData2G[i];
427a55f8588SSujith 
428940cd2c1SFelix Fietkau 				ath9k_hw_get_gain_boundaries_pdadcs(ah, chan,
429a55f8588SSujith 							   pRawDataset,
430b5aec950SSujith 							   pCalBChans, numPiers,
431b5aec950SSujith 							   pdGainOverlap_t2,
432a55f8588SSujith 							   gainBoundaries,
433a55f8588SSujith 							   pdadcValues,
434a55f8588SSujith 							   numXpdGain);
435b5aec950SSujith 			}
436b5aec950SSujith 
437e7fc6338SRajkumar Manoharan 			ENABLE_REGWRITE_BUFFER(ah);
438e7fc6338SRajkumar Manoharan 
439b5aec950SSujith 			if (i == 0) {
440a55f8588SSujith 				if (!ath9k_hw_ar9287_get_eeprom(ah,
441a55f8588SSujith 							EEP_OL_PWRCTRL)) {
442a55f8588SSujith 
443a55f8588SSujith 					regval = SM(pdGainOverlap_t2,
444a55f8588SSujith 						    AR_PHY_TPCRG5_PD_GAIN_OVERLAP)
445a55f8588SSujith 						| SM(gainBoundaries[0],
446b5aec950SSujith 						     AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1)
447b5aec950SSujith 						| SM(gainBoundaries[1],
448b5aec950SSujith 						     AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2)
449b5aec950SSujith 						| SM(gainBoundaries[2],
450b5aec950SSujith 						     AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3)
451b5aec950SSujith 						| SM(gainBoundaries[3],
452a55f8588SSujith 						     AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4);
453a55f8588SSujith 
454a55f8588SSujith 					REG_WRITE(ah,
455a55f8588SSujith 						  AR_PHY_TPCRG5 + regChainOffset,
456a55f8588SSujith 						  regval);
457b5aec950SSujith 				}
458b5aec950SSujith 			}
459b5aec950SSujith 
460b5aec950SSujith 			if ((int32_t)AR9287_PWR_TABLE_OFFSET_DB !=
461b5aec950SSujith 			    pEepData->baseEepHeader.pwrTableOffset) {
462a55f8588SSujith 				diff = (u16)(pEepData->baseEepHeader.pwrTableOffset -
463a55f8588SSujith 					     (int32_t)AR9287_PWR_TABLE_OFFSET_DB);
464b5aec950SSujith 				diff *= 2;
465b5aec950SSujith 
4664ddfcd7dSFelix Fietkau 				for (j = 0; j < ((u16)AR5416_NUM_PDADC_VALUES-diff); j++)
467b5aec950SSujith 					pdadcValues[j] = pdadcValues[j+diff];
468b5aec950SSujith 
4694ddfcd7dSFelix Fietkau 				for (j = (u16)(AR5416_NUM_PDADC_VALUES-diff);
4704ddfcd7dSFelix Fietkau 				     j < AR5416_NUM_PDADC_VALUES; j++)
471b5aec950SSujith 					pdadcValues[j] =
4724ddfcd7dSFelix Fietkau 					  pdadcValues[AR5416_NUM_PDADC_VALUES-diff];
473b5aec950SSujith 			}
474b5aec950SSujith 
47516c94ac6SSujith 			if (!ath9k_hw_ar9287_get_eeprom(ah, EEP_OL_PWRCTRL)) {
476a55f8588SSujith 				regOffset = AR_PHY_BASE +
477a55f8588SSujith 					(672 << 2) + regChainOffset;
478a55f8588SSujith 
479b5aec950SSujith 				for (j = 0; j < 32; j++) {
48078fa99abSPavel Roskin 					reg32 = get_unaligned_le32(&pdadcValues[4 * j]);
481a55f8588SSujith 
482b5aec950SSujith 					REG_WRITE(ah, regOffset, reg32);
483b5aec950SSujith 					regOffset += 4;
484b5aec950SSujith 				}
485b5aec950SSujith 			}
486e7fc6338SRajkumar Manoharan 			REGWRITE_BUFFER_FLUSH(ah);
487b5aec950SSujith 		}
488b5aec950SSujith 	}
489b5aec950SSujith }
490b5aec950SSujith 
ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw * ah,struct ath9k_channel * chan,int16_t * ratesArray,u16 cfgCtl,u16 antenna_reduction,u16 powerLimit)49116c94ac6SSujith static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah,
49216c94ac6SSujith 						     struct ath9k_channel *chan,
49316c94ac6SSujith 						     int16_t *ratesArray,
49416c94ac6SSujith 						     u16 cfgCtl,
495ca2c68ccSFelix Fietkau 						     u16 antenna_reduction,
496b5aec950SSujith 						     u16 powerLimit)
497b5aec950SSujith {
498a55f8588SSujith #define CMP_CTL \
499a55f8588SSujith 	(((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == \
500a55f8588SSujith 	 pEepData->ctlIndex[i])
501a55f8588SSujith 
502a55f8588SSujith #define CMP_NO_CTL \
503a55f8588SSujith 	(((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == \
504a55f8588SSujith 	 ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL))
505a55f8588SSujith 
506a261f0e9SRajkumar Manoharan 	u16 twiceMaxEdgePower;
507b5aec950SSujith 	int i;
508b5aec950SSujith 	struct cal_ctl_data_ar9287 *rep;
509b5aec950SSujith 	struct cal_target_power_leg targetPowerOfdm = {0, {0, 0, 0, 0} },
510b5aec950SSujith 				    targetPowerCck = {0, {0, 0, 0, 0} };
511b5aec950SSujith 	struct cal_target_power_leg targetPowerOfdmExt = {0, {0, 0, 0, 0} },
512b5aec950SSujith 				    targetPowerCckExt = {0, {0, 0, 0, 0} };
513b5aec950SSujith 	struct cal_target_power_ht targetPowerHt20,
514b5aec950SSujith 				    targetPowerHt40 = {0, {0, 0, 0, 0} };
515ca2c68ccSFelix Fietkau 	u16 scaledPower = 0, minCtlPower;
51607b2fa5aSJoe Perches 	static const u16 ctlModesFor11g[] = {
51707b2fa5aSJoe Perches 		CTL_11B, CTL_11G, CTL_2GHT20,
51807b2fa5aSJoe Perches 		CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40
51907b2fa5aSJoe Perches 	};
52007b2fa5aSJoe Perches 	u16 numCtlModes = 0;
52107b2fa5aSJoe Perches 	const u16 *pCtlMode = NULL;
52207b2fa5aSJoe Perches 	u16 ctlMode, freq;
523b5aec950SSujith 	struct chan_centers centers;
524b5aec950SSujith 	int tx_chainmask;
525b5aec950SSujith 	u16 twiceMinEdgePower;
526b5aec950SSujith 	struct ar9287_eeprom *pEepData = &ah->eeprom.map9287;
527b5aec950SSujith 	tx_chainmask = ah->txchainmask;
528b5aec950SSujith 
529b5aec950SSujith 	ath9k_hw_get_channel_centers(ah, chan, &centers);
530ea6f792bSGabor Juhos 	scaledPower = ath9k_hw_get_scaled_power(ah, powerLimit,
531ea6f792bSGabor Juhos 						antenna_reduction);
532b5aec950SSujith 
533a55f8588SSujith 	/*
534a55f8588SSujith 	 * Get TX power from EEPROM.
535a55f8588SSujith 	 */
536b5aec950SSujith 	if (IS_CHAN_2GHZ(chan))	{
537a55f8588SSujith 		/* CTL_11B, CTL_11G, CTL_2GHT20 */
538b5aec950SSujith 		numCtlModes =
539b5aec950SSujith 			ARRAY_SIZE(ctlModesFor11g) - SUB_NUM_CTL_MODES_AT_2G_40;
54016c94ac6SSujith 
541b5aec950SSujith 		pCtlMode = ctlModesFor11g;
542b5aec950SSujith 
543b5aec950SSujith 		ath9k_hw_get_legacy_target_powers(ah, chan,
544b5aec950SSujith 						  pEepData->calTargetPowerCck,
545b5aec950SSujith 						  AR9287_NUM_2G_CCK_TARGET_POWERS,
546b5aec950SSujith 						  &targetPowerCck, 4, false);
547b5aec950SSujith 		ath9k_hw_get_legacy_target_powers(ah, chan,
548b5aec950SSujith 						  pEepData->calTargetPower2G,
549b5aec950SSujith 						  AR9287_NUM_2G_20_TARGET_POWERS,
550b5aec950SSujith 						  &targetPowerOfdm, 4, false);
551b5aec950SSujith 		ath9k_hw_get_target_powers(ah, chan,
552b5aec950SSujith 					   pEepData->calTargetPower2GHT20,
553b5aec950SSujith 					   AR9287_NUM_2G_20_TARGET_POWERS,
554b5aec950SSujith 					   &targetPowerHt20, 8, false);
555b5aec950SSujith 
556b5aec950SSujith 		if (IS_CHAN_HT40(chan))	{
557a55f8588SSujith 			/* All 2G CTLs */
558b5aec950SSujith 			numCtlModes = ARRAY_SIZE(ctlModesFor11g);
559b5aec950SSujith 			ath9k_hw_get_target_powers(ah, chan,
560b5aec950SSujith 						   pEepData->calTargetPower2GHT40,
561b5aec950SSujith 						   AR9287_NUM_2G_40_TARGET_POWERS,
562b5aec950SSujith 						   &targetPowerHt40, 8, true);
563b5aec950SSujith 			ath9k_hw_get_legacy_target_powers(ah, chan,
564b5aec950SSujith 						  pEepData->calTargetPowerCck,
565b5aec950SSujith 						  AR9287_NUM_2G_CCK_TARGET_POWERS,
566b5aec950SSujith 						  &targetPowerCckExt, 4, true);
567b5aec950SSujith 			ath9k_hw_get_legacy_target_powers(ah, chan,
568b5aec950SSujith 						  pEepData->calTargetPower2G,
569b5aec950SSujith 						  AR9287_NUM_2G_20_TARGET_POWERS,
570b5aec950SSujith 						  &targetPowerOfdmExt, 4, true);
571b5aec950SSujith 		}
572b5aec950SSujith 	}
573b5aec950SSujith 
574b5aec950SSujith 	for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) {
575*b2fd72aaSRuan Jinjie 		bool isHt40CtlMode = pCtlMode[ctlMode] == CTL_2GHT40;
576a55f8588SSujith 
577b5aec950SSujith 		if (isHt40CtlMode)
578b5aec950SSujith 			freq = centers.synth_center;
579b5aec950SSujith 		else if (pCtlMode[ctlMode] & EXT_ADDITIVE)
580b5aec950SSujith 			freq = centers.ext_center;
581b5aec950SSujith 		else
582b5aec950SSujith 			freq = centers.ctl_center;
583b5aec950SSujith 
584a261f0e9SRajkumar Manoharan 		twiceMaxEdgePower = MAX_RATE_POWER;
585a55f8588SSujith 		/* Walk through the CTL indices stored in EEPROM */
586b5aec950SSujith 		for (i = 0; (i < AR9287_NUM_CTLS) && pEepData->ctlIndex[i]; i++) {
587a55f8588SSujith 			struct cal_ctl_edges *pRdEdgesPower;
588b5aec950SSujith 
589a55f8588SSujith 			/*
590a55f8588SSujith 			 * Compare test group from regulatory channel list
591a55f8588SSujith 			 * with test mode from pCtlMode list
592a55f8588SSujith 			 */
593a55f8588SSujith 			if (CMP_CTL || CMP_NO_CTL) {
594b5aec950SSujith 				rep = &(pEepData->ctlData[i]);
595a55f8588SSujith 				pRdEdgesPower =
596a55f8588SSujith 				rep->ctlEdges[ar5416_get_ntxchains(tx_chainmask) - 1];
597b5aec950SSujith 
598a55f8588SSujith 				twiceMinEdgePower = ath9k_hw_get_max_edge_power(freq,
599a55f8588SSujith 								pRdEdgesPower,
600a55f8588SSujith 								IS_CHAN_2GHZ(chan),
601a55f8588SSujith 								AR5416_NUM_BAND_EDGES);
602a55f8588SSujith 
603a55f8588SSujith 				if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) {
604a55f8588SSujith 					twiceMaxEdgePower = min(twiceMaxEdgePower,
605b5aec950SSujith 								twiceMinEdgePower);
606a55f8588SSujith 				} else {
607b5aec950SSujith 					twiceMaxEdgePower = twiceMinEdgePower;
608b5aec950SSujith 					break;
609b5aec950SSujith 				}
610b5aec950SSujith 			}
611b5aec950SSujith 		}
612b5aec950SSujith 
613b5aec950SSujith 		minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower);
614b5aec950SSujith 
615a55f8588SSujith 		/* Apply ctl mode to correct target power set */
616b5aec950SSujith 		switch (pCtlMode[ctlMode]) {
617b5aec950SSujith 		case CTL_11B:
618a55f8588SSujith 			for (i = 0; i < ARRAY_SIZE(targetPowerCck.tPow2x); i++) {
619a55f8588SSujith 				targetPowerCck.tPow2x[i] =
620a55f8588SSujith 					(u8)min((u16)targetPowerCck.tPow2x[i],
621b5aec950SSujith 						minCtlPower);
622b5aec950SSujith 			}
623b5aec950SSujith 			break;
624b5aec950SSujith 		case CTL_11A:
625b5aec950SSujith 		case CTL_11G:
626a55f8588SSujith 			for (i = 0; i < ARRAY_SIZE(targetPowerOfdm.tPow2x); i++) {
627a55f8588SSujith 				targetPowerOfdm.tPow2x[i] =
628a55f8588SSujith 					(u8)min((u16)targetPowerOfdm.tPow2x[i],
629b5aec950SSujith 						minCtlPower);
630b5aec950SSujith 			}
631b5aec950SSujith 			break;
632b5aec950SSujith 		case CTL_5GHT20:
633b5aec950SSujith 		case CTL_2GHT20:
634a55f8588SSujith 			for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++) {
635a55f8588SSujith 				targetPowerHt20.tPow2x[i] =
636a55f8588SSujith 					(u8)min((u16)targetPowerHt20.tPow2x[i],
637b5aec950SSujith 						minCtlPower);
638b5aec950SSujith 			}
639b5aec950SSujith 			break;
640b5aec950SSujith 		case CTL_11B_EXT:
641a55f8588SSujith 			targetPowerCckExt.tPow2x[0] =
642a55f8588SSujith 				(u8)min((u16)targetPowerCckExt.tPow2x[0],
643b5aec950SSujith 					minCtlPower);
644b5aec950SSujith 			break;
645b5aec950SSujith 		case CTL_11A_EXT:
646b5aec950SSujith 		case CTL_11G_EXT:
647a55f8588SSujith 			targetPowerOfdmExt.tPow2x[0] =
648a55f8588SSujith 				(u8)min((u16)targetPowerOfdmExt.tPow2x[0],
649b5aec950SSujith 					minCtlPower);
650b5aec950SSujith 			break;
651b5aec950SSujith 		case CTL_5GHT40:
652b5aec950SSujith 		case CTL_2GHT40:
653a55f8588SSujith 			for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {
654a55f8588SSujith 				targetPowerHt40.tPow2x[i] =
655a55f8588SSujith 					(u8)min((u16)targetPowerHt40.tPow2x[i],
656b5aec950SSujith 						minCtlPower);
657b5aec950SSujith 			}
658b5aec950SSujith 			break;
659b5aec950SSujith 		default:
660b5aec950SSujith 			break;
661b5aec950SSujith 		}
662b5aec950SSujith 	}
663b5aec950SSujith 
664a55f8588SSujith 	/* Now set the rates array */
665a55f8588SSujith 
666b5aec950SSujith 	ratesArray[rate6mb] =
667b5aec950SSujith 	ratesArray[rate9mb] =
668b5aec950SSujith 	ratesArray[rate12mb] =
669b5aec950SSujith 	ratesArray[rate18mb] =
670a55f8588SSujith 	ratesArray[rate24mb] = targetPowerOfdm.tPow2x[0];
671b5aec950SSujith 
672b5aec950SSujith 	ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1];
673b5aec950SSujith 	ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2];
674b5aec950SSujith 	ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3];
675b5aec950SSujith 	ratesArray[rateXr] = targetPowerOfdm.tPow2x[0];
676b5aec950SSujith 
677b5aec950SSujith 	for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++)
678b5aec950SSujith 		ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i];
679b5aec950SSujith 
680b5aec950SSujith 	if (IS_CHAN_2GHZ(chan))	{
681b5aec950SSujith 		ratesArray[rate1l] = targetPowerCck.tPow2x[0];
682a55f8588SSujith 		ratesArray[rate2s] =
683a55f8588SSujith 		ratesArray[rate2l] = targetPowerCck.tPow2x[1];
684a55f8588SSujith 		ratesArray[rate5_5s] =
685a55f8588SSujith 		ratesArray[rate5_5l] = targetPowerCck.tPow2x[2];
686a55f8588SSujith 		ratesArray[rate11s] =
687a55f8588SSujith 		ratesArray[rate11l] = targetPowerCck.tPow2x[3];
688b5aec950SSujith 	}
689b5aec950SSujith 	if (IS_CHAN_HT40(chan))	{
690b5aec950SSujith 		for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++)
691b5aec950SSujith 			ratesArray[rateHt40_0 + i] = targetPowerHt40.tPow2x[i];
692b5aec950SSujith 
693b5aec950SSujith 		ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0];
694b5aec950SSujith 		ratesArray[rateDupCck]  = targetPowerHt40.tPow2x[0];
695b5aec950SSujith 		ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0];
696a55f8588SSujith 
697b5aec950SSujith 		if (IS_CHAN_2GHZ(chan))
698b5aec950SSujith 			ratesArray[rateExtCck] = targetPowerCckExt.tPow2x[0];
699b5aec950SSujith 	}
700b5aec950SSujith 
701a55f8588SSujith #undef CMP_CTL
702a55f8588SSujith #undef CMP_NO_CTL
703b5aec950SSujith }
704b5aec950SSujith 
ath9k_hw_ar9287_set_txpower(struct ath_hw * ah,struct ath9k_channel * chan,u16 cfgCtl,u8 twiceAntennaReduction,u8 powerLimit,bool test)70516c94ac6SSujith static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah,
706b5aec950SSujith 					struct ath9k_channel *chan, u16 cfgCtl,
707b5aec950SSujith 					u8 twiceAntennaReduction,
708de40f316SFelix Fietkau 					u8 powerLimit, bool test)
709b5aec950SSujith {
710608b88cbSLuis R. Rodriguez 	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
711b5aec950SSujith 	struct ar9287_eeprom *pEepData = &ah->eeprom.map9287;
712b5aec950SSujith 	struct modal_eep_ar9287_header *pModal = &pEepData->modalHeader;
713b5aec950SSujith 	int16_t ratesArray[Ar5416RateSize];
714b5aec950SSujith 	u8 ht40PowerIncForPdadc = 2;
715b5aec950SSujith 	int i;
716b5aec950SSujith 
717b5aec950SSujith 	memset(ratesArray, 0, sizeof(ratesArray));
718b5aec950SSujith 
7199bff7428SMartin Blumenstingl 	if (ath9k_hw_ar9287_get_eeprom_rev(ah) >= AR9287_EEP_MINOR_VER_2)
720b5aec950SSujith 		ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
721b5aec950SSujith 
72216c94ac6SSujith 	ath9k_hw_set_ar9287_power_per_rate_table(ah, chan,
723b5aec950SSujith 						 &ratesArray[0], cfgCtl,
724b5aec950SSujith 						 twiceAntennaReduction,
725b5aec950SSujith 						 powerLimit);
726b5aec950SSujith 
727e832bf10SFelix Fietkau 	ath9k_hw_set_ar9287_power_cal_table(ah, chan);
728b5aec950SSujith 
729de40f316SFelix Fietkau 	regulatory->max_power_level = 0;
730b5aec950SSujith 	for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
7314ddfcd7dSFelix Fietkau 		if (ratesArray[i] > MAX_RATE_POWER)
7324ddfcd7dSFelix Fietkau 			ratesArray[i] = MAX_RATE_POWER;
733de40f316SFelix Fietkau 
734de40f316SFelix Fietkau 		if (ratesArray[i] > regulatory->max_power_level)
735de40f316SFelix Fietkau 			regulatory->max_power_level = ratesArray[i];
736b5aec950SSujith 	}
737b5aec950SSujith 
73883722bd4SGabor Juhos 	ath9k_hw_update_regulatory_maxpower(ah);
73983722bd4SGabor Juhos 
740de40f316SFelix Fietkau 	if (test)
741de40f316SFelix Fietkau 		return;
742de40f316SFelix Fietkau 
743b5aec950SSujith 	for (i = 0; i < Ar5416RateSize; i++)
744b5aec950SSujith 		ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2;
745b5aec950SSujith 
746e7fc6338SRajkumar Manoharan 	ENABLE_REGWRITE_BUFFER(ah);
747e7fc6338SRajkumar Manoharan 
748a55f8588SSujith 	/* OFDM power per rate */
749b5aec950SSujith 	REG_WRITE(ah, AR_PHY_POWER_TX_RATE1,
750b5aec950SSujith 		  ATH9K_POW_SM(ratesArray[rate18mb], 24)
751b5aec950SSujith 		  | ATH9K_POW_SM(ratesArray[rate12mb], 16)
752b5aec950SSujith 		  | ATH9K_POW_SM(ratesArray[rate9mb], 8)
753b5aec950SSujith 		  | ATH9K_POW_SM(ratesArray[rate6mb], 0));
754b5aec950SSujith 
755b5aec950SSujith 	REG_WRITE(ah, AR_PHY_POWER_TX_RATE2,
756b5aec950SSujith 		  ATH9K_POW_SM(ratesArray[rate54mb], 24)
757b5aec950SSujith 		  | ATH9K_POW_SM(ratesArray[rate48mb], 16)
758b5aec950SSujith 		  | ATH9K_POW_SM(ratesArray[rate36mb], 8)
759b5aec950SSujith 		  | ATH9K_POW_SM(ratesArray[rate24mb], 0));
760b5aec950SSujith 
761a55f8588SSujith 	/* CCK power per rate */
762b5aec950SSujith 	if (IS_CHAN_2GHZ(chan))	{
763b5aec950SSujith 		REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
764b5aec950SSujith 			  ATH9K_POW_SM(ratesArray[rate2s], 24)
765b5aec950SSujith 			  | ATH9K_POW_SM(ratesArray[rate2l], 16)
766b5aec950SSujith 			  | ATH9K_POW_SM(ratesArray[rateXr], 8)
767b5aec950SSujith 			  | ATH9K_POW_SM(ratesArray[rate1l], 0));
768b5aec950SSujith 		REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
769b5aec950SSujith 			  ATH9K_POW_SM(ratesArray[rate11s], 24)
770b5aec950SSujith 			  | ATH9K_POW_SM(ratesArray[rate11l], 16)
771b5aec950SSujith 			  | ATH9K_POW_SM(ratesArray[rate5_5s], 8)
772b5aec950SSujith 			  | ATH9K_POW_SM(ratesArray[rate5_5l], 0));
773b5aec950SSujith 	}
774b5aec950SSujith 
775a55f8588SSujith 	/* HT20 power per rate */
776b5aec950SSujith 	REG_WRITE(ah, AR_PHY_POWER_TX_RATE5,
777b5aec950SSujith 		  ATH9K_POW_SM(ratesArray[rateHt20_3], 24)
778b5aec950SSujith 		  | ATH9K_POW_SM(ratesArray[rateHt20_2], 16)
779b5aec950SSujith 		  | ATH9K_POW_SM(ratesArray[rateHt20_1], 8)
780b5aec950SSujith 		  | ATH9K_POW_SM(ratesArray[rateHt20_0], 0));
781b5aec950SSujith 
782b5aec950SSujith 	REG_WRITE(ah, AR_PHY_POWER_TX_RATE6,
783b5aec950SSujith 		  ATH9K_POW_SM(ratesArray[rateHt20_7], 24)
784b5aec950SSujith 		  | ATH9K_POW_SM(ratesArray[rateHt20_6], 16)
785b5aec950SSujith 		  | ATH9K_POW_SM(ratesArray[rateHt20_5], 8)
786b5aec950SSujith 		  | ATH9K_POW_SM(ratesArray[rateHt20_4], 0));
787b5aec950SSujith 
788a55f8588SSujith 	/* HT40 power per rate */
789b5aec950SSujith 	if (IS_CHAN_HT40(chan))	{
79016c94ac6SSujith 		if (ath9k_hw_ar9287_get_eeprom(ah, EEP_OL_PWRCTRL)) {
791b5aec950SSujith 			REG_WRITE(ah, AR_PHY_POWER_TX_RATE7,
792b5aec950SSujith 				  ATH9K_POW_SM(ratesArray[rateHt40_3], 24)
793b5aec950SSujith 				  | ATH9K_POW_SM(ratesArray[rateHt40_2], 16)
794b5aec950SSujith 				  | ATH9K_POW_SM(ratesArray[rateHt40_1], 8)
795b5aec950SSujith 				  | ATH9K_POW_SM(ratesArray[rateHt40_0], 0));
796b5aec950SSujith 
797b5aec950SSujith 			REG_WRITE(ah, AR_PHY_POWER_TX_RATE8,
798b5aec950SSujith 				  ATH9K_POW_SM(ratesArray[rateHt40_7], 24)
799b5aec950SSujith 				  | ATH9K_POW_SM(ratesArray[rateHt40_6], 16)
800b5aec950SSujith 				  | ATH9K_POW_SM(ratesArray[rateHt40_5], 8)
801b5aec950SSujith 				  | ATH9K_POW_SM(ratesArray[rateHt40_4], 0));
802b5aec950SSujith 		} else {
803b5aec950SSujith 			REG_WRITE(ah, AR_PHY_POWER_TX_RATE7,
804b5aec950SSujith 				  ATH9K_POW_SM(ratesArray[rateHt40_3] +
805b5aec950SSujith 					       ht40PowerIncForPdadc, 24)
806b5aec950SSujith 				  | ATH9K_POW_SM(ratesArray[rateHt40_2] +
807b5aec950SSujith 						 ht40PowerIncForPdadc, 16)
808b5aec950SSujith 				  | ATH9K_POW_SM(ratesArray[rateHt40_1] +
809b5aec950SSujith 						 ht40PowerIncForPdadc, 8)
810b5aec950SSujith 				  | ATH9K_POW_SM(ratesArray[rateHt40_0] +
811b5aec950SSujith 						 ht40PowerIncForPdadc, 0));
812b5aec950SSujith 
813b5aec950SSujith 			REG_WRITE(ah, AR_PHY_POWER_TX_RATE8,
814b5aec950SSujith 				  ATH9K_POW_SM(ratesArray[rateHt40_7] +
815b5aec950SSujith 					       ht40PowerIncForPdadc, 24)
816b5aec950SSujith 				  | ATH9K_POW_SM(ratesArray[rateHt40_6] +
817b5aec950SSujith 						 ht40PowerIncForPdadc, 16)
818b5aec950SSujith 				  | ATH9K_POW_SM(ratesArray[rateHt40_5] +
819b5aec950SSujith 						 ht40PowerIncForPdadc, 8)
820b5aec950SSujith 				  | ATH9K_POW_SM(ratesArray[rateHt40_4] +
821b5aec950SSujith 						 ht40PowerIncForPdadc, 0));
822b5aec950SSujith 		}
823b5aec950SSujith 
824a55f8588SSujith 		/* Dup/Ext power per rate */
825b5aec950SSujith 		REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
826b5aec950SSujith 			  ATH9K_POW_SM(ratesArray[rateExtOfdm], 24)
827b5aec950SSujith 			  | ATH9K_POW_SM(ratesArray[rateExtCck], 16)
828b5aec950SSujith 			  | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
829b5aec950SSujith 			  | ATH9K_POW_SM(ratesArray[rateDupCck], 0));
830b5aec950SSujith 	}
831c08267dcSLorenzo Bianconi 
832c08267dcSLorenzo Bianconi 	/* TPC initializations */
833c08267dcSLorenzo Bianconi 	if (ah->tpc_enabled) {
834c08267dcSLorenzo Bianconi 		int ht40_delta;
835c08267dcSLorenzo Bianconi 
836c08267dcSLorenzo Bianconi 		ht40_delta = (IS_CHAN_HT40(chan)) ? ht40PowerIncForPdadc : 0;
837c08267dcSLorenzo Bianconi 		ar5008_hw_init_rate_txpower(ah, ratesArray, chan, ht40_delta);
838c08267dcSLorenzo Bianconi 		/* Enable TPC */
839c08267dcSLorenzo Bianconi 		REG_WRITE(ah, AR_PHY_POWER_TX_RATE_MAX,
840c08267dcSLorenzo Bianconi 			MAX_RATE_POWER | AR_PHY_POWER_TX_RATE_MAX_TPC_ENABLE);
841c08267dcSLorenzo Bianconi 	} else {
842c08267dcSLorenzo Bianconi 		/* Disable TPC */
843c08267dcSLorenzo Bianconi 		REG_WRITE(ah, AR_PHY_POWER_TX_RATE_MAX, MAX_RATE_POWER);
844c08267dcSLorenzo Bianconi 	}
845c08267dcSLorenzo Bianconi 
846e7fc6338SRajkumar Manoharan 	REGWRITE_BUFFER_FLUSH(ah);
847b5aec950SSujith }
848b5aec950SSujith 
ath9k_hw_ar9287_set_board_values(struct ath_hw * ah,struct ath9k_channel * chan)84916c94ac6SSujith static void ath9k_hw_ar9287_set_board_values(struct ath_hw *ah,
850b5aec950SSujith 					     struct ath9k_channel *chan)
851b5aec950SSujith {
852b5aec950SSujith 	struct ar9287_eeprom *eep = &ah->eeprom.map9287;
853b5aec950SSujith 	struct modal_eep_ar9287_header *pModal = &eep->modalHeader;
85479d7f4bcSSujith 	u32 regChainOffset, regval;
855b5aec950SSujith 	u8 txRxAttenLocal;
8562d05a0c2SRajkumar Manoharan 	int i;
857b5aec950SSujith 
858b5aec950SSujith 	pModal = &eep->modalHeader;
859b5aec950SSujith 
8604bca5303SMartin Blumenstingl 	REG_WRITE(ah, AR_PHY_SWITCH_COM, le32_to_cpu(pModal->antCtrlCommon));
861b5aec950SSujith 
862b5aec950SSujith 	for (i = 0; i < AR9287_MAX_CHAINS; i++)	{
863b5aec950SSujith 		regChainOffset = i * 0x1000;
864b5aec950SSujith 
865b5aec950SSujith 		REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset,
8664bca5303SMartin Blumenstingl 			  le32_to_cpu(pModal->antCtrlChain[i]));
867b5aec950SSujith 
868b5aec950SSujith 		REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset,
869b5aec950SSujith 			  (REG_READ(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset)
870b5aec950SSujith 			   & ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF |
871b5aec950SSujith 			       AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) |
872b5aec950SSujith 			  SM(pModal->iqCalICh[i],
873b5aec950SSujith 			     AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) |
874b5aec950SSujith 			  SM(pModal->iqCalQCh[i],
875b5aec950SSujith 			     AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF));
876b5aec950SSujith 
877b5aec950SSujith 		txRxAttenLocal = pModal->txRxAttenCh[i];
878b5aec950SSujith 
879b5aec950SSujith 		REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
880b5aec950SSujith 			      AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN,
881b5aec950SSujith 			      pModal->bswMargin[i]);
882b5aec950SSujith 		REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
883b5aec950SSujith 			      AR_PHY_GAIN_2GHZ_XATTEN1_DB,
884b5aec950SSujith 			      pModal->bswAtten[i]);
885b5aec950SSujith 		REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset,
886b5aec950SSujith 			      AR9280_PHY_RXGAIN_TXRX_ATTEN,
887b5aec950SSujith 			      txRxAttenLocal);
888b5aec950SSujith 		REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset,
889b5aec950SSujith 			      AR9280_PHY_RXGAIN_TXRX_MARGIN,
890b5aec950SSujith 			      pModal->rxTxMarginCh[i]);
891b5aec950SSujith 	}
892b5aec950SSujith 
893b5aec950SSujith 
894b5aec950SSujith 	if (IS_CHAN_HT40(chan))
895b5aec950SSujith 		REG_RMW_FIELD(ah, AR_PHY_SETTLING,
896b5aec950SSujith 			      AR_PHY_SETTLING_SWITCH, pModal->swSettleHt40);
897b5aec950SSujith 	else
898b5aec950SSujith 		REG_RMW_FIELD(ah, AR_PHY_SETTLING,
899b5aec950SSujith 			      AR_PHY_SETTLING_SWITCH, pModal->switchSettling);
900b5aec950SSujith 
901b5aec950SSujith 	REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
902b5aec950SSujith 		      AR_PHY_DESIRED_SZ_ADC, pModal->adcDesiredSize);
903b5aec950SSujith 
904b5aec950SSujith 	REG_WRITE(ah, AR_PHY_RF_CTL4,
905b5aec950SSujith 		  SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF)
906b5aec950SSujith 		  | SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAB_OFF)
907b5aec950SSujith 		  | SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAA_ON)
908b5aec950SSujith 		  | SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAB_ON));
909b5aec950SSujith 
910b5aec950SSujith 	REG_RMW_FIELD(ah, AR_PHY_RF_CTL3,
911b5aec950SSujith 		      AR_PHY_TX_END_TO_A2_RX_ON, pModal->txEndToRxOn);
912b5aec950SSujith 
913b5aec950SSujith 	REG_RMW_FIELD(ah, AR_PHY_CCA,
914b5aec950SSujith 		      AR9280_PHY_CCA_THRESH62, pModal->thresh62);
915b5aec950SSujith 	REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0,
916b5aec950SSujith 		      AR_PHY_EXT_CCA0_THRESH62, pModal->thresh62);
917b5aec950SSujith 
91879d7f4bcSSujith 	regval = REG_READ(ah, AR9287_AN_RF2G3_CH0);
91979d7f4bcSSujith 	regval &= ~(AR9287_AN_RF2G3_DB1 |
92079d7f4bcSSujith 		    AR9287_AN_RF2G3_DB2 |
92179d7f4bcSSujith 		    AR9287_AN_RF2G3_OB_CCK |
92279d7f4bcSSujith 		    AR9287_AN_RF2G3_OB_PSK |
92379d7f4bcSSujith 		    AR9287_AN_RF2G3_OB_QAM |
92479d7f4bcSSujith 		    AR9287_AN_RF2G3_OB_PAL_OFF);
92579d7f4bcSSujith 	regval |= (SM(pModal->db1, AR9287_AN_RF2G3_DB1) |
92679d7f4bcSSujith 		   SM(pModal->db2, AR9287_AN_RF2G3_DB2) |
92779d7f4bcSSujith 		   SM(pModal->ob_cck, AR9287_AN_RF2G3_OB_CCK) |
92879d7f4bcSSujith 		   SM(pModal->ob_psk, AR9287_AN_RF2G3_OB_PSK) |
92979d7f4bcSSujith 		   SM(pModal->ob_qam, AR9287_AN_RF2G3_OB_QAM) |
93079d7f4bcSSujith 		   SM(pModal->ob_pal_off, AR9287_AN_RF2G3_OB_PAL_OFF));
931b5aec950SSujith 
93279d7f4bcSSujith 	ath9k_hw_analog_shift_regwrite(ah, AR9287_AN_RF2G3_CH0, regval);
93379d7f4bcSSujith 
93479d7f4bcSSujith 	regval = REG_READ(ah, AR9287_AN_RF2G3_CH1);
93579d7f4bcSSujith 	regval &= ~(AR9287_AN_RF2G3_DB1 |
93679d7f4bcSSujith 		    AR9287_AN_RF2G3_DB2 |
93779d7f4bcSSujith 		    AR9287_AN_RF2G3_OB_CCK |
93879d7f4bcSSujith 		    AR9287_AN_RF2G3_OB_PSK |
93979d7f4bcSSujith 		    AR9287_AN_RF2G3_OB_QAM |
94079d7f4bcSSujith 		    AR9287_AN_RF2G3_OB_PAL_OFF);
94179d7f4bcSSujith 	regval |= (SM(pModal->db1, AR9287_AN_RF2G3_DB1) |
94279d7f4bcSSujith 		   SM(pModal->db2, AR9287_AN_RF2G3_DB2) |
94379d7f4bcSSujith 		   SM(pModal->ob_cck, AR9287_AN_RF2G3_OB_CCK) |
94479d7f4bcSSujith 		   SM(pModal->ob_psk, AR9287_AN_RF2G3_OB_PSK) |
94579d7f4bcSSujith 		   SM(pModal->ob_qam, AR9287_AN_RF2G3_OB_QAM) |
94679d7f4bcSSujith 		   SM(pModal->ob_pal_off, AR9287_AN_RF2G3_OB_PAL_OFF));
94779d7f4bcSSujith 
94879d7f4bcSSujith 	ath9k_hw_analog_shift_regwrite(ah, AR9287_AN_RF2G3_CH1, regval);
949b5aec950SSujith 
950b5aec950SSujith 	REG_RMW_FIELD(ah, AR_PHY_RF_CTL2,
951b5aec950SSujith 		      AR_PHY_TX_END_DATA_START, pModal->txFrameToDataStart);
952b5aec950SSujith 	REG_RMW_FIELD(ah, AR_PHY_RF_CTL2,
953b5aec950SSujith 		      AR_PHY_TX_END_PA_ON, pModal->txFrameToPaOn);
954b5aec950SSujith 
955b5aec950SSujith 	ath9k_hw_analog_shift_rmw(ah, AR9287_AN_TOP2,
956b5aec950SSujith 				  AR9287_AN_TOP2_XPABIAS_LVL,
957b5aec950SSujith 				  AR9287_AN_TOP2_XPABIAS_LVL_S,
958b5aec950SSujith 				  pModal->xpaBiasLvl);
959b5aec950SSujith }
960b5aec950SSujith 
ath9k_hw_ar9287_get_spur_channel(struct ath_hw * ah,u16 i,bool is2GHz)96116c94ac6SSujith static u16 ath9k_hw_ar9287_get_spur_channel(struct ath_hw *ah,
962b5aec950SSujith 					    u16 i, bool is2GHz)
963b5aec950SSujith {
9644bca5303SMartin Blumenstingl 	__le16 spur_ch = ah->eeprom.map9287.modalHeader.spurChans[i].spurChan;
9654bca5303SMartin Blumenstingl 
9664bca5303SMartin Blumenstingl 	return le16_to_cpu(spur_ch);
967b5aec950SSujith }
968b5aec950SSujith 
ath9k_hw_ar9287_get_eepmisc(struct ath_hw * ah)969d8ec2e2aSMartin Blumenstingl static u8 ath9k_hw_ar9287_get_eepmisc(struct ath_hw *ah)
970d8ec2e2aSMartin Blumenstingl {
971d8ec2e2aSMartin Blumenstingl 	return ah->eeprom.map9287.baseEepHeader.eepMisc;
972d8ec2e2aSMartin Blumenstingl }
973d8ec2e2aSMartin Blumenstingl 
9740b8f6f2bSLuis R. Rodriguez const struct eeprom_ops eep_ar9287_ops = {
97516c94ac6SSujith 	.check_eeprom		= ath9k_hw_ar9287_check_eeprom,
97616c94ac6SSujith 	.get_eeprom		= ath9k_hw_ar9287_get_eeprom,
97716c94ac6SSujith 	.fill_eeprom		= ath9k_hw_ar9287_fill_eeprom,
97849c99520SRajkumar Manoharan 	.dump_eeprom		= ath9k_hw_ar9287_dump_eeprom,
97916c94ac6SSujith 	.get_eeprom_ver		= ath9k_hw_ar9287_get_eeprom_ver,
98016c94ac6SSujith 	.get_eeprom_rev		= ath9k_hw_ar9287_get_eeprom_rev,
98116c94ac6SSujith 	.set_board_values	= ath9k_hw_ar9287_set_board_values,
98216c94ac6SSujith 	.set_txpower		= ath9k_hw_ar9287_set_txpower,
983d8ec2e2aSMartin Blumenstingl 	.get_spur_channel	= ath9k_hw_ar9287_get_spur_channel,
984d8ec2e2aSMartin Blumenstingl 	.get_eepmisc		= ath9k_hw_ar9287_get_eepmisc
985b5aec950SSujith };
986