xref: /linux/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c (revision 9a87ffc99ec8eb8d35eed7c4f816d75f5cc9662e)
11802d0beSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
210de7a8bSStanislaw Gruszka /*
310de7a8bSStanislaw Gruszka  * (c) Copyright 2002-2010, Ralink Technology, Inc.
410de7a8bSStanislaw Gruszka  * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
510de7a8bSStanislaw Gruszka  * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
610de7a8bSStanislaw Gruszka  * Copyright (C) 2018 Stanislaw Gruszka <stf_xl@wp.pl>
710de7a8bSStanislaw Gruszka  */
810de7a8bSStanislaw Gruszka 
966a34c66SLorenzo Bianconi #include <linux/kernel.h>
1066a34c66SLorenzo Bianconi #include <linux/etherdevice.h>
1166a34c66SLorenzo Bianconi 
1210de7a8bSStanislaw Gruszka #include "mt76x0.h"
1310de7a8bSStanislaw Gruszka #include "mcu.h"
1410de7a8bSStanislaw Gruszka #include "eeprom.h"
1510de7a8bSStanislaw Gruszka #include "phy.h"
1610de7a8bSStanislaw Gruszka #include "initvals.h"
1710de7a8bSStanislaw Gruszka #include "initvals_phy.h"
181f4db1fdSLorenzo Bianconi #include "../mt76x02_phy.h"
1910de7a8bSStanislaw Gruszka 
2010de7a8bSStanislaw Gruszka static int
mt76x0_rf_csr_wr(struct mt76x02_dev * dev,u32 offset,u8 value)21b2d871c0SLorenzo Bianconi mt76x0_rf_csr_wr(struct mt76x02_dev *dev, u32 offset, u8 value)
2210de7a8bSStanislaw Gruszka {
2310de7a8bSStanislaw Gruszka 	int ret = 0;
2410de7a8bSStanislaw Gruszka 	u8 bank, reg;
2510de7a8bSStanislaw Gruszka 
26011849e0SFelix Fietkau 	if (test_bit(MT76_REMOVED, &dev->mphy.state))
2710de7a8bSStanislaw Gruszka 		return -ENODEV;
2810de7a8bSStanislaw Gruszka 
2910de7a8bSStanislaw Gruszka 	bank = MT_RF_BANK(offset);
3010de7a8bSStanislaw Gruszka 	reg = MT_RF_REG(offset);
3110de7a8bSStanislaw Gruszka 
32a14054ceSLorenzo Bianconi 	if (WARN_ON_ONCE(reg > 127) || WARN_ON_ONCE(bank > 8))
3310de7a8bSStanislaw Gruszka 		return -EINVAL;
3410de7a8bSStanislaw Gruszka 
35b2d871c0SLorenzo Bianconi 	mutex_lock(&dev->phy_mutex);
3610de7a8bSStanislaw Gruszka 
3710de7a8bSStanislaw Gruszka 	if (!mt76_poll(dev, MT_RF_CSR_CFG, MT_RF_CSR_CFG_KICK, 0, 100)) {
3810de7a8bSStanislaw Gruszka 		ret = -ETIMEDOUT;
3910de7a8bSStanislaw Gruszka 		goto out;
4010de7a8bSStanislaw Gruszka 	}
4110de7a8bSStanislaw Gruszka 
4210de7a8bSStanislaw Gruszka 	mt76_wr(dev, MT_RF_CSR_CFG,
4310de7a8bSStanislaw Gruszka 		FIELD_PREP(MT_RF_CSR_CFG_DATA, value) |
4410de7a8bSStanislaw Gruszka 		FIELD_PREP(MT_RF_CSR_CFG_REG_BANK, bank) |
4510de7a8bSStanislaw Gruszka 		FIELD_PREP(MT_RF_CSR_CFG_REG_ID, reg) |
4610de7a8bSStanislaw Gruszka 		MT_RF_CSR_CFG_WR |
4710de7a8bSStanislaw Gruszka 		MT_RF_CSR_CFG_KICK);
48e0168dc6SLorenzo Bianconi 
4910de7a8bSStanislaw Gruszka out:
50b2d871c0SLorenzo Bianconi 	mutex_unlock(&dev->phy_mutex);
5110de7a8bSStanislaw Gruszka 
5210de7a8bSStanislaw Gruszka 	if (ret < 0)
5310de7a8bSStanislaw Gruszka 		dev_err(dev->mt76.dev, "Error: RF write %d:%d failed:%d!!\n",
5410de7a8bSStanislaw Gruszka 			bank, reg, ret);
5510de7a8bSStanislaw Gruszka 
5610de7a8bSStanislaw Gruszka 	return ret;
5710de7a8bSStanislaw Gruszka }
5810de7a8bSStanislaw Gruszka 
mt76x0_rf_csr_rr(struct mt76x02_dev * dev,u32 offset)59b2d871c0SLorenzo Bianconi static int mt76x0_rf_csr_rr(struct mt76x02_dev *dev, u32 offset)
6010de7a8bSStanislaw Gruszka {
6110de7a8bSStanislaw Gruszka 	int ret = -ETIMEDOUT;
6210de7a8bSStanislaw Gruszka 	u32 val;
6310de7a8bSStanislaw Gruszka 	u8 bank, reg;
6410de7a8bSStanislaw Gruszka 
65011849e0SFelix Fietkau 	if (test_bit(MT76_REMOVED, &dev->mphy.state))
6610de7a8bSStanislaw Gruszka 		return -ENODEV;
6710de7a8bSStanislaw Gruszka 
6810de7a8bSStanislaw Gruszka 	bank = MT_RF_BANK(offset);
6910de7a8bSStanislaw Gruszka 	reg = MT_RF_REG(offset);
7010de7a8bSStanislaw Gruszka 
71a14054ceSLorenzo Bianconi 	if (WARN_ON_ONCE(reg > 127) || WARN_ON_ONCE(bank > 8))
7210de7a8bSStanislaw Gruszka 		return -EINVAL;
7310de7a8bSStanislaw Gruszka 
74b2d871c0SLorenzo Bianconi 	mutex_lock(&dev->phy_mutex);
7510de7a8bSStanislaw Gruszka 
7610de7a8bSStanislaw Gruszka 	if (!mt76_poll(dev, MT_RF_CSR_CFG, MT_RF_CSR_CFG_KICK, 0, 100))
7710de7a8bSStanislaw Gruszka 		goto out;
7810de7a8bSStanislaw Gruszka 
7910de7a8bSStanislaw Gruszka 	mt76_wr(dev, MT_RF_CSR_CFG,
8010de7a8bSStanislaw Gruszka 		FIELD_PREP(MT_RF_CSR_CFG_REG_BANK, bank) |
8110de7a8bSStanislaw Gruszka 		FIELD_PREP(MT_RF_CSR_CFG_REG_ID, reg) |
8210de7a8bSStanislaw Gruszka 		MT_RF_CSR_CFG_KICK);
8310de7a8bSStanislaw Gruszka 
8410de7a8bSStanislaw Gruszka 	if (!mt76_poll(dev, MT_RF_CSR_CFG, MT_RF_CSR_CFG_KICK, 0, 100))
8510de7a8bSStanislaw Gruszka 		goto out;
8610de7a8bSStanislaw Gruszka 
8710de7a8bSStanislaw Gruszka 	val = mt76_rr(dev, MT_RF_CSR_CFG);
8810de7a8bSStanislaw Gruszka 	if (FIELD_GET(MT_RF_CSR_CFG_REG_ID, val) == reg &&
89e0168dc6SLorenzo Bianconi 	    FIELD_GET(MT_RF_CSR_CFG_REG_BANK, val) == bank)
9010de7a8bSStanislaw Gruszka 		ret = FIELD_GET(MT_RF_CSR_CFG_DATA, val);
91e0168dc6SLorenzo Bianconi 
9210de7a8bSStanislaw Gruszka out:
93b2d871c0SLorenzo Bianconi 	mutex_unlock(&dev->phy_mutex);
9410de7a8bSStanislaw Gruszka 
9510de7a8bSStanislaw Gruszka 	if (ret < 0)
9610de7a8bSStanislaw Gruszka 		dev_err(dev->mt76.dev, "Error: RF read %d:%d failed:%d!!\n",
9710de7a8bSStanislaw Gruszka 			bank, reg, ret);
9810de7a8bSStanislaw Gruszka 
9910de7a8bSStanislaw Gruszka 	return ret;
10010de7a8bSStanislaw Gruszka }
10110de7a8bSStanislaw Gruszka 
10210de7a8bSStanislaw Gruszka static int
mt76x0_rf_wr(struct mt76x02_dev * dev,u32 offset,u8 val)1039c410782SLorenzo Bianconi mt76x0_rf_wr(struct mt76x02_dev *dev, u32 offset, u8 val)
10410de7a8bSStanislaw Gruszka {
10561c51a74SLorenzo Bianconi 	if (mt76_is_usb(&dev->mt76)) {
10610de7a8bSStanislaw Gruszka 		struct mt76_reg_pair pair = {
10710de7a8bSStanislaw Gruszka 			.reg = offset,
10810de7a8bSStanislaw Gruszka 			.value = val,
10910de7a8bSStanislaw Gruszka 		};
11010de7a8bSStanislaw Gruszka 
11169cacac3SStanislaw Gruszka 		WARN_ON_ONCE(!test_bit(MT76_STATE_MCU_RUNNING,
112011849e0SFelix Fietkau 				       &dev->mphy.state));
11317507157SLorenzo Bianconi 		return mt76_wr_rp(dev, MT_MCU_MEMMAP_RF, &pair, 1);
11410de7a8bSStanislaw Gruszka 	} else {
11510de7a8bSStanislaw Gruszka 		return mt76x0_rf_csr_wr(dev, offset, val);
11610de7a8bSStanislaw Gruszka 	}
11710de7a8bSStanislaw Gruszka }
11810de7a8bSStanislaw Gruszka 
mt76x0_rf_rr(struct mt76x02_dev * dev,u32 offset)1199c410782SLorenzo Bianconi static int mt76x0_rf_rr(struct mt76x02_dev *dev, u32 offset)
12010de7a8bSStanislaw Gruszka {
12110de7a8bSStanislaw Gruszka 	int ret;
12210de7a8bSStanislaw Gruszka 	u32 val;
12310de7a8bSStanislaw Gruszka 
12461c51a74SLorenzo Bianconi 	if (mt76_is_usb(&dev->mt76)) {
12510de7a8bSStanislaw Gruszka 		struct mt76_reg_pair pair = {
12610de7a8bSStanislaw Gruszka 			.reg = offset,
12710de7a8bSStanislaw Gruszka 		};
12810de7a8bSStanislaw Gruszka 
12969cacac3SStanislaw Gruszka 		WARN_ON_ONCE(!test_bit(MT76_STATE_MCU_RUNNING,
130011849e0SFelix Fietkau 				       &dev->mphy.state));
13117507157SLorenzo Bianconi 		ret = mt76_rd_rp(dev, MT_MCU_MEMMAP_RF, &pair, 1);
13210de7a8bSStanislaw Gruszka 		val = pair.value;
13310de7a8bSStanislaw Gruszka 	} else {
13410de7a8bSStanislaw Gruszka 		ret = val = mt76x0_rf_csr_rr(dev, offset);
13510de7a8bSStanislaw Gruszka 	}
13610de7a8bSStanislaw Gruszka 
13710de7a8bSStanislaw Gruszka 	return (ret < 0) ? ret : val;
13810de7a8bSStanislaw Gruszka }
13910de7a8bSStanislaw Gruszka 
14010de7a8bSStanislaw Gruszka static int
mt76x0_rf_rmw(struct mt76x02_dev * dev,u32 offset,u8 mask,u8 val)1419c410782SLorenzo Bianconi mt76x0_rf_rmw(struct mt76x02_dev *dev, u32 offset, u8 mask, u8 val)
14210de7a8bSStanislaw Gruszka {
14310de7a8bSStanislaw Gruszka 	int ret;
14410de7a8bSStanislaw Gruszka 
1459c410782SLorenzo Bianconi 	ret = mt76x0_rf_rr(dev, offset);
14610de7a8bSStanislaw Gruszka 	if (ret < 0)
14710de7a8bSStanislaw Gruszka 		return ret;
14810de7a8bSStanislaw Gruszka 
1499c410782SLorenzo Bianconi 	val |= ret & ~mask;
1509c410782SLorenzo Bianconi 
1519c410782SLorenzo Bianconi 	ret = mt76x0_rf_wr(dev, offset, val);
1529c410782SLorenzo Bianconi 	return ret ? ret : val;
15310de7a8bSStanislaw Gruszka }
15410de7a8bSStanislaw Gruszka 
15510de7a8bSStanislaw Gruszka static int
mt76x0_rf_set(struct mt76x02_dev * dev,u32 offset,u8 val)1569c410782SLorenzo Bianconi mt76x0_rf_set(struct mt76x02_dev *dev, u32 offset, u8 val)
15710de7a8bSStanislaw Gruszka {
1589c410782SLorenzo Bianconi 	return mt76x0_rf_rmw(dev, offset, 0, val);
15910de7a8bSStanislaw Gruszka }
16010de7a8bSStanislaw Gruszka 
16110de7a8bSStanislaw Gruszka static int
mt76x0_rf_clear(struct mt76x02_dev * dev,u32 offset,u8 mask)162d3caa060SLorenzo Bianconi mt76x0_rf_clear(struct mt76x02_dev *dev, u32 offset, u8 mask)
16310de7a8bSStanislaw Gruszka {
1649c410782SLorenzo Bianconi 	return mt76x0_rf_rmw(dev, offset, mask, 0);
16510de7a8bSStanislaw Gruszka }
16610de7a8bSStanislaw Gruszka 
167f2761e53SStanislaw Gruszka static void
mt76x0_phy_rf_csr_wr_rp(struct mt76x02_dev * dev,const struct mt76_reg_pair * data,int n)1689c410782SLorenzo Bianconi mt76x0_phy_rf_csr_wr_rp(struct mt76x02_dev *dev,
1699c410782SLorenzo Bianconi 			const struct mt76_reg_pair *data,
170f2761e53SStanislaw Gruszka 			int n)
171f2761e53SStanislaw Gruszka {
172f2761e53SStanislaw Gruszka 	while (n-- > 0) {
173f2761e53SStanislaw Gruszka 		mt76x0_rf_csr_wr(dev, data->reg, data->value);
174f2761e53SStanislaw Gruszka 		data++;
175f2761e53SStanislaw Gruszka 	}
176f2761e53SStanislaw Gruszka }
177f2761e53SStanislaw Gruszka 
178f2761e53SStanislaw Gruszka #define RF_RANDOM_WRITE(dev, tab) do {					\
17961c51a74SLorenzo Bianconi 	if (mt76_is_mmio(&dev->mt76))					\
1809c410782SLorenzo Bianconi 		mt76x0_phy_rf_csr_wr_rp(dev, tab, ARRAY_SIZE(tab));	\
181f2761e53SStanislaw Gruszka 	else								\
182f2761e53SStanislaw Gruszka 		mt76_wr_rp(dev, MT_MCU_MEMMAP_RF, tab, ARRAY_SIZE(tab));\
183f2761e53SStanislaw Gruszka } while (0)
18410de7a8bSStanislaw Gruszka 
mt76x0_phy_wait_bbp_ready(struct mt76x02_dev * dev)1859c410782SLorenzo Bianconi int mt76x0_phy_wait_bbp_ready(struct mt76x02_dev *dev)
18610de7a8bSStanislaw Gruszka {
18710de7a8bSStanislaw Gruszka 	int i = 20;
18810de7a8bSStanislaw Gruszka 	u32 val;
18910de7a8bSStanislaw Gruszka 
19010de7a8bSStanislaw Gruszka 	do {
19110de7a8bSStanislaw Gruszka 		val = mt76_rr(dev, MT_BBP(CORE, 0));
19210de7a8bSStanislaw Gruszka 		if (val && ~val)
19310de7a8bSStanislaw Gruszka 			break;
19410de7a8bSStanislaw Gruszka 	} while (--i);
19510de7a8bSStanislaw Gruszka 
19610de7a8bSStanislaw Gruszka 	if (!i) {
19710de7a8bSStanislaw Gruszka 		dev_err(dev->mt76.dev, "Error: BBP is not ready\n");
19810de7a8bSStanislaw Gruszka 		return -EIO;
19910de7a8bSStanislaw Gruszka 	}
20010de7a8bSStanislaw Gruszka 
201bed25905SStanislaw Gruszka 	dev_dbg(dev->mt76.dev, "BBP version %08x\n", val);
20210de7a8bSStanislaw Gruszka 	return 0;
20310de7a8bSStanislaw Gruszka }
20410de7a8bSStanislaw Gruszka 
20510de7a8bSStanislaw Gruszka static void
mt76x0_phy_set_band(struct mt76x02_dev * dev,enum nl80211_band band)206b2d871c0SLorenzo Bianconi mt76x0_phy_set_band(struct mt76x02_dev *dev, enum nl80211_band band)
20710de7a8bSStanislaw Gruszka {
20810de7a8bSStanislaw Gruszka 	switch (band) {
20910de7a8bSStanislaw Gruszka 	case NL80211_BAND_2GHZ:
21010de7a8bSStanislaw Gruszka 		RF_RANDOM_WRITE(dev, mt76x0_rf_2g_channel_0_tab);
21110de7a8bSStanislaw Gruszka 
2129c410782SLorenzo Bianconi 		mt76x0_rf_wr(dev, MT_RF(5, 0), 0x45);
2139c410782SLorenzo Bianconi 		mt76x0_rf_wr(dev, MT_RF(6, 0), 0x44);
21410de7a8bSStanislaw Gruszka 
21510de7a8bSStanislaw Gruszka 		mt76_wr(dev, MT_TX_ALC_VGA3, 0x00050007);
21610de7a8bSStanislaw Gruszka 		mt76_wr(dev, MT_TX0_RF_GAIN_CORR, 0x003E0002);
21710de7a8bSStanislaw Gruszka 		break;
21810de7a8bSStanislaw Gruszka 	case NL80211_BAND_5GHZ:
21910de7a8bSStanislaw Gruszka 		RF_RANDOM_WRITE(dev, mt76x0_rf_5g_channel_0_tab);
22010de7a8bSStanislaw Gruszka 
2219c410782SLorenzo Bianconi 		mt76x0_rf_wr(dev, MT_RF(5, 0), 0x44);
2229c410782SLorenzo Bianconi 		mt76x0_rf_wr(dev, MT_RF(6, 0), 0x45);
22310de7a8bSStanislaw Gruszka 
22410de7a8bSStanislaw Gruszka 		mt76_wr(dev, MT_TX_ALC_VGA3, 0x00000005);
22510de7a8bSStanislaw Gruszka 		mt76_wr(dev, MT_TX0_RF_GAIN_CORR, 0x01010102);
22610de7a8bSStanislaw Gruszka 		break;
22710de7a8bSStanislaw Gruszka 	default:
22810de7a8bSStanislaw Gruszka 		break;
22910de7a8bSStanislaw Gruszka 	}
23010de7a8bSStanislaw Gruszka }
23110de7a8bSStanislaw Gruszka 
23210de7a8bSStanislaw Gruszka static void
mt76x0_phy_set_chan_rf_params(struct mt76x02_dev * dev,u8 channel,u16 rf_bw_band)233ff97c52aSRyder Lee mt76x0_phy_set_chan_rf_params(struct mt76x02_dev *dev, u8 channel,
234ff97c52aSRyder Lee 			      u16 rf_bw_band)
23510de7a8bSStanislaw Gruszka {
236d3caa060SLorenzo Bianconi 	const struct mt76x0_freq_item *freq_item;
23710de7a8bSStanislaw Gruszka 	u16 rf_band = rf_bw_band & 0xff00;
23810de7a8bSStanislaw Gruszka 	u16 rf_bw = rf_bw_band & 0x00ff;
239443569a5SLorenzo Bianconi 	enum nl80211_band band;
240d3caa060SLorenzo Bianconi 	bool b_sdm = false;
24110de7a8bSStanislaw Gruszka 	u32 mac_reg;
24210de7a8bSStanislaw Gruszka 	int i;
24310de7a8bSStanislaw Gruszka 
24410de7a8bSStanislaw Gruszka 	for (i = 0; i < ARRAY_SIZE(mt76x0_sdm_channel); i++) {
24510de7a8bSStanislaw Gruszka 		if (channel == mt76x0_sdm_channel[i]) {
246d3caa060SLorenzo Bianconi 			b_sdm = true;
24710de7a8bSStanislaw Gruszka 			break;
24810de7a8bSStanislaw Gruszka 		}
24910de7a8bSStanislaw Gruszka 	}
25010de7a8bSStanislaw Gruszka 
25110de7a8bSStanislaw Gruszka 	for (i = 0; i < ARRAY_SIZE(mt76x0_frequency_plan); i++) {
25210de7a8bSStanislaw Gruszka 		if (channel == mt76x0_frequency_plan[i].channel) {
25310de7a8bSStanislaw Gruszka 			rf_band = mt76x0_frequency_plan[i].band;
25410de7a8bSStanislaw Gruszka 
255d3caa060SLorenzo Bianconi 			if (b_sdm)
256ff97c52aSRyder Lee 				freq_item = &mt76x0_sdm_frequency_plan[i];
25710de7a8bSStanislaw Gruszka 			else
258ff97c52aSRyder Lee 				freq_item = &mt76x0_frequency_plan[i];
25910de7a8bSStanislaw Gruszka 
2609c410782SLorenzo Bianconi 			mt76x0_rf_wr(dev, MT_RF(0, 37), freq_item->pllR37);
2619c410782SLorenzo Bianconi 			mt76x0_rf_wr(dev, MT_RF(0, 36), freq_item->pllR36);
2629c410782SLorenzo Bianconi 			mt76x0_rf_wr(dev, MT_RF(0, 35), freq_item->pllR35);
2639c410782SLorenzo Bianconi 			mt76x0_rf_wr(dev, MT_RF(0, 34), freq_item->pllR34);
2649c410782SLorenzo Bianconi 			mt76x0_rf_wr(dev, MT_RF(0, 33), freq_item->pllR33);
26510de7a8bSStanislaw Gruszka 
266d3caa060SLorenzo Bianconi 			mt76x0_rf_rmw(dev, MT_RF(0, 32), 0xe0,
267d3caa060SLorenzo Bianconi 				      freq_item->pllR32_b7b5);
26810de7a8bSStanislaw Gruszka 
26910de7a8bSStanislaw Gruszka 			/* R32<4:0> pll_den: (Denomina - 8) */
270d3caa060SLorenzo Bianconi 			mt76x0_rf_rmw(dev, MT_RF(0, 32), MT_RF_PLL_DEN_MASK,
271d3caa060SLorenzo Bianconi 				      freq_item->pllR32_b4b0);
27210de7a8bSStanislaw Gruszka 
27310de7a8bSStanislaw Gruszka 			/* R31<7:5> */
274d3caa060SLorenzo Bianconi 			mt76x0_rf_rmw(dev, MT_RF(0, 31), 0xe0,
275d3caa060SLorenzo Bianconi 				      freq_item->pllR31_b7b5);
27610de7a8bSStanislaw Gruszka 
27710de7a8bSStanislaw Gruszka 			/* R31<4:0> pll_k(Nominator) */
278d3caa060SLorenzo Bianconi 			mt76x0_rf_rmw(dev, MT_RF(0, 31), MT_RF_PLL_K_MASK,
279d3caa060SLorenzo Bianconi 				      freq_item->pllR31_b4b0);
28010de7a8bSStanislaw Gruszka 
28110de7a8bSStanislaw Gruszka 			/* R30<7> sdm_reset_n */
282d3caa060SLorenzo Bianconi 			if (b_sdm) {
283d3caa060SLorenzo Bianconi 				mt76x0_rf_clear(dev, MT_RF(0, 30),
284d3caa060SLorenzo Bianconi 						MT_RF_SDM_RESET_MASK);
285d3caa060SLorenzo Bianconi 				mt76x0_rf_set(dev, MT_RF(0, 30),
286d3caa060SLorenzo Bianconi 					      MT_RF_SDM_RESET_MASK);
28710de7a8bSStanislaw Gruszka 			} else {
288d3caa060SLorenzo Bianconi 				mt76x0_rf_rmw(dev, MT_RF(0, 30),
289d3caa060SLorenzo Bianconi 					      MT_RF_SDM_RESET_MASK,
290d3caa060SLorenzo Bianconi 					      freq_item->pllR30_b7);
29110de7a8bSStanislaw Gruszka 			}
29210de7a8bSStanislaw Gruszka 
29310de7a8bSStanislaw Gruszka 			/* R30<6:2> sdmmash_prbs,sin */
294d3caa060SLorenzo Bianconi 			mt76x0_rf_rmw(dev, MT_RF(0, 30),
295d3caa060SLorenzo Bianconi 				      MT_RF_SDM_MASH_PRBS_MASK,
296d3caa060SLorenzo Bianconi 				      freq_item->pllR30_b6b2);
29710de7a8bSStanislaw Gruszka 
29810de7a8bSStanislaw Gruszka 			/* R30<1> sdm_bp */
299d3caa060SLorenzo Bianconi 			mt76x0_rf_rmw(dev, MT_RF(0, 30), MT_RF_SDM_BP_MASK,
300d3caa060SLorenzo Bianconi 				      freq_item->pllR30_b1 << 1);
30110de7a8bSStanislaw Gruszka 
30210de7a8bSStanislaw Gruszka 			/* R30<0> R29<7:0> (hex) pll_n */
303d3caa060SLorenzo Bianconi 			mt76x0_rf_wr(dev, MT_RF(0, 29),
304d3caa060SLorenzo Bianconi 				     freq_item->pll_n & 0xff);
30510de7a8bSStanislaw Gruszka 
306d3caa060SLorenzo Bianconi 			mt76x0_rf_rmw(dev, MT_RF(0, 30), 0x1,
307d3caa060SLorenzo Bianconi 				      (freq_item->pll_n >> 8) & 0x1);
30810de7a8bSStanislaw Gruszka 
30910de7a8bSStanislaw Gruszka 			/* R28<7:6> isi_iso */
310d3caa060SLorenzo Bianconi 			mt76x0_rf_rmw(dev, MT_RF(0, 28), MT_RF_ISI_ISO_MASK,
311d3caa060SLorenzo Bianconi 				      freq_item->pllR28_b7b6);
31210de7a8bSStanislaw Gruszka 
31310de7a8bSStanislaw Gruszka 			/* R28<5:4> pfd_dly */
314d3caa060SLorenzo Bianconi 			mt76x0_rf_rmw(dev, MT_RF(0, 28), MT_RF_PFD_DLY_MASK,
315d3caa060SLorenzo Bianconi 				      freq_item->pllR28_b5b4);
31610de7a8bSStanislaw Gruszka 
31710de7a8bSStanislaw Gruszka 			/* R28<3:2> clksel option */
318d3caa060SLorenzo Bianconi 			mt76x0_rf_rmw(dev, MT_RF(0, 28), MT_RF_CLK_SEL_MASK,
319d3caa060SLorenzo Bianconi 				      freq_item->pllR28_b3b2);
32010de7a8bSStanislaw Gruszka 
32110de7a8bSStanislaw Gruszka 			/* R28<1:0> R27<7:0> R26<7:0> (hex) sdm_k */
322d3caa060SLorenzo Bianconi 			mt76x0_rf_wr(dev, MT_RF(0, 26),
323d3caa060SLorenzo Bianconi 				     freq_item->pll_sdm_k & 0xff);
324d3caa060SLorenzo Bianconi 			mt76x0_rf_wr(dev, MT_RF(0, 27),
325d3caa060SLorenzo Bianconi 				     (freq_item->pll_sdm_k >> 8) & 0xff);
32610de7a8bSStanislaw Gruszka 
327d3caa060SLorenzo Bianconi 			mt76x0_rf_rmw(dev, MT_RF(0, 28), 0x3,
328d3caa060SLorenzo Bianconi 				      (freq_item->pll_sdm_k >> 16) & 0x3);
32910de7a8bSStanislaw Gruszka 
33010de7a8bSStanislaw Gruszka 			/* R24<1:0> xo_div */
331d3caa060SLorenzo Bianconi 			mt76x0_rf_rmw(dev, MT_RF(0, 24), MT_RF_XO_DIV_MASK,
332d3caa060SLorenzo Bianconi 				      freq_item->pllR24_b1b0);
33310de7a8bSStanislaw Gruszka 
33410de7a8bSStanislaw Gruszka 			break;
33510de7a8bSStanislaw Gruszka 		}
33610de7a8bSStanislaw Gruszka 	}
33710de7a8bSStanislaw Gruszka 
33810de7a8bSStanislaw Gruszka 	for (i = 0; i < ARRAY_SIZE(mt76x0_rf_bw_switch_tab); i++) {
33910de7a8bSStanislaw Gruszka 		if (rf_bw == mt76x0_rf_bw_switch_tab[i].bw_band) {
3409c410782SLorenzo Bianconi 			mt76x0_rf_wr(dev,
3419c410782SLorenzo Bianconi 				     mt76x0_rf_bw_switch_tab[i].rf_bank_reg,
34210de7a8bSStanislaw Gruszka 				     mt76x0_rf_bw_switch_tab[i].value);
34310de7a8bSStanislaw Gruszka 		} else if ((rf_bw == (mt76x0_rf_bw_switch_tab[i].bw_band & 0xFF)) &&
34410de7a8bSStanislaw Gruszka 			   (rf_band & mt76x0_rf_bw_switch_tab[i].bw_band)) {
3459c410782SLorenzo Bianconi 			mt76x0_rf_wr(dev,
3469c410782SLorenzo Bianconi 				     mt76x0_rf_bw_switch_tab[i].rf_bank_reg,
34710de7a8bSStanislaw Gruszka 				     mt76x0_rf_bw_switch_tab[i].value);
34810de7a8bSStanislaw Gruszka 		}
34910de7a8bSStanislaw Gruszka 	}
35010de7a8bSStanislaw Gruszka 
35110de7a8bSStanislaw Gruszka 	for (i = 0; i < ARRAY_SIZE(mt76x0_rf_band_switch_tab); i++) {
35210de7a8bSStanislaw Gruszka 		if (mt76x0_rf_band_switch_tab[i].bw_band & rf_band) {
3539c410782SLorenzo Bianconi 			mt76x0_rf_wr(dev,
3549c410782SLorenzo Bianconi 				     mt76x0_rf_band_switch_tab[i].rf_bank_reg,
35510de7a8bSStanislaw Gruszka 				     mt76x0_rf_band_switch_tab[i].value);
35610de7a8bSStanislaw Gruszka 		}
35710de7a8bSStanislaw Gruszka 	}
35810de7a8bSStanislaw Gruszka 
359d3caa060SLorenzo Bianconi 	mt76_clear(dev, MT_RF_MISC, 0xc);
36010de7a8bSStanislaw Gruszka 
361443569a5SLorenzo Bianconi 	band = (rf_band & RF_G_BAND) ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ;
36226a9daa6SLorenzo Bianconi 	if (mt76x02_ext_pa_enabled(dev, band)) {
363ff97c52aSRyder Lee 		/* MT_RF_MISC (offset: 0x0518)
364ff97c52aSRyder Lee 		 * [2]1'b1: enable external A band PA
365ff97c52aSRyder Lee 		 *    1'b0: disable external A band PA
366ff97c52aSRyder Lee 		 * [3]1'b1: enable external G band PA
367ff97c52aSRyder Lee 		 *    1'b0: disable external G band PA
36810de7a8bSStanislaw Gruszka 		 */
369d3caa060SLorenzo Bianconi 		if (rf_band & RF_A_BAND)
370d3caa060SLorenzo Bianconi 			mt76_set(dev, MT_RF_MISC, BIT(2));
371d3caa060SLorenzo Bianconi 		else
372d3caa060SLorenzo Bianconi 			mt76_set(dev, MT_RF_MISC, BIT(3));
37310de7a8bSStanislaw Gruszka 
37410de7a8bSStanislaw Gruszka 		/* External PA */
37510de7a8bSStanislaw Gruszka 		for (i = 0; i < ARRAY_SIZE(mt76x0_rf_ext_pa_tab); i++)
37610de7a8bSStanislaw Gruszka 			if (mt76x0_rf_ext_pa_tab[i].bw_band & rf_band)
3779c410782SLorenzo Bianconi 				mt76x0_rf_wr(dev,
3789c410782SLorenzo Bianconi 					mt76x0_rf_ext_pa_tab[i].rf_bank_reg,
37910de7a8bSStanislaw Gruszka 					mt76x0_rf_ext_pa_tab[i].value);
38010de7a8bSStanislaw Gruszka 	}
38110de7a8bSStanislaw Gruszka 
38210de7a8bSStanislaw Gruszka 	if (rf_band & RF_G_BAND) {
38310de7a8bSStanislaw Gruszka 		mt76_wr(dev, MT_TX0_RF_GAIN_ATTEN, 0x63707400);
38410de7a8bSStanislaw Gruszka 		/* Set Atten mode = 2 For G band, Disable Tx Inc dcoc. */
38510de7a8bSStanislaw Gruszka 		mac_reg = mt76_rr(dev, MT_TX_ALC_CFG_1);
38610de7a8bSStanislaw Gruszka 		mac_reg &= 0x896400FF;
38710de7a8bSStanislaw Gruszka 		mt76_wr(dev, MT_TX_ALC_CFG_1, mac_reg);
38810de7a8bSStanislaw Gruszka 	} else {
38910de7a8bSStanislaw Gruszka 		mt76_wr(dev, MT_TX0_RF_GAIN_ATTEN, 0x686A7800);
390ff97c52aSRyder Lee 		/* Set Atten mode = 0
391ff97c52aSRyder Lee 		 * For Ext A band, Disable Tx Inc dcoc Cal.
392ff97c52aSRyder Lee 		 */
39310de7a8bSStanislaw Gruszka 		mac_reg = mt76_rr(dev, MT_TX_ALC_CFG_1);
39410de7a8bSStanislaw Gruszka 		mac_reg &= 0x890400FF;
39510de7a8bSStanislaw Gruszka 		mt76_wr(dev, MT_TX_ALC_CFG_1, mac_reg);
39610de7a8bSStanislaw Gruszka 	}
39710de7a8bSStanislaw Gruszka }
39810de7a8bSStanislaw Gruszka 
39910de7a8bSStanislaw Gruszka static void
mt76x0_phy_set_chan_bbp_params(struct mt76x02_dev * dev,u16 rf_bw_band)4007859c543SLorenzo Bianconi mt76x0_phy_set_chan_bbp_params(struct mt76x02_dev *dev, u16 rf_bw_band)
40110de7a8bSStanislaw Gruszka {
40210de7a8bSStanislaw Gruszka 	int i;
40310de7a8bSStanislaw Gruszka 
40410de7a8bSStanislaw Gruszka 	for (i = 0; i < ARRAY_SIZE(mt76x0_bbp_switch_tab); i++) {
40510de7a8bSStanislaw Gruszka 		const struct mt76x0_bbp_switch_item *item = &mt76x0_bbp_switch_tab[i];
40610de7a8bSStanislaw Gruszka 		const struct mt76_reg_pair *pair = &item->reg_pair;
40710de7a8bSStanislaw Gruszka 
40810de7a8bSStanislaw Gruszka 		if ((rf_bw_band & item->bw_band) != rf_bw_band)
40910de7a8bSStanislaw Gruszka 			continue;
41010de7a8bSStanislaw Gruszka 
41110de7a8bSStanislaw Gruszka 		if (pair->reg == MT_BBP(AGC, 8)) {
41210de7a8bSStanislaw Gruszka 			u32 val = pair->value;
4132daa6758SLorenzo Bianconi 			u8 gain;
41410de7a8bSStanislaw Gruszka 
4152daa6758SLorenzo Bianconi 			gain = FIELD_GET(MT_BBP_AGC_GAIN, val);
416b2d871c0SLorenzo Bianconi 			gain -= dev->cal.rx.lna_gain * 2;
41710de7a8bSStanislaw Gruszka 			val &= ~MT_BBP_AGC_GAIN;
41810de7a8bSStanislaw Gruszka 			val |= FIELD_PREP(MT_BBP_AGC_GAIN, gain);
41910de7a8bSStanislaw Gruszka 			mt76_wr(dev, pair->reg, val);
42010de7a8bSStanislaw Gruszka 		} else {
42110de7a8bSStanislaw Gruszka 			mt76_wr(dev, pair->reg, pair->value);
42210de7a8bSStanislaw Gruszka 		}
42310de7a8bSStanislaw Gruszka 	}
42410de7a8bSStanislaw Gruszka }
42510de7a8bSStanislaw Gruszka 
mt76x0_phy_ant_select(struct mt76x02_dev * dev)4269c410782SLorenzo Bianconi static void mt76x0_phy_ant_select(struct mt76x02_dev *dev)
4274468e92cSLorenzo Bianconi {
428ef442b73SStanislaw Gruszka 	u16 ee_ant = mt76x02_eeprom_get(dev, MT_EE_ANTENNA);
42910ece008SFelix Fietkau 	u16 ee_cfg1 = mt76x02_eeprom_get(dev, MT_EE_CFG1_INIT);
430ef442b73SStanislaw Gruszka 	u16 nic_conf2 = mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_2);
43110ece008SFelix Fietkau 	u32 wlan, coex3;
432ef442b73SStanislaw Gruszka 	bool ant_div;
4334468e92cSLorenzo Bianconi 
434ef442b73SStanislaw Gruszka 	wlan = mt76_rr(dev, MT_WLAN_FUN_CTRL);
435ef442b73SStanislaw Gruszka 	coex3 = mt76_rr(dev, MT_COEXCFG3);
436ef442b73SStanislaw Gruszka 
43710ece008SFelix Fietkau 	ee_ant &= ~(BIT(14) | BIT(12));
438ef442b73SStanislaw Gruszka 	wlan  &= ~(BIT(6) | BIT(5));
439ef442b73SStanislaw Gruszka 	coex3 &= ~GENMASK(5, 2);
440ef442b73SStanislaw Gruszka 
441ef442b73SStanislaw Gruszka 	if (ee_ant & MT_EE_ANTENNA_DUAL) {
442ef442b73SStanislaw Gruszka 		/* dual antenna mode */
443ef442b73SStanislaw Gruszka 		ant_div = !(nic_conf2 & MT_EE_NIC_CONF_2_ANT_OPT) &&
444ef442b73SStanislaw Gruszka 			  (nic_conf2 & MT_EE_NIC_CONF_2_ANT_DIV);
445ef442b73SStanislaw Gruszka 		if (ant_div)
44610ece008SFelix Fietkau 			ee_ant |= BIT(12);
447ef442b73SStanislaw Gruszka 		else
448ef442b73SStanislaw Gruszka 			coex3 |= BIT(4);
449ef442b73SStanislaw Gruszka 		coex3 |= BIT(3);
45048dbce5cSLorenzo Bianconi 		if (dev->mphy.cap.has_2ghz)
451ef442b73SStanislaw Gruszka 			wlan |= BIT(6);
4524468e92cSLorenzo Bianconi 	} else {
453ef442b73SStanislaw Gruszka 		/* sigle antenna mode */
45448dbce5cSLorenzo Bianconi 		if (dev->mphy.cap.has_5ghz) {
455ef442b73SStanislaw Gruszka 			coex3 |= BIT(3) | BIT(4);
456ef442b73SStanislaw Gruszka 		} else {
457ef442b73SStanislaw Gruszka 			wlan |= BIT(6);
458ef442b73SStanislaw Gruszka 			coex3 |= BIT(1);
4594468e92cSLorenzo Bianconi 		}
460ef442b73SStanislaw Gruszka 	}
461ef442b73SStanislaw Gruszka 
462ef442b73SStanislaw Gruszka 	if (is_mt7630(dev))
46310ece008SFelix Fietkau 		ee_ant |= BIT(14) | BIT(11);
464ef442b73SStanislaw Gruszka 
465ef442b73SStanislaw Gruszka 	mt76_wr(dev, MT_WLAN_FUN_CTRL, wlan);
46610ece008SFelix Fietkau 	mt76_rmw(dev, MT_CMB_CTRL, GENMASK(15, 0), ee_ant);
46710ece008SFelix Fietkau 	mt76_rmw(dev, MT_CSR_EE_CFG1, GENMASK(15, 0), ee_cfg1);
4684468e92cSLorenzo Bianconi 	mt76_clear(dev, MT_COEXCFG0, BIT(2));
469ef442b73SStanislaw Gruszka 	mt76_wr(dev, MT_COEXCFG3, coex3);
4704468e92cSLorenzo Bianconi }
4714468e92cSLorenzo Bianconi 
47210de7a8bSStanislaw Gruszka static void
mt76x0_phy_bbp_set_bw(struct mt76x02_dev * dev,enum nl80211_chan_width width)4739c410782SLorenzo Bianconi mt76x0_phy_bbp_set_bw(struct mt76x02_dev *dev, enum nl80211_chan_width width)
47410de7a8bSStanislaw Gruszka {
47510de7a8bSStanislaw Gruszka 	enum { BW_20 = 0, BW_40 = 1, BW_80 = 2, BW_10 = 4};
47610de7a8bSStanislaw Gruszka 	int bw;
47710de7a8bSStanislaw Gruszka 
47810de7a8bSStanislaw Gruszka 	switch (width) {
47910de7a8bSStanislaw Gruszka 	default:
48010de7a8bSStanislaw Gruszka 	case NL80211_CHAN_WIDTH_20_NOHT:
48110de7a8bSStanislaw Gruszka 	case NL80211_CHAN_WIDTH_20:
48210de7a8bSStanislaw Gruszka 		bw = BW_20;
48310de7a8bSStanislaw Gruszka 		break;
48410de7a8bSStanislaw Gruszka 	case NL80211_CHAN_WIDTH_40:
48510de7a8bSStanislaw Gruszka 		bw = BW_40;
48610de7a8bSStanislaw Gruszka 		break;
48710de7a8bSStanislaw Gruszka 	case NL80211_CHAN_WIDTH_80:
48810de7a8bSStanislaw Gruszka 		bw = BW_80;
48910de7a8bSStanislaw Gruszka 		break;
49010de7a8bSStanislaw Gruszka 	case NL80211_CHAN_WIDTH_10:
49110de7a8bSStanislaw Gruszka 		bw = BW_10;
49210de7a8bSStanislaw Gruszka 		break;
49310de7a8bSStanislaw Gruszka 	case NL80211_CHAN_WIDTH_80P80:
49410de7a8bSStanislaw Gruszka 	case NL80211_CHAN_WIDTH_160:
49510de7a8bSStanislaw Gruszka 	case NL80211_CHAN_WIDTH_5:
49610de7a8bSStanislaw Gruszka 		/* TODO error */
49710de7a8bSStanislaw Gruszka 		return;
49810de7a8bSStanislaw Gruszka 	}
49910de7a8bSStanislaw Gruszka 
5003d2d61b5SStanislaw Gruszka 	mt76x02_mcu_function_select(dev, BW_SETTING, bw);
50110de7a8bSStanislaw Gruszka }
50210de7a8bSStanislaw Gruszka 
mt76x0_phy_tssi_dc_calibrate(struct mt76x02_dev * dev)5033548a9ddSLorenzo Bianconi static void mt76x0_phy_tssi_dc_calibrate(struct mt76x02_dev *dev)
5043548a9ddSLorenzo Bianconi {
50596747a51SFelix Fietkau 	struct ieee80211_channel *chan = dev->mphy.chandef.chan;
5063548a9ddSLorenzo Bianconi 	u32 val;
5073548a9ddSLorenzo Bianconi 
5083548a9ddSLorenzo Bianconi 	if (chan->band == NL80211_BAND_5GHZ)
5093548a9ddSLorenzo Bianconi 		mt76x0_rf_clear(dev, MT_RF(0, 67), 0xf);
5103548a9ddSLorenzo Bianconi 
5113548a9ddSLorenzo Bianconi 	/* bypass ADDA control */
5123548a9ddSLorenzo Bianconi 	mt76_wr(dev, MT_RF_SETTING_0, 0x60002237);
5133548a9ddSLorenzo Bianconi 	mt76_wr(dev, MT_RF_BYPASS_0, 0xffffffff);
5143548a9ddSLorenzo Bianconi 
5153548a9ddSLorenzo Bianconi 	/* bbp sw reset */
5163548a9ddSLorenzo Bianconi 	mt76_set(dev, MT_BBP(CORE, 4), BIT(0));
5173548a9ddSLorenzo Bianconi 	usleep_range(500, 1000);
5183548a9ddSLorenzo Bianconi 	mt76_clear(dev, MT_BBP(CORE, 4), BIT(0));
5193548a9ddSLorenzo Bianconi 
5203548a9ddSLorenzo Bianconi 	val = (chan->band == NL80211_BAND_5GHZ) ? 0x80055 : 0x80050;
5213548a9ddSLorenzo Bianconi 	mt76_wr(dev, MT_BBP(CORE, 34), val);
5223548a9ddSLorenzo Bianconi 
5233548a9ddSLorenzo Bianconi 	/* enable TX with DAC0 input */
5243548a9ddSLorenzo Bianconi 	mt76_wr(dev, MT_BBP(TXBE, 6), BIT(31));
5253548a9ddSLorenzo Bianconi 
5263548a9ddSLorenzo Bianconi 	mt76_poll_msec(dev, MT_BBP(CORE, 34), BIT(4), 0, 200);
5273548a9ddSLorenzo Bianconi 	dev->cal.tssi_dc = mt76_rr(dev, MT_BBP(CORE, 35)) & 0xff;
5283548a9ddSLorenzo Bianconi 
5293548a9ddSLorenzo Bianconi 	/* stop bypass ADDA */
5303548a9ddSLorenzo Bianconi 	mt76_wr(dev, MT_RF_BYPASS_0, 0);
5313548a9ddSLorenzo Bianconi 	/* stop TX */
5323548a9ddSLorenzo Bianconi 	mt76_wr(dev, MT_BBP(TXBE, 6), 0);
5333548a9ddSLorenzo Bianconi 	/* bbp sw reset */
5343548a9ddSLorenzo Bianconi 	mt76_set(dev, MT_BBP(CORE, 4), BIT(0));
5353548a9ddSLorenzo Bianconi 	usleep_range(500, 1000);
5363548a9ddSLorenzo Bianconi 	mt76_clear(dev, MT_BBP(CORE, 4), BIT(0));
5373548a9ddSLorenzo Bianconi 
5383548a9ddSLorenzo Bianconi 	if (chan->band == NL80211_BAND_5GHZ)
5393548a9ddSLorenzo Bianconi 		mt76x0_rf_rmw(dev, MT_RF(0, 67), 0xf, 0x4);
5403548a9ddSLorenzo Bianconi }
5413548a9ddSLorenzo Bianconi 
5423548a9ddSLorenzo Bianconi static int
mt76x0_phy_tssi_adc_calibrate(struct mt76x02_dev * dev,s16 * ltssi,u8 * info)5433548a9ddSLorenzo Bianconi mt76x0_phy_tssi_adc_calibrate(struct mt76x02_dev *dev, s16 *ltssi,
5443548a9ddSLorenzo Bianconi 			      u8 *info)
5453548a9ddSLorenzo Bianconi {
54696747a51SFelix Fietkau 	struct ieee80211_channel *chan = dev->mphy.chandef.chan;
5473548a9ddSLorenzo Bianconi 	u32 val;
5483548a9ddSLorenzo Bianconi 
5493548a9ddSLorenzo Bianconi 	val = (chan->band == NL80211_BAND_5GHZ) ? 0x80055 : 0x80050;
5503548a9ddSLorenzo Bianconi 	mt76_wr(dev, MT_BBP(CORE, 34), val);
5513548a9ddSLorenzo Bianconi 
5523548a9ddSLorenzo Bianconi 	if (!mt76_poll_msec(dev, MT_BBP(CORE, 34), BIT(4), 0, 200)) {
5533548a9ddSLorenzo Bianconi 		mt76_clear(dev, MT_BBP(CORE, 34), BIT(4));
5543548a9ddSLorenzo Bianconi 		return -ETIMEDOUT;
5553548a9ddSLorenzo Bianconi 	}
5563548a9ddSLorenzo Bianconi 
5573548a9ddSLorenzo Bianconi 	*ltssi = mt76_rr(dev, MT_BBP(CORE, 35)) & 0xff;
5583548a9ddSLorenzo Bianconi 	if (chan->band == NL80211_BAND_5GHZ)
5593548a9ddSLorenzo Bianconi 		*ltssi += 128;
5603548a9ddSLorenzo Bianconi 
5613548a9ddSLorenzo Bianconi 	/* set packet info#1 mode */
5623548a9ddSLorenzo Bianconi 	mt76_wr(dev, MT_BBP(CORE, 34), 0x80041);
5633548a9ddSLorenzo Bianconi 	info[0] = mt76_rr(dev, MT_BBP(CORE, 35)) & 0xff;
5643548a9ddSLorenzo Bianconi 
5653548a9ddSLorenzo Bianconi 	/* set packet info#2 mode */
5663548a9ddSLorenzo Bianconi 	mt76_wr(dev, MT_BBP(CORE, 34), 0x80042);
5673548a9ddSLorenzo Bianconi 	info[1] = mt76_rr(dev, MT_BBP(CORE, 35)) & 0xff;
5683548a9ddSLorenzo Bianconi 
5693548a9ddSLorenzo Bianconi 	/* set packet info#3 mode */
5703548a9ddSLorenzo Bianconi 	mt76_wr(dev, MT_BBP(CORE, 34), 0x80043);
5713548a9ddSLorenzo Bianconi 	info[2] = mt76_rr(dev, MT_BBP(CORE, 35)) & 0xff;
5723548a9ddSLorenzo Bianconi 
5733548a9ddSLorenzo Bianconi 	return 0;
5743548a9ddSLorenzo Bianconi }
5753548a9ddSLorenzo Bianconi 
mt76x0_phy_get_rf_pa_mode(struct mt76x02_dev * dev,int index,u8 tx_rate)5763548a9ddSLorenzo Bianconi static u8 mt76x0_phy_get_rf_pa_mode(struct mt76x02_dev *dev,
5773548a9ddSLorenzo Bianconi 				    int index, u8 tx_rate)
5783548a9ddSLorenzo Bianconi {
5793548a9ddSLorenzo Bianconi 	u32 val, reg;
5803548a9ddSLorenzo Bianconi 
5813548a9ddSLorenzo Bianconi 	reg = (index == 1) ? MT_RF_PA_MODE_CFG1 : MT_RF_PA_MODE_CFG0;
5823548a9ddSLorenzo Bianconi 	val = mt76_rr(dev, reg);
5833548a9ddSLorenzo Bianconi 	return (val & (3 << (tx_rate * 2))) >> (tx_rate * 2);
5843548a9ddSLorenzo Bianconi }
5853548a9ddSLorenzo Bianconi 
5863548a9ddSLorenzo Bianconi static int
mt76x0_phy_get_target_power(struct mt76x02_dev * dev,u8 tx_mode,u8 * info,s8 * target_power,s8 * target_pa_power)5873548a9ddSLorenzo Bianconi mt76x0_phy_get_target_power(struct mt76x02_dev *dev, u8 tx_mode,
5883548a9ddSLorenzo Bianconi 			    u8 *info, s8 *target_power,
5893548a9ddSLorenzo Bianconi 			    s8 *target_pa_power)
5903548a9ddSLorenzo Bianconi {
5913548a9ddSLorenzo Bianconi 	u8 tx_rate, cur_power;
5923548a9ddSLorenzo Bianconi 
5933548a9ddSLorenzo Bianconi 	cur_power = mt76_rr(dev, MT_TX_ALC_CFG_0) & MT_TX_ALC_CFG_0_CH_INIT_0;
5943548a9ddSLorenzo Bianconi 	switch (tx_mode) {
5953548a9ddSLorenzo Bianconi 	case 0:
5963548a9ddSLorenzo Bianconi 		/* cck rates */
5973548a9ddSLorenzo Bianconi 		tx_rate = (info[0] & 0x60) >> 5;
598b376d963SFelix Fietkau 		*target_power = cur_power + dev->rate_power.cck[tx_rate];
5993548a9ddSLorenzo Bianconi 		*target_pa_power = mt76x0_phy_get_rf_pa_mode(dev, 0, tx_rate);
6003548a9ddSLorenzo Bianconi 		break;
6013548a9ddSLorenzo Bianconi 	case 1: {
6023548a9ddSLorenzo Bianconi 		u8 index;
6033548a9ddSLorenzo Bianconi 
6043548a9ddSLorenzo Bianconi 		/* ofdm rates */
6053548a9ddSLorenzo Bianconi 		tx_rate = (info[0] & 0xf0) >> 4;
6063548a9ddSLorenzo Bianconi 		switch (tx_rate) {
6073548a9ddSLorenzo Bianconi 		case 0xb:
6083548a9ddSLorenzo Bianconi 			index = 0;
6093548a9ddSLorenzo Bianconi 			break;
6103548a9ddSLorenzo Bianconi 		case 0xf:
6113548a9ddSLorenzo Bianconi 			index = 1;
6123548a9ddSLorenzo Bianconi 			break;
6133548a9ddSLorenzo Bianconi 		case 0xa:
6143548a9ddSLorenzo Bianconi 			index = 2;
6153548a9ddSLorenzo Bianconi 			break;
6163548a9ddSLorenzo Bianconi 		case 0xe:
6173548a9ddSLorenzo Bianconi 			index = 3;
6183548a9ddSLorenzo Bianconi 			break;
6193548a9ddSLorenzo Bianconi 		case 0x9:
6203548a9ddSLorenzo Bianconi 			index = 4;
6213548a9ddSLorenzo Bianconi 			break;
6223548a9ddSLorenzo Bianconi 		case 0xd:
6233548a9ddSLorenzo Bianconi 			index = 5;
6243548a9ddSLorenzo Bianconi 			break;
6253548a9ddSLorenzo Bianconi 		case 0x8:
6263548a9ddSLorenzo Bianconi 			index = 6;
6273548a9ddSLorenzo Bianconi 			break;
6283548a9ddSLorenzo Bianconi 		case 0xc:
6293548a9ddSLorenzo Bianconi 			index = 7;
6303548a9ddSLorenzo Bianconi 			break;
6313548a9ddSLorenzo Bianconi 		default:
6323548a9ddSLorenzo Bianconi 			return -EINVAL;
6333548a9ddSLorenzo Bianconi 		}
6343548a9ddSLorenzo Bianconi 
635b376d963SFelix Fietkau 		*target_power = cur_power + dev->rate_power.ofdm[index];
6363548a9ddSLorenzo Bianconi 		*target_pa_power = mt76x0_phy_get_rf_pa_mode(dev, 0, index + 4);
6373548a9ddSLorenzo Bianconi 		break;
6383548a9ddSLorenzo Bianconi 	}
6393548a9ddSLorenzo Bianconi 	case 4:
6403548a9ddSLorenzo Bianconi 		/* vht rates */
6413548a9ddSLorenzo Bianconi 		tx_rate = info[1] & 0xf;
6423548a9ddSLorenzo Bianconi 		if (tx_rate > 9)
6433548a9ddSLorenzo Bianconi 			return -EINVAL;
6443548a9ddSLorenzo Bianconi 
645*6e1abc51SLorenzo Bianconi 		*target_power = cur_power;
646*6e1abc51SLorenzo Bianconi 		if (tx_rate > 7)
647*6e1abc51SLorenzo Bianconi 			*target_power += dev->rate_power.vht[tx_rate - 8];
648*6e1abc51SLorenzo Bianconi 		else
649*6e1abc51SLorenzo Bianconi 			*target_power += dev->rate_power.ht[tx_rate];
650*6e1abc51SLorenzo Bianconi 
6513548a9ddSLorenzo Bianconi 		*target_pa_power = mt76x0_phy_get_rf_pa_mode(dev, 1, tx_rate);
6523548a9ddSLorenzo Bianconi 		break;
6533548a9ddSLorenzo Bianconi 	default:
6543548a9ddSLorenzo Bianconi 		/* ht rates */
6553548a9ddSLorenzo Bianconi 		tx_rate = info[1] & 0x7f;
6563548a9ddSLorenzo Bianconi 		if (tx_rate > 9)
6573548a9ddSLorenzo Bianconi 			return -EINVAL;
6583548a9ddSLorenzo Bianconi 
659b376d963SFelix Fietkau 		*target_power = cur_power + dev->rate_power.ht[tx_rate];
6603548a9ddSLorenzo Bianconi 		*target_pa_power = mt76x0_phy_get_rf_pa_mode(dev, 1, tx_rate);
6613548a9ddSLorenzo Bianconi 		break;
6623548a9ddSLorenzo Bianconi 	}
6633548a9ddSLorenzo Bianconi 
6643548a9ddSLorenzo Bianconi 	return 0;
6653548a9ddSLorenzo Bianconi }
6663548a9ddSLorenzo Bianconi 
mt76x0_phy_lin2db(u16 val)6673548a9ddSLorenzo Bianconi static s16 mt76x0_phy_lin2db(u16 val)
6683548a9ddSLorenzo Bianconi {
6693548a9ddSLorenzo Bianconi 	u32 mantissa = val << 4;
6703548a9ddSLorenzo Bianconi 	int ret, data;
6713548a9ddSLorenzo Bianconi 	s16 exp = -4;
6723548a9ddSLorenzo Bianconi 
6733548a9ddSLorenzo Bianconi 	while (mantissa < BIT(15)) {
6743548a9ddSLorenzo Bianconi 		mantissa <<= 1;
6753548a9ddSLorenzo Bianconi 		if (--exp < -20)
6763548a9ddSLorenzo Bianconi 			return -10000;
6773548a9ddSLorenzo Bianconi 	}
6783548a9ddSLorenzo Bianconi 	while (mantissa > 0xffff) {
6793548a9ddSLorenzo Bianconi 		mantissa >>= 1;
6803548a9ddSLorenzo Bianconi 		if (++exp > 20)
6813548a9ddSLorenzo Bianconi 			return -10000;
6823548a9ddSLorenzo Bianconi 	}
6833548a9ddSLorenzo Bianconi 
6843548a9ddSLorenzo Bianconi 	/* s(15,0) */
6853548a9ddSLorenzo Bianconi 	if (mantissa <= 47104)
6863548a9ddSLorenzo Bianconi 		data = mantissa + (mantissa >> 3) + (mantissa >> 4) - 38400;
6873548a9ddSLorenzo Bianconi 	else
6883548a9ddSLorenzo Bianconi 		data = mantissa - (mantissa >> 3) - (mantissa >> 6) - 23040;
6893548a9ddSLorenzo Bianconi 	data = max_t(int, 0, data);
6903548a9ddSLorenzo Bianconi 
6913548a9ddSLorenzo Bianconi 	ret = ((15 + exp) << 15) + data;
6923548a9ddSLorenzo Bianconi 	ret = (ret << 2) + (ret << 1) + (ret >> 6) + (ret >> 7);
6933548a9ddSLorenzo Bianconi 	return ret >> 10;
6943548a9ddSLorenzo Bianconi }
6953548a9ddSLorenzo Bianconi 
6963548a9ddSLorenzo Bianconi static int
mt76x0_phy_get_delta_power(struct mt76x02_dev * dev,u8 tx_mode,s8 target_power,s8 target_pa_power,s16 ltssi)6973548a9ddSLorenzo Bianconi mt76x0_phy_get_delta_power(struct mt76x02_dev *dev, u8 tx_mode,
6983548a9ddSLorenzo Bianconi 			   s8 target_power, s8 target_pa_power,
6993548a9ddSLorenzo Bianconi 			   s16 ltssi)
7003548a9ddSLorenzo Bianconi {
70196747a51SFelix Fietkau 	struct ieee80211_channel *chan = dev->mphy.chandef.chan;
7023548a9ddSLorenzo Bianconi 	int tssi_target = target_power << 12, tssi_slope;
7033548a9ddSLorenzo Bianconi 	int tssi_offset, tssi_db, ret;
7043548a9ddSLorenzo Bianconi 	u32 data;
7053548a9ddSLorenzo Bianconi 	u16 val;
7063548a9ddSLorenzo Bianconi 
7073548a9ddSLorenzo Bianconi 	if (chan->band == NL80211_BAND_5GHZ) {
7083548a9ddSLorenzo Bianconi 		u8 bound[7];
7093548a9ddSLorenzo Bianconi 		int i, err;
7103548a9ddSLorenzo Bianconi 
7113548a9ddSLorenzo Bianconi 		err = mt76x02_eeprom_copy(dev, MT_EE_TSSI_BOUND1, bound,
7123548a9ddSLorenzo Bianconi 					  sizeof(bound));
7133548a9ddSLorenzo Bianconi 		if (err < 0)
7143548a9ddSLorenzo Bianconi 			return err;
7153548a9ddSLorenzo Bianconi 
7163548a9ddSLorenzo Bianconi 		for (i = 0; i < ARRAY_SIZE(bound); i++) {
7173548a9ddSLorenzo Bianconi 			if (chan->hw_value <= bound[i] || !bound[i])
7183548a9ddSLorenzo Bianconi 				break;
7193548a9ddSLorenzo Bianconi 		}
7203548a9ddSLorenzo Bianconi 		val = mt76x02_eeprom_get(dev, MT_EE_TSSI_SLOPE_5G + i * 2);
7213548a9ddSLorenzo Bianconi 
7223548a9ddSLorenzo Bianconi 		tssi_offset = val >> 8;
7233548a9ddSLorenzo Bianconi 		if ((tssi_offset >= 64 && tssi_offset <= 127) ||
7243548a9ddSLorenzo Bianconi 		    (tssi_offset & BIT(7)))
7253548a9ddSLorenzo Bianconi 			tssi_offset -= BIT(8);
7263548a9ddSLorenzo Bianconi 	} else {
7273548a9ddSLorenzo Bianconi 		val = mt76x02_eeprom_get(dev, MT_EE_TSSI_SLOPE_2G);
7283548a9ddSLorenzo Bianconi 
7293548a9ddSLorenzo Bianconi 		tssi_offset = val >> 8;
7303548a9ddSLorenzo Bianconi 		if (tssi_offset & BIT(7))
7313548a9ddSLorenzo Bianconi 			tssi_offset -= BIT(8);
7323548a9ddSLorenzo Bianconi 	}
7333548a9ddSLorenzo Bianconi 	tssi_slope = val & 0xff;
7343548a9ddSLorenzo Bianconi 
7353548a9ddSLorenzo Bianconi 	switch (target_pa_power) {
7363548a9ddSLorenzo Bianconi 	case 1:
7373548a9ddSLorenzo Bianconi 		if (chan->band == NL80211_BAND_2GHZ)
7383548a9ddSLorenzo Bianconi 			tssi_target += 29491; /* 3.6 * 8192 */
739aab662ccSGustavo A. R. Silva 		fallthrough;
7403548a9ddSLorenzo Bianconi 	case 0:
7413548a9ddSLorenzo Bianconi 		break;
7423548a9ddSLorenzo Bianconi 	default:
7433548a9ddSLorenzo Bianconi 		tssi_target += 4424; /* 0.54 * 8192 */
7443548a9ddSLorenzo Bianconi 		break;
7453548a9ddSLorenzo Bianconi 	}
7463548a9ddSLorenzo Bianconi 
7473548a9ddSLorenzo Bianconi 	if (!tx_mode) {
7483548a9ddSLorenzo Bianconi 		data = mt76_rr(dev, MT_BBP(CORE, 1));
74961c51a74SLorenzo Bianconi 		if (is_mt7630(dev) && mt76_is_mmio(&dev->mt76)) {
7503548a9ddSLorenzo Bianconi 			int offset;
7513548a9ddSLorenzo Bianconi 
7523548a9ddSLorenzo Bianconi 			/* 2.3 * 8192 or 1.5 * 8192 */
7533548a9ddSLorenzo Bianconi 			offset = (data & BIT(5)) ? 18841 : 12288;
7543548a9ddSLorenzo Bianconi 			tssi_target += offset;
7553548a9ddSLorenzo Bianconi 		} else if (data & BIT(5)) {
7563548a9ddSLorenzo Bianconi 			/* 0.8 * 8192 */
7573548a9ddSLorenzo Bianconi 			tssi_target += 6554;
7583548a9ddSLorenzo Bianconi 		}
7593548a9ddSLorenzo Bianconi 	}
7603548a9ddSLorenzo Bianconi 
7613548a9ddSLorenzo Bianconi 	data = mt76_rr(dev, MT_BBP(TXBE, 4));
7623548a9ddSLorenzo Bianconi 	switch (data & 0x3) {
7633548a9ddSLorenzo Bianconi 	case 1:
7643548a9ddSLorenzo Bianconi 		tssi_target -= 49152; /* -6db * 8192 */
7653548a9ddSLorenzo Bianconi 		break;
7663548a9ddSLorenzo Bianconi 	case 2:
7673548a9ddSLorenzo Bianconi 		tssi_target -= 98304; /* -12db * 8192 */
7683548a9ddSLorenzo Bianconi 		break;
7693548a9ddSLorenzo Bianconi 	case 3:
7703548a9ddSLorenzo Bianconi 		tssi_target += 49152; /* 6db * 8192 */
7713548a9ddSLorenzo Bianconi 		break;
7723548a9ddSLorenzo Bianconi 	default:
7733548a9ddSLorenzo Bianconi 		break;
7743548a9ddSLorenzo Bianconi 	}
7753548a9ddSLorenzo Bianconi 
7763548a9ddSLorenzo Bianconi 	tssi_db = mt76x0_phy_lin2db(ltssi - dev->cal.tssi_dc) * tssi_slope;
7773548a9ddSLorenzo Bianconi 	if (chan->band == NL80211_BAND_5GHZ) {
7783548a9ddSLorenzo Bianconi 		tssi_db += ((tssi_offset - 50) << 10); /* offset s4.3 */
7793548a9ddSLorenzo Bianconi 		tssi_target -= tssi_db;
7803548a9ddSLorenzo Bianconi 		if (ltssi > 254 && tssi_target > 0) {
7813548a9ddSLorenzo Bianconi 			/* upper saturate */
7823548a9ddSLorenzo Bianconi 			tssi_target = 0;
7833548a9ddSLorenzo Bianconi 		}
7843548a9ddSLorenzo Bianconi 	} else {
7853548a9ddSLorenzo Bianconi 		tssi_db += (tssi_offset << 9); /* offset s3.4 */
7863548a9ddSLorenzo Bianconi 		tssi_target -= tssi_db;
7873548a9ddSLorenzo Bianconi 		/* upper-lower saturate */
7883548a9ddSLorenzo Bianconi 		if ((ltssi > 126 && tssi_target > 0) ||
7893548a9ddSLorenzo Bianconi 		    ((ltssi - dev->cal.tssi_dc) < 1 && tssi_target < 0)) {
7903548a9ddSLorenzo Bianconi 			tssi_target = 0;
7913548a9ddSLorenzo Bianconi 		}
7923548a9ddSLorenzo Bianconi 	}
7933548a9ddSLorenzo Bianconi 
7943548a9ddSLorenzo Bianconi 	if ((dev->cal.tssi_target ^ tssi_target) < 0 &&
7953548a9ddSLorenzo Bianconi 	    dev->cal.tssi_target > -4096 && dev->cal.tssi_target < 4096 &&
7963548a9ddSLorenzo Bianconi 	    tssi_target > -4096 && tssi_target < 4096) {
7973548a9ddSLorenzo Bianconi 		if ((tssi_target < 0 &&
7983548a9ddSLorenzo Bianconi 		     tssi_target + dev->cal.tssi_target > 0) ||
7993548a9ddSLorenzo Bianconi 		    (tssi_target > 0 &&
8003548a9ddSLorenzo Bianconi 		     tssi_target + dev->cal.tssi_target <= 0))
8013548a9ddSLorenzo Bianconi 			tssi_target = 0;
8023548a9ddSLorenzo Bianconi 		else
8033548a9ddSLorenzo Bianconi 			dev->cal.tssi_target = tssi_target;
8043548a9ddSLorenzo Bianconi 	} else {
8053548a9ddSLorenzo Bianconi 		dev->cal.tssi_target = tssi_target;
8063548a9ddSLorenzo Bianconi 	}
8073548a9ddSLorenzo Bianconi 
8083548a9ddSLorenzo Bianconi 	/* make the compensate value to the nearest compensate code */
8093548a9ddSLorenzo Bianconi 	if (tssi_target > 0)
8103548a9ddSLorenzo Bianconi 		tssi_target += 2048;
8113548a9ddSLorenzo Bianconi 	else
8123548a9ddSLorenzo Bianconi 		tssi_target -= 2048;
8133548a9ddSLorenzo Bianconi 	tssi_target >>= 12;
8143548a9ddSLorenzo Bianconi 
8153548a9ddSLorenzo Bianconi 	ret = mt76_get_field(dev, MT_TX_ALC_CFG_1, MT_TX_ALC_CFG_1_TEMP_COMP);
8163548a9ddSLorenzo Bianconi 	if (ret & BIT(5))
8173548a9ddSLorenzo Bianconi 		ret -= BIT(6);
8183548a9ddSLorenzo Bianconi 	ret += tssi_target;
8193548a9ddSLorenzo Bianconi 
8203548a9ddSLorenzo Bianconi 	ret = min_t(int, 31, ret);
8213548a9ddSLorenzo Bianconi 	return max_t(int, -32, ret);
8223548a9ddSLorenzo Bianconi }
8233548a9ddSLorenzo Bianconi 
mt76x0_phy_tssi_calibrate(struct mt76x02_dev * dev)8243548a9ddSLorenzo Bianconi static void mt76x0_phy_tssi_calibrate(struct mt76x02_dev *dev)
8253548a9ddSLorenzo Bianconi {
8263548a9ddSLorenzo Bianconi 	s8 target_power, target_pa_power;
8273548a9ddSLorenzo Bianconi 	u8 tssi_info[3], tx_mode;
8283548a9ddSLorenzo Bianconi 	s16 ltssi;
8293548a9ddSLorenzo Bianconi 	s8 val;
8303548a9ddSLorenzo Bianconi 
8313548a9ddSLorenzo Bianconi 	if (mt76x0_phy_tssi_adc_calibrate(dev, &ltssi, tssi_info) < 0)
8323548a9ddSLorenzo Bianconi 		return;
8333548a9ddSLorenzo Bianconi 
8343548a9ddSLorenzo Bianconi 	tx_mode = tssi_info[0] & 0x7;
8353548a9ddSLorenzo Bianconi 	if (mt76x0_phy_get_target_power(dev, tx_mode, tssi_info,
8363548a9ddSLorenzo Bianconi 					&target_power, &target_pa_power) < 0)
8373548a9ddSLorenzo Bianconi 		return;
8383548a9ddSLorenzo Bianconi 
8393548a9ddSLorenzo Bianconi 	val = mt76x0_phy_get_delta_power(dev, tx_mode, target_power,
8403548a9ddSLorenzo Bianconi 					 target_pa_power, ltssi);
8413548a9ddSLorenzo Bianconi 	mt76_rmw_field(dev, MT_TX_ALC_CFG_1, MT_TX_ALC_CFG_1_TEMP_COMP, val);
8423548a9ddSLorenzo Bianconi }
8433548a9ddSLorenzo Bianconi 
mt76x0_phy_set_txpower(struct mt76x02_dev * dev)844b2d871c0SLorenzo Bianconi void mt76x0_phy_set_txpower(struct mt76x02_dev *dev)
84510de7a8bSStanislaw Gruszka {
846b376d963SFelix Fietkau 	struct mt76x02_rate_power *t = &dev->rate_power;
84705672636SLorenzo Bianconi 	s8 info;
84810de7a8bSStanislaw Gruszka 
84996747a51SFelix Fietkau 	mt76x0_get_tx_power_per_rate(dev, dev->mphy.chandef.chan, t);
85096747a51SFelix Fietkau 	mt76x0_get_power_info(dev, dev->mphy.chandef.chan, &info);
8511f4db1fdSLorenzo Bianconi 
85205672636SLorenzo Bianconi 	mt76x02_add_rate_power_offset(t, info);
8539e5f6dd7SFelix Fietkau 	mt76x02_limit_rate_power(t, dev->txpower_conf);
854beaaeb6bSFelix Fietkau 	dev->mphy.txpower_cur = mt76x02_get_max_rate_power(t);
85505672636SLorenzo Bianconi 	mt76x02_add_rate_power_offset(t, -info);
8561f4db1fdSLorenzo Bianconi 
8570bee1ff6SLorenzo Bianconi 	dev->target_power = info;
85805672636SLorenzo Bianconi 	mt76x02_phy_set_txpower(dev, info, info);
85910de7a8bSStanislaw Gruszka }
86010de7a8bSStanislaw Gruszka 
mt76x0_phy_calibrate(struct mt76x02_dev * dev,bool power_on)8619aec146dSLorenzo Bianconi void mt76x0_phy_calibrate(struct mt76x02_dev *dev, bool power_on)
8629aec146dSLorenzo Bianconi {
86396747a51SFelix Fietkau 	struct ieee80211_channel *chan = dev->mphy.chandef.chan;
864ad3f993aSStanislaw Gruszka 	int is_5ghz = (chan->band == NL80211_BAND_5GHZ) ? 1 : 0;
8659aec146dSLorenzo Bianconi 	u32 val, tx_alc, reg_val;
8669aec146dSLorenzo Bianconi 
867a83150eaSStanislaw Gruszka 	if (is_mt7630(dev))
868a83150eaSStanislaw Gruszka 		return;
869a83150eaSStanislaw Gruszka 
8709aec146dSLorenzo Bianconi 	if (power_on) {
8714ece1e0aSStanislaw Gruszka 		mt76x02_mcu_calibrate(dev, MCU_CAL_R, 0);
8724ece1e0aSStanislaw Gruszka 		mt76x02_mcu_calibrate(dev, MCU_CAL_VCO, chan->hw_value);
8739aec146dSLorenzo Bianconi 		usleep_range(10, 20);
8743548a9ddSLorenzo Bianconi 
8753548a9ddSLorenzo Bianconi 		if (mt76x0_tssi_enabled(dev)) {
8763548a9ddSLorenzo Bianconi 			mt76_wr(dev, MT_MAC_SYS_CTRL,
8773548a9ddSLorenzo Bianconi 				MT_MAC_SYS_CTRL_ENABLE_RX);
8783548a9ddSLorenzo Bianconi 			mt76x0_phy_tssi_dc_calibrate(dev);
8793548a9ddSLorenzo Bianconi 			mt76_wr(dev, MT_MAC_SYS_CTRL,
8803548a9ddSLorenzo Bianconi 				MT_MAC_SYS_CTRL_ENABLE_TX |
8813548a9ddSLorenzo Bianconi 				MT_MAC_SYS_CTRL_ENABLE_RX);
8823548a9ddSLorenzo Bianconi 		}
8839aec146dSLorenzo Bianconi 	}
8849aec146dSLorenzo Bianconi 
8859aec146dSLorenzo Bianconi 	tx_alc = mt76_rr(dev, MT_TX_ALC_CFG_0);
8869aec146dSLorenzo Bianconi 	mt76_wr(dev, MT_TX_ALC_CFG_0, 0);
8879aec146dSLorenzo Bianconi 	usleep_range(500, 700);
8889aec146dSLorenzo Bianconi 
8899aec146dSLorenzo Bianconi 	reg_val = mt76_rr(dev, MT_BBP(IBI, 9));
8909aec146dSLorenzo Bianconi 	mt76_wr(dev, MT_BBP(IBI, 9), 0xffffff7e);
8919aec146dSLorenzo Bianconi 
892ad3f993aSStanislaw Gruszka 	if (is_5ghz) {
8939aec146dSLorenzo Bianconi 		if (chan->hw_value < 100)
8949aec146dSLorenzo Bianconi 			val = 0x701;
8959aec146dSLorenzo Bianconi 		else if (chan->hw_value < 140)
8969aec146dSLorenzo Bianconi 			val = 0x801;
8979aec146dSLorenzo Bianconi 		else
8989aec146dSLorenzo Bianconi 			val = 0x901;
8999aec146dSLorenzo Bianconi 	} else {
9009aec146dSLorenzo Bianconi 		val = 0x600;
9019aec146dSLorenzo Bianconi 	}
9029aec146dSLorenzo Bianconi 
9034ece1e0aSStanislaw Gruszka 	mt76x02_mcu_calibrate(dev, MCU_CAL_FULL, val);
9044ece1e0aSStanislaw Gruszka 	mt76x02_mcu_calibrate(dev, MCU_CAL_LC, is_5ghz);
9059aec146dSLorenzo Bianconi 	usleep_range(15000, 20000);
9069aec146dSLorenzo Bianconi 
9079aec146dSLorenzo Bianconi 	mt76_wr(dev, MT_BBP(IBI, 9), reg_val);
9089aec146dSLorenzo Bianconi 	mt76_wr(dev, MT_TX_ALC_CFG_0, tx_alc);
9094ece1e0aSStanislaw Gruszka 	mt76x02_mcu_calibrate(dev, MCU_CAL_RXDCOC, 1);
9109aec146dSLorenzo Bianconi }
9119aec146dSLorenzo Bianconi EXPORT_SYMBOL_GPL(mt76x0_phy_calibrate);
9129aec146dSLorenzo Bianconi 
mt76x0_phy_set_channel(struct mt76x02_dev * dev,struct cfg80211_chan_def * chandef)9130c168e10SStanislaw Gruszka void mt76x0_phy_set_channel(struct mt76x02_dev *dev,
91410de7a8bSStanislaw Gruszka 			    struct cfg80211_chan_def *chandef)
91510de7a8bSStanislaw Gruszka {
91610de7a8bSStanislaw Gruszka 	u32 ext_cca_chan[4] = {
91710de7a8bSStanislaw Gruszka 		[0] = FIELD_PREP(MT_EXT_CCA_CFG_CCA0, 0) |
91810de7a8bSStanislaw Gruszka 		      FIELD_PREP(MT_EXT_CCA_CFG_CCA1, 1) |
91910de7a8bSStanislaw Gruszka 		      FIELD_PREP(MT_EXT_CCA_CFG_CCA2, 2) |
92010de7a8bSStanislaw Gruszka 		      FIELD_PREP(MT_EXT_CCA_CFG_CCA3, 3) |
92110de7a8bSStanislaw Gruszka 		      FIELD_PREP(MT_EXT_CCA_CFG_CCA_MASK, BIT(0)),
92210de7a8bSStanislaw Gruszka 		[1] = FIELD_PREP(MT_EXT_CCA_CFG_CCA0, 1) |
92310de7a8bSStanislaw Gruszka 		      FIELD_PREP(MT_EXT_CCA_CFG_CCA1, 0) |
92410de7a8bSStanislaw Gruszka 		      FIELD_PREP(MT_EXT_CCA_CFG_CCA2, 2) |
92510de7a8bSStanislaw Gruszka 		      FIELD_PREP(MT_EXT_CCA_CFG_CCA3, 3) |
92610de7a8bSStanislaw Gruszka 		      FIELD_PREP(MT_EXT_CCA_CFG_CCA_MASK, BIT(1)),
92710de7a8bSStanislaw Gruszka 		[2] = FIELD_PREP(MT_EXT_CCA_CFG_CCA0, 2) |
92810de7a8bSStanislaw Gruszka 		      FIELD_PREP(MT_EXT_CCA_CFG_CCA1, 3) |
92910de7a8bSStanislaw Gruszka 		      FIELD_PREP(MT_EXT_CCA_CFG_CCA2, 1) |
93010de7a8bSStanislaw Gruszka 		      FIELD_PREP(MT_EXT_CCA_CFG_CCA3, 0) |
93110de7a8bSStanislaw Gruszka 		      FIELD_PREP(MT_EXT_CCA_CFG_CCA_MASK, BIT(2)),
93210de7a8bSStanislaw Gruszka 		[3] = FIELD_PREP(MT_EXT_CCA_CFG_CCA0, 3) |
93310de7a8bSStanislaw Gruszka 		      FIELD_PREP(MT_EXT_CCA_CFG_CCA1, 2) |
93410de7a8bSStanislaw Gruszka 		      FIELD_PREP(MT_EXT_CCA_CFG_CCA2, 1) |
93510de7a8bSStanislaw Gruszka 		      FIELD_PREP(MT_EXT_CCA_CFG_CCA3, 0) |
93610de7a8bSStanislaw Gruszka 		      FIELD_PREP(MT_EXT_CCA_CFG_CCA_MASK, BIT(3)),
93710de7a8bSStanislaw Gruszka 	};
938011849e0SFelix Fietkau 	bool scan = test_bit(MT76_SCANNING, &dev->mphy.state);
93910de7a8bSStanislaw Gruszka 	int ch_group_index, freq, freq1;
94010de7a8bSStanislaw Gruszka 	u8 channel;
94110de7a8bSStanislaw Gruszka 	u32 val;
94210de7a8bSStanislaw Gruszka 	u16 rf_bw_band;
94310de7a8bSStanislaw Gruszka 
94410de7a8bSStanislaw Gruszka 	freq = chandef->chan->center_freq;
94510de7a8bSStanislaw Gruszka 	freq1 = chandef->center_freq1;
94610de7a8bSStanislaw Gruszka 	channel = chandef->chan->hw_value;
94710de7a8bSStanislaw Gruszka 	rf_bw_band = (channel <= 14) ? RF_G_BAND : RF_A_BAND;
94810de7a8bSStanislaw Gruszka 
94910de7a8bSStanislaw Gruszka 	switch (chandef->width) {
95010de7a8bSStanislaw Gruszka 	case NL80211_CHAN_WIDTH_40:
95110de7a8bSStanislaw Gruszka 		if (freq1 > freq)
95210de7a8bSStanislaw Gruszka 			ch_group_index = 0;
95310de7a8bSStanislaw Gruszka 		else
95410de7a8bSStanislaw Gruszka 			ch_group_index = 1;
95510de7a8bSStanislaw Gruszka 		channel += 2 - ch_group_index * 4;
95610de7a8bSStanislaw Gruszka 		rf_bw_band |= RF_BW_40;
95710de7a8bSStanislaw Gruszka 		break;
95810de7a8bSStanislaw Gruszka 	case NL80211_CHAN_WIDTH_80:
95910de7a8bSStanislaw Gruszka 		ch_group_index = (freq - freq1 + 30) / 20;
96010de7a8bSStanislaw Gruszka 		if (WARN_ON(ch_group_index < 0 || ch_group_index > 3))
96110de7a8bSStanislaw Gruszka 			ch_group_index = 0;
96210de7a8bSStanislaw Gruszka 		channel += 6 - ch_group_index * 4;
96310de7a8bSStanislaw Gruszka 		rf_bw_band |= RF_BW_80;
96410de7a8bSStanislaw Gruszka 		break;
96510de7a8bSStanislaw Gruszka 	default:
96610de7a8bSStanislaw Gruszka 		ch_group_index = 0;
96710de7a8bSStanislaw Gruszka 		rf_bw_band |= RF_BW_20;
96810de7a8bSStanislaw Gruszka 		break;
96910de7a8bSStanislaw Gruszka 	}
97010de7a8bSStanislaw Gruszka 
97161c51a74SLorenzo Bianconi 	if (mt76_is_usb(&dev->mt76)) {
9729c410782SLorenzo Bianconi 		mt76x0_phy_bbp_set_bw(dev, chandef->width);
973592ebc9cSLorenzo Bianconi 	} else {
974592ebc9cSLorenzo Bianconi 		if (chandef->width == NL80211_CHAN_WIDTH_80 ||
975592ebc9cSLorenzo Bianconi 		    chandef->width == NL80211_CHAN_WIDTH_40)
976592ebc9cSLorenzo Bianconi 			val = 0x201;
977592ebc9cSLorenzo Bianconi 		else
978592ebc9cSLorenzo Bianconi 			val = 0x601;
979592ebc9cSLorenzo Bianconi 		mt76_wr(dev, MT_TX_SW_CFG0, val);
980592ebc9cSLorenzo Bianconi 	}
981032c08f4SLorenzo Bianconi 	mt76x02_phy_set_bw(dev, chandef->width, ch_group_index);
982370c6415SLorenzo Bianconi 	mt76x02_phy_set_band(dev, chandef->chan->band,
983370c6415SLorenzo Bianconi 			     ch_group_index & 1);
98410de7a8bSStanislaw Gruszka 
98510de7a8bSStanislaw Gruszka 	mt76_rmw(dev, MT_EXT_CCA_CFG,
98610de7a8bSStanislaw Gruszka 		 (MT_EXT_CCA_CFG_CCA0 |
98710de7a8bSStanislaw Gruszka 		  MT_EXT_CCA_CFG_CCA1 |
98810de7a8bSStanislaw Gruszka 		  MT_EXT_CCA_CFG_CCA2 |
98910de7a8bSStanislaw Gruszka 		  MT_EXT_CCA_CFG_CCA3 |
99010de7a8bSStanislaw Gruszka 		  MT_EXT_CCA_CFG_CCA_MASK),
99110de7a8bSStanislaw Gruszka 		 ext_cca_chan[ch_group_index]);
99210de7a8bSStanislaw Gruszka 
99310de7a8bSStanislaw Gruszka 	mt76x0_phy_set_band(dev, chandef->chan->band);
99410de7a8bSStanislaw Gruszka 	mt76x0_phy_set_chan_rf_params(dev, channel, rf_bw_band);
99510de7a8bSStanislaw Gruszka 
99610de7a8bSStanislaw Gruszka 	/* set Japan Tx filter at channel 14 */
99710de7a8bSStanislaw Gruszka 	if (channel == 14)
998d3caa060SLorenzo Bianconi 		mt76_set(dev, MT_BBP(CORE, 1), 0x20);
99910de7a8bSStanislaw Gruszka 	else
1000d3caa060SLorenzo Bianconi 		mt76_clear(dev, MT_BBP(CORE, 1), 0x20);
100110de7a8bSStanislaw Gruszka 
1002592ebc9cSLorenzo Bianconi 	mt76x0_read_rx_gain(dev);
10037859c543SLorenzo Bianconi 	mt76x0_phy_set_chan_bbp_params(dev, rf_bw_band);
100410de7a8bSStanislaw Gruszka 
1005592ebc9cSLorenzo Bianconi 	/* enable vco */
10069c410782SLorenzo Bianconi 	mt76x0_rf_set(dev, MT_RF(0, 4), BIT(7));
10074606a26cSFelix Fietkau 	if (scan)
10080c168e10SStanislaw Gruszka 		return;
1009bbd10586SLorenzo Bianconi 
1010f1b8ee35SStanislaw Gruszka 	mt76x02_init_agc_gain(dev);
1011bbd10586SLorenzo Bianconi 	mt76x0_phy_calibrate(dev, false);
10121f4db1fdSLorenzo Bianconi 	mt76x0_phy_set_txpower(dev);
101310de7a8bSStanislaw Gruszka 
1014bbd10586SLorenzo Bianconi 	ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work,
1015bbd10586SLorenzo Bianconi 				     MT_CALIBRATE_INTERVAL);
101610de7a8bSStanislaw Gruszka }
101710de7a8bSStanislaw Gruszka 
mt76x0_phy_temp_sensor(struct mt76x02_dev * dev)10189c410782SLorenzo Bianconi static void mt76x0_phy_temp_sensor(struct mt76x02_dev *dev)
101910de7a8bSStanislaw Gruszka {
102010de7a8bSStanislaw Gruszka 	u8 rf_b7_73, rf_b0_66, rf_b0_67;
102166a34c66SLorenzo Bianconi 	s8 val;
102210de7a8bSStanislaw Gruszka 
10239c410782SLorenzo Bianconi 	rf_b7_73 = mt76x0_rf_rr(dev, MT_RF(7, 73));
10249c410782SLorenzo Bianconi 	rf_b0_66 = mt76x0_rf_rr(dev, MT_RF(0, 66));
10259c410782SLorenzo Bianconi 	rf_b0_67 = mt76x0_rf_rr(dev, MT_RF(0, 67));
102610de7a8bSStanislaw Gruszka 
10279c410782SLorenzo Bianconi 	mt76x0_rf_wr(dev, MT_RF(7, 73), 0x02);
10289c410782SLorenzo Bianconi 	mt76x0_rf_wr(dev, MT_RF(0, 66), 0x23);
10299c410782SLorenzo Bianconi 	mt76x0_rf_wr(dev, MT_RF(0, 67), 0x01);
103010de7a8bSStanislaw Gruszka 
103110de7a8bSStanislaw Gruszka 	mt76_wr(dev, MT_BBP(CORE, 34), 0x00080055);
10320464cbfcSLorenzo Bianconi 	if (!mt76_poll_msec(dev, MT_BBP(CORE, 34), BIT(4), 0, 200)) {
103366a34c66SLorenzo Bianconi 		mt76_clear(dev, MT_BBP(CORE, 34), BIT(4));
103410de7a8bSStanislaw Gruszka 		goto done;
103510de7a8bSStanislaw Gruszka 	}
103610de7a8bSStanislaw Gruszka 
103766a34c66SLorenzo Bianconi 	val = mt76_rr(dev, MT_BBP(CORE, 35));
103866a34c66SLorenzo Bianconi 	val = (35 * (val - dev->cal.rx.temp_offset)) / 10 + 25;
103910de7a8bSStanislaw Gruszka 
104066a34c66SLorenzo Bianconi 	if (abs(val - dev->cal.temp_vco) > 20) {
104166a34c66SLorenzo Bianconi 		mt76x02_mcu_calibrate(dev, MCU_CAL_VCO,
104296747a51SFelix Fietkau 				      dev->mphy.chandef.chan->hw_value);
104366a34c66SLorenzo Bianconi 		dev->cal.temp_vco = val;
104466a34c66SLorenzo Bianconi 	}
104566a34c66SLorenzo Bianconi 	if (abs(val - dev->cal.temp) > 30) {
104666a34c66SLorenzo Bianconi 		mt76x0_phy_calibrate(dev, false);
104766a34c66SLorenzo Bianconi 		dev->cal.temp = val;
104866a34c66SLorenzo Bianconi 	}
104910de7a8bSStanislaw Gruszka 
105010de7a8bSStanislaw Gruszka done:
10519c410782SLorenzo Bianconi 	mt76x0_rf_wr(dev, MT_RF(7, 73), rf_b7_73);
10529c410782SLorenzo Bianconi 	mt76x0_rf_wr(dev, MT_RF(0, 66), rf_b0_66);
10539c410782SLorenzo Bianconi 	mt76x0_rf_wr(dev, MT_RF(0, 67), rf_b0_67);
105410de7a8bSStanislaw Gruszka }
105510de7a8bSStanislaw Gruszka 
mt76x0_phy_set_gain_val(struct mt76x02_dev * dev)10564636a254SLorenzo Bianconi static void mt76x0_phy_set_gain_val(struct mt76x02_dev *dev)
105710de7a8bSStanislaw Gruszka {
10584636a254SLorenzo Bianconi 	u8 gain = dev->cal.agc_gain_cur[0] - dev->cal.agc_gain_adjust;
105910de7a8bSStanislaw Gruszka 
1060b983a5b9SStanislaw Gruszka 	mt76_rmw_field(dev, MT_BBP(AGC, 8), MT_BBP_AGC_GAIN, gain);
1061801ccc8aSLorenzo Bianconi 
106296747a51SFelix Fietkau 	if ((dev->mphy.chandef.chan->flags & IEEE80211_CHAN_RADAR) &&
1063801ccc8aSLorenzo Bianconi 	    !is_mt7630(dev))
1064801ccc8aSLorenzo Bianconi 		mt76x02_phy_dfs_adjust_agc(dev);
10654636a254SLorenzo Bianconi }
106610de7a8bSStanislaw Gruszka 
10674636a254SLorenzo Bianconi static void
mt76x0_phy_update_channel_gain(struct mt76x02_dev * dev)10684636a254SLorenzo Bianconi mt76x0_phy_update_channel_gain(struct mt76x02_dev *dev)
10694636a254SLorenzo Bianconi {
10704636a254SLorenzo Bianconi 	bool gain_change;
10714636a254SLorenzo Bianconi 	u8 gain_delta;
10724636a254SLorenzo Bianconi 	int low_gain;
10734636a254SLorenzo Bianconi 
10748af63fedSFelix Fietkau 	dev->cal.avg_rssi_all = mt76_get_min_avg_rssi(&dev->mt76, false);
1075ef13edc0SFelix Fietkau 	if (!dev->cal.avg_rssi_all)
1076ef13edc0SFelix Fietkau 		dev->cal.avg_rssi_all = -75;
10774636a254SLorenzo Bianconi 
10784636a254SLorenzo Bianconi 	low_gain = (dev->cal.avg_rssi_all > mt76x02_get_rssi_gain_thresh(dev)) +
10794636a254SLorenzo Bianconi 		(dev->cal.avg_rssi_all > mt76x02_get_low_rssi_gain_thresh(dev));
10804636a254SLorenzo Bianconi 
10814784a3ccSStanislaw Gruszka 	gain_change = dev->cal.low_gain < 0 ||
10824784a3ccSStanislaw Gruszka 		      (dev->cal.low_gain & 2) ^ (low_gain & 2);
10834636a254SLorenzo Bianconi 	dev->cal.low_gain = low_gain;
10844636a254SLorenzo Bianconi 
10854636a254SLorenzo Bianconi 	if (!gain_change) {
10864636a254SLorenzo Bianconi 		if (mt76x02_phy_adjust_vga_gain(dev))
10874636a254SLorenzo Bianconi 			mt76x0_phy_set_gain_val(dev);
10884636a254SLorenzo Bianconi 		return;
10894636a254SLorenzo Bianconi 	}
10904636a254SLorenzo Bianconi 
10914636a254SLorenzo Bianconi 	dev->cal.agc_gain_adjust = (low_gain == 2) ? 0 : 10;
10924636a254SLorenzo Bianconi 	gain_delta = (low_gain == 2) ? 10 : 0;
10934636a254SLorenzo Bianconi 
10944636a254SLorenzo Bianconi 	dev->cal.agc_gain_cur[0] = dev->cal.agc_gain_init[0] - gain_delta;
10954636a254SLorenzo Bianconi 	mt76x0_phy_set_gain_val(dev);
10964636a254SLorenzo Bianconi 
10974636a254SLorenzo Bianconi 	/* clear false CCA counters */
10984636a254SLorenzo Bianconi 	mt76_rr(dev, MT_RX_STAT_1);
109910de7a8bSStanislaw Gruszka }
110010de7a8bSStanislaw Gruszka 
mt76x0_phy_calibration_work(struct work_struct * work)11013eaf05deSLorenzo Bianconi static void mt76x0_phy_calibration_work(struct work_struct *work)
110210de7a8bSStanislaw Gruszka {
1103b2d871c0SLorenzo Bianconi 	struct mt76x02_dev *dev = container_of(work, struct mt76x02_dev,
110410de7a8bSStanislaw Gruszka 					       cal_work.work);
110510de7a8bSStanislaw Gruszka 
11064636a254SLorenzo Bianconi 	mt76x0_phy_update_channel_gain(dev);
11073548a9ddSLorenzo Bianconi 	if (mt76x0_tssi_enabled(dev))
11083548a9ddSLorenzo Bianconi 		mt76x0_phy_tssi_calibrate(dev);
11093548a9ddSLorenzo Bianconi 	else
11109c410782SLorenzo Bianconi 		mt76x0_phy_temp_sensor(dev);
111110de7a8bSStanislaw Gruszka 
111210de7a8bSStanislaw Gruszka 	ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work,
11133548a9ddSLorenzo Bianconi 				     4 * MT_CALIBRATE_INTERVAL);
111410de7a8bSStanislaw Gruszka }
111510de7a8bSStanislaw Gruszka 
mt76x0_rf_patch_reg_array(struct mt76x02_dev * dev,const struct mt76_reg_pair * rp,int len)1116cadc83efSFelix Fietkau static void mt76x0_rf_patch_reg_array(struct mt76x02_dev *dev,
1117cadc83efSFelix Fietkau 				      const struct mt76_reg_pair *rp, int len)
1118cadc83efSFelix Fietkau {
1119cadc83efSFelix Fietkau 	int i;
1120cadc83efSFelix Fietkau 
1121cadc83efSFelix Fietkau 	for (i = 0; i < len; i++) {
1122cadc83efSFelix Fietkau 		u32 reg = rp[i].reg;
1123cadc83efSFelix Fietkau 		u8 val = rp[i].value;
1124cadc83efSFelix Fietkau 
1125cadc83efSFelix Fietkau 		switch (reg) {
1126cadc83efSFelix Fietkau 		case MT_RF(0, 3):
112761c51a74SLorenzo Bianconi 			if (mt76_is_mmio(&dev->mt76)) {
1128cadc83efSFelix Fietkau 				if (is_mt7630(dev))
1129cadc83efSFelix Fietkau 					val = 0x70;
1130cadc83efSFelix Fietkau 				else
1131cadc83efSFelix Fietkau 					val = 0x63;
1132cadc83efSFelix Fietkau 			} else {
1133cadc83efSFelix Fietkau 				val = 0x73;
1134cadc83efSFelix Fietkau 			}
1135cadc83efSFelix Fietkau 			break;
1136cadc83efSFelix Fietkau 		case MT_RF(0, 21):
1137cadc83efSFelix Fietkau 			if (is_mt7610e(dev))
1138cadc83efSFelix Fietkau 				val = 0x10;
1139cadc83efSFelix Fietkau 			else
1140cadc83efSFelix Fietkau 				val = 0x12;
1141cadc83efSFelix Fietkau 			break;
1142cadc83efSFelix Fietkau 		case MT_RF(5, 2):
1143cadc83efSFelix Fietkau 			if (is_mt7630(dev))
1144cadc83efSFelix Fietkau 				val = 0x1d;
1145cadc83efSFelix Fietkau 			else if (is_mt7610e(dev))
1146cadc83efSFelix Fietkau 				val = 0x00;
1147cadc83efSFelix Fietkau 			else
1148cadc83efSFelix Fietkau 				val = 0x0c;
1149cadc83efSFelix Fietkau 			break;
1150cadc83efSFelix Fietkau 		default:
1151cadc83efSFelix Fietkau 			break;
1152cadc83efSFelix Fietkau 		}
1153cadc83efSFelix Fietkau 		mt76x0_rf_wr(dev, reg, val);
1154cadc83efSFelix Fietkau 	}
1155cadc83efSFelix Fietkau }
1156cadc83efSFelix Fietkau 
mt76x0_phy_rf_init(struct mt76x02_dev * dev)11579c410782SLorenzo Bianconi static void mt76x0_phy_rf_init(struct mt76x02_dev *dev)
115810de7a8bSStanislaw Gruszka {
115910de7a8bSStanislaw Gruszka 	int i;
116010de7a8bSStanislaw Gruszka 
1161cadc83efSFelix Fietkau 	mt76x0_rf_patch_reg_array(dev, mt76x0_rf_central_tab,
1162cadc83efSFelix Fietkau 				  ARRAY_SIZE(mt76x0_rf_central_tab));
1163cadc83efSFelix Fietkau 	mt76x0_rf_patch_reg_array(dev, mt76x0_rf_2g_channel_0_tab,
1164cadc83efSFelix Fietkau 				  ARRAY_SIZE(mt76x0_rf_2g_channel_0_tab));
116510de7a8bSStanislaw Gruszka 	RF_RANDOM_WRITE(dev, mt76x0_rf_5g_channel_0_tab);
116610de7a8bSStanislaw Gruszka 	RF_RANDOM_WRITE(dev, mt76x0_rf_vga_channel_0_tab);
116710de7a8bSStanislaw Gruszka 
116810de7a8bSStanislaw Gruszka 	for (i = 0; i < ARRAY_SIZE(mt76x0_rf_bw_switch_tab); i++) {
116910de7a8bSStanislaw Gruszka 		const struct mt76x0_rf_switch_item *item = &mt76x0_rf_bw_switch_tab[i];
117010de7a8bSStanislaw Gruszka 
117110de7a8bSStanislaw Gruszka 		if (item->bw_band == RF_BW_20)
11729c410782SLorenzo Bianconi 			mt76x0_rf_wr(dev, item->rf_bank_reg, item->value);
1173ff97c52aSRyder Lee 		else if (((RF_G_BAND | RF_BW_20) & item->bw_band) ==
1174ff97c52aSRyder Lee 			  (RF_G_BAND | RF_BW_20))
11759c410782SLorenzo Bianconi 			mt76x0_rf_wr(dev, item->rf_bank_reg, item->value);
117610de7a8bSStanislaw Gruszka 	}
117710de7a8bSStanislaw Gruszka 
117810de7a8bSStanislaw Gruszka 	for (i = 0; i < ARRAY_SIZE(mt76x0_rf_band_switch_tab); i++) {
117910de7a8bSStanislaw Gruszka 		if (mt76x0_rf_band_switch_tab[i].bw_band & RF_G_BAND) {
11809c410782SLorenzo Bianconi 			mt76x0_rf_wr(dev,
118110de7a8bSStanislaw Gruszka 				     mt76x0_rf_band_switch_tab[i].rf_bank_reg,
118210de7a8bSStanislaw Gruszka 				     mt76x0_rf_band_switch_tab[i].value);
118310de7a8bSStanislaw Gruszka 		}
118410de7a8bSStanislaw Gruszka 	}
118510de7a8bSStanislaw Gruszka 
1186ff97c52aSRyder Lee 	/* Frequency calibration
1187ff97c52aSRyder Lee 	 * E1: B0.R22<6:0>: xo_cxo<6:0>
1188ff97c52aSRyder Lee 	 * E2: B0.R21<0>: xo_cxo<0>, B0.R22<7:0>: xo_cxo<8:1>
118910de7a8bSStanislaw Gruszka 	 */
11909c410782SLorenzo Bianconi 	mt76x0_rf_wr(dev, MT_RF(0, 22),
1191b2d871c0SLorenzo Bianconi 		     min_t(u8, dev->cal.rx.freq_offset, 0xbf));
1192373954efSChen Wandun 	mt76x0_rf_rr(dev, MT_RF(0, 22));
119310de7a8bSStanislaw Gruszka 
1194d3caa060SLorenzo Bianconi 	/* Reset procedure DAC during power-up:
1195d3caa060SLorenzo Bianconi 	 * - set B0.R73<7>
1196d3caa060SLorenzo Bianconi 	 * - clear B0.R73<7>
1197d3caa060SLorenzo Bianconi 	 * - set B0.R73<7>
119810de7a8bSStanislaw Gruszka 	 */
1199d3caa060SLorenzo Bianconi 	mt76x0_rf_set(dev, MT_RF(0, 73), BIT(7));
1200d3caa060SLorenzo Bianconi 	mt76x0_rf_clear(dev, MT_RF(0, 73), BIT(7));
1201d3caa060SLorenzo Bianconi 	mt76x0_rf_set(dev, MT_RF(0, 73), BIT(7));
120210de7a8bSStanislaw Gruszka 
1203d3caa060SLorenzo Bianconi 	/* vcocal_en: initiate VCO calibration (reset after completion)) */
12049c410782SLorenzo Bianconi 	mt76x0_rf_set(dev, MT_RF(0, 4), 0x80);
120510de7a8bSStanislaw Gruszka }
120610de7a8bSStanislaw Gruszka 
mt76x0_phy_init(struct mt76x02_dev * dev)1207b2d871c0SLorenzo Bianconi void mt76x0_phy_init(struct mt76x02_dev *dev)
120810de7a8bSStanislaw Gruszka {
12093eaf05deSLorenzo Bianconi 	INIT_DELAYED_WORK(&dev->cal_work, mt76x0_phy_calibration_work);
121010de7a8bSStanislaw Gruszka 
1211ef442b73SStanislaw Gruszka 	mt76x0_phy_ant_select(dev);
12129c410782SLorenzo Bianconi 	mt76x0_phy_rf_init(dev);
1213bfdff5d0SLorenzo Bianconi 	mt76x02_phy_set_rxpath(dev);
1214bfdff5d0SLorenzo Bianconi 	mt76x02_phy_set_txdac(dev);
121510de7a8bSStanislaw Gruszka }
1216