Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/contrib/dev/mediatek/mt76/mt7603/mcu.c
48524 views
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
10
struct mt7603_fw_trailer {
11
char fw_ver[10];
12
char build_date[15];
13
__le32 dl_len;
14
} __packed;
15
16
static int
17
mt7603_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
37
static int
38
mt7603_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
else
58
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
78
static int
79
mt7603_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
95
static int
96
mt7603_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
110
static int
111
mt7603_mcu_restart(struct mt76_dev *dev)
112
{
113
return mt76_mcu_send_msg(dev, -MCU_CMD_RESTART_DL_REQ, NULL, 0, true);
114
}
115
116
static 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
else
129
firmware = MT7628_FIRMWARE_E2;
130
} else {
131
if (mt76xx_rev(dev) < MT7603_REV_E2)
132
firmware = MT7603_FIRMWARE_E1;
133
else
134
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
200
running:
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
212
out:
213
release_firmware(fw);
214
215
return ret;
216
}
217
218
int 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
230
void 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
236
int mt7603_mcu_set_eeprom(struct mt7603_dev *dev)
237
{
238
static const u16 req_fields[] = {
239
#define WORD(_start) \
240
_start, \
241
_start + 1
242
#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_2G
298
#undef WORD
299
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
340
static 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_VAL
371
};
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
384
int 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
else
413
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
434