1 // SPDX-License-Identifier: ISC 2 /* 3 * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> 4 */ 5 6 #include <linux/module.h> 7 #include <linux/of.h> 8 #include <asm/unaligned.h> 9 #include "mt76x2.h" 10 #include "eeprom.h" 11 12 #define EE_FIELD(_name, _value) [MT_EE_##_name] = (_value) | 1 13 14 static int 15 mt76x2_eeprom_get_macaddr(struct mt76x02_dev *dev) 16 { 17 void *src = dev->mt76.eeprom.data + MT_EE_MAC_ADDR; 18 19 memcpy(dev->mphy.macaddr, src, ETH_ALEN); 20 return 0; 21 } 22 23 static bool 24 mt76x2_has_cal_free_data(struct mt76x02_dev *dev, u8 *efuse) 25 { 26 u16 *efuse_w = (u16 *)efuse; 27 28 if (efuse_w[MT_EE_NIC_CONF_0] != 0) 29 return false; 30 31 if (efuse_w[MT_EE_XTAL_TRIM_1] == 0xffff) 32 return false; 33 34 if (efuse_w[MT_EE_TX_POWER_DELTA_BW40] != 0) 35 return false; 36 37 if (efuse_w[MT_EE_TX_POWER_0_START_2G] == 0xffff) 38 return false; 39 40 if (efuse_w[MT_EE_TX_POWER_0_GRP3_TX_POWER_DELTA] != 0) 41 return false; 42 43 if (efuse_w[MT_EE_TX_POWER_0_GRP4_TSSI_SLOPE] == 0xffff) 44 return false; 45 46 return true; 47 } 48 49 static void 50 mt76x2_apply_cal_free_data(struct mt76x02_dev *dev, u8 *efuse) 51 { 52 #define GROUP_5G(_id) \ 53 MT_EE_TX_POWER_0_START_5G + MT_TX_POWER_GROUP_SIZE_5G * (_id), \ 54 MT_EE_TX_POWER_0_START_5G + MT_TX_POWER_GROUP_SIZE_5G * (_id) + 1, \ 55 MT_EE_TX_POWER_1_START_5G + MT_TX_POWER_GROUP_SIZE_5G * (_id), \ 56 MT_EE_TX_POWER_1_START_5G + MT_TX_POWER_GROUP_SIZE_5G * (_id) + 1 57 58 static const u8 cal_free_bytes[] = { 59 MT_EE_XTAL_TRIM_1, 60 MT_EE_TX_POWER_EXT_PA_5G + 1, 61 MT_EE_TX_POWER_0_START_2G, 62 MT_EE_TX_POWER_0_START_2G + 1, 63 MT_EE_TX_POWER_1_START_2G, 64 MT_EE_TX_POWER_1_START_2G + 1, 65 GROUP_5G(0), 66 GROUP_5G(1), 67 GROUP_5G(2), 68 GROUP_5G(3), 69 GROUP_5G(4), 70 GROUP_5G(5), 71 MT_EE_RF_2G_TSSI_OFF_TXPOWER, 72 MT_EE_RF_2G_RX_HIGH_GAIN + 1, 73 MT_EE_RF_5G_GRP0_1_RX_HIGH_GAIN, 74 MT_EE_RF_5G_GRP0_1_RX_HIGH_GAIN + 1, 75 MT_EE_RF_5G_GRP2_3_RX_HIGH_GAIN, 76 MT_EE_RF_5G_GRP2_3_RX_HIGH_GAIN + 1, 77 MT_EE_RF_5G_GRP4_5_RX_HIGH_GAIN, 78 MT_EE_RF_5G_GRP4_5_RX_HIGH_GAIN + 1, 79 }; 80 struct device_node *np = dev->mt76.dev->of_node; 81 u8 *eeprom = dev->mt76.eeprom.data; 82 u8 prev_grp0[4] = { 83 eeprom[MT_EE_TX_POWER_0_START_5G], 84 eeprom[MT_EE_TX_POWER_0_START_5G + 1], 85 eeprom[MT_EE_TX_POWER_1_START_5G], 86 eeprom[MT_EE_TX_POWER_1_START_5G + 1] 87 }; 88 u16 val; 89 int i; 90 91 if (!np || !of_property_read_bool(np, "mediatek,eeprom-merge-otp")) 92 return; 93 94 if (!mt76x2_has_cal_free_data(dev, efuse)) 95 return; 96 97 for (i = 0; i < ARRAY_SIZE(cal_free_bytes); i++) { 98 int offset = cal_free_bytes[i]; 99 100 eeprom[offset] = efuse[offset]; 101 } 102 103 if (!(efuse[MT_EE_TX_POWER_0_START_5G] | 104 efuse[MT_EE_TX_POWER_0_START_5G + 1])) 105 memcpy(eeprom + MT_EE_TX_POWER_0_START_5G, prev_grp0, 2); 106 if (!(efuse[MT_EE_TX_POWER_1_START_5G] | 107 efuse[MT_EE_TX_POWER_1_START_5G + 1])) 108 memcpy(eeprom + MT_EE_TX_POWER_1_START_5G, prev_grp0 + 2, 2); 109 110 val = get_unaligned_le16(efuse + MT_EE_BT_RCAL_RESULT); 111 if (val != 0xffff) 112 eeprom[MT_EE_BT_RCAL_RESULT] = val & 0xff; 113 114 val = get_unaligned_le16(efuse + MT_EE_BT_VCDL_CALIBRATION); 115 if (val != 0xffff) 116 eeprom[MT_EE_BT_VCDL_CALIBRATION + 1] = val >> 8; 117 118 val = get_unaligned_le16(efuse + MT_EE_BT_PMUCFG); 119 if (val != 0xffff) 120 eeprom[MT_EE_BT_PMUCFG] = val & 0xff; 121 } 122 123 static int mt76x2_check_eeprom(struct mt76x02_dev *dev) 124 { 125 u16 val = get_unaligned_le16(dev->mt76.eeprom.data); 126 127 if (!val) 128 val = get_unaligned_le16(dev->mt76.eeprom.data + MT_EE_PCI_ID); 129 130 switch (val) { 131 case 0x7662: 132 case 0x7612: 133 return 0; 134 default: 135 dev_err(dev->mt76.dev, "EEPROM data check failed: %04x\n", val); 136 return -EINVAL; 137 } 138 } 139 140 static int 141 mt76x2_eeprom_load(struct mt76x02_dev *dev) 142 { 143 void *efuse; 144 bool found; 145 int ret; 146 147 ret = mt76_eeprom_init(&dev->mt76, MT7662_EEPROM_SIZE); 148 if (ret < 0) 149 return ret; 150 151 found = ret; 152 if (found) 153 found = !mt76x2_check_eeprom(dev); 154 155 dev->mt76.otp.data = devm_kzalloc(dev->mt76.dev, MT7662_EEPROM_SIZE, 156 GFP_KERNEL); 157 dev->mt76.otp.size = MT7662_EEPROM_SIZE; 158 if (!dev->mt76.otp.data) 159 return -ENOMEM; 160 161 efuse = dev->mt76.otp.data; 162 163 if (mt76x02_get_efuse_data(dev, 0, efuse, MT7662_EEPROM_SIZE, 164 MT_EE_READ)) 165 goto out; 166 167 if (found) { 168 mt76x2_apply_cal_free_data(dev, efuse); 169 } else { 170 /* FIXME: check if efuse data is complete */ 171 found = true; 172 memcpy(dev->mt76.eeprom.data, efuse, MT7662_EEPROM_SIZE); 173 } 174 175 out: 176 if (!found) 177 return -ENOENT; 178 179 return 0; 180 } 181 182 static void 183 mt76x2_set_rx_gain_group(struct mt76x02_dev *dev, u8 val) 184 { 185 s8 *dest = dev->cal.rx.high_gain; 186 187 if (!mt76x02_field_valid(val)) { 188 dest[0] = 0; 189 dest[1] = 0; 190 return; 191 } 192 193 dest[0] = mt76x02_sign_extend(val, 4); 194 dest[1] = mt76x02_sign_extend(val >> 4, 4); 195 } 196 197 static void 198 mt76x2_set_rssi_offset(struct mt76x02_dev *dev, int chain, u8 val) 199 { 200 s8 *dest = dev->cal.rx.rssi_offset; 201 202 if (!mt76x02_field_valid(val)) { 203 dest[chain] = 0; 204 return; 205 } 206 207 dest[chain] = mt76x02_sign_extend_optional(val, 7); 208 } 209 210 static enum mt76x2_cal_channel_group 211 mt76x2_get_cal_channel_group(int channel) 212 { 213 if (channel >= 184 && channel <= 196) 214 return MT_CH_5G_JAPAN; 215 if (channel <= 48) 216 return MT_CH_5G_UNII_1; 217 if (channel <= 64) 218 return MT_CH_5G_UNII_2; 219 if (channel <= 114) 220 return MT_CH_5G_UNII_2E_1; 221 if (channel <= 144) 222 return MT_CH_5G_UNII_2E_2; 223 return MT_CH_5G_UNII_3; 224 } 225 226 static u8 227 mt76x2_get_5g_rx_gain(struct mt76x02_dev *dev, u8 channel) 228 { 229 enum mt76x2_cal_channel_group group; 230 231 group = mt76x2_get_cal_channel_group(channel); 232 switch (group) { 233 case MT_CH_5G_JAPAN: 234 return mt76x02_eeprom_get(dev, 235 MT_EE_RF_5G_GRP0_1_RX_HIGH_GAIN); 236 case MT_CH_5G_UNII_1: 237 return mt76x02_eeprom_get(dev, 238 MT_EE_RF_5G_GRP0_1_RX_HIGH_GAIN) >> 8; 239 case MT_CH_5G_UNII_2: 240 return mt76x02_eeprom_get(dev, 241 MT_EE_RF_5G_GRP2_3_RX_HIGH_GAIN); 242 case MT_CH_5G_UNII_2E_1: 243 return mt76x02_eeprom_get(dev, 244 MT_EE_RF_5G_GRP2_3_RX_HIGH_GAIN) >> 8; 245 case MT_CH_5G_UNII_2E_2: 246 return mt76x02_eeprom_get(dev, 247 MT_EE_RF_5G_GRP4_5_RX_HIGH_GAIN); 248 default: 249 return mt76x02_eeprom_get(dev, 250 MT_EE_RF_5G_GRP4_5_RX_HIGH_GAIN) >> 8; 251 } 252 } 253 254 void mt76x2_read_rx_gain(struct mt76x02_dev *dev) 255 { 256 struct ieee80211_channel *chan = dev->mphy.chandef.chan; 257 int channel = chan->hw_value; 258 s8 lna_5g[3], lna_2g; 259 u8 lna; 260 u16 val; 261 262 if (chan->band == NL80211_BAND_2GHZ) 263 val = mt76x02_eeprom_get(dev, MT_EE_RF_2G_RX_HIGH_GAIN) >> 8; 264 else 265 val = mt76x2_get_5g_rx_gain(dev, channel); 266 267 mt76x2_set_rx_gain_group(dev, val); 268 269 mt76x02_get_rx_gain(dev, chan->band, &val, &lna_2g, lna_5g); 270 mt76x2_set_rssi_offset(dev, 0, val); 271 mt76x2_set_rssi_offset(dev, 1, val >> 8); 272 273 dev->cal.rx.mcu_gain = (lna_2g & 0xff); 274 dev->cal.rx.mcu_gain |= (lna_5g[0] & 0xff) << 8; 275 dev->cal.rx.mcu_gain |= (lna_5g[1] & 0xff) << 16; 276 dev->cal.rx.mcu_gain |= (lna_5g[2] & 0xff) << 24; 277 278 lna = mt76x02_get_lna_gain(dev, &lna_2g, lna_5g, chan); 279 dev->cal.rx.lna_gain = mt76x02_sign_extend(lna, 8); 280 } 281 EXPORT_SYMBOL_GPL(mt76x2_read_rx_gain); 282 283 void mt76x2_get_rate_power(struct mt76x02_dev *dev, struct mt76_rate_power *t, 284 struct ieee80211_channel *chan) 285 { 286 bool is_5ghz; 287 u16 val; 288 289 is_5ghz = chan->band == NL80211_BAND_5GHZ; 290 291 memset(t, 0, sizeof(*t)); 292 293 val = mt76x02_eeprom_get(dev, MT_EE_TX_POWER_CCK); 294 t->cck[0] = t->cck[1] = mt76x02_rate_power_val(val); 295 t->cck[2] = t->cck[3] = mt76x02_rate_power_val(val >> 8); 296 297 if (is_5ghz) 298 val = mt76x02_eeprom_get(dev, MT_EE_TX_POWER_OFDM_5G_6M); 299 else 300 val = mt76x02_eeprom_get(dev, MT_EE_TX_POWER_OFDM_2G_6M); 301 t->ofdm[0] = t->ofdm[1] = mt76x02_rate_power_val(val); 302 t->ofdm[2] = t->ofdm[3] = mt76x02_rate_power_val(val >> 8); 303 304 if (is_5ghz) 305 val = mt76x02_eeprom_get(dev, MT_EE_TX_POWER_OFDM_5G_24M); 306 else 307 val = mt76x02_eeprom_get(dev, MT_EE_TX_POWER_OFDM_2G_24M); 308 t->ofdm[4] = t->ofdm[5] = mt76x02_rate_power_val(val); 309 t->ofdm[6] = t->ofdm[7] = mt76x02_rate_power_val(val >> 8); 310 311 val = mt76x02_eeprom_get(dev, MT_EE_TX_POWER_HT_MCS0); 312 t->ht[0] = t->ht[1] = mt76x02_rate_power_val(val); 313 t->ht[2] = t->ht[3] = mt76x02_rate_power_val(val >> 8); 314 315 val = mt76x02_eeprom_get(dev, MT_EE_TX_POWER_HT_MCS4); 316 t->ht[4] = t->ht[5] = mt76x02_rate_power_val(val); 317 t->ht[6] = t->ht[7] = mt76x02_rate_power_val(val >> 8); 318 319 val = mt76x02_eeprom_get(dev, MT_EE_TX_POWER_HT_MCS8); 320 t->ht[8] = t->ht[9] = mt76x02_rate_power_val(val); 321 t->ht[10] = t->ht[11] = mt76x02_rate_power_val(val >> 8); 322 323 val = mt76x02_eeprom_get(dev, MT_EE_TX_POWER_HT_MCS12); 324 t->ht[12] = t->ht[13] = mt76x02_rate_power_val(val); 325 t->ht[14] = t->ht[15] = mt76x02_rate_power_val(val >> 8); 326 327 val = mt76x02_eeprom_get(dev, MT_EE_TX_POWER_VHT_MCS0); 328 t->vht[0] = t->vht[1] = mt76x02_rate_power_val(val); 329 t->vht[2] = t->vht[3] = mt76x02_rate_power_val(val >> 8); 330 331 val = mt76x02_eeprom_get(dev, MT_EE_TX_POWER_VHT_MCS4); 332 t->vht[4] = t->vht[5] = mt76x02_rate_power_val(val); 333 t->vht[6] = t->vht[7] = mt76x02_rate_power_val(val >> 8); 334 335 val = mt76x02_eeprom_get(dev, MT_EE_TX_POWER_VHT_MCS8); 336 if (!is_5ghz) 337 val >>= 8; 338 t->vht[8] = t->vht[9] = mt76x02_rate_power_val(val >> 8); 339 340 memcpy(t->stbc, t->ht, sizeof(t->stbc[0]) * 8); 341 t->stbc[8] = t->vht[8]; 342 t->stbc[9] = t->vht[9]; 343 } 344 EXPORT_SYMBOL_GPL(mt76x2_get_rate_power); 345 346 static void 347 mt76x2_get_power_info_2g(struct mt76x02_dev *dev, 348 struct mt76x2_tx_power_info *t, 349 struct ieee80211_channel *chan, 350 int chain, int offset) 351 { 352 int channel = chan->hw_value; 353 int delta_idx; 354 u8 data[6]; 355 u16 val; 356 357 if (channel < 6) 358 delta_idx = 3; 359 else if (channel < 11) 360 delta_idx = 4; 361 else 362 delta_idx = 5; 363 364 mt76x02_eeprom_copy(dev, offset, data, sizeof(data)); 365 366 t->chain[chain].tssi_slope = data[0]; 367 t->chain[chain].tssi_offset = data[1]; 368 t->chain[chain].target_power = data[2]; 369 t->chain[chain].delta = 370 mt76x02_sign_extend_optional(data[delta_idx], 7); 371 372 val = mt76x02_eeprom_get(dev, MT_EE_RF_2G_TSSI_OFF_TXPOWER); 373 t->target_power = val >> 8; 374 } 375 376 static void 377 mt76x2_get_power_info_5g(struct mt76x02_dev *dev, 378 struct mt76x2_tx_power_info *t, 379 struct ieee80211_channel *chan, 380 int chain, int offset) 381 { 382 int channel = chan->hw_value; 383 enum mt76x2_cal_channel_group group; 384 int delta_idx; 385 u16 val; 386 u8 data[5]; 387 388 group = mt76x2_get_cal_channel_group(channel); 389 offset += group * MT_TX_POWER_GROUP_SIZE_5G; 390 391 if (channel >= 192) 392 delta_idx = 4; 393 else if (channel >= 184) 394 delta_idx = 3; 395 else if (channel < 44) 396 delta_idx = 3; 397 else if (channel < 52) 398 delta_idx = 4; 399 else if (channel < 58) 400 delta_idx = 3; 401 else if (channel < 98) 402 delta_idx = 4; 403 else if (channel < 106) 404 delta_idx = 3; 405 else if (channel < 116) 406 delta_idx = 4; 407 else if (channel < 130) 408 delta_idx = 3; 409 else if (channel < 149) 410 delta_idx = 4; 411 else if (channel < 157) 412 delta_idx = 3; 413 else 414 delta_idx = 4; 415 416 mt76x02_eeprom_copy(dev, offset, data, sizeof(data)); 417 418 t->chain[chain].tssi_slope = data[0]; 419 t->chain[chain].tssi_offset = data[1]; 420 t->chain[chain].target_power = data[2]; 421 t->chain[chain].delta = 422 mt76x02_sign_extend_optional(data[delta_idx], 7); 423 424 val = mt76x02_eeprom_get(dev, MT_EE_RF_2G_RX_HIGH_GAIN); 425 t->target_power = val & 0xff; 426 } 427 428 void mt76x2_get_power_info(struct mt76x02_dev *dev, 429 struct mt76x2_tx_power_info *t, 430 struct ieee80211_channel *chan) 431 { 432 u16 bw40, bw80; 433 434 memset(t, 0, sizeof(*t)); 435 436 bw40 = mt76x02_eeprom_get(dev, MT_EE_TX_POWER_DELTA_BW40); 437 bw80 = mt76x02_eeprom_get(dev, MT_EE_TX_POWER_DELTA_BW80); 438 439 if (chan->band == NL80211_BAND_5GHZ) { 440 bw40 >>= 8; 441 mt76x2_get_power_info_5g(dev, t, chan, 0, 442 MT_EE_TX_POWER_0_START_5G); 443 mt76x2_get_power_info_5g(dev, t, chan, 1, 444 MT_EE_TX_POWER_1_START_5G); 445 } else { 446 mt76x2_get_power_info_2g(dev, t, chan, 0, 447 MT_EE_TX_POWER_0_START_2G); 448 mt76x2_get_power_info_2g(dev, t, chan, 1, 449 MT_EE_TX_POWER_1_START_2G); 450 } 451 452 if (mt76x2_tssi_enabled(dev) || 453 !mt76x02_field_valid(t->target_power)) 454 t->target_power = t->chain[0].target_power; 455 456 t->delta_bw40 = mt76x02_rate_power_val(bw40); 457 t->delta_bw80 = mt76x02_rate_power_val(bw80); 458 } 459 EXPORT_SYMBOL_GPL(mt76x2_get_power_info); 460 461 int mt76x2_get_temp_comp(struct mt76x02_dev *dev, struct mt76x2_temp_comp *t) 462 { 463 enum nl80211_band band = dev->mphy.chandef.chan->band; 464 u16 val, slope; 465 u8 bounds; 466 467 memset(t, 0, sizeof(*t)); 468 469 if (!mt76x2_temp_tx_alc_enabled(dev)) 470 return -EINVAL; 471 472 if (!mt76x02_ext_pa_enabled(dev, band)) 473 return -EINVAL; 474 475 val = mt76x02_eeprom_get(dev, MT_EE_TX_POWER_EXT_PA_5G) >> 8; 476 t->temp_25_ref = val & 0x7f; 477 if (band == NL80211_BAND_5GHZ) { 478 slope = mt76x02_eeprom_get(dev, MT_EE_RF_TEMP_COMP_SLOPE_5G); 479 bounds = mt76x02_eeprom_get(dev, MT_EE_TX_POWER_EXT_PA_5G); 480 } else { 481 slope = mt76x02_eeprom_get(dev, MT_EE_RF_TEMP_COMP_SLOPE_2G); 482 bounds = mt76x02_eeprom_get(dev, 483 MT_EE_TX_POWER_DELTA_BW80) >> 8; 484 } 485 486 t->high_slope = slope & 0xff; 487 t->low_slope = slope >> 8; 488 t->lower_bound = 0 - (bounds & 0xf); 489 t->upper_bound = (bounds >> 4) & 0xf; 490 491 return 0; 492 } 493 EXPORT_SYMBOL_GPL(mt76x2_get_temp_comp); 494 495 int mt76x2_eeprom_init(struct mt76x02_dev *dev) 496 { 497 int ret; 498 499 ret = mt76x2_eeprom_load(dev); 500 if (ret) 501 return ret; 502 503 mt76x02_eeprom_parse_hw_cap(dev); 504 mt76x2_eeprom_get_macaddr(dev); 505 mt76_eeprom_override(&dev->mphy); 506 dev->mphy.macaddr[0] &= ~BIT(1); 507 508 return 0; 509 } 510 EXPORT_SYMBOL_GPL(mt76x2_eeprom_init); 511 512 MODULE_LICENSE("Dual BSD/GPL"); 513