1 // SPDX-License-Identifier: ISC 2 /* Copyright (C) 2020 MediaTek Inc. */ 3 4 #include "mt7915.h" 5 #include "eeprom.h" 6 7 static u32 mt7915_eeprom_read(struct mt7915_dev *dev, u32 offset) 8 { 9 u8 *data = dev->mt76.eeprom.data; 10 11 if (data[offset] == 0xff) 12 mt7915_mcu_get_eeprom(dev, offset); 13 14 return data[offset]; 15 } 16 17 static int mt7915_eeprom_load(struct mt7915_dev *dev) 18 { 19 int ret; 20 21 ret = mt76_eeprom_init(&dev->mt76, MT7915_EEPROM_SIZE); 22 if (ret < 0) 23 return ret; 24 25 if (ret) 26 dev->flash_mode = true; 27 else 28 memset(dev->mt76.eeprom.data, -1, MT7915_EEPROM_SIZE); 29 30 return 0; 31 } 32 33 static int mt7915_check_eeprom(struct mt7915_dev *dev) 34 { 35 u8 *eeprom = dev->mt76.eeprom.data; 36 u16 val; 37 38 mt7915_eeprom_read(dev, MT_EE_CHIP_ID); 39 val = get_unaligned_le16(eeprom); 40 41 switch (val) { 42 case 0x7915: 43 return 0; 44 default: 45 return -EINVAL; 46 } 47 } 48 49 void mt7915_eeprom_parse_band_config(struct mt7915_phy *phy) 50 { 51 struct mt7915_dev *dev = phy->dev; 52 bool ext_phy = phy != &dev->phy; 53 u32 val; 54 55 val = mt7915_eeprom_read(dev, MT_EE_WIFI_CONF + ext_phy); 56 val = FIELD_GET(MT_EE_WIFI_CONF0_BAND_SEL, val); 57 if (val == MT_EE_BAND_SEL_DEFAULT && dev->dbdc_support) 58 val = ext_phy ? MT_EE_BAND_SEL_5GHZ : MT_EE_BAND_SEL_2GHZ; 59 60 switch (val) { 61 case MT_EE_BAND_SEL_5GHZ: 62 phy->mt76->cap.has_5ghz = true; 63 break; 64 case MT_EE_BAND_SEL_2GHZ: 65 phy->mt76->cap.has_2ghz = true; 66 break; 67 default: 68 phy->mt76->cap.has_2ghz = true; 69 phy->mt76->cap.has_5ghz = true; 70 break; 71 } 72 } 73 74 static void mt7915_eeprom_parse_hw_cap(struct mt7915_dev *dev) 75 { 76 u8 nss, nss_band, *eeprom = dev->mt76.eeprom.data; 77 78 mt7915_eeprom_parse_band_config(&dev->phy); 79 80 /* read tx mask from eeprom */ 81 nss = FIELD_GET(MT_EE_WIFI_CONF0_TX_PATH, eeprom[MT_EE_WIFI_CONF]); 82 if (!nss || nss > 4) 83 nss = 4; 84 85 nss_band = nss; 86 87 if (dev->dbdc_support) { 88 nss_band = FIELD_GET(MT_EE_WIFI_CONF3_TX_PATH_B0, 89 eeprom[MT_EE_WIFI_CONF + 3]); 90 if (!nss_band || nss_band > 2) 91 nss_band = 2; 92 93 if (nss_band >= nss) 94 nss = 4; 95 } 96 97 dev->chainmask = BIT(nss) - 1; 98 dev->mphy.antenna_mask = BIT(nss_band) - 1; 99 dev->mphy.chainmask = dev->mphy.antenna_mask; 100 } 101 102 int mt7915_eeprom_init(struct mt7915_dev *dev) 103 { 104 int ret; 105 106 ret = mt7915_eeprom_load(dev); 107 if (ret < 0) 108 return ret; 109 110 ret = mt7915_check_eeprom(dev); 111 if (ret) 112 return ret; 113 114 mt7915_eeprom_parse_hw_cap(dev); 115 memcpy(dev->mphy.macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR, 116 ETH_ALEN); 117 118 mt76_eeprom_override(&dev->mphy); 119 120 return 0; 121 } 122 123 int mt7915_eeprom_get_target_power(struct mt7915_dev *dev, 124 struct ieee80211_channel *chan, 125 u8 chain_idx) 126 { 127 int index; 128 bool tssi_on; 129 130 if (chain_idx > 3) 131 return -EINVAL; 132 133 tssi_on = mt7915_tssi_enabled(dev, chan->band); 134 135 if (chan->band == NL80211_BAND_2GHZ) { 136 index = MT_EE_TX0_POWER_2G + chain_idx * 3 + !tssi_on; 137 } else { 138 int group = tssi_on ? 139 mt7915_get_channel_group(chan->hw_value) : 8; 140 141 index = MT_EE_TX0_POWER_5G + chain_idx * 12 + group; 142 } 143 144 return mt7915_eeprom_read(dev, index); 145 } 146 147 static const u8 sku_cck_delta_map[] = { 148 SKU_CCK_GROUP0, 149 SKU_CCK_GROUP0, 150 SKU_CCK_GROUP1, 151 SKU_CCK_GROUP1, 152 }; 153 154 static const u8 sku_ofdm_delta_map[] = { 155 SKU_OFDM_GROUP0, 156 SKU_OFDM_GROUP0, 157 SKU_OFDM_GROUP1, 158 SKU_OFDM_GROUP1, 159 SKU_OFDM_GROUP2, 160 SKU_OFDM_GROUP2, 161 SKU_OFDM_GROUP3, 162 SKU_OFDM_GROUP4, 163 }; 164 165 static const u8 sku_mcs_delta_map[] = { 166 SKU_MCS_GROUP0, 167 SKU_MCS_GROUP1, 168 SKU_MCS_GROUP1, 169 SKU_MCS_GROUP2, 170 SKU_MCS_GROUP2, 171 SKU_MCS_GROUP3, 172 SKU_MCS_GROUP4, 173 SKU_MCS_GROUP5, 174 SKU_MCS_GROUP6, 175 SKU_MCS_GROUP7, 176 SKU_MCS_GROUP8, 177 SKU_MCS_GROUP9, 178 }; 179 180 #define SKU_GROUP(_mode, _len, _ofs_2g, _ofs_5g, _map) \ 181 [_mode] = { \ 182 .len = _len, \ 183 .offset = { \ 184 _ofs_2g, \ 185 _ofs_5g, \ 186 }, \ 187 .delta_map = _map \ 188 } 189 190 const struct sku_group mt7915_sku_groups[] = { 191 SKU_GROUP(SKU_CCK, 4, 0x252, 0, sku_cck_delta_map), 192 SKU_GROUP(SKU_OFDM, 8, 0x254, 0x29d, sku_ofdm_delta_map), 193 194 SKU_GROUP(SKU_HT_BW20, 8, 0x259, 0x2a2, sku_mcs_delta_map), 195 SKU_GROUP(SKU_HT_BW40, 9, 0x262, 0x2ab, sku_mcs_delta_map), 196 SKU_GROUP(SKU_VHT_BW20, 12, 0x259, 0x2a2, sku_mcs_delta_map), 197 SKU_GROUP(SKU_VHT_BW40, 12, 0x262, 0x2ab, sku_mcs_delta_map), 198 SKU_GROUP(SKU_VHT_BW80, 12, 0, 0x2b4, sku_mcs_delta_map), 199 SKU_GROUP(SKU_VHT_BW160, 12, 0, 0, sku_mcs_delta_map), 200 201 SKU_GROUP(SKU_HE_RU26, 12, 0x27f, 0x2dd, sku_mcs_delta_map), 202 SKU_GROUP(SKU_HE_RU52, 12, 0x289, 0x2e7, sku_mcs_delta_map), 203 SKU_GROUP(SKU_HE_RU106, 12, 0x293, 0x2f1, sku_mcs_delta_map), 204 SKU_GROUP(SKU_HE_RU242, 12, 0x26b, 0x2bf, sku_mcs_delta_map), 205 SKU_GROUP(SKU_HE_RU484, 12, 0x275, 0x2c9, sku_mcs_delta_map), 206 SKU_GROUP(SKU_HE_RU996, 12, 0, 0x2d3, sku_mcs_delta_map), 207 SKU_GROUP(SKU_HE_RU2x996, 12, 0, 0, sku_mcs_delta_map), 208 }; 209 210 static s8 211 mt7915_get_sku_delta(struct mt7915_dev *dev, u32 addr) 212 { 213 u32 val = mt7915_eeprom_read(dev, addr); 214 s8 delta = FIELD_GET(SKU_DELTA_VAL, val); 215 216 if (!(val & SKU_DELTA_EN)) 217 return 0; 218 219 return val & SKU_DELTA_ADD ? delta : -delta; 220 } 221 222 static void 223 mt7915_eeprom_init_sku_band(struct mt7915_dev *dev, 224 struct ieee80211_supported_band *sband) 225 { 226 int i, band = sband->band; 227 s8 *rate_power = dev->rate_power[band], max_delta = 0; 228 u8 idx = 0; 229 230 for (i = 0; i < ARRAY_SIZE(mt7915_sku_groups); i++) { 231 const struct sku_group *sku = &mt7915_sku_groups[i]; 232 u32 offset = sku->offset[band]; 233 int j; 234 235 if (!offset) { 236 idx += sku->len; 237 continue; 238 } 239 240 rate_power[idx++] = mt7915_get_sku_delta(dev, offset); 241 if (rate_power[idx - 1] > max_delta) 242 max_delta = rate_power[idx - 1]; 243 244 if (i == SKU_HT_BW20 || i == SKU_VHT_BW20) 245 offset += 1; 246 247 for (j = 1; j < sku->len; j++) { 248 u32 addr = offset + sku->delta_map[j]; 249 250 rate_power[idx++] = mt7915_get_sku_delta(dev, addr); 251 if (rate_power[idx - 1] > max_delta) 252 max_delta = rate_power[idx - 1]; 253 } 254 } 255 256 rate_power[idx] = max_delta; 257 } 258 259 void mt7915_eeprom_init_sku(struct mt7915_dev *dev) 260 { 261 mt7915_eeprom_init_sku_band(dev, &dev->mphy.sband_2g.sband); 262 mt7915_eeprom_init_sku_band(dev, &dev->mphy.sband_5g.sband); 263 } 264