18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * (c) Copyright 2002-2010, Ralink Technology, Inc. 48c2ecf20Sopenharmony_ci * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org> 58c2ecf20Sopenharmony_ci * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl> 68c2ecf20Sopenharmony_ci * Copyright (C) 2018 Stanislaw Gruszka <stf_xl@wp.pl> 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include <linux/kernel.h> 108c2ecf20Sopenharmony_ci#include <linux/etherdevice.h> 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include "mt76x0.h" 138c2ecf20Sopenharmony_ci#include "mcu.h" 148c2ecf20Sopenharmony_ci#include "eeprom.h" 158c2ecf20Sopenharmony_ci#include "phy.h" 168c2ecf20Sopenharmony_ci#include "initvals.h" 178c2ecf20Sopenharmony_ci#include "initvals_phy.h" 188c2ecf20Sopenharmony_ci#include "../mt76x02_phy.h" 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_cistatic int 218c2ecf20Sopenharmony_cimt76x0_rf_csr_wr(struct mt76x02_dev *dev, u32 offset, u8 value) 228c2ecf20Sopenharmony_ci{ 238c2ecf20Sopenharmony_ci int ret = 0; 248c2ecf20Sopenharmony_ci u8 bank, reg; 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci if (test_bit(MT76_REMOVED, &dev->mphy.state)) 278c2ecf20Sopenharmony_ci return -ENODEV; 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci bank = MT_RF_BANK(offset); 308c2ecf20Sopenharmony_ci reg = MT_RF_REG(offset); 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci if (WARN_ON_ONCE(reg > 127) || WARN_ON_ONCE(bank > 8)) 338c2ecf20Sopenharmony_ci return -EINVAL; 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci mutex_lock(&dev->phy_mutex); 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci if (!mt76_poll(dev, MT_RF_CSR_CFG, MT_RF_CSR_CFG_KICK, 0, 100)) { 388c2ecf20Sopenharmony_ci ret = -ETIMEDOUT; 398c2ecf20Sopenharmony_ci goto out; 408c2ecf20Sopenharmony_ci } 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci mt76_wr(dev, MT_RF_CSR_CFG, 438c2ecf20Sopenharmony_ci FIELD_PREP(MT_RF_CSR_CFG_DATA, value) | 448c2ecf20Sopenharmony_ci FIELD_PREP(MT_RF_CSR_CFG_REG_BANK, bank) | 458c2ecf20Sopenharmony_ci FIELD_PREP(MT_RF_CSR_CFG_REG_ID, reg) | 468c2ecf20Sopenharmony_ci MT_RF_CSR_CFG_WR | 478c2ecf20Sopenharmony_ci MT_RF_CSR_CFG_KICK); 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ciout: 508c2ecf20Sopenharmony_ci mutex_unlock(&dev->phy_mutex); 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci if (ret < 0) 538c2ecf20Sopenharmony_ci dev_err(dev->mt76.dev, "Error: RF write %d:%d failed:%d!!\n", 548c2ecf20Sopenharmony_ci bank, reg, ret); 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci return ret; 578c2ecf20Sopenharmony_ci} 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_cistatic int mt76x0_rf_csr_rr(struct mt76x02_dev *dev, u32 offset) 608c2ecf20Sopenharmony_ci{ 618c2ecf20Sopenharmony_ci int ret = -ETIMEDOUT; 628c2ecf20Sopenharmony_ci u32 val; 638c2ecf20Sopenharmony_ci u8 bank, reg; 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci if (test_bit(MT76_REMOVED, &dev->mphy.state)) 668c2ecf20Sopenharmony_ci return -ENODEV; 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci bank = MT_RF_BANK(offset); 698c2ecf20Sopenharmony_ci reg = MT_RF_REG(offset); 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci if (WARN_ON_ONCE(reg > 127) || WARN_ON_ONCE(bank > 8)) 728c2ecf20Sopenharmony_ci return -EINVAL; 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci mutex_lock(&dev->phy_mutex); 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci if (!mt76_poll(dev, MT_RF_CSR_CFG, MT_RF_CSR_CFG_KICK, 0, 100)) 778c2ecf20Sopenharmony_ci goto out; 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci mt76_wr(dev, MT_RF_CSR_CFG, 808c2ecf20Sopenharmony_ci FIELD_PREP(MT_RF_CSR_CFG_REG_BANK, bank) | 818c2ecf20Sopenharmony_ci FIELD_PREP(MT_RF_CSR_CFG_REG_ID, reg) | 828c2ecf20Sopenharmony_ci MT_RF_CSR_CFG_KICK); 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci if (!mt76_poll(dev, MT_RF_CSR_CFG, MT_RF_CSR_CFG_KICK, 0, 100)) 858c2ecf20Sopenharmony_ci goto out; 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci val = mt76_rr(dev, MT_RF_CSR_CFG); 888c2ecf20Sopenharmony_ci if (FIELD_GET(MT_RF_CSR_CFG_REG_ID, val) == reg && 898c2ecf20Sopenharmony_ci FIELD_GET(MT_RF_CSR_CFG_REG_BANK, val) == bank) 908c2ecf20Sopenharmony_ci ret = FIELD_GET(MT_RF_CSR_CFG_DATA, val); 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ciout: 938c2ecf20Sopenharmony_ci mutex_unlock(&dev->phy_mutex); 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci if (ret < 0) 968c2ecf20Sopenharmony_ci dev_err(dev->mt76.dev, "Error: RF read %d:%d failed:%d!!\n", 978c2ecf20Sopenharmony_ci bank, reg, ret); 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci return ret; 1008c2ecf20Sopenharmony_ci} 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_cistatic int 1038c2ecf20Sopenharmony_cimt76x0_rf_wr(struct mt76x02_dev *dev, u32 offset, u8 val) 1048c2ecf20Sopenharmony_ci{ 1058c2ecf20Sopenharmony_ci if (mt76_is_usb(&dev->mt76)) { 1068c2ecf20Sopenharmony_ci struct mt76_reg_pair pair = { 1078c2ecf20Sopenharmony_ci .reg = offset, 1088c2ecf20Sopenharmony_ci .value = val, 1098c2ecf20Sopenharmony_ci }; 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci WARN_ON_ONCE(!test_bit(MT76_STATE_MCU_RUNNING, 1128c2ecf20Sopenharmony_ci &dev->mphy.state)); 1138c2ecf20Sopenharmony_ci return mt76_wr_rp(dev, MT_MCU_MEMMAP_RF, &pair, 1); 1148c2ecf20Sopenharmony_ci } else { 1158c2ecf20Sopenharmony_ci return mt76x0_rf_csr_wr(dev, offset, val); 1168c2ecf20Sopenharmony_ci } 1178c2ecf20Sopenharmony_ci} 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_cistatic int mt76x0_rf_rr(struct mt76x02_dev *dev, u32 offset) 1208c2ecf20Sopenharmony_ci{ 1218c2ecf20Sopenharmony_ci int ret; 1228c2ecf20Sopenharmony_ci u32 val; 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci if (mt76_is_usb(&dev->mt76)) { 1258c2ecf20Sopenharmony_ci struct mt76_reg_pair pair = { 1268c2ecf20Sopenharmony_ci .reg = offset, 1278c2ecf20Sopenharmony_ci }; 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci WARN_ON_ONCE(!test_bit(MT76_STATE_MCU_RUNNING, 1308c2ecf20Sopenharmony_ci &dev->mphy.state)); 1318c2ecf20Sopenharmony_ci ret = mt76_rd_rp(dev, MT_MCU_MEMMAP_RF, &pair, 1); 1328c2ecf20Sopenharmony_ci val = pair.value; 1338c2ecf20Sopenharmony_ci } else { 1348c2ecf20Sopenharmony_ci ret = val = mt76x0_rf_csr_rr(dev, offset); 1358c2ecf20Sopenharmony_ci } 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci return (ret < 0) ? ret : val; 1388c2ecf20Sopenharmony_ci} 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_cistatic int 1418c2ecf20Sopenharmony_cimt76x0_rf_rmw(struct mt76x02_dev *dev, u32 offset, u8 mask, u8 val) 1428c2ecf20Sopenharmony_ci{ 1438c2ecf20Sopenharmony_ci int ret; 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci ret = mt76x0_rf_rr(dev, offset); 1468c2ecf20Sopenharmony_ci if (ret < 0) 1478c2ecf20Sopenharmony_ci return ret; 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci val |= ret & ~mask; 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci ret = mt76x0_rf_wr(dev, offset, val); 1528c2ecf20Sopenharmony_ci return ret ? ret : val; 1538c2ecf20Sopenharmony_ci} 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_cistatic int 1568c2ecf20Sopenharmony_cimt76x0_rf_set(struct mt76x02_dev *dev, u32 offset, u8 val) 1578c2ecf20Sopenharmony_ci{ 1588c2ecf20Sopenharmony_ci return mt76x0_rf_rmw(dev, offset, 0, val); 1598c2ecf20Sopenharmony_ci} 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_cistatic int 1628c2ecf20Sopenharmony_cimt76x0_rf_clear(struct mt76x02_dev *dev, u32 offset, u8 mask) 1638c2ecf20Sopenharmony_ci{ 1648c2ecf20Sopenharmony_ci return mt76x0_rf_rmw(dev, offset, mask, 0); 1658c2ecf20Sopenharmony_ci} 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_cistatic void 1688c2ecf20Sopenharmony_cimt76x0_phy_rf_csr_wr_rp(struct mt76x02_dev *dev, 1698c2ecf20Sopenharmony_ci const struct mt76_reg_pair *data, 1708c2ecf20Sopenharmony_ci int n) 1718c2ecf20Sopenharmony_ci{ 1728c2ecf20Sopenharmony_ci while (n-- > 0) { 1738c2ecf20Sopenharmony_ci mt76x0_rf_csr_wr(dev, data->reg, data->value); 1748c2ecf20Sopenharmony_ci data++; 1758c2ecf20Sopenharmony_ci } 1768c2ecf20Sopenharmony_ci} 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci#define RF_RANDOM_WRITE(dev, tab) do { \ 1798c2ecf20Sopenharmony_ci if (mt76_is_mmio(&dev->mt76)) \ 1808c2ecf20Sopenharmony_ci mt76x0_phy_rf_csr_wr_rp(dev, tab, ARRAY_SIZE(tab)); \ 1818c2ecf20Sopenharmony_ci else \ 1828c2ecf20Sopenharmony_ci mt76_wr_rp(dev, MT_MCU_MEMMAP_RF, tab, ARRAY_SIZE(tab));\ 1838c2ecf20Sopenharmony_ci} while (0) 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ciint mt76x0_phy_wait_bbp_ready(struct mt76x02_dev *dev) 1868c2ecf20Sopenharmony_ci{ 1878c2ecf20Sopenharmony_ci int i = 20; 1888c2ecf20Sopenharmony_ci u32 val; 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci do { 1918c2ecf20Sopenharmony_ci val = mt76_rr(dev, MT_BBP(CORE, 0)); 1928c2ecf20Sopenharmony_ci if (val && ~val) 1938c2ecf20Sopenharmony_ci break; 1948c2ecf20Sopenharmony_ci } while (--i); 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci if (!i) { 1978c2ecf20Sopenharmony_ci dev_err(dev->mt76.dev, "Error: BBP is not ready\n"); 1988c2ecf20Sopenharmony_ci return -EIO; 1998c2ecf20Sopenharmony_ci } 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci dev_dbg(dev->mt76.dev, "BBP version %08x\n", val); 2028c2ecf20Sopenharmony_ci return 0; 2038c2ecf20Sopenharmony_ci} 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_cistatic void 2068c2ecf20Sopenharmony_cimt76x0_phy_set_band(struct mt76x02_dev *dev, enum nl80211_band band) 2078c2ecf20Sopenharmony_ci{ 2088c2ecf20Sopenharmony_ci switch (band) { 2098c2ecf20Sopenharmony_ci case NL80211_BAND_2GHZ: 2108c2ecf20Sopenharmony_ci RF_RANDOM_WRITE(dev, mt76x0_rf_2g_channel_0_tab); 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci mt76x0_rf_wr(dev, MT_RF(5, 0), 0x45); 2138c2ecf20Sopenharmony_ci mt76x0_rf_wr(dev, MT_RF(6, 0), 0x44); 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci mt76_wr(dev, MT_TX_ALC_VGA3, 0x00050007); 2168c2ecf20Sopenharmony_ci mt76_wr(dev, MT_TX0_RF_GAIN_CORR, 0x003E0002); 2178c2ecf20Sopenharmony_ci break; 2188c2ecf20Sopenharmony_ci case NL80211_BAND_5GHZ: 2198c2ecf20Sopenharmony_ci RF_RANDOM_WRITE(dev, mt76x0_rf_5g_channel_0_tab); 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_ci mt76x0_rf_wr(dev, MT_RF(5, 0), 0x44); 2228c2ecf20Sopenharmony_ci mt76x0_rf_wr(dev, MT_RF(6, 0), 0x45); 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci mt76_wr(dev, MT_TX_ALC_VGA3, 0x00000005); 2258c2ecf20Sopenharmony_ci mt76_wr(dev, MT_TX0_RF_GAIN_CORR, 0x01010102); 2268c2ecf20Sopenharmony_ci break; 2278c2ecf20Sopenharmony_ci default: 2288c2ecf20Sopenharmony_ci break; 2298c2ecf20Sopenharmony_ci } 2308c2ecf20Sopenharmony_ci} 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_cistatic void 2338c2ecf20Sopenharmony_cimt76x0_phy_set_chan_rf_params(struct mt76x02_dev *dev, u8 channel, 2348c2ecf20Sopenharmony_ci u16 rf_bw_band) 2358c2ecf20Sopenharmony_ci{ 2368c2ecf20Sopenharmony_ci const struct mt76x0_freq_item *freq_item; 2378c2ecf20Sopenharmony_ci u16 rf_band = rf_bw_band & 0xff00; 2388c2ecf20Sopenharmony_ci u16 rf_bw = rf_bw_band & 0x00ff; 2398c2ecf20Sopenharmony_ci enum nl80211_band band; 2408c2ecf20Sopenharmony_ci bool b_sdm = false; 2418c2ecf20Sopenharmony_ci u32 mac_reg; 2428c2ecf20Sopenharmony_ci int i; 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(mt76x0_sdm_channel); i++) { 2458c2ecf20Sopenharmony_ci if (channel == mt76x0_sdm_channel[i]) { 2468c2ecf20Sopenharmony_ci b_sdm = true; 2478c2ecf20Sopenharmony_ci break; 2488c2ecf20Sopenharmony_ci } 2498c2ecf20Sopenharmony_ci } 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(mt76x0_frequency_plan); i++) { 2528c2ecf20Sopenharmony_ci if (channel == mt76x0_frequency_plan[i].channel) { 2538c2ecf20Sopenharmony_ci rf_band = mt76x0_frequency_plan[i].band; 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci if (b_sdm) 2568c2ecf20Sopenharmony_ci freq_item = &mt76x0_sdm_frequency_plan[i]; 2578c2ecf20Sopenharmony_ci else 2588c2ecf20Sopenharmony_ci freq_item = &mt76x0_frequency_plan[i]; 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci mt76x0_rf_wr(dev, MT_RF(0, 37), freq_item->pllR37); 2618c2ecf20Sopenharmony_ci mt76x0_rf_wr(dev, MT_RF(0, 36), freq_item->pllR36); 2628c2ecf20Sopenharmony_ci mt76x0_rf_wr(dev, MT_RF(0, 35), freq_item->pllR35); 2638c2ecf20Sopenharmony_ci mt76x0_rf_wr(dev, MT_RF(0, 34), freq_item->pllR34); 2648c2ecf20Sopenharmony_ci mt76x0_rf_wr(dev, MT_RF(0, 33), freq_item->pllR33); 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci mt76x0_rf_rmw(dev, MT_RF(0, 32), 0xe0, 2678c2ecf20Sopenharmony_ci freq_item->pllR32_b7b5); 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci /* R32<4:0> pll_den: (Denomina - 8) */ 2708c2ecf20Sopenharmony_ci mt76x0_rf_rmw(dev, MT_RF(0, 32), MT_RF_PLL_DEN_MASK, 2718c2ecf20Sopenharmony_ci freq_item->pllR32_b4b0); 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci /* R31<7:5> */ 2748c2ecf20Sopenharmony_ci mt76x0_rf_rmw(dev, MT_RF(0, 31), 0xe0, 2758c2ecf20Sopenharmony_ci freq_item->pllR31_b7b5); 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ci /* R31<4:0> pll_k(Nominator) */ 2788c2ecf20Sopenharmony_ci mt76x0_rf_rmw(dev, MT_RF(0, 31), MT_RF_PLL_K_MASK, 2798c2ecf20Sopenharmony_ci freq_item->pllR31_b4b0); 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci /* R30<7> sdm_reset_n */ 2828c2ecf20Sopenharmony_ci if (b_sdm) { 2838c2ecf20Sopenharmony_ci mt76x0_rf_clear(dev, MT_RF(0, 30), 2848c2ecf20Sopenharmony_ci MT_RF_SDM_RESET_MASK); 2858c2ecf20Sopenharmony_ci mt76x0_rf_set(dev, MT_RF(0, 30), 2868c2ecf20Sopenharmony_ci MT_RF_SDM_RESET_MASK); 2878c2ecf20Sopenharmony_ci } else { 2888c2ecf20Sopenharmony_ci mt76x0_rf_rmw(dev, MT_RF(0, 30), 2898c2ecf20Sopenharmony_ci MT_RF_SDM_RESET_MASK, 2908c2ecf20Sopenharmony_ci freq_item->pllR30_b7); 2918c2ecf20Sopenharmony_ci } 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci /* R30<6:2> sdmmash_prbs,sin */ 2948c2ecf20Sopenharmony_ci mt76x0_rf_rmw(dev, MT_RF(0, 30), 2958c2ecf20Sopenharmony_ci MT_RF_SDM_MASH_PRBS_MASK, 2968c2ecf20Sopenharmony_ci freq_item->pllR30_b6b2); 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci /* R30<1> sdm_bp */ 2998c2ecf20Sopenharmony_ci mt76x0_rf_rmw(dev, MT_RF(0, 30), MT_RF_SDM_BP_MASK, 3008c2ecf20Sopenharmony_ci freq_item->pllR30_b1 << 1); 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci /* R30<0> R29<7:0> (hex) pll_n */ 3038c2ecf20Sopenharmony_ci mt76x0_rf_wr(dev, MT_RF(0, 29), 3048c2ecf20Sopenharmony_ci freq_item->pll_n & 0xff); 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_ci mt76x0_rf_rmw(dev, MT_RF(0, 30), 0x1, 3078c2ecf20Sopenharmony_ci (freq_item->pll_n >> 8) & 0x1); 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci /* R28<7:6> isi_iso */ 3108c2ecf20Sopenharmony_ci mt76x0_rf_rmw(dev, MT_RF(0, 28), MT_RF_ISI_ISO_MASK, 3118c2ecf20Sopenharmony_ci freq_item->pllR28_b7b6); 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_ci /* R28<5:4> pfd_dly */ 3148c2ecf20Sopenharmony_ci mt76x0_rf_rmw(dev, MT_RF(0, 28), MT_RF_PFD_DLY_MASK, 3158c2ecf20Sopenharmony_ci freq_item->pllR28_b5b4); 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci /* R28<3:2> clksel option */ 3188c2ecf20Sopenharmony_ci mt76x0_rf_rmw(dev, MT_RF(0, 28), MT_RF_CLK_SEL_MASK, 3198c2ecf20Sopenharmony_ci freq_item->pllR28_b3b2); 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci /* R28<1:0> R27<7:0> R26<7:0> (hex) sdm_k */ 3228c2ecf20Sopenharmony_ci mt76x0_rf_wr(dev, MT_RF(0, 26), 3238c2ecf20Sopenharmony_ci freq_item->pll_sdm_k & 0xff); 3248c2ecf20Sopenharmony_ci mt76x0_rf_wr(dev, MT_RF(0, 27), 3258c2ecf20Sopenharmony_ci (freq_item->pll_sdm_k >> 8) & 0xff); 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci mt76x0_rf_rmw(dev, MT_RF(0, 28), 0x3, 3288c2ecf20Sopenharmony_ci (freq_item->pll_sdm_k >> 16) & 0x3); 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci /* R24<1:0> xo_div */ 3318c2ecf20Sopenharmony_ci mt76x0_rf_rmw(dev, MT_RF(0, 24), MT_RF_XO_DIV_MASK, 3328c2ecf20Sopenharmony_ci freq_item->pllR24_b1b0); 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_ci break; 3358c2ecf20Sopenharmony_ci } 3368c2ecf20Sopenharmony_ci } 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(mt76x0_rf_bw_switch_tab); i++) { 3398c2ecf20Sopenharmony_ci if (rf_bw == mt76x0_rf_bw_switch_tab[i].bw_band) { 3408c2ecf20Sopenharmony_ci mt76x0_rf_wr(dev, 3418c2ecf20Sopenharmony_ci mt76x0_rf_bw_switch_tab[i].rf_bank_reg, 3428c2ecf20Sopenharmony_ci mt76x0_rf_bw_switch_tab[i].value); 3438c2ecf20Sopenharmony_ci } else if ((rf_bw == (mt76x0_rf_bw_switch_tab[i].bw_band & 0xFF)) && 3448c2ecf20Sopenharmony_ci (rf_band & mt76x0_rf_bw_switch_tab[i].bw_band)) { 3458c2ecf20Sopenharmony_ci mt76x0_rf_wr(dev, 3468c2ecf20Sopenharmony_ci mt76x0_rf_bw_switch_tab[i].rf_bank_reg, 3478c2ecf20Sopenharmony_ci mt76x0_rf_bw_switch_tab[i].value); 3488c2ecf20Sopenharmony_ci } 3498c2ecf20Sopenharmony_ci } 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(mt76x0_rf_band_switch_tab); i++) { 3528c2ecf20Sopenharmony_ci if (mt76x0_rf_band_switch_tab[i].bw_band & rf_band) { 3538c2ecf20Sopenharmony_ci mt76x0_rf_wr(dev, 3548c2ecf20Sopenharmony_ci mt76x0_rf_band_switch_tab[i].rf_bank_reg, 3558c2ecf20Sopenharmony_ci mt76x0_rf_band_switch_tab[i].value); 3568c2ecf20Sopenharmony_ci } 3578c2ecf20Sopenharmony_ci } 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_ci mt76_clear(dev, MT_RF_MISC, 0xc); 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ci band = (rf_band & RF_G_BAND) ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ; 3628c2ecf20Sopenharmony_ci if (mt76x02_ext_pa_enabled(dev, band)) { 3638c2ecf20Sopenharmony_ci /* MT_RF_MISC (offset: 0x0518) 3648c2ecf20Sopenharmony_ci * [2]1'b1: enable external A band PA 3658c2ecf20Sopenharmony_ci * 1'b0: disable external A band PA 3668c2ecf20Sopenharmony_ci * [3]1'b1: enable external G band PA 3678c2ecf20Sopenharmony_ci * 1'b0: disable external G band PA 3688c2ecf20Sopenharmony_ci */ 3698c2ecf20Sopenharmony_ci if (rf_band & RF_A_BAND) 3708c2ecf20Sopenharmony_ci mt76_set(dev, MT_RF_MISC, BIT(2)); 3718c2ecf20Sopenharmony_ci else 3728c2ecf20Sopenharmony_ci mt76_set(dev, MT_RF_MISC, BIT(3)); 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci /* External PA */ 3758c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(mt76x0_rf_ext_pa_tab); i++) 3768c2ecf20Sopenharmony_ci if (mt76x0_rf_ext_pa_tab[i].bw_band & rf_band) 3778c2ecf20Sopenharmony_ci mt76x0_rf_wr(dev, 3788c2ecf20Sopenharmony_ci mt76x0_rf_ext_pa_tab[i].rf_bank_reg, 3798c2ecf20Sopenharmony_ci mt76x0_rf_ext_pa_tab[i].value); 3808c2ecf20Sopenharmony_ci } 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_ci if (rf_band & RF_G_BAND) { 3838c2ecf20Sopenharmony_ci mt76_wr(dev, MT_TX0_RF_GAIN_ATTEN, 0x63707400); 3848c2ecf20Sopenharmony_ci /* Set Atten mode = 2 For G band, Disable Tx Inc dcoc. */ 3858c2ecf20Sopenharmony_ci mac_reg = mt76_rr(dev, MT_TX_ALC_CFG_1); 3868c2ecf20Sopenharmony_ci mac_reg &= 0x896400FF; 3878c2ecf20Sopenharmony_ci mt76_wr(dev, MT_TX_ALC_CFG_1, mac_reg); 3888c2ecf20Sopenharmony_ci } else { 3898c2ecf20Sopenharmony_ci mt76_wr(dev, MT_TX0_RF_GAIN_ATTEN, 0x686A7800); 3908c2ecf20Sopenharmony_ci /* Set Atten mode = 0 3918c2ecf20Sopenharmony_ci * For Ext A band, Disable Tx Inc dcoc Cal. 3928c2ecf20Sopenharmony_ci */ 3938c2ecf20Sopenharmony_ci mac_reg = mt76_rr(dev, MT_TX_ALC_CFG_1); 3948c2ecf20Sopenharmony_ci mac_reg &= 0x890400FF; 3958c2ecf20Sopenharmony_ci mt76_wr(dev, MT_TX_ALC_CFG_1, mac_reg); 3968c2ecf20Sopenharmony_ci } 3978c2ecf20Sopenharmony_ci} 3988c2ecf20Sopenharmony_ci 3998c2ecf20Sopenharmony_cistatic void 4008c2ecf20Sopenharmony_cimt76x0_phy_set_chan_bbp_params(struct mt76x02_dev *dev, u16 rf_bw_band) 4018c2ecf20Sopenharmony_ci{ 4028c2ecf20Sopenharmony_ci int i; 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(mt76x0_bbp_switch_tab); i++) { 4058c2ecf20Sopenharmony_ci const struct mt76x0_bbp_switch_item *item = &mt76x0_bbp_switch_tab[i]; 4068c2ecf20Sopenharmony_ci const struct mt76_reg_pair *pair = &item->reg_pair; 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_ci if ((rf_bw_band & item->bw_band) != rf_bw_band) 4098c2ecf20Sopenharmony_ci continue; 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_ci if (pair->reg == MT_BBP(AGC, 8)) { 4128c2ecf20Sopenharmony_ci u32 val = pair->value; 4138c2ecf20Sopenharmony_ci u8 gain; 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_ci gain = FIELD_GET(MT_BBP_AGC_GAIN, val); 4168c2ecf20Sopenharmony_ci gain -= dev->cal.rx.lna_gain * 2; 4178c2ecf20Sopenharmony_ci val &= ~MT_BBP_AGC_GAIN; 4188c2ecf20Sopenharmony_ci val |= FIELD_PREP(MT_BBP_AGC_GAIN, gain); 4198c2ecf20Sopenharmony_ci mt76_wr(dev, pair->reg, val); 4208c2ecf20Sopenharmony_ci } else { 4218c2ecf20Sopenharmony_ci mt76_wr(dev, pair->reg, pair->value); 4228c2ecf20Sopenharmony_ci } 4238c2ecf20Sopenharmony_ci } 4248c2ecf20Sopenharmony_ci} 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_cistatic void mt76x0_phy_ant_select(struct mt76x02_dev *dev) 4278c2ecf20Sopenharmony_ci{ 4288c2ecf20Sopenharmony_ci u16 ee_ant = mt76x02_eeprom_get(dev, MT_EE_ANTENNA); 4298c2ecf20Sopenharmony_ci u16 ee_cfg1 = mt76x02_eeprom_get(dev, MT_EE_CFG1_INIT); 4308c2ecf20Sopenharmony_ci u16 nic_conf2 = mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_2); 4318c2ecf20Sopenharmony_ci u32 wlan, coex3; 4328c2ecf20Sopenharmony_ci bool ant_div; 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_ci wlan = mt76_rr(dev, MT_WLAN_FUN_CTRL); 4358c2ecf20Sopenharmony_ci coex3 = mt76_rr(dev, MT_COEXCFG3); 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_ci ee_ant &= ~(BIT(14) | BIT(12)); 4388c2ecf20Sopenharmony_ci wlan &= ~(BIT(6) | BIT(5)); 4398c2ecf20Sopenharmony_ci coex3 &= ~GENMASK(5, 2); 4408c2ecf20Sopenharmony_ci 4418c2ecf20Sopenharmony_ci if (ee_ant & MT_EE_ANTENNA_DUAL) { 4428c2ecf20Sopenharmony_ci /* dual antenna mode */ 4438c2ecf20Sopenharmony_ci ant_div = !(nic_conf2 & MT_EE_NIC_CONF_2_ANT_OPT) && 4448c2ecf20Sopenharmony_ci (nic_conf2 & MT_EE_NIC_CONF_2_ANT_DIV); 4458c2ecf20Sopenharmony_ci if (ant_div) 4468c2ecf20Sopenharmony_ci ee_ant |= BIT(12); 4478c2ecf20Sopenharmony_ci else 4488c2ecf20Sopenharmony_ci coex3 |= BIT(4); 4498c2ecf20Sopenharmony_ci coex3 |= BIT(3); 4508c2ecf20Sopenharmony_ci if (dev->mphy.cap.has_2ghz) 4518c2ecf20Sopenharmony_ci wlan |= BIT(6); 4528c2ecf20Sopenharmony_ci } else { 4538c2ecf20Sopenharmony_ci /* sigle antenna mode */ 4548c2ecf20Sopenharmony_ci if (dev->mphy.cap.has_5ghz) { 4558c2ecf20Sopenharmony_ci coex3 |= BIT(3) | BIT(4); 4568c2ecf20Sopenharmony_ci } else { 4578c2ecf20Sopenharmony_ci wlan |= BIT(6); 4588c2ecf20Sopenharmony_ci coex3 |= BIT(1); 4598c2ecf20Sopenharmony_ci } 4608c2ecf20Sopenharmony_ci } 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_ci if (is_mt7630(dev)) 4638c2ecf20Sopenharmony_ci ee_ant |= BIT(14) | BIT(11); 4648c2ecf20Sopenharmony_ci 4658c2ecf20Sopenharmony_ci mt76_wr(dev, MT_WLAN_FUN_CTRL, wlan); 4668c2ecf20Sopenharmony_ci mt76_rmw(dev, MT_CMB_CTRL, GENMASK(15, 0), ee_ant); 4678c2ecf20Sopenharmony_ci mt76_rmw(dev, MT_CSR_EE_CFG1, GENMASK(15, 0), ee_cfg1); 4688c2ecf20Sopenharmony_ci mt76_clear(dev, MT_COEXCFG0, BIT(2)); 4698c2ecf20Sopenharmony_ci mt76_wr(dev, MT_COEXCFG3, coex3); 4708c2ecf20Sopenharmony_ci} 4718c2ecf20Sopenharmony_ci 4728c2ecf20Sopenharmony_cistatic void 4738c2ecf20Sopenharmony_cimt76x0_phy_bbp_set_bw(struct mt76x02_dev *dev, enum nl80211_chan_width width) 4748c2ecf20Sopenharmony_ci{ 4758c2ecf20Sopenharmony_ci enum { BW_20 = 0, BW_40 = 1, BW_80 = 2, BW_10 = 4}; 4768c2ecf20Sopenharmony_ci int bw; 4778c2ecf20Sopenharmony_ci 4788c2ecf20Sopenharmony_ci switch (width) { 4798c2ecf20Sopenharmony_ci default: 4808c2ecf20Sopenharmony_ci case NL80211_CHAN_WIDTH_20_NOHT: 4818c2ecf20Sopenharmony_ci case NL80211_CHAN_WIDTH_20: 4828c2ecf20Sopenharmony_ci bw = BW_20; 4838c2ecf20Sopenharmony_ci break; 4848c2ecf20Sopenharmony_ci case NL80211_CHAN_WIDTH_40: 4858c2ecf20Sopenharmony_ci bw = BW_40; 4868c2ecf20Sopenharmony_ci break; 4878c2ecf20Sopenharmony_ci case NL80211_CHAN_WIDTH_80: 4888c2ecf20Sopenharmony_ci bw = BW_80; 4898c2ecf20Sopenharmony_ci break; 4908c2ecf20Sopenharmony_ci case NL80211_CHAN_WIDTH_10: 4918c2ecf20Sopenharmony_ci bw = BW_10; 4928c2ecf20Sopenharmony_ci break; 4938c2ecf20Sopenharmony_ci case NL80211_CHAN_WIDTH_80P80: 4948c2ecf20Sopenharmony_ci case NL80211_CHAN_WIDTH_160: 4958c2ecf20Sopenharmony_ci case NL80211_CHAN_WIDTH_5: 4968c2ecf20Sopenharmony_ci /* TODO error */ 4978c2ecf20Sopenharmony_ci return; 4988c2ecf20Sopenharmony_ci } 4998c2ecf20Sopenharmony_ci 5008c2ecf20Sopenharmony_ci mt76x02_mcu_function_select(dev, BW_SETTING, bw); 5018c2ecf20Sopenharmony_ci} 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_cistatic void mt76x0_phy_tssi_dc_calibrate(struct mt76x02_dev *dev) 5048c2ecf20Sopenharmony_ci{ 5058c2ecf20Sopenharmony_ci struct ieee80211_channel *chan = dev->mphy.chandef.chan; 5068c2ecf20Sopenharmony_ci u32 val; 5078c2ecf20Sopenharmony_ci 5088c2ecf20Sopenharmony_ci if (chan->band == NL80211_BAND_5GHZ) 5098c2ecf20Sopenharmony_ci mt76x0_rf_clear(dev, MT_RF(0, 67), 0xf); 5108c2ecf20Sopenharmony_ci 5118c2ecf20Sopenharmony_ci /* bypass ADDA control */ 5128c2ecf20Sopenharmony_ci mt76_wr(dev, MT_RF_SETTING_0, 0x60002237); 5138c2ecf20Sopenharmony_ci mt76_wr(dev, MT_RF_BYPASS_0, 0xffffffff); 5148c2ecf20Sopenharmony_ci 5158c2ecf20Sopenharmony_ci /* bbp sw reset */ 5168c2ecf20Sopenharmony_ci mt76_set(dev, MT_BBP(CORE, 4), BIT(0)); 5178c2ecf20Sopenharmony_ci usleep_range(500, 1000); 5188c2ecf20Sopenharmony_ci mt76_clear(dev, MT_BBP(CORE, 4), BIT(0)); 5198c2ecf20Sopenharmony_ci 5208c2ecf20Sopenharmony_ci val = (chan->band == NL80211_BAND_5GHZ) ? 0x80055 : 0x80050; 5218c2ecf20Sopenharmony_ci mt76_wr(dev, MT_BBP(CORE, 34), val); 5228c2ecf20Sopenharmony_ci 5238c2ecf20Sopenharmony_ci /* enable TX with DAC0 input */ 5248c2ecf20Sopenharmony_ci mt76_wr(dev, MT_BBP(TXBE, 6), BIT(31)); 5258c2ecf20Sopenharmony_ci 5268c2ecf20Sopenharmony_ci mt76_poll_msec(dev, MT_BBP(CORE, 34), BIT(4), 0, 200); 5278c2ecf20Sopenharmony_ci dev->cal.tssi_dc = mt76_rr(dev, MT_BBP(CORE, 35)) & 0xff; 5288c2ecf20Sopenharmony_ci 5298c2ecf20Sopenharmony_ci /* stop bypass ADDA */ 5308c2ecf20Sopenharmony_ci mt76_wr(dev, MT_RF_BYPASS_0, 0); 5318c2ecf20Sopenharmony_ci /* stop TX */ 5328c2ecf20Sopenharmony_ci mt76_wr(dev, MT_BBP(TXBE, 6), 0); 5338c2ecf20Sopenharmony_ci /* bbp sw reset */ 5348c2ecf20Sopenharmony_ci mt76_set(dev, MT_BBP(CORE, 4), BIT(0)); 5358c2ecf20Sopenharmony_ci usleep_range(500, 1000); 5368c2ecf20Sopenharmony_ci mt76_clear(dev, MT_BBP(CORE, 4), BIT(0)); 5378c2ecf20Sopenharmony_ci 5388c2ecf20Sopenharmony_ci if (chan->band == NL80211_BAND_5GHZ) 5398c2ecf20Sopenharmony_ci mt76x0_rf_rmw(dev, MT_RF(0, 67), 0xf, 0x4); 5408c2ecf20Sopenharmony_ci} 5418c2ecf20Sopenharmony_ci 5428c2ecf20Sopenharmony_cistatic int 5438c2ecf20Sopenharmony_cimt76x0_phy_tssi_adc_calibrate(struct mt76x02_dev *dev, s16 *ltssi, 5448c2ecf20Sopenharmony_ci u8 *info) 5458c2ecf20Sopenharmony_ci{ 5468c2ecf20Sopenharmony_ci struct ieee80211_channel *chan = dev->mphy.chandef.chan; 5478c2ecf20Sopenharmony_ci u32 val; 5488c2ecf20Sopenharmony_ci 5498c2ecf20Sopenharmony_ci val = (chan->band == NL80211_BAND_5GHZ) ? 0x80055 : 0x80050; 5508c2ecf20Sopenharmony_ci mt76_wr(dev, MT_BBP(CORE, 34), val); 5518c2ecf20Sopenharmony_ci 5528c2ecf20Sopenharmony_ci if (!mt76_poll_msec(dev, MT_BBP(CORE, 34), BIT(4), 0, 200)) { 5538c2ecf20Sopenharmony_ci mt76_clear(dev, MT_BBP(CORE, 34), BIT(4)); 5548c2ecf20Sopenharmony_ci return -ETIMEDOUT; 5558c2ecf20Sopenharmony_ci } 5568c2ecf20Sopenharmony_ci 5578c2ecf20Sopenharmony_ci *ltssi = mt76_rr(dev, MT_BBP(CORE, 35)) & 0xff; 5588c2ecf20Sopenharmony_ci if (chan->band == NL80211_BAND_5GHZ) 5598c2ecf20Sopenharmony_ci *ltssi += 128; 5608c2ecf20Sopenharmony_ci 5618c2ecf20Sopenharmony_ci /* set packet info#1 mode */ 5628c2ecf20Sopenharmony_ci mt76_wr(dev, MT_BBP(CORE, 34), 0x80041); 5638c2ecf20Sopenharmony_ci info[0] = mt76_rr(dev, MT_BBP(CORE, 35)) & 0xff; 5648c2ecf20Sopenharmony_ci 5658c2ecf20Sopenharmony_ci /* set packet info#2 mode */ 5668c2ecf20Sopenharmony_ci mt76_wr(dev, MT_BBP(CORE, 34), 0x80042); 5678c2ecf20Sopenharmony_ci info[1] = mt76_rr(dev, MT_BBP(CORE, 35)) & 0xff; 5688c2ecf20Sopenharmony_ci 5698c2ecf20Sopenharmony_ci /* set packet info#3 mode */ 5708c2ecf20Sopenharmony_ci mt76_wr(dev, MT_BBP(CORE, 34), 0x80043); 5718c2ecf20Sopenharmony_ci info[2] = mt76_rr(dev, MT_BBP(CORE, 35)) & 0xff; 5728c2ecf20Sopenharmony_ci 5738c2ecf20Sopenharmony_ci return 0; 5748c2ecf20Sopenharmony_ci} 5758c2ecf20Sopenharmony_ci 5768c2ecf20Sopenharmony_cistatic u8 mt76x0_phy_get_rf_pa_mode(struct mt76x02_dev *dev, 5778c2ecf20Sopenharmony_ci int index, u8 tx_rate) 5788c2ecf20Sopenharmony_ci{ 5798c2ecf20Sopenharmony_ci u32 val, reg; 5808c2ecf20Sopenharmony_ci 5818c2ecf20Sopenharmony_ci reg = (index == 1) ? MT_RF_PA_MODE_CFG1 : MT_RF_PA_MODE_CFG0; 5828c2ecf20Sopenharmony_ci val = mt76_rr(dev, reg); 5838c2ecf20Sopenharmony_ci return (val & (3 << (tx_rate * 2))) >> (tx_rate * 2); 5848c2ecf20Sopenharmony_ci} 5858c2ecf20Sopenharmony_ci 5868c2ecf20Sopenharmony_cistatic int 5878c2ecf20Sopenharmony_cimt76x0_phy_get_target_power(struct mt76x02_dev *dev, u8 tx_mode, 5888c2ecf20Sopenharmony_ci u8 *info, s8 *target_power, 5898c2ecf20Sopenharmony_ci s8 *target_pa_power) 5908c2ecf20Sopenharmony_ci{ 5918c2ecf20Sopenharmony_ci u8 tx_rate, cur_power; 5928c2ecf20Sopenharmony_ci 5938c2ecf20Sopenharmony_ci cur_power = mt76_rr(dev, MT_TX_ALC_CFG_0) & MT_TX_ALC_CFG_0_CH_INIT_0; 5948c2ecf20Sopenharmony_ci switch (tx_mode) { 5958c2ecf20Sopenharmony_ci case 0: 5968c2ecf20Sopenharmony_ci /* cck rates */ 5978c2ecf20Sopenharmony_ci tx_rate = (info[0] & 0x60) >> 5; 5988c2ecf20Sopenharmony_ci if (tx_rate > 3) 5998c2ecf20Sopenharmony_ci return -EINVAL; 6008c2ecf20Sopenharmony_ci 6018c2ecf20Sopenharmony_ci *target_power = cur_power + dev->mt76.rate_power.cck[tx_rate]; 6028c2ecf20Sopenharmony_ci *target_pa_power = mt76x0_phy_get_rf_pa_mode(dev, 0, tx_rate); 6038c2ecf20Sopenharmony_ci break; 6048c2ecf20Sopenharmony_ci case 1: { 6058c2ecf20Sopenharmony_ci u8 index; 6068c2ecf20Sopenharmony_ci 6078c2ecf20Sopenharmony_ci /* ofdm rates */ 6088c2ecf20Sopenharmony_ci tx_rate = (info[0] & 0xf0) >> 4; 6098c2ecf20Sopenharmony_ci switch (tx_rate) { 6108c2ecf20Sopenharmony_ci case 0xb: 6118c2ecf20Sopenharmony_ci index = 0; 6128c2ecf20Sopenharmony_ci break; 6138c2ecf20Sopenharmony_ci case 0xf: 6148c2ecf20Sopenharmony_ci index = 1; 6158c2ecf20Sopenharmony_ci break; 6168c2ecf20Sopenharmony_ci case 0xa: 6178c2ecf20Sopenharmony_ci index = 2; 6188c2ecf20Sopenharmony_ci break; 6198c2ecf20Sopenharmony_ci case 0xe: 6208c2ecf20Sopenharmony_ci index = 3; 6218c2ecf20Sopenharmony_ci break; 6228c2ecf20Sopenharmony_ci case 0x9: 6238c2ecf20Sopenharmony_ci index = 4; 6248c2ecf20Sopenharmony_ci break; 6258c2ecf20Sopenharmony_ci case 0xd: 6268c2ecf20Sopenharmony_ci index = 5; 6278c2ecf20Sopenharmony_ci break; 6288c2ecf20Sopenharmony_ci case 0x8: 6298c2ecf20Sopenharmony_ci index = 6; 6308c2ecf20Sopenharmony_ci break; 6318c2ecf20Sopenharmony_ci case 0xc: 6328c2ecf20Sopenharmony_ci index = 7; 6338c2ecf20Sopenharmony_ci break; 6348c2ecf20Sopenharmony_ci default: 6358c2ecf20Sopenharmony_ci return -EINVAL; 6368c2ecf20Sopenharmony_ci } 6378c2ecf20Sopenharmony_ci 6388c2ecf20Sopenharmony_ci *target_power = cur_power + dev->mt76.rate_power.ofdm[index]; 6398c2ecf20Sopenharmony_ci *target_pa_power = mt76x0_phy_get_rf_pa_mode(dev, 0, index + 4); 6408c2ecf20Sopenharmony_ci break; 6418c2ecf20Sopenharmony_ci } 6428c2ecf20Sopenharmony_ci case 4: 6438c2ecf20Sopenharmony_ci /* vht rates */ 6448c2ecf20Sopenharmony_ci tx_rate = info[1] & 0xf; 6458c2ecf20Sopenharmony_ci if (tx_rate > 9) 6468c2ecf20Sopenharmony_ci return -EINVAL; 6478c2ecf20Sopenharmony_ci 6488c2ecf20Sopenharmony_ci *target_power = cur_power + dev->mt76.rate_power.vht[tx_rate]; 6498c2ecf20Sopenharmony_ci *target_pa_power = mt76x0_phy_get_rf_pa_mode(dev, 1, tx_rate); 6508c2ecf20Sopenharmony_ci break; 6518c2ecf20Sopenharmony_ci default: 6528c2ecf20Sopenharmony_ci /* ht rates */ 6538c2ecf20Sopenharmony_ci tx_rate = info[1] & 0x7f; 6548c2ecf20Sopenharmony_ci if (tx_rate > 9) 6558c2ecf20Sopenharmony_ci return -EINVAL; 6568c2ecf20Sopenharmony_ci 6578c2ecf20Sopenharmony_ci *target_power = cur_power + dev->mt76.rate_power.ht[tx_rate]; 6588c2ecf20Sopenharmony_ci *target_pa_power = mt76x0_phy_get_rf_pa_mode(dev, 1, tx_rate); 6598c2ecf20Sopenharmony_ci break; 6608c2ecf20Sopenharmony_ci } 6618c2ecf20Sopenharmony_ci 6628c2ecf20Sopenharmony_ci return 0; 6638c2ecf20Sopenharmony_ci} 6648c2ecf20Sopenharmony_ci 6658c2ecf20Sopenharmony_cistatic s16 mt76x0_phy_lin2db(u16 val) 6668c2ecf20Sopenharmony_ci{ 6678c2ecf20Sopenharmony_ci u32 mantissa = val << 4; 6688c2ecf20Sopenharmony_ci int ret, data; 6698c2ecf20Sopenharmony_ci s16 exp = -4; 6708c2ecf20Sopenharmony_ci 6718c2ecf20Sopenharmony_ci while (mantissa < BIT(15)) { 6728c2ecf20Sopenharmony_ci mantissa <<= 1; 6738c2ecf20Sopenharmony_ci if (--exp < -20) 6748c2ecf20Sopenharmony_ci return -10000; 6758c2ecf20Sopenharmony_ci } 6768c2ecf20Sopenharmony_ci while (mantissa > 0xffff) { 6778c2ecf20Sopenharmony_ci mantissa >>= 1; 6788c2ecf20Sopenharmony_ci if (++exp > 20) 6798c2ecf20Sopenharmony_ci return -10000; 6808c2ecf20Sopenharmony_ci } 6818c2ecf20Sopenharmony_ci 6828c2ecf20Sopenharmony_ci /* s(15,0) */ 6838c2ecf20Sopenharmony_ci if (mantissa <= 47104) 6848c2ecf20Sopenharmony_ci data = mantissa + (mantissa >> 3) + (mantissa >> 4) - 38400; 6858c2ecf20Sopenharmony_ci else 6868c2ecf20Sopenharmony_ci data = mantissa - (mantissa >> 3) - (mantissa >> 6) - 23040; 6878c2ecf20Sopenharmony_ci data = max_t(int, 0, data); 6888c2ecf20Sopenharmony_ci 6898c2ecf20Sopenharmony_ci ret = ((15 + exp) << 15) + data; 6908c2ecf20Sopenharmony_ci ret = (ret << 2) + (ret << 1) + (ret >> 6) + (ret >> 7); 6918c2ecf20Sopenharmony_ci return ret >> 10; 6928c2ecf20Sopenharmony_ci} 6938c2ecf20Sopenharmony_ci 6948c2ecf20Sopenharmony_cistatic int 6958c2ecf20Sopenharmony_cimt76x0_phy_get_delta_power(struct mt76x02_dev *dev, u8 tx_mode, 6968c2ecf20Sopenharmony_ci s8 target_power, s8 target_pa_power, 6978c2ecf20Sopenharmony_ci s16 ltssi) 6988c2ecf20Sopenharmony_ci{ 6998c2ecf20Sopenharmony_ci struct ieee80211_channel *chan = dev->mphy.chandef.chan; 7008c2ecf20Sopenharmony_ci int tssi_target = target_power << 12, tssi_slope; 7018c2ecf20Sopenharmony_ci int tssi_offset, tssi_db, ret; 7028c2ecf20Sopenharmony_ci u32 data; 7038c2ecf20Sopenharmony_ci u16 val; 7048c2ecf20Sopenharmony_ci 7058c2ecf20Sopenharmony_ci if (chan->band == NL80211_BAND_5GHZ) { 7068c2ecf20Sopenharmony_ci u8 bound[7]; 7078c2ecf20Sopenharmony_ci int i, err; 7088c2ecf20Sopenharmony_ci 7098c2ecf20Sopenharmony_ci err = mt76x02_eeprom_copy(dev, MT_EE_TSSI_BOUND1, bound, 7108c2ecf20Sopenharmony_ci sizeof(bound)); 7118c2ecf20Sopenharmony_ci if (err < 0) 7128c2ecf20Sopenharmony_ci return err; 7138c2ecf20Sopenharmony_ci 7148c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(bound); i++) { 7158c2ecf20Sopenharmony_ci if (chan->hw_value <= bound[i] || !bound[i]) 7168c2ecf20Sopenharmony_ci break; 7178c2ecf20Sopenharmony_ci } 7188c2ecf20Sopenharmony_ci val = mt76x02_eeprom_get(dev, MT_EE_TSSI_SLOPE_5G + i * 2); 7198c2ecf20Sopenharmony_ci 7208c2ecf20Sopenharmony_ci tssi_offset = val >> 8; 7218c2ecf20Sopenharmony_ci if ((tssi_offset >= 64 && tssi_offset <= 127) || 7228c2ecf20Sopenharmony_ci (tssi_offset & BIT(7))) 7238c2ecf20Sopenharmony_ci tssi_offset -= BIT(8); 7248c2ecf20Sopenharmony_ci } else { 7258c2ecf20Sopenharmony_ci val = mt76x02_eeprom_get(dev, MT_EE_TSSI_SLOPE_2G); 7268c2ecf20Sopenharmony_ci 7278c2ecf20Sopenharmony_ci tssi_offset = val >> 8; 7288c2ecf20Sopenharmony_ci if (tssi_offset & BIT(7)) 7298c2ecf20Sopenharmony_ci tssi_offset -= BIT(8); 7308c2ecf20Sopenharmony_ci } 7318c2ecf20Sopenharmony_ci tssi_slope = val & 0xff; 7328c2ecf20Sopenharmony_ci 7338c2ecf20Sopenharmony_ci switch (target_pa_power) { 7348c2ecf20Sopenharmony_ci case 1: 7358c2ecf20Sopenharmony_ci if (chan->band == NL80211_BAND_2GHZ) 7368c2ecf20Sopenharmony_ci tssi_target += 29491; /* 3.6 * 8192 */ 7378c2ecf20Sopenharmony_ci fallthrough; 7388c2ecf20Sopenharmony_ci case 0: 7398c2ecf20Sopenharmony_ci break; 7408c2ecf20Sopenharmony_ci default: 7418c2ecf20Sopenharmony_ci tssi_target += 4424; /* 0.54 * 8192 */ 7428c2ecf20Sopenharmony_ci break; 7438c2ecf20Sopenharmony_ci } 7448c2ecf20Sopenharmony_ci 7458c2ecf20Sopenharmony_ci if (!tx_mode) { 7468c2ecf20Sopenharmony_ci data = mt76_rr(dev, MT_BBP(CORE, 1)); 7478c2ecf20Sopenharmony_ci if (is_mt7630(dev) && mt76_is_mmio(&dev->mt76)) { 7488c2ecf20Sopenharmony_ci int offset; 7498c2ecf20Sopenharmony_ci 7508c2ecf20Sopenharmony_ci /* 2.3 * 8192 or 1.5 * 8192 */ 7518c2ecf20Sopenharmony_ci offset = (data & BIT(5)) ? 18841 : 12288; 7528c2ecf20Sopenharmony_ci tssi_target += offset; 7538c2ecf20Sopenharmony_ci } else if (data & BIT(5)) { 7548c2ecf20Sopenharmony_ci /* 0.8 * 8192 */ 7558c2ecf20Sopenharmony_ci tssi_target += 6554; 7568c2ecf20Sopenharmony_ci } 7578c2ecf20Sopenharmony_ci } 7588c2ecf20Sopenharmony_ci 7598c2ecf20Sopenharmony_ci data = mt76_rr(dev, MT_BBP(TXBE, 4)); 7608c2ecf20Sopenharmony_ci switch (data & 0x3) { 7618c2ecf20Sopenharmony_ci case 1: 7628c2ecf20Sopenharmony_ci tssi_target -= 49152; /* -6db * 8192 */ 7638c2ecf20Sopenharmony_ci break; 7648c2ecf20Sopenharmony_ci case 2: 7658c2ecf20Sopenharmony_ci tssi_target -= 98304; /* -12db * 8192 */ 7668c2ecf20Sopenharmony_ci break; 7678c2ecf20Sopenharmony_ci case 3: 7688c2ecf20Sopenharmony_ci tssi_target += 49152; /* 6db * 8192 */ 7698c2ecf20Sopenharmony_ci break; 7708c2ecf20Sopenharmony_ci default: 7718c2ecf20Sopenharmony_ci break; 7728c2ecf20Sopenharmony_ci } 7738c2ecf20Sopenharmony_ci 7748c2ecf20Sopenharmony_ci tssi_db = mt76x0_phy_lin2db(ltssi - dev->cal.tssi_dc) * tssi_slope; 7758c2ecf20Sopenharmony_ci if (chan->band == NL80211_BAND_5GHZ) { 7768c2ecf20Sopenharmony_ci tssi_db += ((tssi_offset - 50) << 10); /* offset s4.3 */ 7778c2ecf20Sopenharmony_ci tssi_target -= tssi_db; 7788c2ecf20Sopenharmony_ci if (ltssi > 254 && tssi_target > 0) { 7798c2ecf20Sopenharmony_ci /* upper saturate */ 7808c2ecf20Sopenharmony_ci tssi_target = 0; 7818c2ecf20Sopenharmony_ci } 7828c2ecf20Sopenharmony_ci } else { 7838c2ecf20Sopenharmony_ci tssi_db += (tssi_offset << 9); /* offset s3.4 */ 7848c2ecf20Sopenharmony_ci tssi_target -= tssi_db; 7858c2ecf20Sopenharmony_ci /* upper-lower saturate */ 7868c2ecf20Sopenharmony_ci if ((ltssi > 126 && tssi_target > 0) || 7878c2ecf20Sopenharmony_ci ((ltssi - dev->cal.tssi_dc) < 1 && tssi_target < 0)) { 7888c2ecf20Sopenharmony_ci tssi_target = 0; 7898c2ecf20Sopenharmony_ci } 7908c2ecf20Sopenharmony_ci } 7918c2ecf20Sopenharmony_ci 7928c2ecf20Sopenharmony_ci if ((dev->cal.tssi_target ^ tssi_target) < 0 && 7938c2ecf20Sopenharmony_ci dev->cal.tssi_target > -4096 && dev->cal.tssi_target < 4096 && 7948c2ecf20Sopenharmony_ci tssi_target > -4096 && tssi_target < 4096) { 7958c2ecf20Sopenharmony_ci if ((tssi_target < 0 && 7968c2ecf20Sopenharmony_ci tssi_target + dev->cal.tssi_target > 0) || 7978c2ecf20Sopenharmony_ci (tssi_target > 0 && 7988c2ecf20Sopenharmony_ci tssi_target + dev->cal.tssi_target <= 0)) 7998c2ecf20Sopenharmony_ci tssi_target = 0; 8008c2ecf20Sopenharmony_ci else 8018c2ecf20Sopenharmony_ci dev->cal.tssi_target = tssi_target; 8028c2ecf20Sopenharmony_ci } else { 8038c2ecf20Sopenharmony_ci dev->cal.tssi_target = tssi_target; 8048c2ecf20Sopenharmony_ci } 8058c2ecf20Sopenharmony_ci 8068c2ecf20Sopenharmony_ci /* make the compensate value to the nearest compensate code */ 8078c2ecf20Sopenharmony_ci if (tssi_target > 0) 8088c2ecf20Sopenharmony_ci tssi_target += 2048; 8098c2ecf20Sopenharmony_ci else 8108c2ecf20Sopenharmony_ci tssi_target -= 2048; 8118c2ecf20Sopenharmony_ci tssi_target >>= 12; 8128c2ecf20Sopenharmony_ci 8138c2ecf20Sopenharmony_ci ret = mt76_get_field(dev, MT_TX_ALC_CFG_1, MT_TX_ALC_CFG_1_TEMP_COMP); 8148c2ecf20Sopenharmony_ci if (ret & BIT(5)) 8158c2ecf20Sopenharmony_ci ret -= BIT(6); 8168c2ecf20Sopenharmony_ci ret += tssi_target; 8178c2ecf20Sopenharmony_ci 8188c2ecf20Sopenharmony_ci ret = min_t(int, 31, ret); 8198c2ecf20Sopenharmony_ci return max_t(int, -32, ret); 8208c2ecf20Sopenharmony_ci} 8218c2ecf20Sopenharmony_ci 8228c2ecf20Sopenharmony_cistatic void mt76x0_phy_tssi_calibrate(struct mt76x02_dev *dev) 8238c2ecf20Sopenharmony_ci{ 8248c2ecf20Sopenharmony_ci s8 target_power, target_pa_power; 8258c2ecf20Sopenharmony_ci u8 tssi_info[3], tx_mode; 8268c2ecf20Sopenharmony_ci s16 ltssi; 8278c2ecf20Sopenharmony_ci s8 val; 8288c2ecf20Sopenharmony_ci 8298c2ecf20Sopenharmony_ci if (mt76x0_phy_tssi_adc_calibrate(dev, <ssi, tssi_info) < 0) 8308c2ecf20Sopenharmony_ci return; 8318c2ecf20Sopenharmony_ci 8328c2ecf20Sopenharmony_ci tx_mode = tssi_info[0] & 0x7; 8338c2ecf20Sopenharmony_ci if (mt76x0_phy_get_target_power(dev, tx_mode, tssi_info, 8348c2ecf20Sopenharmony_ci &target_power, &target_pa_power) < 0) 8358c2ecf20Sopenharmony_ci return; 8368c2ecf20Sopenharmony_ci 8378c2ecf20Sopenharmony_ci val = mt76x0_phy_get_delta_power(dev, tx_mode, target_power, 8388c2ecf20Sopenharmony_ci target_pa_power, ltssi); 8398c2ecf20Sopenharmony_ci mt76_rmw_field(dev, MT_TX_ALC_CFG_1, MT_TX_ALC_CFG_1_TEMP_COMP, val); 8408c2ecf20Sopenharmony_ci} 8418c2ecf20Sopenharmony_ci 8428c2ecf20Sopenharmony_civoid mt76x0_phy_set_txpower(struct mt76x02_dev *dev) 8438c2ecf20Sopenharmony_ci{ 8448c2ecf20Sopenharmony_ci struct mt76_rate_power *t = &dev->mt76.rate_power; 8458c2ecf20Sopenharmony_ci s8 info; 8468c2ecf20Sopenharmony_ci 8478c2ecf20Sopenharmony_ci mt76x0_get_tx_power_per_rate(dev, dev->mphy.chandef.chan, t); 8488c2ecf20Sopenharmony_ci mt76x0_get_power_info(dev, dev->mphy.chandef.chan, &info); 8498c2ecf20Sopenharmony_ci 8508c2ecf20Sopenharmony_ci mt76x02_add_rate_power_offset(t, info); 8518c2ecf20Sopenharmony_ci mt76x02_limit_rate_power(t, dev->txpower_conf); 8528c2ecf20Sopenharmony_ci dev->mphy.txpower_cur = mt76x02_get_max_rate_power(t); 8538c2ecf20Sopenharmony_ci mt76x02_add_rate_power_offset(t, -info); 8548c2ecf20Sopenharmony_ci 8558c2ecf20Sopenharmony_ci dev->target_power = info; 8568c2ecf20Sopenharmony_ci mt76x02_phy_set_txpower(dev, info, info); 8578c2ecf20Sopenharmony_ci} 8588c2ecf20Sopenharmony_ci 8598c2ecf20Sopenharmony_civoid mt76x0_phy_calibrate(struct mt76x02_dev *dev, bool power_on) 8608c2ecf20Sopenharmony_ci{ 8618c2ecf20Sopenharmony_ci struct ieee80211_channel *chan = dev->mphy.chandef.chan; 8628c2ecf20Sopenharmony_ci int is_5ghz = (chan->band == NL80211_BAND_5GHZ) ? 1 : 0; 8638c2ecf20Sopenharmony_ci u32 val, tx_alc, reg_val; 8648c2ecf20Sopenharmony_ci 8658c2ecf20Sopenharmony_ci if (is_mt7630(dev)) 8668c2ecf20Sopenharmony_ci return; 8678c2ecf20Sopenharmony_ci 8688c2ecf20Sopenharmony_ci if (power_on) { 8698c2ecf20Sopenharmony_ci mt76x02_mcu_calibrate(dev, MCU_CAL_R, 0); 8708c2ecf20Sopenharmony_ci mt76x02_mcu_calibrate(dev, MCU_CAL_VCO, chan->hw_value); 8718c2ecf20Sopenharmony_ci usleep_range(10, 20); 8728c2ecf20Sopenharmony_ci 8738c2ecf20Sopenharmony_ci if (mt76x0_tssi_enabled(dev)) { 8748c2ecf20Sopenharmony_ci mt76_wr(dev, MT_MAC_SYS_CTRL, 8758c2ecf20Sopenharmony_ci MT_MAC_SYS_CTRL_ENABLE_RX); 8768c2ecf20Sopenharmony_ci mt76x0_phy_tssi_dc_calibrate(dev); 8778c2ecf20Sopenharmony_ci mt76_wr(dev, MT_MAC_SYS_CTRL, 8788c2ecf20Sopenharmony_ci MT_MAC_SYS_CTRL_ENABLE_TX | 8798c2ecf20Sopenharmony_ci MT_MAC_SYS_CTRL_ENABLE_RX); 8808c2ecf20Sopenharmony_ci } 8818c2ecf20Sopenharmony_ci } 8828c2ecf20Sopenharmony_ci 8838c2ecf20Sopenharmony_ci tx_alc = mt76_rr(dev, MT_TX_ALC_CFG_0); 8848c2ecf20Sopenharmony_ci mt76_wr(dev, MT_TX_ALC_CFG_0, 0); 8858c2ecf20Sopenharmony_ci usleep_range(500, 700); 8868c2ecf20Sopenharmony_ci 8878c2ecf20Sopenharmony_ci reg_val = mt76_rr(dev, MT_BBP(IBI, 9)); 8888c2ecf20Sopenharmony_ci mt76_wr(dev, MT_BBP(IBI, 9), 0xffffff7e); 8898c2ecf20Sopenharmony_ci 8908c2ecf20Sopenharmony_ci if (is_5ghz) { 8918c2ecf20Sopenharmony_ci if (chan->hw_value < 100) 8928c2ecf20Sopenharmony_ci val = 0x701; 8938c2ecf20Sopenharmony_ci else if (chan->hw_value < 140) 8948c2ecf20Sopenharmony_ci val = 0x801; 8958c2ecf20Sopenharmony_ci else 8968c2ecf20Sopenharmony_ci val = 0x901; 8978c2ecf20Sopenharmony_ci } else { 8988c2ecf20Sopenharmony_ci val = 0x600; 8998c2ecf20Sopenharmony_ci } 9008c2ecf20Sopenharmony_ci 9018c2ecf20Sopenharmony_ci mt76x02_mcu_calibrate(dev, MCU_CAL_FULL, val); 9028c2ecf20Sopenharmony_ci mt76x02_mcu_calibrate(dev, MCU_CAL_LC, is_5ghz); 9038c2ecf20Sopenharmony_ci usleep_range(15000, 20000); 9048c2ecf20Sopenharmony_ci 9058c2ecf20Sopenharmony_ci mt76_wr(dev, MT_BBP(IBI, 9), reg_val); 9068c2ecf20Sopenharmony_ci mt76_wr(dev, MT_TX_ALC_CFG_0, tx_alc); 9078c2ecf20Sopenharmony_ci mt76x02_mcu_calibrate(dev, MCU_CAL_RXDCOC, 1); 9088c2ecf20Sopenharmony_ci} 9098c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(mt76x0_phy_calibrate); 9108c2ecf20Sopenharmony_ci 9118c2ecf20Sopenharmony_civoid mt76x0_phy_set_channel(struct mt76x02_dev *dev, 9128c2ecf20Sopenharmony_ci struct cfg80211_chan_def *chandef) 9138c2ecf20Sopenharmony_ci{ 9148c2ecf20Sopenharmony_ci u32 ext_cca_chan[4] = { 9158c2ecf20Sopenharmony_ci [0] = FIELD_PREP(MT_EXT_CCA_CFG_CCA0, 0) | 9168c2ecf20Sopenharmony_ci FIELD_PREP(MT_EXT_CCA_CFG_CCA1, 1) | 9178c2ecf20Sopenharmony_ci FIELD_PREP(MT_EXT_CCA_CFG_CCA2, 2) | 9188c2ecf20Sopenharmony_ci FIELD_PREP(MT_EXT_CCA_CFG_CCA3, 3) | 9198c2ecf20Sopenharmony_ci FIELD_PREP(MT_EXT_CCA_CFG_CCA_MASK, BIT(0)), 9208c2ecf20Sopenharmony_ci [1] = FIELD_PREP(MT_EXT_CCA_CFG_CCA0, 1) | 9218c2ecf20Sopenharmony_ci FIELD_PREP(MT_EXT_CCA_CFG_CCA1, 0) | 9228c2ecf20Sopenharmony_ci FIELD_PREP(MT_EXT_CCA_CFG_CCA2, 2) | 9238c2ecf20Sopenharmony_ci FIELD_PREP(MT_EXT_CCA_CFG_CCA3, 3) | 9248c2ecf20Sopenharmony_ci FIELD_PREP(MT_EXT_CCA_CFG_CCA_MASK, BIT(1)), 9258c2ecf20Sopenharmony_ci [2] = FIELD_PREP(MT_EXT_CCA_CFG_CCA0, 2) | 9268c2ecf20Sopenharmony_ci FIELD_PREP(MT_EXT_CCA_CFG_CCA1, 3) | 9278c2ecf20Sopenharmony_ci FIELD_PREP(MT_EXT_CCA_CFG_CCA2, 1) | 9288c2ecf20Sopenharmony_ci FIELD_PREP(MT_EXT_CCA_CFG_CCA3, 0) | 9298c2ecf20Sopenharmony_ci FIELD_PREP(MT_EXT_CCA_CFG_CCA_MASK, BIT(2)), 9308c2ecf20Sopenharmony_ci [3] = FIELD_PREP(MT_EXT_CCA_CFG_CCA0, 3) | 9318c2ecf20Sopenharmony_ci FIELD_PREP(MT_EXT_CCA_CFG_CCA1, 2) | 9328c2ecf20Sopenharmony_ci FIELD_PREP(MT_EXT_CCA_CFG_CCA2, 1) | 9338c2ecf20Sopenharmony_ci FIELD_PREP(MT_EXT_CCA_CFG_CCA3, 0) | 9348c2ecf20Sopenharmony_ci FIELD_PREP(MT_EXT_CCA_CFG_CCA_MASK, BIT(3)), 9358c2ecf20Sopenharmony_ci }; 9368c2ecf20Sopenharmony_ci bool scan = test_bit(MT76_SCANNING, &dev->mphy.state); 9378c2ecf20Sopenharmony_ci int ch_group_index, freq, freq1; 9388c2ecf20Sopenharmony_ci u8 channel; 9398c2ecf20Sopenharmony_ci u32 val; 9408c2ecf20Sopenharmony_ci u16 rf_bw_band; 9418c2ecf20Sopenharmony_ci 9428c2ecf20Sopenharmony_ci freq = chandef->chan->center_freq; 9438c2ecf20Sopenharmony_ci freq1 = chandef->center_freq1; 9448c2ecf20Sopenharmony_ci channel = chandef->chan->hw_value; 9458c2ecf20Sopenharmony_ci rf_bw_band = (channel <= 14) ? RF_G_BAND : RF_A_BAND; 9468c2ecf20Sopenharmony_ci 9478c2ecf20Sopenharmony_ci switch (chandef->width) { 9488c2ecf20Sopenharmony_ci case NL80211_CHAN_WIDTH_40: 9498c2ecf20Sopenharmony_ci if (freq1 > freq) 9508c2ecf20Sopenharmony_ci ch_group_index = 0; 9518c2ecf20Sopenharmony_ci else 9528c2ecf20Sopenharmony_ci ch_group_index = 1; 9538c2ecf20Sopenharmony_ci channel += 2 - ch_group_index * 4; 9548c2ecf20Sopenharmony_ci rf_bw_band |= RF_BW_40; 9558c2ecf20Sopenharmony_ci break; 9568c2ecf20Sopenharmony_ci case NL80211_CHAN_WIDTH_80: 9578c2ecf20Sopenharmony_ci ch_group_index = (freq - freq1 + 30) / 20; 9588c2ecf20Sopenharmony_ci if (WARN_ON(ch_group_index < 0 || ch_group_index > 3)) 9598c2ecf20Sopenharmony_ci ch_group_index = 0; 9608c2ecf20Sopenharmony_ci channel += 6 - ch_group_index * 4; 9618c2ecf20Sopenharmony_ci rf_bw_band |= RF_BW_80; 9628c2ecf20Sopenharmony_ci break; 9638c2ecf20Sopenharmony_ci default: 9648c2ecf20Sopenharmony_ci ch_group_index = 0; 9658c2ecf20Sopenharmony_ci rf_bw_band |= RF_BW_20; 9668c2ecf20Sopenharmony_ci break; 9678c2ecf20Sopenharmony_ci } 9688c2ecf20Sopenharmony_ci 9698c2ecf20Sopenharmony_ci if (mt76_is_usb(&dev->mt76)) { 9708c2ecf20Sopenharmony_ci mt76x0_phy_bbp_set_bw(dev, chandef->width); 9718c2ecf20Sopenharmony_ci } else { 9728c2ecf20Sopenharmony_ci if (chandef->width == NL80211_CHAN_WIDTH_80 || 9738c2ecf20Sopenharmony_ci chandef->width == NL80211_CHAN_WIDTH_40) 9748c2ecf20Sopenharmony_ci val = 0x201; 9758c2ecf20Sopenharmony_ci else 9768c2ecf20Sopenharmony_ci val = 0x601; 9778c2ecf20Sopenharmony_ci mt76_wr(dev, MT_TX_SW_CFG0, val); 9788c2ecf20Sopenharmony_ci } 9798c2ecf20Sopenharmony_ci mt76x02_phy_set_bw(dev, chandef->width, ch_group_index); 9808c2ecf20Sopenharmony_ci mt76x02_phy_set_band(dev, chandef->chan->band, 9818c2ecf20Sopenharmony_ci ch_group_index & 1); 9828c2ecf20Sopenharmony_ci 9838c2ecf20Sopenharmony_ci mt76_rmw(dev, MT_EXT_CCA_CFG, 9848c2ecf20Sopenharmony_ci (MT_EXT_CCA_CFG_CCA0 | 9858c2ecf20Sopenharmony_ci MT_EXT_CCA_CFG_CCA1 | 9868c2ecf20Sopenharmony_ci MT_EXT_CCA_CFG_CCA2 | 9878c2ecf20Sopenharmony_ci MT_EXT_CCA_CFG_CCA3 | 9888c2ecf20Sopenharmony_ci MT_EXT_CCA_CFG_CCA_MASK), 9898c2ecf20Sopenharmony_ci ext_cca_chan[ch_group_index]); 9908c2ecf20Sopenharmony_ci 9918c2ecf20Sopenharmony_ci mt76x0_phy_set_band(dev, chandef->chan->band); 9928c2ecf20Sopenharmony_ci mt76x0_phy_set_chan_rf_params(dev, channel, rf_bw_band); 9938c2ecf20Sopenharmony_ci 9948c2ecf20Sopenharmony_ci /* set Japan Tx filter at channel 14 */ 9958c2ecf20Sopenharmony_ci if (channel == 14) 9968c2ecf20Sopenharmony_ci mt76_set(dev, MT_BBP(CORE, 1), 0x20); 9978c2ecf20Sopenharmony_ci else 9988c2ecf20Sopenharmony_ci mt76_clear(dev, MT_BBP(CORE, 1), 0x20); 9998c2ecf20Sopenharmony_ci 10008c2ecf20Sopenharmony_ci mt76x0_read_rx_gain(dev); 10018c2ecf20Sopenharmony_ci mt76x0_phy_set_chan_bbp_params(dev, rf_bw_band); 10028c2ecf20Sopenharmony_ci 10038c2ecf20Sopenharmony_ci /* enable vco */ 10048c2ecf20Sopenharmony_ci mt76x0_rf_set(dev, MT_RF(0, 4), BIT(7)); 10058c2ecf20Sopenharmony_ci if (scan) 10068c2ecf20Sopenharmony_ci return; 10078c2ecf20Sopenharmony_ci 10088c2ecf20Sopenharmony_ci mt76x02_init_agc_gain(dev); 10098c2ecf20Sopenharmony_ci mt76x0_phy_calibrate(dev, false); 10108c2ecf20Sopenharmony_ci mt76x0_phy_set_txpower(dev); 10118c2ecf20Sopenharmony_ci 10128c2ecf20Sopenharmony_ci ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work, 10138c2ecf20Sopenharmony_ci MT_CALIBRATE_INTERVAL); 10148c2ecf20Sopenharmony_ci} 10158c2ecf20Sopenharmony_ci 10168c2ecf20Sopenharmony_cistatic void mt76x0_phy_temp_sensor(struct mt76x02_dev *dev) 10178c2ecf20Sopenharmony_ci{ 10188c2ecf20Sopenharmony_ci u8 rf_b7_73, rf_b0_66, rf_b0_67; 10198c2ecf20Sopenharmony_ci s8 val; 10208c2ecf20Sopenharmony_ci 10218c2ecf20Sopenharmony_ci rf_b7_73 = mt76x0_rf_rr(dev, MT_RF(7, 73)); 10228c2ecf20Sopenharmony_ci rf_b0_66 = mt76x0_rf_rr(dev, MT_RF(0, 66)); 10238c2ecf20Sopenharmony_ci rf_b0_67 = mt76x0_rf_rr(dev, MT_RF(0, 67)); 10248c2ecf20Sopenharmony_ci 10258c2ecf20Sopenharmony_ci mt76x0_rf_wr(dev, MT_RF(7, 73), 0x02); 10268c2ecf20Sopenharmony_ci mt76x0_rf_wr(dev, MT_RF(0, 66), 0x23); 10278c2ecf20Sopenharmony_ci mt76x0_rf_wr(dev, MT_RF(0, 67), 0x01); 10288c2ecf20Sopenharmony_ci 10298c2ecf20Sopenharmony_ci mt76_wr(dev, MT_BBP(CORE, 34), 0x00080055); 10308c2ecf20Sopenharmony_ci if (!mt76_poll_msec(dev, MT_BBP(CORE, 34), BIT(4), 0, 200)) { 10318c2ecf20Sopenharmony_ci mt76_clear(dev, MT_BBP(CORE, 34), BIT(4)); 10328c2ecf20Sopenharmony_ci goto done; 10338c2ecf20Sopenharmony_ci } 10348c2ecf20Sopenharmony_ci 10358c2ecf20Sopenharmony_ci val = mt76_rr(dev, MT_BBP(CORE, 35)); 10368c2ecf20Sopenharmony_ci val = (35 * (val - dev->cal.rx.temp_offset)) / 10 + 25; 10378c2ecf20Sopenharmony_ci 10388c2ecf20Sopenharmony_ci if (abs(val - dev->cal.temp_vco) > 20) { 10398c2ecf20Sopenharmony_ci mt76x02_mcu_calibrate(dev, MCU_CAL_VCO, 10408c2ecf20Sopenharmony_ci dev->mphy.chandef.chan->hw_value); 10418c2ecf20Sopenharmony_ci dev->cal.temp_vco = val; 10428c2ecf20Sopenharmony_ci } 10438c2ecf20Sopenharmony_ci if (abs(val - dev->cal.temp) > 30) { 10448c2ecf20Sopenharmony_ci mt76x0_phy_calibrate(dev, false); 10458c2ecf20Sopenharmony_ci dev->cal.temp = val; 10468c2ecf20Sopenharmony_ci } 10478c2ecf20Sopenharmony_ci 10488c2ecf20Sopenharmony_cidone: 10498c2ecf20Sopenharmony_ci mt76x0_rf_wr(dev, MT_RF(7, 73), rf_b7_73); 10508c2ecf20Sopenharmony_ci mt76x0_rf_wr(dev, MT_RF(0, 66), rf_b0_66); 10518c2ecf20Sopenharmony_ci mt76x0_rf_wr(dev, MT_RF(0, 67), rf_b0_67); 10528c2ecf20Sopenharmony_ci} 10538c2ecf20Sopenharmony_ci 10548c2ecf20Sopenharmony_cistatic void mt76x0_phy_set_gain_val(struct mt76x02_dev *dev) 10558c2ecf20Sopenharmony_ci{ 10568c2ecf20Sopenharmony_ci u8 gain = dev->cal.agc_gain_cur[0] - dev->cal.agc_gain_adjust; 10578c2ecf20Sopenharmony_ci 10588c2ecf20Sopenharmony_ci mt76_rmw_field(dev, MT_BBP(AGC, 8), MT_BBP_AGC_GAIN, gain); 10598c2ecf20Sopenharmony_ci 10608c2ecf20Sopenharmony_ci if ((dev->mphy.chandef.chan->flags & IEEE80211_CHAN_RADAR) && 10618c2ecf20Sopenharmony_ci !is_mt7630(dev)) 10628c2ecf20Sopenharmony_ci mt76x02_phy_dfs_adjust_agc(dev); 10638c2ecf20Sopenharmony_ci} 10648c2ecf20Sopenharmony_ci 10658c2ecf20Sopenharmony_cistatic void 10668c2ecf20Sopenharmony_cimt76x0_phy_update_channel_gain(struct mt76x02_dev *dev) 10678c2ecf20Sopenharmony_ci{ 10688c2ecf20Sopenharmony_ci bool gain_change; 10698c2ecf20Sopenharmony_ci u8 gain_delta; 10708c2ecf20Sopenharmony_ci int low_gain; 10718c2ecf20Sopenharmony_ci 10728c2ecf20Sopenharmony_ci dev->cal.avg_rssi_all = mt76_get_min_avg_rssi(&dev->mt76, false); 10738c2ecf20Sopenharmony_ci if (!dev->cal.avg_rssi_all) 10748c2ecf20Sopenharmony_ci dev->cal.avg_rssi_all = -75; 10758c2ecf20Sopenharmony_ci 10768c2ecf20Sopenharmony_ci low_gain = (dev->cal.avg_rssi_all > mt76x02_get_rssi_gain_thresh(dev)) + 10778c2ecf20Sopenharmony_ci (dev->cal.avg_rssi_all > mt76x02_get_low_rssi_gain_thresh(dev)); 10788c2ecf20Sopenharmony_ci 10798c2ecf20Sopenharmony_ci gain_change = dev->cal.low_gain < 0 || 10808c2ecf20Sopenharmony_ci (dev->cal.low_gain & 2) ^ (low_gain & 2); 10818c2ecf20Sopenharmony_ci dev->cal.low_gain = low_gain; 10828c2ecf20Sopenharmony_ci 10838c2ecf20Sopenharmony_ci if (!gain_change) { 10848c2ecf20Sopenharmony_ci if (mt76x02_phy_adjust_vga_gain(dev)) 10858c2ecf20Sopenharmony_ci mt76x0_phy_set_gain_val(dev); 10868c2ecf20Sopenharmony_ci return; 10878c2ecf20Sopenharmony_ci } 10888c2ecf20Sopenharmony_ci 10898c2ecf20Sopenharmony_ci dev->cal.agc_gain_adjust = (low_gain == 2) ? 0 : 10; 10908c2ecf20Sopenharmony_ci gain_delta = (low_gain == 2) ? 10 : 0; 10918c2ecf20Sopenharmony_ci 10928c2ecf20Sopenharmony_ci dev->cal.agc_gain_cur[0] = dev->cal.agc_gain_init[0] - gain_delta; 10938c2ecf20Sopenharmony_ci mt76x0_phy_set_gain_val(dev); 10948c2ecf20Sopenharmony_ci 10958c2ecf20Sopenharmony_ci /* clear false CCA counters */ 10968c2ecf20Sopenharmony_ci mt76_rr(dev, MT_RX_STAT_1); 10978c2ecf20Sopenharmony_ci} 10988c2ecf20Sopenharmony_ci 10998c2ecf20Sopenharmony_cistatic void mt76x0_phy_calibration_work(struct work_struct *work) 11008c2ecf20Sopenharmony_ci{ 11018c2ecf20Sopenharmony_ci struct mt76x02_dev *dev = container_of(work, struct mt76x02_dev, 11028c2ecf20Sopenharmony_ci cal_work.work); 11038c2ecf20Sopenharmony_ci 11048c2ecf20Sopenharmony_ci mt76x0_phy_update_channel_gain(dev); 11058c2ecf20Sopenharmony_ci if (mt76x0_tssi_enabled(dev)) 11068c2ecf20Sopenharmony_ci mt76x0_phy_tssi_calibrate(dev); 11078c2ecf20Sopenharmony_ci else 11088c2ecf20Sopenharmony_ci mt76x0_phy_temp_sensor(dev); 11098c2ecf20Sopenharmony_ci 11108c2ecf20Sopenharmony_ci ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work, 11118c2ecf20Sopenharmony_ci 4 * MT_CALIBRATE_INTERVAL); 11128c2ecf20Sopenharmony_ci} 11138c2ecf20Sopenharmony_ci 11148c2ecf20Sopenharmony_cistatic void mt76x0_rf_patch_reg_array(struct mt76x02_dev *dev, 11158c2ecf20Sopenharmony_ci const struct mt76_reg_pair *rp, int len) 11168c2ecf20Sopenharmony_ci{ 11178c2ecf20Sopenharmony_ci int i; 11188c2ecf20Sopenharmony_ci 11198c2ecf20Sopenharmony_ci for (i = 0; i < len; i++) { 11208c2ecf20Sopenharmony_ci u32 reg = rp[i].reg; 11218c2ecf20Sopenharmony_ci u8 val = rp[i].value; 11228c2ecf20Sopenharmony_ci 11238c2ecf20Sopenharmony_ci switch (reg) { 11248c2ecf20Sopenharmony_ci case MT_RF(0, 3): 11258c2ecf20Sopenharmony_ci if (mt76_is_mmio(&dev->mt76)) { 11268c2ecf20Sopenharmony_ci if (is_mt7630(dev)) 11278c2ecf20Sopenharmony_ci val = 0x70; 11288c2ecf20Sopenharmony_ci else 11298c2ecf20Sopenharmony_ci val = 0x63; 11308c2ecf20Sopenharmony_ci } else { 11318c2ecf20Sopenharmony_ci val = 0x73; 11328c2ecf20Sopenharmony_ci } 11338c2ecf20Sopenharmony_ci break; 11348c2ecf20Sopenharmony_ci case MT_RF(0, 21): 11358c2ecf20Sopenharmony_ci if (is_mt7610e(dev)) 11368c2ecf20Sopenharmony_ci val = 0x10; 11378c2ecf20Sopenharmony_ci else 11388c2ecf20Sopenharmony_ci val = 0x12; 11398c2ecf20Sopenharmony_ci break; 11408c2ecf20Sopenharmony_ci case MT_RF(5, 2): 11418c2ecf20Sopenharmony_ci if (is_mt7630(dev)) 11428c2ecf20Sopenharmony_ci val = 0x1d; 11438c2ecf20Sopenharmony_ci else if (is_mt7610e(dev)) 11448c2ecf20Sopenharmony_ci val = 0x00; 11458c2ecf20Sopenharmony_ci else 11468c2ecf20Sopenharmony_ci val = 0x0c; 11478c2ecf20Sopenharmony_ci break; 11488c2ecf20Sopenharmony_ci default: 11498c2ecf20Sopenharmony_ci break; 11508c2ecf20Sopenharmony_ci } 11518c2ecf20Sopenharmony_ci mt76x0_rf_wr(dev, reg, val); 11528c2ecf20Sopenharmony_ci } 11538c2ecf20Sopenharmony_ci} 11548c2ecf20Sopenharmony_ci 11558c2ecf20Sopenharmony_cistatic void mt76x0_phy_rf_init(struct mt76x02_dev *dev) 11568c2ecf20Sopenharmony_ci{ 11578c2ecf20Sopenharmony_ci int i; 11588c2ecf20Sopenharmony_ci 11598c2ecf20Sopenharmony_ci mt76x0_rf_patch_reg_array(dev, mt76x0_rf_central_tab, 11608c2ecf20Sopenharmony_ci ARRAY_SIZE(mt76x0_rf_central_tab)); 11618c2ecf20Sopenharmony_ci mt76x0_rf_patch_reg_array(dev, mt76x0_rf_2g_channel_0_tab, 11628c2ecf20Sopenharmony_ci ARRAY_SIZE(mt76x0_rf_2g_channel_0_tab)); 11638c2ecf20Sopenharmony_ci RF_RANDOM_WRITE(dev, mt76x0_rf_5g_channel_0_tab); 11648c2ecf20Sopenharmony_ci RF_RANDOM_WRITE(dev, mt76x0_rf_vga_channel_0_tab); 11658c2ecf20Sopenharmony_ci 11668c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(mt76x0_rf_bw_switch_tab); i++) { 11678c2ecf20Sopenharmony_ci const struct mt76x0_rf_switch_item *item = &mt76x0_rf_bw_switch_tab[i]; 11688c2ecf20Sopenharmony_ci 11698c2ecf20Sopenharmony_ci if (item->bw_band == RF_BW_20) 11708c2ecf20Sopenharmony_ci mt76x0_rf_wr(dev, item->rf_bank_reg, item->value); 11718c2ecf20Sopenharmony_ci else if (((RF_G_BAND | RF_BW_20) & item->bw_band) == 11728c2ecf20Sopenharmony_ci (RF_G_BAND | RF_BW_20)) 11738c2ecf20Sopenharmony_ci mt76x0_rf_wr(dev, item->rf_bank_reg, item->value); 11748c2ecf20Sopenharmony_ci } 11758c2ecf20Sopenharmony_ci 11768c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(mt76x0_rf_band_switch_tab); i++) { 11778c2ecf20Sopenharmony_ci if (mt76x0_rf_band_switch_tab[i].bw_band & RF_G_BAND) { 11788c2ecf20Sopenharmony_ci mt76x0_rf_wr(dev, 11798c2ecf20Sopenharmony_ci mt76x0_rf_band_switch_tab[i].rf_bank_reg, 11808c2ecf20Sopenharmony_ci mt76x0_rf_band_switch_tab[i].value); 11818c2ecf20Sopenharmony_ci } 11828c2ecf20Sopenharmony_ci } 11838c2ecf20Sopenharmony_ci 11848c2ecf20Sopenharmony_ci /* Frequency calibration 11858c2ecf20Sopenharmony_ci * E1: B0.R22<6:0>: xo_cxo<6:0> 11868c2ecf20Sopenharmony_ci * E2: B0.R21<0>: xo_cxo<0>, B0.R22<7:0>: xo_cxo<8:1> 11878c2ecf20Sopenharmony_ci */ 11888c2ecf20Sopenharmony_ci mt76x0_rf_wr(dev, MT_RF(0, 22), 11898c2ecf20Sopenharmony_ci min_t(u8, dev->cal.rx.freq_offset, 0xbf)); 11908c2ecf20Sopenharmony_ci mt76x0_rf_rr(dev, MT_RF(0, 22)); 11918c2ecf20Sopenharmony_ci 11928c2ecf20Sopenharmony_ci /* Reset procedure DAC during power-up: 11938c2ecf20Sopenharmony_ci * - set B0.R73<7> 11948c2ecf20Sopenharmony_ci * - clear B0.R73<7> 11958c2ecf20Sopenharmony_ci * - set B0.R73<7> 11968c2ecf20Sopenharmony_ci */ 11978c2ecf20Sopenharmony_ci mt76x0_rf_set(dev, MT_RF(0, 73), BIT(7)); 11988c2ecf20Sopenharmony_ci mt76x0_rf_clear(dev, MT_RF(0, 73), BIT(7)); 11998c2ecf20Sopenharmony_ci mt76x0_rf_set(dev, MT_RF(0, 73), BIT(7)); 12008c2ecf20Sopenharmony_ci 12018c2ecf20Sopenharmony_ci /* vcocal_en: initiate VCO calibration (reset after completion)) */ 12028c2ecf20Sopenharmony_ci mt76x0_rf_set(dev, MT_RF(0, 4), 0x80); 12038c2ecf20Sopenharmony_ci} 12048c2ecf20Sopenharmony_ci 12058c2ecf20Sopenharmony_civoid mt76x0_phy_init(struct mt76x02_dev *dev) 12068c2ecf20Sopenharmony_ci{ 12078c2ecf20Sopenharmony_ci INIT_DELAYED_WORK(&dev->cal_work, mt76x0_phy_calibration_work); 12088c2ecf20Sopenharmony_ci 12098c2ecf20Sopenharmony_ci mt76x0_phy_ant_select(dev); 12108c2ecf20Sopenharmony_ci mt76x0_phy_rf_init(dev); 12118c2ecf20Sopenharmony_ci mt76x02_phy_set_rxpath(dev); 12128c2ecf20Sopenharmony_ci mt76x02_phy_set_txdac(dev); 12138c2ecf20Sopenharmony_ci} 1214