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 (7702B)


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