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 <asm/unaligned.h> 188c2ecf20Sopenharmony_ci#include "hw.h" 198c2ecf20Sopenharmony_ci#include "ar9002_phy.h" 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_cistatic void ath9k_get_txgain_index(struct ath_hw *ah, 228c2ecf20Sopenharmony_ci struct ath9k_channel *chan, 238c2ecf20Sopenharmony_ci struct calDataPerFreqOpLoop *rawDatasetOpLoop, 248c2ecf20Sopenharmony_ci u8 *calChans, u16 availPiers, u8 *pwr, u8 *pcdacIdx) 258c2ecf20Sopenharmony_ci{ 268c2ecf20Sopenharmony_ci u8 pcdac, i = 0; 278c2ecf20Sopenharmony_ci u16 idxL = 0, idxR = 0, numPiers; 288c2ecf20Sopenharmony_ci bool match; 298c2ecf20Sopenharmony_ci struct chan_centers centers; 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci ath9k_hw_get_channel_centers(ah, chan, ¢ers); 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci for (numPiers = 0; numPiers < availPiers; numPiers++) 348c2ecf20Sopenharmony_ci if (calChans[numPiers] == AR5416_BCHAN_UNUSED) 358c2ecf20Sopenharmony_ci break; 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci match = ath9k_hw_get_lower_upper_index( 388c2ecf20Sopenharmony_ci (u8)FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan)), 398c2ecf20Sopenharmony_ci calChans, numPiers, &idxL, &idxR); 408c2ecf20Sopenharmony_ci if (match) { 418c2ecf20Sopenharmony_ci pcdac = rawDatasetOpLoop[idxL].pcdac[0][0]; 428c2ecf20Sopenharmony_ci *pwr = rawDatasetOpLoop[idxL].pwrPdg[0][0]; 438c2ecf20Sopenharmony_ci } else { 448c2ecf20Sopenharmony_ci pcdac = rawDatasetOpLoop[idxR].pcdac[0][0]; 458c2ecf20Sopenharmony_ci *pwr = (rawDatasetOpLoop[idxL].pwrPdg[0][0] + 468c2ecf20Sopenharmony_ci rawDatasetOpLoop[idxR].pwrPdg[0][0])/2; 478c2ecf20Sopenharmony_ci } 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci while (pcdac > ah->originalGain[i] && 508c2ecf20Sopenharmony_ci i < (AR9280_TX_GAIN_TABLE_SIZE - 1)) 518c2ecf20Sopenharmony_ci i++; 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci *pcdacIdx = i; 548c2ecf20Sopenharmony_ci} 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_cistatic void ath9k_olc_get_pdadcs(struct ath_hw *ah, 578c2ecf20Sopenharmony_ci u32 initTxGain, 588c2ecf20Sopenharmony_ci int txPower, 598c2ecf20Sopenharmony_ci u8 *pPDADCValues) 608c2ecf20Sopenharmony_ci{ 618c2ecf20Sopenharmony_ci u32 i; 628c2ecf20Sopenharmony_ci u32 offset; 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL6_0, 658c2ecf20Sopenharmony_ci AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3); 668c2ecf20Sopenharmony_ci REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL6_1, 678c2ecf20Sopenharmony_ci AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3); 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL7, 708c2ecf20Sopenharmony_ci AR_PHY_TX_PWRCTRL_INIT_TX_GAIN, initTxGain); 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci offset = txPower; 738c2ecf20Sopenharmony_ci for (i = 0; i < AR5416_NUM_PDADC_VALUES; i++) 748c2ecf20Sopenharmony_ci if (i < offset) 758c2ecf20Sopenharmony_ci pPDADCValues[i] = 0x0; 768c2ecf20Sopenharmony_ci else 778c2ecf20Sopenharmony_ci pPDADCValues[i] = 0xFF; 788c2ecf20Sopenharmony_ci} 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_cistatic int ath9k_hw_def_get_eeprom_ver(struct ath_hw *ah) 818c2ecf20Sopenharmony_ci{ 828c2ecf20Sopenharmony_ci u16 version = le16_to_cpu(ah->eeprom.def.baseEepHeader.version); 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci return (version & AR5416_EEP_VER_MAJOR_MASK) >> 858c2ecf20Sopenharmony_ci AR5416_EEP_VER_MAJOR_SHIFT; 868c2ecf20Sopenharmony_ci} 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_cistatic int ath9k_hw_def_get_eeprom_rev(struct ath_hw *ah) 898c2ecf20Sopenharmony_ci{ 908c2ecf20Sopenharmony_ci u16 version = le16_to_cpu(ah->eeprom.def.baseEepHeader.version); 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci return version & AR5416_EEP_VER_MINOR_MASK; 938c2ecf20Sopenharmony_ci} 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci#define SIZE_EEPROM_DEF (sizeof(struct ar5416_eeprom_def) / sizeof(u16)) 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_cistatic bool __ath9k_hw_def_fill_eeprom(struct ath_hw *ah) 988c2ecf20Sopenharmony_ci{ 998c2ecf20Sopenharmony_ci u16 *eep_data = (u16 *)&ah->eeprom.def; 1008c2ecf20Sopenharmony_ci int addr, ar5416_eep_start_loc = 0x100; 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci for (addr = 0; addr < SIZE_EEPROM_DEF; addr++) { 1038c2ecf20Sopenharmony_ci if (!ath9k_hw_nvram_read(ah, addr + ar5416_eep_start_loc, 1048c2ecf20Sopenharmony_ci eep_data)) 1058c2ecf20Sopenharmony_ci return false; 1068c2ecf20Sopenharmony_ci eep_data++; 1078c2ecf20Sopenharmony_ci } 1088c2ecf20Sopenharmony_ci return true; 1098c2ecf20Sopenharmony_ci} 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_cistatic bool __ath9k_hw_usb_def_fill_eeprom(struct ath_hw *ah) 1128c2ecf20Sopenharmony_ci{ 1138c2ecf20Sopenharmony_ci u16 *eep_data = (u16 *)&ah->eeprom.def; 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci ath9k_hw_usb_gen_fill_eeprom(ah, eep_data, 1168c2ecf20Sopenharmony_ci 0x100, SIZE_EEPROM_DEF); 1178c2ecf20Sopenharmony_ci return true; 1188c2ecf20Sopenharmony_ci} 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_cistatic bool ath9k_hw_def_fill_eeprom(struct ath_hw *ah) 1218c2ecf20Sopenharmony_ci{ 1228c2ecf20Sopenharmony_ci struct ath_common *common = ath9k_hw_common(ah); 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci if (!ath9k_hw_use_flash(ah)) { 1258c2ecf20Sopenharmony_ci ath_dbg(common, EEPROM, "Reading from EEPROM, not flash\n"); 1268c2ecf20Sopenharmony_ci } 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci if (common->bus_ops->ath_bus_type == ATH_USB) 1298c2ecf20Sopenharmony_ci return __ath9k_hw_usb_def_fill_eeprom(ah); 1308c2ecf20Sopenharmony_ci else 1318c2ecf20Sopenharmony_ci return __ath9k_hw_def_fill_eeprom(ah); 1328c2ecf20Sopenharmony_ci} 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci#ifdef CONFIG_ATH9K_COMMON_DEBUG 1358c2ecf20Sopenharmony_cistatic u32 ath9k_def_dump_modal_eeprom(char *buf, u32 len, u32 size, 1368c2ecf20Sopenharmony_ci struct modal_eep_header *modal_hdr) 1378c2ecf20Sopenharmony_ci{ 1388c2ecf20Sopenharmony_ci PR_EEP("Chain0 Ant. Control", le16_to_cpu(modal_hdr->antCtrlChain[0])); 1398c2ecf20Sopenharmony_ci PR_EEP("Chain1 Ant. Control", le16_to_cpu(modal_hdr->antCtrlChain[1])); 1408c2ecf20Sopenharmony_ci PR_EEP("Chain2 Ant. Control", le16_to_cpu(modal_hdr->antCtrlChain[2])); 1418c2ecf20Sopenharmony_ci PR_EEP("Ant. Common Control", le32_to_cpu(modal_hdr->antCtrlCommon)); 1428c2ecf20Sopenharmony_ci PR_EEP("Chain0 Ant. Gain", modal_hdr->antennaGainCh[0]); 1438c2ecf20Sopenharmony_ci PR_EEP("Chain1 Ant. Gain", modal_hdr->antennaGainCh[1]); 1448c2ecf20Sopenharmony_ci PR_EEP("Chain2 Ant. Gain", modal_hdr->antennaGainCh[2]); 1458c2ecf20Sopenharmony_ci PR_EEP("Switch Settle", modal_hdr->switchSettling); 1468c2ecf20Sopenharmony_ci PR_EEP("Chain0 TxRxAtten", modal_hdr->txRxAttenCh[0]); 1478c2ecf20Sopenharmony_ci PR_EEP("Chain1 TxRxAtten", modal_hdr->txRxAttenCh[1]); 1488c2ecf20Sopenharmony_ci PR_EEP("Chain2 TxRxAtten", modal_hdr->txRxAttenCh[2]); 1498c2ecf20Sopenharmony_ci PR_EEP("Chain0 RxTxMargin", modal_hdr->rxTxMarginCh[0]); 1508c2ecf20Sopenharmony_ci PR_EEP("Chain1 RxTxMargin", modal_hdr->rxTxMarginCh[1]); 1518c2ecf20Sopenharmony_ci PR_EEP("Chain2 RxTxMargin", modal_hdr->rxTxMarginCh[2]); 1528c2ecf20Sopenharmony_ci PR_EEP("ADC Desired size", modal_hdr->adcDesiredSize); 1538c2ecf20Sopenharmony_ci PR_EEP("PGA Desired size", modal_hdr->pgaDesiredSize); 1548c2ecf20Sopenharmony_ci PR_EEP("Chain0 xlna Gain", modal_hdr->xlnaGainCh[0]); 1558c2ecf20Sopenharmony_ci PR_EEP("Chain1 xlna Gain", modal_hdr->xlnaGainCh[1]); 1568c2ecf20Sopenharmony_ci PR_EEP("Chain2 xlna Gain", modal_hdr->xlnaGainCh[2]); 1578c2ecf20Sopenharmony_ci PR_EEP("txEndToXpaOff", modal_hdr->txEndToXpaOff); 1588c2ecf20Sopenharmony_ci PR_EEP("txEndToRxOn", modal_hdr->txEndToRxOn); 1598c2ecf20Sopenharmony_ci PR_EEP("txFrameToXpaOn", modal_hdr->txFrameToXpaOn); 1608c2ecf20Sopenharmony_ci PR_EEP("CCA Threshold)", modal_hdr->thresh62); 1618c2ecf20Sopenharmony_ci PR_EEP("Chain0 NF Threshold", modal_hdr->noiseFloorThreshCh[0]); 1628c2ecf20Sopenharmony_ci PR_EEP("Chain1 NF Threshold", modal_hdr->noiseFloorThreshCh[1]); 1638c2ecf20Sopenharmony_ci PR_EEP("Chain2 NF Threshold", modal_hdr->noiseFloorThreshCh[2]); 1648c2ecf20Sopenharmony_ci PR_EEP("xpdGain", modal_hdr->xpdGain); 1658c2ecf20Sopenharmony_ci PR_EEP("External PD", modal_hdr->xpd); 1668c2ecf20Sopenharmony_ci PR_EEP("Chain0 I Coefficient", modal_hdr->iqCalICh[0]); 1678c2ecf20Sopenharmony_ci PR_EEP("Chain1 I Coefficient", modal_hdr->iqCalICh[1]); 1688c2ecf20Sopenharmony_ci PR_EEP("Chain2 I Coefficient", modal_hdr->iqCalICh[2]); 1698c2ecf20Sopenharmony_ci PR_EEP("Chain0 Q Coefficient", modal_hdr->iqCalQCh[0]); 1708c2ecf20Sopenharmony_ci PR_EEP("Chain1 Q Coefficient", modal_hdr->iqCalQCh[1]); 1718c2ecf20Sopenharmony_ci PR_EEP("Chain2 Q Coefficient", modal_hdr->iqCalQCh[2]); 1728c2ecf20Sopenharmony_ci PR_EEP("pdGainOverlap", modal_hdr->pdGainOverlap); 1738c2ecf20Sopenharmony_ci PR_EEP("Chain0 OutputBias", modal_hdr->ob); 1748c2ecf20Sopenharmony_ci PR_EEP("Chain0 DriverBias", modal_hdr->db); 1758c2ecf20Sopenharmony_ci PR_EEP("xPA Bias Level", modal_hdr->xpaBiasLvl); 1768c2ecf20Sopenharmony_ci PR_EEP("2chain pwr decrease", modal_hdr->pwrDecreaseFor2Chain); 1778c2ecf20Sopenharmony_ci PR_EEP("3chain pwr decrease", modal_hdr->pwrDecreaseFor3Chain); 1788c2ecf20Sopenharmony_ci PR_EEP("txFrameToDataStart", modal_hdr->txFrameToDataStart); 1798c2ecf20Sopenharmony_ci PR_EEP("txFrameToPaOn", modal_hdr->txFrameToPaOn); 1808c2ecf20Sopenharmony_ci PR_EEP("HT40 Power Inc.", modal_hdr->ht40PowerIncForPdadc); 1818c2ecf20Sopenharmony_ci PR_EEP("Chain0 bswAtten", modal_hdr->bswAtten[0]); 1828c2ecf20Sopenharmony_ci PR_EEP("Chain1 bswAtten", modal_hdr->bswAtten[1]); 1838c2ecf20Sopenharmony_ci PR_EEP("Chain2 bswAtten", modal_hdr->bswAtten[2]); 1848c2ecf20Sopenharmony_ci PR_EEP("Chain0 bswMargin", modal_hdr->bswMargin[0]); 1858c2ecf20Sopenharmony_ci PR_EEP("Chain1 bswMargin", modal_hdr->bswMargin[1]); 1868c2ecf20Sopenharmony_ci PR_EEP("Chain2 bswMargin", modal_hdr->bswMargin[2]); 1878c2ecf20Sopenharmony_ci PR_EEP("HT40 Switch Settle", modal_hdr->swSettleHt40); 1888c2ecf20Sopenharmony_ci PR_EEP("Chain0 xatten2Db", modal_hdr->xatten2Db[0]); 1898c2ecf20Sopenharmony_ci PR_EEP("Chain1 xatten2Db", modal_hdr->xatten2Db[1]); 1908c2ecf20Sopenharmony_ci PR_EEP("Chain2 xatten2Db", modal_hdr->xatten2Db[2]); 1918c2ecf20Sopenharmony_ci PR_EEP("Chain0 xatten2Margin", modal_hdr->xatten2Margin[0]); 1928c2ecf20Sopenharmony_ci PR_EEP("Chain1 xatten2Margin", modal_hdr->xatten2Margin[1]); 1938c2ecf20Sopenharmony_ci PR_EEP("Chain2 xatten2Margin", modal_hdr->xatten2Margin[2]); 1948c2ecf20Sopenharmony_ci PR_EEP("Chain1 OutputBias", modal_hdr->ob_ch1); 1958c2ecf20Sopenharmony_ci PR_EEP("Chain1 DriverBias", modal_hdr->db_ch1); 1968c2ecf20Sopenharmony_ci PR_EEP("LNA Control", modal_hdr->lna_ctl); 1978c2ecf20Sopenharmony_ci PR_EEP("XPA Bias Freq0", le16_to_cpu(modal_hdr->xpaBiasLvlFreq[0])); 1988c2ecf20Sopenharmony_ci PR_EEP("XPA Bias Freq1", le16_to_cpu(modal_hdr->xpaBiasLvlFreq[1])); 1998c2ecf20Sopenharmony_ci PR_EEP("XPA Bias Freq2", le16_to_cpu(modal_hdr->xpaBiasLvlFreq[2])); 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci return len; 2028c2ecf20Sopenharmony_ci} 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_cistatic u32 ath9k_hw_def_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr, 2058c2ecf20Sopenharmony_ci u8 *buf, u32 len, u32 size) 2068c2ecf20Sopenharmony_ci{ 2078c2ecf20Sopenharmony_ci struct ar5416_eeprom_def *eep = &ah->eeprom.def; 2088c2ecf20Sopenharmony_ci struct base_eep_header *pBase = &eep->baseEepHeader; 2098c2ecf20Sopenharmony_ci u32 binBuildNumber = le32_to_cpu(pBase->binBuildNumber); 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci if (!dump_base_hdr) { 2128c2ecf20Sopenharmony_ci len += scnprintf(buf + len, size - len, 2138c2ecf20Sopenharmony_ci "%20s :\n", "2GHz modal Header"); 2148c2ecf20Sopenharmony_ci len = ath9k_def_dump_modal_eeprom(buf, len, size, 2158c2ecf20Sopenharmony_ci &eep->modalHeader[0]); 2168c2ecf20Sopenharmony_ci len += scnprintf(buf + len, size - len, 2178c2ecf20Sopenharmony_ci "%20s :\n", "5GHz modal Header"); 2188c2ecf20Sopenharmony_ci len = ath9k_def_dump_modal_eeprom(buf, len, size, 2198c2ecf20Sopenharmony_ci &eep->modalHeader[1]); 2208c2ecf20Sopenharmony_ci goto out; 2218c2ecf20Sopenharmony_ci } 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci PR_EEP("Major Version", ath9k_hw_def_get_eeprom_ver(ah)); 2248c2ecf20Sopenharmony_ci PR_EEP("Minor Version", ath9k_hw_def_get_eeprom_rev(ah)); 2258c2ecf20Sopenharmony_ci PR_EEP("Checksum", le16_to_cpu(pBase->checksum)); 2268c2ecf20Sopenharmony_ci PR_EEP("Length", le16_to_cpu(pBase->length)); 2278c2ecf20Sopenharmony_ci PR_EEP("RegDomain1", le16_to_cpu(pBase->regDmn[0])); 2288c2ecf20Sopenharmony_ci PR_EEP("RegDomain2", le16_to_cpu(pBase->regDmn[1])); 2298c2ecf20Sopenharmony_ci PR_EEP("TX Mask", pBase->txMask); 2308c2ecf20Sopenharmony_ci PR_EEP("RX Mask", pBase->rxMask); 2318c2ecf20Sopenharmony_ci PR_EEP("Allow 5GHz", !!(pBase->opCapFlags & AR5416_OPFLAGS_11A)); 2328c2ecf20Sopenharmony_ci PR_EEP("Allow 2GHz", !!(pBase->opCapFlags & AR5416_OPFLAGS_11G)); 2338c2ecf20Sopenharmony_ci PR_EEP("Disable 2GHz HT20", !!(pBase->opCapFlags & 2348c2ecf20Sopenharmony_ci AR5416_OPFLAGS_N_2G_HT20)); 2358c2ecf20Sopenharmony_ci PR_EEP("Disable 2GHz HT40", !!(pBase->opCapFlags & 2368c2ecf20Sopenharmony_ci AR5416_OPFLAGS_N_2G_HT40)); 2378c2ecf20Sopenharmony_ci PR_EEP("Disable 5Ghz HT20", !!(pBase->opCapFlags & 2388c2ecf20Sopenharmony_ci AR5416_OPFLAGS_N_5G_HT20)); 2398c2ecf20Sopenharmony_ci PR_EEP("Disable 5Ghz HT40", !!(pBase->opCapFlags & 2408c2ecf20Sopenharmony_ci AR5416_OPFLAGS_N_5G_HT40)); 2418c2ecf20Sopenharmony_ci PR_EEP("Big Endian", !!(pBase->eepMisc & AR5416_EEPMISC_BIG_ENDIAN)); 2428c2ecf20Sopenharmony_ci PR_EEP("Cal Bin Major Ver", (binBuildNumber >> 24) & 0xFF); 2438c2ecf20Sopenharmony_ci PR_EEP("Cal Bin Minor Ver", (binBuildNumber >> 16) & 0xFF); 2448c2ecf20Sopenharmony_ci PR_EEP("Cal Bin Build", (binBuildNumber >> 8) & 0xFF); 2458c2ecf20Sopenharmony_ci PR_EEP("OpenLoop Power Ctrl", pBase->openLoopPwrCntl); 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci len += scnprintf(buf + len, size - len, "%20s : %pM\n", "MacAddress", 2488c2ecf20Sopenharmony_ci pBase->macAddr); 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ciout: 2518c2ecf20Sopenharmony_ci if (len > size) 2528c2ecf20Sopenharmony_ci len = size; 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_ci return len; 2558c2ecf20Sopenharmony_ci} 2568c2ecf20Sopenharmony_ci#else 2578c2ecf20Sopenharmony_cistatic u32 ath9k_hw_def_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr, 2588c2ecf20Sopenharmony_ci u8 *buf, u32 len, u32 size) 2598c2ecf20Sopenharmony_ci{ 2608c2ecf20Sopenharmony_ci return 0; 2618c2ecf20Sopenharmony_ci} 2628c2ecf20Sopenharmony_ci#endif 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_cistatic int ath9k_hw_def_check_eeprom(struct ath_hw *ah) 2658c2ecf20Sopenharmony_ci{ 2668c2ecf20Sopenharmony_ci struct ar5416_eeprom_def *eep = &ah->eeprom.def; 2678c2ecf20Sopenharmony_ci struct ath_common *common = ath9k_hw_common(ah); 2688c2ecf20Sopenharmony_ci u32 el; 2698c2ecf20Sopenharmony_ci bool need_swap; 2708c2ecf20Sopenharmony_ci int i, err; 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci err = ath9k_hw_nvram_swap_data(ah, &need_swap, SIZE_EEPROM_DEF); 2738c2ecf20Sopenharmony_ci if (err) 2748c2ecf20Sopenharmony_ci return err; 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci if (need_swap) 2778c2ecf20Sopenharmony_ci el = swab16((__force u16)eep->baseEepHeader.length); 2788c2ecf20Sopenharmony_ci else 2798c2ecf20Sopenharmony_ci el = le16_to_cpu(eep->baseEepHeader.length); 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci el = min(el / sizeof(u16), SIZE_EEPROM_DEF); 2828c2ecf20Sopenharmony_ci if (!ath9k_hw_nvram_validate_checksum(ah, el)) 2838c2ecf20Sopenharmony_ci return -EINVAL; 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci if (need_swap) { 2868c2ecf20Sopenharmony_ci u32 j; 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_ci EEPROM_FIELD_SWAB16(eep->baseEepHeader.length); 2898c2ecf20Sopenharmony_ci EEPROM_FIELD_SWAB16(eep->baseEepHeader.checksum); 2908c2ecf20Sopenharmony_ci EEPROM_FIELD_SWAB16(eep->baseEepHeader.version); 2918c2ecf20Sopenharmony_ci EEPROM_FIELD_SWAB16(eep->baseEepHeader.regDmn[0]); 2928c2ecf20Sopenharmony_ci EEPROM_FIELD_SWAB16(eep->baseEepHeader.regDmn[1]); 2938c2ecf20Sopenharmony_ci EEPROM_FIELD_SWAB16(eep->baseEepHeader.rfSilent); 2948c2ecf20Sopenharmony_ci EEPROM_FIELD_SWAB16(eep->baseEepHeader.blueToothOptions); 2958c2ecf20Sopenharmony_ci EEPROM_FIELD_SWAB16(eep->baseEepHeader.deviceCap); 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci for (j = 0; j < ARRAY_SIZE(eep->modalHeader); j++) { 2988c2ecf20Sopenharmony_ci struct modal_eep_header *pModal = 2998c2ecf20Sopenharmony_ci &eep->modalHeader[j]; 3008c2ecf20Sopenharmony_ci EEPROM_FIELD_SWAB32(pModal->antCtrlCommon); 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci for (i = 0; i < AR5416_MAX_CHAINS; i++) 3038c2ecf20Sopenharmony_ci EEPROM_FIELD_SWAB32(pModal->antCtrlChain[i]); 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci for (i = 0; i < 3; i++) 3068c2ecf20Sopenharmony_ci EEPROM_FIELD_SWAB16(pModal->xpaBiasLvlFreq[i]); 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) 3098c2ecf20Sopenharmony_ci EEPROM_FIELD_SWAB16( 3108c2ecf20Sopenharmony_ci pModal->spurChans[i].spurChan); 3118c2ecf20Sopenharmony_ci } 3128c2ecf20Sopenharmony_ci } 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci if (!ath9k_hw_nvram_check_version(ah, AR5416_EEP_VER, 3158c2ecf20Sopenharmony_ci AR5416_EEP_NO_BACK_VER)) 3168c2ecf20Sopenharmony_ci return -EINVAL; 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci /* Enable fixup for AR_AN_TOP2 if necessary */ 3198c2ecf20Sopenharmony_ci if ((ah->hw_version.devid == AR9280_DEVID_PCI) && 3208c2ecf20Sopenharmony_ci ((le16_to_cpu(eep->baseEepHeader.version) & 0xff) > 0x0a) && 3218c2ecf20Sopenharmony_ci (eep->baseEepHeader.pwdclkind == 0)) 3228c2ecf20Sopenharmony_ci ah->need_an_top2_fixup = true; 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ci if ((common->bus_ops->ath_bus_type == ATH_USB) && 3258c2ecf20Sopenharmony_ci (AR_SREV_9280(ah))) 3268c2ecf20Sopenharmony_ci eep->modalHeader[0].xpaBiasLvl = 0; 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci return 0; 3298c2ecf20Sopenharmony_ci} 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci#undef SIZE_EEPROM_DEF 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_cistatic u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah, 3348c2ecf20Sopenharmony_ci enum eeprom_param param) 3358c2ecf20Sopenharmony_ci{ 3368c2ecf20Sopenharmony_ci struct ar5416_eeprom_def *eep = &ah->eeprom.def; 3378c2ecf20Sopenharmony_ci struct modal_eep_header *pModal = eep->modalHeader; 3388c2ecf20Sopenharmony_ci struct base_eep_header *pBase = &eep->baseEepHeader; 3398c2ecf20Sopenharmony_ci int band = 0; 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci switch (param) { 3428c2ecf20Sopenharmony_ci case EEP_NFTHRESH_5: 3438c2ecf20Sopenharmony_ci return pModal[0].noiseFloorThreshCh[0]; 3448c2ecf20Sopenharmony_ci case EEP_NFTHRESH_2: 3458c2ecf20Sopenharmony_ci return pModal[1].noiseFloorThreshCh[0]; 3468c2ecf20Sopenharmony_ci case EEP_MAC_LSW: 3478c2ecf20Sopenharmony_ci return get_unaligned_be16(pBase->macAddr); 3488c2ecf20Sopenharmony_ci case EEP_MAC_MID: 3498c2ecf20Sopenharmony_ci return get_unaligned_be16(pBase->macAddr + 2); 3508c2ecf20Sopenharmony_ci case EEP_MAC_MSW: 3518c2ecf20Sopenharmony_ci return get_unaligned_be16(pBase->macAddr + 4); 3528c2ecf20Sopenharmony_ci case EEP_REG_0: 3538c2ecf20Sopenharmony_ci return le16_to_cpu(pBase->regDmn[0]); 3548c2ecf20Sopenharmony_ci case EEP_OP_CAP: 3558c2ecf20Sopenharmony_ci return le16_to_cpu(pBase->deviceCap); 3568c2ecf20Sopenharmony_ci case EEP_OP_MODE: 3578c2ecf20Sopenharmony_ci return pBase->opCapFlags; 3588c2ecf20Sopenharmony_ci case EEP_RF_SILENT: 3598c2ecf20Sopenharmony_ci return le16_to_cpu(pBase->rfSilent); 3608c2ecf20Sopenharmony_ci case EEP_OB_5: 3618c2ecf20Sopenharmony_ci return pModal[0].ob; 3628c2ecf20Sopenharmony_ci case EEP_DB_5: 3638c2ecf20Sopenharmony_ci return pModal[0].db; 3648c2ecf20Sopenharmony_ci case EEP_OB_2: 3658c2ecf20Sopenharmony_ci return pModal[1].ob; 3668c2ecf20Sopenharmony_ci case EEP_DB_2: 3678c2ecf20Sopenharmony_ci return pModal[1].db; 3688c2ecf20Sopenharmony_ci case EEP_TX_MASK: 3698c2ecf20Sopenharmony_ci return pBase->txMask; 3708c2ecf20Sopenharmony_ci case EEP_RX_MASK: 3718c2ecf20Sopenharmony_ci return pBase->rxMask; 3728c2ecf20Sopenharmony_ci case EEP_FSTCLK_5G: 3738c2ecf20Sopenharmony_ci return pBase->fastClk5g; 3748c2ecf20Sopenharmony_ci case EEP_RXGAIN_TYPE: 3758c2ecf20Sopenharmony_ci return pBase->rxGainType; 3768c2ecf20Sopenharmony_ci case EEP_TXGAIN_TYPE: 3778c2ecf20Sopenharmony_ci return pBase->txGainType; 3788c2ecf20Sopenharmony_ci case EEP_OL_PWRCTRL: 3798c2ecf20Sopenharmony_ci if (ath9k_hw_def_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_19) 3808c2ecf20Sopenharmony_ci return pBase->openLoopPwrCntl ? true : false; 3818c2ecf20Sopenharmony_ci else 3828c2ecf20Sopenharmony_ci return false; 3838c2ecf20Sopenharmony_ci case EEP_RC_CHAIN_MASK: 3848c2ecf20Sopenharmony_ci if (ath9k_hw_def_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_19) 3858c2ecf20Sopenharmony_ci return pBase->rcChainMask; 3868c2ecf20Sopenharmony_ci else 3878c2ecf20Sopenharmony_ci return 0; 3888c2ecf20Sopenharmony_ci case EEP_DAC_HPWR_5G: 3898c2ecf20Sopenharmony_ci if (ath9k_hw_def_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_20) 3908c2ecf20Sopenharmony_ci return pBase->dacHiPwrMode_5G; 3918c2ecf20Sopenharmony_ci else 3928c2ecf20Sopenharmony_ci return 0; 3938c2ecf20Sopenharmony_ci case EEP_FRAC_N_5G: 3948c2ecf20Sopenharmony_ci if (ath9k_hw_def_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_22) 3958c2ecf20Sopenharmony_ci return pBase->frac_n_5g; 3968c2ecf20Sopenharmony_ci else 3978c2ecf20Sopenharmony_ci return 0; 3988c2ecf20Sopenharmony_ci case EEP_PWR_TABLE_OFFSET: 3998c2ecf20Sopenharmony_ci if (ath9k_hw_def_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_21) 4008c2ecf20Sopenharmony_ci return pBase->pwr_table_offset; 4018c2ecf20Sopenharmony_ci else 4028c2ecf20Sopenharmony_ci return AR5416_PWR_TABLE_OFFSET_DB; 4038c2ecf20Sopenharmony_ci case EEP_ANTENNA_GAIN_2G: 4048c2ecf20Sopenharmony_ci band = 1; 4058c2ecf20Sopenharmony_ci fallthrough; 4068c2ecf20Sopenharmony_ci case EEP_ANTENNA_GAIN_5G: 4078c2ecf20Sopenharmony_ci return max_t(u8, max_t(u8, 4088c2ecf20Sopenharmony_ci pModal[band].antennaGainCh[0], 4098c2ecf20Sopenharmony_ci pModal[band].antennaGainCh[1]), 4108c2ecf20Sopenharmony_ci pModal[band].antennaGainCh[2]); 4118c2ecf20Sopenharmony_ci default: 4128c2ecf20Sopenharmony_ci return 0; 4138c2ecf20Sopenharmony_ci } 4148c2ecf20Sopenharmony_ci} 4158c2ecf20Sopenharmony_ci 4168c2ecf20Sopenharmony_cistatic void ath9k_hw_def_set_gain(struct ath_hw *ah, 4178c2ecf20Sopenharmony_ci struct modal_eep_header *pModal, 4188c2ecf20Sopenharmony_ci struct ar5416_eeprom_def *eep, 4198c2ecf20Sopenharmony_ci u8 txRxAttenLocal, int regChainOffset, int i) 4208c2ecf20Sopenharmony_ci{ 4218c2ecf20Sopenharmony_ci ENABLE_REG_RMW_BUFFER(ah); 4228c2ecf20Sopenharmony_ci if (ath9k_hw_def_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_3) { 4238c2ecf20Sopenharmony_ci txRxAttenLocal = pModal->txRxAttenCh[i]; 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_ci if (AR_SREV_9280_20_OR_LATER(ah)) { 4268c2ecf20Sopenharmony_ci REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, 4278c2ecf20Sopenharmony_ci AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, 4288c2ecf20Sopenharmony_ci pModal->bswMargin[i]); 4298c2ecf20Sopenharmony_ci REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, 4308c2ecf20Sopenharmony_ci AR_PHY_GAIN_2GHZ_XATTEN1_DB, 4318c2ecf20Sopenharmony_ci pModal->bswAtten[i]); 4328c2ecf20Sopenharmony_ci REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, 4338c2ecf20Sopenharmony_ci AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN, 4348c2ecf20Sopenharmony_ci pModal->xatten2Margin[i]); 4358c2ecf20Sopenharmony_ci REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, 4368c2ecf20Sopenharmony_ci AR_PHY_GAIN_2GHZ_XATTEN2_DB, 4378c2ecf20Sopenharmony_ci pModal->xatten2Db[i]); 4388c2ecf20Sopenharmony_ci } else { 4398c2ecf20Sopenharmony_ci REG_RMW(ah, AR_PHY_GAIN_2GHZ + regChainOffset, 4408c2ecf20Sopenharmony_ci SM(pModal-> bswMargin[i], AR_PHY_GAIN_2GHZ_BSW_MARGIN), 4418c2ecf20Sopenharmony_ci AR_PHY_GAIN_2GHZ_BSW_MARGIN); 4428c2ecf20Sopenharmony_ci REG_RMW(ah, AR_PHY_GAIN_2GHZ + regChainOffset, 4438c2ecf20Sopenharmony_ci SM(pModal->bswAtten[i], AR_PHY_GAIN_2GHZ_BSW_ATTEN), 4448c2ecf20Sopenharmony_ci AR_PHY_GAIN_2GHZ_BSW_ATTEN); 4458c2ecf20Sopenharmony_ci } 4468c2ecf20Sopenharmony_ci } 4478c2ecf20Sopenharmony_ci 4488c2ecf20Sopenharmony_ci if (AR_SREV_9280_20_OR_LATER(ah)) { 4498c2ecf20Sopenharmony_ci REG_RMW_FIELD(ah, 4508c2ecf20Sopenharmony_ci AR_PHY_RXGAIN + regChainOffset, 4518c2ecf20Sopenharmony_ci AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal); 4528c2ecf20Sopenharmony_ci REG_RMW_FIELD(ah, 4538c2ecf20Sopenharmony_ci AR_PHY_RXGAIN + regChainOffset, 4548c2ecf20Sopenharmony_ci AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[i]); 4558c2ecf20Sopenharmony_ci } else { 4568c2ecf20Sopenharmony_ci REG_RMW(ah, AR_PHY_RXGAIN + regChainOffset, 4578c2ecf20Sopenharmony_ci SM(txRxAttenLocal, AR_PHY_RXGAIN_TXRX_ATTEN), 4588c2ecf20Sopenharmony_ci AR_PHY_RXGAIN_TXRX_ATTEN); 4598c2ecf20Sopenharmony_ci REG_RMW(ah, AR_PHY_GAIN_2GHZ + regChainOffset, 4608c2ecf20Sopenharmony_ci SM(pModal->rxTxMarginCh[i], AR_PHY_GAIN_2GHZ_RXTX_MARGIN), 4618c2ecf20Sopenharmony_ci AR_PHY_GAIN_2GHZ_RXTX_MARGIN); 4628c2ecf20Sopenharmony_ci } 4638c2ecf20Sopenharmony_ci REG_RMW_BUFFER_FLUSH(ah); 4648c2ecf20Sopenharmony_ci} 4658c2ecf20Sopenharmony_ci 4668c2ecf20Sopenharmony_cistatic void ath9k_hw_def_set_board_values(struct ath_hw *ah, 4678c2ecf20Sopenharmony_ci struct ath9k_channel *chan) 4688c2ecf20Sopenharmony_ci{ 4698c2ecf20Sopenharmony_ci struct modal_eep_header *pModal; 4708c2ecf20Sopenharmony_ci struct ar5416_eeprom_def *eep = &ah->eeprom.def; 4718c2ecf20Sopenharmony_ci int i, regChainOffset; 4728c2ecf20Sopenharmony_ci u8 txRxAttenLocal; 4738c2ecf20Sopenharmony_ci u32 antCtrlCommon; 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_ci pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]); 4768c2ecf20Sopenharmony_ci txRxAttenLocal = IS_CHAN_2GHZ(chan) ? 23 : 44; 4778c2ecf20Sopenharmony_ci antCtrlCommon = le32_to_cpu(pModal->antCtrlCommon); 4788c2ecf20Sopenharmony_ci 4798c2ecf20Sopenharmony_ci REG_WRITE(ah, AR_PHY_SWITCH_COM, antCtrlCommon & 0xffff); 4808c2ecf20Sopenharmony_ci 4818c2ecf20Sopenharmony_ci for (i = 0; i < AR5416_MAX_CHAINS; i++) { 4828c2ecf20Sopenharmony_ci if (AR_SREV_9280(ah)) { 4838c2ecf20Sopenharmony_ci if (i >= 2) 4848c2ecf20Sopenharmony_ci break; 4858c2ecf20Sopenharmony_ci } 4868c2ecf20Sopenharmony_ci 4878c2ecf20Sopenharmony_ci if ((ah->rxchainmask == 5 || ah->txchainmask == 5) && (i != 0)) 4888c2ecf20Sopenharmony_ci regChainOffset = (i == 1) ? 0x2000 : 0x1000; 4898c2ecf20Sopenharmony_ci else 4908c2ecf20Sopenharmony_ci regChainOffset = i * 0x1000; 4918c2ecf20Sopenharmony_ci 4928c2ecf20Sopenharmony_ci REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset, 4938c2ecf20Sopenharmony_ci le32_to_cpu(pModal->antCtrlChain[i])); 4948c2ecf20Sopenharmony_ci 4958c2ecf20Sopenharmony_ci REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset, 4968c2ecf20Sopenharmony_ci (REG_READ(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset) & 4978c2ecf20Sopenharmony_ci ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF | 4988c2ecf20Sopenharmony_ci AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) | 4998c2ecf20Sopenharmony_ci SM(pModal->iqCalICh[i], 5008c2ecf20Sopenharmony_ci AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) | 5018c2ecf20Sopenharmony_ci SM(pModal->iqCalQCh[i], 5028c2ecf20Sopenharmony_ci AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF)); 5038c2ecf20Sopenharmony_ci 5048c2ecf20Sopenharmony_ci ath9k_hw_def_set_gain(ah, pModal, eep, txRxAttenLocal, 5058c2ecf20Sopenharmony_ci regChainOffset, i); 5068c2ecf20Sopenharmony_ci } 5078c2ecf20Sopenharmony_ci 5088c2ecf20Sopenharmony_ci if (AR_SREV_9280_20_OR_LATER(ah)) { 5098c2ecf20Sopenharmony_ci if (IS_CHAN_2GHZ(chan)) { 5108c2ecf20Sopenharmony_ci ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0, 5118c2ecf20Sopenharmony_ci AR_AN_RF2G1_CH0_OB, 5128c2ecf20Sopenharmony_ci AR_AN_RF2G1_CH0_OB_S, 5138c2ecf20Sopenharmony_ci pModal->ob); 5148c2ecf20Sopenharmony_ci ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0, 5158c2ecf20Sopenharmony_ci AR_AN_RF2G1_CH0_DB, 5168c2ecf20Sopenharmony_ci AR_AN_RF2G1_CH0_DB_S, 5178c2ecf20Sopenharmony_ci pModal->db); 5188c2ecf20Sopenharmony_ci ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH1, 5198c2ecf20Sopenharmony_ci AR_AN_RF2G1_CH1_OB, 5208c2ecf20Sopenharmony_ci AR_AN_RF2G1_CH1_OB_S, 5218c2ecf20Sopenharmony_ci pModal->ob_ch1); 5228c2ecf20Sopenharmony_ci ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH1, 5238c2ecf20Sopenharmony_ci AR_AN_RF2G1_CH1_DB, 5248c2ecf20Sopenharmony_ci AR_AN_RF2G1_CH1_DB_S, 5258c2ecf20Sopenharmony_ci pModal->db_ch1); 5268c2ecf20Sopenharmony_ci } else { 5278c2ecf20Sopenharmony_ci ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH0, 5288c2ecf20Sopenharmony_ci AR_AN_RF5G1_CH0_OB5, 5298c2ecf20Sopenharmony_ci AR_AN_RF5G1_CH0_OB5_S, 5308c2ecf20Sopenharmony_ci pModal->ob); 5318c2ecf20Sopenharmony_ci ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH0, 5328c2ecf20Sopenharmony_ci AR_AN_RF5G1_CH0_DB5, 5338c2ecf20Sopenharmony_ci AR_AN_RF5G1_CH0_DB5_S, 5348c2ecf20Sopenharmony_ci pModal->db); 5358c2ecf20Sopenharmony_ci ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH1, 5368c2ecf20Sopenharmony_ci AR_AN_RF5G1_CH1_OB5, 5378c2ecf20Sopenharmony_ci AR_AN_RF5G1_CH1_OB5_S, 5388c2ecf20Sopenharmony_ci pModal->ob_ch1); 5398c2ecf20Sopenharmony_ci ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH1, 5408c2ecf20Sopenharmony_ci AR_AN_RF5G1_CH1_DB5, 5418c2ecf20Sopenharmony_ci AR_AN_RF5G1_CH1_DB5_S, 5428c2ecf20Sopenharmony_ci pModal->db_ch1); 5438c2ecf20Sopenharmony_ci } 5448c2ecf20Sopenharmony_ci ath9k_hw_analog_shift_rmw(ah, AR_AN_TOP2, 5458c2ecf20Sopenharmony_ci AR_AN_TOP2_XPABIAS_LVL, 5468c2ecf20Sopenharmony_ci AR_AN_TOP2_XPABIAS_LVL_S, 5478c2ecf20Sopenharmony_ci pModal->xpaBiasLvl); 5488c2ecf20Sopenharmony_ci ath9k_hw_analog_shift_rmw(ah, AR_AN_TOP2, 5498c2ecf20Sopenharmony_ci AR_AN_TOP2_LOCALBIAS, 5508c2ecf20Sopenharmony_ci AR_AN_TOP2_LOCALBIAS_S, 5518c2ecf20Sopenharmony_ci !!(pModal->lna_ctl & 5528c2ecf20Sopenharmony_ci LNA_CTL_LOCAL_BIAS)); 5538c2ecf20Sopenharmony_ci REG_RMW_FIELD(ah, AR_PHY_XPA_CFG, AR_PHY_FORCE_XPA_CFG, 5548c2ecf20Sopenharmony_ci !!(pModal->lna_ctl & LNA_CTL_FORCE_XPA)); 5558c2ecf20Sopenharmony_ci } 5568c2ecf20Sopenharmony_ci 5578c2ecf20Sopenharmony_ci REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH, 5588c2ecf20Sopenharmony_ci pModal->switchSettling); 5598c2ecf20Sopenharmony_ci REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC, 5608c2ecf20Sopenharmony_ci pModal->adcDesiredSize); 5618c2ecf20Sopenharmony_ci 5628c2ecf20Sopenharmony_ci if (!AR_SREV_9280_20_OR_LATER(ah)) 5638c2ecf20Sopenharmony_ci REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, 5648c2ecf20Sopenharmony_ci AR_PHY_DESIRED_SZ_PGA, 5658c2ecf20Sopenharmony_ci pModal->pgaDesiredSize); 5668c2ecf20Sopenharmony_ci 5678c2ecf20Sopenharmony_ci REG_WRITE(ah, AR_PHY_RF_CTL4, 5688c2ecf20Sopenharmony_ci SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF) 5698c2ecf20Sopenharmony_ci | SM(pModal->txEndToXpaOff, 5708c2ecf20Sopenharmony_ci AR_PHY_RF_CTL4_TX_END_XPAB_OFF) 5718c2ecf20Sopenharmony_ci | SM(pModal->txFrameToXpaOn, 5728c2ecf20Sopenharmony_ci AR_PHY_RF_CTL4_FRAME_XPAA_ON) 5738c2ecf20Sopenharmony_ci | SM(pModal->txFrameToXpaOn, 5748c2ecf20Sopenharmony_ci AR_PHY_RF_CTL4_FRAME_XPAB_ON)); 5758c2ecf20Sopenharmony_ci 5768c2ecf20Sopenharmony_ci REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON, 5778c2ecf20Sopenharmony_ci pModal->txEndToRxOn); 5788c2ecf20Sopenharmony_ci 5798c2ecf20Sopenharmony_ci if (AR_SREV_9280_20_OR_LATER(ah)) { 5808c2ecf20Sopenharmony_ci REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62, 5818c2ecf20Sopenharmony_ci pModal->thresh62); 5828c2ecf20Sopenharmony_ci REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, 5838c2ecf20Sopenharmony_ci AR_PHY_EXT_CCA0_THRESH62, 5848c2ecf20Sopenharmony_ci pModal->thresh62); 5858c2ecf20Sopenharmony_ci } else { 5868c2ecf20Sopenharmony_ci REG_RMW_FIELD(ah, AR_PHY_CCA, AR_PHY_CCA_THRESH62, 5878c2ecf20Sopenharmony_ci pModal->thresh62); 5888c2ecf20Sopenharmony_ci REG_RMW_FIELD(ah, AR_PHY_EXT_CCA, 5898c2ecf20Sopenharmony_ci AR_PHY_EXT_CCA_THRESH62, 5908c2ecf20Sopenharmony_ci pModal->thresh62); 5918c2ecf20Sopenharmony_ci } 5928c2ecf20Sopenharmony_ci 5938c2ecf20Sopenharmony_ci if (ath9k_hw_def_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_2) { 5948c2ecf20Sopenharmony_ci REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, 5958c2ecf20Sopenharmony_ci AR_PHY_TX_END_DATA_START, 5968c2ecf20Sopenharmony_ci pModal->txFrameToDataStart); 5978c2ecf20Sopenharmony_ci REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_PA_ON, 5988c2ecf20Sopenharmony_ci pModal->txFrameToPaOn); 5998c2ecf20Sopenharmony_ci } 6008c2ecf20Sopenharmony_ci 6018c2ecf20Sopenharmony_ci if (ath9k_hw_def_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_3) { 6028c2ecf20Sopenharmony_ci if (IS_CHAN_HT40(chan)) 6038c2ecf20Sopenharmony_ci REG_RMW_FIELD(ah, AR_PHY_SETTLING, 6048c2ecf20Sopenharmony_ci AR_PHY_SETTLING_SWITCH, 6058c2ecf20Sopenharmony_ci pModal->swSettleHt40); 6068c2ecf20Sopenharmony_ci } 6078c2ecf20Sopenharmony_ci 6088c2ecf20Sopenharmony_ci if (AR_SREV_9280_20_OR_LATER(ah) && 6098c2ecf20Sopenharmony_ci ath9k_hw_def_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_19) 6108c2ecf20Sopenharmony_ci REG_RMW_FIELD(ah, AR_PHY_CCK_TX_CTRL, 6118c2ecf20Sopenharmony_ci AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK, 6128c2ecf20Sopenharmony_ci pModal->miscBits); 6138c2ecf20Sopenharmony_ci 6148c2ecf20Sopenharmony_ci 6158c2ecf20Sopenharmony_ci if (AR_SREV_9280_20(ah) && 6168c2ecf20Sopenharmony_ci ath9k_hw_def_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_20) { 6178c2ecf20Sopenharmony_ci if (IS_CHAN_2GHZ(chan)) 6188c2ecf20Sopenharmony_ci REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE, 6198c2ecf20Sopenharmony_ci eep->baseEepHeader.dacLpMode); 6208c2ecf20Sopenharmony_ci else if (eep->baseEepHeader.dacHiPwrMode_5G) 6218c2ecf20Sopenharmony_ci REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE, 0); 6228c2ecf20Sopenharmony_ci else 6238c2ecf20Sopenharmony_ci REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE, 6248c2ecf20Sopenharmony_ci eep->baseEepHeader.dacLpMode); 6258c2ecf20Sopenharmony_ci 6268c2ecf20Sopenharmony_ci udelay(100); 6278c2ecf20Sopenharmony_ci 6288c2ecf20Sopenharmony_ci REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL, AR_PHY_FRAME_CTL_TX_CLIP, 6298c2ecf20Sopenharmony_ci pModal->miscBits >> 2); 6308c2ecf20Sopenharmony_ci 6318c2ecf20Sopenharmony_ci REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL9, 6328c2ecf20Sopenharmony_ci AR_PHY_TX_DESIRED_SCALE_CCK, 6338c2ecf20Sopenharmony_ci eep->baseEepHeader.desiredScaleCCK); 6348c2ecf20Sopenharmony_ci } 6358c2ecf20Sopenharmony_ci} 6368c2ecf20Sopenharmony_ci 6378c2ecf20Sopenharmony_cistatic void ath9k_hw_def_set_addac(struct ath_hw *ah, 6388c2ecf20Sopenharmony_ci struct ath9k_channel *chan) 6398c2ecf20Sopenharmony_ci{ 6408c2ecf20Sopenharmony_ci#define XPA_LVL_FREQ(cnt) (le16_to_cpu(pModal->xpaBiasLvlFreq[cnt])) 6418c2ecf20Sopenharmony_ci struct modal_eep_header *pModal; 6428c2ecf20Sopenharmony_ci struct ar5416_eeprom_def *eep = &ah->eeprom.def; 6438c2ecf20Sopenharmony_ci u8 biaslevel; 6448c2ecf20Sopenharmony_ci 6458c2ecf20Sopenharmony_ci if (ah->hw_version.macVersion != AR_SREV_VERSION_9160) 6468c2ecf20Sopenharmony_ci return; 6478c2ecf20Sopenharmony_ci 6488c2ecf20Sopenharmony_ci if (ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_MINOR_VER_7) 6498c2ecf20Sopenharmony_ci return; 6508c2ecf20Sopenharmony_ci 6518c2ecf20Sopenharmony_ci pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]); 6528c2ecf20Sopenharmony_ci 6538c2ecf20Sopenharmony_ci if (pModal->xpaBiasLvl != 0xff) { 6548c2ecf20Sopenharmony_ci biaslevel = pModal->xpaBiasLvl; 6558c2ecf20Sopenharmony_ci } else { 6568c2ecf20Sopenharmony_ci u16 resetFreqBin, freqBin, freqCount = 0; 6578c2ecf20Sopenharmony_ci struct chan_centers centers; 6588c2ecf20Sopenharmony_ci 6598c2ecf20Sopenharmony_ci ath9k_hw_get_channel_centers(ah, chan, ¢ers); 6608c2ecf20Sopenharmony_ci 6618c2ecf20Sopenharmony_ci resetFreqBin = FREQ2FBIN(centers.synth_center, 6628c2ecf20Sopenharmony_ci IS_CHAN_2GHZ(chan)); 6638c2ecf20Sopenharmony_ci freqBin = XPA_LVL_FREQ(0) & 0xff; 6648c2ecf20Sopenharmony_ci biaslevel = (u8) (XPA_LVL_FREQ(0) >> 14); 6658c2ecf20Sopenharmony_ci 6668c2ecf20Sopenharmony_ci freqCount++; 6678c2ecf20Sopenharmony_ci 6688c2ecf20Sopenharmony_ci while (freqCount < 3) { 6698c2ecf20Sopenharmony_ci if (XPA_LVL_FREQ(freqCount) == 0x0) 6708c2ecf20Sopenharmony_ci break; 6718c2ecf20Sopenharmony_ci 6728c2ecf20Sopenharmony_ci freqBin = XPA_LVL_FREQ(freqCount) & 0xff; 6738c2ecf20Sopenharmony_ci if (resetFreqBin >= freqBin) 6748c2ecf20Sopenharmony_ci biaslevel = (u8)(XPA_LVL_FREQ(freqCount) >> 14); 6758c2ecf20Sopenharmony_ci else 6768c2ecf20Sopenharmony_ci break; 6778c2ecf20Sopenharmony_ci freqCount++; 6788c2ecf20Sopenharmony_ci } 6798c2ecf20Sopenharmony_ci } 6808c2ecf20Sopenharmony_ci 6818c2ecf20Sopenharmony_ci if (IS_CHAN_2GHZ(chan)) { 6828c2ecf20Sopenharmony_ci INI_RA(&ah->iniAddac, 7, 1) = (INI_RA(&ah->iniAddac, 6838c2ecf20Sopenharmony_ci 7, 1) & (~0x18)) | biaslevel << 3; 6848c2ecf20Sopenharmony_ci } else { 6858c2ecf20Sopenharmony_ci INI_RA(&ah->iniAddac, 6, 1) = (INI_RA(&ah->iniAddac, 6868c2ecf20Sopenharmony_ci 6, 1) & (~0xc0)) | biaslevel << 6; 6878c2ecf20Sopenharmony_ci } 6888c2ecf20Sopenharmony_ci#undef XPA_LVL_FREQ 6898c2ecf20Sopenharmony_ci} 6908c2ecf20Sopenharmony_ci 6918c2ecf20Sopenharmony_cistatic int16_t ath9k_change_gain_boundary_setting(struct ath_hw *ah, 6928c2ecf20Sopenharmony_ci u16 *gb, 6938c2ecf20Sopenharmony_ci u16 numXpdGain, 6948c2ecf20Sopenharmony_ci u16 pdGainOverlap_t2, 6958c2ecf20Sopenharmony_ci int8_t pwr_table_offset, 6968c2ecf20Sopenharmony_ci int16_t *diff) 6978c2ecf20Sopenharmony_ci 6988c2ecf20Sopenharmony_ci{ 6998c2ecf20Sopenharmony_ci u16 k; 7008c2ecf20Sopenharmony_ci 7018c2ecf20Sopenharmony_ci /* Prior to writing the boundaries or the pdadc vs. power table 7028c2ecf20Sopenharmony_ci * into the chip registers the default starting point on the pdadc 7038c2ecf20Sopenharmony_ci * vs. power table needs to be checked and the curve boundaries 7048c2ecf20Sopenharmony_ci * adjusted accordingly 7058c2ecf20Sopenharmony_ci */ 7068c2ecf20Sopenharmony_ci if (AR_SREV_9280_20_OR_LATER(ah)) { 7078c2ecf20Sopenharmony_ci u16 gb_limit; 7088c2ecf20Sopenharmony_ci 7098c2ecf20Sopenharmony_ci if (AR5416_PWR_TABLE_OFFSET_DB != pwr_table_offset) { 7108c2ecf20Sopenharmony_ci /* get the difference in dB */ 7118c2ecf20Sopenharmony_ci *diff = (u16)(pwr_table_offset - AR5416_PWR_TABLE_OFFSET_DB); 7128c2ecf20Sopenharmony_ci /* get the number of half dB steps */ 7138c2ecf20Sopenharmony_ci *diff *= 2; 7148c2ecf20Sopenharmony_ci /* change the original gain boundary settings 7158c2ecf20Sopenharmony_ci * by the number of half dB steps 7168c2ecf20Sopenharmony_ci */ 7178c2ecf20Sopenharmony_ci for (k = 0; k < numXpdGain; k++) 7188c2ecf20Sopenharmony_ci gb[k] = (u16)(gb[k] - *diff); 7198c2ecf20Sopenharmony_ci } 7208c2ecf20Sopenharmony_ci /* Because of a hardware limitation, ensure the gain boundary 7218c2ecf20Sopenharmony_ci * is not larger than (63 - overlap) 7228c2ecf20Sopenharmony_ci */ 7238c2ecf20Sopenharmony_ci gb_limit = (u16)(MAX_RATE_POWER - pdGainOverlap_t2); 7248c2ecf20Sopenharmony_ci 7258c2ecf20Sopenharmony_ci for (k = 0; k < numXpdGain; k++) 7268c2ecf20Sopenharmony_ci gb[k] = (u16)min(gb_limit, gb[k]); 7278c2ecf20Sopenharmony_ci } 7288c2ecf20Sopenharmony_ci 7298c2ecf20Sopenharmony_ci return *diff; 7308c2ecf20Sopenharmony_ci} 7318c2ecf20Sopenharmony_ci 7328c2ecf20Sopenharmony_cistatic void ath9k_adjust_pdadc_values(struct ath_hw *ah, 7338c2ecf20Sopenharmony_ci int8_t pwr_table_offset, 7348c2ecf20Sopenharmony_ci int16_t diff, 7358c2ecf20Sopenharmony_ci u8 *pdadcValues) 7368c2ecf20Sopenharmony_ci{ 7378c2ecf20Sopenharmony_ci#define NUM_PDADC(diff) (AR5416_NUM_PDADC_VALUES - diff) 7388c2ecf20Sopenharmony_ci u16 k; 7398c2ecf20Sopenharmony_ci 7408c2ecf20Sopenharmony_ci /* If this is a board that has a pwrTableOffset that differs from 7418c2ecf20Sopenharmony_ci * the default AR5416_PWR_TABLE_OFFSET_DB then the start of the 7428c2ecf20Sopenharmony_ci * pdadc vs pwr table needs to be adjusted prior to writing to the 7438c2ecf20Sopenharmony_ci * chip. 7448c2ecf20Sopenharmony_ci */ 7458c2ecf20Sopenharmony_ci if (AR_SREV_9280_20_OR_LATER(ah)) { 7468c2ecf20Sopenharmony_ci if (AR5416_PWR_TABLE_OFFSET_DB != pwr_table_offset) { 7478c2ecf20Sopenharmony_ci /* shift the table to start at the new offset */ 7488c2ecf20Sopenharmony_ci for (k = 0; k < (u16)NUM_PDADC(diff); k++ ) { 7498c2ecf20Sopenharmony_ci pdadcValues[k] = pdadcValues[k + diff]; 7508c2ecf20Sopenharmony_ci } 7518c2ecf20Sopenharmony_ci 7528c2ecf20Sopenharmony_ci /* fill the back of the table */ 7538c2ecf20Sopenharmony_ci for (k = (u16)NUM_PDADC(diff); k < NUM_PDADC(0); k++) { 7548c2ecf20Sopenharmony_ci pdadcValues[k] = pdadcValues[NUM_PDADC(diff)]; 7558c2ecf20Sopenharmony_ci } 7568c2ecf20Sopenharmony_ci } 7578c2ecf20Sopenharmony_ci } 7588c2ecf20Sopenharmony_ci#undef NUM_PDADC 7598c2ecf20Sopenharmony_ci} 7608c2ecf20Sopenharmony_ci 7618c2ecf20Sopenharmony_cistatic void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah, 7628c2ecf20Sopenharmony_ci struct ath9k_channel *chan) 7638c2ecf20Sopenharmony_ci{ 7648c2ecf20Sopenharmony_ci#define SM_PD_GAIN(x) SM(0x38, AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_##x) 7658c2ecf20Sopenharmony_ci#define SM_PDGAIN_B(x, y) \ 7668c2ecf20Sopenharmony_ci SM((gainBoundaries[x]), AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_##y) 7678c2ecf20Sopenharmony_ci struct ath_common *common = ath9k_hw_common(ah); 7688c2ecf20Sopenharmony_ci struct ar5416_eeprom_def *pEepData = &ah->eeprom.def; 7698c2ecf20Sopenharmony_ci struct cal_data_per_freq *pRawDataset; 7708c2ecf20Sopenharmony_ci u8 *pCalBChans = NULL; 7718c2ecf20Sopenharmony_ci u16 pdGainOverlap_t2; 7728c2ecf20Sopenharmony_ci static u8 pdadcValues[AR5416_NUM_PDADC_VALUES]; 7738c2ecf20Sopenharmony_ci u16 gainBoundaries[AR5416_PD_GAINS_IN_MASK]; 7748c2ecf20Sopenharmony_ci u16 numPiers, i, j; 7758c2ecf20Sopenharmony_ci int16_t diff = 0; 7768c2ecf20Sopenharmony_ci u16 numXpdGain, xpdMask; 7778c2ecf20Sopenharmony_ci u16 xpdGainValues[AR5416_NUM_PD_GAINS] = { 0, 0, 0, 0 }; 7788c2ecf20Sopenharmony_ci u32 reg32, regOffset, regChainOffset; 7798c2ecf20Sopenharmony_ci int16_t modalIdx; 7808c2ecf20Sopenharmony_ci int8_t pwr_table_offset; 7818c2ecf20Sopenharmony_ci 7828c2ecf20Sopenharmony_ci modalIdx = IS_CHAN_2GHZ(chan) ? 1 : 0; 7838c2ecf20Sopenharmony_ci xpdMask = pEepData->modalHeader[modalIdx].xpdGain; 7848c2ecf20Sopenharmony_ci 7858c2ecf20Sopenharmony_ci pwr_table_offset = ah->eep_ops->get_eeprom(ah, EEP_PWR_TABLE_OFFSET); 7868c2ecf20Sopenharmony_ci 7878c2ecf20Sopenharmony_ci if (ath9k_hw_def_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_2) { 7888c2ecf20Sopenharmony_ci pdGainOverlap_t2 = 7898c2ecf20Sopenharmony_ci pEepData->modalHeader[modalIdx].pdGainOverlap; 7908c2ecf20Sopenharmony_ci } else { 7918c2ecf20Sopenharmony_ci pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5), 7928c2ecf20Sopenharmony_ci AR_PHY_TPCRG5_PD_GAIN_OVERLAP)); 7938c2ecf20Sopenharmony_ci } 7948c2ecf20Sopenharmony_ci 7958c2ecf20Sopenharmony_ci if (IS_CHAN_2GHZ(chan)) { 7968c2ecf20Sopenharmony_ci pCalBChans = pEepData->calFreqPier2G; 7978c2ecf20Sopenharmony_ci numPiers = AR5416_NUM_2G_CAL_PIERS; 7988c2ecf20Sopenharmony_ci } else { 7998c2ecf20Sopenharmony_ci pCalBChans = pEepData->calFreqPier5G; 8008c2ecf20Sopenharmony_ci numPiers = AR5416_NUM_5G_CAL_PIERS; 8018c2ecf20Sopenharmony_ci } 8028c2ecf20Sopenharmony_ci 8038c2ecf20Sopenharmony_ci if (OLC_FOR_AR9280_20_LATER && IS_CHAN_2GHZ(chan)) { 8048c2ecf20Sopenharmony_ci pRawDataset = pEepData->calPierData2G[0]; 8058c2ecf20Sopenharmony_ci ah->initPDADC = ((struct calDataPerFreqOpLoop *) 8068c2ecf20Sopenharmony_ci pRawDataset)->vpdPdg[0][0]; 8078c2ecf20Sopenharmony_ci } 8088c2ecf20Sopenharmony_ci 8098c2ecf20Sopenharmony_ci numXpdGain = 0; 8108c2ecf20Sopenharmony_ci 8118c2ecf20Sopenharmony_ci for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) { 8128c2ecf20Sopenharmony_ci if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) { 8138c2ecf20Sopenharmony_ci if (numXpdGain >= AR5416_NUM_PD_GAINS) 8148c2ecf20Sopenharmony_ci break; 8158c2ecf20Sopenharmony_ci xpdGainValues[numXpdGain] = 8168c2ecf20Sopenharmony_ci (u16)(AR5416_PD_GAINS_IN_MASK - i); 8178c2ecf20Sopenharmony_ci numXpdGain++; 8188c2ecf20Sopenharmony_ci } 8198c2ecf20Sopenharmony_ci } 8208c2ecf20Sopenharmony_ci 8218c2ecf20Sopenharmony_ci REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN, 8228c2ecf20Sopenharmony_ci (numXpdGain - 1) & 0x3); 8238c2ecf20Sopenharmony_ci REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1, 8248c2ecf20Sopenharmony_ci xpdGainValues[0]); 8258c2ecf20Sopenharmony_ci REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2, 8268c2ecf20Sopenharmony_ci xpdGainValues[1]); 8278c2ecf20Sopenharmony_ci REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3, 8288c2ecf20Sopenharmony_ci xpdGainValues[2]); 8298c2ecf20Sopenharmony_ci 8308c2ecf20Sopenharmony_ci for (i = 0; i < AR5416_MAX_CHAINS; i++) { 8318c2ecf20Sopenharmony_ci if ((ah->rxchainmask == 5 || ah->txchainmask == 5) && 8328c2ecf20Sopenharmony_ci (i != 0)) { 8338c2ecf20Sopenharmony_ci regChainOffset = (i == 1) ? 0x2000 : 0x1000; 8348c2ecf20Sopenharmony_ci } else 8358c2ecf20Sopenharmony_ci regChainOffset = i * 0x1000; 8368c2ecf20Sopenharmony_ci 8378c2ecf20Sopenharmony_ci if (pEepData->baseEepHeader.txMask & (1 << i)) { 8388c2ecf20Sopenharmony_ci if (IS_CHAN_2GHZ(chan)) 8398c2ecf20Sopenharmony_ci pRawDataset = pEepData->calPierData2G[i]; 8408c2ecf20Sopenharmony_ci else 8418c2ecf20Sopenharmony_ci pRawDataset = pEepData->calPierData5G[i]; 8428c2ecf20Sopenharmony_ci 8438c2ecf20Sopenharmony_ci 8448c2ecf20Sopenharmony_ci if (OLC_FOR_AR9280_20_LATER) { 8458c2ecf20Sopenharmony_ci u8 pcdacIdx; 8468c2ecf20Sopenharmony_ci u8 txPower; 8478c2ecf20Sopenharmony_ci 8488c2ecf20Sopenharmony_ci ath9k_get_txgain_index(ah, chan, 8498c2ecf20Sopenharmony_ci (struct calDataPerFreqOpLoop *)pRawDataset, 8508c2ecf20Sopenharmony_ci pCalBChans, numPiers, &txPower, &pcdacIdx); 8518c2ecf20Sopenharmony_ci ath9k_olc_get_pdadcs(ah, pcdacIdx, 8528c2ecf20Sopenharmony_ci txPower/2, pdadcValues); 8538c2ecf20Sopenharmony_ci } else { 8548c2ecf20Sopenharmony_ci ath9k_hw_get_gain_boundaries_pdadcs(ah, 8558c2ecf20Sopenharmony_ci chan, pRawDataset, 8568c2ecf20Sopenharmony_ci pCalBChans, numPiers, 8578c2ecf20Sopenharmony_ci pdGainOverlap_t2, 8588c2ecf20Sopenharmony_ci gainBoundaries, 8598c2ecf20Sopenharmony_ci pdadcValues, 8608c2ecf20Sopenharmony_ci numXpdGain); 8618c2ecf20Sopenharmony_ci } 8628c2ecf20Sopenharmony_ci 8638c2ecf20Sopenharmony_ci diff = ath9k_change_gain_boundary_setting(ah, 8648c2ecf20Sopenharmony_ci gainBoundaries, 8658c2ecf20Sopenharmony_ci numXpdGain, 8668c2ecf20Sopenharmony_ci pdGainOverlap_t2, 8678c2ecf20Sopenharmony_ci pwr_table_offset, 8688c2ecf20Sopenharmony_ci &diff); 8698c2ecf20Sopenharmony_ci 8708c2ecf20Sopenharmony_ci ENABLE_REGWRITE_BUFFER(ah); 8718c2ecf20Sopenharmony_ci 8728c2ecf20Sopenharmony_ci if (OLC_FOR_AR9280_20_LATER) { 8738c2ecf20Sopenharmony_ci REG_WRITE(ah, 8748c2ecf20Sopenharmony_ci AR_PHY_TPCRG5 + regChainOffset, 8758c2ecf20Sopenharmony_ci SM(0x6, 8768c2ecf20Sopenharmony_ci AR_PHY_TPCRG5_PD_GAIN_OVERLAP) | 8778c2ecf20Sopenharmony_ci SM_PD_GAIN(1) | SM_PD_GAIN(2) | 8788c2ecf20Sopenharmony_ci SM_PD_GAIN(3) | SM_PD_GAIN(4)); 8798c2ecf20Sopenharmony_ci } else { 8808c2ecf20Sopenharmony_ci REG_WRITE(ah, 8818c2ecf20Sopenharmony_ci AR_PHY_TPCRG5 + regChainOffset, 8828c2ecf20Sopenharmony_ci SM(pdGainOverlap_t2, 8838c2ecf20Sopenharmony_ci AR_PHY_TPCRG5_PD_GAIN_OVERLAP)| 8848c2ecf20Sopenharmony_ci SM_PDGAIN_B(0, 1) | 8858c2ecf20Sopenharmony_ci SM_PDGAIN_B(1, 2) | 8868c2ecf20Sopenharmony_ci SM_PDGAIN_B(2, 3) | 8878c2ecf20Sopenharmony_ci SM_PDGAIN_B(3, 4)); 8888c2ecf20Sopenharmony_ci } 8898c2ecf20Sopenharmony_ci 8908c2ecf20Sopenharmony_ci ath9k_adjust_pdadc_values(ah, pwr_table_offset, 8918c2ecf20Sopenharmony_ci diff, pdadcValues); 8928c2ecf20Sopenharmony_ci 8938c2ecf20Sopenharmony_ci regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset; 8948c2ecf20Sopenharmony_ci for (j = 0; j < 32; j++) { 8958c2ecf20Sopenharmony_ci reg32 = get_unaligned_le32(&pdadcValues[4 * j]); 8968c2ecf20Sopenharmony_ci REG_WRITE(ah, regOffset, reg32); 8978c2ecf20Sopenharmony_ci 8988c2ecf20Sopenharmony_ci ath_dbg(common, EEPROM, 8998c2ecf20Sopenharmony_ci "PDADC (%d,%4x): %4.4x %8.8x\n", 9008c2ecf20Sopenharmony_ci i, regChainOffset, regOffset, 9018c2ecf20Sopenharmony_ci reg32); 9028c2ecf20Sopenharmony_ci ath_dbg(common, EEPROM, 9038c2ecf20Sopenharmony_ci "PDADC: Chain %d | PDADC %3d Value %3d | PDADC %3d Value %3d | PDADC %3d Value %3d | PDADC %3d Value %3d |\n", 9048c2ecf20Sopenharmony_ci i, 4 * j, pdadcValues[4 * j], 9058c2ecf20Sopenharmony_ci 4 * j + 1, pdadcValues[4 * j + 1], 9068c2ecf20Sopenharmony_ci 4 * j + 2, pdadcValues[4 * j + 2], 9078c2ecf20Sopenharmony_ci 4 * j + 3, pdadcValues[4 * j + 3]); 9088c2ecf20Sopenharmony_ci 9098c2ecf20Sopenharmony_ci regOffset += 4; 9108c2ecf20Sopenharmony_ci } 9118c2ecf20Sopenharmony_ci REGWRITE_BUFFER_FLUSH(ah); 9128c2ecf20Sopenharmony_ci } 9138c2ecf20Sopenharmony_ci } 9148c2ecf20Sopenharmony_ci 9158c2ecf20Sopenharmony_ci#undef SM_PD_GAIN 9168c2ecf20Sopenharmony_ci#undef SM_PDGAIN_B 9178c2ecf20Sopenharmony_ci} 9188c2ecf20Sopenharmony_ci 9198c2ecf20Sopenharmony_cistatic void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah, 9208c2ecf20Sopenharmony_ci struct ath9k_channel *chan, 9218c2ecf20Sopenharmony_ci int16_t *ratesArray, 9228c2ecf20Sopenharmony_ci u16 cfgCtl, 9238c2ecf20Sopenharmony_ci u16 antenna_reduction, 9248c2ecf20Sopenharmony_ci u16 powerLimit) 9258c2ecf20Sopenharmony_ci{ 9268c2ecf20Sopenharmony_ci struct ar5416_eeprom_def *pEepData = &ah->eeprom.def; 9278c2ecf20Sopenharmony_ci u16 twiceMaxEdgePower; 9288c2ecf20Sopenharmony_ci int i; 9298c2ecf20Sopenharmony_ci struct cal_ctl_data *rep; 9308c2ecf20Sopenharmony_ci struct cal_target_power_leg targetPowerOfdm, targetPowerCck = { 9318c2ecf20Sopenharmony_ci 0, { 0, 0, 0, 0} 9328c2ecf20Sopenharmony_ci }; 9338c2ecf20Sopenharmony_ci struct cal_target_power_leg targetPowerOfdmExt = { 9348c2ecf20Sopenharmony_ci 0, { 0, 0, 0, 0} }, targetPowerCckExt = { 9358c2ecf20Sopenharmony_ci 0, { 0, 0, 0, 0 } 9368c2ecf20Sopenharmony_ci }; 9378c2ecf20Sopenharmony_ci struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = { 9388c2ecf20Sopenharmony_ci 0, {0, 0, 0, 0} 9398c2ecf20Sopenharmony_ci }; 9408c2ecf20Sopenharmony_ci u16 scaledPower = 0, minCtlPower; 9418c2ecf20Sopenharmony_ci static const u16 ctlModesFor11a[] = { 9428c2ecf20Sopenharmony_ci CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40 9438c2ecf20Sopenharmony_ci }; 9448c2ecf20Sopenharmony_ci static const u16 ctlModesFor11g[] = { 9458c2ecf20Sopenharmony_ci CTL_11B, CTL_11G, CTL_2GHT20, 9468c2ecf20Sopenharmony_ci CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40 9478c2ecf20Sopenharmony_ci }; 9488c2ecf20Sopenharmony_ci u16 numCtlModes; 9498c2ecf20Sopenharmony_ci const u16 *pCtlMode; 9508c2ecf20Sopenharmony_ci u16 ctlMode, freq; 9518c2ecf20Sopenharmony_ci struct chan_centers centers; 9528c2ecf20Sopenharmony_ci int tx_chainmask; 9538c2ecf20Sopenharmony_ci u16 twiceMinEdgePower; 9548c2ecf20Sopenharmony_ci 9558c2ecf20Sopenharmony_ci tx_chainmask = ah->txchainmask; 9568c2ecf20Sopenharmony_ci 9578c2ecf20Sopenharmony_ci ath9k_hw_get_channel_centers(ah, chan, ¢ers); 9588c2ecf20Sopenharmony_ci 9598c2ecf20Sopenharmony_ci scaledPower = ath9k_hw_get_scaled_power(ah, powerLimit, 9608c2ecf20Sopenharmony_ci antenna_reduction); 9618c2ecf20Sopenharmony_ci 9628c2ecf20Sopenharmony_ci if (IS_CHAN_2GHZ(chan)) { 9638c2ecf20Sopenharmony_ci numCtlModes = ARRAY_SIZE(ctlModesFor11g) - 9648c2ecf20Sopenharmony_ci SUB_NUM_CTL_MODES_AT_2G_40; 9658c2ecf20Sopenharmony_ci pCtlMode = ctlModesFor11g; 9668c2ecf20Sopenharmony_ci 9678c2ecf20Sopenharmony_ci ath9k_hw_get_legacy_target_powers(ah, chan, 9688c2ecf20Sopenharmony_ci pEepData->calTargetPowerCck, 9698c2ecf20Sopenharmony_ci AR5416_NUM_2G_CCK_TARGET_POWERS, 9708c2ecf20Sopenharmony_ci &targetPowerCck, 4, false); 9718c2ecf20Sopenharmony_ci ath9k_hw_get_legacy_target_powers(ah, chan, 9728c2ecf20Sopenharmony_ci pEepData->calTargetPower2G, 9738c2ecf20Sopenharmony_ci AR5416_NUM_2G_20_TARGET_POWERS, 9748c2ecf20Sopenharmony_ci &targetPowerOfdm, 4, false); 9758c2ecf20Sopenharmony_ci ath9k_hw_get_target_powers(ah, chan, 9768c2ecf20Sopenharmony_ci pEepData->calTargetPower2GHT20, 9778c2ecf20Sopenharmony_ci AR5416_NUM_2G_20_TARGET_POWERS, 9788c2ecf20Sopenharmony_ci &targetPowerHt20, 8, false); 9798c2ecf20Sopenharmony_ci 9808c2ecf20Sopenharmony_ci if (IS_CHAN_HT40(chan)) { 9818c2ecf20Sopenharmony_ci numCtlModes = ARRAY_SIZE(ctlModesFor11g); 9828c2ecf20Sopenharmony_ci ath9k_hw_get_target_powers(ah, chan, 9838c2ecf20Sopenharmony_ci pEepData->calTargetPower2GHT40, 9848c2ecf20Sopenharmony_ci AR5416_NUM_2G_40_TARGET_POWERS, 9858c2ecf20Sopenharmony_ci &targetPowerHt40, 8, true); 9868c2ecf20Sopenharmony_ci ath9k_hw_get_legacy_target_powers(ah, chan, 9878c2ecf20Sopenharmony_ci pEepData->calTargetPowerCck, 9888c2ecf20Sopenharmony_ci AR5416_NUM_2G_CCK_TARGET_POWERS, 9898c2ecf20Sopenharmony_ci &targetPowerCckExt, 4, true); 9908c2ecf20Sopenharmony_ci ath9k_hw_get_legacy_target_powers(ah, chan, 9918c2ecf20Sopenharmony_ci pEepData->calTargetPower2G, 9928c2ecf20Sopenharmony_ci AR5416_NUM_2G_20_TARGET_POWERS, 9938c2ecf20Sopenharmony_ci &targetPowerOfdmExt, 4, true); 9948c2ecf20Sopenharmony_ci } 9958c2ecf20Sopenharmony_ci } else { 9968c2ecf20Sopenharmony_ci numCtlModes = ARRAY_SIZE(ctlModesFor11a) - 9978c2ecf20Sopenharmony_ci SUB_NUM_CTL_MODES_AT_5G_40; 9988c2ecf20Sopenharmony_ci pCtlMode = ctlModesFor11a; 9998c2ecf20Sopenharmony_ci 10008c2ecf20Sopenharmony_ci ath9k_hw_get_legacy_target_powers(ah, chan, 10018c2ecf20Sopenharmony_ci pEepData->calTargetPower5G, 10028c2ecf20Sopenharmony_ci AR5416_NUM_5G_20_TARGET_POWERS, 10038c2ecf20Sopenharmony_ci &targetPowerOfdm, 4, false); 10048c2ecf20Sopenharmony_ci ath9k_hw_get_target_powers(ah, chan, 10058c2ecf20Sopenharmony_ci pEepData->calTargetPower5GHT20, 10068c2ecf20Sopenharmony_ci AR5416_NUM_5G_20_TARGET_POWERS, 10078c2ecf20Sopenharmony_ci &targetPowerHt20, 8, false); 10088c2ecf20Sopenharmony_ci 10098c2ecf20Sopenharmony_ci if (IS_CHAN_HT40(chan)) { 10108c2ecf20Sopenharmony_ci numCtlModes = ARRAY_SIZE(ctlModesFor11a); 10118c2ecf20Sopenharmony_ci ath9k_hw_get_target_powers(ah, chan, 10128c2ecf20Sopenharmony_ci pEepData->calTargetPower5GHT40, 10138c2ecf20Sopenharmony_ci AR5416_NUM_5G_40_TARGET_POWERS, 10148c2ecf20Sopenharmony_ci &targetPowerHt40, 8, true); 10158c2ecf20Sopenharmony_ci ath9k_hw_get_legacy_target_powers(ah, chan, 10168c2ecf20Sopenharmony_ci pEepData->calTargetPower5G, 10178c2ecf20Sopenharmony_ci AR5416_NUM_5G_20_TARGET_POWERS, 10188c2ecf20Sopenharmony_ci &targetPowerOfdmExt, 4, true); 10198c2ecf20Sopenharmony_ci } 10208c2ecf20Sopenharmony_ci } 10218c2ecf20Sopenharmony_ci 10228c2ecf20Sopenharmony_ci for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) { 10238c2ecf20Sopenharmony_ci bool isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) || 10248c2ecf20Sopenharmony_ci (pCtlMode[ctlMode] == CTL_2GHT40); 10258c2ecf20Sopenharmony_ci if (isHt40CtlMode) 10268c2ecf20Sopenharmony_ci freq = centers.synth_center; 10278c2ecf20Sopenharmony_ci else if (pCtlMode[ctlMode] & EXT_ADDITIVE) 10288c2ecf20Sopenharmony_ci freq = centers.ext_center; 10298c2ecf20Sopenharmony_ci else 10308c2ecf20Sopenharmony_ci freq = centers.ctl_center; 10318c2ecf20Sopenharmony_ci 10328c2ecf20Sopenharmony_ci twiceMaxEdgePower = MAX_RATE_POWER; 10338c2ecf20Sopenharmony_ci 10348c2ecf20Sopenharmony_ci for (i = 0; (i < AR5416_NUM_CTLS) && pEepData->ctlIndex[i]; i++) { 10358c2ecf20Sopenharmony_ci if ((((cfgCtl & ~CTL_MODE_M) | 10368c2ecf20Sopenharmony_ci (pCtlMode[ctlMode] & CTL_MODE_M)) == 10378c2ecf20Sopenharmony_ci pEepData->ctlIndex[i]) || 10388c2ecf20Sopenharmony_ci (((cfgCtl & ~CTL_MODE_M) | 10398c2ecf20Sopenharmony_ci (pCtlMode[ctlMode] & CTL_MODE_M)) == 10408c2ecf20Sopenharmony_ci ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL))) { 10418c2ecf20Sopenharmony_ci rep = &(pEepData->ctlData[i]); 10428c2ecf20Sopenharmony_ci 10438c2ecf20Sopenharmony_ci twiceMinEdgePower = ath9k_hw_get_max_edge_power(freq, 10448c2ecf20Sopenharmony_ci rep->ctlEdges[ar5416_get_ntxchains(tx_chainmask) - 1], 10458c2ecf20Sopenharmony_ci IS_CHAN_2GHZ(chan), AR5416_NUM_BAND_EDGES); 10468c2ecf20Sopenharmony_ci 10478c2ecf20Sopenharmony_ci if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) { 10488c2ecf20Sopenharmony_ci twiceMaxEdgePower = min(twiceMaxEdgePower, 10498c2ecf20Sopenharmony_ci twiceMinEdgePower); 10508c2ecf20Sopenharmony_ci } else { 10518c2ecf20Sopenharmony_ci twiceMaxEdgePower = twiceMinEdgePower; 10528c2ecf20Sopenharmony_ci break; 10538c2ecf20Sopenharmony_ci } 10548c2ecf20Sopenharmony_ci } 10558c2ecf20Sopenharmony_ci } 10568c2ecf20Sopenharmony_ci 10578c2ecf20Sopenharmony_ci minCtlPower = min(twiceMaxEdgePower, scaledPower); 10588c2ecf20Sopenharmony_ci 10598c2ecf20Sopenharmony_ci switch (pCtlMode[ctlMode]) { 10608c2ecf20Sopenharmony_ci case CTL_11B: 10618c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(targetPowerCck.tPow2x); i++) { 10628c2ecf20Sopenharmony_ci targetPowerCck.tPow2x[i] = 10638c2ecf20Sopenharmony_ci min((u16)targetPowerCck.tPow2x[i], 10648c2ecf20Sopenharmony_ci minCtlPower); 10658c2ecf20Sopenharmony_ci } 10668c2ecf20Sopenharmony_ci break; 10678c2ecf20Sopenharmony_ci case CTL_11A: 10688c2ecf20Sopenharmony_ci case CTL_11G: 10698c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(targetPowerOfdm.tPow2x); i++) { 10708c2ecf20Sopenharmony_ci targetPowerOfdm.tPow2x[i] = 10718c2ecf20Sopenharmony_ci min((u16)targetPowerOfdm.tPow2x[i], 10728c2ecf20Sopenharmony_ci minCtlPower); 10738c2ecf20Sopenharmony_ci } 10748c2ecf20Sopenharmony_ci break; 10758c2ecf20Sopenharmony_ci case CTL_5GHT20: 10768c2ecf20Sopenharmony_ci case CTL_2GHT20: 10778c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++) { 10788c2ecf20Sopenharmony_ci targetPowerHt20.tPow2x[i] = 10798c2ecf20Sopenharmony_ci min((u16)targetPowerHt20.tPow2x[i], 10808c2ecf20Sopenharmony_ci minCtlPower); 10818c2ecf20Sopenharmony_ci } 10828c2ecf20Sopenharmony_ci break; 10838c2ecf20Sopenharmony_ci case CTL_11B_EXT: 10848c2ecf20Sopenharmony_ci targetPowerCckExt.tPow2x[0] = min((u16) 10858c2ecf20Sopenharmony_ci targetPowerCckExt.tPow2x[0], 10868c2ecf20Sopenharmony_ci minCtlPower); 10878c2ecf20Sopenharmony_ci break; 10888c2ecf20Sopenharmony_ci case CTL_11A_EXT: 10898c2ecf20Sopenharmony_ci case CTL_11G_EXT: 10908c2ecf20Sopenharmony_ci targetPowerOfdmExt.tPow2x[0] = min((u16) 10918c2ecf20Sopenharmony_ci targetPowerOfdmExt.tPow2x[0], 10928c2ecf20Sopenharmony_ci minCtlPower); 10938c2ecf20Sopenharmony_ci break; 10948c2ecf20Sopenharmony_ci case CTL_5GHT40: 10958c2ecf20Sopenharmony_ci case CTL_2GHT40: 10968c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) { 10978c2ecf20Sopenharmony_ci targetPowerHt40.tPow2x[i] = 10988c2ecf20Sopenharmony_ci min((u16)targetPowerHt40.tPow2x[i], 10998c2ecf20Sopenharmony_ci minCtlPower); 11008c2ecf20Sopenharmony_ci } 11018c2ecf20Sopenharmony_ci break; 11028c2ecf20Sopenharmony_ci default: 11038c2ecf20Sopenharmony_ci break; 11048c2ecf20Sopenharmony_ci } 11058c2ecf20Sopenharmony_ci } 11068c2ecf20Sopenharmony_ci 11078c2ecf20Sopenharmony_ci ratesArray[rate6mb] = ratesArray[rate9mb] = ratesArray[rate12mb] = 11088c2ecf20Sopenharmony_ci ratesArray[rate18mb] = ratesArray[rate24mb] = 11098c2ecf20Sopenharmony_ci targetPowerOfdm.tPow2x[0]; 11108c2ecf20Sopenharmony_ci ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1]; 11118c2ecf20Sopenharmony_ci ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2]; 11128c2ecf20Sopenharmony_ci ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3]; 11138c2ecf20Sopenharmony_ci ratesArray[rateXr] = targetPowerOfdm.tPow2x[0]; 11148c2ecf20Sopenharmony_ci 11158c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++) 11168c2ecf20Sopenharmony_ci ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i]; 11178c2ecf20Sopenharmony_ci 11188c2ecf20Sopenharmony_ci if (IS_CHAN_2GHZ(chan)) { 11198c2ecf20Sopenharmony_ci ratesArray[rate1l] = targetPowerCck.tPow2x[0]; 11208c2ecf20Sopenharmony_ci ratesArray[rate2s] = ratesArray[rate2l] = 11218c2ecf20Sopenharmony_ci targetPowerCck.tPow2x[1]; 11228c2ecf20Sopenharmony_ci ratesArray[rate5_5s] = ratesArray[rate5_5l] = 11238c2ecf20Sopenharmony_ci targetPowerCck.tPow2x[2]; 11248c2ecf20Sopenharmony_ci ratesArray[rate11s] = ratesArray[rate11l] = 11258c2ecf20Sopenharmony_ci targetPowerCck.tPow2x[3]; 11268c2ecf20Sopenharmony_ci } 11278c2ecf20Sopenharmony_ci if (IS_CHAN_HT40(chan)) { 11288c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) { 11298c2ecf20Sopenharmony_ci ratesArray[rateHt40_0 + i] = 11308c2ecf20Sopenharmony_ci targetPowerHt40.tPow2x[i]; 11318c2ecf20Sopenharmony_ci } 11328c2ecf20Sopenharmony_ci ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0]; 11338c2ecf20Sopenharmony_ci ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0]; 11348c2ecf20Sopenharmony_ci ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0]; 11358c2ecf20Sopenharmony_ci if (IS_CHAN_2GHZ(chan)) { 11368c2ecf20Sopenharmony_ci ratesArray[rateExtCck] = 11378c2ecf20Sopenharmony_ci targetPowerCckExt.tPow2x[0]; 11388c2ecf20Sopenharmony_ci } 11398c2ecf20Sopenharmony_ci } 11408c2ecf20Sopenharmony_ci} 11418c2ecf20Sopenharmony_ci 11428c2ecf20Sopenharmony_cistatic void ath9k_hw_def_set_txpower(struct ath_hw *ah, 11438c2ecf20Sopenharmony_ci struct ath9k_channel *chan, 11448c2ecf20Sopenharmony_ci u16 cfgCtl, 11458c2ecf20Sopenharmony_ci u8 twiceAntennaReduction, 11468c2ecf20Sopenharmony_ci u8 powerLimit, bool test) 11478c2ecf20Sopenharmony_ci{ 11488c2ecf20Sopenharmony_ci#define RT_AR_DELTA(x) (ratesArray[x] - cck_ofdm_delta) 11498c2ecf20Sopenharmony_ci struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); 11508c2ecf20Sopenharmony_ci struct ar5416_eeprom_def *pEepData = &ah->eeprom.def; 11518c2ecf20Sopenharmony_ci struct modal_eep_header *pModal = 11528c2ecf20Sopenharmony_ci &(pEepData->modalHeader[IS_CHAN_2GHZ(chan)]); 11538c2ecf20Sopenharmony_ci int16_t ratesArray[Ar5416RateSize]; 11548c2ecf20Sopenharmony_ci u8 ht40PowerIncForPdadc = 2; 11558c2ecf20Sopenharmony_ci int i, cck_ofdm_delta = 0; 11568c2ecf20Sopenharmony_ci 11578c2ecf20Sopenharmony_ci memset(ratesArray, 0, sizeof(ratesArray)); 11588c2ecf20Sopenharmony_ci 11598c2ecf20Sopenharmony_ci if (ath9k_hw_def_get_eeprom_rev(ah) >= AR5416_EEP_MINOR_VER_2) 11608c2ecf20Sopenharmony_ci ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc; 11618c2ecf20Sopenharmony_ci 11628c2ecf20Sopenharmony_ci ath9k_hw_set_def_power_per_rate_table(ah, chan, 11638c2ecf20Sopenharmony_ci &ratesArray[0], cfgCtl, 11648c2ecf20Sopenharmony_ci twiceAntennaReduction, 11658c2ecf20Sopenharmony_ci powerLimit); 11668c2ecf20Sopenharmony_ci 11678c2ecf20Sopenharmony_ci ath9k_hw_set_def_power_cal_table(ah, chan); 11688c2ecf20Sopenharmony_ci 11698c2ecf20Sopenharmony_ci regulatory->max_power_level = 0; 11708c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(ratesArray); i++) { 11718c2ecf20Sopenharmony_ci if (ratesArray[i] > MAX_RATE_POWER) 11728c2ecf20Sopenharmony_ci ratesArray[i] = MAX_RATE_POWER; 11738c2ecf20Sopenharmony_ci if (ratesArray[i] > regulatory->max_power_level) 11748c2ecf20Sopenharmony_ci regulatory->max_power_level = ratesArray[i]; 11758c2ecf20Sopenharmony_ci } 11768c2ecf20Sopenharmony_ci 11778c2ecf20Sopenharmony_ci ath9k_hw_update_regulatory_maxpower(ah); 11788c2ecf20Sopenharmony_ci 11798c2ecf20Sopenharmony_ci if (test) 11808c2ecf20Sopenharmony_ci return; 11818c2ecf20Sopenharmony_ci 11828c2ecf20Sopenharmony_ci if (AR_SREV_9280_20_OR_LATER(ah)) { 11838c2ecf20Sopenharmony_ci for (i = 0; i < Ar5416RateSize; i++) { 11848c2ecf20Sopenharmony_ci int8_t pwr_table_offset; 11858c2ecf20Sopenharmony_ci 11868c2ecf20Sopenharmony_ci pwr_table_offset = ah->eep_ops->get_eeprom(ah, 11878c2ecf20Sopenharmony_ci EEP_PWR_TABLE_OFFSET); 11888c2ecf20Sopenharmony_ci ratesArray[i] -= pwr_table_offset * 2; 11898c2ecf20Sopenharmony_ci } 11908c2ecf20Sopenharmony_ci } 11918c2ecf20Sopenharmony_ci 11928c2ecf20Sopenharmony_ci ENABLE_REGWRITE_BUFFER(ah); 11938c2ecf20Sopenharmony_ci 11948c2ecf20Sopenharmony_ci REG_WRITE(ah, AR_PHY_POWER_TX_RATE1, 11958c2ecf20Sopenharmony_ci ATH9K_POW_SM(ratesArray[rate18mb], 24) 11968c2ecf20Sopenharmony_ci | ATH9K_POW_SM(ratesArray[rate12mb], 16) 11978c2ecf20Sopenharmony_ci | ATH9K_POW_SM(ratesArray[rate9mb], 8) 11988c2ecf20Sopenharmony_ci | ATH9K_POW_SM(ratesArray[rate6mb], 0)); 11998c2ecf20Sopenharmony_ci REG_WRITE(ah, AR_PHY_POWER_TX_RATE2, 12008c2ecf20Sopenharmony_ci ATH9K_POW_SM(ratesArray[rate54mb], 24) 12018c2ecf20Sopenharmony_ci | ATH9K_POW_SM(ratesArray[rate48mb], 16) 12028c2ecf20Sopenharmony_ci | ATH9K_POW_SM(ratesArray[rate36mb], 8) 12038c2ecf20Sopenharmony_ci | ATH9K_POW_SM(ratesArray[rate24mb], 0)); 12048c2ecf20Sopenharmony_ci 12058c2ecf20Sopenharmony_ci if (IS_CHAN_2GHZ(chan)) { 12068c2ecf20Sopenharmony_ci if (OLC_FOR_AR9280_20_LATER) { 12078c2ecf20Sopenharmony_ci cck_ofdm_delta = 2; 12088c2ecf20Sopenharmony_ci REG_WRITE(ah, AR_PHY_POWER_TX_RATE3, 12098c2ecf20Sopenharmony_ci ATH9K_POW_SM(RT_AR_DELTA(rate2s), 24) 12108c2ecf20Sopenharmony_ci | ATH9K_POW_SM(RT_AR_DELTA(rate2l), 16) 12118c2ecf20Sopenharmony_ci | ATH9K_POW_SM(ratesArray[rateXr], 8) 12128c2ecf20Sopenharmony_ci | ATH9K_POW_SM(RT_AR_DELTA(rate1l), 0)); 12138c2ecf20Sopenharmony_ci REG_WRITE(ah, AR_PHY_POWER_TX_RATE4, 12148c2ecf20Sopenharmony_ci ATH9K_POW_SM(RT_AR_DELTA(rate11s), 24) 12158c2ecf20Sopenharmony_ci | ATH9K_POW_SM(RT_AR_DELTA(rate11l), 16) 12168c2ecf20Sopenharmony_ci | ATH9K_POW_SM(RT_AR_DELTA(rate5_5s), 8) 12178c2ecf20Sopenharmony_ci | ATH9K_POW_SM(RT_AR_DELTA(rate5_5l), 0)); 12188c2ecf20Sopenharmony_ci } else { 12198c2ecf20Sopenharmony_ci REG_WRITE(ah, AR_PHY_POWER_TX_RATE3, 12208c2ecf20Sopenharmony_ci ATH9K_POW_SM(ratesArray[rate2s], 24) 12218c2ecf20Sopenharmony_ci | ATH9K_POW_SM(ratesArray[rate2l], 16) 12228c2ecf20Sopenharmony_ci | ATH9K_POW_SM(ratesArray[rateXr], 8) 12238c2ecf20Sopenharmony_ci | ATH9K_POW_SM(ratesArray[rate1l], 0)); 12248c2ecf20Sopenharmony_ci REG_WRITE(ah, AR_PHY_POWER_TX_RATE4, 12258c2ecf20Sopenharmony_ci ATH9K_POW_SM(ratesArray[rate11s], 24) 12268c2ecf20Sopenharmony_ci | ATH9K_POW_SM(ratesArray[rate11l], 16) 12278c2ecf20Sopenharmony_ci | ATH9K_POW_SM(ratesArray[rate5_5s], 8) 12288c2ecf20Sopenharmony_ci | ATH9K_POW_SM(ratesArray[rate5_5l], 0)); 12298c2ecf20Sopenharmony_ci } 12308c2ecf20Sopenharmony_ci } 12318c2ecf20Sopenharmony_ci 12328c2ecf20Sopenharmony_ci REG_WRITE(ah, AR_PHY_POWER_TX_RATE5, 12338c2ecf20Sopenharmony_ci ATH9K_POW_SM(ratesArray[rateHt20_3], 24) 12348c2ecf20Sopenharmony_ci | ATH9K_POW_SM(ratesArray[rateHt20_2], 16) 12358c2ecf20Sopenharmony_ci | ATH9K_POW_SM(ratesArray[rateHt20_1], 8) 12368c2ecf20Sopenharmony_ci | ATH9K_POW_SM(ratesArray[rateHt20_0], 0)); 12378c2ecf20Sopenharmony_ci REG_WRITE(ah, AR_PHY_POWER_TX_RATE6, 12388c2ecf20Sopenharmony_ci ATH9K_POW_SM(ratesArray[rateHt20_7], 24) 12398c2ecf20Sopenharmony_ci | ATH9K_POW_SM(ratesArray[rateHt20_6], 16) 12408c2ecf20Sopenharmony_ci | ATH9K_POW_SM(ratesArray[rateHt20_5], 8) 12418c2ecf20Sopenharmony_ci | ATH9K_POW_SM(ratesArray[rateHt20_4], 0)); 12428c2ecf20Sopenharmony_ci 12438c2ecf20Sopenharmony_ci if (IS_CHAN_HT40(chan)) { 12448c2ecf20Sopenharmony_ci REG_WRITE(ah, AR_PHY_POWER_TX_RATE7, 12458c2ecf20Sopenharmony_ci ATH9K_POW_SM(ratesArray[rateHt40_3] + 12468c2ecf20Sopenharmony_ci ht40PowerIncForPdadc, 24) 12478c2ecf20Sopenharmony_ci | ATH9K_POW_SM(ratesArray[rateHt40_2] + 12488c2ecf20Sopenharmony_ci ht40PowerIncForPdadc, 16) 12498c2ecf20Sopenharmony_ci | ATH9K_POW_SM(ratesArray[rateHt40_1] + 12508c2ecf20Sopenharmony_ci ht40PowerIncForPdadc, 8) 12518c2ecf20Sopenharmony_ci | ATH9K_POW_SM(ratesArray[rateHt40_0] + 12528c2ecf20Sopenharmony_ci ht40PowerIncForPdadc, 0)); 12538c2ecf20Sopenharmony_ci REG_WRITE(ah, AR_PHY_POWER_TX_RATE8, 12548c2ecf20Sopenharmony_ci ATH9K_POW_SM(ratesArray[rateHt40_7] + 12558c2ecf20Sopenharmony_ci ht40PowerIncForPdadc, 24) 12568c2ecf20Sopenharmony_ci | ATH9K_POW_SM(ratesArray[rateHt40_6] + 12578c2ecf20Sopenharmony_ci ht40PowerIncForPdadc, 16) 12588c2ecf20Sopenharmony_ci | ATH9K_POW_SM(ratesArray[rateHt40_5] + 12598c2ecf20Sopenharmony_ci ht40PowerIncForPdadc, 8) 12608c2ecf20Sopenharmony_ci | ATH9K_POW_SM(ratesArray[rateHt40_4] + 12618c2ecf20Sopenharmony_ci ht40PowerIncForPdadc, 0)); 12628c2ecf20Sopenharmony_ci if (OLC_FOR_AR9280_20_LATER) { 12638c2ecf20Sopenharmony_ci REG_WRITE(ah, AR_PHY_POWER_TX_RATE9, 12648c2ecf20Sopenharmony_ci ATH9K_POW_SM(ratesArray[rateExtOfdm], 24) 12658c2ecf20Sopenharmony_ci | ATH9K_POW_SM(RT_AR_DELTA(rateExtCck), 16) 12668c2ecf20Sopenharmony_ci | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8) 12678c2ecf20Sopenharmony_ci | ATH9K_POW_SM(RT_AR_DELTA(rateDupCck), 0)); 12688c2ecf20Sopenharmony_ci } else { 12698c2ecf20Sopenharmony_ci REG_WRITE(ah, AR_PHY_POWER_TX_RATE9, 12708c2ecf20Sopenharmony_ci ATH9K_POW_SM(ratesArray[rateExtOfdm], 24) 12718c2ecf20Sopenharmony_ci | ATH9K_POW_SM(ratesArray[rateExtCck], 16) 12728c2ecf20Sopenharmony_ci | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8) 12738c2ecf20Sopenharmony_ci | ATH9K_POW_SM(ratesArray[rateDupCck], 0)); 12748c2ecf20Sopenharmony_ci } 12758c2ecf20Sopenharmony_ci } 12768c2ecf20Sopenharmony_ci 12778c2ecf20Sopenharmony_ci REG_WRITE(ah, AR_PHY_POWER_TX_SUB, 12788c2ecf20Sopenharmony_ci ATH9K_POW_SM(pModal->pwrDecreaseFor3Chain, 6) 12798c2ecf20Sopenharmony_ci | ATH9K_POW_SM(pModal->pwrDecreaseFor2Chain, 0)); 12808c2ecf20Sopenharmony_ci 12818c2ecf20Sopenharmony_ci /* TPC initializations */ 12828c2ecf20Sopenharmony_ci if (ah->tpc_enabled) { 12838c2ecf20Sopenharmony_ci int ht40_delta; 12848c2ecf20Sopenharmony_ci 12858c2ecf20Sopenharmony_ci ht40_delta = (IS_CHAN_HT40(chan)) ? ht40PowerIncForPdadc : 0; 12868c2ecf20Sopenharmony_ci ar5008_hw_init_rate_txpower(ah, ratesArray, chan, ht40_delta); 12878c2ecf20Sopenharmony_ci /* Enable TPC */ 12888c2ecf20Sopenharmony_ci REG_WRITE(ah, AR_PHY_POWER_TX_RATE_MAX, 12898c2ecf20Sopenharmony_ci MAX_RATE_POWER | AR_PHY_POWER_TX_RATE_MAX_TPC_ENABLE); 12908c2ecf20Sopenharmony_ci } else { 12918c2ecf20Sopenharmony_ci /* Disable TPC */ 12928c2ecf20Sopenharmony_ci REG_WRITE(ah, AR_PHY_POWER_TX_RATE_MAX, MAX_RATE_POWER); 12938c2ecf20Sopenharmony_ci } 12948c2ecf20Sopenharmony_ci 12958c2ecf20Sopenharmony_ci REGWRITE_BUFFER_FLUSH(ah); 12968c2ecf20Sopenharmony_ci} 12978c2ecf20Sopenharmony_ci 12988c2ecf20Sopenharmony_cistatic u16 ath9k_hw_def_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz) 12998c2ecf20Sopenharmony_ci{ 13008c2ecf20Sopenharmony_ci __le16 spch = ah->eeprom.def.modalHeader[is2GHz].spurChans[i].spurChan; 13018c2ecf20Sopenharmony_ci 13028c2ecf20Sopenharmony_ci return le16_to_cpu(spch); 13038c2ecf20Sopenharmony_ci} 13048c2ecf20Sopenharmony_ci 13058c2ecf20Sopenharmony_cistatic u8 ath9k_hw_def_get_eepmisc(struct ath_hw *ah) 13068c2ecf20Sopenharmony_ci{ 13078c2ecf20Sopenharmony_ci return ah->eeprom.def.baseEepHeader.eepMisc; 13088c2ecf20Sopenharmony_ci} 13098c2ecf20Sopenharmony_ci 13108c2ecf20Sopenharmony_ciconst struct eeprom_ops eep_def_ops = { 13118c2ecf20Sopenharmony_ci .check_eeprom = ath9k_hw_def_check_eeprom, 13128c2ecf20Sopenharmony_ci .get_eeprom = ath9k_hw_def_get_eeprom, 13138c2ecf20Sopenharmony_ci .fill_eeprom = ath9k_hw_def_fill_eeprom, 13148c2ecf20Sopenharmony_ci .dump_eeprom = ath9k_hw_def_dump_eeprom, 13158c2ecf20Sopenharmony_ci .get_eeprom_ver = ath9k_hw_def_get_eeprom_ver, 13168c2ecf20Sopenharmony_ci .get_eeprom_rev = ath9k_hw_def_get_eeprom_rev, 13178c2ecf20Sopenharmony_ci .set_board_values = ath9k_hw_def_set_board_values, 13188c2ecf20Sopenharmony_ci .set_addac = ath9k_hw_def_set_addac, 13198c2ecf20Sopenharmony_ci .set_txpower = ath9k_hw_def_set_txpower, 13208c2ecf20Sopenharmony_ci .get_spur_channel = ath9k_hw_def_get_spur_channel, 13218c2ecf20Sopenharmony_ci .get_eepmisc = ath9k_hw_def_get_eepmisc 13228c2ecf20Sopenharmony_ci}; 1323