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 		return 0;
88 	default:
89 		return -EINVAL;
90 	}
91 }
92 
93 static void mt7615_eeprom_parse_hw_cap(struct mt7615_dev *dev)
94 {
95 	u8 val, *eeprom = dev->mt76.eeprom.data;
96 
97 	val = FIELD_GET(MT_EE_NIC_WIFI_CONF_BAND_SEL,
98 			eeprom[MT_EE_WIFI_CONF]);
99 	switch (val) {
100 	case MT_EE_5GHZ:
101 		dev->mt76.cap.has_5ghz = true;
102 		break;
103 	case MT_EE_2GHZ:
104 		dev->mt76.cap.has_2ghz = true;
105 		break;
106 	default:
107 		dev->mt76.cap.has_2ghz = true;
108 		dev->mt76.cap.has_5ghz = true;
109 		break;
110 	}
111 }
112 
113 int mt7615_eeprom_get_power_index(struct mt7615_dev *dev,
114 				  struct ieee80211_channel *chan,
115 				  u8 chain_idx)
116 {
117 	int index;
118 
119 	if (chain_idx > 3)
120 		return -EINVAL;
121 
122 	/* TSSI disabled */
123 	if (mt7615_ext_pa_enabled(dev, chan->band)) {
124 		if (chan->band == NL80211_BAND_2GHZ)
125 			return MT_EE_EXT_PA_2G_TARGET_POWER;
126 		else
127 			return MT_EE_EXT_PA_5G_TARGET_POWER;
128 	}
129 
130 	/* TSSI enabled */
131 	if (chan->band == NL80211_BAND_2GHZ) {
132 		index = MT_EE_TX0_2G_TARGET_POWER + chain_idx * 6;
133 	} else {
134 		int group = mt7615_get_channel_group(chan->hw_value);
135 
136 		switch (chain_idx) {
137 		case 1:
138 			index = MT_EE_TX1_5G_G0_TARGET_POWER;
139 			break;
140 		case 2:
141 			index = MT_EE_TX2_5G_G0_TARGET_POWER;
142 			break;
143 		case 3:
144 			index = MT_EE_TX3_5G_G0_TARGET_POWER;
145 			break;
146 		case 0:
147 		default:
148 			index = MT_EE_TX0_5G_G0_TARGET_POWER;
149 			break;
150 		}
151 		index += 5 * group;
152 	}
153 
154 	return index;
155 }
156 
157 static void mt7615_apply_cal_free_data(struct mt7615_dev *dev)
158 {
159 	static const u16 ical[] = {
160 		0x53, 0x54, 0x55, 0x56, 0x57, 0x5c, 0x5d, 0x62, 0x63, 0x68,
161 		0x69, 0x6e, 0x6f, 0x73, 0x74, 0x78, 0x79, 0x82, 0x83, 0x87,
162 		0x88, 0x8c, 0x8d, 0x91, 0x92, 0x96, 0x97, 0x9b, 0x9c, 0xa0,
163 		0xa1, 0xaa, 0xab, 0xaf, 0xb0, 0xb4, 0xb5, 0xb9, 0xba, 0xf4,
164 		0xf7, 0xff,
165 		0x140, 0x141, 0x145, 0x146, 0x14a, 0x14b, 0x154, 0x155, 0x159,
166 		0x15a, 0x15e, 0x15f, 0x163, 0x164, 0x168, 0x169, 0x16d, 0x16e,
167 		0x172, 0x173, 0x17c, 0x17d, 0x181, 0x182, 0x186, 0x187, 0x18b,
168 		0x18c
169 	};
170 	static const u16 ical_nocheck[] = {
171 		0x110, 0x111, 0x112, 0x113, 0x114, 0x115, 0x116, 0x117, 0x118,
172 		0x1b5, 0x1b6, 0x1b7, 0x3ac, 0x3ad, 0x3ae, 0x3af, 0x3b0, 0x3b1,
173 		0x3b2
174 	};
175 	u8 *eeprom = dev->mt76.eeprom.data;
176 	u8 *otp = dev->mt76.otp.data;
177 	int i;
178 
179 	if (!otp)
180 		return;
181 
182 	for (i = 0; i < ARRAY_SIZE(ical); i++)
183 		if (!otp[ical[i]])
184 			return;
185 
186 	for (i = 0; i < ARRAY_SIZE(ical); i++)
187 		eeprom[ical[i]] = otp[ical[i]];
188 
189 	for (i = 0; i < ARRAY_SIZE(ical_nocheck); i++)
190 		eeprom[ical_nocheck[i]] = otp[ical_nocheck[i]];
191 }
192 
193 int mt7615_eeprom_init(struct mt7615_dev *dev)
194 {
195 	int ret;
196 
197 	ret = mt7615_eeprom_load(dev);
198 	if (ret < 0)
199 		return ret;
200 
201 	ret = mt7615_check_eeprom(&dev->mt76);
202 	if (ret && dev->mt76.otp.data)
203 		memcpy(dev->mt76.eeprom.data, dev->mt76.otp.data,
204 		       MT7615_EEPROM_SIZE);
205 	else
206 		mt7615_apply_cal_free_data(dev);
207 
208 	mt7615_eeprom_parse_hw_cap(dev);
209 	memcpy(dev->mt76.macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR,
210 	       ETH_ALEN);
211 
212 	mt76_eeprom_override(&dev->mt76);
213 
214 	return 0;
215 }
216