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 <linux/of.h> 9 #include "mt7615.h" 10 #include "eeprom.h" 11 12 static int mt7615_efuse_read(struct mt7615_dev *dev, u32 base, 13 u16 addr, u8 *data) 14 { 15 u32 val; 16 int i; 17 18 val = mt76_rr(dev, base + MT_EFUSE_CTRL); 19 val &= ~(MT_EFUSE_CTRL_AIN | MT_EFUSE_CTRL_MODE); 20 val |= FIELD_PREP(MT_EFUSE_CTRL_AIN, addr & ~0xf); 21 val |= MT_EFUSE_CTRL_KICK; 22 mt76_wr(dev, base + MT_EFUSE_CTRL, val); 23 24 if (!mt76_poll(dev, base + MT_EFUSE_CTRL, MT_EFUSE_CTRL_KICK, 0, 1000)) 25 return -ETIMEDOUT; 26 27 udelay(2); 28 29 val = mt76_rr(dev, base + MT_EFUSE_CTRL); 30 if ((val & MT_EFUSE_CTRL_AOUT) == MT_EFUSE_CTRL_AOUT || 31 WARN_ON_ONCE(!(val & MT_EFUSE_CTRL_VALID))) { 32 memset(data, 0x0, 16); 33 return 0; 34 } 35 36 for (i = 0; i < 4; i++) { 37 val = mt76_rr(dev, base + MT_EFUSE_RDATA(i)); 38 put_unaligned_le32(val, data + 4 * i); 39 } 40 41 return 0; 42 } 43 44 static int mt7615_efuse_init(struct mt7615_dev *dev, u32 base) 45 { 46 int i, len = MT7615_EEPROM_SIZE; 47 void *buf; 48 u32 val; 49 50 val = mt76_rr(dev, base + MT_EFUSE_BASE_CTRL); 51 if (val & MT_EFUSE_BASE_CTRL_EMPTY) 52 return 0; 53 54 dev->mt76.otp.data = devm_kzalloc(dev->mt76.dev, len, GFP_KERNEL); 55 dev->mt76.otp.size = len; 56 if (!dev->mt76.otp.data) 57 return -ENOMEM; 58 59 buf = dev->mt76.otp.data; 60 for (i = 0; i + 16 <= len; i += 16) { 61 int ret; 62 63 ret = mt7615_efuse_read(dev, base, i, buf + i); 64 if (ret) 65 return ret; 66 } 67 68 return 0; 69 } 70 71 static int mt7615_eeprom_load(struct mt7615_dev *dev, u32 addr) 72 { 73 int ret; 74 75 ret = mt76_eeprom_init(&dev->mt76, MT7615_EEPROM_FULL_SIZE); 76 if (ret < 0) 77 return ret; 78 79 return mt7615_efuse_init(dev, addr); 80 } 81 82 static int mt7615_check_eeprom(struct mt76_dev *dev) 83 { 84 u16 val = get_unaligned_le16(dev->eeprom.data); 85 86 switch (val) { 87 case 0x7615: 88 case 0x7622: 89 return 0; 90 default: 91 return -EINVAL; 92 } 93 } 94 95 static void 96 mt7615_eeprom_parse_hw_band_cap(struct mt7615_dev *dev) 97 { 98 u8 val, *eeprom = dev->mt76.eeprom.data; 99 100 if (is_mt7663(&dev->mt76)) { 101 /* dual band */ 102 dev->mphy.cap.has_2ghz = true; 103 dev->mphy.cap.has_5ghz = true; 104 return; 105 } 106 107 if (is_mt7622(&dev->mt76)) { 108 /* 2GHz only */ 109 dev->mphy.cap.has_2ghz = true; 110 return; 111 } 112 113 if (is_mt7611(&dev->mt76)) { 114 /* 5GHz only */ 115 dev->mphy.cap.has_5ghz = true; 116 return; 117 } 118 119 val = FIELD_GET(MT_EE_NIC_WIFI_CONF_BAND_SEL, 120 eeprom[MT_EE_WIFI_CONF]); 121 switch (val) { 122 case MT_EE_5GHZ: 123 dev->mphy.cap.has_5ghz = true; 124 break; 125 case MT_EE_2GHZ: 126 dev->mphy.cap.has_2ghz = true; 127 break; 128 case MT_EE_DBDC: 129 dev->dbdc_support = true; 130 fallthrough; 131 default: 132 dev->mphy.cap.has_2ghz = true; 133 dev->mphy.cap.has_5ghz = true; 134 break; 135 } 136 } 137 138 static void mt7615_eeprom_parse_hw_cap(struct mt7615_dev *dev) 139 { 140 u8 *eeprom = dev->mt76.eeprom.data; 141 u8 tx_mask, max_nss; 142 143 mt7615_eeprom_parse_hw_band_cap(dev); 144 145 if (is_mt7663(&dev->mt76)) { 146 max_nss = 2; 147 tx_mask = FIELD_GET(MT_EE_HW_CONF1_TX_MASK, 148 eeprom[MT7663_EE_HW_CONF1]); 149 } else { 150 u32 val; 151 152 /* read tx-rx mask from eeprom */ 153 val = mt76_rr(dev, MT_TOP_STRAP_STA); 154 max_nss = val & MT_TOP_3NSS ? 3 : 4; 155 156 tx_mask = FIELD_GET(MT_EE_NIC_CONF_TX_MASK, 157 eeprom[MT_EE_NIC_CONF_0]); 158 } 159 if (!tx_mask || tx_mask > max_nss) 160 tx_mask = max_nss; 161 162 dev->chainmask = BIT(tx_mask) - 1; 163 dev->mphy.antenna_mask = dev->chainmask; 164 dev->mphy.chainmask = dev->chainmask; 165 } 166 167 static int mt7663_eeprom_get_target_power_index(struct mt7615_dev *dev, 168 struct ieee80211_channel *chan, 169 u8 chain_idx) 170 { 171 int index, group; 172 173 if (chain_idx > 1) 174 return -EINVAL; 175 176 if (chan->band == NL80211_BAND_2GHZ) 177 return MT7663_EE_TX0_2G_TARGET_POWER + (chain_idx << 4); 178 179 group = mt7615_get_channel_group(chan->hw_value); 180 if (chain_idx == 1) 181 index = MT7663_EE_TX1_5G_G0_TARGET_POWER; 182 else 183 index = MT7663_EE_TX0_5G_G0_TARGET_POWER; 184 185 return index + group * 3; 186 } 187 188 int mt7615_eeprom_get_target_power_index(struct mt7615_dev *dev, 189 struct ieee80211_channel *chan, 190 u8 chain_idx) 191 { 192 int index; 193 194 if (is_mt7663(&dev->mt76)) 195 return mt7663_eeprom_get_target_power_index(dev, chan, 196 chain_idx); 197 198 if (chain_idx > 3) 199 return -EINVAL; 200 201 /* TSSI disabled */ 202 if (mt7615_ext_pa_enabled(dev, chan->band)) { 203 if (chan->band == NL80211_BAND_2GHZ) 204 return MT_EE_EXT_PA_2G_TARGET_POWER; 205 else 206 return MT_EE_EXT_PA_5G_TARGET_POWER; 207 } 208 209 /* TSSI enabled */ 210 if (chan->band == NL80211_BAND_2GHZ) { 211 index = MT_EE_TX0_2G_TARGET_POWER + chain_idx * 6; 212 } else { 213 int group = mt7615_get_channel_group(chan->hw_value); 214 215 switch (chain_idx) { 216 case 1: 217 index = MT_EE_TX1_5G_G0_TARGET_POWER; 218 break; 219 case 2: 220 index = MT_EE_TX2_5G_G0_TARGET_POWER; 221 break; 222 case 3: 223 index = MT_EE_TX3_5G_G0_TARGET_POWER; 224 break; 225 case 0: 226 default: 227 index = MT_EE_TX0_5G_G0_TARGET_POWER; 228 break; 229 } 230 index += 5 * group; 231 } 232 233 return index; 234 } 235 236 int mt7615_eeprom_get_power_delta_index(struct mt7615_dev *dev, 237 enum nl80211_band band) 238 { 239 /* assume the first rate has the highest power offset */ 240 if (is_mt7663(&dev->mt76)) { 241 if (band == NL80211_BAND_2GHZ) 242 return MT_EE_TX0_5G_G0_TARGET_POWER; 243 else 244 return MT7663_EE_5G_RATE_POWER; 245 } 246 247 if (band == NL80211_BAND_2GHZ) 248 return MT_EE_2G_RATE_POWER; 249 else 250 return MT_EE_5G_RATE_POWER; 251 } 252 253 static void mt7615_apply_cal_free_data(struct mt7615_dev *dev) 254 { 255 static const u16 ical[] = { 256 0x53, 0x54, 0x55, 0x56, 0x57, 0x5c, 0x5d, 0x62, 0x63, 0x68, 257 0x69, 0x6e, 0x6f, 0x73, 0x74, 0x78, 0x79, 0x82, 0x83, 0x87, 258 0x88, 0x8c, 0x8d, 0x91, 0x92, 0x96, 0x97, 0x9b, 0x9c, 0xa0, 259 0xa1, 0xaa, 0xab, 0xaf, 0xb0, 0xb4, 0xb5, 0xb9, 0xba, 0xf4, 260 0xf7, 0xff, 261 0x140, 0x141, 0x145, 0x146, 0x14a, 0x14b, 0x154, 0x155, 0x159, 262 0x15a, 0x15e, 0x15f, 0x163, 0x164, 0x168, 0x169, 0x16d, 0x16e, 263 0x172, 0x173, 0x17c, 0x17d, 0x181, 0x182, 0x186, 0x187, 0x18b, 264 0x18c 265 }; 266 static const u16 ical_nocheck[] = { 267 0x110, 0x111, 0x112, 0x113, 0x114, 0x115, 0x116, 0x117, 0x118, 268 0x1b5, 0x1b6, 0x1b7, 0x3ac, 0x3ad, 0x3ae, 0x3af, 0x3b0, 0x3b1, 269 0x3b2 270 }; 271 u8 *eeprom = dev->mt76.eeprom.data; 272 u8 *otp = dev->mt76.otp.data; 273 int i; 274 275 if (!otp) 276 return; 277 278 for (i = 0; i < ARRAY_SIZE(ical); i++) 279 if (!otp[ical[i]]) 280 return; 281 282 for (i = 0; i < ARRAY_SIZE(ical); i++) 283 eeprom[ical[i]] = otp[ical[i]]; 284 285 for (i = 0; i < ARRAY_SIZE(ical_nocheck); i++) 286 eeprom[ical_nocheck[i]] = otp[ical_nocheck[i]]; 287 } 288 289 static void mt7622_apply_cal_free_data(struct mt7615_dev *dev) 290 { 291 static const u16 ical[] = { 292 0x53, 0x54, 0x55, 0x56, 0xf4, 0xf7, 0x144, 0x156, 0x15b 293 }; 294 u8 *eeprom = dev->mt76.eeprom.data; 295 u8 *otp = dev->mt76.otp.data; 296 int i; 297 298 if (!otp) 299 return; 300 301 for (i = 0; i < ARRAY_SIZE(ical); i++) { 302 if (!otp[ical[i]]) 303 continue; 304 305 eeprom[ical[i]] = otp[ical[i]]; 306 } 307 } 308 309 static void mt7615_cal_free_data(struct mt7615_dev *dev) 310 { 311 struct device_node *np = dev->mt76.dev->of_node; 312 313 if (!np || !of_property_read_bool(np, "mediatek,eeprom-merge-otp")) 314 return; 315 316 switch (mt76_chip(&dev->mt76)) { 317 case 0x7622: 318 mt7622_apply_cal_free_data(dev); 319 break; 320 case 0x7615: 321 case 0x7611: 322 mt7615_apply_cal_free_data(dev); 323 break; 324 } 325 } 326 327 int mt7615_eeprom_init(struct mt7615_dev *dev, u32 addr) 328 { 329 int ret; 330 331 ret = mt7615_eeprom_load(dev, addr); 332 if (ret < 0) 333 return ret; 334 335 ret = mt7615_check_eeprom(&dev->mt76); 336 if (ret && dev->mt76.otp.data) { 337 memcpy(dev->mt76.eeprom.data, dev->mt76.otp.data, 338 MT7615_EEPROM_SIZE); 339 } else { 340 dev->flash_eeprom = true; 341 mt7615_cal_free_data(dev); 342 } 343 344 mt7615_eeprom_parse_hw_cap(dev); 345 memcpy(dev->mphy.macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR, 346 ETH_ALEN); 347 348 mt76_eeprom_override(&dev->mphy); 349 350 return 0; 351 } 352 EXPORT_SYMBOL_GPL(mt7615_eeprom_init); 353