blob: 6dbaaf95ee3859682e59c119c46d46fbabc001ab [file] [log] [blame]
developer0f312e82022-11-01 12:31:52 +08001// SPDX-License-Identifier: ISC
2/* Copyright (C) 2019 MediaTek Inc.
3 *
4 * Author: Ryder Lee <ryder.lee@mediatek.com>
5 * Felix Fietkau <nbd@nbd.name>
6 */
7
8#include <linux/of.h>
9#include "mt7615.h"
10#include "eeprom.h"
11
12static int mt7615_efuse_read(struct mt7615_dev *dev, u32 base,
13 u16 addr, u8 *data)
14{
15 u32 val;
16 int i;
17
18 val = mt76_rr(dev, base + MT_EFUSE_CTRL);
19 val &= ~(MT_EFUSE_CTRL_AIN | MT_EFUSE_CTRL_MODE);
20 val |= FIELD_PREP(MT_EFUSE_CTRL_AIN, addr & ~0xf);
21 val |= MT_EFUSE_CTRL_KICK;
22 mt76_wr(dev, base + MT_EFUSE_CTRL, val);
23
24 if (!mt76_poll(dev, base + MT_EFUSE_CTRL, MT_EFUSE_CTRL_KICK, 0, 1000))
25 return -ETIMEDOUT;
26
27 udelay(2);
28
29 val = mt76_rr(dev, base + MT_EFUSE_CTRL);
30 if ((val & MT_EFUSE_CTRL_AOUT) == MT_EFUSE_CTRL_AOUT ||
31 WARN_ON_ONCE(!(val & MT_EFUSE_CTRL_VALID))) {
32 memset(data, 0x0, 16);
33 return 0;
34 }
35
36 for (i = 0; i < 4; i++) {
37 val = mt76_rr(dev, base + MT_EFUSE_RDATA(i));
38 put_unaligned_le32(val, data + 4 * i);
39 }
40
41 return 0;
42}
43
44static int mt7615_efuse_init(struct mt7615_dev *dev, u32 base)
45{
46 int i, len = MT7615_EEPROM_SIZE;
47 void *buf;
48 u32 val;
49
50 val = mt76_rr(dev, base + MT_EFUSE_BASE_CTRL);
51 if (val & MT_EFUSE_BASE_CTRL_EMPTY)
52 return 0;
53
54 dev->mt76.otp.data = devm_kzalloc(dev->mt76.dev, len, GFP_KERNEL);
55 dev->mt76.otp.size = len;
56 if (!dev->mt76.otp.data)
57 return -ENOMEM;
58
59 buf = dev->mt76.otp.data;
60 for (i = 0; i + 16 <= len; i += 16) {
61 int ret;
62
63 ret = mt7615_efuse_read(dev, base, i, buf + i);
64 if (ret)
65 return ret;
66 }
67
68 return 0;
69}
70
71static int mt7615_eeprom_load(struct mt7615_dev *dev, u32 addr)
72{
73 int ret;
74
75 ret = mt76_eeprom_init(&dev->mt76, MT7615_EEPROM_FULL_SIZE);
76 if (ret < 0)
77 return ret;
78
79 return mt7615_efuse_init(dev, addr);
80}
81
82static int mt7615_check_eeprom(struct mt76_dev *dev)
83{
84 u16 val = get_unaligned_le16(dev->eeprom.data);
85
86 switch (val) {
87 case 0x7615:
88 case 0x7622:
89 case 0x7663:
90 return 0;
91 default:
92 return -EINVAL;
93 }
94}
95
96static void
97mt7615_eeprom_parse_hw_band_cap(struct mt7615_dev *dev)
98{
99 u8 val, *eeprom = dev->mt76.eeprom.data;
100
101 if (is_mt7663(&dev->mt76)) {
102 /* dual band */
103 dev->mphy.cap.has_2ghz = true;
104 dev->mphy.cap.has_5ghz = true;
105 return;
106 }
107
108 if (is_mt7622(&dev->mt76)) {
109 /* 2GHz only */
110 dev->mphy.cap.has_2ghz = true;
111 return;
112 }
113
114 if (is_mt7611(&dev->mt76)) {
115 /* 5GHz only */
116 dev->mphy.cap.has_5ghz = true;
117 return;
118 }
119
120 val = FIELD_GET(MT_EE_NIC_WIFI_CONF_BAND_SEL,
121 eeprom[MT_EE_WIFI_CONF]);
122 switch (val) {
123 case MT_EE_5GHZ:
124 dev->mphy.cap.has_5ghz = true;
125 break;
126 case MT_EE_2GHZ:
127 dev->mphy.cap.has_2ghz = true;
128 break;
129 case MT_EE_DBDC:
130 dev->dbdc_support = true;
131 fallthrough;
132 default:
133 dev->mphy.cap.has_2ghz = true;
134 dev->mphy.cap.has_5ghz = true;
135 break;
136 }
137}
138
139static void mt7615_eeprom_parse_hw_cap(struct mt7615_dev *dev)
140{
141 u8 *eeprom = dev->mt76.eeprom.data;
142 u8 tx_mask, max_nss;
143
144 mt7615_eeprom_parse_hw_band_cap(dev);
145
146 if (is_mt7663(&dev->mt76)) {
147 max_nss = 2;
148 tx_mask = FIELD_GET(MT_EE_HW_CONF1_TX_MASK,
149 eeprom[MT7663_EE_HW_CONF1]);
150 } else {
151 u32 val;
152
153 /* read tx-rx mask from eeprom */
154 val = mt76_rr(dev, MT_TOP_STRAP_STA);
155 max_nss = val & MT_TOP_3NSS ? 3 : 4;
156
157 tx_mask = FIELD_GET(MT_EE_NIC_CONF_TX_MASK,
158 eeprom[MT_EE_NIC_CONF_0]);
159 }
160 if (!tx_mask || tx_mask > max_nss)
161 tx_mask = max_nss;
162
163 dev->chainmask = BIT(tx_mask) - 1;
164 dev->mphy.antenna_mask = dev->chainmask;
165 dev->mphy.chainmask = dev->chainmask;
166}
167
168static int mt7663_eeprom_get_target_power_index(struct mt7615_dev *dev,
169 struct ieee80211_channel *chan,
170 u8 chain_idx)
171{
172 int index, group;
173
174 if (chain_idx > 1)
175 return -EINVAL;
176
177 if (chan->band == NL80211_BAND_2GHZ)
178 return MT7663_EE_TX0_2G_TARGET_POWER + (chain_idx << 4);
179
180 group = mt7615_get_channel_group(chan->hw_value);
181 if (chain_idx == 1)
182 index = MT7663_EE_TX1_5G_G0_TARGET_POWER;
183 else
184 index = MT7663_EE_TX0_5G_G0_TARGET_POWER;
185
186 return index + group * 3;
187}
188
189int mt7615_eeprom_get_target_power_index(struct mt7615_dev *dev,
190 struct ieee80211_channel *chan,
191 u8 chain_idx)
192{
193 int index;
194
195 if (is_mt7663(&dev->mt76))
196 return mt7663_eeprom_get_target_power_index(dev, chan,
197 chain_idx);
198
199 if (chain_idx > 3)
200 return -EINVAL;
201
202 /* TSSI disabled */
203 if (mt7615_ext_pa_enabled(dev, chan->band)) {
204 if (chan->band == NL80211_BAND_2GHZ)
205 return MT_EE_EXT_PA_2G_TARGET_POWER;
206 else
207 return MT_EE_EXT_PA_5G_TARGET_POWER;
208 }
209
210 /* TSSI enabled */
211 if (chan->band == NL80211_BAND_2GHZ) {
212 index = MT_EE_TX0_2G_TARGET_POWER + chain_idx * 6;
213 } else {
214 int group = mt7615_get_channel_group(chan->hw_value);
215
216 switch (chain_idx) {
217 case 1:
218 index = MT_EE_TX1_5G_G0_TARGET_POWER;
219 break;
220 case 2:
221 index = MT_EE_TX2_5G_G0_TARGET_POWER;
222 break;
223 case 3:
224 index = MT_EE_TX3_5G_G0_TARGET_POWER;
225 break;
226 case 0:
227 default:
228 index = MT_EE_TX0_5G_G0_TARGET_POWER;
229 break;
230 }
231 index += 5 * group;
232 }
233
234 return index;
235}
236
237int mt7615_eeprom_get_power_delta_index(struct mt7615_dev *dev,
238 enum nl80211_band band)
239{
240 /* assume the first rate has the highest power offset */
241 if (is_mt7663(&dev->mt76)) {
242 if (band == NL80211_BAND_2GHZ)
243 return MT_EE_TX0_5G_G0_TARGET_POWER;
244 else
245 return MT7663_EE_5G_RATE_POWER;
246 }
247
248 if (band == NL80211_BAND_2GHZ)
249 return MT_EE_2G_RATE_POWER;
250 else
251 return MT_EE_5G_RATE_POWER;
252}
253
254static void mt7615_apply_cal_free_data(struct mt7615_dev *dev)
255{
256 static const u16 ical[] = {
257 0x53, 0x54, 0x55, 0x56, 0x57, 0x5c, 0x5d, 0x62, 0x63, 0x68,
258 0x69, 0x6e, 0x6f, 0x73, 0x74, 0x78, 0x79, 0x82, 0x83, 0x87,
259 0x88, 0x8c, 0x8d, 0x91, 0x92, 0x96, 0x97, 0x9b, 0x9c, 0xa0,
260 0xa1, 0xaa, 0xab, 0xaf, 0xb0, 0xb4, 0xb5, 0xb9, 0xba, 0xf4,
261 0xf7, 0xff,
262 0x140, 0x141, 0x145, 0x146, 0x14a, 0x14b, 0x154, 0x155, 0x159,
263 0x15a, 0x15e, 0x15f, 0x163, 0x164, 0x168, 0x169, 0x16d, 0x16e,
264 0x172, 0x173, 0x17c, 0x17d, 0x181, 0x182, 0x186, 0x187, 0x18b,
265 0x18c
266 };
267 static const u16 ical_nocheck[] = {
268 0x110, 0x111, 0x112, 0x113, 0x114, 0x115, 0x116, 0x117, 0x118,
269 0x1b5, 0x1b6, 0x1b7, 0x3ac, 0x3ad, 0x3ae, 0x3af, 0x3b0, 0x3b1,
270 0x3b2
271 };
272 u8 *eeprom = dev->mt76.eeprom.data;
273 u8 *otp = dev->mt76.otp.data;
274 int i;
275
276 if (!otp)
277 return;
278
279 for (i = 0; i < ARRAY_SIZE(ical); i++)
280 if (!otp[ical[i]])
281 return;
282
283 for (i = 0; i < ARRAY_SIZE(ical); i++)
284 eeprom[ical[i]] = otp[ical[i]];
285
286 for (i = 0; i < ARRAY_SIZE(ical_nocheck); i++)
287 eeprom[ical_nocheck[i]] = otp[ical_nocheck[i]];
288}
289
290static void mt7622_apply_cal_free_data(struct mt7615_dev *dev)
291{
292 static const u16 ical[] = {
293 0x53, 0x54, 0x55, 0x56, 0xf4, 0xf7, 0x144, 0x156, 0x15b
294 };
295 u8 *eeprom = dev->mt76.eeprom.data;
296 u8 *otp = dev->mt76.otp.data;
297 int i;
298
299 if (!otp)
300 return;
301
302 for (i = 0; i < ARRAY_SIZE(ical); i++) {
303 if (!otp[ical[i]])
304 continue;
305
306 eeprom[ical[i]] = otp[ical[i]];
307 }
308}
309
310static void mt7615_cal_free_data(struct mt7615_dev *dev)
311{
312 struct device_node *np = dev->mt76.dev->of_node;
313
314 if (!np || !of_property_read_bool(np, "mediatek,eeprom-merge-otp"))
315 return;
316
317 switch (mt76_chip(&dev->mt76)) {
318 case 0x7622:
319 mt7622_apply_cal_free_data(dev);
320 break;
321 case 0x7615:
322 case 0x7611:
323 mt7615_apply_cal_free_data(dev);
324 break;
325 }
326}
327
328int mt7615_eeprom_init(struct mt7615_dev *dev, u32 addr)
329{
330 int ret;
331
332 ret = mt7615_eeprom_load(dev, addr);
333 if (ret < 0)
334 return ret;
335
336 ret = mt7615_check_eeprom(&dev->mt76);
337 if (ret && dev->mt76.otp.data) {
338 memcpy(dev->mt76.eeprom.data, dev->mt76.otp.data,
339 MT7615_EEPROM_SIZE);
340 } else {
341 dev->flash_eeprom = true;
342 mt7615_cal_free_data(dev);
343 }
344
345 mt7615_eeprom_parse_hw_cap(dev);
346 memcpy(dev->mphy.macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR,
347 ETH_ALEN);
348
349 mt76_eeprom_override(&dev->mphy);
350
351 return 0;
352}
353EXPORT_SYMBOL_GPL(mt7615_eeprom_init);