17f17b86aSRyder Lee // SPDX-License-Identifier: ISC
2c8846e10SFelix Fietkau 
3c8846e10SFelix Fietkau #include <linux/firmware.h>
4c8846e10SFelix Fietkau #include "mt7603.h"
5c8846e10SFelix Fietkau #include "mcu.h"
6c8846e10SFelix Fietkau #include "eeprom.h"
7c8846e10SFelix Fietkau 
8c8846e10SFelix Fietkau #define MCU_SKB_RESERVE	8
9c8846e10SFelix Fietkau 
10c8846e10SFelix Fietkau struct mt7603_fw_trailer {
11c8846e10SFelix Fietkau 	char fw_ver[10];
12c8846e10SFelix Fietkau 	char build_date[15];
13c8846e10SFelix Fietkau 	__le32 dl_len;
14c8846e10SFelix Fietkau } __packed;
15c8846e10SFelix Fietkau 
16c8846e10SFelix Fietkau static int
17114fe5e3SLorenzo Bianconi __mt7603_mcu_msg_send(struct mt7603_dev *dev, struct sk_buff *skb,
18114fe5e3SLorenzo Bianconi 		      int cmd, int *wait_seq)
19c8846e10SFelix Fietkau {
20c8846e10SFelix Fietkau 	int hdrlen = dev->mcu_running ? sizeof(struct mt7603_mcu_txd) : 12;
21c8846e10SFelix Fietkau 	struct mt76_dev *mdev = &dev->mt76;
22c8846e10SFelix Fietkau 	struct mt7603_mcu_txd *txd;
23c8846e10SFelix Fietkau 	u8 seq;
24c8846e10SFelix Fietkau 
2509872957SLorenzo Bianconi 	seq = ++mdev->mcu.msg_seq & 0xf;
26c8846e10SFelix Fietkau 	if (!seq)
2709872957SLorenzo Bianconi 		seq = ++mdev->mcu.msg_seq & 0xf;
28c8846e10SFelix Fietkau 
29c8846e10SFelix Fietkau 	txd = (struct mt7603_mcu_txd *)skb_push(skb, hdrlen);
30c8846e10SFelix Fietkau 
31c8846e10SFelix Fietkau 	txd->len = cpu_to_le16(skb->len);
32c8846e10SFelix Fietkau 	if (cmd == -MCU_CMD_FW_SCATTER)
33c8846e10SFelix Fietkau 		txd->pq_id = cpu_to_le16(MCU_PORT_QUEUE_FW);
34c8846e10SFelix Fietkau 	else
35c8846e10SFelix Fietkau 		txd->pq_id = cpu_to_le16(MCU_PORT_QUEUE);
36c8846e10SFelix Fietkau 	txd->pkt_type = MCU_PKT_ID;
37c8846e10SFelix Fietkau 	txd->seq = seq;
38c8846e10SFelix Fietkau 
39c8846e10SFelix Fietkau 	if (cmd < 0) {
40c8846e10SFelix Fietkau 		txd->cid = -cmd;
41114fe5e3SLorenzo Bianconi 		txd->set_query = MCU_Q_NA;
42c8846e10SFelix Fietkau 	} else {
43c8846e10SFelix Fietkau 		txd->cid = MCU_CMD_EXT_CID;
44c8846e10SFelix Fietkau 		txd->ext_cid = cmd;
45114fe5e3SLorenzo Bianconi 		txd->set_query = MCU_Q_SET;
46c8846e10SFelix Fietkau 		txd->ext_cid_ack = 1;
47c8846e10SFelix Fietkau 	}
48c8846e10SFelix Fietkau 
49c8846e10SFelix Fietkau 	if (wait_seq)
50c8846e10SFelix Fietkau 		*wait_seq = seq;
51c8846e10SFelix Fietkau 
52c8846e10SFelix Fietkau 	return mt76_tx_queue_skb_raw(dev, MT_TXQ_MCU, skb, 0);
53c8846e10SFelix Fietkau }
54c8846e10SFelix Fietkau 
55c8846e10SFelix Fietkau static int
56cc173875SLorenzo Bianconi mt7603_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data,
5711ca82d7SLorenzo Bianconi 		    int len, bool wait_resp)
58c8846e10SFelix Fietkau {
59cc173875SLorenzo Bianconi 	struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76);
60c8846e10SFelix Fietkau 	unsigned long expires = jiffies + 3 * HZ;
61c8846e10SFelix Fietkau 	struct mt7603_mcu_rxd *rxd;
6211ca82d7SLorenzo Bianconi 	struct sk_buff *skb;
63c8846e10SFelix Fietkau 	int ret, seq;
64c8846e10SFelix Fietkau 
65bb31a80eSLorenzo Bianconi 	skb = mt76_mcu_msg_alloc(mdev, data, len);
6611ca82d7SLorenzo Bianconi 	if (!skb)
6711ca82d7SLorenzo Bianconi 		return -ENOMEM;
6811ca82d7SLorenzo Bianconi 
6909872957SLorenzo Bianconi 	mutex_lock(&mdev->mcu.mutex);
70c8846e10SFelix Fietkau 
71114fe5e3SLorenzo Bianconi 	ret = __mt7603_mcu_msg_send(dev, skb, cmd, &seq);
72c8846e10SFelix Fietkau 	if (ret)
73c8846e10SFelix Fietkau 		goto out;
74c8846e10SFelix Fietkau 
7511ca82d7SLorenzo Bianconi 	while (wait_resp) {
76c8846e10SFelix Fietkau 		bool check_seq = false;
77c8846e10SFelix Fietkau 
78c8846e10SFelix Fietkau 		skb = mt76_mcu_get_response(&dev->mt76, expires);
79c8846e10SFelix Fietkau 		if (!skb) {
80c8846e10SFelix Fietkau 			dev_err(mdev->dev,
81c8846e10SFelix Fietkau 				"MCU message %d (seq %d) timed out\n",
82c8846e10SFelix Fietkau 				cmd, seq);
83c8846e10SFelix Fietkau 			dev->mcu_hang = MT7603_WATCHDOG_TIMEOUT;
84c8846e10SFelix Fietkau 			ret = -ETIMEDOUT;
85c8846e10SFelix Fietkau 			break;
86c8846e10SFelix Fietkau 		}
87c8846e10SFelix Fietkau 
88c8846e10SFelix Fietkau 		rxd = (struct mt7603_mcu_rxd *)skb->data;
89c8846e10SFelix Fietkau 		if (seq == rxd->seq)
90c8846e10SFelix Fietkau 			check_seq = true;
91c8846e10SFelix Fietkau 
92c8846e10SFelix Fietkau 		dev_kfree_skb(skb);
93c8846e10SFelix Fietkau 
94c8846e10SFelix Fietkau 		if (check_seq)
95c8846e10SFelix Fietkau 			break;
96c8846e10SFelix Fietkau 	}
97c8846e10SFelix Fietkau 
98c8846e10SFelix Fietkau out:
9909872957SLorenzo Bianconi 	mutex_unlock(&mdev->mcu.mutex);
100c8846e10SFelix Fietkau 
101c8846e10SFelix Fietkau 	return ret;
102c8846e10SFelix Fietkau }
103c8846e10SFelix Fietkau 
104c8846e10SFelix Fietkau static int
105c8846e10SFelix Fietkau mt7603_mcu_init_download(struct mt7603_dev *dev, u32 addr, u32 len)
106c8846e10SFelix Fietkau {
107c8846e10SFelix Fietkau 	struct {
108c8846e10SFelix Fietkau 		__le32 addr;
109c8846e10SFelix Fietkau 		__le32 len;
110c8846e10SFelix Fietkau 		__le32 mode;
111c8846e10SFelix Fietkau 	} req = {
112c8846e10SFelix Fietkau 		.addr = cpu_to_le32(addr),
113c8846e10SFelix Fietkau 		.len = cpu_to_le32(len),
114c8846e10SFelix Fietkau 		.mode = cpu_to_le32(BIT(31)),
115c8846e10SFelix Fietkau 	};
116c8846e10SFelix Fietkau 
117cc173875SLorenzo Bianconi 	return __mt76_mcu_send_msg(&dev->mt76, -MCU_CMD_TARGET_ADDRESS_LEN_REQ,
11811ca82d7SLorenzo Bianconi 				   &req, sizeof(req), true);
119c8846e10SFelix Fietkau }
120c8846e10SFelix Fietkau 
121c8846e10SFelix Fietkau static int
122c8846e10SFelix Fietkau mt7603_mcu_send_firmware(struct mt7603_dev *dev, const void *data, int len)
123c8846e10SFelix Fietkau {
124d422bb26SLorenzo Bianconi 	int cur_len, ret = 0;
125c8846e10SFelix Fietkau 
126c8846e10SFelix Fietkau 	while (len > 0) {
127d422bb26SLorenzo Bianconi 		cur_len = min_t(int, 4096 - sizeof(struct mt7603_mcu_txd),
128c8846e10SFelix Fietkau 				len);
129c8846e10SFelix Fietkau 
130d422bb26SLorenzo Bianconi 		ret = __mt76_mcu_send_msg(&dev->mt76, -MCU_CMD_FW_SCATTER,
131d422bb26SLorenzo Bianconi 					  data, cur_len, false);
132c8846e10SFelix Fietkau 		if (ret)
133c8846e10SFelix Fietkau 			break;
134c8846e10SFelix Fietkau 
135c8846e10SFelix Fietkau 		data += cur_len;
136c8846e10SFelix Fietkau 		len -= cur_len;
137c8846e10SFelix Fietkau 	}
138c8846e10SFelix Fietkau 
139c8846e10SFelix Fietkau 	return ret;
140c8846e10SFelix Fietkau }
141c8846e10SFelix Fietkau 
142c8846e10SFelix Fietkau static int
143c8846e10SFelix Fietkau mt7603_mcu_start_firmware(struct mt7603_dev *dev, u32 addr)
144c8846e10SFelix Fietkau {
145c8846e10SFelix Fietkau 	struct {
146c8846e10SFelix Fietkau 		__le32 override;
147c8846e10SFelix Fietkau 		__le32 addr;
148c8846e10SFelix Fietkau 	} req = {
149c8846e10SFelix Fietkau 		.override = cpu_to_le32(addr ? 1 : 0),
150c8846e10SFelix Fietkau 		.addr = cpu_to_le32(addr),
151c8846e10SFelix Fietkau 	};
152c8846e10SFelix Fietkau 
153cc173875SLorenzo Bianconi 	return __mt76_mcu_send_msg(&dev->mt76, -MCU_CMD_FW_START_REQ,
15411ca82d7SLorenzo Bianconi 				   &req, sizeof(req), true);
155c8846e10SFelix Fietkau }
156c8846e10SFelix Fietkau 
157c8846e10SFelix Fietkau static int
158a4834814SLorenzo Bianconi mt7603_mcu_restart(struct mt76_dev *dev)
159c8846e10SFelix Fietkau {
160a4834814SLorenzo Bianconi 	return __mt76_mcu_send_msg(dev, -MCU_CMD_RESTART_DL_REQ,
16111ca82d7SLorenzo Bianconi 				   NULL, 0, true);
162c8846e10SFelix Fietkau }
163c8846e10SFelix Fietkau 
164cc173875SLorenzo Bianconi static int mt7603_load_firmware(struct mt7603_dev *dev)
165c8846e10SFelix Fietkau {
166c8846e10SFelix Fietkau 	const struct firmware *fw;
167c8846e10SFelix Fietkau 	const struct mt7603_fw_trailer *hdr;
168c8846e10SFelix Fietkau 	const char *firmware;
169c8846e10SFelix Fietkau 	int dl_len;
170c8846e10SFelix Fietkau 	u32 addr, val;
171c8846e10SFelix Fietkau 	int ret;
172c8846e10SFelix Fietkau 
173c8846e10SFelix Fietkau 	if (is_mt7628(dev)) {
174c8846e10SFelix Fietkau 		if (mt76xx_rev(dev) == MT7628_REV_E1)
175c8846e10SFelix Fietkau 			firmware = MT7628_FIRMWARE_E1;
176c8846e10SFelix Fietkau 		else
177c8846e10SFelix Fietkau 			firmware = MT7628_FIRMWARE_E2;
178c8846e10SFelix Fietkau 	} else {
179c8846e10SFelix Fietkau 		if (mt76xx_rev(dev) < MT7603_REV_E2)
180c8846e10SFelix Fietkau 			firmware = MT7603_FIRMWARE_E1;
181c8846e10SFelix Fietkau 		else
182c8846e10SFelix Fietkau 			firmware = MT7603_FIRMWARE_E2;
183c8846e10SFelix Fietkau 	}
184c8846e10SFelix Fietkau 
185c8846e10SFelix Fietkau 	ret = request_firmware(&fw, firmware, dev->mt76.dev);
186c8846e10SFelix Fietkau 	if (ret)
187c8846e10SFelix Fietkau 		return ret;
188c8846e10SFelix Fietkau 
189c8846e10SFelix Fietkau 	if (!fw || !fw->data || fw->size < sizeof(*hdr)) {
190c8846e10SFelix Fietkau 		dev_err(dev->mt76.dev, "Invalid firmware\n");
191c8846e10SFelix Fietkau 		ret = -EINVAL;
192c8846e10SFelix Fietkau 		goto out;
193c8846e10SFelix Fietkau 	}
194c8846e10SFelix Fietkau 
195c8846e10SFelix Fietkau 	hdr = (const struct mt7603_fw_trailer *)(fw->data + fw->size -
196c8846e10SFelix Fietkau 						 sizeof(*hdr));
197c8846e10SFelix Fietkau 
198c8846e10SFelix Fietkau 	dev_info(dev->mt76.dev, "Firmware Version: %.10s\n", hdr->fw_ver);
199c8846e10SFelix Fietkau 	dev_info(dev->mt76.dev, "Build Time: %.15s\n", hdr->build_date);
200c8846e10SFelix Fietkau 
201c8846e10SFelix Fietkau 	addr = mt7603_reg_map(dev, 0x50012498);
202c8846e10SFelix Fietkau 	mt76_wr(dev, addr, 0x5);
203c8846e10SFelix Fietkau 	mt76_wr(dev, addr, 0x5);
204c8846e10SFelix Fietkau 	udelay(1);
205c8846e10SFelix Fietkau 
206c8846e10SFelix Fietkau 	/* switch to bypass mode */
207c8846e10SFelix Fietkau 	mt76_rmw(dev, MT_SCH_4, MT_SCH_4_FORCE_QID,
208c8846e10SFelix Fietkau 		 MT_SCH_4_BYPASS | FIELD_PREP(MT_SCH_4_FORCE_QID, 5));
209c8846e10SFelix Fietkau 
210c8846e10SFelix Fietkau 	val = mt76_rr(dev, MT_TOP_MISC2);
211c8846e10SFelix Fietkau 	if (val & BIT(1)) {
212c8846e10SFelix Fietkau 		dev_info(dev->mt76.dev, "Firmware already running...\n");
213c8846e10SFelix Fietkau 		goto running;
214c8846e10SFelix Fietkau 	}
215c8846e10SFelix Fietkau 
216c8846e10SFelix Fietkau 	if (!mt76_poll_msec(dev, MT_TOP_MISC2, BIT(0) | BIT(1), BIT(0), 500)) {
217c8846e10SFelix Fietkau 		dev_err(dev->mt76.dev, "Timeout waiting for ROM code to become ready\n");
218c8846e10SFelix Fietkau 		ret = -EIO;
219c8846e10SFelix Fietkau 		goto out;
220c8846e10SFelix Fietkau 	}
221c8846e10SFelix Fietkau 
222c8846e10SFelix Fietkau 	dl_len = le32_to_cpu(hdr->dl_len) + 4;
223c8846e10SFelix Fietkau 	ret = mt7603_mcu_init_download(dev, MCU_FIRMWARE_ADDRESS, dl_len);
224c8846e10SFelix Fietkau 	if (ret) {
225c8846e10SFelix Fietkau 		dev_err(dev->mt76.dev, "Download request failed\n");
226c8846e10SFelix Fietkau 		goto out;
227c8846e10SFelix Fietkau 	}
228c8846e10SFelix Fietkau 
229c8846e10SFelix Fietkau 	ret = mt7603_mcu_send_firmware(dev, fw->data, dl_len);
230c8846e10SFelix Fietkau 	if (ret) {
231c8846e10SFelix Fietkau 		dev_err(dev->mt76.dev, "Failed to send firmware to device\n");
232c8846e10SFelix Fietkau 		goto out;
233c8846e10SFelix Fietkau 	}
234c8846e10SFelix Fietkau 
235c8846e10SFelix Fietkau 	ret = mt7603_mcu_start_firmware(dev, MCU_FIRMWARE_ADDRESS);
236c8846e10SFelix Fietkau 	if (ret) {
237c8846e10SFelix Fietkau 		dev_err(dev->mt76.dev, "Failed to start firmware\n");
238c8846e10SFelix Fietkau 		goto out;
239c8846e10SFelix Fietkau 	}
240c8846e10SFelix Fietkau 
241c8846e10SFelix Fietkau 	if (!mt76_poll_msec(dev, MT_TOP_MISC2, BIT(1), BIT(1), 500)) {
242c8846e10SFelix Fietkau 		dev_err(dev->mt76.dev, "Timeout waiting for firmware to initialize\n");
243c8846e10SFelix Fietkau 		ret = -EIO;
244c8846e10SFelix Fietkau 		goto out;
245c8846e10SFelix Fietkau 	}
246c8846e10SFelix Fietkau 
247c8846e10SFelix Fietkau running:
248c8846e10SFelix Fietkau 	mt76_clear(dev, MT_SCH_4, MT_SCH_4_FORCE_QID | MT_SCH_4_BYPASS);
249c8846e10SFelix Fietkau 
250c8846e10SFelix Fietkau 	mt76_set(dev, MT_SCH_4, BIT(8));
251c8846e10SFelix Fietkau 	mt76_clear(dev, MT_SCH_4, BIT(8));
252c8846e10SFelix Fietkau 
253c8846e10SFelix Fietkau 	dev->mcu_running = true;
2544d0fe26fSLorenzo Bianconi 	snprintf(dev->mt76.hw->wiphy->fw_version,
2554d0fe26fSLorenzo Bianconi 		 sizeof(dev->mt76.hw->wiphy->fw_version),
2564d0fe26fSLorenzo Bianconi 		 "%.10s-%.15s", hdr->fw_ver, hdr->build_date);
257c8846e10SFelix Fietkau 	dev_info(dev->mt76.dev, "firmware init done\n");
258c8846e10SFelix Fietkau 
259c8846e10SFelix Fietkau out:
260c8846e10SFelix Fietkau 	release_firmware(fw);
261c8846e10SFelix Fietkau 
262c8846e10SFelix Fietkau 	return ret;
263c8846e10SFelix Fietkau }
264c8846e10SFelix Fietkau 
265cc173875SLorenzo Bianconi int mt7603_mcu_init(struct mt7603_dev *dev)
266cc173875SLorenzo Bianconi {
267cc173875SLorenzo Bianconi 	static const struct mt76_mcu_ops mt7603_mcu_ops = {
268bb31a80eSLorenzo Bianconi 		.headroom = sizeof(struct mt7603_mcu_txd),
269cc173875SLorenzo Bianconi 		.mcu_send_msg = mt7603_mcu_msg_send,
270a4834814SLorenzo Bianconi 		.mcu_restart = mt7603_mcu_restart,
271cc173875SLorenzo Bianconi 	};
272cc173875SLorenzo Bianconi 
273cc173875SLorenzo Bianconi 	dev->mt76.mcu_ops = &mt7603_mcu_ops;
274cc173875SLorenzo Bianconi 	return mt7603_load_firmware(dev);
275cc173875SLorenzo Bianconi }
276cc173875SLorenzo Bianconi 
277c8846e10SFelix Fietkau void mt7603_mcu_exit(struct mt7603_dev *dev)
278c8846e10SFelix Fietkau {
279a4834814SLorenzo Bianconi 	__mt76_mcu_restart(&dev->mt76);
28009872957SLorenzo Bianconi 	skb_queue_purge(&dev->mt76.mcu.res_q);
281c8846e10SFelix Fietkau }
282c8846e10SFelix Fietkau 
283c8846e10SFelix Fietkau int mt7603_mcu_set_eeprom(struct mt7603_dev *dev)
284c8846e10SFelix Fietkau {
285c8846e10SFelix Fietkau 	static const u16 req_fields[] = {
286c8846e10SFelix Fietkau #define WORD(_start)			\
287c8846e10SFelix Fietkau 		_start,			\
288c8846e10SFelix Fietkau 		_start + 1
289c8846e10SFelix Fietkau #define GROUP_2G(_start)		\
290c8846e10SFelix Fietkau 		WORD(_start),		\
291c8846e10SFelix Fietkau 		WORD(_start + 2),	\
292c8846e10SFelix Fietkau 		WORD(_start + 4)
293c8846e10SFelix Fietkau 
294c8846e10SFelix Fietkau 		MT_EE_NIC_CONF_0 + 1,
295c8846e10SFelix Fietkau 		WORD(MT_EE_NIC_CONF_1),
296c8846e10SFelix Fietkau 		MT_EE_WIFI_RF_SETTING,
297c8846e10SFelix Fietkau 		MT_EE_TX_POWER_DELTA_BW40,
298c8846e10SFelix Fietkau 		MT_EE_TX_POWER_DELTA_BW80 + 1,
299c8846e10SFelix Fietkau 		MT_EE_TX_POWER_EXT_PA_5G,
300c8846e10SFelix Fietkau 		MT_EE_TEMP_SENSOR_CAL,
301c8846e10SFelix Fietkau 		GROUP_2G(MT_EE_TX_POWER_0_START_2G),
302c8846e10SFelix Fietkau 		GROUP_2G(MT_EE_TX_POWER_1_START_2G),
303c8846e10SFelix Fietkau 		WORD(MT_EE_TX_POWER_CCK),
304c8846e10SFelix Fietkau 		WORD(MT_EE_TX_POWER_OFDM_2G_6M),
305c8846e10SFelix Fietkau 		WORD(MT_EE_TX_POWER_OFDM_2G_24M),
306c8846e10SFelix Fietkau 		WORD(MT_EE_TX_POWER_OFDM_2G_54M),
307c8846e10SFelix Fietkau 		WORD(MT_EE_TX_POWER_HT_BPSK_QPSK),
308c8846e10SFelix Fietkau 		WORD(MT_EE_TX_POWER_HT_16_64_QAM),
309c8846e10SFelix Fietkau 		WORD(MT_EE_TX_POWER_HT_64_QAM),
310c8846e10SFelix Fietkau 		MT_EE_ELAN_RX_MODE_GAIN,
311c8846e10SFelix Fietkau 		MT_EE_ELAN_RX_MODE_NF,
312c8846e10SFelix Fietkau 		MT_EE_ELAN_RX_MODE_P1DB,
313c8846e10SFelix Fietkau 		MT_EE_ELAN_BYPASS_MODE_GAIN,
314c8846e10SFelix Fietkau 		MT_EE_ELAN_BYPASS_MODE_NF,
315c8846e10SFelix Fietkau 		MT_EE_ELAN_BYPASS_MODE_P1DB,
316c8846e10SFelix Fietkau 		WORD(MT_EE_STEP_NUM_NEG_6_7),
317c8846e10SFelix Fietkau 		WORD(MT_EE_STEP_NUM_NEG_4_5),
318c8846e10SFelix Fietkau 		WORD(MT_EE_STEP_NUM_NEG_2_3),
319c8846e10SFelix Fietkau 		WORD(MT_EE_STEP_NUM_NEG_0_1),
320c8846e10SFelix Fietkau 		WORD(MT_EE_REF_STEP_24G),
321c8846e10SFelix Fietkau 		WORD(MT_EE_STEP_NUM_PLUS_1_2),
322c8846e10SFelix Fietkau 		WORD(MT_EE_STEP_NUM_PLUS_3_4),
323c8846e10SFelix Fietkau 		WORD(MT_EE_STEP_NUM_PLUS_5_6),
324c8846e10SFelix Fietkau 		MT_EE_STEP_NUM_PLUS_7,
325c8846e10SFelix Fietkau 		MT_EE_XTAL_FREQ_OFFSET,
326c8846e10SFelix Fietkau 		MT_EE_XTAL_TRIM_2_COMP,
327c8846e10SFelix Fietkau 		MT_EE_XTAL_TRIM_3_COMP,
328c8846e10SFelix Fietkau 		MT_EE_XTAL_WF_RFCAL,
329c8846e10SFelix Fietkau 
330c8846e10SFelix Fietkau 		/* unknown fields below */
331c8846e10SFelix Fietkau 		WORD(0x24),
332c8846e10SFelix Fietkau 		0x34,
333c8846e10SFelix Fietkau 		0x39,
334c8846e10SFelix Fietkau 		0x3b,
335c8846e10SFelix Fietkau 		WORD(0x42),
336c8846e10SFelix Fietkau 		WORD(0x9e),
337c8846e10SFelix Fietkau 		0xf2,
338c8846e10SFelix Fietkau 		WORD(0xf8),
339c8846e10SFelix Fietkau 		0xfa,
340c8846e10SFelix Fietkau 		0x12e,
341c8846e10SFelix Fietkau 		WORD(0x130), WORD(0x132), WORD(0x134), WORD(0x136),
342c8846e10SFelix Fietkau 		WORD(0x138), WORD(0x13a), WORD(0x13c), WORD(0x13e),
343c8846e10SFelix Fietkau 
344c8846e10SFelix Fietkau #undef GROUP_2G
345c8846e10SFelix Fietkau #undef WORD
346c8846e10SFelix Fietkau 
347c8846e10SFelix Fietkau 	};
348c8846e10SFelix Fietkau 	struct req_data {
349676fabd1SLorenzo Bianconi 		__le16 addr;
350c8846e10SFelix Fietkau 		u8 val;
351c8846e10SFelix Fietkau 		u8 pad;
352c8846e10SFelix Fietkau 	} __packed;
353c8846e10SFelix Fietkau 	struct {
354c8846e10SFelix Fietkau 		u8 buffer_mode;
355c8846e10SFelix Fietkau 		u8 len;
356c8846e10SFelix Fietkau 		u8 pad[2];
3574d2a6f7bSLorenzo Bianconi 	} req_hdr = {
358c8846e10SFelix Fietkau 		.buffer_mode = 1,
359c8846e10SFelix Fietkau 		.len = ARRAY_SIZE(req_fields) - 1,
360c8846e10SFelix Fietkau 	};
3614d2a6f7bSLorenzo Bianconi 	const int size = 0xff * sizeof(struct req_data);
3624d2a6f7bSLorenzo Bianconi 	u8 *req, *eep = (u8 *)dev->mt76.eeprom.data;
3634d2a6f7bSLorenzo Bianconi 	int i, ret, len = sizeof(req_hdr) + size;
3644d2a6f7bSLorenzo Bianconi 	struct req_data *data;
365c8846e10SFelix Fietkau 
3664d2a6f7bSLorenzo Bianconi 	BUILD_BUG_ON(ARRAY_SIZE(req_fields) * sizeof(*data) > size);
367c8846e10SFelix Fietkau 
3684d2a6f7bSLorenzo Bianconi 	req = kmalloc(len, GFP_KERNEL);
3694d2a6f7bSLorenzo Bianconi 	if (!req)
3704d2a6f7bSLorenzo Bianconi 		return -ENOMEM;
3714d2a6f7bSLorenzo Bianconi 
3724d2a6f7bSLorenzo Bianconi 	memcpy(req, &req_hdr, sizeof(req_hdr));
3734d2a6f7bSLorenzo Bianconi 	data = (struct req_data *)(req + sizeof(req_hdr));
3744d2a6f7bSLorenzo Bianconi 	memset(data, 0, size);
375c8846e10SFelix Fietkau 	for (i = 0; i < ARRAY_SIZE(req_fields); i++) {
3764d2a6f7bSLorenzo Bianconi 		data[i].addr = cpu_to_le16(req_fields[i]);
3774d2a6f7bSLorenzo Bianconi 		data[i].val = eep[req_fields[i]];
378c8846e10SFelix Fietkau 	}
379c8846e10SFelix Fietkau 
3804d2a6f7bSLorenzo Bianconi 	ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_EFUSE_BUFFER_MODE,
3814d2a6f7bSLorenzo Bianconi 				  req, len, true);
3824d2a6f7bSLorenzo Bianconi 	kfree(req);
3834d2a6f7bSLorenzo Bianconi 
3844d2a6f7bSLorenzo Bianconi 	return ret;
385c8846e10SFelix Fietkau }
386c8846e10SFelix Fietkau 
387c8846e10SFelix Fietkau static int mt7603_mcu_set_tx_power(struct mt7603_dev *dev)
388c8846e10SFelix Fietkau {
389c8846e10SFelix Fietkau 	struct {
390c8846e10SFelix Fietkau 		u8 center_channel;
391c8846e10SFelix Fietkau 		u8 tssi;
392c8846e10SFelix Fietkau 		u8 temp_comp;
393c8846e10SFelix Fietkau 		u8 target_power[2];
394c8846e10SFelix Fietkau 		u8 rate_power_delta[14];
395c8846e10SFelix Fietkau 		u8 bw_power_delta;
396c8846e10SFelix Fietkau 		u8 ch_power_delta[6];
397c8846e10SFelix Fietkau 		u8 temp_comp_power[17];
398c8846e10SFelix Fietkau 		u8 reserved;
399c8846e10SFelix Fietkau 	} req = {
40096747a51SFelix Fietkau 		.center_channel = dev->mphy.chandef.chan->hw_value,
401c8846e10SFelix Fietkau #define EEP_VAL(n) ((u8 *)dev->mt76.eeprom.data)[n]
402c8846e10SFelix Fietkau 		.tssi = EEP_VAL(MT_EE_NIC_CONF_1 + 1),
403c8846e10SFelix Fietkau 		.temp_comp = EEP_VAL(MT_EE_NIC_CONF_1),
404c8846e10SFelix Fietkau 		.target_power = {
405c8846e10SFelix Fietkau 			EEP_VAL(MT_EE_TX_POWER_0_START_2G + 2),
406c8846e10SFelix Fietkau 			EEP_VAL(MT_EE_TX_POWER_1_START_2G + 2)
407c8846e10SFelix Fietkau 		},
408c8846e10SFelix Fietkau 		.bw_power_delta = EEP_VAL(MT_EE_TX_POWER_DELTA_BW40),
409c8846e10SFelix Fietkau 		.ch_power_delta = {
410c8846e10SFelix Fietkau 			EEP_VAL(MT_EE_TX_POWER_0_START_2G + 3),
411c8846e10SFelix Fietkau 			EEP_VAL(MT_EE_TX_POWER_0_START_2G + 4),
412c8846e10SFelix Fietkau 			EEP_VAL(MT_EE_TX_POWER_0_START_2G + 5),
413c8846e10SFelix Fietkau 			EEP_VAL(MT_EE_TX_POWER_1_START_2G + 3),
414c8846e10SFelix Fietkau 			EEP_VAL(MT_EE_TX_POWER_1_START_2G + 4),
415c8846e10SFelix Fietkau 			EEP_VAL(MT_EE_TX_POWER_1_START_2G + 5)
416c8846e10SFelix Fietkau 		},
417c8846e10SFelix Fietkau #undef EEP_VAL
418c8846e10SFelix Fietkau 	};
419c8846e10SFelix Fietkau 	u8 *eep = (u8 *)dev->mt76.eeprom.data;
420c8846e10SFelix Fietkau 
421c8846e10SFelix Fietkau 	memcpy(req.rate_power_delta, eep + MT_EE_TX_POWER_CCK,
422c8846e10SFelix Fietkau 	       sizeof(req.rate_power_delta));
423c8846e10SFelix Fietkau 
424c8846e10SFelix Fietkau 	memcpy(req.temp_comp_power, eep + MT_EE_STEP_NUM_NEG_6_7,
425c8846e10SFelix Fietkau 	       sizeof(req.temp_comp_power));
426c8846e10SFelix Fietkau 
427cc173875SLorenzo Bianconi 	return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_TX_POWER_CTRL,
42811ca82d7SLorenzo Bianconi 				   &req, sizeof(req), true);
429c8846e10SFelix Fietkau }
430c8846e10SFelix Fietkau 
431c8846e10SFelix Fietkau int mt7603_mcu_set_channel(struct mt7603_dev *dev)
432c8846e10SFelix Fietkau {
43396747a51SFelix Fietkau 	struct cfg80211_chan_def *chandef = &dev->mphy.chandef;
434c8846e10SFelix Fietkau 	struct ieee80211_hw *hw = mt76_hw(dev);
435beaaeb6bSFelix Fietkau 	int n_chains = hweight8(dev->mphy.antenna_mask);
436c8846e10SFelix Fietkau 	struct {
437c8846e10SFelix Fietkau 		u8 control_chan;
438c8846e10SFelix Fietkau 		u8 center_chan;
439c8846e10SFelix Fietkau 		u8 bw;
440c8846e10SFelix Fietkau 		u8 tx_streams;
441c8846e10SFelix Fietkau 		u8 rx_streams;
442c8846e10SFelix Fietkau 		u8 _res0[7];
443c8846e10SFelix Fietkau 		u8 txpower[21];
444c8846e10SFelix Fietkau 		u8 _res1[3];
445c8846e10SFelix Fietkau 	} req = {
446c8846e10SFelix Fietkau 		.control_chan = chandef->chan->hw_value,
447c8846e10SFelix Fietkau 		.center_chan = chandef->chan->hw_value,
448c8846e10SFelix Fietkau 		.bw = MT_BW_20,
449c8846e10SFelix Fietkau 		.tx_streams = n_chains,
450c8846e10SFelix Fietkau 		.rx_streams = n_chains,
451c8846e10SFelix Fietkau 	};
452c8846e10SFelix Fietkau 	s8 tx_power;
45311ca82d7SLorenzo Bianconi 	int i, ret;
454c8846e10SFelix Fietkau 
45596747a51SFelix Fietkau 	if (dev->mphy.chandef.width == NL80211_CHAN_WIDTH_40) {
456c8846e10SFelix Fietkau 		req.bw = MT_BW_40;
457c8846e10SFelix Fietkau 		if (chandef->center_freq1 > chandef->chan->center_freq)
458c8846e10SFelix Fietkau 			req.center_chan += 2;
459c8846e10SFelix Fietkau 		else
460c8846e10SFelix Fietkau 			req.center_chan -= 2;
461c8846e10SFelix Fietkau 	}
462c8846e10SFelix Fietkau 
463c8846e10SFelix Fietkau 	tx_power = hw->conf.power_level * 2;
464beaaeb6bSFelix Fietkau 	if (dev->mphy.antenna_mask == 3)
465c8846e10SFelix Fietkau 		tx_power -= 6;
466c8846e10SFelix Fietkau 	tx_power = min(tx_power, dev->tx_power_limit);
467c8846e10SFelix Fietkau 
468beaaeb6bSFelix Fietkau 	dev->mphy.txpower_cur = tx_power;
469c8846e10SFelix Fietkau 
470c8846e10SFelix Fietkau 	for (i = 0; i < ARRAY_SIZE(req.txpower); i++)
471c8846e10SFelix Fietkau 		req.txpower[i] = tx_power;
472c8846e10SFelix Fietkau 
473cc173875SLorenzo Bianconi 	ret = __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_CHANNEL_SWITCH,
47411ca82d7SLorenzo Bianconi 				  &req, sizeof(req), true);
475c8846e10SFelix Fietkau 	if (ret)
476c8846e10SFelix Fietkau 		return ret;
477c8846e10SFelix Fietkau 
478c8846e10SFelix Fietkau 	return mt7603_mcu_set_tx_power(dev);
479c8846e10SFelix Fietkau }
480