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