xref: /freebsd/sys/contrib/dev/mediatek/mt76/mt7615/eeprom.c (revision cbb3ec25236ba72f91cbdf23f8b78b9d1af0cedf)
16c92544dSBjoern A. Zeeb // SPDX-License-Identifier: ISC
26c92544dSBjoern A. Zeeb /* Copyright (C) 2019 MediaTek Inc.
36c92544dSBjoern A. Zeeb  *
46c92544dSBjoern A. Zeeb  * Author: Ryder Lee <ryder.lee@mediatek.com>
56c92544dSBjoern A. Zeeb  *         Felix Fietkau <nbd@nbd.name>
66c92544dSBjoern A. Zeeb  */
76c92544dSBjoern A. Zeeb 
86c92544dSBjoern A. Zeeb #include <linux/of.h>
96c92544dSBjoern A. Zeeb #include "mt7615.h"
106c92544dSBjoern A. Zeeb #include "eeprom.h"
116c92544dSBjoern A. Zeeb 
126c92544dSBjoern A. Zeeb static int mt7615_efuse_read(struct mt7615_dev *dev, u32 base,
136c92544dSBjoern A. Zeeb 			     u16 addr, u8 *data)
146c92544dSBjoern A. Zeeb {
156c92544dSBjoern A. Zeeb 	u32 val;
166c92544dSBjoern A. Zeeb 	int i;
176c92544dSBjoern A. Zeeb 
186c92544dSBjoern A. Zeeb 	val = mt76_rr(dev, base + MT_EFUSE_CTRL);
196c92544dSBjoern A. Zeeb 	val &= ~(MT_EFUSE_CTRL_AIN | MT_EFUSE_CTRL_MODE);
206c92544dSBjoern A. Zeeb 	val |= FIELD_PREP(MT_EFUSE_CTRL_AIN, addr & ~0xf);
216c92544dSBjoern A. Zeeb 	val |= MT_EFUSE_CTRL_KICK;
226c92544dSBjoern A. Zeeb 	mt76_wr(dev, base + MT_EFUSE_CTRL, val);
236c92544dSBjoern A. Zeeb 
246c92544dSBjoern A. Zeeb 	if (!mt76_poll(dev, base + MT_EFUSE_CTRL, MT_EFUSE_CTRL_KICK, 0, 1000))
256c92544dSBjoern A. Zeeb 		return -ETIMEDOUT;
266c92544dSBjoern A. Zeeb 
276c92544dSBjoern A. Zeeb 	udelay(2);
286c92544dSBjoern A. Zeeb 
296c92544dSBjoern A. Zeeb 	val = mt76_rr(dev, base + MT_EFUSE_CTRL);
306c92544dSBjoern A. Zeeb 	if ((val & MT_EFUSE_CTRL_AOUT) == MT_EFUSE_CTRL_AOUT ||
316c92544dSBjoern A. Zeeb 	    WARN_ON_ONCE(!(val & MT_EFUSE_CTRL_VALID))) {
326c92544dSBjoern A. Zeeb 		memset(data, 0x0, 16);
336c92544dSBjoern A. Zeeb 		return 0;
346c92544dSBjoern A. Zeeb 	}
356c92544dSBjoern A. Zeeb 
366c92544dSBjoern A. Zeeb 	for (i = 0; i < 4; i++) {
376c92544dSBjoern A. Zeeb 		val = mt76_rr(dev, base + MT_EFUSE_RDATA(i));
386c92544dSBjoern A. Zeeb 		put_unaligned_le32(val, data + 4 * i);
396c92544dSBjoern A. Zeeb 	}
406c92544dSBjoern A. Zeeb 
416c92544dSBjoern A. Zeeb 	return 0;
426c92544dSBjoern A. Zeeb }
436c92544dSBjoern A. Zeeb 
446c92544dSBjoern A. Zeeb static int mt7615_efuse_init(struct mt7615_dev *dev, u32 base)
456c92544dSBjoern A. Zeeb {
466c92544dSBjoern A. Zeeb 	int i, len = MT7615_EEPROM_SIZE;
476c92544dSBjoern A. Zeeb 	void *buf;
486c92544dSBjoern A. Zeeb 	u32 val;
496c92544dSBjoern A. Zeeb 
50*cbb3ec25SBjoern A. Zeeb 	if (is_mt7663(&dev->mt76))
51*cbb3ec25SBjoern A. Zeeb 		len = MT7663_EEPROM_SIZE;
52*cbb3ec25SBjoern A. Zeeb 
536c92544dSBjoern A. Zeeb 	val = mt76_rr(dev, base + MT_EFUSE_BASE_CTRL);
546c92544dSBjoern A. Zeeb 	if (val & MT_EFUSE_BASE_CTRL_EMPTY)
556c92544dSBjoern A. Zeeb 		return 0;
566c92544dSBjoern A. Zeeb 
576c92544dSBjoern A. Zeeb 	dev->mt76.otp.data = devm_kzalloc(dev->mt76.dev, len, GFP_KERNEL);
586c92544dSBjoern A. Zeeb 	dev->mt76.otp.size = len;
596c92544dSBjoern A. Zeeb 	if (!dev->mt76.otp.data)
606c92544dSBjoern A. Zeeb 		return -ENOMEM;
616c92544dSBjoern A. Zeeb 
626c92544dSBjoern A. Zeeb 	buf = dev->mt76.otp.data;
636c92544dSBjoern A. Zeeb 	for (i = 0; i + 16 <= len; i += 16) {
646c92544dSBjoern A. Zeeb 		int ret;
656c92544dSBjoern A. Zeeb 
666c92544dSBjoern A. Zeeb 		ret = mt7615_efuse_read(dev, base, i, buf + i);
676c92544dSBjoern A. Zeeb 		if (ret)
686c92544dSBjoern A. Zeeb 			return ret;
696c92544dSBjoern A. Zeeb 	}
706c92544dSBjoern A. Zeeb 
716c92544dSBjoern A. Zeeb 	return 0;
726c92544dSBjoern A. Zeeb }
736c92544dSBjoern A. Zeeb 
746c92544dSBjoern A. Zeeb static int mt7615_eeprom_load(struct mt7615_dev *dev, u32 addr)
756c92544dSBjoern A. Zeeb {
766c92544dSBjoern A. Zeeb 	int ret;
776c92544dSBjoern A. Zeeb 
78*cbb3ec25SBjoern A. Zeeb 	BUILD_BUG_ON(MT7615_EEPROM_FULL_SIZE < MT7663_EEPROM_SIZE);
79*cbb3ec25SBjoern A. Zeeb 
806c92544dSBjoern A. Zeeb 	ret = mt76_eeprom_init(&dev->mt76, MT7615_EEPROM_FULL_SIZE);
816c92544dSBjoern A. Zeeb 	if (ret < 0)
826c92544dSBjoern A. Zeeb 		return ret;
836c92544dSBjoern A. Zeeb 
846c92544dSBjoern A. Zeeb 	return mt7615_efuse_init(dev, addr);
856c92544dSBjoern A. Zeeb }
866c92544dSBjoern A. Zeeb 
876c92544dSBjoern A. Zeeb static int mt7615_check_eeprom(struct mt76_dev *dev)
886c92544dSBjoern A. Zeeb {
896c92544dSBjoern A. Zeeb 	u16 val = get_unaligned_le16(dev->eeprom.data);
906c92544dSBjoern A. Zeeb 
916c92544dSBjoern A. Zeeb 	switch (val) {
926c92544dSBjoern A. Zeeb 	case 0x7615:
936c92544dSBjoern A. Zeeb 	case 0x7622:
946c92544dSBjoern A. Zeeb 	case 0x7663:
956c92544dSBjoern A. Zeeb 		return 0;
966c92544dSBjoern A. Zeeb 	default:
976c92544dSBjoern A. Zeeb 		return -EINVAL;
986c92544dSBjoern A. Zeeb 	}
996c92544dSBjoern A. Zeeb }
1006c92544dSBjoern A. Zeeb 
1016c92544dSBjoern A. Zeeb static void
1026c92544dSBjoern A. Zeeb mt7615_eeprom_parse_hw_band_cap(struct mt7615_dev *dev)
1036c92544dSBjoern A. Zeeb {
1046c92544dSBjoern A. Zeeb 	u8 val, *eeprom = dev->mt76.eeprom.data;
1056c92544dSBjoern A. Zeeb 
1066c92544dSBjoern A. Zeeb 	if (is_mt7663(&dev->mt76)) {
1076c92544dSBjoern A. Zeeb 		/* dual band */
1086c92544dSBjoern A. Zeeb 		dev->mphy.cap.has_2ghz = true;
1096c92544dSBjoern A. Zeeb 		dev->mphy.cap.has_5ghz = true;
1106c92544dSBjoern A. Zeeb 		return;
1116c92544dSBjoern A. Zeeb 	}
1126c92544dSBjoern A. Zeeb 
1136c92544dSBjoern A. Zeeb 	if (is_mt7622(&dev->mt76)) {
1146c92544dSBjoern A. Zeeb 		/* 2GHz only */
1156c92544dSBjoern A. Zeeb 		dev->mphy.cap.has_2ghz = true;
1166c92544dSBjoern A. Zeeb 		return;
1176c92544dSBjoern A. Zeeb 	}
1186c92544dSBjoern A. Zeeb 
1196c92544dSBjoern A. Zeeb 	if (is_mt7611(&dev->mt76)) {
1206c92544dSBjoern A. Zeeb 		/* 5GHz only */
1216c92544dSBjoern A. Zeeb 		dev->mphy.cap.has_5ghz = true;
1226c92544dSBjoern A. Zeeb 		return;
1236c92544dSBjoern A. Zeeb 	}
1246c92544dSBjoern A. Zeeb 
1256c92544dSBjoern A. Zeeb 	val = FIELD_GET(MT_EE_NIC_WIFI_CONF_BAND_SEL,
1266c92544dSBjoern A. Zeeb 			eeprom[MT_EE_WIFI_CONF]);
1276c92544dSBjoern A. Zeeb 	switch (val) {
1286c92544dSBjoern A. Zeeb 	case MT_EE_5GHZ:
1296c92544dSBjoern A. Zeeb 		dev->mphy.cap.has_5ghz = true;
1306c92544dSBjoern A. Zeeb 		break;
1316c92544dSBjoern A. Zeeb 	case MT_EE_DBDC:
1326c92544dSBjoern A. Zeeb 		dev->dbdc_support = true;
1336c92544dSBjoern A. Zeeb 		fallthrough;
134*cbb3ec25SBjoern A. Zeeb 	case MT_EE_2GHZ:
135*cbb3ec25SBjoern A. Zeeb 		dev->mphy.cap.has_2ghz = true;
136*cbb3ec25SBjoern A. Zeeb 		break;
1376c92544dSBjoern A. Zeeb 	default:
1386c92544dSBjoern A. Zeeb 		dev->mphy.cap.has_2ghz = true;
1396c92544dSBjoern A. Zeeb 		dev->mphy.cap.has_5ghz = true;
1406c92544dSBjoern A. Zeeb 		break;
1416c92544dSBjoern A. Zeeb 	}
1426c92544dSBjoern A. Zeeb }
1436c92544dSBjoern A. Zeeb 
1446c92544dSBjoern A. Zeeb static void mt7615_eeprom_parse_hw_cap(struct mt7615_dev *dev)
1456c92544dSBjoern A. Zeeb {
1466c92544dSBjoern A. Zeeb 	u8 *eeprom = dev->mt76.eeprom.data;
1476c92544dSBjoern A. Zeeb 	u8 tx_mask, max_nss;
1486c92544dSBjoern A. Zeeb 
1496c92544dSBjoern A. Zeeb 	mt7615_eeprom_parse_hw_band_cap(dev);
1506c92544dSBjoern A. Zeeb 
1516c92544dSBjoern A. Zeeb 	if (is_mt7663(&dev->mt76)) {
1526c92544dSBjoern A. Zeeb 		max_nss = 2;
1536c92544dSBjoern A. Zeeb 		tx_mask = FIELD_GET(MT_EE_HW_CONF1_TX_MASK,
1546c92544dSBjoern A. Zeeb 				    eeprom[MT7663_EE_HW_CONF1]);
1556c92544dSBjoern A. Zeeb 	} else {
1566c92544dSBjoern A. Zeeb 		u32 val;
1576c92544dSBjoern A. Zeeb 
1586c92544dSBjoern A. Zeeb 		/* read tx-rx mask from eeprom */
1596c92544dSBjoern A. Zeeb 		val = mt76_rr(dev, MT_TOP_STRAP_STA);
1606c92544dSBjoern A. Zeeb 		max_nss = val & MT_TOP_3NSS ? 3 : 4;
1616c92544dSBjoern A. Zeeb 
1626c92544dSBjoern A. Zeeb 		tx_mask =  FIELD_GET(MT_EE_NIC_CONF_TX_MASK,
1636c92544dSBjoern A. Zeeb 				     eeprom[MT_EE_NIC_CONF_0]);
1646c92544dSBjoern A. Zeeb 	}
1656c92544dSBjoern A. Zeeb 	if (!tx_mask || tx_mask > max_nss)
1666c92544dSBjoern A. Zeeb 		tx_mask = max_nss;
1676c92544dSBjoern A. Zeeb 
1686c92544dSBjoern A. Zeeb 	dev->chainmask = BIT(tx_mask) - 1;
1696c92544dSBjoern A. Zeeb 	dev->mphy.antenna_mask = dev->chainmask;
1706c92544dSBjoern A. Zeeb 	dev->mphy.chainmask = dev->chainmask;
1716c92544dSBjoern A. Zeeb }
1726c92544dSBjoern A. Zeeb 
1736c92544dSBjoern A. Zeeb static int mt7663_eeprom_get_target_power_index(struct mt7615_dev *dev,
1746c92544dSBjoern A. Zeeb 						struct ieee80211_channel *chan,
1756c92544dSBjoern A. Zeeb 						u8 chain_idx)
1766c92544dSBjoern A. Zeeb {
1776c92544dSBjoern A. Zeeb 	int index, group;
1786c92544dSBjoern A. Zeeb 
1796c92544dSBjoern A. Zeeb 	if (chain_idx > 1)
1806c92544dSBjoern A. Zeeb 		return -EINVAL;
1816c92544dSBjoern A. Zeeb 
1826c92544dSBjoern A. Zeeb 	if (chan->band == NL80211_BAND_2GHZ)
1836c92544dSBjoern A. Zeeb 		return MT7663_EE_TX0_2G_TARGET_POWER + (chain_idx << 4);
1846c92544dSBjoern A. Zeeb 
1856c92544dSBjoern A. Zeeb 	group = mt7615_get_channel_group(chan->hw_value);
1866c92544dSBjoern A. Zeeb 	if (chain_idx == 1)
1876c92544dSBjoern A. Zeeb 		index = MT7663_EE_TX1_5G_G0_TARGET_POWER;
1886c92544dSBjoern A. Zeeb 	else
1896c92544dSBjoern A. Zeeb 		index = MT7663_EE_TX0_5G_G0_TARGET_POWER;
1906c92544dSBjoern A. Zeeb 
1916c92544dSBjoern A. Zeeb 	return index + group * 3;
1926c92544dSBjoern A. Zeeb }
1936c92544dSBjoern A. Zeeb 
1946c92544dSBjoern A. Zeeb int mt7615_eeprom_get_target_power_index(struct mt7615_dev *dev,
1956c92544dSBjoern A. Zeeb 					 struct ieee80211_channel *chan,
1966c92544dSBjoern A. Zeeb 					 u8 chain_idx)
1976c92544dSBjoern A. Zeeb {
1986c92544dSBjoern A. Zeeb 	int index;
1996c92544dSBjoern A. Zeeb 
2006c92544dSBjoern A. Zeeb 	if (is_mt7663(&dev->mt76))
2016c92544dSBjoern A. Zeeb 		return mt7663_eeprom_get_target_power_index(dev, chan,
2026c92544dSBjoern A. Zeeb 							    chain_idx);
2036c92544dSBjoern A. Zeeb 
2046c92544dSBjoern A. Zeeb 	if (chain_idx > 3)
2056c92544dSBjoern A. Zeeb 		return -EINVAL;
2066c92544dSBjoern A. Zeeb 
2076c92544dSBjoern A. Zeeb 	/* TSSI disabled */
2086c92544dSBjoern A. Zeeb 	if (mt7615_ext_pa_enabled(dev, chan->band)) {
2096c92544dSBjoern A. Zeeb 		if (chan->band == NL80211_BAND_2GHZ)
2106c92544dSBjoern A. Zeeb 			return MT_EE_EXT_PA_2G_TARGET_POWER;
2116c92544dSBjoern A. Zeeb 		else
2126c92544dSBjoern A. Zeeb 			return MT_EE_EXT_PA_5G_TARGET_POWER;
2136c92544dSBjoern A. Zeeb 	}
2146c92544dSBjoern A. Zeeb 
2156c92544dSBjoern A. Zeeb 	/* TSSI enabled */
2166c92544dSBjoern A. Zeeb 	if (chan->band == NL80211_BAND_2GHZ) {
2176c92544dSBjoern A. Zeeb 		index = MT_EE_TX0_2G_TARGET_POWER + chain_idx * 6;
2186c92544dSBjoern A. Zeeb 	} else {
2196c92544dSBjoern A. Zeeb 		int group = mt7615_get_channel_group(chan->hw_value);
2206c92544dSBjoern A. Zeeb 
2216c92544dSBjoern A. Zeeb 		switch (chain_idx) {
2226c92544dSBjoern A. Zeeb 		case 1:
2236c92544dSBjoern A. Zeeb 			index = MT_EE_TX1_5G_G0_TARGET_POWER;
2246c92544dSBjoern A. Zeeb 			break;
2256c92544dSBjoern A. Zeeb 		case 2:
2266c92544dSBjoern A. Zeeb 			index = MT_EE_TX2_5G_G0_TARGET_POWER;
2276c92544dSBjoern A. Zeeb 			break;
2286c92544dSBjoern A. Zeeb 		case 3:
2296c92544dSBjoern A. Zeeb 			index = MT_EE_TX3_5G_G0_TARGET_POWER;
2306c92544dSBjoern A. Zeeb 			break;
2316c92544dSBjoern A. Zeeb 		case 0:
2326c92544dSBjoern A. Zeeb 		default:
2336c92544dSBjoern A. Zeeb 			index = MT_EE_TX0_5G_G0_TARGET_POWER;
2346c92544dSBjoern A. Zeeb 			break;
2356c92544dSBjoern A. Zeeb 		}
2366c92544dSBjoern A. Zeeb 		index += 5 * group;
2376c92544dSBjoern A. Zeeb 	}
2386c92544dSBjoern A. Zeeb 
2396c92544dSBjoern A. Zeeb 	return index;
2406c92544dSBjoern A. Zeeb }
2416c92544dSBjoern A. Zeeb 
2426c92544dSBjoern A. Zeeb int mt7615_eeprom_get_power_delta_index(struct mt7615_dev *dev,
2436c92544dSBjoern A. Zeeb 					enum nl80211_band band)
2446c92544dSBjoern A. Zeeb {
2456c92544dSBjoern A. Zeeb 	/* assume the first rate has the highest power offset */
2466c92544dSBjoern A. Zeeb 	if (is_mt7663(&dev->mt76)) {
2476c92544dSBjoern A. Zeeb 		if (band == NL80211_BAND_2GHZ)
2486c92544dSBjoern A. Zeeb 			return MT_EE_TX0_5G_G0_TARGET_POWER;
2496c92544dSBjoern A. Zeeb 		else
2506c92544dSBjoern A. Zeeb 			return MT7663_EE_5G_RATE_POWER;
2516c92544dSBjoern A. Zeeb 	}
2526c92544dSBjoern A. Zeeb 
2536c92544dSBjoern A. Zeeb 	if (band == NL80211_BAND_2GHZ)
2546c92544dSBjoern A. Zeeb 		return MT_EE_2G_RATE_POWER;
2556c92544dSBjoern A. Zeeb 	else
2566c92544dSBjoern A. Zeeb 		return MT_EE_5G_RATE_POWER;
2576c92544dSBjoern A. Zeeb }
2586c92544dSBjoern A. Zeeb 
2596c92544dSBjoern A. Zeeb static void mt7615_apply_cal_free_data(struct mt7615_dev *dev)
2606c92544dSBjoern A. Zeeb {
2616c92544dSBjoern A. Zeeb 	static const u16 ical[] = {
2626c92544dSBjoern A. Zeeb 		0x53, 0x54, 0x55, 0x56, 0x57, 0x5c, 0x5d, 0x62, 0x63, 0x68,
2636c92544dSBjoern A. Zeeb 		0x69, 0x6e, 0x6f, 0x73, 0x74, 0x78, 0x79, 0x82, 0x83, 0x87,
2646c92544dSBjoern A. Zeeb 		0x88, 0x8c, 0x8d, 0x91, 0x92, 0x96, 0x97, 0x9b, 0x9c, 0xa0,
2656c92544dSBjoern A. Zeeb 		0xa1, 0xaa, 0xab, 0xaf, 0xb0, 0xb4, 0xb5, 0xb9, 0xba, 0xf4,
2666c92544dSBjoern A. Zeeb 		0xf7, 0xff,
2676c92544dSBjoern A. Zeeb 		0x140, 0x141, 0x145, 0x146, 0x14a, 0x14b, 0x154, 0x155, 0x159,
2686c92544dSBjoern A. Zeeb 		0x15a, 0x15e, 0x15f, 0x163, 0x164, 0x168, 0x169, 0x16d, 0x16e,
2696c92544dSBjoern A. Zeeb 		0x172, 0x173, 0x17c, 0x17d, 0x181, 0x182, 0x186, 0x187, 0x18b,
2706c92544dSBjoern A. Zeeb 		0x18c
2716c92544dSBjoern A. Zeeb 	};
2726c92544dSBjoern A. Zeeb 	static const u16 ical_nocheck[] = {
2736c92544dSBjoern A. Zeeb 		0x110, 0x111, 0x112, 0x113, 0x114, 0x115, 0x116, 0x117, 0x118,
2746c92544dSBjoern A. Zeeb 		0x1b5, 0x1b6, 0x1b7, 0x3ac, 0x3ad, 0x3ae, 0x3af, 0x3b0, 0x3b1,
2756c92544dSBjoern A. Zeeb 		0x3b2
2766c92544dSBjoern A. Zeeb 	};
2776c92544dSBjoern A. Zeeb 	u8 *eeprom = dev->mt76.eeprom.data;
2786c92544dSBjoern A. Zeeb 	u8 *otp = dev->mt76.otp.data;
2796c92544dSBjoern A. Zeeb 	int i;
2806c92544dSBjoern A. Zeeb 
2816c92544dSBjoern A. Zeeb 	if (!otp)
2826c92544dSBjoern A. Zeeb 		return;
2836c92544dSBjoern A. Zeeb 
2846c92544dSBjoern A. Zeeb 	for (i = 0; i < ARRAY_SIZE(ical); i++)
2856c92544dSBjoern A. Zeeb 		if (!otp[ical[i]])
2866c92544dSBjoern A. Zeeb 			return;
2876c92544dSBjoern A. Zeeb 
2886c92544dSBjoern A. Zeeb 	for (i = 0; i < ARRAY_SIZE(ical); i++)
2896c92544dSBjoern A. Zeeb 		eeprom[ical[i]] = otp[ical[i]];
2906c92544dSBjoern A. Zeeb 
2916c92544dSBjoern A. Zeeb 	for (i = 0; i < ARRAY_SIZE(ical_nocheck); i++)
2926c92544dSBjoern A. Zeeb 		eeprom[ical_nocheck[i]] = otp[ical_nocheck[i]];
2936c92544dSBjoern A. Zeeb }
2946c92544dSBjoern A. Zeeb 
2956c92544dSBjoern A. Zeeb static void mt7622_apply_cal_free_data(struct mt7615_dev *dev)
2966c92544dSBjoern A. Zeeb {
2976c92544dSBjoern A. Zeeb 	static const u16 ical[] = {
2986c92544dSBjoern A. Zeeb 		0x53, 0x54, 0x55, 0x56, 0xf4, 0xf7, 0x144, 0x156, 0x15b
2996c92544dSBjoern A. Zeeb 	};
3006c92544dSBjoern A. Zeeb 	u8 *eeprom = dev->mt76.eeprom.data;
3016c92544dSBjoern A. Zeeb 	u8 *otp = dev->mt76.otp.data;
3026c92544dSBjoern A. Zeeb 	int i;
3036c92544dSBjoern A. Zeeb 
3046c92544dSBjoern A. Zeeb 	if (!otp)
3056c92544dSBjoern A. Zeeb 		return;
3066c92544dSBjoern A. Zeeb 
3076c92544dSBjoern A. Zeeb 	for (i = 0; i < ARRAY_SIZE(ical); i++) {
3086c92544dSBjoern A. Zeeb 		if (!otp[ical[i]])
3096c92544dSBjoern A. Zeeb 			continue;
3106c92544dSBjoern A. Zeeb 
3116c92544dSBjoern A. Zeeb 		eeprom[ical[i]] = otp[ical[i]];
3126c92544dSBjoern A. Zeeb 	}
3136c92544dSBjoern A. Zeeb }
3146c92544dSBjoern A. Zeeb 
3156c92544dSBjoern A. Zeeb static void mt7615_cal_free_data(struct mt7615_dev *dev)
3166c92544dSBjoern A. Zeeb {
3176c92544dSBjoern A. Zeeb 	struct device_node *np = dev->mt76.dev->of_node;
3186c92544dSBjoern A. Zeeb 
3196c92544dSBjoern A. Zeeb 	if (!np || !of_property_read_bool(np, "mediatek,eeprom-merge-otp"))
3206c92544dSBjoern A. Zeeb 		return;
3216c92544dSBjoern A. Zeeb 
3226c92544dSBjoern A. Zeeb 	switch (mt76_chip(&dev->mt76)) {
3236c92544dSBjoern A. Zeeb 	case 0x7622:
3246c92544dSBjoern A. Zeeb 		mt7622_apply_cal_free_data(dev);
3256c92544dSBjoern A. Zeeb 		break;
3266c92544dSBjoern A. Zeeb 	case 0x7615:
3276c92544dSBjoern A. Zeeb 	case 0x7611:
3286c92544dSBjoern A. Zeeb 		mt7615_apply_cal_free_data(dev);
3296c92544dSBjoern A. Zeeb 		break;
3306c92544dSBjoern A. Zeeb 	}
3316c92544dSBjoern A. Zeeb }
3326c92544dSBjoern A. Zeeb 
3336c92544dSBjoern A. Zeeb int mt7615_eeprom_init(struct mt7615_dev *dev, u32 addr)
3346c92544dSBjoern A. Zeeb {
3356c92544dSBjoern A. Zeeb 	int ret;
3366c92544dSBjoern A. Zeeb 
3376c92544dSBjoern A. Zeeb 	ret = mt7615_eeprom_load(dev, addr);
3386c92544dSBjoern A. Zeeb 	if (ret < 0)
3396c92544dSBjoern A. Zeeb 		return ret;
3406c92544dSBjoern A. Zeeb 
3416c92544dSBjoern A. Zeeb 	ret = mt7615_check_eeprom(&dev->mt76);
3426c92544dSBjoern A. Zeeb 	if (ret && dev->mt76.otp.data) {
3436c92544dSBjoern A. Zeeb 		memcpy(dev->mt76.eeprom.data, dev->mt76.otp.data,
344*cbb3ec25SBjoern A. Zeeb 		       dev->mt76.otp.size);
3456c92544dSBjoern A. Zeeb 	} else {
3466c92544dSBjoern A. Zeeb 		dev->flash_eeprom = true;
3476c92544dSBjoern A. Zeeb 		mt7615_cal_free_data(dev);
3486c92544dSBjoern A. Zeeb 	}
3496c92544dSBjoern A. Zeeb 
3506c92544dSBjoern A. Zeeb 	mt7615_eeprom_parse_hw_cap(dev);
3516c92544dSBjoern A. Zeeb 	memcpy(dev->mphy.macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR,
3526c92544dSBjoern A. Zeeb 	       ETH_ALEN);
3536c92544dSBjoern A. Zeeb 
3546c92544dSBjoern A. Zeeb 	mt76_eeprom_override(&dev->mphy);
3556c92544dSBjoern A. Zeeb 
3566c92544dSBjoern A. Zeeb 	return 0;
3576c92544dSBjoern A. Zeeb }
3586c92544dSBjoern A. Zeeb EXPORT_SYMBOL_GPL(mt7615_eeprom_init);
359