brintos

brintos / linux-shallow public Read only

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