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