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 int mt7615_eeprom_init(struct mt7615_dev *dev) 158 { 159 int ret; 160 161 ret = mt7615_eeprom_load(dev); 162 if (ret < 0) 163 return ret; 164 165 ret = mt7615_check_eeprom(&dev->mt76); 166 if (ret && dev->mt76.otp.data) 167 memcpy(dev->mt76.eeprom.data, dev->mt76.otp.data, 168 MT7615_EEPROM_SIZE); 169 170 mt7615_eeprom_parse_hw_cap(dev); 171 memcpy(dev->mt76.macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR, 172 ETH_ALEN); 173 174 mt76_eeprom_override(&dev->mt76); 175 176 return 0; 177 } 178