brintos

brintos / linux-shallow public Read only

0
0
Text · 7.6 KiB · ccedea7 Raw
359 lines · c
1// SPDX-License-Identifier: ISC2/* Copyright (C) 2019 MediaTek Inc.3 *4 * Author: Ryder Lee <ryder.lee@mediatek.com>5 *         Felix Fietkau <nbd@nbd.name>6 */7 8#include <linux/of.h>9#include "mt7615.h"10#include "eeprom.h"11 12static int mt7615_efuse_read(struct mt7615_dev *dev, u32 base,13			     u16 addr, u8 *data)14{15	u32 val;16	int i;17 18	val = mt76_rr(dev, base + MT_EFUSE_CTRL);19	val &= ~(MT_EFUSE_CTRL_AIN | MT_EFUSE_CTRL_MODE);20	val |= FIELD_PREP(MT_EFUSE_CTRL_AIN, addr & ~0xf);21	val |= MT_EFUSE_CTRL_KICK;22	mt76_wr(dev, base + MT_EFUSE_CTRL, val);23 24	if (!mt76_poll(dev, base + MT_EFUSE_CTRL, MT_EFUSE_CTRL_KICK, 0, 1000))25		return -ETIMEDOUT;26 27	udelay(2);28 29	val = mt76_rr(dev, base + MT_EFUSE_CTRL);30	if ((val & MT_EFUSE_CTRL_AOUT) == MT_EFUSE_CTRL_AOUT ||31	    WARN_ON_ONCE(!(val & MT_EFUSE_CTRL_VALID))) {32		memset(data, 0x0, 16);33		return 0;34	}35 36	for (i = 0; i < 4; i++) {37		val = mt76_rr(dev, base + MT_EFUSE_RDATA(i));38		put_unaligned_le32(val, data + 4 * i);39	}40 41	return 0;42}43 44static int mt7615_efuse_init(struct mt7615_dev *dev, u32 base)45{46	int i, len = MT7615_EEPROM_SIZE;47	void *buf;48	u32 val;49 50	if (is_mt7663(&dev->mt76))51		len = MT7663_EEPROM_SIZE;52 53	val = mt76_rr(dev, base + MT_EFUSE_BASE_CTRL);54	if (val & MT_EFUSE_BASE_CTRL_EMPTY)55		return 0;56 57	dev->mt76.otp.data = devm_kzalloc(dev->mt76.dev, len, GFP_KERNEL);58	dev->mt76.otp.size = len;59	if (!dev->mt76.otp.data)60		return -ENOMEM;61 62	buf = dev->mt76.otp.data;63	for (i = 0; i + 16 <= len; i += 16) {64		int ret;65 66		ret = mt7615_efuse_read(dev, base, i, buf + i);67		if (ret)68			return ret;69	}70 71	return 0;72}73 74static int mt7615_eeprom_load(struct mt7615_dev *dev, u32 addr)75{76	int ret;77 78	BUILD_BUG_ON(MT7615_EEPROM_FULL_SIZE < MT7663_EEPROM_SIZE);79 80	ret = mt76_eeprom_init(&dev->mt76, MT7615_EEPROM_FULL_SIZE);81	if (ret < 0)82		return ret;83 84	return mt7615_efuse_init(dev, addr);85}86 87static int mt7615_check_eeprom(struct mt76_dev *dev)88{89	u16 val = get_unaligned_le16(dev->eeprom.data);90 91	switch (val) {92	case 0x7615:93	case 0x7622:94	case 0x7663:95		return 0;96	default:97		return -EINVAL;98	}99}100 101static void102mt7615_eeprom_parse_hw_band_cap(struct mt7615_dev *dev)103{104	u8 val, *eeprom = dev->mt76.eeprom.data;105 106	if (is_mt7663(&dev->mt76)) {107		/* dual band */108		dev->mphy.cap.has_2ghz = true;109		dev->mphy.cap.has_5ghz = true;110		return;111	}112 113	if (is_mt7622(&dev->mt76)) {114		/* 2GHz only */115		dev->mphy.cap.has_2ghz = true;116		return;117	}118 119	if (is_mt7611(&dev->mt76)) {120		/* 5GHz only */121		dev->mphy.cap.has_5ghz = true;122		return;123	}124 125	val = FIELD_GET(MT_EE_NIC_WIFI_CONF_BAND_SEL,126			eeprom[MT_EE_WIFI_CONF]);127	switch (val) {128	case MT_EE_5GHZ:129		dev->mphy.cap.has_5ghz = true;130		break;131	case MT_EE_DBDC:132		dev->dbdc_support = true;133		fallthrough;134	case MT_EE_2GHZ:135		dev->mphy.cap.has_2ghz = true;136		break;137	default:138		dev->mphy.cap.has_2ghz = true;139		dev->mphy.cap.has_5ghz = true;140		break;141	}142}143 144static void mt7615_eeprom_parse_hw_cap(struct mt7615_dev *dev)145{146	u8 *eeprom = dev->mt76.eeprom.data;147	u8 tx_mask, max_nss;148 149	mt7615_eeprom_parse_hw_band_cap(dev);150 151	if (is_mt7663(&dev->mt76)) {152		max_nss = 2;153		tx_mask = FIELD_GET(MT_EE_HW_CONF1_TX_MASK,154				    eeprom[MT7663_EE_HW_CONF1]);155	} else {156		u32 val;157 158		/* read tx-rx mask from eeprom */159		val = mt76_rr(dev, MT_TOP_STRAP_STA);160		max_nss = val & MT_TOP_3NSS ? 3 : 4;161 162		tx_mask =  FIELD_GET(MT_EE_NIC_CONF_TX_MASK,163				     eeprom[MT_EE_NIC_CONF_0]);164	}165	if (!tx_mask || tx_mask > max_nss)166		tx_mask = max_nss;167 168	dev->chainmask = BIT(tx_mask) - 1;169	dev->mphy.antenna_mask = dev->chainmask;170	dev->mphy.chainmask = dev->chainmask;171}172 173static int mt7663_eeprom_get_target_power_index(struct mt7615_dev *dev,174						struct ieee80211_channel *chan,175						u8 chain_idx)176{177	int index, group;178 179	if (chain_idx > 1)180		return -EINVAL;181 182	if (chan->band == NL80211_BAND_2GHZ)183		return MT7663_EE_TX0_2G_TARGET_POWER + (chain_idx << 4);184 185	group = mt7615_get_channel_group(chan->hw_value);186	if (chain_idx == 1)187		index = MT7663_EE_TX1_5G_G0_TARGET_POWER;188	else189		index = MT7663_EE_TX0_5G_G0_TARGET_POWER;190 191	return index + group * 3;192}193 194int mt7615_eeprom_get_target_power_index(struct mt7615_dev *dev,195					 struct ieee80211_channel *chan,196					 u8 chain_idx)197{198	int index;199 200	if (is_mt7663(&dev->mt76))201		return mt7663_eeprom_get_target_power_index(dev, chan,202							    chain_idx);203 204	if (chain_idx > 3)205		return -EINVAL;206 207	/* TSSI disabled */208	if (mt7615_ext_pa_enabled(dev, chan->band)) {209		if (chan->band == NL80211_BAND_2GHZ)210			return MT_EE_EXT_PA_2G_TARGET_POWER;211		else212			return MT_EE_EXT_PA_5G_TARGET_POWER;213	}214 215	/* TSSI enabled */216	if (chan->band == NL80211_BAND_2GHZ) {217		index = MT_EE_TX0_2G_TARGET_POWER + chain_idx * 6;218	} else {219		int group = mt7615_get_channel_group(chan->hw_value);220 221		switch (chain_idx) {222		case 1:223			index = MT_EE_TX1_5G_G0_TARGET_POWER;224			break;225		case 2:226			index = MT_EE_TX2_5G_G0_TARGET_POWER;227			break;228		case 3:229			index = MT_EE_TX3_5G_G0_TARGET_POWER;230			break;231		case 0:232		default:233			index = MT_EE_TX0_5G_G0_TARGET_POWER;234			break;235		}236		index += 5 * group;237	}238 239	return index;240}241 242int mt7615_eeprom_get_power_delta_index(struct mt7615_dev *dev,243					enum nl80211_band band)244{245	/* assume the first rate has the highest power offset */246	if (is_mt7663(&dev->mt76)) {247		if (band == NL80211_BAND_2GHZ)248			return MT_EE_TX0_5G_G0_TARGET_POWER;249		else250			return MT7663_EE_5G_RATE_POWER;251	}252 253	if (band == NL80211_BAND_2GHZ)254		return MT_EE_2G_RATE_POWER;255	else256		return MT_EE_5G_RATE_POWER;257}258 259static void mt7615_apply_cal_free_data(struct mt7615_dev *dev)260{261	static const u16 ical[] = {262		0x53, 0x54, 0x55, 0x56, 0x57, 0x5c, 0x5d, 0x62, 0x63, 0x68,263		0x69, 0x6e, 0x6f, 0x73, 0x74, 0x78, 0x79, 0x82, 0x83, 0x87,264		0x88, 0x8c, 0x8d, 0x91, 0x92, 0x96, 0x97, 0x9b, 0x9c, 0xa0,265		0xa1, 0xaa, 0xab, 0xaf, 0xb0, 0xb4, 0xb5, 0xb9, 0xba, 0xf4,266		0xf7, 0xff,267		0x140, 0x141, 0x145, 0x146, 0x14a, 0x14b, 0x154, 0x155, 0x159,268		0x15a, 0x15e, 0x15f, 0x163, 0x164, 0x168, 0x169, 0x16d, 0x16e,269		0x172, 0x173, 0x17c, 0x17d, 0x181, 0x182, 0x186, 0x187, 0x18b,270		0x18c271	};272	static const u16 ical_nocheck[] = {273		0x110, 0x111, 0x112, 0x113, 0x114, 0x115, 0x116, 0x117, 0x118,274		0x1b5, 0x1b6, 0x1b7, 0x3ac, 0x3ad, 0x3ae, 0x3af, 0x3b0, 0x3b1,275		0x3b2276	};277	u8 *eeprom = dev->mt76.eeprom.data;278	u8 *otp = dev->mt76.otp.data;279	int i;280 281	if (!otp)282		return;283 284	for (i = 0; i < ARRAY_SIZE(ical); i++)285		if (!otp[ical[i]])286			return;287 288	for (i = 0; i < ARRAY_SIZE(ical); i++)289		eeprom[ical[i]] = otp[ical[i]];290 291	for (i = 0; i < ARRAY_SIZE(ical_nocheck); i++)292		eeprom[ical_nocheck[i]] = otp[ical_nocheck[i]];293}294 295static void mt7622_apply_cal_free_data(struct mt7615_dev *dev)296{297	static const u16 ical[] = {298		0x53, 0x54, 0x55, 0x56, 0xf4, 0xf7, 0x144, 0x156, 0x15b299	};300	u8 *eeprom = dev->mt76.eeprom.data;301	u8 *otp = dev->mt76.otp.data;302	int i;303 304	if (!otp)305		return;306 307	for (i = 0; i < ARRAY_SIZE(ical); i++) {308		if (!otp[ical[i]])309			continue;310 311		eeprom[ical[i]] = otp[ical[i]];312	}313}314 315static void mt7615_cal_free_data(struct mt7615_dev *dev)316{317	struct device_node *np = dev->mt76.dev->of_node;318 319	if (!np || !of_property_read_bool(np, "mediatek,eeprom-merge-otp"))320		return;321 322	switch (mt76_chip(&dev->mt76)) {323	case 0x7622:324		mt7622_apply_cal_free_data(dev);325		break;326	case 0x7615:327	case 0x7611:328		mt7615_apply_cal_free_data(dev);329		break;330	}331}332 333int mt7615_eeprom_init(struct mt7615_dev *dev, u32 addr)334{335	int ret;336 337	ret = mt7615_eeprom_load(dev, addr);338	if (ret < 0)339		return ret;340 341	ret = mt7615_check_eeprom(&dev->mt76);342	if (ret && dev->mt76.otp.data) {343		memcpy(dev->mt76.eeprom.data, dev->mt76.otp.data,344		       dev->mt76.otp.size);345	} else {346		dev->flash_eeprom = true;347		mt7615_cal_free_data(dev);348	}349 350	mt7615_eeprom_parse_hw_cap(dev);351	memcpy(dev->mphy.macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR,352	       ETH_ALEN);353 354	mt76_eeprom_override(&dev->mphy);355 356	return 0;357}358EXPORT_SYMBOL_GPL(mt7615_eeprom_init);359