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