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, ¢ers); 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, ¢ers); 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, ¢ers); 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