1 // SPDX-License-Identifier: ISC
2 /* Copyright (C) 2020 MediaTek Inc. */
3 
4 #include <linux/firmware.h>
5 #include "mt7915.h"
6 #include "eeprom.h"
7 
8 static int mt7915_eeprom_load_precal(struct mt7915_dev *dev)
9 {
10 	struct mt76_dev *mdev = &dev->mt76;
11 	u8 *eeprom = mdev->eeprom.data;
12 	u32 val = eeprom[MT_EE_DO_PRE_CAL];
13 
14 	if (!dev->flash_mode)
15 		return 0;
16 
17 	if (val != (MT_EE_WIFI_CAL_DPD | MT_EE_WIFI_CAL_GROUP))
18 		return 0;
19 
20 	val = MT_EE_CAL_GROUP_SIZE + MT_EE_CAL_DPD_SIZE;
21 	dev->cal = devm_kzalloc(mdev->dev, val, GFP_KERNEL);
22 	if (!dev->cal)
23 		return -ENOMEM;
24 
25 	return mt76_get_of_eeprom(mdev, dev->cal, MT_EE_PRECAL, val);
26 }
27 
28 static int mt7915_check_eeprom(struct mt7915_dev *dev)
29 {
30 	u8 *eeprom = dev->mt76.eeprom.data;
31 	u16 val = get_unaligned_le16(eeprom);
32 
33 	switch (val) {
34 	case 0x7915:
35 		return 0;
36 	default:
37 		return -EINVAL;
38 	}
39 }
40 
41 static int
42 mt7915_eeprom_load_default(struct mt7915_dev *dev)
43 {
44 	char *default_bin = MT7915_EEPROM_DEFAULT;
45 	u8 *eeprom = dev->mt76.eeprom.data;
46 	const struct firmware *fw = NULL;
47 	int ret;
48 
49 	if (dev->dbdc_support)
50 		default_bin = MT7915_EEPROM_DEFAULT_DBDC;
51 
52 	ret = request_firmware(&fw, default_bin, dev->mt76.dev);
53 	if (ret)
54 		return ret;
55 
56 	if (!fw || !fw->data) {
57 		dev_err(dev->mt76.dev, "Invalid default bin\n");
58 		ret = -EINVAL;
59 		goto out;
60 	}
61 
62 	memcpy(eeprom, fw->data, MT7915_EEPROM_SIZE);
63 	dev->flash_mode = true;
64 
65 out:
66 	release_firmware(fw);
67 
68 	return ret;
69 }
70 
71 static int mt7915_eeprom_load(struct mt7915_dev *dev)
72 {
73 	int ret;
74 
75 	ret = mt76_eeprom_init(&dev->mt76, MT7915_EEPROM_SIZE);
76 	if (ret < 0)
77 		return ret;
78 
79 	if (ret) {
80 		dev->flash_mode = true;
81 	} else {
82 		u8 free_block_num;
83 		u32 block_num, i;
84 
85 		mt7915_mcu_get_eeprom_free_block(dev, &free_block_num);
86 		/* efuse info not enough */
87 		if (free_block_num >= 29)
88 			return -EINVAL;
89 
90 		/* read eeprom data from efuse */
91 		block_num = DIV_ROUND_UP(MT7915_EEPROM_SIZE,
92 					 MT7915_EEPROM_BLOCK_SIZE);
93 		for (i = 0; i < block_num; i++)
94 			mt7915_mcu_get_eeprom(dev,
95 					      i * MT7915_EEPROM_BLOCK_SIZE);
96 	}
97 
98 	return mt7915_check_eeprom(dev);
99 }
100 
101 void mt7915_eeprom_parse_band_config(struct mt7915_phy *phy)
102 {
103 	struct mt7915_dev *dev = phy->dev;
104 	bool ext_phy = phy != &dev->phy;
105 	u8 *eeprom = dev->mt76.eeprom.data;
106 	u32 val;
107 
108 	val = eeprom[MT_EE_WIFI_CONF + ext_phy];
109 	val = FIELD_GET(MT_EE_WIFI_CONF0_BAND_SEL, val);
110 	if (val == MT_EE_BAND_SEL_DEFAULT && dev->dbdc_support)
111 		val = ext_phy ? MT_EE_BAND_SEL_5GHZ : MT_EE_BAND_SEL_2GHZ;
112 
113 	switch (val) {
114 	case MT_EE_BAND_SEL_5GHZ:
115 		phy->mt76->cap.has_5ghz = true;
116 		break;
117 	case MT_EE_BAND_SEL_2GHZ:
118 		phy->mt76->cap.has_2ghz = true;
119 		break;
120 	default:
121 		phy->mt76->cap.has_2ghz = true;
122 		phy->mt76->cap.has_5ghz = true;
123 		break;
124 	}
125 }
126 
127 static void mt7915_eeprom_parse_hw_cap(struct mt7915_dev *dev)
128 {
129 	u8 nss, nss_band, *eeprom = dev->mt76.eeprom.data;
130 
131 	mt7915_eeprom_parse_band_config(&dev->phy);
132 
133 	/* read tx mask from eeprom */
134 	nss = FIELD_GET(MT_EE_WIFI_CONF0_TX_PATH, eeprom[MT_EE_WIFI_CONF]);
135 	if (!nss || nss > 4)
136 		nss = 4;
137 
138 	nss_band = nss;
139 
140 	if (dev->dbdc_support) {
141 		nss_band = FIELD_GET(MT_EE_WIFI_CONF3_TX_PATH_B0,
142 				     eeprom[MT_EE_WIFI_CONF + 3]);
143 		if (!nss_band || nss_band > 2)
144 			nss_band = 2;
145 
146 		if (nss_band >= nss)
147 			nss = 4;
148 	}
149 
150 	dev->chainmask = BIT(nss) - 1;
151 	dev->mphy.antenna_mask = BIT(nss_band) - 1;
152 	dev->mphy.chainmask = dev->mphy.antenna_mask;
153 }
154 
155 int mt7915_eeprom_init(struct mt7915_dev *dev)
156 {
157 	int ret;
158 
159 	ret = mt7915_eeprom_load(dev);
160 	if (ret < 0) {
161 		if (ret != -EINVAL)
162 			return ret;
163 
164 		dev_warn(dev->mt76.dev, "eeprom load fail, use default bin\n");
165 		ret = mt7915_eeprom_load_default(dev);
166 		if (ret)
167 			return ret;
168 	}
169 
170 	ret = mt7915_eeprom_load_precal(dev);
171 	if (ret)
172 		return ret;
173 
174 	mt7915_eeprom_parse_hw_cap(dev);
175 	memcpy(dev->mphy.macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR,
176 	       ETH_ALEN);
177 
178 	mt76_eeprom_override(&dev->mphy);
179 
180 	return 0;
181 }
182 
183 int mt7915_eeprom_get_target_power(struct mt7915_dev *dev,
184 				   struct ieee80211_channel *chan,
185 				   u8 chain_idx)
186 {
187 	u8 *eeprom = dev->mt76.eeprom.data;
188 	int index, target_power;
189 	bool tssi_on;
190 
191 	if (chain_idx > 3)
192 		return -EINVAL;
193 
194 	tssi_on = mt7915_tssi_enabled(dev, chan->band);
195 
196 	if (chan->band == NL80211_BAND_2GHZ) {
197 		index = MT_EE_TX0_POWER_2G + chain_idx * 3;
198 		target_power = eeprom[index];
199 
200 		if (!tssi_on)
201 			target_power += eeprom[index + 1];
202 	} else {
203 		int group = mt7915_get_channel_group(chan->hw_value);
204 
205 		index = MT_EE_TX0_POWER_5G + chain_idx * 12;
206 		target_power = eeprom[index + group];
207 
208 		if (!tssi_on)
209 			target_power += eeprom[index + 8];
210 	}
211 
212 	return target_power;
213 }
214 
215 s8 mt7915_eeprom_get_power_delta(struct mt7915_dev *dev, int band)
216 {
217 	u8 *eeprom = dev->mt76.eeprom.data;
218 	u32 val;
219 	s8 delta;
220 
221 	if (band == NL80211_BAND_2GHZ)
222 		val = eeprom[MT_EE_RATE_DELTA_2G];
223 	else
224 		val = eeprom[MT_EE_RATE_DELTA_5G];
225 
226 	if (!(val & MT_EE_RATE_DELTA_EN))
227 		return 0;
228 
229 	delta = FIELD_GET(MT_EE_RATE_DELTA_MASK, val);
230 
231 	return val & MT_EE_RATE_DELTA_SIGN ? delta : -delta;
232 }
233 
234 const u8 mt7915_sku_group_len[] = {
235 	[SKU_CCK] = 4,
236 	[SKU_OFDM] = 8,
237 	[SKU_HT_BW20] = 8,
238 	[SKU_HT_BW40] = 9,
239 	[SKU_VHT_BW20] = 12,
240 	[SKU_VHT_BW40] = 12,
241 	[SKU_VHT_BW80] = 12,
242 	[SKU_VHT_BW160] = 12,
243 	[SKU_HE_RU26] = 12,
244 	[SKU_HE_RU52] = 12,
245 	[SKU_HE_RU106] = 12,
246 	[SKU_HE_RU242] = 12,
247 	[SKU_HE_RU484] = 12,
248 	[SKU_HE_RU996] = 12,
249 	[SKU_HE_RU2x996] = 12
250 };
251