18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * Copyright (c) 2008-2011 Atheros Communications Inc.
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * Permission to use, copy, modify, and/or distribute this software for any
58c2ecf20Sopenharmony_ci * purpose with or without fee is hereby granted, provided that the above
68c2ecf20Sopenharmony_ci * copyright notice and this permission notice appear in all copies.
78c2ecf20Sopenharmony_ci *
88c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
98c2ecf20Sopenharmony_ci * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
108c2ecf20Sopenharmony_ci * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
118c2ecf20Sopenharmony_ci * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
128c2ecf20Sopenharmony_ci * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
138c2ecf20Sopenharmony_ci * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
148c2ecf20Sopenharmony_ci * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
158c2ecf20Sopenharmony_ci */
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci#include "hw.h"
188c2ecf20Sopenharmony_ci#include <linux/ath9k_platform.h>
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_civoid ath9k_hw_analog_shift_regwrite(struct ath_hw *ah, u32 reg, u32 val)
218c2ecf20Sopenharmony_ci{
228c2ecf20Sopenharmony_ci        REG_WRITE(ah, reg, val);
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ci        if (ah->config.analog_shiftreg)
258c2ecf20Sopenharmony_ci		udelay(100);
268c2ecf20Sopenharmony_ci}
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_civoid ath9k_hw_analog_shift_rmw(struct ath_hw *ah, u32 reg, u32 mask,
298c2ecf20Sopenharmony_ci			       u32 shift, u32 val)
308c2ecf20Sopenharmony_ci{
318c2ecf20Sopenharmony_ci	REG_RMW(ah, reg, ((val << shift) & mask), mask);
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci	if (ah->config.analog_shiftreg)
348c2ecf20Sopenharmony_ci		udelay(100);
358c2ecf20Sopenharmony_ci}
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ciint16_t ath9k_hw_interpolate(u16 target, u16 srcLeft, u16 srcRight,
388c2ecf20Sopenharmony_ci			     int16_t targetLeft, int16_t targetRight)
398c2ecf20Sopenharmony_ci{
408c2ecf20Sopenharmony_ci	int16_t rv;
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci	if (srcRight == srcLeft) {
438c2ecf20Sopenharmony_ci		rv = targetLeft;
448c2ecf20Sopenharmony_ci	} else {
458c2ecf20Sopenharmony_ci		rv = (int16_t) (((target - srcLeft) * targetRight +
468c2ecf20Sopenharmony_ci				 (srcRight - target) * targetLeft) /
478c2ecf20Sopenharmony_ci				(srcRight - srcLeft));
488c2ecf20Sopenharmony_ci	}
498c2ecf20Sopenharmony_ci	return rv;
508c2ecf20Sopenharmony_ci}
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_cibool ath9k_hw_get_lower_upper_index(u8 target, u8 *pList, u16 listSize,
538c2ecf20Sopenharmony_ci				    u16 *indexL, u16 *indexR)
548c2ecf20Sopenharmony_ci{
558c2ecf20Sopenharmony_ci	u16 i;
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci	if (target <= pList[0]) {
588c2ecf20Sopenharmony_ci		*indexL = *indexR = 0;
598c2ecf20Sopenharmony_ci		return true;
608c2ecf20Sopenharmony_ci	}
618c2ecf20Sopenharmony_ci	if (target >= pList[listSize - 1]) {
628c2ecf20Sopenharmony_ci		*indexL = *indexR = (u16) (listSize - 1);
638c2ecf20Sopenharmony_ci		return true;
648c2ecf20Sopenharmony_ci	}
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci	for (i = 0; i < listSize - 1; i++) {
678c2ecf20Sopenharmony_ci		if (pList[i] == target) {
688c2ecf20Sopenharmony_ci			*indexL = *indexR = i;
698c2ecf20Sopenharmony_ci			return true;
708c2ecf20Sopenharmony_ci		}
718c2ecf20Sopenharmony_ci		if (target < pList[i + 1]) {
728c2ecf20Sopenharmony_ci			*indexL = i;
738c2ecf20Sopenharmony_ci			*indexR = (u16) (i + 1);
748c2ecf20Sopenharmony_ci			return false;
758c2ecf20Sopenharmony_ci		}
768c2ecf20Sopenharmony_ci	}
778c2ecf20Sopenharmony_ci	return false;
788c2ecf20Sopenharmony_ci}
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_civoid ath9k_hw_usb_gen_fill_eeprom(struct ath_hw *ah, u16 *eep_data,
818c2ecf20Sopenharmony_ci				  int eep_start_loc, int size)
828c2ecf20Sopenharmony_ci{
838c2ecf20Sopenharmony_ci	int i = 0, j, addr;
848c2ecf20Sopenharmony_ci	u32 addrdata[8];
858c2ecf20Sopenharmony_ci	u32 data[8];
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci	for (addr = 0; addr < size; addr++) {
888c2ecf20Sopenharmony_ci		addrdata[i] = AR5416_EEPROM_OFFSET +
898c2ecf20Sopenharmony_ci			((addr + eep_start_loc) << AR5416_EEPROM_S);
908c2ecf20Sopenharmony_ci		i++;
918c2ecf20Sopenharmony_ci		if (i == 8) {
928c2ecf20Sopenharmony_ci			REG_READ_MULTI(ah, addrdata, data, i);
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci			for (j = 0; j < i; j++) {
958c2ecf20Sopenharmony_ci				*eep_data = data[j];
968c2ecf20Sopenharmony_ci				eep_data++;
978c2ecf20Sopenharmony_ci			}
988c2ecf20Sopenharmony_ci			i = 0;
998c2ecf20Sopenharmony_ci		}
1008c2ecf20Sopenharmony_ci	}
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_ci	if (i != 0) {
1038c2ecf20Sopenharmony_ci		REG_READ_MULTI(ah, addrdata, data, i);
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ci		for (j = 0; j < i; j++) {
1068c2ecf20Sopenharmony_ci			*eep_data = data[j];
1078c2ecf20Sopenharmony_ci			eep_data++;
1088c2ecf20Sopenharmony_ci		}
1098c2ecf20Sopenharmony_ci	}
1108c2ecf20Sopenharmony_ci}
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_cistatic bool ath9k_hw_nvram_read_array(u16 *blob, size_t blob_size,
1138c2ecf20Sopenharmony_ci				      off_t offset, u16 *data)
1148c2ecf20Sopenharmony_ci{
1158c2ecf20Sopenharmony_ci	if (offset >= blob_size)
1168c2ecf20Sopenharmony_ci		return false;
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_ci	*data =  blob[offset];
1198c2ecf20Sopenharmony_ci	return true;
1208c2ecf20Sopenharmony_ci}
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_cistatic bool ath9k_hw_nvram_read_pdata(struct ath9k_platform_data *pdata,
1238c2ecf20Sopenharmony_ci				      off_t offset, u16 *data)
1248c2ecf20Sopenharmony_ci{
1258c2ecf20Sopenharmony_ci	return ath9k_hw_nvram_read_array(pdata->eeprom_data,
1268c2ecf20Sopenharmony_ci					 ARRAY_SIZE(pdata->eeprom_data),
1278c2ecf20Sopenharmony_ci					 offset, data);
1288c2ecf20Sopenharmony_ci}
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_cistatic bool ath9k_hw_nvram_read_firmware(const struct firmware *eeprom_blob,
1318c2ecf20Sopenharmony_ci					 off_t offset, u16 *data)
1328c2ecf20Sopenharmony_ci{
1338c2ecf20Sopenharmony_ci	return ath9k_hw_nvram_read_array((u16 *) eeprom_blob->data,
1348c2ecf20Sopenharmony_ci					 eeprom_blob->size / sizeof(u16),
1358c2ecf20Sopenharmony_ci					 offset, data);
1368c2ecf20Sopenharmony_ci}
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_cibool ath9k_hw_nvram_read(struct ath_hw *ah, u32 off, u16 *data)
1398c2ecf20Sopenharmony_ci{
1408c2ecf20Sopenharmony_ci	struct ath_common *common = ath9k_hw_common(ah);
1418c2ecf20Sopenharmony_ci	struct ath9k_platform_data *pdata = ah->dev->platform_data;
1428c2ecf20Sopenharmony_ci	bool ret;
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_ci	if (ah->eeprom_blob)
1458c2ecf20Sopenharmony_ci		ret = ath9k_hw_nvram_read_firmware(ah->eeprom_blob, off, data);
1468c2ecf20Sopenharmony_ci	else if (pdata && !pdata->use_eeprom)
1478c2ecf20Sopenharmony_ci		ret = ath9k_hw_nvram_read_pdata(pdata, off, data);
1488c2ecf20Sopenharmony_ci	else
1498c2ecf20Sopenharmony_ci		ret = common->bus_ops->eeprom_read(common, off, data);
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_ci	if (!ret)
1528c2ecf20Sopenharmony_ci		ath_dbg(common, EEPROM,
1538c2ecf20Sopenharmony_ci			"unable to read eeprom region at offset %u\n", off);
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ci	return ret;
1568c2ecf20Sopenharmony_ci}
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_ciint ath9k_hw_nvram_swap_data(struct ath_hw *ah, bool *swap_needed, int size)
1598c2ecf20Sopenharmony_ci{
1608c2ecf20Sopenharmony_ci	u16 magic;
1618c2ecf20Sopenharmony_ci	u16 *eepdata;
1628c2ecf20Sopenharmony_ci	int i;
1638c2ecf20Sopenharmony_ci	bool needs_byteswap = false;
1648c2ecf20Sopenharmony_ci	struct ath_common *common = ath9k_hw_common(ah);
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_ci	if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) {
1678c2ecf20Sopenharmony_ci		ath_err(common, "Reading Magic # failed\n");
1688c2ecf20Sopenharmony_ci		return -EIO;
1698c2ecf20Sopenharmony_ci	}
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_ci	if (swab16(magic) == AR5416_EEPROM_MAGIC) {
1728c2ecf20Sopenharmony_ci		needs_byteswap = true;
1738c2ecf20Sopenharmony_ci		ath_dbg(common, EEPROM,
1748c2ecf20Sopenharmony_ci			"EEPROM needs byte-swapping to correct endianness.\n");
1758c2ecf20Sopenharmony_ci	} else if (magic != AR5416_EEPROM_MAGIC) {
1768c2ecf20Sopenharmony_ci		if (ath9k_hw_use_flash(ah)) {
1778c2ecf20Sopenharmony_ci			ath_dbg(common, EEPROM,
1788c2ecf20Sopenharmony_ci				"Ignoring invalid EEPROM magic (0x%04x).\n",
1798c2ecf20Sopenharmony_ci				magic);
1808c2ecf20Sopenharmony_ci		} else {
1818c2ecf20Sopenharmony_ci			ath_err(common,
1828c2ecf20Sopenharmony_ci				"Invalid EEPROM magic (0x%04x).\n", magic);
1838c2ecf20Sopenharmony_ci			return -EINVAL;
1848c2ecf20Sopenharmony_ci		}
1858c2ecf20Sopenharmony_ci	}
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_ci	if (needs_byteswap) {
1888c2ecf20Sopenharmony_ci		if (ah->ah_flags & AH_NO_EEP_SWAP) {
1898c2ecf20Sopenharmony_ci			ath_info(common,
1908c2ecf20Sopenharmony_ci				 "Ignoring endianness difference in EEPROM magic bytes.\n");
1918c2ecf20Sopenharmony_ci		} else {
1928c2ecf20Sopenharmony_ci			eepdata = (u16 *)(&ah->eeprom);
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_ci			for (i = 0; i < size; i++)
1958c2ecf20Sopenharmony_ci				eepdata[i] = swab16(eepdata[i]);
1968c2ecf20Sopenharmony_ci		}
1978c2ecf20Sopenharmony_ci	}
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ci	if (ah->eep_ops->get_eepmisc(ah) & AR5416_EEPMISC_BIG_ENDIAN) {
2008c2ecf20Sopenharmony_ci		*swap_needed = true;
2018c2ecf20Sopenharmony_ci		ath_dbg(common, EEPROM,
2028c2ecf20Sopenharmony_ci			"Big Endian EEPROM detected according to EEPMISC register.\n");
2038c2ecf20Sopenharmony_ci	} else {
2048c2ecf20Sopenharmony_ci		*swap_needed = false;
2058c2ecf20Sopenharmony_ci	}
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_ci	return 0;
2088c2ecf20Sopenharmony_ci}
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_cibool ath9k_hw_nvram_validate_checksum(struct ath_hw *ah, int size)
2118c2ecf20Sopenharmony_ci{
2128c2ecf20Sopenharmony_ci	u32 i, sum = 0;
2138c2ecf20Sopenharmony_ci	u16 *eepdata = (u16 *)(&ah->eeprom);
2148c2ecf20Sopenharmony_ci	struct ath_common *common = ath9k_hw_common(ah);
2158c2ecf20Sopenharmony_ci
2168c2ecf20Sopenharmony_ci	for (i = 0; i < size; i++)
2178c2ecf20Sopenharmony_ci		sum ^= eepdata[i];
2188c2ecf20Sopenharmony_ci
2198c2ecf20Sopenharmony_ci	if (sum != 0xffff) {
2208c2ecf20Sopenharmony_ci		ath_err(common, "Bad EEPROM checksum 0x%x\n", sum);
2218c2ecf20Sopenharmony_ci		return false;
2228c2ecf20Sopenharmony_ci	}
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_ci	return true;
2258c2ecf20Sopenharmony_ci}
2268c2ecf20Sopenharmony_ci
2278c2ecf20Sopenharmony_cibool ath9k_hw_nvram_check_version(struct ath_hw *ah, int version, int minrev)
2288c2ecf20Sopenharmony_ci{
2298c2ecf20Sopenharmony_ci	struct ath_common *common = ath9k_hw_common(ah);
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ci	if (ah->eep_ops->get_eeprom_ver(ah) != version ||
2328c2ecf20Sopenharmony_ci	    ah->eep_ops->get_eeprom_rev(ah) < minrev) {
2338c2ecf20Sopenharmony_ci		ath_err(common, "Bad EEPROM VER 0x%04x or REV 0x%04x\n",
2348c2ecf20Sopenharmony_ci			ah->eep_ops->get_eeprom_ver(ah),
2358c2ecf20Sopenharmony_ci			ah->eep_ops->get_eeprom_rev(ah));
2368c2ecf20Sopenharmony_ci		return false;
2378c2ecf20Sopenharmony_ci	}
2388c2ecf20Sopenharmony_ci
2398c2ecf20Sopenharmony_ci	return true;
2408c2ecf20Sopenharmony_ci}
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_civoid ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList,
2438c2ecf20Sopenharmony_ci			     u8 *pVpdList, u16 numIntercepts,
2448c2ecf20Sopenharmony_ci			     u8 *pRetVpdList)
2458c2ecf20Sopenharmony_ci{
2468c2ecf20Sopenharmony_ci	u16 i, k;
2478c2ecf20Sopenharmony_ci	u8 currPwr = pwrMin;
2488c2ecf20Sopenharmony_ci	u16 idxL = 0, idxR = 0;
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_ci	for (i = 0; i <= (pwrMax - pwrMin) / 2; i++) {
2518c2ecf20Sopenharmony_ci		ath9k_hw_get_lower_upper_index(currPwr, pPwrList,
2528c2ecf20Sopenharmony_ci					       numIntercepts, &(idxL),
2538c2ecf20Sopenharmony_ci					       &(idxR));
2548c2ecf20Sopenharmony_ci		if (idxR < 1)
2558c2ecf20Sopenharmony_ci			idxR = 1;
2568c2ecf20Sopenharmony_ci		if (idxL == numIntercepts - 1)
2578c2ecf20Sopenharmony_ci			idxL = (u16) (numIntercepts - 2);
2588c2ecf20Sopenharmony_ci		if (pPwrList[idxL] == pPwrList[idxR])
2598c2ecf20Sopenharmony_ci			k = pVpdList[idxL];
2608c2ecf20Sopenharmony_ci		else
2618c2ecf20Sopenharmony_ci			k = (u16)(((currPwr - pPwrList[idxL]) * pVpdList[idxR] +
2628c2ecf20Sopenharmony_ci				   (pPwrList[idxR] - currPwr) * pVpdList[idxL]) /
2638c2ecf20Sopenharmony_ci				  (pPwrList[idxR] - pPwrList[idxL]));
2648c2ecf20Sopenharmony_ci		pRetVpdList[i] = (u8) k;
2658c2ecf20Sopenharmony_ci		currPwr += 2;
2668c2ecf20Sopenharmony_ci	}
2678c2ecf20Sopenharmony_ci}
2688c2ecf20Sopenharmony_ci
2698c2ecf20Sopenharmony_civoid ath9k_hw_get_legacy_target_powers(struct ath_hw *ah,
2708c2ecf20Sopenharmony_ci				       struct ath9k_channel *chan,
2718c2ecf20Sopenharmony_ci				       struct cal_target_power_leg *powInfo,
2728c2ecf20Sopenharmony_ci				       u16 numChannels,
2738c2ecf20Sopenharmony_ci				       struct cal_target_power_leg *pNewPower,
2748c2ecf20Sopenharmony_ci				       u16 numRates, bool isExtTarget)
2758c2ecf20Sopenharmony_ci{
2768c2ecf20Sopenharmony_ci	struct chan_centers centers;
2778c2ecf20Sopenharmony_ci	u16 clo, chi;
2788c2ecf20Sopenharmony_ci	int i;
2798c2ecf20Sopenharmony_ci	int matchIndex = -1, lowIndex = -1;
2808c2ecf20Sopenharmony_ci	u16 freq;
2818c2ecf20Sopenharmony_ci
2828c2ecf20Sopenharmony_ci	ath9k_hw_get_channel_centers(ah, chan, &centers);
2838c2ecf20Sopenharmony_ci	freq = (isExtTarget) ? centers.ext_center : centers.ctl_center;
2848c2ecf20Sopenharmony_ci
2858c2ecf20Sopenharmony_ci	if (freq <= ath9k_hw_fbin2freq(powInfo[0].bChannel,
2868c2ecf20Sopenharmony_ci				       IS_CHAN_2GHZ(chan))) {
2878c2ecf20Sopenharmony_ci		matchIndex = 0;
2888c2ecf20Sopenharmony_ci	} else {
2898c2ecf20Sopenharmony_ci		for (i = 0; (i < numChannels) &&
2908c2ecf20Sopenharmony_ci			     (powInfo[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
2918c2ecf20Sopenharmony_ci			if (freq == ath9k_hw_fbin2freq(powInfo[i].bChannel,
2928c2ecf20Sopenharmony_ci						       IS_CHAN_2GHZ(chan))) {
2938c2ecf20Sopenharmony_ci				matchIndex = i;
2948c2ecf20Sopenharmony_ci				break;
2958c2ecf20Sopenharmony_ci			} else if (freq < ath9k_hw_fbin2freq(powInfo[i].bChannel,
2968c2ecf20Sopenharmony_ci						IS_CHAN_2GHZ(chan)) && i > 0 &&
2978c2ecf20Sopenharmony_ci				   freq > ath9k_hw_fbin2freq(powInfo[i - 1].bChannel,
2988c2ecf20Sopenharmony_ci						IS_CHAN_2GHZ(chan))) {
2998c2ecf20Sopenharmony_ci				lowIndex = i - 1;
3008c2ecf20Sopenharmony_ci				break;
3018c2ecf20Sopenharmony_ci			}
3028c2ecf20Sopenharmony_ci		}
3038c2ecf20Sopenharmony_ci		if ((matchIndex == -1) && (lowIndex == -1))
3048c2ecf20Sopenharmony_ci			matchIndex = i - 1;
3058c2ecf20Sopenharmony_ci	}
3068c2ecf20Sopenharmony_ci
3078c2ecf20Sopenharmony_ci	if (matchIndex != -1) {
3088c2ecf20Sopenharmony_ci		*pNewPower = powInfo[matchIndex];
3098c2ecf20Sopenharmony_ci	} else {
3108c2ecf20Sopenharmony_ci		clo = ath9k_hw_fbin2freq(powInfo[lowIndex].bChannel,
3118c2ecf20Sopenharmony_ci					 IS_CHAN_2GHZ(chan));
3128c2ecf20Sopenharmony_ci		chi = ath9k_hw_fbin2freq(powInfo[lowIndex + 1].bChannel,
3138c2ecf20Sopenharmony_ci					 IS_CHAN_2GHZ(chan));
3148c2ecf20Sopenharmony_ci
3158c2ecf20Sopenharmony_ci		for (i = 0; i < numRates; i++) {
3168c2ecf20Sopenharmony_ci			pNewPower->tPow2x[i] =
3178c2ecf20Sopenharmony_ci				(u8)ath9k_hw_interpolate(freq, clo, chi,
3188c2ecf20Sopenharmony_ci						powInfo[lowIndex].tPow2x[i],
3198c2ecf20Sopenharmony_ci						powInfo[lowIndex + 1].tPow2x[i]);
3208c2ecf20Sopenharmony_ci		}
3218c2ecf20Sopenharmony_ci	}
3228c2ecf20Sopenharmony_ci}
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_civoid ath9k_hw_get_target_powers(struct ath_hw *ah,
3258c2ecf20Sopenharmony_ci				struct ath9k_channel *chan,
3268c2ecf20Sopenharmony_ci				struct cal_target_power_ht *powInfo,
3278c2ecf20Sopenharmony_ci				u16 numChannels,
3288c2ecf20Sopenharmony_ci				struct cal_target_power_ht *pNewPower,
3298c2ecf20Sopenharmony_ci				u16 numRates, bool isHt40Target)
3308c2ecf20Sopenharmony_ci{
3318c2ecf20Sopenharmony_ci	struct chan_centers centers;
3328c2ecf20Sopenharmony_ci	u16 clo, chi;
3338c2ecf20Sopenharmony_ci	int i;
3348c2ecf20Sopenharmony_ci	int matchIndex = -1, lowIndex = -1;
3358c2ecf20Sopenharmony_ci	u16 freq;
3368c2ecf20Sopenharmony_ci
3378c2ecf20Sopenharmony_ci	ath9k_hw_get_channel_centers(ah, chan, &centers);
3388c2ecf20Sopenharmony_ci	freq = isHt40Target ? centers.synth_center : centers.ctl_center;
3398c2ecf20Sopenharmony_ci
3408c2ecf20Sopenharmony_ci	if (freq <= ath9k_hw_fbin2freq(powInfo[0].bChannel, IS_CHAN_2GHZ(chan))) {
3418c2ecf20Sopenharmony_ci		matchIndex = 0;
3428c2ecf20Sopenharmony_ci	} else {
3438c2ecf20Sopenharmony_ci		for (i = 0; (i < numChannels) &&
3448c2ecf20Sopenharmony_ci			     (powInfo[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
3458c2ecf20Sopenharmony_ci			if (freq == ath9k_hw_fbin2freq(powInfo[i].bChannel,
3468c2ecf20Sopenharmony_ci						       IS_CHAN_2GHZ(chan))) {
3478c2ecf20Sopenharmony_ci				matchIndex = i;
3488c2ecf20Sopenharmony_ci				break;
3498c2ecf20Sopenharmony_ci			} else
3508c2ecf20Sopenharmony_ci				if (freq < ath9k_hw_fbin2freq(powInfo[i].bChannel,
3518c2ecf20Sopenharmony_ci						IS_CHAN_2GHZ(chan)) && i > 0 &&
3528c2ecf20Sopenharmony_ci				    freq > ath9k_hw_fbin2freq(powInfo[i - 1].bChannel,
3538c2ecf20Sopenharmony_ci						IS_CHAN_2GHZ(chan))) {
3548c2ecf20Sopenharmony_ci					lowIndex = i - 1;
3558c2ecf20Sopenharmony_ci					break;
3568c2ecf20Sopenharmony_ci				}
3578c2ecf20Sopenharmony_ci		}
3588c2ecf20Sopenharmony_ci		if ((matchIndex == -1) && (lowIndex == -1))
3598c2ecf20Sopenharmony_ci			matchIndex = i - 1;
3608c2ecf20Sopenharmony_ci	}
3618c2ecf20Sopenharmony_ci
3628c2ecf20Sopenharmony_ci	if (matchIndex != -1) {
3638c2ecf20Sopenharmony_ci		*pNewPower = powInfo[matchIndex];
3648c2ecf20Sopenharmony_ci	} else {
3658c2ecf20Sopenharmony_ci		clo = ath9k_hw_fbin2freq(powInfo[lowIndex].bChannel,
3668c2ecf20Sopenharmony_ci					 IS_CHAN_2GHZ(chan));
3678c2ecf20Sopenharmony_ci		chi = ath9k_hw_fbin2freq(powInfo[lowIndex + 1].bChannel,
3688c2ecf20Sopenharmony_ci					 IS_CHAN_2GHZ(chan));
3698c2ecf20Sopenharmony_ci
3708c2ecf20Sopenharmony_ci		for (i = 0; i < numRates; i++) {
3718c2ecf20Sopenharmony_ci			pNewPower->tPow2x[i] = (u8)ath9k_hw_interpolate(freq,
3728c2ecf20Sopenharmony_ci						clo, chi,
3738c2ecf20Sopenharmony_ci						powInfo[lowIndex].tPow2x[i],
3748c2ecf20Sopenharmony_ci						powInfo[lowIndex + 1].tPow2x[i]);
3758c2ecf20Sopenharmony_ci		}
3768c2ecf20Sopenharmony_ci	}
3778c2ecf20Sopenharmony_ci}
3788c2ecf20Sopenharmony_ci
3798c2ecf20Sopenharmony_ciu16 ath9k_hw_get_max_edge_power(u16 freq, struct cal_ctl_edges *pRdEdgesPower,
3808c2ecf20Sopenharmony_ci				bool is2GHz, int num_band_edges)
3818c2ecf20Sopenharmony_ci{
3828c2ecf20Sopenharmony_ci	u16 twiceMaxEdgePower = MAX_RATE_POWER;
3838c2ecf20Sopenharmony_ci	int i;
3848c2ecf20Sopenharmony_ci
3858c2ecf20Sopenharmony_ci	for (i = 0; (i < num_band_edges) &&
3868c2ecf20Sopenharmony_ci		     (pRdEdgesPower[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
3878c2ecf20Sopenharmony_ci		if (freq == ath9k_hw_fbin2freq(pRdEdgesPower[i].bChannel, is2GHz)) {
3888c2ecf20Sopenharmony_ci			twiceMaxEdgePower = CTL_EDGE_TPOWER(pRdEdgesPower[i].ctl);
3898c2ecf20Sopenharmony_ci			break;
3908c2ecf20Sopenharmony_ci		} else if ((i > 0) &&
3918c2ecf20Sopenharmony_ci			   (freq < ath9k_hw_fbin2freq(pRdEdgesPower[i].bChannel,
3928c2ecf20Sopenharmony_ci						      is2GHz))) {
3938c2ecf20Sopenharmony_ci			if (ath9k_hw_fbin2freq(pRdEdgesPower[i - 1].bChannel,
3948c2ecf20Sopenharmony_ci					       is2GHz) < freq &&
3958c2ecf20Sopenharmony_ci			    CTL_EDGE_FLAGS(pRdEdgesPower[i - 1].ctl)) {
3968c2ecf20Sopenharmony_ci				twiceMaxEdgePower =
3978c2ecf20Sopenharmony_ci					CTL_EDGE_TPOWER(pRdEdgesPower[i - 1].ctl);
3988c2ecf20Sopenharmony_ci			}
3998c2ecf20Sopenharmony_ci			break;
4008c2ecf20Sopenharmony_ci		}
4018c2ecf20Sopenharmony_ci	}
4028c2ecf20Sopenharmony_ci
4038c2ecf20Sopenharmony_ci	return twiceMaxEdgePower;
4048c2ecf20Sopenharmony_ci}
4058c2ecf20Sopenharmony_ci
4068c2ecf20Sopenharmony_ciu16 ath9k_hw_get_scaled_power(struct ath_hw *ah, u16 power_limit,
4078c2ecf20Sopenharmony_ci			      u8 antenna_reduction)
4088c2ecf20Sopenharmony_ci{
4098c2ecf20Sopenharmony_ci	u16 reduction = antenna_reduction;
4108c2ecf20Sopenharmony_ci
4118c2ecf20Sopenharmony_ci	/*
4128c2ecf20Sopenharmony_ci	 * Reduce scaled Power by number of chains active
4138c2ecf20Sopenharmony_ci	 * to get the per chain tx power level.
4148c2ecf20Sopenharmony_ci	 */
4158c2ecf20Sopenharmony_ci	switch (ar5416_get_ntxchains(ah->txchainmask)) {
4168c2ecf20Sopenharmony_ci	case 1:
4178c2ecf20Sopenharmony_ci		break;
4188c2ecf20Sopenharmony_ci	case 2:
4198c2ecf20Sopenharmony_ci		reduction += POWER_CORRECTION_FOR_TWO_CHAIN;
4208c2ecf20Sopenharmony_ci		break;
4218c2ecf20Sopenharmony_ci	case 3:
4228c2ecf20Sopenharmony_ci		reduction += POWER_CORRECTION_FOR_THREE_CHAIN;
4238c2ecf20Sopenharmony_ci		break;
4248c2ecf20Sopenharmony_ci	}
4258c2ecf20Sopenharmony_ci
4268c2ecf20Sopenharmony_ci	if (power_limit > reduction)
4278c2ecf20Sopenharmony_ci		power_limit -= reduction;
4288c2ecf20Sopenharmony_ci	else
4298c2ecf20Sopenharmony_ci		power_limit = 0;
4308c2ecf20Sopenharmony_ci
4318c2ecf20Sopenharmony_ci	return min_t(u16, power_limit, MAX_RATE_POWER);
4328c2ecf20Sopenharmony_ci}
4338c2ecf20Sopenharmony_ci
4348c2ecf20Sopenharmony_civoid ath9k_hw_update_regulatory_maxpower(struct ath_hw *ah)
4358c2ecf20Sopenharmony_ci{
4368c2ecf20Sopenharmony_ci	struct ath_common *common = ath9k_hw_common(ah);
4378c2ecf20Sopenharmony_ci	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
4388c2ecf20Sopenharmony_ci
4398c2ecf20Sopenharmony_ci	switch (ar5416_get_ntxchains(ah->txchainmask)) {
4408c2ecf20Sopenharmony_ci	case 1:
4418c2ecf20Sopenharmony_ci		break;
4428c2ecf20Sopenharmony_ci	case 2:
4438c2ecf20Sopenharmony_ci		regulatory->max_power_level += POWER_CORRECTION_FOR_TWO_CHAIN;
4448c2ecf20Sopenharmony_ci		break;
4458c2ecf20Sopenharmony_ci	case 3:
4468c2ecf20Sopenharmony_ci		regulatory->max_power_level += POWER_CORRECTION_FOR_THREE_CHAIN;
4478c2ecf20Sopenharmony_ci		break;
4488c2ecf20Sopenharmony_ci	default:
4498c2ecf20Sopenharmony_ci		ath_dbg(common, EEPROM, "Invalid chainmask configuration\n");
4508c2ecf20Sopenharmony_ci		break;
4518c2ecf20Sopenharmony_ci	}
4528c2ecf20Sopenharmony_ci}
4538c2ecf20Sopenharmony_ci
4548c2ecf20Sopenharmony_civoid ath9k_hw_get_gain_boundaries_pdadcs(struct ath_hw *ah,
4558c2ecf20Sopenharmony_ci				struct ath9k_channel *chan,
4568c2ecf20Sopenharmony_ci				void *pRawDataSet,
4578c2ecf20Sopenharmony_ci				u8 *bChans, u16 availPiers,
4588c2ecf20Sopenharmony_ci				u16 tPdGainOverlap,
4598c2ecf20Sopenharmony_ci				u16 *pPdGainBoundaries, u8 *pPDADCValues,
4608c2ecf20Sopenharmony_ci				u16 numXpdGains)
4618c2ecf20Sopenharmony_ci{
4628c2ecf20Sopenharmony_ci	int i, j, k;
4638c2ecf20Sopenharmony_ci	int16_t ss;
4648c2ecf20Sopenharmony_ci	u16 idxL = 0, idxR = 0, numPiers;
4658c2ecf20Sopenharmony_ci	static u8 vpdTableL[AR5416_NUM_PD_GAINS]
4668c2ecf20Sopenharmony_ci		[AR5416_MAX_PWR_RANGE_IN_HALF_DB];
4678c2ecf20Sopenharmony_ci	static u8 vpdTableR[AR5416_NUM_PD_GAINS]
4688c2ecf20Sopenharmony_ci		[AR5416_MAX_PWR_RANGE_IN_HALF_DB];
4698c2ecf20Sopenharmony_ci	static u8 vpdTableI[AR5416_NUM_PD_GAINS]
4708c2ecf20Sopenharmony_ci		[AR5416_MAX_PWR_RANGE_IN_HALF_DB];
4718c2ecf20Sopenharmony_ci
4728c2ecf20Sopenharmony_ci	u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR;
4738c2ecf20Sopenharmony_ci	u8 minPwrT4[AR5416_NUM_PD_GAINS];
4748c2ecf20Sopenharmony_ci	u8 maxPwrT4[AR5416_NUM_PD_GAINS];
4758c2ecf20Sopenharmony_ci	int16_t vpdStep;
4768c2ecf20Sopenharmony_ci	int16_t tmpVal;
4778c2ecf20Sopenharmony_ci	u16 sizeCurrVpdTable, maxIndex, tgtIndex;
4788c2ecf20Sopenharmony_ci	bool match;
4798c2ecf20Sopenharmony_ci	int16_t minDelta = 0;
4808c2ecf20Sopenharmony_ci	struct chan_centers centers;
4818c2ecf20Sopenharmony_ci	int pdgain_boundary_default;
4828c2ecf20Sopenharmony_ci	struct cal_data_per_freq *data_def = pRawDataSet;
4838c2ecf20Sopenharmony_ci	struct cal_data_per_freq_4k *data_4k = pRawDataSet;
4848c2ecf20Sopenharmony_ci	struct cal_data_per_freq_ar9287 *data_9287 = pRawDataSet;
4858c2ecf20Sopenharmony_ci	bool eeprom_4k = AR_SREV_9285(ah) || AR_SREV_9271(ah);
4868c2ecf20Sopenharmony_ci	int intercepts;
4878c2ecf20Sopenharmony_ci
4888c2ecf20Sopenharmony_ci	if (AR_SREV_9287(ah))
4898c2ecf20Sopenharmony_ci		intercepts = AR9287_PD_GAIN_ICEPTS;
4908c2ecf20Sopenharmony_ci	else
4918c2ecf20Sopenharmony_ci		intercepts = AR5416_PD_GAIN_ICEPTS;
4928c2ecf20Sopenharmony_ci
4938c2ecf20Sopenharmony_ci	memset(&minPwrT4, 0, AR5416_NUM_PD_GAINS);
4948c2ecf20Sopenharmony_ci	ath9k_hw_get_channel_centers(ah, chan, &centers);
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_ci	for (numPiers = 0; numPiers < availPiers; numPiers++) {
4978c2ecf20Sopenharmony_ci		if (bChans[numPiers] == AR5416_BCHAN_UNUSED)
4988c2ecf20Sopenharmony_ci			break;
4998c2ecf20Sopenharmony_ci	}
5008c2ecf20Sopenharmony_ci
5018c2ecf20Sopenharmony_ci	match = ath9k_hw_get_lower_upper_index((u8)FREQ2FBIN(centers.synth_center,
5028c2ecf20Sopenharmony_ci							     IS_CHAN_2GHZ(chan)),
5038c2ecf20Sopenharmony_ci					       bChans, numPiers, &idxL, &idxR);
5048c2ecf20Sopenharmony_ci
5058c2ecf20Sopenharmony_ci	if (match) {
5068c2ecf20Sopenharmony_ci		if (AR_SREV_9287(ah)) {
5078c2ecf20Sopenharmony_ci			for (i = 0; i < numXpdGains; i++) {
5088c2ecf20Sopenharmony_ci				minPwrT4[i] = data_9287[idxL].pwrPdg[i][0];
5098c2ecf20Sopenharmony_ci				maxPwrT4[i] = data_9287[idxL].pwrPdg[i][intercepts - 1];
5108c2ecf20Sopenharmony_ci				ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
5118c2ecf20Sopenharmony_ci						data_9287[idxL].pwrPdg[i],
5128c2ecf20Sopenharmony_ci						data_9287[idxL].vpdPdg[i],
5138c2ecf20Sopenharmony_ci						intercepts,
5148c2ecf20Sopenharmony_ci						vpdTableI[i]);
5158c2ecf20Sopenharmony_ci			}
5168c2ecf20Sopenharmony_ci		} else if (eeprom_4k) {
5178c2ecf20Sopenharmony_ci			for (i = 0; i < numXpdGains; i++) {
5188c2ecf20Sopenharmony_ci				minPwrT4[i] = data_4k[idxL].pwrPdg[i][0];
5198c2ecf20Sopenharmony_ci				maxPwrT4[i] = data_4k[idxL].pwrPdg[i][intercepts - 1];
5208c2ecf20Sopenharmony_ci				ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
5218c2ecf20Sopenharmony_ci						data_4k[idxL].pwrPdg[i],
5228c2ecf20Sopenharmony_ci						data_4k[idxL].vpdPdg[i],
5238c2ecf20Sopenharmony_ci						intercepts,
5248c2ecf20Sopenharmony_ci						vpdTableI[i]);
5258c2ecf20Sopenharmony_ci			}
5268c2ecf20Sopenharmony_ci		} else {
5278c2ecf20Sopenharmony_ci			for (i = 0; i < numXpdGains; i++) {
5288c2ecf20Sopenharmony_ci				minPwrT4[i] = data_def[idxL].pwrPdg[i][0];
5298c2ecf20Sopenharmony_ci				maxPwrT4[i] = data_def[idxL].pwrPdg[i][intercepts - 1];
5308c2ecf20Sopenharmony_ci				ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
5318c2ecf20Sopenharmony_ci						data_def[idxL].pwrPdg[i],
5328c2ecf20Sopenharmony_ci						data_def[idxL].vpdPdg[i],
5338c2ecf20Sopenharmony_ci						intercepts,
5348c2ecf20Sopenharmony_ci						vpdTableI[i]);
5358c2ecf20Sopenharmony_ci			}
5368c2ecf20Sopenharmony_ci		}
5378c2ecf20Sopenharmony_ci	} else {
5388c2ecf20Sopenharmony_ci		for (i = 0; i < numXpdGains; i++) {
5398c2ecf20Sopenharmony_ci			if (AR_SREV_9287(ah)) {
5408c2ecf20Sopenharmony_ci				pVpdL = data_9287[idxL].vpdPdg[i];
5418c2ecf20Sopenharmony_ci				pPwrL = data_9287[idxL].pwrPdg[i];
5428c2ecf20Sopenharmony_ci				pVpdR = data_9287[idxR].vpdPdg[i];
5438c2ecf20Sopenharmony_ci				pPwrR = data_9287[idxR].pwrPdg[i];
5448c2ecf20Sopenharmony_ci			} else if (eeprom_4k) {
5458c2ecf20Sopenharmony_ci				pVpdL = data_4k[idxL].vpdPdg[i];
5468c2ecf20Sopenharmony_ci				pPwrL = data_4k[idxL].pwrPdg[i];
5478c2ecf20Sopenharmony_ci				pVpdR = data_4k[idxR].vpdPdg[i];
5488c2ecf20Sopenharmony_ci				pPwrR = data_4k[idxR].pwrPdg[i];
5498c2ecf20Sopenharmony_ci			} else {
5508c2ecf20Sopenharmony_ci				pVpdL = data_def[idxL].vpdPdg[i];
5518c2ecf20Sopenharmony_ci				pPwrL = data_def[idxL].pwrPdg[i];
5528c2ecf20Sopenharmony_ci				pVpdR = data_def[idxR].vpdPdg[i];
5538c2ecf20Sopenharmony_ci				pPwrR = data_def[idxR].pwrPdg[i];
5548c2ecf20Sopenharmony_ci			}
5558c2ecf20Sopenharmony_ci
5568c2ecf20Sopenharmony_ci			minPwrT4[i] = max(pPwrL[0], pPwrR[0]);
5578c2ecf20Sopenharmony_ci
5588c2ecf20Sopenharmony_ci			maxPwrT4[i] =
5598c2ecf20Sopenharmony_ci				min(pPwrL[intercepts - 1],
5608c2ecf20Sopenharmony_ci				    pPwrR[intercepts - 1]);
5618c2ecf20Sopenharmony_ci
5628c2ecf20Sopenharmony_ci
5638c2ecf20Sopenharmony_ci			ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
5648c2ecf20Sopenharmony_ci						pPwrL, pVpdL,
5658c2ecf20Sopenharmony_ci						intercepts,
5668c2ecf20Sopenharmony_ci						vpdTableL[i]);
5678c2ecf20Sopenharmony_ci			ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
5688c2ecf20Sopenharmony_ci						pPwrR, pVpdR,
5698c2ecf20Sopenharmony_ci						intercepts,
5708c2ecf20Sopenharmony_ci						vpdTableR[i]);
5718c2ecf20Sopenharmony_ci
5728c2ecf20Sopenharmony_ci			for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) {
5738c2ecf20Sopenharmony_ci				vpdTableI[i][j] =
5748c2ecf20Sopenharmony_ci					(u8)(ath9k_hw_interpolate((u16)
5758c2ecf20Sopenharmony_ci					     FREQ2FBIN(centers.
5768c2ecf20Sopenharmony_ci						       synth_center,
5778c2ecf20Sopenharmony_ci						       IS_CHAN_2GHZ
5788c2ecf20Sopenharmony_ci						       (chan)),
5798c2ecf20Sopenharmony_ci					     bChans[idxL], bChans[idxR],
5808c2ecf20Sopenharmony_ci					     vpdTableL[i][j], vpdTableR[i][j]));
5818c2ecf20Sopenharmony_ci			}
5828c2ecf20Sopenharmony_ci		}
5838c2ecf20Sopenharmony_ci	}
5848c2ecf20Sopenharmony_ci
5858c2ecf20Sopenharmony_ci	k = 0;
5868c2ecf20Sopenharmony_ci
5878c2ecf20Sopenharmony_ci	for (i = 0; i < numXpdGains; i++) {
5888c2ecf20Sopenharmony_ci		if (i == (numXpdGains - 1))
5898c2ecf20Sopenharmony_ci			pPdGainBoundaries[i] =
5908c2ecf20Sopenharmony_ci				(u16)(maxPwrT4[i] / 2);
5918c2ecf20Sopenharmony_ci		else
5928c2ecf20Sopenharmony_ci			pPdGainBoundaries[i] =
5938c2ecf20Sopenharmony_ci				(u16)((maxPwrT4[i] + minPwrT4[i + 1]) / 4);
5948c2ecf20Sopenharmony_ci
5958c2ecf20Sopenharmony_ci		pPdGainBoundaries[i] =
5968c2ecf20Sopenharmony_ci			min((u16)MAX_RATE_POWER, pPdGainBoundaries[i]);
5978c2ecf20Sopenharmony_ci
5988c2ecf20Sopenharmony_ci		minDelta = 0;
5998c2ecf20Sopenharmony_ci
6008c2ecf20Sopenharmony_ci		if (i == 0) {
6018c2ecf20Sopenharmony_ci			if (AR_SREV_9280_20_OR_LATER(ah))
6028c2ecf20Sopenharmony_ci				ss = (int16_t)(0 - (minPwrT4[i] / 2));
6038c2ecf20Sopenharmony_ci			else
6048c2ecf20Sopenharmony_ci				ss = 0;
6058c2ecf20Sopenharmony_ci		} else {
6068c2ecf20Sopenharmony_ci			ss = (int16_t)((pPdGainBoundaries[i - 1] -
6078c2ecf20Sopenharmony_ci					(minPwrT4[i] / 2)) -
6088c2ecf20Sopenharmony_ci				       tPdGainOverlap + 1 + minDelta);
6098c2ecf20Sopenharmony_ci		}
6108c2ecf20Sopenharmony_ci		vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]);
6118c2ecf20Sopenharmony_ci		vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
6128c2ecf20Sopenharmony_ci
6138c2ecf20Sopenharmony_ci		while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
6148c2ecf20Sopenharmony_ci			tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep);
6158c2ecf20Sopenharmony_ci			pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal);
6168c2ecf20Sopenharmony_ci			ss++;
6178c2ecf20Sopenharmony_ci		}
6188c2ecf20Sopenharmony_ci
6198c2ecf20Sopenharmony_ci		sizeCurrVpdTable = (u8) ((maxPwrT4[i] - minPwrT4[i]) / 2 + 1);
6208c2ecf20Sopenharmony_ci		tgtIndex = (u8)(pPdGainBoundaries[i] + tPdGainOverlap -
6218c2ecf20Sopenharmony_ci				(minPwrT4[i] / 2));
6228c2ecf20Sopenharmony_ci		maxIndex = (tgtIndex < sizeCurrVpdTable) ?
6238c2ecf20Sopenharmony_ci			tgtIndex : sizeCurrVpdTable;
6248c2ecf20Sopenharmony_ci
6258c2ecf20Sopenharmony_ci		while ((ss < maxIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
6268c2ecf20Sopenharmony_ci			pPDADCValues[k++] = vpdTableI[i][ss++];
6278c2ecf20Sopenharmony_ci		}
6288c2ecf20Sopenharmony_ci
6298c2ecf20Sopenharmony_ci		vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] -
6308c2ecf20Sopenharmony_ci				    vpdTableI[i][sizeCurrVpdTable - 2]);
6318c2ecf20Sopenharmony_ci		vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
6328c2ecf20Sopenharmony_ci
6338c2ecf20Sopenharmony_ci		if (tgtIndex >= maxIndex) {
6348c2ecf20Sopenharmony_ci			while ((ss <= tgtIndex) &&
6358c2ecf20Sopenharmony_ci			       (k < (AR5416_NUM_PDADC_VALUES - 1))) {
6368c2ecf20Sopenharmony_ci				tmpVal = (int16_t)((vpdTableI[i][sizeCurrVpdTable - 1] +
6378c2ecf20Sopenharmony_ci						    (ss - maxIndex + 1) * vpdStep));
6388c2ecf20Sopenharmony_ci				pPDADCValues[k++] = (u8)((tmpVal > 255) ?
6398c2ecf20Sopenharmony_ci							 255 : tmpVal);
6408c2ecf20Sopenharmony_ci				ss++;
6418c2ecf20Sopenharmony_ci			}
6428c2ecf20Sopenharmony_ci		}
6438c2ecf20Sopenharmony_ci	}
6448c2ecf20Sopenharmony_ci
6458c2ecf20Sopenharmony_ci	if (eeprom_4k)
6468c2ecf20Sopenharmony_ci		pdgain_boundary_default = 58;
6478c2ecf20Sopenharmony_ci	else
6488c2ecf20Sopenharmony_ci		pdgain_boundary_default = pPdGainBoundaries[i - 1];
6498c2ecf20Sopenharmony_ci
6508c2ecf20Sopenharmony_ci	while (i < AR5416_PD_GAINS_IN_MASK) {
6518c2ecf20Sopenharmony_ci		pPdGainBoundaries[i] = pdgain_boundary_default;
6528c2ecf20Sopenharmony_ci		i++;
6538c2ecf20Sopenharmony_ci	}
6548c2ecf20Sopenharmony_ci
6558c2ecf20Sopenharmony_ci	while (k < AR5416_NUM_PDADC_VALUES) {
6568c2ecf20Sopenharmony_ci		pPDADCValues[k] = pPDADCValues[k - 1];
6578c2ecf20Sopenharmony_ci		k++;
6588c2ecf20Sopenharmony_ci	}
6598c2ecf20Sopenharmony_ci}
6608c2ecf20Sopenharmony_ci
6618c2ecf20Sopenharmony_ciint ath9k_hw_eeprom_init(struct ath_hw *ah)
6628c2ecf20Sopenharmony_ci{
6638c2ecf20Sopenharmony_ci	int status;
6648c2ecf20Sopenharmony_ci
6658c2ecf20Sopenharmony_ci	if (AR_SREV_9300_20_OR_LATER(ah))
6668c2ecf20Sopenharmony_ci		ah->eep_ops = &eep_ar9300_ops;
6678c2ecf20Sopenharmony_ci	else if (AR_SREV_9287(ah)) {
6688c2ecf20Sopenharmony_ci		ah->eep_ops = &eep_ar9287_ops;
6698c2ecf20Sopenharmony_ci	} else if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) {
6708c2ecf20Sopenharmony_ci		ah->eep_ops = &eep_4k_ops;
6718c2ecf20Sopenharmony_ci	} else {
6728c2ecf20Sopenharmony_ci		ah->eep_ops = &eep_def_ops;
6738c2ecf20Sopenharmony_ci	}
6748c2ecf20Sopenharmony_ci
6758c2ecf20Sopenharmony_ci	if (!ah->eep_ops->fill_eeprom(ah))
6768c2ecf20Sopenharmony_ci		return -EIO;
6778c2ecf20Sopenharmony_ci
6788c2ecf20Sopenharmony_ci	status = ah->eep_ops->check_eeprom(ah);
6798c2ecf20Sopenharmony_ci
6808c2ecf20Sopenharmony_ci	return status;
6818c2ecf20Sopenharmony_ci}
682