1c8846e10SFelix Fietkau /* 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
17c8846e10SFelix Fietkau __mt7603_mcu_msg_send(struct mt7603_dev *dev, struct sk_buff *skb, int cmd,
18c8846e10SFelix Fietkau 		      int query, 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 
25c8846e10SFelix Fietkau 	if (!skb)
26c8846e10SFelix Fietkau 		return -EINVAL;
27c8846e10SFelix Fietkau 
28c8846e10SFelix Fietkau 	seq = ++mdev->mmio.mcu.msg_seq & 0xf;
29c8846e10SFelix Fietkau 	if (!seq)
30c8846e10SFelix Fietkau 		seq = ++mdev->mmio.mcu.msg_seq & 0xf;
31c8846e10SFelix Fietkau 
32c8846e10SFelix Fietkau 	txd = (struct mt7603_mcu_txd *)skb_push(skb, hdrlen);
33c8846e10SFelix Fietkau 	memset(txd, 0, hdrlen);
34c8846e10SFelix Fietkau 
35c8846e10SFelix Fietkau 	txd->len = cpu_to_le16(skb->len);
36c8846e10SFelix Fietkau 	if (cmd == -MCU_CMD_FW_SCATTER)
37c8846e10SFelix Fietkau 		txd->pq_id = cpu_to_le16(MCU_PORT_QUEUE_FW);
38c8846e10SFelix Fietkau 	else
39c8846e10SFelix Fietkau 		txd->pq_id = cpu_to_le16(MCU_PORT_QUEUE);
40c8846e10SFelix Fietkau 	txd->pkt_type = MCU_PKT_ID;
41c8846e10SFelix Fietkau 	txd->seq = seq;
42c8846e10SFelix Fietkau 
43c8846e10SFelix Fietkau 	if (cmd < 0) {
44c8846e10SFelix Fietkau 		txd->cid = -cmd;
45c8846e10SFelix Fietkau 	} else {
46c8846e10SFelix Fietkau 		txd->cid = MCU_CMD_EXT_CID;
47c8846e10SFelix Fietkau 		txd->ext_cid = cmd;
48c8846e10SFelix Fietkau 		if (query != MCU_Q_NA)
49c8846e10SFelix Fietkau 			txd->ext_cid_ack = 1;
50c8846e10SFelix Fietkau 	}
51c8846e10SFelix Fietkau 
52c8846e10SFelix Fietkau 	txd->set_query = query;
53c8846e10SFelix Fietkau 
54c8846e10SFelix Fietkau 	if (wait_seq)
55c8846e10SFelix Fietkau 		*wait_seq = seq;
56c8846e10SFelix Fietkau 
57c8846e10SFelix Fietkau 	return mt76_tx_queue_skb_raw(dev, MT_TXQ_MCU, skb, 0);
58c8846e10SFelix Fietkau }
59c8846e10SFelix Fietkau 
60c8846e10SFelix Fietkau static int
61c8846e10SFelix Fietkau mt7603_mcu_msg_send(struct mt7603_dev *dev, struct sk_buff *skb, int cmd,
62c8846e10SFelix Fietkau 		    int query)
63c8846e10SFelix Fietkau {
64c8846e10SFelix Fietkau 	struct mt76_dev *mdev = &dev->mt76;
65c8846e10SFelix Fietkau 	unsigned long expires = jiffies + 3 * HZ;
66c8846e10SFelix Fietkau 	struct mt7603_mcu_rxd *rxd;
67c8846e10SFelix Fietkau 	int ret, seq;
68c8846e10SFelix Fietkau 
69c8846e10SFelix Fietkau 	mutex_lock(&mdev->mmio.mcu.mutex);
70c8846e10SFelix Fietkau 
71c8846e10SFelix Fietkau 	ret = __mt7603_mcu_msg_send(dev, skb, cmd, query, &seq);
72c8846e10SFelix Fietkau 	if (ret)
73c8846e10SFelix Fietkau 		goto out;
74c8846e10SFelix Fietkau 
75c8846e10SFelix Fietkau 	while (1) {
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:
99c8846e10SFelix Fietkau 	mutex_unlock(&mdev->mmio.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 	struct sk_buff *skb = mt7603_mcu_msg_alloc(&req, sizeof(req));
117c8846e10SFelix Fietkau 
118c8846e10SFelix Fietkau 	return mt7603_mcu_msg_send(dev, skb, -MCU_CMD_TARGET_ADDRESS_LEN_REQ,
119c8846e10SFelix Fietkau 				   MCU_Q_NA);
120c8846e10SFelix Fietkau }
121c8846e10SFelix Fietkau 
122c8846e10SFelix Fietkau static int
123c8846e10SFelix Fietkau mt7603_mcu_send_firmware(struct mt7603_dev *dev, const void *data, int len)
124c8846e10SFelix Fietkau {
125c8846e10SFelix Fietkau 	struct sk_buff *skb;
126c8846e10SFelix Fietkau 	int ret = 0;
127c8846e10SFelix Fietkau 
128c8846e10SFelix Fietkau 	while (len > 0) {
129c8846e10SFelix Fietkau 		int cur_len = min_t(int, 4096 - sizeof(struct mt7603_mcu_txd),
130c8846e10SFelix Fietkau 				    len);
131c8846e10SFelix Fietkau 
132c8846e10SFelix Fietkau 		skb = mt7603_mcu_msg_alloc(data, cur_len);
133c8846e10SFelix Fietkau 		if (!skb)
134c8846e10SFelix Fietkau 			return -ENOMEM;
135c8846e10SFelix Fietkau 
136c8846e10SFelix Fietkau 		ret = __mt7603_mcu_msg_send(dev, skb, -MCU_CMD_FW_SCATTER,
137c8846e10SFelix Fietkau 					    MCU_Q_NA, NULL);
138c8846e10SFelix Fietkau 		if (ret)
139c8846e10SFelix Fietkau 			break;
140c8846e10SFelix Fietkau 
141c8846e10SFelix Fietkau 		data += cur_len;
142c8846e10SFelix Fietkau 		len -= cur_len;
143c8846e10SFelix Fietkau 	}
144c8846e10SFelix Fietkau 
145c8846e10SFelix Fietkau 	return ret;
146c8846e10SFelix Fietkau }
147c8846e10SFelix Fietkau 
148c8846e10SFelix Fietkau static int
149c8846e10SFelix Fietkau mt7603_mcu_start_firmware(struct mt7603_dev *dev, u32 addr)
150c8846e10SFelix Fietkau {
151c8846e10SFelix Fietkau 	struct {
152c8846e10SFelix Fietkau 		__le32 override;
153c8846e10SFelix Fietkau 		__le32 addr;
154c8846e10SFelix Fietkau 	} req = {
155c8846e10SFelix Fietkau 		.override = cpu_to_le32(addr ? 1 : 0),
156c8846e10SFelix Fietkau 		.addr = cpu_to_le32(addr),
157c8846e10SFelix Fietkau 	};
158c8846e10SFelix Fietkau 	struct sk_buff *skb = mt7603_mcu_msg_alloc(&req, sizeof(req));
159c8846e10SFelix Fietkau 
160c8846e10SFelix Fietkau 	return mt7603_mcu_msg_send(dev, skb, -MCU_CMD_FW_START_REQ,
161c8846e10SFelix Fietkau 				   MCU_Q_NA);
162c8846e10SFelix Fietkau }
163c8846e10SFelix Fietkau 
164c8846e10SFelix Fietkau static int
165c8846e10SFelix Fietkau mt7603_mcu_restart(struct mt7603_dev *dev)
166c8846e10SFelix Fietkau {
167c8846e10SFelix Fietkau 	struct sk_buff *skb = mt7603_mcu_msg_alloc(NULL, 0);
168c8846e10SFelix Fietkau 
169c8846e10SFelix Fietkau 	return mt7603_mcu_msg_send(dev, skb, -MCU_CMD_RESTART_DL_REQ,
170c8846e10SFelix Fietkau 				   MCU_Q_NA);
171c8846e10SFelix Fietkau }
172c8846e10SFelix Fietkau 
173c8846e10SFelix Fietkau static int
174c8846e10SFelix Fietkau mt7603_load_firmware(struct mt7603_dev *dev)
175c8846e10SFelix Fietkau {
176c8846e10SFelix Fietkau 	const struct firmware *fw;
177c8846e10SFelix Fietkau 	const struct mt7603_fw_trailer *hdr;
178c8846e10SFelix Fietkau 	const char *firmware;
179c8846e10SFelix Fietkau 	int dl_len;
180c8846e10SFelix Fietkau 	u32 addr, val;
181c8846e10SFelix Fietkau 	int ret;
182c8846e10SFelix Fietkau 
183c8846e10SFelix Fietkau 	if (is_mt7628(dev)) {
184c8846e10SFelix Fietkau 		if (mt76xx_rev(dev) == MT7628_REV_E1)
185c8846e10SFelix Fietkau 			firmware = MT7628_FIRMWARE_E1;
186c8846e10SFelix Fietkau 		else
187c8846e10SFelix Fietkau 			firmware = MT7628_FIRMWARE_E2;
188c8846e10SFelix Fietkau 	} else {
189c8846e10SFelix Fietkau 		if (mt76xx_rev(dev) < MT7603_REV_E2)
190c8846e10SFelix Fietkau 			firmware = MT7603_FIRMWARE_E1;
191c8846e10SFelix Fietkau 		else
192c8846e10SFelix Fietkau 			firmware = MT7603_FIRMWARE_E2;
193c8846e10SFelix Fietkau 	}
194c8846e10SFelix Fietkau 
195c8846e10SFelix Fietkau 	ret = request_firmware(&fw, firmware, dev->mt76.dev);
196c8846e10SFelix Fietkau 	if (ret)
197c8846e10SFelix Fietkau 		return ret;
198c8846e10SFelix Fietkau 
199c8846e10SFelix Fietkau 	if (!fw || !fw->data || fw->size < sizeof(*hdr)) {
200c8846e10SFelix Fietkau 		dev_err(dev->mt76.dev, "Invalid firmware\n");
201c8846e10SFelix Fietkau 		ret = -EINVAL;
202c8846e10SFelix Fietkau 		goto out;
203c8846e10SFelix Fietkau 	}
204c8846e10SFelix Fietkau 
205c8846e10SFelix Fietkau 	hdr = (const struct mt7603_fw_trailer *)(fw->data + fw->size -
206c8846e10SFelix Fietkau 						 sizeof(*hdr));
207c8846e10SFelix Fietkau 
208c8846e10SFelix Fietkau 	dev_info(dev->mt76.dev, "Firmware Version: %.10s\n", hdr->fw_ver);
209c8846e10SFelix Fietkau 	dev_info(dev->mt76.dev, "Build Time: %.15s\n", hdr->build_date);
210c8846e10SFelix Fietkau 
211c8846e10SFelix Fietkau 	addr = mt7603_reg_map(dev, 0x50012498);
212c8846e10SFelix Fietkau 	mt76_wr(dev, addr, 0x5);
213c8846e10SFelix Fietkau 	mt76_wr(dev, addr, 0x5);
214c8846e10SFelix Fietkau 	udelay(1);
215c8846e10SFelix Fietkau 
216c8846e10SFelix Fietkau 	/* switch to bypass mode */
217c8846e10SFelix Fietkau 	mt76_rmw(dev, MT_SCH_4, MT_SCH_4_FORCE_QID,
218c8846e10SFelix Fietkau 		 MT_SCH_4_BYPASS | FIELD_PREP(MT_SCH_4_FORCE_QID, 5));
219c8846e10SFelix Fietkau 
220c8846e10SFelix Fietkau 	val = mt76_rr(dev, MT_TOP_MISC2);
221c8846e10SFelix Fietkau 	if (val & BIT(1)) {
222c8846e10SFelix Fietkau 		dev_info(dev->mt76.dev, "Firmware already running...\n");
223c8846e10SFelix Fietkau 		goto running;
224c8846e10SFelix Fietkau 	}
225c8846e10SFelix Fietkau 
226c8846e10SFelix Fietkau 	if (!mt76_poll_msec(dev, MT_TOP_MISC2, BIT(0) | BIT(1), BIT(0), 500)) {
227c8846e10SFelix Fietkau 		dev_err(dev->mt76.dev, "Timeout waiting for ROM code to become ready\n");
228c8846e10SFelix Fietkau 		ret = -EIO;
229c8846e10SFelix Fietkau 		goto out;
230c8846e10SFelix Fietkau 	}
231c8846e10SFelix Fietkau 
232c8846e10SFelix Fietkau 	dl_len = le32_to_cpu(hdr->dl_len) + 4;
233c8846e10SFelix Fietkau 	ret = mt7603_mcu_init_download(dev, MCU_FIRMWARE_ADDRESS, dl_len);
234c8846e10SFelix Fietkau 	if (ret) {
235c8846e10SFelix Fietkau 		dev_err(dev->mt76.dev, "Download request failed\n");
236c8846e10SFelix Fietkau 		goto out;
237c8846e10SFelix Fietkau 	}
238c8846e10SFelix Fietkau 
239c8846e10SFelix Fietkau 	ret = mt7603_mcu_send_firmware(dev, fw->data, dl_len);
240c8846e10SFelix Fietkau 	if (ret) {
241c8846e10SFelix Fietkau 		dev_err(dev->mt76.dev, "Failed to send firmware to device\n");
242c8846e10SFelix Fietkau 		goto out;
243c8846e10SFelix Fietkau 	}
244c8846e10SFelix Fietkau 
245c8846e10SFelix Fietkau 	ret = mt7603_mcu_start_firmware(dev, MCU_FIRMWARE_ADDRESS);
246c8846e10SFelix Fietkau 	if (ret) {
247c8846e10SFelix Fietkau 		dev_err(dev->mt76.dev, "Failed to start firmware\n");
248c8846e10SFelix Fietkau 		goto out;
249c8846e10SFelix Fietkau 	}
250c8846e10SFelix Fietkau 
251c8846e10SFelix Fietkau 	if (!mt76_poll_msec(dev, MT_TOP_MISC2, BIT(1), BIT(1), 500)) {
252c8846e10SFelix Fietkau 		dev_err(dev->mt76.dev, "Timeout waiting for firmware to initialize\n");
253c8846e10SFelix Fietkau 		ret = -EIO;
254c8846e10SFelix Fietkau 		goto out;
255c8846e10SFelix Fietkau 	}
256c8846e10SFelix Fietkau 
257c8846e10SFelix Fietkau running:
258c8846e10SFelix Fietkau 	mt76_clear(dev, MT_SCH_4, MT_SCH_4_FORCE_QID | MT_SCH_4_BYPASS);
259c8846e10SFelix Fietkau 
260c8846e10SFelix Fietkau 	mt76_set(dev, MT_SCH_4, BIT(8));
261c8846e10SFelix Fietkau 	mt76_clear(dev, MT_SCH_4, BIT(8));
262c8846e10SFelix Fietkau 
263c8846e10SFelix Fietkau 	dev->mcu_running = true;
264c8846e10SFelix Fietkau 	dev_info(dev->mt76.dev, "firmware init done\n");
265c8846e10SFelix Fietkau 
266c8846e10SFelix Fietkau out:
267c8846e10SFelix Fietkau 	release_firmware(fw);
268c8846e10SFelix Fietkau 
269c8846e10SFelix Fietkau 	return ret;
270c8846e10SFelix Fietkau }
271c8846e10SFelix Fietkau 
272c8846e10SFelix Fietkau int mt7603_mcu_init(struct mt7603_dev *dev)
273c8846e10SFelix Fietkau {
274c8846e10SFelix Fietkau 	mutex_init(&dev->mt76.mmio.mcu.mutex);
275c8846e10SFelix Fietkau 
276c8846e10SFelix Fietkau 	return mt7603_load_firmware(dev);
277c8846e10SFelix Fietkau }
278c8846e10SFelix Fietkau 
279c8846e10SFelix Fietkau void mt7603_mcu_exit(struct mt7603_dev *dev)
280c8846e10SFelix Fietkau {
281c8846e10SFelix Fietkau 	mt7603_mcu_restart(dev);
282c8846e10SFelix Fietkau 	skb_queue_purge(&dev->mt76.mmio.mcu.res_q);
283c8846e10SFelix Fietkau }
284c8846e10SFelix Fietkau 
285c8846e10SFelix Fietkau int mt7603_mcu_set_eeprom(struct mt7603_dev *dev)
286c8846e10SFelix Fietkau {
287c8846e10SFelix Fietkau 	static const u16 req_fields[] = {
288c8846e10SFelix Fietkau #define WORD(_start)			\
289c8846e10SFelix Fietkau 		_start,			\
290c8846e10SFelix Fietkau 		_start + 1
291c8846e10SFelix Fietkau #define GROUP_2G(_start)		\
292c8846e10SFelix Fietkau 		WORD(_start),		\
293c8846e10SFelix Fietkau 		WORD(_start + 2),	\
294c8846e10SFelix Fietkau 		WORD(_start + 4)
295c8846e10SFelix Fietkau 
296c8846e10SFelix Fietkau 		MT_EE_NIC_CONF_0 + 1,
297c8846e10SFelix Fietkau 		WORD(MT_EE_NIC_CONF_1),
298c8846e10SFelix Fietkau 		MT_EE_WIFI_RF_SETTING,
299c8846e10SFelix Fietkau 		MT_EE_TX_POWER_DELTA_BW40,
300c8846e10SFelix Fietkau 		MT_EE_TX_POWER_DELTA_BW80 + 1,
301c8846e10SFelix Fietkau 		MT_EE_TX_POWER_EXT_PA_5G,
302c8846e10SFelix Fietkau 		MT_EE_TEMP_SENSOR_CAL,
303c8846e10SFelix Fietkau 		GROUP_2G(MT_EE_TX_POWER_0_START_2G),
304c8846e10SFelix Fietkau 		GROUP_2G(MT_EE_TX_POWER_1_START_2G),
305c8846e10SFelix Fietkau 		WORD(MT_EE_TX_POWER_CCK),
306c8846e10SFelix Fietkau 		WORD(MT_EE_TX_POWER_OFDM_2G_6M),
307c8846e10SFelix Fietkau 		WORD(MT_EE_TX_POWER_OFDM_2G_24M),
308c8846e10SFelix Fietkau 		WORD(MT_EE_TX_POWER_OFDM_2G_54M),
309c8846e10SFelix Fietkau 		WORD(MT_EE_TX_POWER_HT_BPSK_QPSK),
310c8846e10SFelix Fietkau 		WORD(MT_EE_TX_POWER_HT_16_64_QAM),
311c8846e10SFelix Fietkau 		WORD(MT_EE_TX_POWER_HT_64_QAM),
312c8846e10SFelix Fietkau 		MT_EE_ELAN_RX_MODE_GAIN,
313c8846e10SFelix Fietkau 		MT_EE_ELAN_RX_MODE_NF,
314c8846e10SFelix Fietkau 		MT_EE_ELAN_RX_MODE_P1DB,
315c8846e10SFelix Fietkau 		MT_EE_ELAN_BYPASS_MODE_GAIN,
316c8846e10SFelix Fietkau 		MT_EE_ELAN_BYPASS_MODE_NF,
317c8846e10SFelix Fietkau 		MT_EE_ELAN_BYPASS_MODE_P1DB,
318c8846e10SFelix Fietkau 		WORD(MT_EE_STEP_NUM_NEG_6_7),
319c8846e10SFelix Fietkau 		WORD(MT_EE_STEP_NUM_NEG_4_5),
320c8846e10SFelix Fietkau 		WORD(MT_EE_STEP_NUM_NEG_2_3),
321c8846e10SFelix Fietkau 		WORD(MT_EE_STEP_NUM_NEG_0_1),
322c8846e10SFelix Fietkau 		WORD(MT_EE_REF_STEP_24G),
323c8846e10SFelix Fietkau 		WORD(MT_EE_STEP_NUM_PLUS_1_2),
324c8846e10SFelix Fietkau 		WORD(MT_EE_STEP_NUM_PLUS_3_4),
325c8846e10SFelix Fietkau 		WORD(MT_EE_STEP_NUM_PLUS_5_6),
326c8846e10SFelix Fietkau 		MT_EE_STEP_NUM_PLUS_7,
327c8846e10SFelix Fietkau 		MT_EE_XTAL_FREQ_OFFSET,
328c8846e10SFelix Fietkau 		MT_EE_XTAL_TRIM_2_COMP,
329c8846e10SFelix Fietkau 		MT_EE_XTAL_TRIM_3_COMP,
330c8846e10SFelix Fietkau 		MT_EE_XTAL_WF_RFCAL,
331c8846e10SFelix Fietkau 
332c8846e10SFelix Fietkau 		/* unknown fields below */
333c8846e10SFelix Fietkau 		WORD(0x24),
334c8846e10SFelix Fietkau 		0x34,
335c8846e10SFelix Fietkau 		0x39,
336c8846e10SFelix Fietkau 		0x3b,
337c8846e10SFelix Fietkau 		WORD(0x42),
338c8846e10SFelix Fietkau 		WORD(0x9e),
339c8846e10SFelix Fietkau 		0xf2,
340c8846e10SFelix Fietkau 		WORD(0xf8),
341c8846e10SFelix Fietkau 		0xfa,
342c8846e10SFelix Fietkau 		0x12e,
343c8846e10SFelix Fietkau 		WORD(0x130), WORD(0x132), WORD(0x134), WORD(0x136),
344c8846e10SFelix Fietkau 		WORD(0x138), WORD(0x13a), WORD(0x13c), WORD(0x13e),
345c8846e10SFelix Fietkau 
346c8846e10SFelix Fietkau #undef GROUP_2G
347c8846e10SFelix Fietkau #undef WORD
348c8846e10SFelix Fietkau 
349c8846e10SFelix Fietkau 	};
350c8846e10SFelix Fietkau 	struct req_data {
351c8846e10SFelix Fietkau 		u16 addr;
352c8846e10SFelix Fietkau 		u8 val;
353c8846e10SFelix Fietkau 		u8 pad;
354c8846e10SFelix Fietkau 	} __packed;
355c8846e10SFelix Fietkau 	struct {
356c8846e10SFelix Fietkau 		u8 buffer_mode;
357c8846e10SFelix Fietkau 		u8 len;
358c8846e10SFelix Fietkau 		u8 pad[2];
359c8846e10SFelix Fietkau 	} req_hdr = {
360c8846e10SFelix Fietkau 		.buffer_mode = 1,
361c8846e10SFelix Fietkau 		.len = ARRAY_SIZE(req_fields) - 1,
362c8846e10SFelix Fietkau 	};
363c8846e10SFelix Fietkau 	struct sk_buff *skb;
364c8846e10SFelix Fietkau 	struct req_data *data;
365c8846e10SFelix Fietkau 	const int size = 0xff * sizeof(struct req_data);
366c8846e10SFelix Fietkau 	u8 *eep = (u8 *)dev->mt76.eeprom.data;
367c8846e10SFelix Fietkau 	int i;
368c8846e10SFelix Fietkau 
369c8846e10SFelix Fietkau 	BUILD_BUG_ON(ARRAY_SIZE(req_fields) * sizeof(*data) > size);
370c8846e10SFelix Fietkau 
371c8846e10SFelix Fietkau 	skb = mt7603_mcu_msg_alloc(NULL, size + sizeof(req_hdr));
372c8846e10SFelix Fietkau 	memcpy(skb_put(skb, sizeof(req_hdr)), &req_hdr, sizeof(req_hdr));
373c8846e10SFelix Fietkau 	data = (struct req_data *)skb_put(skb, size);
374c8846e10SFelix Fietkau 	memset(data, 0, size);
375c8846e10SFelix Fietkau 
376c8846e10SFelix Fietkau 	for (i = 0; i < ARRAY_SIZE(req_fields); i++) {
377c8846e10SFelix Fietkau 		data[i].addr = cpu_to_le16(req_fields[i]);
378c8846e10SFelix Fietkau 		data[i].val = eep[req_fields[i]];
379c8846e10SFelix Fietkau 		data[i].pad = 0;
380c8846e10SFelix Fietkau 	}
381c8846e10SFelix Fietkau 
382c8846e10SFelix Fietkau 	return mt7603_mcu_msg_send(dev, skb, MCU_EXT_CMD_EFUSE_BUFFER_MODE,
383c8846e10SFelix Fietkau 				   MCU_Q_SET);
384c8846e10SFelix Fietkau }
385c8846e10SFelix Fietkau 
386c8846e10SFelix Fietkau static int mt7603_mcu_set_tx_power(struct mt7603_dev *dev)
387c8846e10SFelix Fietkau {
388c8846e10SFelix Fietkau 	struct {
389c8846e10SFelix Fietkau 		u8 center_channel;
390c8846e10SFelix Fietkau 		u8 tssi;
391c8846e10SFelix Fietkau 		u8 temp_comp;
392c8846e10SFelix Fietkau 		u8 target_power[2];
393c8846e10SFelix Fietkau 		u8 rate_power_delta[14];
394c8846e10SFelix Fietkau 		u8 bw_power_delta;
395c8846e10SFelix Fietkau 		u8 ch_power_delta[6];
396c8846e10SFelix Fietkau 		u8 temp_comp_power[17];
397c8846e10SFelix Fietkau 		u8 reserved;
398c8846e10SFelix Fietkau 	} req = {
399c8846e10SFelix Fietkau 		.center_channel = dev->mt76.chandef.chan->hw_value,
400c8846e10SFelix Fietkau #define EEP_VAL(n) ((u8 *)dev->mt76.eeprom.data)[n]
401c8846e10SFelix Fietkau 		.tssi = EEP_VAL(MT_EE_NIC_CONF_1 + 1),
402c8846e10SFelix Fietkau 		.temp_comp = EEP_VAL(MT_EE_NIC_CONF_1),
403c8846e10SFelix Fietkau 		.target_power = {
404c8846e10SFelix Fietkau 			EEP_VAL(MT_EE_TX_POWER_0_START_2G + 2),
405c8846e10SFelix Fietkau 			EEP_VAL(MT_EE_TX_POWER_1_START_2G + 2)
406c8846e10SFelix Fietkau 		},
407c8846e10SFelix Fietkau 		.bw_power_delta = EEP_VAL(MT_EE_TX_POWER_DELTA_BW40),
408c8846e10SFelix Fietkau 		.ch_power_delta = {
409c8846e10SFelix Fietkau 			EEP_VAL(MT_EE_TX_POWER_0_START_2G + 3),
410c8846e10SFelix Fietkau 			EEP_VAL(MT_EE_TX_POWER_0_START_2G + 4),
411c8846e10SFelix Fietkau 			EEP_VAL(MT_EE_TX_POWER_0_START_2G + 5),
412c8846e10SFelix Fietkau 			EEP_VAL(MT_EE_TX_POWER_1_START_2G + 3),
413c8846e10SFelix Fietkau 			EEP_VAL(MT_EE_TX_POWER_1_START_2G + 4),
414c8846e10SFelix Fietkau 			EEP_VAL(MT_EE_TX_POWER_1_START_2G + 5)
415c8846e10SFelix Fietkau 		},
416c8846e10SFelix Fietkau #undef EEP_VAL
417c8846e10SFelix Fietkau 	};
418c8846e10SFelix Fietkau 	struct sk_buff *skb;
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 
427c8846e10SFelix Fietkau 	skb = mt7603_mcu_msg_alloc(&req, sizeof(req));
428c8846e10SFelix Fietkau 	return mt7603_mcu_msg_send(dev, skb, MCU_EXT_CMD_SET_TX_POWER_CTRL,
429c8846e10SFelix Fietkau 				   MCU_Q_SET);
430c8846e10SFelix Fietkau }
431c8846e10SFelix Fietkau 
432c8846e10SFelix Fietkau int mt7603_mcu_set_channel(struct mt7603_dev *dev)
433c8846e10SFelix Fietkau {
434c8846e10SFelix Fietkau 	struct cfg80211_chan_def *chandef = &dev->mt76.chandef;
435c8846e10SFelix Fietkau 	struct ieee80211_hw *hw = mt76_hw(dev);
436c8846e10SFelix Fietkau 	int n_chains = __sw_hweight8(dev->mt76.antenna_mask);
437c8846e10SFelix Fietkau 	struct {
438c8846e10SFelix Fietkau 		u8 control_chan;
439c8846e10SFelix Fietkau 		u8 center_chan;
440c8846e10SFelix Fietkau 		u8 bw;
441c8846e10SFelix Fietkau 		u8 tx_streams;
442c8846e10SFelix Fietkau 		u8 rx_streams;
443c8846e10SFelix Fietkau 		u8 _res0[7];
444c8846e10SFelix Fietkau 		u8 txpower[21];
445c8846e10SFelix Fietkau 		u8 _res1[3];
446c8846e10SFelix Fietkau 	} req = {
447c8846e10SFelix Fietkau 		.control_chan = chandef->chan->hw_value,
448c8846e10SFelix Fietkau 		.center_chan = chandef->chan->hw_value,
449c8846e10SFelix Fietkau 		.bw = MT_BW_20,
450c8846e10SFelix Fietkau 		.tx_streams = n_chains,
451c8846e10SFelix Fietkau 		.rx_streams = n_chains,
452c8846e10SFelix Fietkau 	};
453c8846e10SFelix Fietkau 	struct sk_buff *skb;
454c8846e10SFelix Fietkau 	s8 tx_power;
455c8846e10SFelix Fietkau 	int ret;
456c8846e10SFelix Fietkau 	int i;
457c8846e10SFelix Fietkau 
458c8846e10SFelix Fietkau 	if (dev->mt76.chandef.width == NL80211_CHAN_WIDTH_40) {
459c8846e10SFelix Fietkau 		req.bw = MT_BW_40;
460c8846e10SFelix Fietkau 		if (chandef->center_freq1 > chandef->chan->center_freq)
461c8846e10SFelix Fietkau 			req.center_chan += 2;
462c8846e10SFelix Fietkau 		else
463c8846e10SFelix Fietkau 			req.center_chan -= 2;
464c8846e10SFelix Fietkau 	}
465c8846e10SFelix Fietkau 
466c8846e10SFelix Fietkau 	tx_power = hw->conf.power_level * 2;
467c8846e10SFelix Fietkau 	if (dev->mt76.antenna_mask == 3)
468c8846e10SFelix Fietkau 		tx_power -= 6;
469c8846e10SFelix Fietkau 	tx_power = min(tx_power, dev->tx_power_limit);
470c8846e10SFelix Fietkau 
471c8846e10SFelix Fietkau 	dev->mt76.txpower_cur = tx_power;
472c8846e10SFelix Fietkau 
473c8846e10SFelix Fietkau 	for (i = 0; i < ARRAY_SIZE(req.txpower); i++)
474c8846e10SFelix Fietkau 		req.txpower[i] = tx_power;
475c8846e10SFelix Fietkau 
476c8846e10SFelix Fietkau 	skb = mt7603_mcu_msg_alloc(&req, sizeof(req));
477c8846e10SFelix Fietkau 	ret = mt7603_mcu_msg_send(dev, skb, MCU_EXT_CMD_CHANNEL_SWITCH,
478c8846e10SFelix Fietkau 				  MCU_Q_SET);
479c8846e10SFelix Fietkau 	if (ret)
480c8846e10SFelix Fietkau 		return ret;
481c8846e10SFelix Fietkau 
482c8846e10SFelix Fietkau 	return mt7603_mcu_set_tx_power(dev);
483c8846e10SFelix Fietkau }
484