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