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 return 0; 88 default: 89 return -EINVAL; 90 } 91 } 92 93 static void mt7615_eeprom_parse_hw_cap(struct mt7615_dev *dev) 94 { 95 u8 val, *eeprom = dev->mt76.eeprom.data; 96 97 val = FIELD_GET(MT_EE_NIC_WIFI_CONF_BAND_SEL, 98 eeprom[MT_EE_WIFI_CONF]); 99 switch (val) { 100 case MT_EE_5GHZ: 101 dev->mt76.cap.has_5ghz = true; 102 break; 103 case MT_EE_2GHZ: 104 dev->mt76.cap.has_2ghz = true; 105 break; 106 default: 107 dev->mt76.cap.has_2ghz = true; 108 dev->mt76.cap.has_5ghz = true; 109 break; 110 } 111 } 112 113 int mt7615_eeprom_get_power_index(struct mt7615_dev *dev, 114 struct ieee80211_channel *chan, 115 u8 chain_idx) 116 { 117 int index; 118 119 if (chain_idx > 3) 120 return -EINVAL; 121 122 /* TSSI disabled */ 123 if (mt7615_ext_pa_enabled(dev, chan->band)) { 124 if (chan->band == NL80211_BAND_2GHZ) 125 return MT_EE_EXT_PA_2G_TARGET_POWER; 126 else 127 return MT_EE_EXT_PA_5G_TARGET_POWER; 128 } 129 130 /* TSSI enabled */ 131 if (chan->band == NL80211_BAND_2GHZ) { 132 index = MT_EE_TX0_2G_TARGET_POWER + chain_idx * 6; 133 } else { 134 int group = mt7615_get_channel_group(chan->hw_value); 135 136 switch (chain_idx) { 137 case 1: 138 index = MT_EE_TX1_5G_G0_TARGET_POWER; 139 break; 140 case 2: 141 index = MT_EE_TX2_5G_G0_TARGET_POWER; 142 break; 143 case 3: 144 index = MT_EE_TX3_5G_G0_TARGET_POWER; 145 break; 146 case 0: 147 default: 148 index = MT_EE_TX0_5G_G0_TARGET_POWER; 149 break; 150 } 151 index += 5 * group; 152 } 153 154 return index; 155 } 156 157 static void mt7615_apply_cal_free_data(struct mt7615_dev *dev) 158 { 159 static const u16 ical[] = { 160 0x53, 0x54, 0x55, 0x56, 0x57, 0x5c, 0x5d, 0x62, 0x63, 0x68, 161 0x69, 0x6e, 0x6f, 0x73, 0x74, 0x78, 0x79, 0x82, 0x83, 0x87, 162 0x88, 0x8c, 0x8d, 0x91, 0x92, 0x96, 0x97, 0x9b, 0x9c, 0xa0, 163 0xa1, 0xaa, 0xab, 0xaf, 0xb0, 0xb4, 0xb5, 0xb9, 0xba, 0xf4, 164 0xf7, 0xff, 165 0x140, 0x141, 0x145, 0x146, 0x14a, 0x14b, 0x154, 0x155, 0x159, 166 0x15a, 0x15e, 0x15f, 0x163, 0x164, 0x168, 0x169, 0x16d, 0x16e, 167 0x172, 0x173, 0x17c, 0x17d, 0x181, 0x182, 0x186, 0x187, 0x18b, 168 0x18c 169 }; 170 static const u16 ical_nocheck[] = { 171 0x110, 0x111, 0x112, 0x113, 0x114, 0x115, 0x116, 0x117, 0x118, 172 0x1b5, 0x1b6, 0x1b7, 0x3ac, 0x3ad, 0x3ae, 0x3af, 0x3b0, 0x3b1, 173 0x3b2 174 }; 175 u8 *eeprom = dev->mt76.eeprom.data; 176 u8 *otp = dev->mt76.otp.data; 177 int i; 178 179 if (!otp) 180 return; 181 182 for (i = 0; i < ARRAY_SIZE(ical); i++) 183 if (!otp[ical[i]]) 184 return; 185 186 for (i = 0; i < ARRAY_SIZE(ical); i++) 187 eeprom[ical[i]] = otp[ical[i]]; 188 189 for (i = 0; i < ARRAY_SIZE(ical_nocheck); i++) 190 eeprom[ical_nocheck[i]] = otp[ical_nocheck[i]]; 191 } 192 193 int mt7615_eeprom_init(struct mt7615_dev *dev) 194 { 195 int ret; 196 197 ret = mt7615_eeprom_load(dev); 198 if (ret < 0) 199 return ret; 200 201 ret = mt7615_check_eeprom(&dev->mt76); 202 if (ret && dev->mt76.otp.data) 203 memcpy(dev->mt76.eeprom.data, dev->mt76.otp.data, 204 MT7615_EEPROM_SIZE); 205 else 206 mt7615_apply_cal_free_data(dev); 207 208 mt7615_eeprom_parse_hw_cap(dev); 209 memcpy(dev->mt76.macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR, 210 ETH_ALEN); 211 212 mt76_eeprom_override(&dev->mt76); 213 214 return 0; 215 } 216