linux/drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.c
<<
>>
Prefs
   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
  14static int
  15mt76x2_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
  23static bool
  24mt76x2_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
  49static void
  50mt76x2_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
 123static 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
 140static int
 141mt76x2_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
 175out:
 176        if (!found)
 177                return -ENOENT;
 178
 179        return 0;
 180}
 181
 182static void
 183mt76x2_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
 197static void
 198mt76x2_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
 210static enum mt76x2_cal_channel_group
 211mt76x2_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
 226static u8
 227mt76x2_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
 254void 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}
 281EXPORT_SYMBOL_GPL(mt76x2_read_rx_gain);
 282
 283void 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}
 344EXPORT_SYMBOL_GPL(mt76x2_get_rate_power);
 345
 346static void
 347mt76x2_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
 376static void
 377mt76x2_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
 428void 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}
 459EXPORT_SYMBOL_GPL(mt76x2_get_power_info);
 460
 461int 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}
 493EXPORT_SYMBOL_GPL(mt76x2_get_temp_comp);
 494
 495int 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}
 510EXPORT_SYMBOL_GPL(mt76x2_eeprom_init);
 511
 512MODULE_LICENSE("Dual BSD/GPL");
 513