281 lines · c
1// SPDX-License-Identifier: ISC2/*3 * Copyright (C) 2022 MediaTek Inc.4 */5 6#include <linux/firmware.h>7#include "mt7996.h"8#include "eeprom.h"9 10static int mt7996_check_eeprom(struct mt7996_dev *dev)11{12 u8 *eeprom = dev->mt76.eeprom.data;13 u16 val = get_unaligned_le16(eeprom);14 15 switch (val) {16 case 0x7990:17 return is_mt7996(&dev->mt76) ? 0 : -EINVAL;18 case 0x7992:19 return is_mt7992(&dev->mt76) ? 0 : -EINVAL;20 default:21 return -EINVAL;22 }23}24 25static char *mt7996_eeprom_name(struct mt7996_dev *dev)26{27 switch (mt76_chip(&dev->mt76)) {28 case 0x7990:29 return MT7996_EEPROM_DEFAULT;30 case 0x7992:31 return MT7992_EEPROM_DEFAULT;32 default:33 return MT7996_EEPROM_DEFAULT;34 }35}36 37static int38mt7996_eeprom_load_default(struct mt7996_dev *dev)39{40 u8 *eeprom = dev->mt76.eeprom.data;41 const struct firmware *fw = NULL;42 int ret;43 44 ret = request_firmware(&fw, mt7996_eeprom_name(dev), dev->mt76.dev);45 if (ret)46 return ret;47 48 if (!fw || !fw->data) {49 dev_err(dev->mt76.dev, "Invalid default bin\n");50 ret = -EINVAL;51 goto out;52 }53 54 memcpy(eeprom, fw->data, MT7996_EEPROM_SIZE);55 dev->flash_mode = true;56 57out:58 release_firmware(fw);59 60 return ret;61}62 63static int mt7996_eeprom_load(struct mt7996_dev *dev)64{65 int ret;66 67 ret = mt76_eeprom_init(&dev->mt76, MT7996_EEPROM_SIZE);68 if (ret < 0)69 return ret;70 71 if (ret) {72 dev->flash_mode = true;73 } else {74 u8 free_block_num;75 u32 block_num, i;76 u32 eeprom_blk_size = MT7996_EEPROM_BLOCK_SIZE;77 78 ret = mt7996_mcu_get_eeprom_free_block(dev, &free_block_num);79 if (ret < 0)80 return ret;81 82 /* efuse info isn't enough */83 if (free_block_num >= 59)84 return -EINVAL;85 86 /* read eeprom data from efuse */87 block_num = DIV_ROUND_UP(MT7996_EEPROM_SIZE, eeprom_blk_size);88 for (i = 0; i < block_num; i++) {89 ret = mt7996_mcu_get_eeprom(dev, i * eeprom_blk_size);90 if (ret < 0)91 return ret;92 }93 }94 95 return mt7996_check_eeprom(dev);96}97 98static int mt7996_eeprom_parse_efuse_hw_cap(struct mt7996_dev *dev)99{100#define MODE_HE_ONLY BIT(0)101#define WTBL_SIZE_GROUP GENMASK(31, 28)102 u32 cap = 0;103 int ret;104 105 ret = mt7996_mcu_get_chip_config(dev, &cap);106 if (ret)107 return ret;108 109 if (cap) {110 dev->has_eht = !(cap & MODE_HE_ONLY);111 dev->wtbl_size_group = u32_get_bits(cap, WTBL_SIZE_GROUP);112 }113 114 if (dev->wtbl_size_group < 2 || dev->wtbl_size_group > 4 ||115 is_mt7992(&dev->mt76))116 dev->wtbl_size_group = 2; /* set default */117 118 return 0;119}120 121static int mt7996_eeprom_parse_band_config(struct mt7996_phy *phy)122{123 u8 *eeprom = phy->dev->mt76.eeprom.data;124 u32 val = eeprom[MT_EE_WIFI_CONF];125 int ret = 0;126 127 switch (phy->mt76->band_idx) {128 case MT_BAND1:129 val = FIELD_GET(MT_EE_WIFI_CONF1_BAND_SEL, val);130 break;131 case MT_BAND2:132 val = eeprom[MT_EE_WIFI_CONF + 1];133 val = FIELD_GET(MT_EE_WIFI_CONF2_BAND_SEL, val);134 break;135 default:136 val = FIELD_GET(MT_EE_WIFI_CONF0_BAND_SEL, val);137 break;138 }139 140 switch (val) {141 case MT_EE_BAND_SEL_2GHZ:142 phy->mt76->cap.has_2ghz = true;143 break;144 case MT_EE_BAND_SEL_5GHZ:145 phy->mt76->cap.has_5ghz = true;146 break;147 case MT_EE_BAND_SEL_6GHZ:148 phy->mt76->cap.has_6ghz = true;149 break;150 default:151 ret = -EINVAL;152 break;153 }154 155 return ret;156}157 158int mt7996_eeprom_parse_hw_cap(struct mt7996_dev *dev, struct mt7996_phy *phy)159{160 u8 path, rx_path, nss, band_idx = phy->mt76->band_idx;161 u8 *eeprom = dev->mt76.eeprom.data;162 struct mt76_phy *mphy = phy->mt76;163 int max_path = 5, max_nss = 4;164 int ret;165 166 switch (band_idx) {167 case MT_BAND1:168 path = FIELD_GET(MT_EE_WIFI_CONF2_TX_PATH_BAND1,169 eeprom[MT_EE_WIFI_CONF + 2]);170 rx_path = FIELD_GET(MT_EE_WIFI_CONF3_RX_PATH_BAND1,171 eeprom[MT_EE_WIFI_CONF + 3]);172 nss = FIELD_GET(MT_EE_WIFI_CONF5_STREAM_NUM_BAND1,173 eeprom[MT_EE_WIFI_CONF + 5]);174 break;175 case MT_BAND2:176 path = FIELD_GET(MT_EE_WIFI_CONF2_TX_PATH_BAND2,177 eeprom[MT_EE_WIFI_CONF + 2]);178 rx_path = FIELD_GET(MT_EE_WIFI_CONF4_RX_PATH_BAND2,179 eeprom[MT_EE_WIFI_CONF + 4]);180 nss = FIELD_GET(MT_EE_WIFI_CONF5_STREAM_NUM_BAND2,181 eeprom[MT_EE_WIFI_CONF + 5]);182 break;183 default:184 path = FIELD_GET(MT_EE_WIFI_CONF1_TX_PATH_BAND0,185 eeprom[MT_EE_WIFI_CONF + 1]);186 rx_path = FIELD_GET(MT_EE_WIFI_CONF3_RX_PATH_BAND0,187 eeprom[MT_EE_WIFI_CONF + 3]);188 nss = FIELD_GET(MT_EE_WIFI_CONF4_STREAM_NUM_BAND0,189 eeprom[MT_EE_WIFI_CONF + 4]);190 break;191 }192 193 if (!path || path > max_path)194 path = max_path;195 196 if (!nss || nss > max_nss)197 nss = max_nss;198 199 nss = min_t(u8, nss, path);200 201 if (path != rx_path)202 phy->has_aux_rx = true;203 204 mphy->antenna_mask = BIT(nss) - 1;205 mphy->chainmask = (BIT(path) - 1) << dev->chainshift[band_idx];206 dev->chainmask |= mphy->chainmask;207 if (band_idx < MT_BAND2)208 dev->chainshift[band_idx + 1] = dev->chainshift[band_idx] +209 hweight16(mphy->chainmask);210 211 ret = mt7996_eeprom_parse_efuse_hw_cap(dev);212 if (ret)213 return ret;214 215 return mt7996_eeprom_parse_band_config(phy);216}217 218int mt7996_eeprom_init(struct mt7996_dev *dev)219{220 int ret;221 222 ret = mt7996_eeprom_load(dev);223 if (ret < 0) {224 if (ret != -EINVAL)225 return ret;226 227 dev_warn(dev->mt76.dev, "eeprom load fail, use default bin\n");228 ret = mt7996_eeprom_load_default(dev);229 if (ret)230 return ret;231 }232 233 ret = mt7996_eeprom_parse_hw_cap(dev, &dev->phy);234 if (ret < 0)235 return ret;236 237 memcpy(dev->mphy.macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR, ETH_ALEN);238 mt76_eeprom_override(&dev->mphy);239 240 return 0;241}242 243int mt7996_eeprom_get_target_power(struct mt7996_dev *dev,244 struct ieee80211_channel *chan)245{246 u8 *eeprom = dev->mt76.eeprom.data;247 int target_power;248 249 if (chan->band == NL80211_BAND_5GHZ)250 target_power = eeprom[MT_EE_TX0_POWER_5G +251 mt7996_get_channel_group_5g(chan->hw_value)];252 else if (chan->band == NL80211_BAND_6GHZ)253 target_power = eeprom[MT_EE_TX0_POWER_6G +254 mt7996_get_channel_group_6g(chan->hw_value)];255 else256 target_power = eeprom[MT_EE_TX0_POWER_2G];257 258 return target_power;259}260 261s8 mt7996_eeprom_get_power_delta(struct mt7996_dev *dev, int band)262{263 u8 *eeprom = dev->mt76.eeprom.data;264 u32 val;265 s8 delta;266 267 if (band == NL80211_BAND_5GHZ)268 val = eeprom[MT_EE_RATE_DELTA_5G];269 else if (band == NL80211_BAND_6GHZ)270 val = eeprom[MT_EE_RATE_DELTA_6G];271 else272 val = eeprom[MT_EE_RATE_DELTA_2G];273 274 if (!(val & MT_EE_RATE_DELTA_EN))275 return 0;276 277 delta = FIELD_GET(MT_EE_RATE_DELTA_MASK, val);278 279 return val & MT_EE_RATE_DELTA_SIGN ? delta : -delta;280}281