Path: blob/main/sys/contrib/dev/mediatek/mt76/mt7915/eeprom.c
48526 views
// SPDX-License-Identifier: ISC1/* Copyright (C) 2020 MediaTek Inc. */23#include <linux/firmware.h>4#include <linux/moduleparam.h>5#include "mt7915.h"6#include "eeprom.h"78static bool enable_6ghz;9module_param(enable_6ghz, bool, 0644);10MODULE_PARM_DESC(enable_6ghz, "Enable 6 GHz instead of 5 GHz on hardware that supports both");1112static int mt7915_eeprom_load_precal(struct mt7915_dev *dev)13{14struct mt76_dev *mdev = &dev->mt76;15u8 *eeprom = mdev->eeprom.data;16u32 offs = is_mt7915(&dev->mt76) ? MT_EE_DO_PRE_CAL : MT_EE_DO_PRE_CAL_V2;17u32 size, val = eeprom[offs];18int ret;1920if (!dev->flash_mode || !val)21return 0;2223size = mt7915_get_cal_group_size(dev) + mt7915_get_cal_dpd_size(dev);2425dev->cal = devm_kzalloc(mdev->dev, size, GFP_KERNEL);26if (!dev->cal)27return -ENOMEM;2829offs = is_mt7915(&dev->mt76) ? MT_EE_PRECAL : MT_EE_PRECAL_V2;3031ret = mt76_get_of_data_from_mtd(mdev, dev->cal, offs, size);32if (!ret)33return ret;3435ret = mt76_get_of_data_from_nvmem(mdev, dev->cal, "precal", size);36if (!ret)37return ret;3839dev_warn(mdev->dev, "missing precal data, size=%d\n", size);40devm_kfree(mdev->dev, dev->cal);41dev->cal = NULL;4243return ret;44}4546static int mt7915_check_eeprom(struct mt7915_dev *dev)47{48u8 *eeprom = dev->mt76.eeprom.data;49u16 val = get_unaligned_le16(eeprom);5051#define CHECK_EEPROM_ERR(match) (match ? 0 : -EINVAL)52switch (val) {53case 0x7915:54return CHECK_EEPROM_ERR(is_mt7915(&dev->mt76));55case 0x7916:56return CHECK_EEPROM_ERR(is_mt7916(&dev->mt76));57case 0x7981:58return CHECK_EEPROM_ERR(is_mt7981(&dev->mt76));59case 0x7986:60return CHECK_EEPROM_ERR(is_mt7986(&dev->mt76));61default:62return -EINVAL;63}64}6566static char *mt7915_eeprom_name(struct mt7915_dev *dev)67{68switch (mt76_chip(&dev->mt76)) {69case 0x7915:70return dev->dbdc_support ?71MT7915_EEPROM_DEFAULT_DBDC : MT7915_EEPROM_DEFAULT;72case 0x7981:73/* mt7981 only supports mt7976 and only in DBDC mode */74return MT7981_EEPROM_MT7976_DEFAULT_DBDC;75case 0x7986:76switch (mt7915_check_adie(dev, true)) {77case MT7976_ONE_ADIE_DBDC:78return MT7986_EEPROM_MT7976_DEFAULT_DBDC;79case MT7975_ONE_ADIE:80return MT7986_EEPROM_MT7975_DEFAULT;81case MT7976_ONE_ADIE:82return MT7986_EEPROM_MT7976_DEFAULT;83case MT7975_DUAL_ADIE:84return MT7986_EEPROM_MT7975_DUAL_DEFAULT;85case MT7976_DUAL_ADIE:86return MT7986_EEPROM_MT7976_DUAL_DEFAULT;87default:88break;89}90return NULL;91default:92return MT7916_EEPROM_DEFAULT;93}94}9596static int97mt7915_eeprom_load_default(struct mt7915_dev *dev)98{99u8 *eeprom = dev->mt76.eeprom.data;100const struct firmware *fw = NULL;101int ret;102103ret = request_firmware(&fw, mt7915_eeprom_name(dev), dev->mt76.dev);104if (ret)105return ret;106107if (!fw || !fw->data) {108dev_err(dev->mt76.dev, "Invalid default bin\n");109ret = -EINVAL;110goto out;111}112113memcpy(eeprom, fw->data, mt7915_eeprom_size(dev));114dev->flash_mode = true;115116out:117release_firmware(fw);118119return ret;120}121122static int mt7915_eeprom_load(struct mt7915_dev *dev)123{124int ret;125u16 eeprom_size = mt7915_eeprom_size(dev);126127ret = mt76_eeprom_init(&dev->mt76, eeprom_size);128if (ret < 0)129return ret;130131if (ret) {132dev->flash_mode = true;133} else {134u8 free_block_num;135u32 block_num, i;136u32 eeprom_blk_size = MT7915_EEPROM_BLOCK_SIZE;137138ret = mt7915_mcu_get_eeprom_free_block(dev, &free_block_num);139if (ret < 0)140return ret;141142/* efuse info isn't enough */143if (free_block_num >= 29)144return -EINVAL;145146/* read eeprom data from efuse */147block_num = DIV_ROUND_UP(eeprom_size, eeprom_blk_size);148for (i = 0; i < block_num; i++) {149ret = mt7915_mcu_get_eeprom(dev, i * eeprom_blk_size, NULL);150if (ret < 0)151return ret;152}153}154155return mt7915_check_eeprom(dev);156}157158static void mt7915_eeprom_parse_band_config(struct mt7915_phy *phy)159{160struct mt7915_dev *dev = phy->dev;161u8 *eeprom = dev->mt76.eeprom.data;162u8 band = phy->mt76->band_idx;163u32 val;164165val = eeprom[MT_EE_WIFI_CONF + band];166val = FIELD_GET(MT_EE_WIFI_CONF0_BAND_SEL, val);167168if (!is_mt7915(&dev->mt76)) {169switch (val) {170case MT_EE_V2_BAND_SEL_5GHZ:171phy->mt76->cap.has_5ghz = true;172return;173case MT_EE_V2_BAND_SEL_6GHZ:174phy->mt76->cap.has_6ghz = true;175return;176case MT_EE_V2_BAND_SEL_5GHZ_6GHZ:177if (enable_6ghz) {178phy->mt76->cap.has_6ghz = true;179u8p_replace_bits(&eeprom[MT_EE_WIFI_CONF + band],180MT_EE_V2_BAND_SEL_6GHZ,181MT_EE_WIFI_CONF0_BAND_SEL);182} else {183phy->mt76->cap.has_5ghz = true;184u8p_replace_bits(&eeprom[MT_EE_WIFI_CONF + band],185MT_EE_V2_BAND_SEL_5GHZ,186MT_EE_WIFI_CONF0_BAND_SEL);187}188/* force to buffer mode */189dev->flash_mode = true;190191return;192default:193phy->mt76->cap.has_2ghz = true;194return;195}196} else if (val == MT_EE_BAND_SEL_DEFAULT && dev->dbdc_support) {197val = band ? MT_EE_BAND_SEL_5GHZ : MT_EE_BAND_SEL_2GHZ;198}199200switch (val) {201case MT_EE_BAND_SEL_5GHZ:202phy->mt76->cap.has_5ghz = true;203break;204case MT_EE_BAND_SEL_2GHZ:205phy->mt76->cap.has_2ghz = true;206break;207default:208phy->mt76->cap.has_2ghz = true;209phy->mt76->cap.has_5ghz = true;210break;211}212}213214void mt7915_eeprom_parse_hw_cap(struct mt7915_dev *dev,215struct mt7915_phy *phy)216{217u8 path, nss, nss_max = 4, *eeprom = dev->mt76.eeprom.data;218struct mt76_phy *mphy = phy->mt76;219u8 band = phy->mt76->band_idx;220221mt7915_eeprom_parse_band_config(phy);222223/* read tx/rx path from eeprom */224if (is_mt7915(&dev->mt76)) {225path = FIELD_GET(MT_EE_WIFI_CONF0_TX_PATH,226eeprom[MT_EE_WIFI_CONF]);227} else {228path = FIELD_GET(MT_EE_WIFI_CONF0_TX_PATH,229eeprom[MT_EE_WIFI_CONF + band]);230}231232if (!path || path > 4)233path = 4;234235/* read tx/rx stream */236nss = path;237if (dev->dbdc_support) {238if (is_mt7915(&dev->mt76)) {239path = min_t(u8, path, 2);240nss = FIELD_GET(MT_EE_WIFI_CONF3_TX_PATH_B0,241eeprom[MT_EE_WIFI_CONF + 3]);242if (band)243nss = FIELD_GET(MT_EE_WIFI_CONF3_TX_PATH_B1,244eeprom[MT_EE_WIFI_CONF + 3]);245} else {246nss = FIELD_GET(MT_EE_WIFI_CONF_STREAM_NUM,247eeprom[MT_EE_WIFI_CONF + 2 + band]);248}249250if (!is_mt798x(&dev->mt76))251nss_max = 2;252}253254if (!nss)255nss = nss_max;256nss = min_t(u8, min_t(u8, nss_max, nss), path);257258mphy->chainmask = BIT(path) - 1;259if (band)260mphy->chainmask <<= dev->chainshift;261mphy->antenna_mask = BIT(nss) - 1;262dev->chainmask |= mphy->chainmask;263dev->chainshift = hweight8(dev->mphy.chainmask);264}265266int mt7915_eeprom_init(struct mt7915_dev *dev)267{268int ret;269270ret = mt7915_eeprom_load(dev);271if (ret < 0) {272if (ret != -EINVAL)273return ret;274275dev_warn(dev->mt76.dev, "eeprom load fail, use default bin\n");276ret = mt7915_eeprom_load_default(dev);277if (ret)278return ret;279}280281mt7915_eeprom_load_precal(dev);282mt7915_eeprom_parse_hw_cap(dev, &dev->phy);283#if defined(__linux__)284memcpy(dev->mphy.macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR,285#elif defined(__FreeBSD__)286memcpy(dev->mphy.macaddr, (u8 *)dev->mt76.eeprom.data + MT_EE_MAC_ADDR,287#endif288ETH_ALEN);289290mt76_eeprom_override(&dev->mphy);291292return 0;293}294295int mt7915_eeprom_get_target_power(struct mt7915_dev *dev,296struct ieee80211_channel *chan,297u8 chain_idx)298{299u8 *eeprom = dev->mt76.eeprom.data;300int index, target_power;301bool tssi_on, is_7976;302303if (chain_idx > 3)304return -EINVAL;305306tssi_on = mt7915_tssi_enabled(dev, chan->band);307is_7976 = mt7915_check_adie(dev, false) || is_mt7916(&dev->mt76);308309if (chan->band == NL80211_BAND_2GHZ) {310if (is_7976) {311index = MT_EE_TX0_POWER_2G_V2 + chain_idx;312target_power = eeprom[index];313} else {314index = MT_EE_TX0_POWER_2G + chain_idx * 3;315target_power = eeprom[index];316317if (!tssi_on)318target_power += eeprom[index + 1];319}320} else if (chan->band == NL80211_BAND_5GHZ) {321int group = mt7915_get_channel_group_5g(chan->hw_value, is_7976);322323if (is_7976) {324index = MT_EE_TX0_POWER_5G_V2 + chain_idx * 5;325target_power = eeprom[index + group];326} else {327index = MT_EE_TX0_POWER_5G + chain_idx * 12;328target_power = eeprom[index + group];329330if (!tssi_on)331target_power += eeprom[index + 8];332}333} else {334int group = mt7915_get_channel_group_6g(chan->hw_value);335336index = MT_EE_TX0_POWER_6G_V2 + chain_idx * 8;337target_power = is_7976 ? eeprom[index + group] : 0;338}339340return target_power;341}342343s8 mt7915_eeprom_get_power_delta(struct mt7915_dev *dev, int band)344{345u8 *eeprom = dev->mt76.eeprom.data;346u32 val, offs;347s8 delta;348bool is_7976 = mt7915_check_adie(dev, false) || is_mt7916(&dev->mt76);349350if (band == NL80211_BAND_2GHZ)351offs = is_7976 ? MT_EE_RATE_DELTA_2G_V2 : MT_EE_RATE_DELTA_2G;352else if (band == NL80211_BAND_5GHZ)353offs = is_7976 ? MT_EE_RATE_DELTA_5G_V2 : MT_EE_RATE_DELTA_5G;354else355offs = is_7976 ? MT_EE_RATE_DELTA_6G_V2 : 0;356357val = eeprom[offs];358359if (!offs || !(val & MT_EE_RATE_DELTA_EN))360return 0;361362delta = FIELD_GET(MT_EE_RATE_DELTA_MASK, val);363364return val & MT_EE_RATE_DELTA_SIGN ? delta : -delta;365}366367bool368mt7915_eeprom_has_background_radar(struct mt7915_dev *dev)369{370u8 val, buf[MT7915_EEPROM_BLOCK_SIZE];371u8 band_sel, tx_path, rx_path;372int offs = MT_EE_WIFI_CONF + 1;373374switch (mt76_chip(&dev->mt76)) {375case 0x7915:376return true;377case 0x7906:378/* read efuse to check background radar capability */379if (mt7915_mcu_get_eeprom(dev, offs, buf))380break;381382val = buf[offs % MT7915_EEPROM_BLOCK_SIZE];383band_sel = u8_get_bits(val, MT_EE_WIFI_CONF0_BAND_SEL);384tx_path = u8_get_bits(val, MT_EE_WIFI_CONF0_TX_PATH);385rx_path = u8_get_bits(val, MT_EE_WIFI_CONF0_RX_PATH);386387return (band_sel == MT_EE_V2_BAND_SEL_5GHZ &&388tx_path == rx_path && rx_path == 2);389case 0x7981:390case 0x7986:391default:392break;393}394395return false;396}397398const u8 mt7915_sku_group_len[] = {399[SKU_CCK] = 4,400[SKU_OFDM] = 8,401[SKU_HT_BW20] = 8,402[SKU_HT_BW40] = 9,403[SKU_VHT_BW20] = 12,404[SKU_VHT_BW40] = 12,405[SKU_VHT_BW80] = 12,406[SKU_VHT_BW160] = 12,407[SKU_HE_RU26] = 12,408[SKU_HE_RU52] = 12,409[SKU_HE_RU106] = 12,410[SKU_HE_RU242] = 12,411[SKU_HE_RU484] = 12,412[SKU_HE_RU996] = 12,413[SKU_HE_RU2x996] = 12414};415416417