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