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