xref: /openbmc/linux/drivers/net/wireless/mediatek/mt76/mt76x2/init.c (revision 7ae9fb1b7ecbb5d85d07857943f677fd1a559b18)
10e3d6777SRyder Lee // SPDX-License-Identifier: ISC
21613c621SLorenzo Bianconi /*
31613c621SLorenzo Bianconi  * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
41613c621SLorenzo Bianconi  * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
51613c621SLorenzo Bianconi  */
61613c621SLorenzo Bianconi 
71613c621SLorenzo Bianconi #include "mt76x2.h"
81613c621SLorenzo Bianconi #include "eeprom.h"
91613c621SLorenzo Bianconi #include "../mt76x02_phy.h"
101613c621SLorenzo Bianconi 
mt76x2_set_sar_specs(struct ieee80211_hw * hw,const struct cfg80211_sar_specs * sar)11633f77b5SLorenzo Bianconi int mt76x2_set_sar_specs(struct ieee80211_hw *hw,
12633f77b5SLorenzo Bianconi 			 const struct cfg80211_sar_specs *sar)
13633f77b5SLorenzo Bianconi {
14633f77b5SLorenzo Bianconi 	int err = -EINVAL, power = hw->conf.power_level * 2;
15633f77b5SLorenzo Bianconi 	struct mt76x02_dev *dev = hw->priv;
16633f77b5SLorenzo Bianconi 	struct mt76_phy *mphy = &dev->mphy;
17633f77b5SLorenzo Bianconi 
18633f77b5SLorenzo Bianconi 	mutex_lock(&dev->mt76.mutex);
19633f77b5SLorenzo Bianconi 	if (!cfg80211_chandef_valid(&mphy->chandef))
20633f77b5SLorenzo Bianconi 		goto out;
21633f77b5SLorenzo Bianconi 
22633f77b5SLorenzo Bianconi 	err = mt76_init_sar_power(hw, sar);
23633f77b5SLorenzo Bianconi 	if (err)
24633f77b5SLorenzo Bianconi 		goto out;
25633f77b5SLorenzo Bianconi 
26633f77b5SLorenzo Bianconi 	dev->txpower_conf = mt76_get_sar_power(mphy, mphy->chandef.chan,
27633f77b5SLorenzo Bianconi 					       power);
28633f77b5SLorenzo Bianconi 	/* convert to per-chain power for 2x2 devices */
29633f77b5SLorenzo Bianconi 	dev->txpower_conf -= 6;
30633f77b5SLorenzo Bianconi 
31633f77b5SLorenzo Bianconi 	if (test_bit(MT76_STATE_RUNNING, &mphy->state))
32633f77b5SLorenzo Bianconi 		mt76x2_phy_set_txpower(dev);
33633f77b5SLorenzo Bianconi out:
34633f77b5SLorenzo Bianconi 	mutex_unlock(&dev->mt76.mutex);
35633f77b5SLorenzo Bianconi 
36633f77b5SLorenzo Bianconi 	return err;
37633f77b5SLorenzo Bianconi }
38633f77b5SLorenzo Bianconi EXPORT_SYMBOL_GPL(mt76x2_set_sar_specs);
39633f77b5SLorenzo Bianconi 
401613c621SLorenzo Bianconi static void
mt76x2_set_wlan_state(struct mt76x02_dev * dev,bool enable)41e40803f2SLorenzo Bianconi mt76x2_set_wlan_state(struct mt76x02_dev *dev, bool enable)
421613c621SLorenzo Bianconi {
431613c621SLorenzo Bianconi 	u32 val = mt76_rr(dev, MT_WLAN_FUN_CTRL);
441613c621SLorenzo Bianconi 
451613c621SLorenzo Bianconi 	if (enable)
461613c621SLorenzo Bianconi 		val |= (MT_WLAN_FUN_CTRL_WLAN_EN |
471613c621SLorenzo Bianconi 			MT_WLAN_FUN_CTRL_WLAN_CLK_EN);
481613c621SLorenzo Bianconi 	else
491613c621SLorenzo Bianconi 		val &= ~(MT_WLAN_FUN_CTRL_WLAN_EN |
501613c621SLorenzo Bianconi 			 MT_WLAN_FUN_CTRL_WLAN_CLK_EN);
511613c621SLorenzo Bianconi 
521613c621SLorenzo Bianconi 	mt76_wr(dev, MT_WLAN_FUN_CTRL, val);
531613c621SLorenzo Bianconi 	udelay(20);
541613c621SLorenzo Bianconi }
551613c621SLorenzo Bianconi 
mt76x2_reset_wlan(struct mt76x02_dev * dev,bool enable)56e40803f2SLorenzo Bianconi void mt76x2_reset_wlan(struct mt76x02_dev *dev, bool enable)
571613c621SLorenzo Bianconi {
581613c621SLorenzo Bianconi 	u32 val;
591613c621SLorenzo Bianconi 
601613c621SLorenzo Bianconi 	if (!enable)
611613c621SLorenzo Bianconi 		goto out;
621613c621SLorenzo Bianconi 
631613c621SLorenzo Bianconi 	val = mt76_rr(dev, MT_WLAN_FUN_CTRL);
641613c621SLorenzo Bianconi 
651613c621SLorenzo Bianconi 	val &= ~MT_WLAN_FUN_CTRL_FRC_WL_ANT_SEL;
661613c621SLorenzo Bianconi 
671613c621SLorenzo Bianconi 	if (val & MT_WLAN_FUN_CTRL_WLAN_EN) {
681613c621SLorenzo Bianconi 		val |= MT_WLAN_FUN_CTRL_WLAN_RESET_RF;
691613c621SLorenzo Bianconi 		mt76_wr(dev, MT_WLAN_FUN_CTRL, val);
701613c621SLorenzo Bianconi 		udelay(20);
711613c621SLorenzo Bianconi 
721613c621SLorenzo Bianconi 		val &= ~MT_WLAN_FUN_CTRL_WLAN_RESET_RF;
731613c621SLorenzo Bianconi 	}
741613c621SLorenzo Bianconi 
751613c621SLorenzo Bianconi 	mt76_wr(dev, MT_WLAN_FUN_CTRL, val);
761613c621SLorenzo Bianconi 	udelay(20);
771613c621SLorenzo Bianconi 
781613c621SLorenzo Bianconi out:
791613c621SLorenzo Bianconi 	mt76x2_set_wlan_state(dev, enable);
801613c621SLorenzo Bianconi }
811613c621SLorenzo Bianconi EXPORT_SYMBOL_GPL(mt76x2_reset_wlan);
821613c621SLorenzo Bianconi 
mt76_write_mac_initvals(struct mt76x02_dev * dev)83e40803f2SLorenzo Bianconi void mt76_write_mac_initvals(struct mt76x02_dev *dev)
841613c621SLorenzo Bianconi {
851613c621SLorenzo Bianconi #define DEFAULT_PROT_CFG_CCK				\
861613c621SLorenzo Bianconi 	(FIELD_PREP(MT_PROT_CFG_RATE, 0x3) |		\
871613c621SLorenzo Bianconi 	 FIELD_PREP(MT_PROT_CFG_NAV, 1) |		\
881613c621SLorenzo Bianconi 	 FIELD_PREP(MT_PROT_CFG_TXOP_ALLOW, 0x3f) |	\
891613c621SLorenzo Bianconi 	 MT_PROT_CFG_RTS_THRESH)
901613c621SLorenzo Bianconi 
911613c621SLorenzo Bianconi #define DEFAULT_PROT_CFG_OFDM				\
921613c621SLorenzo Bianconi 	(FIELD_PREP(MT_PROT_CFG_RATE, 0x2004) |		\
931613c621SLorenzo Bianconi 	 FIELD_PREP(MT_PROT_CFG_NAV, 1) |			\
941613c621SLorenzo Bianconi 	 FIELD_PREP(MT_PROT_CFG_TXOP_ALLOW, 0x3f) |	\
951613c621SLorenzo Bianconi 	 MT_PROT_CFG_RTS_THRESH)
961613c621SLorenzo Bianconi 
971613c621SLorenzo Bianconi #define DEFAULT_PROT_CFG_20				\
981613c621SLorenzo Bianconi 	(FIELD_PREP(MT_PROT_CFG_RATE, 0x2004) |		\
991613c621SLorenzo Bianconi 	 FIELD_PREP(MT_PROT_CFG_CTRL, 1) |		\
1001613c621SLorenzo Bianconi 	 FIELD_PREP(MT_PROT_CFG_NAV, 1) |			\
1011613c621SLorenzo Bianconi 	 FIELD_PREP(MT_PROT_CFG_TXOP_ALLOW, 0x17))
1021613c621SLorenzo Bianconi 
1031613c621SLorenzo Bianconi #define DEFAULT_PROT_CFG_40				\
1041613c621SLorenzo Bianconi 	(FIELD_PREP(MT_PROT_CFG_RATE, 0x2084) |		\
1051613c621SLorenzo Bianconi 	 FIELD_PREP(MT_PROT_CFG_CTRL, 1) |		\
1061613c621SLorenzo Bianconi 	 FIELD_PREP(MT_PROT_CFG_NAV, 1) |			\
1071613c621SLorenzo Bianconi 	 FIELD_PREP(MT_PROT_CFG_TXOP_ALLOW, 0x3f))
1081613c621SLorenzo Bianconi 
1091613c621SLorenzo Bianconi 	static const struct mt76_reg_pair vals[] = {
1101613c621SLorenzo Bianconi 		/* Copied from MediaTek reference source */
1111613c621SLorenzo Bianconi 		{ MT_PBF_SYS_CTRL,		0x00080c00 },
1121613c621SLorenzo Bianconi 		{ MT_PBF_CFG,			0x1efebcff },
1131613c621SLorenzo Bianconi 		{ MT_FCE_PSE_CTRL,		0x00000001 },
114049019c2SFelix Fietkau 		{ MT_MAC_SYS_CTRL,		0x00000000 },
1151613c621SLorenzo Bianconi 		{ MT_MAX_LEN_CFG,		0x003e3f00 },
1161613c621SLorenzo Bianconi 		{ MT_AMPDU_MAX_LEN_20M1S,	0xaaa99887 },
1171613c621SLorenzo Bianconi 		{ MT_AMPDU_MAX_LEN_20M2S,	0x000000aa },
1181613c621SLorenzo Bianconi 		{ MT_XIFS_TIME_CFG,		0x33a40d0a },
1191613c621SLorenzo Bianconi 		{ MT_BKOFF_SLOT_CFG,		0x00000209 },
1201613c621SLorenzo Bianconi 		{ MT_TBTT_SYNC_CFG,		0x00422010 },
1211613c621SLorenzo Bianconi 		{ MT_PWR_PIN_CFG,		0x00000000 },
1221613c621SLorenzo Bianconi 		{ 0x1238,			0x001700c8 },
1231613c621SLorenzo Bianconi 		{ MT_TX_SW_CFG0,		0x00101001 },
1241613c621SLorenzo Bianconi 		{ MT_TX_SW_CFG1,		0x00010000 },
1251613c621SLorenzo Bianconi 		{ MT_TX_SW_CFG2,		0x00000000 },
1261613c621SLorenzo Bianconi 		{ MT_TXOP_CTRL_CFG,		0x0400583f },
1277dfc45e6SStanislaw Gruszka 		{ MT_TX_RTS_CFG,		0x00ffff20 },
1281613c621SLorenzo Bianconi 		{ MT_TX_TIMEOUT_CFG,		0x000a2290 },
1291613c621SLorenzo Bianconi 		{ MT_TX_RETRY_CFG,		0x47f01f0f },
1301613c621SLorenzo Bianconi 		{ MT_EXP_ACK_TIME,		0x002c00dc },
1311613c621SLorenzo Bianconi 		{ MT_TX_PROT_CFG6,		0xe3f42004 },
1321613c621SLorenzo Bianconi 		{ MT_TX_PROT_CFG7,		0xe3f42084 },
1331613c621SLorenzo Bianconi 		{ MT_TX_PROT_CFG8,		0xe3f42104 },
1341613c621SLorenzo Bianconi 		{ MT_PIFS_TX_CFG,		0x00060fff },
1351613c621SLorenzo Bianconi 		{ MT_RX_FILTR_CFG,		0x00015f97 },
1361613c621SLorenzo Bianconi 		{ MT_LEGACY_BASIC_RATE,		0x0000017f },
1371613c621SLorenzo Bianconi 		{ MT_HT_BASIC_RATE,		0x00004003 },
1381613c621SLorenzo Bianconi 		{ MT_PN_PAD_MODE,		0x00000003 },
1391613c621SLorenzo Bianconi 		{ MT_TXOP_HLDR_ET,		0x00000002 },
1401613c621SLorenzo Bianconi 		{ 0xa44,			0x00000000 },
1411613c621SLorenzo Bianconi 		{ MT_HEADER_TRANS_CTRL_REG,	0x00000000 },
1421613c621SLorenzo Bianconi 		{ MT_TSO_CTRL,			0x00000000 },
1431613c621SLorenzo Bianconi 		{ MT_AUX_CLK_CFG,		0x00000000 },
1441613c621SLorenzo Bianconi 		{ MT_DACCLK_EN_DLY_CFG,		0x00000000 },
1451613c621SLorenzo Bianconi 		{ MT_TX_ALC_CFG_4,		0x00000000 },
1461613c621SLorenzo Bianconi 		{ MT_TX_ALC_VGA3,		0x00000000 },
1471613c621SLorenzo Bianconi 		{ MT_TX_PWR_CFG_0,		0x3a3a3a3a },
1481613c621SLorenzo Bianconi 		{ MT_TX_PWR_CFG_1,		0x3a3a3a3a },
1491613c621SLorenzo Bianconi 		{ MT_TX_PWR_CFG_2,		0x3a3a3a3a },
1501613c621SLorenzo Bianconi 		{ MT_TX_PWR_CFG_3,		0x3a3a3a3a },
1511613c621SLorenzo Bianconi 		{ MT_TX_PWR_CFG_4,		0x3a3a3a3a },
1521613c621SLorenzo Bianconi 		{ MT_TX_PWR_CFG_7,		0x3a3a3a3a },
1531613c621SLorenzo Bianconi 		{ MT_TX_PWR_CFG_8,		0x0000003a },
1541613c621SLorenzo Bianconi 		{ MT_TX_PWR_CFG_9,		0x0000003a },
1551613c621SLorenzo Bianconi 		{ MT_EFUSE_CTRL,		0x0000d000 },
1561613c621SLorenzo Bianconi 		{ MT_PAUSE_ENABLE_CONTROL1,	0x0000000a },
1571613c621SLorenzo Bianconi 		{ MT_FCE_WLAN_FLOW_CONTROL1,	0x60401c18 },
1581613c621SLorenzo Bianconi 		{ MT_WPDMA_DELAY_INT_CFG,	0x94ff0000 },
1591613c621SLorenzo Bianconi 		{ MT_TX_SW_CFG3,		0x00000004 },
1601613c621SLorenzo Bianconi 		{ MT_HT_FBK_TO_LEGACY,		0x00001818 },
1611613c621SLorenzo Bianconi 		{ MT_VHT_HT_FBK_CFG1,		0xedcba980 },
1621613c621SLorenzo Bianconi 		{ MT_PROT_AUTO_TX_CFG,		0x00830083 },
1631613c621SLorenzo Bianconi 		{ MT_HT_CTRL_CFG,		0x000001ff },
1643fd612dfSLorenzo Bianconi 		{ MT_TX_LINK_CFG,		0x00001020 },
1651613c621SLorenzo Bianconi 	};
1661613c621SLorenzo Bianconi 	struct mt76_reg_pair prot_vals[] = {
1671613c621SLorenzo Bianconi 		{ MT_CCK_PROT_CFG,		DEFAULT_PROT_CFG_CCK },
1681613c621SLorenzo Bianconi 		{ MT_OFDM_PROT_CFG,		DEFAULT_PROT_CFG_OFDM },
1691613c621SLorenzo Bianconi 		{ MT_MM20_PROT_CFG,		DEFAULT_PROT_CFG_20 },
1701613c621SLorenzo Bianconi 		{ MT_MM40_PROT_CFG,		DEFAULT_PROT_CFG_40 },
1711613c621SLorenzo Bianconi 		{ MT_GF20_PROT_CFG,		DEFAULT_PROT_CFG_20 },
1721613c621SLorenzo Bianconi 		{ MT_GF40_PROT_CFG,		DEFAULT_PROT_CFG_40 },
1731613c621SLorenzo Bianconi 	};
1741613c621SLorenzo Bianconi 
1751613c621SLorenzo Bianconi 	mt76_wr_rp(dev, 0, vals, ARRAY_SIZE(vals));
1761613c621SLorenzo Bianconi 	mt76_wr_rp(dev, 0, prot_vals, ARRAY_SIZE(prot_vals));
1771613c621SLorenzo Bianconi }
1781613c621SLorenzo Bianconi EXPORT_SYMBOL_GPL(mt76_write_mac_initvals);
1791613c621SLorenzo Bianconi 
mt76x2_init_txpower(struct mt76x02_dev * dev,struct ieee80211_supported_band * sband)180e40803f2SLorenzo Bianconi void mt76x2_init_txpower(struct mt76x02_dev *dev,
1811613c621SLorenzo Bianconi 			 struct ieee80211_supported_band *sband)
1821613c621SLorenzo Bianconi {
1831613c621SLorenzo Bianconi 	struct ieee80211_channel *chan;
1841613c621SLorenzo Bianconi 	struct mt76x2_tx_power_info txp;
185*b376d963SFelix Fietkau 	struct mt76x02_rate_power t = {};
1861613c621SLorenzo Bianconi 	int i;
1871613c621SLorenzo Bianconi 
1881613c621SLorenzo Bianconi 	for (i = 0; i < sband->n_channels; i++) {
1891613c621SLorenzo Bianconi 		chan = &sband->channels[i];
1901613c621SLorenzo Bianconi 
1911613c621SLorenzo Bianconi 		mt76x2_get_power_info(dev, &txp, chan);
1921613c621SLorenzo Bianconi 		mt76x2_get_rate_power(dev, &t, chan);
1931613c621SLorenzo Bianconi 
19409952572SFelix Fietkau 		chan->orig_mpwr = mt76x02_get_max_rate_power(&t) +
195cee646d6SFelix Fietkau 				  txp.target_power;
19609952572SFelix Fietkau 		chan->orig_mpwr = DIV_ROUND_UP(chan->orig_mpwr, 2);
1971613c621SLorenzo Bianconi 
1981613c621SLorenzo Bianconi 		/* convert to combined output power on 2x2 devices */
19909952572SFelix Fietkau 		chan->orig_mpwr += 3;
20009952572SFelix Fietkau 		chan->max_power = min_t(int, chan->max_reg_power,
20109952572SFelix Fietkau 					chan->orig_mpwr);
2021613c621SLorenzo Bianconi 	}
2031613c621SLorenzo Bianconi }
2041613c621SLorenzo Bianconi EXPORT_SYMBOL_GPL(mt76x2_init_txpower);
205