xref: /linux/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c (revision cdd5b5a9761fd66d17586e4f4ba6588c70e640ea)
104b8e659SRyder Lee // SPDX-License-Identifier: ISC
204b8e659SRyder Lee /* Copyright (C) 2019 MediaTek Inc.
304b8e659SRyder Lee  *
404b8e659SRyder Lee  * Author: Ryder Lee <ryder.lee@mediatek.com>
504b8e659SRyder Lee  *         Felix Fietkau <nbd@nbd.name>
604b8e659SRyder Lee  */
704b8e659SRyder Lee 
8b90728f8SFelix Fietkau #include <linux/of.h>
904b8e659SRyder Lee #include "mt7615.h"
1004b8e659SRyder Lee #include "eeprom.h"
1104b8e659SRyder Lee 
mt7615_efuse_read(struct mt7615_dev * dev,u32 base,u16 addr,u8 * data)1204b8e659SRyder Lee static int mt7615_efuse_read(struct mt7615_dev *dev, u32 base,
1304b8e659SRyder Lee 			     u16 addr, u8 *data)
1404b8e659SRyder Lee {
1504b8e659SRyder Lee 	u32 val;
1604b8e659SRyder Lee 	int i;
1704b8e659SRyder Lee 
1804b8e659SRyder Lee 	val = mt76_rr(dev, base + MT_EFUSE_CTRL);
1904b8e659SRyder Lee 	val &= ~(MT_EFUSE_CTRL_AIN | MT_EFUSE_CTRL_MODE);
2004b8e659SRyder Lee 	val |= FIELD_PREP(MT_EFUSE_CTRL_AIN, addr & ~0xf);
2104b8e659SRyder Lee 	val |= MT_EFUSE_CTRL_KICK;
2204b8e659SRyder Lee 	mt76_wr(dev, base + MT_EFUSE_CTRL, val);
2304b8e659SRyder Lee 
2404b8e659SRyder Lee 	if (!mt76_poll(dev, base + MT_EFUSE_CTRL, MT_EFUSE_CTRL_KICK, 0, 1000))
2504b8e659SRyder Lee 		return -ETIMEDOUT;
2604b8e659SRyder Lee 
2704b8e659SRyder Lee 	udelay(2);
2804b8e659SRyder Lee 
2904b8e659SRyder Lee 	val = mt76_rr(dev, base + MT_EFUSE_CTRL);
3004b8e659SRyder Lee 	if ((val & MT_EFUSE_CTRL_AOUT) == MT_EFUSE_CTRL_AOUT ||
3104b8e659SRyder Lee 	    WARN_ON_ONCE(!(val & MT_EFUSE_CTRL_VALID))) {
3204b8e659SRyder Lee 		memset(data, 0x0, 16);
3304b8e659SRyder Lee 		return 0;
3404b8e659SRyder Lee 	}
3504b8e659SRyder Lee 
3604b8e659SRyder Lee 	for (i = 0; i < 4; i++) {
3704b8e659SRyder Lee 		val = mt76_rr(dev, base + MT_EFUSE_RDATA(i));
3804b8e659SRyder Lee 		put_unaligned_le32(val, data + 4 * i);
3904b8e659SRyder Lee 	}
4004b8e659SRyder Lee 
4104b8e659SRyder Lee 	return 0;
4204b8e659SRyder Lee }
4304b8e659SRyder Lee 
mt7615_efuse_init(struct mt7615_dev * dev,u32 base)446e5d2099SLorenzo Bianconi static int mt7615_efuse_init(struct mt7615_dev *dev, u32 base)
4504b8e659SRyder Lee {
46f9461a68SLorenzo Bianconi 	int i, len = MT7615_EEPROM_SIZE;
4704b8e659SRyder Lee 	void *buf;
486e5d2099SLorenzo Bianconi 	u32 val;
4904b8e659SRyder Lee 
50e12b2e99SFelix Fietkau 	if (is_mt7663(&dev->mt76))
51e12b2e99SFelix Fietkau 		len = MT7663_EEPROM_SIZE;
52e12b2e99SFelix Fietkau 
53f9461a68SLorenzo Bianconi 	val = mt76_rr(dev, base + MT_EFUSE_BASE_CTRL);
54f9461a68SLorenzo Bianconi 	if (val & MT_EFUSE_BASE_CTRL_EMPTY)
55f9461a68SLorenzo Bianconi 		return 0;
5604b8e659SRyder Lee 
5704b8e659SRyder Lee 	dev->mt76.otp.data = devm_kzalloc(dev->mt76.dev, len, GFP_KERNEL);
5804b8e659SRyder Lee 	dev->mt76.otp.size = len;
5904b8e659SRyder Lee 	if (!dev->mt76.otp.data)
6004b8e659SRyder Lee 		return -ENOMEM;
6104b8e659SRyder Lee 
6204b8e659SRyder Lee 	buf = dev->mt76.otp.data;
6304b8e659SRyder Lee 	for (i = 0; i + 16 <= len; i += 16) {
64f9461a68SLorenzo Bianconi 		int ret;
65f9461a68SLorenzo Bianconi 
6604b8e659SRyder Lee 		ret = mt7615_efuse_read(dev, base, i, buf + i);
6704b8e659SRyder Lee 		if (ret)
6804b8e659SRyder Lee 			return ret;
6904b8e659SRyder Lee 	}
7004b8e659SRyder Lee 
7104b8e659SRyder Lee 	return 0;
7204b8e659SRyder Lee }
7304b8e659SRyder Lee 
mt7615_eeprom_load(struct mt7615_dev * dev,u32 addr)746e5d2099SLorenzo Bianconi static int mt7615_eeprom_load(struct mt7615_dev *dev, u32 addr)
7504b8e659SRyder Lee {
7604b8e659SRyder Lee 	int ret;
7704b8e659SRyder Lee 
78e12b2e99SFelix Fietkau 	BUILD_BUG_ON(MT7615_EEPROM_FULL_SIZE < MT7663_EEPROM_SIZE);
79e12b2e99SFelix Fietkau 
80dc7bd30bSFelix Fietkau 	ret = mt76_eeprom_init(&dev->mt76, MT7615_EEPROM_FULL_SIZE);
8104b8e659SRyder Lee 	if (ret < 0)
8204b8e659SRyder Lee 		return ret;
8304b8e659SRyder Lee 
846e5d2099SLorenzo Bianconi 	return mt7615_efuse_init(dev, addr);
8504b8e659SRyder Lee }
8604b8e659SRyder Lee 
mt7615_check_eeprom(struct mt76_dev * dev)87f9461a68SLorenzo Bianconi static int mt7615_check_eeprom(struct mt76_dev *dev)
88f9461a68SLorenzo Bianconi {
89f9461a68SLorenzo Bianconi 	u16 val = get_unaligned_le16(dev->eeprom.data);
90f9461a68SLorenzo Bianconi 
91f9461a68SLorenzo Bianconi 	switch (val) {
92f9461a68SLorenzo Bianconi 	case 0x7615:
935dff21eeSFelix Fietkau 	case 0x7622:
94858ebf44SSander Vanheule 	case 0x7663:
95f9461a68SLorenzo Bianconi 		return 0;
96f9461a68SLorenzo Bianconi 	default:
97f9461a68SLorenzo Bianconi 		return -EINVAL;
98f9461a68SLorenzo Bianconi 	}
99f9461a68SLorenzo Bianconi }
100f9461a68SLorenzo Bianconi 
101b3d95f09SLorenzo Bianconi static void
mt7615_eeprom_parse_hw_band_cap(struct mt7615_dev * dev)102b3d95f09SLorenzo Bianconi mt7615_eeprom_parse_hw_band_cap(struct mt7615_dev *dev)
103c988a77fSLorenzo Bianconi {
104b3d95f09SLorenzo Bianconi 	u8 val, *eeprom = dev->mt76.eeprom.data;
105b3d95f09SLorenzo Bianconi 
106b3d95f09SLorenzo Bianconi 	if (is_mt7663(&dev->mt76)) {
107b3d95f09SLorenzo Bianconi 		/* dual band */
10848dbce5cSLorenzo Bianconi 		dev->mphy.cap.has_2ghz = true;
10948dbce5cSLorenzo Bianconi 		dev->mphy.cap.has_5ghz = true;
110b3d95f09SLorenzo Bianconi 		return;
111b3d95f09SLorenzo Bianconi 	}
112b3d95f09SLorenzo Bianconi 
113b3d95f09SLorenzo Bianconi 	if (is_mt7622(&dev->mt76)) {
114b3d95f09SLorenzo Bianconi 		/* 2GHz only */
11548dbce5cSLorenzo Bianconi 		dev->mphy.cap.has_2ghz = true;
116b3d95f09SLorenzo Bianconi 		return;
117b3d95f09SLorenzo Bianconi 	}
118c988a77fSLorenzo Bianconi 
119e47f2245SDENG Qingfang 	if (is_mt7611(&dev->mt76)) {
120e47f2245SDENG Qingfang 		/* 5GHz only */
12148dbce5cSLorenzo Bianconi 		dev->mphy.cap.has_5ghz = true;
122e47f2245SDENG Qingfang 		return;
123e47f2245SDENG Qingfang 	}
124e47f2245SDENG Qingfang 
125c988a77fSLorenzo Bianconi 	val = FIELD_GET(MT_EE_NIC_WIFI_CONF_BAND_SEL,
126c988a77fSLorenzo Bianconi 			eeprom[MT_EE_WIFI_CONF]);
127c988a77fSLorenzo Bianconi 	switch (val) {
128c988a77fSLorenzo Bianconi 	case MT_EE_5GHZ:
12948dbce5cSLorenzo Bianconi 		dev->mphy.cap.has_5ghz = true;
130c988a77fSLorenzo Bianconi 		break;
1317660a1bdSShayne Chen 	case MT_EE_DBDC:
1327660a1bdSShayne Chen 		dev->dbdc_support = true;
133f12758f6SGustavo A. R. Silva 		fallthrough;
134421033deSPaul Fertser 	case MT_EE_2GHZ:
135421033deSPaul Fertser 		dev->mphy.cap.has_2ghz = true;
136421033deSPaul Fertser 		break;
137c988a77fSLorenzo Bianconi 	default:
13848dbce5cSLorenzo Bianconi 		dev->mphy.cap.has_2ghz = true;
13948dbce5cSLorenzo Bianconi 		dev->mphy.cap.has_5ghz = true;
140c988a77fSLorenzo Bianconi 		break;
141c988a77fSLorenzo Bianconi 	}
142b3d95f09SLorenzo Bianconi }
143acf5457fSLorenzo Bianconi 
mt7615_eeprom_parse_hw_cap(struct mt7615_dev * dev)144b3d95f09SLorenzo Bianconi static void mt7615_eeprom_parse_hw_cap(struct mt7615_dev *dev)
145b3d95f09SLorenzo Bianconi {
146b3d95f09SLorenzo Bianconi 	u8 *eeprom = dev->mt76.eeprom.data;
147eb7bd8d7SLorenzo Bianconi 	u8 tx_mask, max_nss;
148b3d95f09SLorenzo Bianconi 
149b3d95f09SLorenzo Bianconi 	mt7615_eeprom_parse_hw_band_cap(dev);
150c3ad5e9dSFelix Fietkau 
151f40ac0f3SLorenzo Bianconi 	if (is_mt7663(&dev->mt76)) {
152eb7bd8d7SLorenzo Bianconi 		max_nss = 2;
153eb7bd8d7SLorenzo Bianconi 		tx_mask = FIELD_GET(MT_EE_HW_CONF1_TX_MASK,
154eb7bd8d7SLorenzo Bianconi 				    eeprom[MT7663_EE_HW_CONF1]);
155f40ac0f3SLorenzo Bianconi 	} else {
156f40ac0f3SLorenzo Bianconi 		u32 val;
157f40ac0f3SLorenzo Bianconi 
158acf5457fSLorenzo Bianconi 		/* read tx-rx mask from eeprom */
159acf5457fSLorenzo Bianconi 		val = mt76_rr(dev, MT_TOP_STRAP_STA);
160acf5457fSLorenzo Bianconi 		max_nss = val & MT_TOP_3NSS ? 3 : 4;
161acf5457fSLorenzo Bianconi 
162acf5457fSLorenzo Bianconi 		tx_mask =  FIELD_GET(MT_EE_NIC_CONF_TX_MASK,
163acf5457fSLorenzo Bianconi 				     eeprom[MT_EE_NIC_CONF_0]);
164eb7bd8d7SLorenzo Bianconi 	}
165acf5457fSLorenzo Bianconi 	if (!tx_mask || tx_mask > max_nss)
166acf5457fSLorenzo Bianconi 		tx_mask = max_nss;
167acf5457fSLorenzo Bianconi 
1680f2173f0SFelix Fietkau 	dev->chainmask = BIT(tx_mask) - 1;
1690f2173f0SFelix Fietkau 	dev->mphy.antenna_mask = dev->chainmask;
170b9027e08SLorenzo Bianconi 	dev->mphy.chainmask = dev->chainmask;
171c988a77fSLorenzo Bianconi }
172c988a77fSLorenzo Bianconi 
mt7663_eeprom_get_target_power_index(struct mt7615_dev * dev,struct ieee80211_channel * chan,u8 chain_idx)173e0ec633dSLorenzo Bianconi static int mt7663_eeprom_get_target_power_index(struct mt7615_dev *dev,
174e0ec633dSLorenzo Bianconi 						struct ieee80211_channel *chan,
175e0ec633dSLorenzo Bianconi 						u8 chain_idx)
176e0ec633dSLorenzo Bianconi {
177e0ec633dSLorenzo Bianconi 	int index, group;
178e0ec633dSLorenzo Bianconi 
179e0ec633dSLorenzo Bianconi 	if (chain_idx > 1)
180e0ec633dSLorenzo Bianconi 		return -EINVAL;
181e0ec633dSLorenzo Bianconi 
182e0ec633dSLorenzo Bianconi 	if (chan->band == NL80211_BAND_2GHZ)
183e0ec633dSLorenzo Bianconi 		return MT7663_EE_TX0_2G_TARGET_POWER + (chain_idx << 4);
184e0ec633dSLorenzo Bianconi 
185e0ec633dSLorenzo Bianconi 	group = mt7615_get_channel_group(chan->hw_value);
186e0ec633dSLorenzo Bianconi 	if (chain_idx == 1)
187e0ec633dSLorenzo Bianconi 		index = MT7663_EE_TX1_5G_G0_TARGET_POWER;
188e0ec633dSLorenzo Bianconi 	else
189e0ec633dSLorenzo Bianconi 		index = MT7663_EE_TX0_5G_G0_TARGET_POWER;
190e0ec633dSLorenzo Bianconi 
191e0ec633dSLorenzo Bianconi 	return index + group * 3;
192e0ec633dSLorenzo Bianconi }
193e0ec633dSLorenzo Bianconi 
mt7615_eeprom_get_target_power_index(struct mt7615_dev * dev,struct ieee80211_channel * chan,u8 chain_idx)194e0ec633dSLorenzo Bianconi int mt7615_eeprom_get_target_power_index(struct mt7615_dev *dev,
19516a2f8e2SLorenzo Bianconi 					 struct ieee80211_channel *chan,
19661d36824SLorenzo Bianconi 					 u8 chain_idx)
19761d36824SLorenzo Bianconi {
19861d36824SLorenzo Bianconi 	int index;
19961d36824SLorenzo Bianconi 
200e0ec633dSLorenzo Bianconi 	if (is_mt7663(&dev->mt76))
201e0ec633dSLorenzo Bianconi 		return mt7663_eeprom_get_target_power_index(dev, chan,
202e0ec633dSLorenzo Bianconi 							    chain_idx);
203e0ec633dSLorenzo Bianconi 
20461d36824SLorenzo Bianconi 	if (chain_idx > 3)
20561d36824SLorenzo Bianconi 		return -EINVAL;
20661d36824SLorenzo Bianconi 
20716a2f8e2SLorenzo Bianconi 	/* TSSI disabled */
20816a2f8e2SLorenzo Bianconi 	if (mt7615_ext_pa_enabled(dev, chan->band)) {
20916a2f8e2SLorenzo Bianconi 		if (chan->band == NL80211_BAND_2GHZ)
21016a2f8e2SLorenzo Bianconi 			return MT_EE_EXT_PA_2G_TARGET_POWER;
21116a2f8e2SLorenzo Bianconi 		else
21216a2f8e2SLorenzo Bianconi 			return MT_EE_EXT_PA_5G_TARGET_POWER;
21316a2f8e2SLorenzo Bianconi 	}
21416a2f8e2SLorenzo Bianconi 
21516a2f8e2SLorenzo Bianconi 	/* TSSI enabled */
21661d36824SLorenzo Bianconi 	if (chan->band == NL80211_BAND_2GHZ) {
21761d36824SLorenzo Bianconi 		index = MT_EE_TX0_2G_TARGET_POWER + chain_idx * 6;
21861d36824SLorenzo Bianconi 	} else {
21961d36824SLorenzo Bianconi 		int group = mt7615_get_channel_group(chan->hw_value);
22061d36824SLorenzo Bianconi 
22161d36824SLorenzo Bianconi 		switch (chain_idx) {
22261d36824SLorenzo Bianconi 		case 1:
22361d36824SLorenzo Bianconi 			index = MT_EE_TX1_5G_G0_TARGET_POWER;
22461d36824SLorenzo Bianconi 			break;
22561d36824SLorenzo Bianconi 		case 2:
22661d36824SLorenzo Bianconi 			index = MT_EE_TX2_5G_G0_TARGET_POWER;
22761d36824SLorenzo Bianconi 			break;
22861d36824SLorenzo Bianconi 		case 3:
22961d36824SLorenzo Bianconi 			index = MT_EE_TX3_5G_G0_TARGET_POWER;
23061d36824SLorenzo Bianconi 			break;
23161d36824SLorenzo Bianconi 		case 0:
23261d36824SLorenzo Bianconi 		default:
23361d36824SLorenzo Bianconi 			index = MT_EE_TX0_5G_G0_TARGET_POWER;
23461d36824SLorenzo Bianconi 			break;
23561d36824SLorenzo Bianconi 		}
23661d36824SLorenzo Bianconi 		index += 5 * group;
23761d36824SLorenzo Bianconi 	}
23861d36824SLorenzo Bianconi 
23961d36824SLorenzo Bianconi 	return index;
24061d36824SLorenzo Bianconi }
24161d36824SLorenzo Bianconi 
mt7615_eeprom_get_power_delta_index(struct mt7615_dev * dev,enum nl80211_band band)242c88bf52bSLorenzo Bianconi int mt7615_eeprom_get_power_delta_index(struct mt7615_dev *dev,
243c88bf52bSLorenzo Bianconi 					enum nl80211_band band)
244c88bf52bSLorenzo Bianconi {
245c88bf52bSLorenzo Bianconi 	/* assume the first rate has the highest power offset */
246c88bf52bSLorenzo Bianconi 	if (is_mt7663(&dev->mt76)) {
247c88bf52bSLorenzo Bianconi 		if (band == NL80211_BAND_2GHZ)
248c88bf52bSLorenzo Bianconi 			return MT_EE_TX0_5G_G0_TARGET_POWER;
249c88bf52bSLorenzo Bianconi 		else
250c88bf52bSLorenzo Bianconi 			return MT7663_EE_5G_RATE_POWER;
251c88bf52bSLorenzo Bianconi 	}
252c88bf52bSLorenzo Bianconi 
253c88bf52bSLorenzo Bianconi 	if (band == NL80211_BAND_2GHZ)
254c88bf52bSLorenzo Bianconi 		return MT_EE_2G_RATE_POWER;
255c88bf52bSLorenzo Bianconi 	else
256c88bf52bSLorenzo Bianconi 		return MT_EE_5G_RATE_POWER;
257c88bf52bSLorenzo Bianconi }
258c88bf52bSLorenzo Bianconi 
mt7615_apply_cal_free_data(struct mt7615_dev * dev)25955bbbefdSFelix Fietkau static void mt7615_apply_cal_free_data(struct mt7615_dev *dev)
26055bbbefdSFelix Fietkau {
26155bbbefdSFelix Fietkau 	static const u16 ical[] = {
26255bbbefdSFelix Fietkau 		0x53, 0x54, 0x55, 0x56, 0x57, 0x5c, 0x5d, 0x62, 0x63, 0x68,
26355bbbefdSFelix Fietkau 		0x69, 0x6e, 0x6f, 0x73, 0x74, 0x78, 0x79, 0x82, 0x83, 0x87,
26455bbbefdSFelix Fietkau 		0x88, 0x8c, 0x8d, 0x91, 0x92, 0x96, 0x97, 0x9b, 0x9c, 0xa0,
26555bbbefdSFelix Fietkau 		0xa1, 0xaa, 0xab, 0xaf, 0xb0, 0xb4, 0xb5, 0xb9, 0xba, 0xf4,
26655bbbefdSFelix Fietkau 		0xf7, 0xff,
26755bbbefdSFelix Fietkau 		0x140, 0x141, 0x145, 0x146, 0x14a, 0x14b, 0x154, 0x155, 0x159,
26855bbbefdSFelix Fietkau 		0x15a, 0x15e, 0x15f, 0x163, 0x164, 0x168, 0x169, 0x16d, 0x16e,
26955bbbefdSFelix Fietkau 		0x172, 0x173, 0x17c, 0x17d, 0x181, 0x182, 0x186, 0x187, 0x18b,
27055bbbefdSFelix Fietkau 		0x18c
27155bbbefdSFelix Fietkau 	};
27255bbbefdSFelix Fietkau 	static const u16 ical_nocheck[] = {
27355bbbefdSFelix Fietkau 		0x110, 0x111, 0x112, 0x113, 0x114, 0x115, 0x116, 0x117, 0x118,
27455bbbefdSFelix Fietkau 		0x1b5, 0x1b6, 0x1b7, 0x3ac, 0x3ad, 0x3ae, 0x3af, 0x3b0, 0x3b1,
27555bbbefdSFelix Fietkau 		0x3b2
27655bbbefdSFelix Fietkau 	};
27755bbbefdSFelix Fietkau 	u8 *eeprom = dev->mt76.eeprom.data;
27855bbbefdSFelix Fietkau 	u8 *otp = dev->mt76.otp.data;
27955bbbefdSFelix Fietkau 	int i;
28055bbbefdSFelix Fietkau 
28155bbbefdSFelix Fietkau 	if (!otp)
28255bbbefdSFelix Fietkau 		return;
28355bbbefdSFelix Fietkau 
28455bbbefdSFelix Fietkau 	for (i = 0; i < ARRAY_SIZE(ical); i++)
28555bbbefdSFelix Fietkau 		if (!otp[ical[i]])
28655bbbefdSFelix Fietkau 			return;
28755bbbefdSFelix Fietkau 
28855bbbefdSFelix Fietkau 	for (i = 0; i < ARRAY_SIZE(ical); i++)
28955bbbefdSFelix Fietkau 		eeprom[ical[i]] = otp[ical[i]];
29055bbbefdSFelix Fietkau 
29155bbbefdSFelix Fietkau 	for (i = 0; i < ARRAY_SIZE(ical_nocheck); i++)
29255bbbefdSFelix Fietkau 		eeprom[ical_nocheck[i]] = otp[ical_nocheck[i]];
29355bbbefdSFelix Fietkau }
29455bbbefdSFelix Fietkau 
mt7622_apply_cal_free_data(struct mt7615_dev * dev)2958acb7afcSFelix Fietkau static void mt7622_apply_cal_free_data(struct mt7615_dev *dev)
2968acb7afcSFelix Fietkau {
2978acb7afcSFelix Fietkau 	static const u16 ical[] = {
2988acb7afcSFelix Fietkau 		0x53, 0x54, 0x55, 0x56, 0xf4, 0xf7, 0x144, 0x156, 0x15b
2998acb7afcSFelix Fietkau 	};
3008acb7afcSFelix Fietkau 	u8 *eeprom = dev->mt76.eeprom.data;
3018acb7afcSFelix Fietkau 	u8 *otp = dev->mt76.otp.data;
3028acb7afcSFelix Fietkau 	int i;
3038acb7afcSFelix Fietkau 
3048acb7afcSFelix Fietkau 	if (!otp)
3058acb7afcSFelix Fietkau 		return;
3068acb7afcSFelix Fietkau 
3078acb7afcSFelix Fietkau 	for (i = 0; i < ARRAY_SIZE(ical); i++) {
3088acb7afcSFelix Fietkau 		if (!otp[ical[i]])
3098acb7afcSFelix Fietkau 			continue;
3108acb7afcSFelix Fietkau 
3118acb7afcSFelix Fietkau 		eeprom[ical[i]] = otp[ical[i]];
3128acb7afcSFelix Fietkau 	}
3138acb7afcSFelix Fietkau }
3148acb7afcSFelix Fietkau 
mt7615_cal_free_data(struct mt7615_dev * dev)315f40ac0f3SLorenzo Bianconi static void mt7615_cal_free_data(struct mt7615_dev *dev)
316f40ac0f3SLorenzo Bianconi {
317b90728f8SFelix Fietkau 	struct device_node *np = dev->mt76.dev->of_node;
318b90728f8SFelix Fietkau 
319b90728f8SFelix Fietkau 	if (!np || !of_property_read_bool(np, "mediatek,eeprom-merge-otp"))
320b90728f8SFelix Fietkau 		return;
321b90728f8SFelix Fietkau 
322f40ac0f3SLorenzo Bianconi 	switch (mt76_chip(&dev->mt76)) {
323f40ac0f3SLorenzo Bianconi 	case 0x7622:
324f40ac0f3SLorenzo Bianconi 		mt7622_apply_cal_free_data(dev);
325f40ac0f3SLorenzo Bianconi 		break;
326f40ac0f3SLorenzo Bianconi 	case 0x7615:
327e47f2245SDENG Qingfang 	case 0x7611:
328f40ac0f3SLorenzo Bianconi 		mt7615_apply_cal_free_data(dev);
329f40ac0f3SLorenzo Bianconi 		break;
330f40ac0f3SLorenzo Bianconi 	}
331f40ac0f3SLorenzo Bianconi }
332f40ac0f3SLorenzo Bianconi 
mt7615_eeprom_init(struct mt7615_dev * dev,u32 addr)3336e5d2099SLorenzo Bianconi int mt7615_eeprom_init(struct mt7615_dev *dev, u32 addr)
33404b8e659SRyder Lee {
33504b8e659SRyder Lee 	int ret;
33604b8e659SRyder Lee 
3376e5d2099SLorenzo Bianconi 	ret = mt7615_eeprom_load(dev, addr);
33804b8e659SRyder Lee 	if (ret < 0)
33904b8e659SRyder Lee 		return ret;
34004b8e659SRyder Lee 
341f9461a68SLorenzo Bianconi 	ret = mt7615_check_eeprom(&dev->mt76);
342ad380ad1SFelix Fietkau 	if (ret && dev->mt76.otp.data) {
343f9461a68SLorenzo Bianconi 		memcpy(dev->mt76.eeprom.data, dev->mt76.otp.data,
344e12b2e99SFelix Fietkau 		       dev->mt76.otp.size);
345ad380ad1SFelix Fietkau 	} else {
346ad380ad1SFelix Fietkau 		dev->flash_eeprom = true;
347f40ac0f3SLorenzo Bianconi 		mt7615_cal_free_data(dev);
348ad380ad1SFelix Fietkau 	}
34904b8e659SRyder Lee 
350c988a77fSLorenzo Bianconi 	mt7615_eeprom_parse_hw_cap(dev);
35198df2baeSLorenzo Bianconi 	memcpy(dev->mphy.macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR,
35204b8e659SRyder Lee 	       ETH_ALEN);
35304b8e659SRyder Lee 
35498df2baeSLorenzo Bianconi 	mt76_eeprom_override(&dev->mphy);
35504b8e659SRyder Lee 
35604b8e659SRyder Lee 	return 0;
35704b8e659SRyder Lee }
358e90354e0SLorenzo Bianconi EXPORT_SYMBOL_GPL(mt7615_eeprom_init);
359