xref: /linux/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c (revision 65c93628599dff4cd7cfb70130d1f6a2203731ea)
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 "mt7615.h"
9 #include "eeprom.h"
10 
11 static int mt7615_efuse_read(struct mt7615_dev *dev, u32 base,
12 			     u16 addr, u8 *data)
13 {
14 	u32 val;
15 	int i;
16 
17 	val = mt76_rr(dev, base + MT_EFUSE_CTRL);
18 	val &= ~(MT_EFUSE_CTRL_AIN | MT_EFUSE_CTRL_MODE);
19 	val |= FIELD_PREP(MT_EFUSE_CTRL_AIN, addr & ~0xf);
20 	val |= MT_EFUSE_CTRL_KICK;
21 	mt76_wr(dev, base + MT_EFUSE_CTRL, val);
22 
23 	if (!mt76_poll(dev, base + MT_EFUSE_CTRL, MT_EFUSE_CTRL_KICK, 0, 1000))
24 		return -ETIMEDOUT;
25 
26 	udelay(2);
27 
28 	val = mt76_rr(dev, base + MT_EFUSE_CTRL);
29 	if ((val & MT_EFUSE_CTRL_AOUT) == MT_EFUSE_CTRL_AOUT ||
30 	    WARN_ON_ONCE(!(val & MT_EFUSE_CTRL_VALID))) {
31 		memset(data, 0x0, 16);
32 		return 0;
33 	}
34 
35 	for (i = 0; i < 4; i++) {
36 		val = mt76_rr(dev, base + MT_EFUSE_RDATA(i));
37 		put_unaligned_le32(val, data + 4 * i);
38 	}
39 
40 	return 0;
41 }
42 
43 static int mt7615_efuse_init(struct mt7615_dev *dev)
44 {
45 	u32 val, base = mt7615_reg_map(dev, MT_EFUSE_BASE);
46 	int i, len = MT7615_EEPROM_SIZE;
47 	void *buf;
48 
49 	val = mt76_rr(dev, base + MT_EFUSE_BASE_CTRL);
50 	if (val & MT_EFUSE_BASE_CTRL_EMPTY)
51 		return 0;
52 
53 	dev->mt76.otp.data = devm_kzalloc(dev->mt76.dev, len, GFP_KERNEL);
54 	dev->mt76.otp.size = len;
55 	if (!dev->mt76.otp.data)
56 		return -ENOMEM;
57 
58 	buf = dev->mt76.otp.data;
59 	for (i = 0; i + 16 <= len; i += 16) {
60 		int ret;
61 
62 		ret = mt7615_efuse_read(dev, base, i, buf + i);
63 		if (ret)
64 			return ret;
65 	}
66 
67 	return 0;
68 }
69 
70 static int mt7615_eeprom_load(struct mt7615_dev *dev)
71 {
72 	int ret;
73 
74 	ret = mt76_eeprom_init(&dev->mt76, MT7615_EEPROM_SIZE);
75 	if (ret < 0)
76 		return ret;
77 
78 	return mt7615_efuse_init(dev);
79 }
80 
81 static int mt7615_check_eeprom(struct mt76_dev *dev)
82 {
83 	u16 val = get_unaligned_le16(dev->eeprom.data);
84 
85 	switch (val) {
86 	case 0x7615:
87 	case 0x7622:
88 		return 0;
89 	default:
90 		return -EINVAL;
91 	}
92 }
93 
94 static void mt7615_eeprom_parse_hw_cap(struct mt7615_dev *dev)
95 {
96 	u8 *eeprom = dev->mt76.eeprom.data;
97 	u8 tx_mask, max_nss;
98 	u32 val;
99 
100 	val = FIELD_GET(MT_EE_NIC_WIFI_CONF_BAND_SEL,
101 			eeprom[MT_EE_WIFI_CONF]);
102 	switch (val) {
103 	case MT_EE_5GHZ:
104 		dev->mt76.cap.has_5ghz = true;
105 		break;
106 	case MT_EE_2GHZ:
107 		dev->mt76.cap.has_2ghz = true;
108 		break;
109 	default:
110 		dev->mt76.cap.has_2ghz = true;
111 		dev->mt76.cap.has_5ghz = true;
112 		break;
113 	}
114 
115 	if (is_mt7622(&dev->mt76))
116 		dev->mt76.cap.has_5ghz = false;
117 
118 	/* read tx-rx mask from eeprom */
119 	val = mt76_rr(dev, MT_TOP_STRAP_STA);
120 	max_nss = val & MT_TOP_3NSS ? 3 : 4;
121 
122 	tx_mask =  FIELD_GET(MT_EE_NIC_CONF_TX_MASK,
123 			     eeprom[MT_EE_NIC_CONF_0]);
124 	if (!tx_mask || tx_mask > max_nss)
125 		tx_mask = max_nss;
126 
127 	dev->chainmask = BIT(tx_mask) - 1;
128 	dev->mphy.antenna_mask = dev->chainmask;
129 	dev->phy.chainmask = dev->chainmask;
130 }
131 
132 int mt7615_eeprom_get_power_index(struct mt7615_dev *dev,
133 				  struct ieee80211_channel *chan,
134 				  u8 chain_idx)
135 {
136 	int index;
137 
138 	if (chain_idx > 3)
139 		return -EINVAL;
140 
141 	/* TSSI disabled */
142 	if (mt7615_ext_pa_enabled(dev, chan->band)) {
143 		if (chan->band == NL80211_BAND_2GHZ)
144 			return MT_EE_EXT_PA_2G_TARGET_POWER;
145 		else
146 			return MT_EE_EXT_PA_5G_TARGET_POWER;
147 	}
148 
149 	/* TSSI enabled */
150 	if (chan->band == NL80211_BAND_2GHZ) {
151 		index = MT_EE_TX0_2G_TARGET_POWER + chain_idx * 6;
152 	} else {
153 		int group = mt7615_get_channel_group(chan->hw_value);
154 
155 		switch (chain_idx) {
156 		case 1:
157 			index = MT_EE_TX1_5G_G0_TARGET_POWER;
158 			break;
159 		case 2:
160 			index = MT_EE_TX2_5G_G0_TARGET_POWER;
161 			break;
162 		case 3:
163 			index = MT_EE_TX3_5G_G0_TARGET_POWER;
164 			break;
165 		case 0:
166 		default:
167 			index = MT_EE_TX0_5G_G0_TARGET_POWER;
168 			break;
169 		}
170 		index += 5 * group;
171 	}
172 
173 	return index;
174 }
175 
176 static void mt7615_apply_cal_free_data(struct mt7615_dev *dev)
177 {
178 	static const u16 ical[] = {
179 		0x53, 0x54, 0x55, 0x56, 0x57, 0x5c, 0x5d, 0x62, 0x63, 0x68,
180 		0x69, 0x6e, 0x6f, 0x73, 0x74, 0x78, 0x79, 0x82, 0x83, 0x87,
181 		0x88, 0x8c, 0x8d, 0x91, 0x92, 0x96, 0x97, 0x9b, 0x9c, 0xa0,
182 		0xa1, 0xaa, 0xab, 0xaf, 0xb0, 0xb4, 0xb5, 0xb9, 0xba, 0xf4,
183 		0xf7, 0xff,
184 		0x140, 0x141, 0x145, 0x146, 0x14a, 0x14b, 0x154, 0x155, 0x159,
185 		0x15a, 0x15e, 0x15f, 0x163, 0x164, 0x168, 0x169, 0x16d, 0x16e,
186 		0x172, 0x173, 0x17c, 0x17d, 0x181, 0x182, 0x186, 0x187, 0x18b,
187 		0x18c
188 	};
189 	static const u16 ical_nocheck[] = {
190 		0x110, 0x111, 0x112, 0x113, 0x114, 0x115, 0x116, 0x117, 0x118,
191 		0x1b5, 0x1b6, 0x1b7, 0x3ac, 0x3ad, 0x3ae, 0x3af, 0x3b0, 0x3b1,
192 		0x3b2
193 	};
194 	u8 *eeprom = dev->mt76.eeprom.data;
195 	u8 *otp = dev->mt76.otp.data;
196 	int i;
197 
198 	if (!otp)
199 		return;
200 
201 	for (i = 0; i < ARRAY_SIZE(ical); i++)
202 		if (!otp[ical[i]])
203 			return;
204 
205 	for (i = 0; i < ARRAY_SIZE(ical); i++)
206 		eeprom[ical[i]] = otp[ical[i]];
207 
208 	for (i = 0; i < ARRAY_SIZE(ical_nocheck); i++)
209 		eeprom[ical_nocheck[i]] = otp[ical_nocheck[i]];
210 }
211 
212 static void mt7622_apply_cal_free_data(struct mt7615_dev *dev)
213 {
214 	static const u16 ical[] = {
215 		0x53, 0x54, 0x55, 0x56, 0xf4, 0xf7, 0x144, 0x156, 0x15b
216 	};
217 	u8 *eeprom = dev->mt76.eeprom.data;
218 	u8 *otp = dev->mt76.otp.data;
219 	int i;
220 
221 	if (!otp)
222 		return;
223 
224 	for (i = 0; i < ARRAY_SIZE(ical); i++) {
225 		if (!otp[ical[i]])
226 			continue;
227 
228 		eeprom[ical[i]] = otp[ical[i]];
229 	}
230 }
231 
232 int mt7615_eeprom_init(struct mt7615_dev *dev)
233 {
234 	int ret;
235 
236 	ret = mt7615_eeprom_load(dev);
237 	if (ret < 0)
238 		return ret;
239 
240 	ret = mt7615_check_eeprom(&dev->mt76);
241 	if (ret && dev->mt76.otp.data)
242 		memcpy(dev->mt76.eeprom.data, dev->mt76.otp.data,
243 		       MT7615_EEPROM_SIZE);
244 	else if (is_mt7622(&dev->mt76))
245 		mt7622_apply_cal_free_data(dev);
246 	else
247 		mt7615_apply_cal_free_data(dev);
248 
249 	mt7615_eeprom_parse_hw_cap(dev);
250 	memcpy(dev->mt76.macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR,
251 	       ETH_ALEN);
252 
253 	mt76_eeprom_override(&dev->mt76);
254 
255 	return 0;
256 }
257