1 // SPDX-License-Identifier: ISC 2 /* Copyright (C) 2019 MediaTek Inc. 3 * 4 * Author: Ryder Lee <ryder.lee@mediatek.com> 5 * Felix Fietkau <nbd@nbd.name> 6 */ 7 8 #include "mt7615.h" 9 #include "eeprom.h" 10 11 static int mt7615_efuse_read(struct mt7615_dev *dev, u32 base, 12 u16 addr, u8 *data) 13 { 14 u32 val; 15 int i; 16 17 val = mt76_rr(dev, base + MT_EFUSE_CTRL); 18 val &= ~(MT_EFUSE_CTRL_AIN | MT_EFUSE_CTRL_MODE); 19 val |= FIELD_PREP(MT_EFUSE_CTRL_AIN, addr & ~0xf); 20 val |= MT_EFUSE_CTRL_KICK; 21 mt76_wr(dev, base + MT_EFUSE_CTRL, val); 22 23 if (!mt76_poll(dev, base + MT_EFUSE_CTRL, MT_EFUSE_CTRL_KICK, 0, 1000)) 24 return -ETIMEDOUT; 25 26 udelay(2); 27 28 val = mt76_rr(dev, base + MT_EFUSE_CTRL); 29 if ((val & MT_EFUSE_CTRL_AOUT) == MT_EFUSE_CTRL_AOUT || 30 WARN_ON_ONCE(!(val & MT_EFUSE_CTRL_VALID))) { 31 memset(data, 0x0, 16); 32 return 0; 33 } 34 35 for (i = 0; i < 4; i++) { 36 val = mt76_rr(dev, base + MT_EFUSE_RDATA(i)); 37 put_unaligned_le32(val, data + 4 * i); 38 } 39 40 return 0; 41 } 42 43 static int mt7615_efuse_init(struct mt7615_dev *dev) 44 { 45 u32 val, base = mt7615_reg_map(dev, MT_EFUSE_BASE); 46 int i, len = MT7615_EEPROM_SIZE; 47 void *buf; 48 49 val = mt76_rr(dev, base + MT_EFUSE_BASE_CTRL); 50 if (val & MT_EFUSE_BASE_CTRL_EMPTY) 51 return 0; 52 53 dev->mt76.otp.data = devm_kzalloc(dev->mt76.dev, len, GFP_KERNEL); 54 dev->mt76.otp.size = len; 55 if (!dev->mt76.otp.data) 56 return -ENOMEM; 57 58 buf = dev->mt76.otp.data; 59 for (i = 0; i + 16 <= len; i += 16) { 60 int ret; 61 62 ret = mt7615_efuse_read(dev, base, i, buf + i); 63 if (ret) 64 return ret; 65 } 66 67 return 0; 68 } 69 70 static int mt7615_eeprom_load(struct mt7615_dev *dev) 71 { 72 int ret; 73 74 ret = mt76_eeprom_init(&dev->mt76, MT7615_EEPROM_SIZE); 75 if (ret < 0) 76 return ret; 77 78 return mt7615_efuse_init(dev); 79 } 80 81 static int mt7615_check_eeprom(struct mt76_dev *dev) 82 { 83 u16 val = get_unaligned_le16(dev->eeprom.data); 84 85 switch (val) { 86 case 0x7615: 87 case 0x7622: 88 return 0; 89 default: 90 return -EINVAL; 91 } 92 } 93 94 static void mt7615_eeprom_parse_hw_cap(struct mt7615_dev *dev) 95 { 96 u8 *eeprom = dev->mt76.eeprom.data; 97 u8 tx_mask, max_nss; 98 u32 val; 99 100 val = FIELD_GET(MT_EE_NIC_WIFI_CONF_BAND_SEL, 101 eeprom[MT_EE_WIFI_CONF]); 102 switch (val) { 103 case MT_EE_5GHZ: 104 dev->mt76.cap.has_5ghz = true; 105 break; 106 case MT_EE_2GHZ: 107 dev->mt76.cap.has_2ghz = true; 108 break; 109 default: 110 dev->mt76.cap.has_2ghz = true; 111 dev->mt76.cap.has_5ghz = true; 112 break; 113 } 114 115 if (is_mt7622(&dev->mt76)) 116 dev->mt76.cap.has_5ghz = false; 117 118 /* read tx-rx mask from eeprom */ 119 val = mt76_rr(dev, MT_TOP_STRAP_STA); 120 max_nss = val & MT_TOP_3NSS ? 3 : 4; 121 122 tx_mask = FIELD_GET(MT_EE_NIC_CONF_TX_MASK, 123 eeprom[MT_EE_NIC_CONF_0]); 124 if (!tx_mask || tx_mask > max_nss) 125 tx_mask = max_nss; 126 127 dev->chainmask = BIT(tx_mask) - 1; 128 dev->mphy.antenna_mask = dev->chainmask; 129 dev->phy.chainmask = dev->chainmask; 130 } 131 132 int mt7615_eeprom_get_power_index(struct mt7615_dev *dev, 133 struct ieee80211_channel *chan, 134 u8 chain_idx) 135 { 136 int index; 137 138 if (chain_idx > 3) 139 return -EINVAL; 140 141 /* TSSI disabled */ 142 if (mt7615_ext_pa_enabled(dev, chan->band)) { 143 if (chan->band == NL80211_BAND_2GHZ) 144 return MT_EE_EXT_PA_2G_TARGET_POWER; 145 else 146 return MT_EE_EXT_PA_5G_TARGET_POWER; 147 } 148 149 /* TSSI enabled */ 150 if (chan->band == NL80211_BAND_2GHZ) { 151 index = MT_EE_TX0_2G_TARGET_POWER + chain_idx * 6; 152 } else { 153 int group = mt7615_get_channel_group(chan->hw_value); 154 155 switch (chain_idx) { 156 case 1: 157 index = MT_EE_TX1_5G_G0_TARGET_POWER; 158 break; 159 case 2: 160 index = MT_EE_TX2_5G_G0_TARGET_POWER; 161 break; 162 case 3: 163 index = MT_EE_TX3_5G_G0_TARGET_POWER; 164 break; 165 case 0: 166 default: 167 index = MT_EE_TX0_5G_G0_TARGET_POWER; 168 break; 169 } 170 index += 5 * group; 171 } 172 173 return index; 174 } 175 176 static void mt7615_apply_cal_free_data(struct mt7615_dev *dev) 177 { 178 static const u16 ical[] = { 179 0x53, 0x54, 0x55, 0x56, 0x57, 0x5c, 0x5d, 0x62, 0x63, 0x68, 180 0x69, 0x6e, 0x6f, 0x73, 0x74, 0x78, 0x79, 0x82, 0x83, 0x87, 181 0x88, 0x8c, 0x8d, 0x91, 0x92, 0x96, 0x97, 0x9b, 0x9c, 0xa0, 182 0xa1, 0xaa, 0xab, 0xaf, 0xb0, 0xb4, 0xb5, 0xb9, 0xba, 0xf4, 183 0xf7, 0xff, 184 0x140, 0x141, 0x145, 0x146, 0x14a, 0x14b, 0x154, 0x155, 0x159, 185 0x15a, 0x15e, 0x15f, 0x163, 0x164, 0x168, 0x169, 0x16d, 0x16e, 186 0x172, 0x173, 0x17c, 0x17d, 0x181, 0x182, 0x186, 0x187, 0x18b, 187 0x18c 188 }; 189 static const u16 ical_nocheck[] = { 190 0x110, 0x111, 0x112, 0x113, 0x114, 0x115, 0x116, 0x117, 0x118, 191 0x1b5, 0x1b6, 0x1b7, 0x3ac, 0x3ad, 0x3ae, 0x3af, 0x3b0, 0x3b1, 192 0x3b2 193 }; 194 u8 *eeprom = dev->mt76.eeprom.data; 195 u8 *otp = dev->mt76.otp.data; 196 int i; 197 198 if (!otp) 199 return; 200 201 for (i = 0; i < ARRAY_SIZE(ical); i++) 202 if (!otp[ical[i]]) 203 return; 204 205 for (i = 0; i < ARRAY_SIZE(ical); i++) 206 eeprom[ical[i]] = otp[ical[i]]; 207 208 for (i = 0; i < ARRAY_SIZE(ical_nocheck); i++) 209 eeprom[ical_nocheck[i]] = otp[ical_nocheck[i]]; 210 } 211 212 static void mt7622_apply_cal_free_data(struct mt7615_dev *dev) 213 { 214 static const u16 ical[] = { 215 0x53, 0x54, 0x55, 0x56, 0xf4, 0xf7, 0x144, 0x156, 0x15b 216 }; 217 u8 *eeprom = dev->mt76.eeprom.data; 218 u8 *otp = dev->mt76.otp.data; 219 int i; 220 221 if (!otp) 222 return; 223 224 for (i = 0; i < ARRAY_SIZE(ical); i++) { 225 if (!otp[ical[i]]) 226 continue; 227 228 eeprom[ical[i]] = otp[ical[i]]; 229 } 230 } 231 232 int mt7615_eeprom_init(struct mt7615_dev *dev) 233 { 234 int ret; 235 236 ret = mt7615_eeprom_load(dev); 237 if (ret < 0) 238 return ret; 239 240 ret = mt7615_check_eeprom(&dev->mt76); 241 if (ret && dev->mt76.otp.data) 242 memcpy(dev->mt76.eeprom.data, dev->mt76.otp.data, 243 MT7615_EEPROM_SIZE); 244 else if (is_mt7622(&dev->mt76)) 245 mt7622_apply_cal_free_data(dev); 246 else 247 mt7615_apply_cal_free_data(dev); 248 249 mt7615_eeprom_parse_hw_cap(dev); 250 memcpy(dev->mt76.macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR, 251 ETH_ALEN); 252 253 mt76_eeprom_override(&dev->mt76); 254 255 return 0; 256 } 257