1e57b7901SRyder Lee // SPDX-License-Identifier: ISC
2e57b7901SRyder Lee /* Copyright (C) 2020 MediaTek Inc. */
3e57b7901SRyder Lee 
4e57b7901SRyder Lee #include "mt7915.h"
5e57b7901SRyder Lee #include "eeprom.h"
6e57b7901SRyder Lee 
7078b6d21SLorenzo Bianconi static u32 mt7915_eeprom_read(struct mt7915_dev *dev, u32 offset)
8e57b7901SRyder Lee {
9e57b7901SRyder Lee 	u8 *data = dev->mt76.eeprom.data;
10e57b7901SRyder Lee 
11078b6d21SLorenzo Bianconi 	if (data[offset] == 0xff)
12e57b7901SRyder Lee 		mt7915_mcu_get_eeprom(dev, offset);
13e57b7901SRyder Lee 
14e57b7901SRyder Lee 	return data[offset];
15e57b7901SRyder Lee }
16e57b7901SRyder Lee 
17495184acSRyder Lee static int mt7915_eeprom_load_precal(struct mt7915_dev *dev)
18495184acSRyder Lee {
19495184acSRyder Lee 	struct mt76_dev *mdev = &dev->mt76;
20495184acSRyder Lee 	u32 val;
21495184acSRyder Lee 
22495184acSRyder Lee 	val = mt7915_eeprom_read(dev, MT_EE_DO_PRE_CAL);
23495184acSRyder Lee 	if (val != (MT_EE_WIFI_CAL_DPD | MT_EE_WIFI_CAL_GROUP))
24495184acSRyder Lee 		return 0;
25495184acSRyder Lee 
26495184acSRyder Lee 	val = MT_EE_CAL_GROUP_SIZE + MT_EE_CAL_DPD_SIZE;
27495184acSRyder Lee 	dev->cal = devm_kzalloc(mdev->dev, val, GFP_KERNEL);
28495184acSRyder Lee 	if (!dev->cal)
29495184acSRyder Lee 		return -ENOMEM;
30495184acSRyder Lee 
31495184acSRyder Lee 	return mt76_get_of_eeprom(mdev, dev->cal, MT_EE_PRECAL, val);
32495184acSRyder Lee }
33495184acSRyder Lee 
34e57b7901SRyder Lee static int mt7915_eeprom_load(struct mt7915_dev *dev)
35e57b7901SRyder Lee {
36e57b7901SRyder Lee 	int ret;
37e57b7901SRyder Lee 
38e57b7901SRyder Lee 	ret = mt76_eeprom_init(&dev->mt76, MT7915_EEPROM_SIZE);
39e57b7901SRyder Lee 	if (ret < 0)
40e57b7901SRyder Lee 		return ret;
41e57b7901SRyder Lee 
42495184acSRyder Lee 	if (ret) {
4326f18380SShayne Chen 		dev->flash_mode = true;
44495184acSRyder Lee 		ret = mt7915_eeprom_load_precal(dev);
45495184acSRyder Lee 	} else {
46e57b7901SRyder Lee 		memset(dev->mt76.eeprom.data, -1, MT7915_EEPROM_SIZE);
47495184acSRyder Lee 	}
48e57b7901SRyder Lee 
49495184acSRyder Lee 	return ret;
50e57b7901SRyder Lee }
51e57b7901SRyder Lee 
52e57b7901SRyder Lee static int mt7915_check_eeprom(struct mt7915_dev *dev)
53e57b7901SRyder Lee {
54e57b7901SRyder Lee 	u8 *eeprom = dev->mt76.eeprom.data;
553d51a3e9SLorenzo Bianconi 	u16 val;
56e57b7901SRyder Lee 
573d51a3e9SLorenzo Bianconi 	mt7915_eeprom_read(dev, MT_EE_CHIP_ID);
58e57b7901SRyder Lee 	val = get_unaligned_le16(eeprom);
59e57b7901SRyder Lee 
60e57b7901SRyder Lee 	switch (val) {
61e57b7901SRyder Lee 	case 0x7915:
62e57b7901SRyder Lee 		return 0;
63e57b7901SRyder Lee 	default:
64e57b7901SRyder Lee 		return -EINVAL;
65e57b7901SRyder Lee 	}
66e57b7901SRyder Lee }
67e57b7901SRyder Lee 
684c430774SLorenzo Bianconi void mt7915_eeprom_parse_band_config(struct mt7915_phy *phy)
69e57b7901SRyder Lee {
704c430774SLorenzo Bianconi 	struct mt7915_dev *dev = phy->dev;
714c430774SLorenzo Bianconi 	bool ext_phy = phy != &dev->phy;
724c430774SLorenzo Bianconi 	u32 val;
73e57b7901SRyder Lee 
744c430774SLorenzo Bianconi 	val = mt7915_eeprom_read(dev, MT_EE_WIFI_CONF + ext_phy);
75f7fc2bbeSFelix Fietkau 	val = FIELD_GET(MT_EE_WIFI_CONF0_BAND_SEL, val);
7645a8b67aSFelix Fietkau 	if (val == MT_EE_BAND_SEL_DEFAULT && dev->dbdc_support)
7745a8b67aSFelix Fietkau 		val = ext_phy ? MT_EE_BAND_SEL_5GHZ : MT_EE_BAND_SEL_2GHZ;
7845a8b67aSFelix Fietkau 
79e57b7901SRyder Lee 	switch (val) {
8045a8b67aSFelix Fietkau 	case MT_EE_BAND_SEL_5GHZ:
814c430774SLorenzo Bianconi 		phy->mt76->cap.has_5ghz = true;
82e57b7901SRyder Lee 		break;
8345a8b67aSFelix Fietkau 	case MT_EE_BAND_SEL_2GHZ:
844c430774SLorenzo Bianconi 		phy->mt76->cap.has_2ghz = true;
85e57b7901SRyder Lee 		break;
86e57b7901SRyder Lee 	default:
874c430774SLorenzo Bianconi 		phy->mt76->cap.has_2ghz = true;
884c430774SLorenzo Bianconi 		phy->mt76->cap.has_5ghz = true;
89e57b7901SRyder Lee 		break;
90e57b7901SRyder Lee 	}
914c430774SLorenzo Bianconi }
924c430774SLorenzo Bianconi 
934c430774SLorenzo Bianconi static void mt7915_eeprom_parse_hw_cap(struct mt7915_dev *dev)
944c430774SLorenzo Bianconi {
95f7fc2bbeSFelix Fietkau 	u8 nss, nss_band, *eeprom = dev->mt76.eeprom.data;
964c430774SLorenzo Bianconi 
974c430774SLorenzo Bianconi 	mt7915_eeprom_parse_band_config(&dev->phy);
98e57b7901SRyder Lee 
99e57b7901SRyder Lee 	/* read tx mask from eeprom */
100f7fc2bbeSFelix Fietkau 	nss = FIELD_GET(MT_EE_WIFI_CONF0_TX_PATH, eeprom[MT_EE_WIFI_CONF]);
101f7fc2bbeSFelix Fietkau 	if (!nss || nss > 4)
102f7fc2bbeSFelix Fietkau 		nss = 4;
103e57b7901SRyder Lee 
104f7fc2bbeSFelix Fietkau 	nss_band = nss;
105f7fc2bbeSFelix Fietkau 
106f7fc2bbeSFelix Fietkau 	if (dev->dbdc_support) {
107f7fc2bbeSFelix Fietkau 		nss_band = FIELD_GET(MT_EE_WIFI_CONF3_TX_PATH_B0,
108f7fc2bbeSFelix Fietkau 				     eeprom[MT_EE_WIFI_CONF + 3]);
109f7fc2bbeSFelix Fietkau 		if (!nss_band || nss_band > 2)
110f7fc2bbeSFelix Fietkau 			nss_band = 2;
111f7fc2bbeSFelix Fietkau 
112f7fc2bbeSFelix Fietkau 		if (nss_band >= nss)
1134c430774SLorenzo Bianconi 			nss = 4;
1144c430774SLorenzo Bianconi 	}
1154c430774SLorenzo Bianconi 
1164c430774SLorenzo Bianconi 	dev->chainmask = BIT(nss) - 1;
117f7fc2bbeSFelix Fietkau 	dev->mphy.antenna_mask = BIT(nss_band) - 1;
118b9027e08SLorenzo Bianconi 	dev->mphy.chainmask = dev->mphy.antenna_mask;
119e57b7901SRyder Lee }
120e57b7901SRyder Lee 
121e57b7901SRyder Lee int mt7915_eeprom_init(struct mt7915_dev *dev)
122e57b7901SRyder Lee {
123e57b7901SRyder Lee 	int ret;
124e57b7901SRyder Lee 
125e57b7901SRyder Lee 	ret = mt7915_eeprom_load(dev);
126e57b7901SRyder Lee 	if (ret < 0)
127e57b7901SRyder Lee 		return ret;
128e57b7901SRyder Lee 
129e57b7901SRyder Lee 	ret = mt7915_check_eeprom(dev);
130e57b7901SRyder Lee 	if (ret)
131e57b7901SRyder Lee 		return ret;
132e57b7901SRyder Lee 
133e57b7901SRyder Lee 	mt7915_eeprom_parse_hw_cap(dev);
13498df2baeSLorenzo Bianconi 	memcpy(dev->mphy.macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR,
135e57b7901SRyder Lee 	       ETH_ALEN);
136e57b7901SRyder Lee 
13798df2baeSLorenzo Bianconi 	mt76_eeprom_override(&dev->mphy);
138e57b7901SRyder Lee 
139e57b7901SRyder Lee 	return 0;
140e57b7901SRyder Lee }
141e57b7901SRyder Lee 
142e57b7901SRyder Lee int mt7915_eeprom_get_target_power(struct mt7915_dev *dev,
143e57b7901SRyder Lee 				   struct ieee80211_channel *chan,
144e57b7901SRyder Lee 				   u8 chain_idx)
145e57b7901SRyder Lee {
146a226ccd0SShayne Chen 	int index, target_power;
147e57b7901SRyder Lee 	bool tssi_on;
148e57b7901SRyder Lee 
149e57b7901SRyder Lee 	if (chain_idx > 3)
150e57b7901SRyder Lee 		return -EINVAL;
151e57b7901SRyder Lee 
152e57b7901SRyder Lee 	tssi_on = mt7915_tssi_enabled(dev, chan->band);
153e57b7901SRyder Lee 
154e57b7901SRyder Lee 	if (chan->band == NL80211_BAND_2GHZ) {
155a226ccd0SShayne Chen 		index = MT_EE_TX0_POWER_2G + chain_idx * 3;
156a226ccd0SShayne Chen 		target_power = mt7915_eeprom_read(dev, index);
157e57b7901SRyder Lee 
158a226ccd0SShayne Chen 		if (!tssi_on)
159a226ccd0SShayne Chen 			target_power += mt7915_eeprom_read(dev, index + 1);
160a226ccd0SShayne Chen 	} else {
161a226ccd0SShayne Chen 		int group = mt7915_get_channel_group(chan->hw_value);
162a226ccd0SShayne Chen 
163a226ccd0SShayne Chen 		index = MT_EE_TX0_POWER_5G + chain_idx * 12;
164a226ccd0SShayne Chen 		target_power = mt7915_eeprom_read(dev, index + group);
165a226ccd0SShayne Chen 
166a226ccd0SShayne Chen 		if (!tssi_on)
167a226ccd0SShayne Chen 			target_power += mt7915_eeprom_read(dev, index + 8);
168e57b7901SRyder Lee 	}
169e57b7901SRyder Lee 
170a226ccd0SShayne Chen 	return target_power;
171e57b7901SRyder Lee }
172f1d96236SRyder Lee 
173*ecb187a7SShayne Chen s8 mt7915_eeprom_get_power_delta(struct mt7915_dev *dev, int band)
174f1d96236SRyder Lee {
175*ecb187a7SShayne Chen 	u32 val;
176*ecb187a7SShayne Chen 	s8 delta;
177f1d96236SRyder Lee 
178*ecb187a7SShayne Chen 	if (band == NL80211_BAND_2GHZ)
179*ecb187a7SShayne Chen 		val = mt7915_eeprom_read(dev, MT_EE_RATE_DELTA_2G);
180*ecb187a7SShayne Chen 	else
181*ecb187a7SShayne Chen 		val = mt7915_eeprom_read(dev, MT_EE_RATE_DELTA_5G);
182*ecb187a7SShayne Chen 
183*ecb187a7SShayne Chen 	if (!(val & MT_EE_RATE_DELTA_EN))
184f1d96236SRyder Lee 		return 0;
185f1d96236SRyder Lee 
186*ecb187a7SShayne Chen 	delta = FIELD_GET(MT_EE_RATE_DELTA_MASK, val);
187*ecb187a7SShayne Chen 
188*ecb187a7SShayne Chen 	return val & MT_EE_RATE_DELTA_SIGN ? delta : -delta;
189f1d96236SRyder Lee }
190f1d96236SRyder Lee 
191*ecb187a7SShayne Chen const u8 mt7915_sku_group_len[] = {
192*ecb187a7SShayne Chen 	[SKU_CCK] = 4,
193*ecb187a7SShayne Chen 	[SKU_OFDM] = 8,
194*ecb187a7SShayne Chen 	[SKU_HT_BW20] = 8,
195*ecb187a7SShayne Chen 	[SKU_HT_BW40] = 9,
196*ecb187a7SShayne Chen 	[SKU_VHT_BW20] = 12,
197*ecb187a7SShayne Chen 	[SKU_VHT_BW40] = 12,
198*ecb187a7SShayne Chen 	[SKU_VHT_BW80] = 12,
199*ecb187a7SShayne Chen 	[SKU_VHT_BW160] = 12,
200*ecb187a7SShayne Chen 	[SKU_HE_RU26] = 12,
201*ecb187a7SShayne Chen 	[SKU_HE_RU52] = 12,
202*ecb187a7SShayne Chen 	[SKU_HE_RU106] = 12,
203*ecb187a7SShayne Chen 	[SKU_HE_RU242] = 12,
204*ecb187a7SShayne Chen 	[SKU_HE_RU484] = 12,
205*ecb187a7SShayne Chen 	[SKU_HE_RU996] = 12,
206*ecb187a7SShayne Chen 	[SKU_HE_RU2x996] = 12
207*ecb187a7SShayne Chen };
208