Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/contrib/dev/mediatek/mt76/mt7915/eeprom.c
107707 views
1
// SPDX-License-Identifier: BSD-3-Clause-Clear
2
/* Copyright (C) 2020 MediaTek Inc. */
3
4
#if defined(__FreeBSD__)
5
#define LINUXKPI_PARAM_PREFIX mt7915_
6
#endif
7
8
#include <linux/firmware.h>
9
#include <linux/moduleparam.h>
10
#include "mt7915.h"
11
#include "eeprom.h"
12
13
static bool enable_6ghz;
14
module_param(enable_6ghz, bool, 0644);
15
MODULE_PARM_DESC(enable_6ghz, "Enable 6 GHz instead of 5 GHz on hardware that supports both");
16
17
static int mt7915_eeprom_load_precal(struct mt7915_dev *dev)
18
{
19
struct mt76_dev *mdev = &dev->mt76;
20
u8 *eeprom = mdev->eeprom.data;
21
u32 offs = is_mt7915(&dev->mt76) ? MT_EE_DO_PRE_CAL : MT_EE_DO_PRE_CAL_V2;
22
u32 size, val = eeprom[offs];
23
int ret;
24
25
if (!dev->flash_mode || !val)
26
return 0;
27
28
size = mt7915_get_cal_group_size(dev) + mt7915_get_cal_dpd_size(dev);
29
30
dev->cal = devm_kzalloc(mdev->dev, size, GFP_KERNEL);
31
if (!dev->cal)
32
return -ENOMEM;
33
34
offs = is_mt7915(&dev->mt76) ? MT_EE_PRECAL : MT_EE_PRECAL_V2;
35
36
ret = mt76_get_of_data_from_mtd(mdev, dev->cal, offs, size);
37
if (!ret)
38
return ret;
39
40
ret = mt76_get_of_data_from_nvmem(mdev, dev->cal, "precal", size);
41
if (!ret)
42
return ret;
43
44
dev_warn(mdev->dev, "missing precal data, size=%d\n", size);
45
devm_kfree(mdev->dev, dev->cal);
46
dev->cal = NULL;
47
48
return ret;
49
}
50
51
static int mt7915_check_eeprom(struct mt7915_dev *dev)
52
{
53
u8 *eeprom = dev->mt76.eeprom.data;
54
u16 val = get_unaligned_le16(eeprom);
55
56
#define CHECK_EEPROM_ERR(match) (match ? 0 : -EINVAL)
57
switch (val) {
58
case 0x7915:
59
return CHECK_EEPROM_ERR(is_mt7915(&dev->mt76));
60
case 0x7916:
61
return CHECK_EEPROM_ERR(is_mt7916(&dev->mt76));
62
case 0x7981:
63
return CHECK_EEPROM_ERR(is_mt7981(&dev->mt76));
64
case 0x7986:
65
return CHECK_EEPROM_ERR(is_mt7986(&dev->mt76));
66
default:
67
return -EINVAL;
68
}
69
}
70
71
static char *mt7915_eeprom_name(struct mt7915_dev *dev)
72
{
73
switch (mt76_chip(&dev->mt76)) {
74
case 0x7915:
75
return dev->dbdc_support ?
76
MT7915_EEPROM_DEFAULT_DBDC : MT7915_EEPROM_DEFAULT;
77
case 0x7981:
78
/* mt7981 only supports mt7976 and only in DBDC mode */
79
return MT7981_EEPROM_MT7976_DEFAULT_DBDC;
80
case 0x7986:
81
switch (mt7915_check_adie(dev, true)) {
82
case MT7976_ONE_ADIE_DBDC:
83
return MT7986_EEPROM_MT7976_DEFAULT_DBDC;
84
case MT7975_ONE_ADIE:
85
return MT7986_EEPROM_MT7975_DEFAULT;
86
case MT7976_ONE_ADIE:
87
return MT7986_EEPROM_MT7976_DEFAULT;
88
case MT7975_DUAL_ADIE:
89
return MT7986_EEPROM_MT7975_DUAL_DEFAULT;
90
case MT7976_DUAL_ADIE:
91
return MT7986_EEPROM_MT7976_DUAL_DEFAULT;
92
default:
93
break;
94
}
95
return NULL;
96
default:
97
return MT7916_EEPROM_DEFAULT;
98
}
99
}
100
101
static int
102
mt7915_eeprom_load_default(struct mt7915_dev *dev)
103
{
104
u8 *eeprom = dev->mt76.eeprom.data;
105
const struct firmware *fw = NULL;
106
int ret;
107
108
ret = request_firmware(&fw, mt7915_eeprom_name(dev), dev->mt76.dev);
109
if (ret)
110
return ret;
111
112
if (!fw || !fw->data) {
113
dev_err(dev->mt76.dev, "Invalid default bin\n");
114
ret = -EINVAL;
115
goto out;
116
}
117
118
memcpy(eeprom, fw->data, mt7915_eeprom_size(dev));
119
dev->flash_mode = true;
120
121
out:
122
release_firmware(fw);
123
124
return ret;
125
}
126
127
static int mt7915_eeprom_load(struct mt7915_dev *dev)
128
{
129
int ret;
130
u16 eeprom_size = mt7915_eeprom_size(dev);
131
132
ret = mt76_eeprom_init(&dev->mt76, eeprom_size);
133
if (ret < 0)
134
return ret;
135
136
if (ret) {
137
dev->flash_mode = true;
138
} else {
139
u8 free_block_num;
140
u32 block_num, i;
141
u32 eeprom_blk_size = MT7915_EEPROM_BLOCK_SIZE;
142
143
ret = mt7915_mcu_get_eeprom_free_block(dev, &free_block_num);
144
if (ret < 0)
145
return ret;
146
147
/* efuse info isn't enough */
148
if (free_block_num >= 29)
149
return -EINVAL;
150
151
/* read eeprom data from efuse */
152
block_num = DIV_ROUND_UP(eeprom_size, eeprom_blk_size);
153
for (i = 0; i < block_num; i++) {
154
ret = mt7915_mcu_get_eeprom(dev, i * eeprom_blk_size, NULL);
155
if (ret < 0)
156
return ret;
157
}
158
}
159
160
return mt7915_check_eeprom(dev);
161
}
162
163
static void mt7915_eeprom_parse_band_config(struct mt7915_phy *phy)
164
{
165
struct mt7915_dev *dev = phy->dev;
166
u8 *eeprom = dev->mt76.eeprom.data;
167
u8 band = phy->mt76->band_idx;
168
u32 val;
169
170
val = eeprom[MT_EE_WIFI_CONF + band];
171
val = FIELD_GET(MT_EE_WIFI_CONF0_BAND_SEL, val);
172
173
if (!is_mt7915(&dev->mt76)) {
174
switch (val) {
175
case MT_EE_V2_BAND_SEL_5GHZ:
176
phy->mt76->cap.has_5ghz = true;
177
return;
178
case MT_EE_V2_BAND_SEL_6GHZ:
179
phy->mt76->cap.has_6ghz = true;
180
return;
181
case MT_EE_V2_BAND_SEL_5GHZ_6GHZ:
182
if (enable_6ghz) {
183
phy->mt76->cap.has_6ghz = true;
184
u8p_replace_bits(&eeprom[MT_EE_WIFI_CONF + band],
185
MT_EE_V2_BAND_SEL_6GHZ,
186
MT_EE_WIFI_CONF0_BAND_SEL);
187
} else {
188
phy->mt76->cap.has_5ghz = true;
189
u8p_replace_bits(&eeprom[MT_EE_WIFI_CONF + band],
190
MT_EE_V2_BAND_SEL_5GHZ,
191
MT_EE_WIFI_CONF0_BAND_SEL);
192
}
193
/* force to buffer mode */
194
dev->flash_mode = true;
195
196
return;
197
default:
198
phy->mt76->cap.has_2ghz = true;
199
return;
200
}
201
} else if (val == MT_EE_BAND_SEL_DEFAULT && dev->dbdc_support) {
202
val = band ? MT_EE_BAND_SEL_5GHZ : MT_EE_BAND_SEL_2GHZ;
203
}
204
205
switch (val) {
206
case MT_EE_BAND_SEL_5GHZ:
207
phy->mt76->cap.has_5ghz = true;
208
break;
209
case MT_EE_BAND_SEL_2GHZ:
210
phy->mt76->cap.has_2ghz = true;
211
break;
212
default:
213
phy->mt76->cap.has_2ghz = true;
214
phy->mt76->cap.has_5ghz = true;
215
break;
216
}
217
}
218
219
void mt7915_eeprom_parse_hw_cap(struct mt7915_dev *dev,
220
struct mt7915_phy *phy)
221
{
222
u8 path, nss, nss_max = 4, *eeprom = dev->mt76.eeprom.data;
223
struct mt76_phy *mphy = phy->mt76;
224
u8 band = phy->mt76->band_idx;
225
226
mt7915_eeprom_parse_band_config(phy);
227
228
/* read tx/rx path from eeprom */
229
if (is_mt7915(&dev->mt76)) {
230
path = FIELD_GET(MT_EE_WIFI_CONF0_TX_PATH,
231
eeprom[MT_EE_WIFI_CONF]);
232
} else {
233
path = FIELD_GET(MT_EE_WIFI_CONF0_TX_PATH,
234
eeprom[MT_EE_WIFI_CONF + band]);
235
}
236
237
if (!path || path > 4)
238
path = 4;
239
240
/* read tx/rx stream */
241
nss = path;
242
if (dev->dbdc_support) {
243
if (is_mt7915(&dev->mt76)) {
244
path = min_t(u8, path, 2);
245
nss = FIELD_GET(MT_EE_WIFI_CONF3_TX_PATH_B0,
246
eeprom[MT_EE_WIFI_CONF + 3]);
247
if (band)
248
nss = FIELD_GET(MT_EE_WIFI_CONF3_TX_PATH_B1,
249
eeprom[MT_EE_WIFI_CONF + 3]);
250
} else {
251
nss = FIELD_GET(MT_EE_WIFI_CONF_STREAM_NUM,
252
eeprom[MT_EE_WIFI_CONF + 2 + band]);
253
}
254
255
if (!is_mt798x(&dev->mt76))
256
nss_max = 2;
257
}
258
259
if (!nss)
260
nss = nss_max;
261
nss = min_t(u8, min_t(u8, nss_max, nss), path);
262
263
mphy->chainmask = BIT(path) - 1;
264
if (band)
265
mphy->chainmask <<= dev->chainshift;
266
mphy->antenna_mask = BIT(nss) - 1;
267
dev->chainmask |= mphy->chainmask;
268
dev->chainshift = hweight8(dev->mphy.chainmask);
269
}
270
271
int mt7915_eeprom_init(struct mt7915_dev *dev)
272
{
273
int ret;
274
275
ret = mt7915_eeprom_load(dev);
276
if (ret < 0) {
277
if (ret != -EINVAL)
278
return ret;
279
280
dev_warn(dev->mt76.dev, "eeprom load fail, use default bin\n");
281
ret = mt7915_eeprom_load_default(dev);
282
if (ret)
283
return ret;
284
}
285
286
mt7915_eeprom_load_precal(dev);
287
mt7915_eeprom_parse_hw_cap(dev, &dev->phy);
288
#if defined(__linux__)
289
memcpy(dev->mphy.macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR,
290
#elif defined(__FreeBSD__)
291
memcpy(dev->mphy.macaddr, (u8 *)dev->mt76.eeprom.data + MT_EE_MAC_ADDR,
292
#endif
293
ETH_ALEN);
294
295
return mt76_eeprom_override(&dev->mphy);
296
}
297
298
int mt7915_eeprom_get_target_power(struct mt7915_dev *dev,
299
struct ieee80211_channel *chan,
300
u8 chain_idx)
301
{
302
u8 *eeprom = dev->mt76.eeprom.data;
303
int index, target_power;
304
bool tssi_on, is_7976;
305
306
if (chain_idx > 3)
307
return -EINVAL;
308
309
tssi_on = mt7915_tssi_enabled(dev, chan->band);
310
is_7976 = mt7915_check_adie(dev, false) || is_mt7916(&dev->mt76);
311
312
if (chan->band == NL80211_BAND_2GHZ) {
313
if (is_7976) {
314
index = MT_EE_TX0_POWER_2G_V2 + chain_idx;
315
target_power = eeprom[index];
316
} else {
317
index = MT_EE_TX0_POWER_2G + chain_idx * 3;
318
target_power = eeprom[index];
319
320
if (!tssi_on)
321
target_power += eeprom[index + 1];
322
}
323
} else if (chan->band == NL80211_BAND_5GHZ) {
324
int group = mt7915_get_channel_group_5g(chan->hw_value, is_7976);
325
326
if (is_7976) {
327
index = MT_EE_TX0_POWER_5G_V2 + chain_idx * 5;
328
target_power = eeprom[index + group];
329
} else {
330
index = MT_EE_TX0_POWER_5G + chain_idx * 12;
331
target_power = eeprom[index + group];
332
333
if (!tssi_on)
334
target_power += eeprom[index + 8];
335
}
336
} else {
337
int group = mt7915_get_channel_group_6g(chan->hw_value);
338
339
index = MT_EE_TX0_POWER_6G_V2 + chain_idx * 8;
340
target_power = is_7976 ? eeprom[index + group] : 0;
341
}
342
343
return target_power;
344
}
345
346
s8 mt7915_eeprom_get_power_delta(struct mt7915_dev *dev, int band)
347
{
348
u8 *eeprom = dev->mt76.eeprom.data;
349
u32 val, offs;
350
s8 delta;
351
bool is_7976 = mt7915_check_adie(dev, false) || is_mt7916(&dev->mt76);
352
353
if (band == NL80211_BAND_2GHZ)
354
offs = is_7976 ? MT_EE_RATE_DELTA_2G_V2 : MT_EE_RATE_DELTA_2G;
355
else if (band == NL80211_BAND_5GHZ)
356
offs = is_7976 ? MT_EE_RATE_DELTA_5G_V2 : MT_EE_RATE_DELTA_5G;
357
else
358
offs = is_7976 ? MT_EE_RATE_DELTA_6G_V2 : 0;
359
360
val = eeprom[offs];
361
362
if (!offs || !(val & MT_EE_RATE_DELTA_EN))
363
return 0;
364
365
delta = FIELD_GET(MT_EE_RATE_DELTA_MASK, val);
366
367
return val & MT_EE_RATE_DELTA_SIGN ? delta : -delta;
368
}
369
370
bool
371
mt7915_eeprom_has_background_radar(struct mt7915_dev *dev)
372
{
373
u8 val, buf[MT7915_EEPROM_BLOCK_SIZE];
374
u8 band_sel, tx_path, rx_path;
375
int offs = MT_EE_WIFI_CONF + 1;
376
377
switch (mt76_chip(&dev->mt76)) {
378
case 0x7915:
379
return true;
380
case 0x7906:
381
/* read efuse to check background radar capability */
382
if (mt7915_mcu_get_eeprom(dev, offs, buf))
383
break;
384
385
val = buf[offs % MT7915_EEPROM_BLOCK_SIZE];
386
band_sel = u8_get_bits(val, MT_EE_WIFI_CONF0_BAND_SEL);
387
tx_path = u8_get_bits(val, MT_EE_WIFI_CONF0_TX_PATH);
388
rx_path = u8_get_bits(val, MT_EE_WIFI_CONF0_RX_PATH);
389
390
return (band_sel == MT_EE_V2_BAND_SEL_5GHZ &&
391
tx_path == rx_path && rx_path == 2);
392
case 0x7981:
393
case 0x7986:
394
default:
395
break;
396
}
397
398
return false;
399
}
400
401
const u8 mt7915_sku_group_len[] = {
402
[SKU_CCK] = 4,
403
[SKU_OFDM] = 8,
404
[SKU_HT_BW20] = 8,
405
[SKU_HT_BW40] = 9,
406
[SKU_VHT_BW20] = 12,
407
[SKU_VHT_BW40] = 12,
408
[SKU_VHT_BW80] = 12,
409
[SKU_VHT_BW160] = 12,
410
[SKU_HE_RU26] = 12,
411
[SKU_HE_RU52] = 12,
412
[SKU_HE_RU106] = 12,
413
[SKU_HE_RU242] = 12,
414
[SKU_HE_RU484] = 12,
415
[SKU_HE_RU996] = 12,
416
[SKU_HE_RU2x996] = 12
417
};
418
419