linux/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c
<<
>>
Prefs
   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);
 354