17f17b86aSRyder Lee // SPDX-License-Identifier: ISC
2c8846e10SFelix Fietkau 
36d3390a6SFelix Fietkau #include <linux/of.h>
4c8846e10SFelix Fietkau #include "mt7603.h"
5c8846e10SFelix Fietkau #include "eeprom.h"
6c8846e10SFelix Fietkau 
7c8846e10SFelix Fietkau static int
mt7603_efuse_read(struct mt7603_dev * dev,u32 base,u16 addr,u8 * data)8c8846e10SFelix Fietkau mt7603_efuse_read(struct mt7603_dev *dev, u32 base, u16 addr, u8 *data)
9c8846e10SFelix Fietkau {
10c8846e10SFelix Fietkau 	u32 val;
11c8846e10SFelix Fietkau 	int i;
12c8846e10SFelix Fietkau 
13c8846e10SFelix Fietkau 	val = mt76_rr(dev, base + MT_EFUSE_CTRL);
14c8846e10SFelix Fietkau 	val &= ~(MT_EFUSE_CTRL_AIN |
15c8846e10SFelix Fietkau 		 MT_EFUSE_CTRL_MODE);
16c8846e10SFelix Fietkau 	val |= FIELD_PREP(MT_EFUSE_CTRL_AIN, addr & ~0xf);
17c8846e10SFelix Fietkau 	val |= MT_EFUSE_CTRL_KICK;
18c8846e10SFelix Fietkau 	mt76_wr(dev, base + MT_EFUSE_CTRL, val);
19c8846e10SFelix Fietkau 
20c8846e10SFelix Fietkau 	if (!mt76_poll(dev, base + MT_EFUSE_CTRL, MT_EFUSE_CTRL_KICK, 0, 1000))
21c8846e10SFelix Fietkau 		return -ETIMEDOUT;
22c8846e10SFelix Fietkau 
23c8846e10SFelix Fietkau 	udelay(2);
24c8846e10SFelix Fietkau 
25c8846e10SFelix Fietkau 	val = mt76_rr(dev, base + MT_EFUSE_CTRL);
26c8846e10SFelix Fietkau 	if ((val & MT_EFUSE_CTRL_AOUT) == MT_EFUSE_CTRL_AOUT ||
27c8846e10SFelix Fietkau 	    WARN_ON_ONCE(!(val & MT_EFUSE_CTRL_VALID))) {
28c8846e10SFelix Fietkau 		memset(data, 0xff, 16);
29c8846e10SFelix Fietkau 		return 0;
30c8846e10SFelix Fietkau 	}
31c8846e10SFelix Fietkau 
32c8846e10SFelix Fietkau 	for (i = 0; i < 4; i++) {
33c8846e10SFelix Fietkau 		val = mt76_rr(dev, base + MT_EFUSE_RDATA(i));
34c8846e10SFelix Fietkau 		put_unaligned_le32(val, data + 4 * i);
35c8846e10SFelix Fietkau 	}
36c8846e10SFelix Fietkau 
37c8846e10SFelix Fietkau 	return 0;
38c8846e10SFelix Fietkau }
39c8846e10SFelix Fietkau 
40c8846e10SFelix Fietkau static int
mt7603_efuse_init(struct mt7603_dev * dev)41c8846e10SFelix Fietkau mt7603_efuse_init(struct mt7603_dev *dev)
42c8846e10SFelix Fietkau {
43c8846e10SFelix Fietkau 	u32 base = mt7603_reg_map(dev, MT_EFUSE_BASE);
44c8846e10SFelix Fietkau 	int len = MT7603_EEPROM_SIZE;
45c8846e10SFelix Fietkau 	void *buf;
46c8846e10SFelix Fietkau 	int ret, i;
47c8846e10SFelix Fietkau 
48c8846e10SFelix Fietkau 	if (mt76_rr(dev, base + MT_EFUSE_BASE_CTRL) & MT_EFUSE_BASE_CTRL_EMPTY)
49c8846e10SFelix Fietkau 		return 0;
50c8846e10SFelix Fietkau 
51c8846e10SFelix Fietkau 	dev->mt76.otp.data = devm_kzalloc(dev->mt76.dev, len, GFP_KERNEL);
52c8846e10SFelix Fietkau 	dev->mt76.otp.size = len;
53c8846e10SFelix Fietkau 	if (!dev->mt76.otp.data)
54c8846e10SFelix Fietkau 		return -ENOMEM;
55c8846e10SFelix Fietkau 
56c8846e10SFelix Fietkau 	buf = dev->mt76.otp.data;
57c8846e10SFelix Fietkau 	for (i = 0; i + 16 <= len; i += 16) {
58c8846e10SFelix Fietkau 		ret = mt7603_efuse_read(dev, base, i, buf + i);
59c8846e10SFelix Fietkau 		if (ret)
60c8846e10SFelix Fietkau 			return ret;
61c8846e10SFelix Fietkau 	}
62c8846e10SFelix Fietkau 
63c8846e10SFelix Fietkau 	return 0;
64c8846e10SFelix Fietkau }
65c8846e10SFelix Fietkau 
66c8846e10SFelix Fietkau static bool
mt7603_has_cal_free_data(struct mt7603_dev * dev,u8 * efuse)67c8846e10SFelix Fietkau mt7603_has_cal_free_data(struct mt7603_dev *dev, u8 *efuse)
68c8846e10SFelix Fietkau {
69c8846e10SFelix Fietkau 	if (!efuse[MT_EE_TEMP_SENSOR_CAL])
70c8846e10SFelix Fietkau 		return false;
71c8846e10SFelix Fietkau 
72c8846e10SFelix Fietkau 	if (get_unaligned_le16(efuse + MT_EE_TX_POWER_0_START_2G) == 0)
73c8846e10SFelix Fietkau 		return false;
74c8846e10SFelix Fietkau 
75c8846e10SFelix Fietkau 	if (get_unaligned_le16(efuse + MT_EE_TX_POWER_1_START_2G) == 0)
76c8846e10SFelix Fietkau 		return false;
77c8846e10SFelix Fietkau 
78c8846e10SFelix Fietkau 	if (!efuse[MT_EE_CP_FT_VERSION])
79c8846e10SFelix Fietkau 		return false;
80c8846e10SFelix Fietkau 
81c8846e10SFelix Fietkau 	if (!efuse[MT_EE_XTAL_FREQ_OFFSET])
82c8846e10SFelix Fietkau 		return false;
83c8846e10SFelix Fietkau 
84c8846e10SFelix Fietkau 	if (!efuse[MT_EE_XTAL_WF_RFCAL])
85c8846e10SFelix Fietkau 		return false;
86c8846e10SFelix Fietkau 
87c8846e10SFelix Fietkau 	return true;
88c8846e10SFelix Fietkau }
89c8846e10SFelix Fietkau 
90c8846e10SFelix Fietkau static void
mt7603_apply_cal_free_data(struct mt7603_dev * dev,u8 * efuse)91c8846e10SFelix Fietkau mt7603_apply_cal_free_data(struct mt7603_dev *dev, u8 *efuse)
92c8846e10SFelix Fietkau {
93c8846e10SFelix Fietkau 	static const u8 cal_free_bytes[] = {
94c8846e10SFelix Fietkau 		MT_EE_TEMP_SENSOR_CAL,
95c8846e10SFelix Fietkau 		MT_EE_CP_FT_VERSION,
96c8846e10SFelix Fietkau 		MT_EE_XTAL_FREQ_OFFSET,
97c8846e10SFelix Fietkau 		MT_EE_XTAL_WF_RFCAL,
98c8846e10SFelix Fietkau 		/* Skip for MT7628 */
99c8846e10SFelix Fietkau 		MT_EE_TX_POWER_0_START_2G,
100c8846e10SFelix Fietkau 		MT_EE_TX_POWER_0_START_2G + 1,
101c8846e10SFelix Fietkau 		MT_EE_TX_POWER_1_START_2G,
102c8846e10SFelix Fietkau 		MT_EE_TX_POWER_1_START_2G + 1,
103c8846e10SFelix Fietkau 	};
1046d3390a6SFelix Fietkau 	struct device_node *np = dev->mt76.dev->of_node;
105c8846e10SFelix Fietkau 	u8 *eeprom = dev->mt76.eeprom.data;
106c8846e10SFelix Fietkau 	int n = ARRAY_SIZE(cal_free_bytes);
107c8846e10SFelix Fietkau 	int i;
108c8846e10SFelix Fietkau 
1096d3390a6SFelix Fietkau 	if (!np || !of_property_read_bool(np, "mediatek,eeprom-merge-otp"))
1106d3390a6SFelix Fietkau 		return;
1116d3390a6SFelix Fietkau 
112c8846e10SFelix Fietkau 	if (!mt7603_has_cal_free_data(dev, efuse))
113c8846e10SFelix Fietkau 		return;
114c8846e10SFelix Fietkau 
115c8846e10SFelix Fietkau 	if (is_mt7628(dev))
116c8846e10SFelix Fietkau 		n -= 4;
117c8846e10SFelix Fietkau 
118c8846e10SFelix Fietkau 	for (i = 0; i < n; i++) {
119c8846e10SFelix Fietkau 		int offset = cal_free_bytes[i];
120c8846e10SFelix Fietkau 
121c8846e10SFelix Fietkau 		eeprom[offset] = efuse[offset];
122c8846e10SFelix Fietkau 	}
123c8846e10SFelix Fietkau }
124c8846e10SFelix Fietkau 
125c8846e10SFelix Fietkau static int
mt7603_eeprom_load(struct mt7603_dev * dev)126c8846e10SFelix Fietkau mt7603_eeprom_load(struct mt7603_dev *dev)
127c8846e10SFelix Fietkau {
128c8846e10SFelix Fietkau 	int ret;
129c8846e10SFelix Fietkau 
130c8846e10SFelix Fietkau 	ret = mt76_eeprom_init(&dev->mt76, MT7603_EEPROM_SIZE);
131c8846e10SFelix Fietkau 	if (ret < 0)
132c8846e10SFelix Fietkau 		return ret;
133c8846e10SFelix Fietkau 
134c8846e10SFelix Fietkau 	return mt7603_efuse_init(dev);
135c8846e10SFelix Fietkau }
136c8846e10SFelix Fietkau 
mt7603_check_eeprom(struct mt76_dev * dev)137c8846e10SFelix Fietkau static int mt7603_check_eeprom(struct mt76_dev *dev)
138c8846e10SFelix Fietkau {
139c8846e10SFelix Fietkau 	u16 val = get_unaligned_le16(dev->eeprom.data);
140c8846e10SFelix Fietkau 
141c8846e10SFelix Fietkau 	switch (val) {
142c8846e10SFelix Fietkau 	case 0x7628:
143c8846e10SFelix Fietkau 	case 0x7603:
144bf4a938aSDavid Bauer 	case 0x7600:
145c8846e10SFelix Fietkau 		return 0;
146c8846e10SFelix Fietkau 	default:
147c8846e10SFelix Fietkau 		return -EINVAL;
148c8846e10SFelix Fietkau 	}
149c8846e10SFelix Fietkau }
150c8846e10SFelix Fietkau 
is_mt7688(struct mt7603_dev * dev)151d407afcbSFelix Fietkau static inline bool is_mt7688(struct mt7603_dev *dev)
152d407afcbSFelix Fietkau {
153d407afcbSFelix Fietkau 	return mt76_rr(dev, MT_EFUSE_BASE + 0x64) & BIT(4);
154d407afcbSFelix Fietkau }
155d407afcbSFelix Fietkau 
mt7603_eeprom_init(struct mt7603_dev * dev)156c8846e10SFelix Fietkau int mt7603_eeprom_init(struct mt7603_dev *dev)
157c8846e10SFelix Fietkau {
158d407afcbSFelix Fietkau 	u8 *eeprom;
159c8846e10SFelix Fietkau 	int ret;
160c8846e10SFelix Fietkau 
161c8846e10SFelix Fietkau 	ret = mt7603_eeprom_load(dev);
162c8846e10SFelix Fietkau 	if (ret < 0)
163c8846e10SFelix Fietkau 		return ret;
164c8846e10SFelix Fietkau 
165c8846e10SFelix Fietkau 	if (dev->mt76.otp.data) {
166c8846e10SFelix Fietkau 		if (mt7603_check_eeprom(&dev->mt76) == 0)
167c8846e10SFelix Fietkau 			mt7603_apply_cal_free_data(dev, dev->mt76.otp.data);
168c8846e10SFelix Fietkau 		else
169c8846e10SFelix Fietkau 			memcpy(dev->mt76.eeprom.data, dev->mt76.otp.data,
170c8846e10SFelix Fietkau 			       MT7603_EEPROM_SIZE);
171c8846e10SFelix Fietkau 	}
172c8846e10SFelix Fietkau 
173d407afcbSFelix Fietkau 	eeprom = (u8 *)dev->mt76.eeprom.data;
17448dbce5cSLorenzo Bianconi 	dev->mphy.cap.has_2ghz = true;
175*98df2baeSLorenzo Bianconi 	memcpy(dev->mphy.macaddr, eeprom + MT_EE_MAC_ADDR, ETH_ALEN);
176d407afcbSFelix Fietkau 
177d407afcbSFelix Fietkau 	/* Check for 1SS devices */
178d407afcbSFelix Fietkau 	dev->mphy.antenna_mask = 3;
179d407afcbSFelix Fietkau 	if (FIELD_GET(MT_EE_NIC_CONF_0_RX_PATH, eeprom[MT_EE_NIC_CONF_0]) == 1 ||
180d407afcbSFelix Fietkau 	    FIELD_GET(MT_EE_NIC_CONF_0_TX_PATH, eeprom[MT_EE_NIC_CONF_0]) == 1 ||
181d407afcbSFelix Fietkau 	    is_mt7688(dev))
182d407afcbSFelix Fietkau 		dev->mphy.antenna_mask = 1;
183c8846e10SFelix Fietkau 
184*98df2baeSLorenzo Bianconi 	mt76_eeprom_override(&dev->mphy);
185c8846e10SFelix Fietkau 
186c8846e10SFelix Fietkau 	return 0;
187c8846e10SFelix Fietkau }
188