Linux Audio

Check our new training course

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