cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

eeprom.c (8200B)


      1// SPDX-License-Identifier: ISC
      2/* Copyright (C) 2020 MediaTek Inc. */
      3
      4#include <linux/firmware.h>
      5#include "mt7915.h"
      6#include "eeprom.h"
      7
      8static int mt7915_eeprom_load_precal(struct mt7915_dev *dev)
      9{
     10	struct mt76_dev *mdev = &dev->mt76;
     11	u8 *eeprom = mdev->eeprom.data;
     12	u32 val = eeprom[MT_EE_DO_PRE_CAL];
     13	u32 offs;
     14
     15	if (!dev->flash_mode)
     16		return 0;
     17
     18	if (val != (MT_EE_WIFI_CAL_DPD | MT_EE_WIFI_CAL_GROUP))
     19		return 0;
     20
     21	val = MT_EE_CAL_GROUP_SIZE + MT_EE_CAL_DPD_SIZE;
     22	dev->cal = devm_kzalloc(mdev->dev, val, GFP_KERNEL);
     23	if (!dev->cal)
     24		return -ENOMEM;
     25
     26	offs = is_mt7915(&dev->mt76) ? MT_EE_PRECAL : MT_EE_PRECAL_V2;
     27
     28	return mt76_get_of_eeprom(mdev, dev->cal, offs, val);
     29}
     30
     31static int mt7915_check_eeprom(struct mt7915_dev *dev)
     32{
     33	u8 *eeprom = dev->mt76.eeprom.data;
     34	u16 val = get_unaligned_le16(eeprom);
     35
     36	switch (val) {
     37	case 0x7915:
     38	case 0x7916:
     39	case 0x7986:
     40		return 0;
     41	default:
     42		return -EINVAL;
     43	}
     44}
     45
     46static char *mt7915_eeprom_name(struct mt7915_dev *dev)
     47{
     48	switch (mt76_chip(&dev->mt76)) {
     49	case 0x7915:
     50		return dev->dbdc_support ?
     51		       MT7915_EEPROM_DEFAULT_DBDC : MT7915_EEPROM_DEFAULT;
     52	case 0x7986:
     53		switch (mt7915_check_adie(dev, true)) {
     54		case MT7976_ONE_ADIE_DBDC:
     55			return MT7986_EEPROM_MT7976_DEFAULT_DBDC;
     56		case MT7975_ONE_ADIE:
     57			return MT7986_EEPROM_MT7975_DEFAULT;
     58		case MT7976_ONE_ADIE:
     59			return MT7986_EEPROM_MT7976_DEFAULT;
     60		case MT7975_DUAL_ADIE:
     61			return MT7986_EEPROM_MT7975_DUAL_DEFAULT;
     62		case MT7976_DUAL_ADIE:
     63			return MT7986_EEPROM_MT7976_DUAL_DEFAULT;
     64		default:
     65			break;
     66		}
     67		return NULL;
     68	default:
     69		return MT7916_EEPROM_DEFAULT;
     70	}
     71}
     72
     73static int
     74mt7915_eeprom_load_default(struct mt7915_dev *dev)
     75{
     76	u8 *eeprom = dev->mt76.eeprom.data;
     77	const struct firmware *fw = NULL;
     78	int ret;
     79
     80	ret = request_firmware(&fw, mt7915_eeprom_name(dev), dev->mt76.dev);
     81	if (ret)
     82		return ret;
     83
     84	if (!fw || !fw->data) {
     85		dev_err(dev->mt76.dev, "Invalid default bin\n");
     86		ret = -EINVAL;
     87		goto out;
     88	}
     89
     90	memcpy(eeprom, fw->data, mt7915_eeprom_size(dev));
     91	dev->flash_mode = true;
     92
     93out:
     94	release_firmware(fw);
     95
     96	return ret;
     97}
     98
     99static int mt7915_eeprom_load(struct mt7915_dev *dev)
    100{
    101	int ret;
    102	u16 eeprom_size = mt7915_eeprom_size(dev);
    103
    104	ret = mt76_eeprom_init(&dev->mt76, eeprom_size);
    105	if (ret < 0)
    106		return ret;
    107
    108	if (ret) {
    109		dev->flash_mode = true;
    110	} else {
    111		u8 free_block_num;
    112		u32 block_num, i;
    113
    114		mt7915_mcu_get_eeprom_free_block(dev, &free_block_num);
    115		/* efuse info not enough */
    116		if (free_block_num >= 29)
    117			return -EINVAL;
    118
    119		/* read eeprom data from efuse */
    120		block_num = DIV_ROUND_UP(eeprom_size,
    121					 MT7915_EEPROM_BLOCK_SIZE);
    122		for (i = 0; i < block_num; i++)
    123			mt7915_mcu_get_eeprom(dev,
    124					      i * MT7915_EEPROM_BLOCK_SIZE);
    125	}
    126
    127	return mt7915_check_eeprom(dev);
    128}
    129
    130static void mt7915_eeprom_parse_band_config(struct mt7915_phy *phy)
    131{
    132	struct mt7915_dev *dev = phy->dev;
    133	u8 *eeprom = dev->mt76.eeprom.data;
    134	u32 val;
    135
    136	val = eeprom[MT_EE_WIFI_CONF + phy->band_idx];
    137	val = FIELD_GET(MT_EE_WIFI_CONF0_BAND_SEL, val);
    138
    139	if (!is_mt7915(&dev->mt76)) {
    140		switch (val) {
    141		case MT_EE_V2_BAND_SEL_5GHZ:
    142			phy->mt76->cap.has_5ghz = true;
    143			return;
    144		case MT_EE_V2_BAND_SEL_6GHZ:
    145			phy->mt76->cap.has_6ghz = true;
    146			return;
    147		case MT_EE_V2_BAND_SEL_5GHZ_6GHZ:
    148			phy->mt76->cap.has_5ghz = true;
    149			phy->mt76->cap.has_6ghz = true;
    150			return;
    151		default:
    152			phy->mt76->cap.has_2ghz = true;
    153			return;
    154		}
    155	} else if (val == MT_EE_BAND_SEL_DEFAULT && dev->dbdc_support) {
    156		val = phy->band_idx ? MT_EE_BAND_SEL_5GHZ : MT_EE_BAND_SEL_2GHZ;
    157	}
    158
    159	switch (val) {
    160	case MT_EE_BAND_SEL_5GHZ:
    161		phy->mt76->cap.has_5ghz = true;
    162		break;
    163	case MT_EE_BAND_SEL_2GHZ:
    164		phy->mt76->cap.has_2ghz = true;
    165		break;
    166	default:
    167		phy->mt76->cap.has_2ghz = true;
    168		phy->mt76->cap.has_5ghz = true;
    169		break;
    170	}
    171}
    172
    173void mt7915_eeprom_parse_hw_cap(struct mt7915_dev *dev,
    174				struct mt7915_phy *phy)
    175{
    176	u8 nss, nss_band, nss_band_max, *eeprom = dev->mt76.eeprom.data;
    177	struct mt76_phy *mphy = phy->mt76;
    178	bool ext_phy = phy != &dev->phy;
    179
    180	mt7915_eeprom_parse_band_config(phy);
    181
    182	/* read tx/rx mask from eeprom */
    183	if (is_mt7915(&dev->mt76)) {
    184		nss = FIELD_GET(MT_EE_WIFI_CONF0_TX_PATH,
    185				eeprom[MT_EE_WIFI_CONF]);
    186	} else {
    187		nss = FIELD_GET(MT_EE_WIFI_CONF0_TX_PATH,
    188				eeprom[MT_EE_WIFI_CONF + phy->band_idx]);
    189	}
    190
    191	if (!nss || nss > 4)
    192		nss = 4;
    193
    194	/* read tx/rx stream */
    195	nss_band = nss;
    196
    197	if (dev->dbdc_support) {
    198		if (is_mt7915(&dev->mt76)) {
    199			nss_band = FIELD_GET(MT_EE_WIFI_CONF3_TX_PATH_B0,
    200					     eeprom[MT_EE_WIFI_CONF + 3]);
    201			if (phy->band_idx)
    202				nss_band = FIELD_GET(MT_EE_WIFI_CONF3_TX_PATH_B1,
    203						     eeprom[MT_EE_WIFI_CONF + 3]);
    204		} else {
    205			nss_band = FIELD_GET(MT_EE_WIFI_CONF_STREAM_NUM,
    206					     eeprom[MT_EE_WIFI_CONF + 2 + phy->band_idx]);
    207		}
    208
    209		nss_band_max = is_mt7986(&dev->mt76) ?
    210			       MT_EE_NSS_MAX_DBDC_MA7986 : MT_EE_NSS_MAX_DBDC_MA7915;
    211	} else {
    212		nss_band_max = is_mt7986(&dev->mt76) ?
    213			       MT_EE_NSS_MAX_MA7986 : MT_EE_NSS_MAX_MA7915;
    214	}
    215
    216	if (!nss_band || nss_band > nss_band_max)
    217		nss_band = nss_band_max;
    218
    219	if (nss_band > nss) {
    220		dev_warn(dev->mt76.dev,
    221			 "nss mismatch, nss(%d) nss_band(%d) band(%d) ext_phy(%d)\n",
    222			 nss, nss_band, phy->band_idx, ext_phy);
    223		nss = nss_band;
    224	}
    225
    226	mphy->chainmask = BIT(nss) - 1;
    227	if (ext_phy)
    228		mphy->chainmask <<= dev->chainshift;
    229	mphy->antenna_mask = BIT(nss_band) - 1;
    230	dev->chainmask |= mphy->chainmask;
    231	dev->chainshift = hweight8(dev->mphy.chainmask);
    232}
    233
    234int mt7915_eeprom_init(struct mt7915_dev *dev)
    235{
    236	int ret;
    237
    238	ret = mt7915_eeprom_load(dev);
    239	if (ret < 0) {
    240		if (ret != -EINVAL)
    241			return ret;
    242
    243		dev_warn(dev->mt76.dev, "eeprom load fail, use default bin\n");
    244		ret = mt7915_eeprom_load_default(dev);
    245		if (ret)
    246			return ret;
    247	}
    248
    249	ret = mt7915_eeprom_load_precal(dev);
    250	if (ret)
    251		return ret;
    252
    253	mt7915_eeprom_parse_hw_cap(dev, &dev->phy);
    254	memcpy(dev->mphy.macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR,
    255	       ETH_ALEN);
    256
    257	mt76_eeprom_override(&dev->mphy);
    258
    259	return 0;
    260}
    261
    262int mt7915_eeprom_get_target_power(struct mt7915_dev *dev,
    263				   struct ieee80211_channel *chan,
    264				   u8 chain_idx)
    265{
    266	u8 *eeprom = dev->mt76.eeprom.data;
    267	int index, target_power;
    268	bool tssi_on, is_7976;
    269
    270	if (chain_idx > 3)
    271		return -EINVAL;
    272
    273	tssi_on = mt7915_tssi_enabled(dev, chan->band);
    274	is_7976 = mt7915_check_adie(dev, false) || is_mt7916(&dev->mt76);
    275
    276	if (chan->band == NL80211_BAND_2GHZ) {
    277		if (is_7976) {
    278			index = MT_EE_TX0_POWER_2G_V2 + chain_idx;
    279			target_power = eeprom[index];
    280		} else {
    281			index = MT_EE_TX0_POWER_2G + chain_idx * 3;
    282			target_power = eeprom[index];
    283
    284			if (!tssi_on)
    285				target_power += eeprom[index + 1];
    286		}
    287	} else if (chan->band == NL80211_BAND_5GHZ) {
    288		int group = mt7915_get_channel_group_5g(chan->hw_value, is_7976);
    289
    290		if (is_7976) {
    291			index = MT_EE_TX0_POWER_5G_V2 + chain_idx * 5;
    292			target_power = eeprom[index + group];
    293		} else {
    294			index = MT_EE_TX0_POWER_5G + chain_idx * 12;
    295			target_power = eeprom[index + group];
    296
    297			if (!tssi_on)
    298				target_power += eeprom[index + 8];
    299		}
    300	} else {
    301		int group = mt7915_get_channel_group_6g(chan->hw_value);
    302
    303		index = MT_EE_TX0_POWER_6G_V2 + chain_idx * 8;
    304		target_power = is_7976 ? eeprom[index + group] : 0;
    305	}
    306
    307	return target_power;
    308}
    309
    310s8 mt7915_eeprom_get_power_delta(struct mt7915_dev *dev, int band)
    311{
    312	u8 *eeprom = dev->mt76.eeprom.data;
    313	u32 val, offs;
    314	s8 delta;
    315	bool is_7976 = mt7915_check_adie(dev, false) || is_mt7916(&dev->mt76);
    316
    317	if (band == NL80211_BAND_2GHZ)
    318		offs = is_7976 ? MT_EE_RATE_DELTA_2G_V2 : MT_EE_RATE_DELTA_2G;
    319	else if (band == NL80211_BAND_5GHZ)
    320		offs = is_7976 ? MT_EE_RATE_DELTA_5G_V2 : MT_EE_RATE_DELTA_5G;
    321	else
    322		offs = is_7976 ? MT_EE_RATE_DELTA_6G_V2 : 0;
    323
    324	val = eeprom[offs];
    325
    326	if (!offs || !(val & MT_EE_RATE_DELTA_EN))
    327		return 0;
    328
    329	delta = FIELD_GET(MT_EE_RATE_DELTA_MASK, val);
    330
    331	return val & MT_EE_RATE_DELTA_SIGN ? delta : -delta;
    332}
    333
    334const u8 mt7915_sku_group_len[] = {
    335	[SKU_CCK] = 4,
    336	[SKU_OFDM] = 8,
    337	[SKU_HT_BW20] = 8,
    338	[SKU_HT_BW40] = 9,
    339	[SKU_VHT_BW20] = 12,
    340	[SKU_VHT_BW40] = 12,
    341	[SKU_VHT_BW80] = 12,
    342	[SKU_VHT_BW160] = 12,
    343	[SKU_HE_RU26] = 12,
    344	[SKU_HE_RU52] = 12,
    345	[SKU_HE_RU106] = 12,
    346	[SKU_HE_RU242] = 12,
    347	[SKU_HE_RU484] = 12,
    348	[SKU_HE_RU996] = 12,
    349	[SKU_HE_RU2x996] = 12
    350};