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