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