1e57b7901SRyder Lee // SPDX-License-Identifier: ISC 2e57b7901SRyder Lee /* Copyright (C) 2020 MediaTek Inc. */ 3e57b7901SRyder Lee 4e57b7901SRyder Lee #include "mt7915.h" 5e57b7901SRyder Lee #include "eeprom.h" 6e57b7901SRyder Lee 7078b6d21SLorenzo Bianconi static u32 mt7915_eeprom_read(struct mt7915_dev *dev, u32 offset) 8e57b7901SRyder Lee { 9e57b7901SRyder Lee u8 *data = dev->mt76.eeprom.data; 10e57b7901SRyder Lee 11078b6d21SLorenzo Bianconi if (data[offset] == 0xff) 12e57b7901SRyder Lee mt7915_mcu_get_eeprom(dev, offset); 13e57b7901SRyder Lee 14e57b7901SRyder Lee return data[offset]; 15e57b7901SRyder Lee } 16e57b7901SRyder Lee 17495184acSRyder Lee static int mt7915_eeprom_load_precal(struct mt7915_dev *dev) 18495184acSRyder Lee { 19495184acSRyder Lee struct mt76_dev *mdev = &dev->mt76; 20495184acSRyder Lee u32 val; 21495184acSRyder Lee 22495184acSRyder Lee val = mt7915_eeprom_read(dev, MT_EE_DO_PRE_CAL); 23495184acSRyder Lee if (val != (MT_EE_WIFI_CAL_DPD | MT_EE_WIFI_CAL_GROUP)) 24495184acSRyder Lee return 0; 25495184acSRyder Lee 26495184acSRyder Lee val = MT_EE_CAL_GROUP_SIZE + MT_EE_CAL_DPD_SIZE; 27495184acSRyder Lee dev->cal = devm_kzalloc(mdev->dev, val, GFP_KERNEL); 28495184acSRyder Lee if (!dev->cal) 29495184acSRyder Lee return -ENOMEM; 30495184acSRyder Lee 31495184acSRyder Lee return mt76_get_of_eeprom(mdev, dev->cal, MT_EE_PRECAL, val); 32495184acSRyder Lee } 33495184acSRyder Lee 34e57b7901SRyder Lee static int mt7915_eeprom_load(struct mt7915_dev *dev) 35e57b7901SRyder Lee { 36e57b7901SRyder Lee int ret; 37e57b7901SRyder Lee 38e57b7901SRyder Lee ret = mt76_eeprom_init(&dev->mt76, MT7915_EEPROM_SIZE); 39e57b7901SRyder Lee if (ret < 0) 40e57b7901SRyder Lee return ret; 41e57b7901SRyder Lee 42495184acSRyder Lee if (ret) { 4326f18380SShayne Chen dev->flash_mode = true; 44495184acSRyder Lee ret = mt7915_eeprom_load_precal(dev); 45495184acSRyder Lee } else { 46e57b7901SRyder Lee memset(dev->mt76.eeprom.data, -1, MT7915_EEPROM_SIZE); 47495184acSRyder Lee } 48e57b7901SRyder Lee 49495184acSRyder Lee return ret; 50e57b7901SRyder Lee } 51e57b7901SRyder Lee 52e57b7901SRyder Lee static int mt7915_check_eeprom(struct mt7915_dev *dev) 53e57b7901SRyder Lee { 54e57b7901SRyder Lee u8 *eeprom = dev->mt76.eeprom.data; 553d51a3e9SLorenzo Bianconi u16 val; 56e57b7901SRyder Lee 573d51a3e9SLorenzo Bianconi mt7915_eeprom_read(dev, MT_EE_CHIP_ID); 58e57b7901SRyder Lee val = get_unaligned_le16(eeprom); 59e57b7901SRyder Lee 60e57b7901SRyder Lee switch (val) { 61e57b7901SRyder Lee case 0x7915: 62e57b7901SRyder Lee return 0; 63e57b7901SRyder Lee default: 64e57b7901SRyder Lee return -EINVAL; 65e57b7901SRyder Lee } 66e57b7901SRyder Lee } 67e57b7901SRyder Lee 684c430774SLorenzo Bianconi void mt7915_eeprom_parse_band_config(struct mt7915_phy *phy) 69e57b7901SRyder Lee { 704c430774SLorenzo Bianconi struct mt7915_dev *dev = phy->dev; 714c430774SLorenzo Bianconi bool ext_phy = phy != &dev->phy; 724c430774SLorenzo Bianconi u32 val; 73e57b7901SRyder Lee 744c430774SLorenzo Bianconi val = mt7915_eeprom_read(dev, MT_EE_WIFI_CONF + ext_phy); 75f7fc2bbeSFelix Fietkau val = FIELD_GET(MT_EE_WIFI_CONF0_BAND_SEL, val); 7645a8b67aSFelix Fietkau if (val == MT_EE_BAND_SEL_DEFAULT && dev->dbdc_support) 7745a8b67aSFelix Fietkau val = ext_phy ? MT_EE_BAND_SEL_5GHZ : MT_EE_BAND_SEL_2GHZ; 7845a8b67aSFelix Fietkau 79e57b7901SRyder Lee switch (val) { 8045a8b67aSFelix Fietkau case MT_EE_BAND_SEL_5GHZ: 814c430774SLorenzo Bianconi phy->mt76->cap.has_5ghz = true; 82e57b7901SRyder Lee break; 8345a8b67aSFelix Fietkau case MT_EE_BAND_SEL_2GHZ: 844c430774SLorenzo Bianconi phy->mt76->cap.has_2ghz = true; 85e57b7901SRyder Lee break; 86e57b7901SRyder Lee default: 874c430774SLorenzo Bianconi phy->mt76->cap.has_2ghz = true; 884c430774SLorenzo Bianconi phy->mt76->cap.has_5ghz = true; 89e57b7901SRyder Lee break; 90e57b7901SRyder Lee } 914c430774SLorenzo Bianconi } 924c430774SLorenzo Bianconi 934c430774SLorenzo Bianconi static void mt7915_eeprom_parse_hw_cap(struct mt7915_dev *dev) 944c430774SLorenzo Bianconi { 95f7fc2bbeSFelix Fietkau u8 nss, nss_band, *eeprom = dev->mt76.eeprom.data; 964c430774SLorenzo Bianconi 974c430774SLorenzo Bianconi mt7915_eeprom_parse_band_config(&dev->phy); 98e57b7901SRyder Lee 99e57b7901SRyder Lee /* read tx mask from eeprom */ 100f7fc2bbeSFelix Fietkau nss = FIELD_GET(MT_EE_WIFI_CONF0_TX_PATH, eeprom[MT_EE_WIFI_CONF]); 101f7fc2bbeSFelix Fietkau if (!nss || nss > 4) 102f7fc2bbeSFelix Fietkau nss = 4; 103e57b7901SRyder Lee 104f7fc2bbeSFelix Fietkau nss_band = nss; 105f7fc2bbeSFelix Fietkau 106f7fc2bbeSFelix Fietkau if (dev->dbdc_support) { 107f7fc2bbeSFelix Fietkau nss_band = FIELD_GET(MT_EE_WIFI_CONF3_TX_PATH_B0, 108f7fc2bbeSFelix Fietkau eeprom[MT_EE_WIFI_CONF + 3]); 109f7fc2bbeSFelix Fietkau if (!nss_band || nss_band > 2) 110f7fc2bbeSFelix Fietkau nss_band = 2; 111f7fc2bbeSFelix Fietkau 112f7fc2bbeSFelix Fietkau if (nss_band >= nss) 1134c430774SLorenzo Bianconi nss = 4; 1144c430774SLorenzo Bianconi } 1154c430774SLorenzo Bianconi 1164c430774SLorenzo Bianconi dev->chainmask = BIT(nss) - 1; 117f7fc2bbeSFelix Fietkau dev->mphy.antenna_mask = BIT(nss_band) - 1; 118b9027e08SLorenzo Bianconi dev->mphy.chainmask = dev->mphy.antenna_mask; 119e57b7901SRyder Lee } 120e57b7901SRyder Lee 121e57b7901SRyder Lee int mt7915_eeprom_init(struct mt7915_dev *dev) 122e57b7901SRyder Lee { 123e57b7901SRyder Lee int ret; 124e57b7901SRyder Lee 125e57b7901SRyder Lee ret = mt7915_eeprom_load(dev); 126e57b7901SRyder Lee if (ret < 0) 127e57b7901SRyder Lee return ret; 128e57b7901SRyder Lee 129e57b7901SRyder Lee ret = mt7915_check_eeprom(dev); 130e57b7901SRyder Lee if (ret) 131e57b7901SRyder Lee return ret; 132e57b7901SRyder Lee 133e57b7901SRyder Lee mt7915_eeprom_parse_hw_cap(dev); 13498df2baeSLorenzo Bianconi memcpy(dev->mphy.macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR, 135e57b7901SRyder Lee ETH_ALEN); 136e57b7901SRyder Lee 13798df2baeSLorenzo Bianconi mt76_eeprom_override(&dev->mphy); 138e57b7901SRyder Lee 139e57b7901SRyder Lee return 0; 140e57b7901SRyder Lee } 141e57b7901SRyder Lee 142e57b7901SRyder Lee int mt7915_eeprom_get_target_power(struct mt7915_dev *dev, 143e57b7901SRyder Lee struct ieee80211_channel *chan, 144e57b7901SRyder Lee u8 chain_idx) 145e57b7901SRyder Lee { 146a226ccd0SShayne Chen int index, target_power; 147e57b7901SRyder Lee bool tssi_on; 148e57b7901SRyder Lee 149e57b7901SRyder Lee if (chain_idx > 3) 150e57b7901SRyder Lee return -EINVAL; 151e57b7901SRyder Lee 152e57b7901SRyder Lee tssi_on = mt7915_tssi_enabled(dev, chan->band); 153e57b7901SRyder Lee 154e57b7901SRyder Lee if (chan->band == NL80211_BAND_2GHZ) { 155a226ccd0SShayne Chen index = MT_EE_TX0_POWER_2G + chain_idx * 3; 156a226ccd0SShayne Chen target_power = mt7915_eeprom_read(dev, index); 157e57b7901SRyder Lee 158a226ccd0SShayne Chen if (!tssi_on) 159a226ccd0SShayne Chen target_power += mt7915_eeprom_read(dev, index + 1); 160a226ccd0SShayne Chen } else { 161a226ccd0SShayne Chen int group = mt7915_get_channel_group(chan->hw_value); 162a226ccd0SShayne Chen 163a226ccd0SShayne Chen index = MT_EE_TX0_POWER_5G + chain_idx * 12; 164a226ccd0SShayne Chen target_power = mt7915_eeprom_read(dev, index + group); 165a226ccd0SShayne Chen 166a226ccd0SShayne Chen if (!tssi_on) 167a226ccd0SShayne Chen target_power += mt7915_eeprom_read(dev, index + 8); 168e57b7901SRyder Lee } 169e57b7901SRyder Lee 170a226ccd0SShayne Chen return target_power; 171e57b7901SRyder Lee } 172f1d96236SRyder Lee 173*ecb187a7SShayne Chen s8 mt7915_eeprom_get_power_delta(struct mt7915_dev *dev, int band) 174f1d96236SRyder Lee { 175*ecb187a7SShayne Chen u32 val; 176*ecb187a7SShayne Chen s8 delta; 177f1d96236SRyder Lee 178*ecb187a7SShayne Chen if (band == NL80211_BAND_2GHZ) 179*ecb187a7SShayne Chen val = mt7915_eeprom_read(dev, MT_EE_RATE_DELTA_2G); 180*ecb187a7SShayne Chen else 181*ecb187a7SShayne Chen val = mt7915_eeprom_read(dev, MT_EE_RATE_DELTA_5G); 182*ecb187a7SShayne Chen 183*ecb187a7SShayne Chen if (!(val & MT_EE_RATE_DELTA_EN)) 184f1d96236SRyder Lee return 0; 185f1d96236SRyder Lee 186*ecb187a7SShayne Chen delta = FIELD_GET(MT_EE_RATE_DELTA_MASK, val); 187*ecb187a7SShayne Chen 188*ecb187a7SShayne Chen return val & MT_EE_RATE_DELTA_SIGN ? delta : -delta; 189f1d96236SRyder Lee } 190f1d96236SRyder Lee 191*ecb187a7SShayne Chen const u8 mt7915_sku_group_len[] = { 192*ecb187a7SShayne Chen [SKU_CCK] = 4, 193*ecb187a7SShayne Chen [SKU_OFDM] = 8, 194*ecb187a7SShayne Chen [SKU_HT_BW20] = 8, 195*ecb187a7SShayne Chen [SKU_HT_BW40] = 9, 196*ecb187a7SShayne Chen [SKU_VHT_BW20] = 12, 197*ecb187a7SShayne Chen [SKU_VHT_BW40] = 12, 198*ecb187a7SShayne Chen [SKU_VHT_BW80] = 12, 199*ecb187a7SShayne Chen [SKU_VHT_BW160] = 12, 200*ecb187a7SShayne Chen [SKU_HE_RU26] = 12, 201*ecb187a7SShayne Chen [SKU_HE_RU52] = 12, 202*ecb187a7SShayne Chen [SKU_HE_RU106] = 12, 203*ecb187a7SShayne Chen [SKU_HE_RU242] = 12, 204*ecb187a7SShayne Chen [SKU_HE_RU484] = 12, 205*ecb187a7SShayne Chen [SKU_HE_RU996] = 12, 206*ecb187a7SShayne Chen [SKU_HE_RU2x996] = 12 207*ecb187a7SShayne Chen }; 208