root/drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mt76x2_eeprom_get_macaddr
  2. mt76x2_has_cal_free_data
  3. mt76x2_apply_cal_free_data
  4. mt76x2_check_eeprom
  5. mt76x2_eeprom_load
  6. mt76x2_set_rx_gain_group
  7. mt76x2_set_rssi_offset
  8. mt76x2_get_cal_channel_group
  9. mt76x2_get_5g_rx_gain
  10. mt76x2_read_rx_gain
  11. mt76x2_get_rate_power
  12. mt76x2_get_power_info_2g
  13. mt76x2_get_power_info_5g
  14. mt76x2_get_power_info
  15. mt76x2_get_temp_comp
  16. mt76x2_eeprom_init

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

/* [<][>][^][v][top][bottom][index][help] */