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

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

DEFINITIONS

This source file includes following definitions.
  1. mt7603_efuse_read
  2. mt7603_efuse_init
  3. mt7603_has_cal_free_data
  4. mt7603_apply_cal_free_data
  5. mt7603_eeprom_load
  6. mt7603_check_eeprom
  7. mt7603_eeprom_init

   1 // SPDX-License-Identifier: ISC
   2 
   3 #include "mt7603.h"
   4 #include "eeprom.h"
   5 
   6 static int
   7 mt7603_efuse_read(struct mt7603_dev *dev, u32 base, u16 addr, u8 *data)
   8 {
   9         u32 val;
  10         int i;
  11 
  12         val = mt76_rr(dev, base + MT_EFUSE_CTRL);
  13         val &= ~(MT_EFUSE_CTRL_AIN |
  14                  MT_EFUSE_CTRL_MODE);
  15         val |= FIELD_PREP(MT_EFUSE_CTRL_AIN, addr & ~0xf);
  16         val |= MT_EFUSE_CTRL_KICK;
  17         mt76_wr(dev, base + MT_EFUSE_CTRL, val);
  18 
  19         if (!mt76_poll(dev, base + MT_EFUSE_CTRL, MT_EFUSE_CTRL_KICK, 0, 1000))
  20                 return -ETIMEDOUT;
  21 
  22         udelay(2);
  23 
  24         val = mt76_rr(dev, base + MT_EFUSE_CTRL);
  25         if ((val & MT_EFUSE_CTRL_AOUT) == MT_EFUSE_CTRL_AOUT ||
  26             WARN_ON_ONCE(!(val & MT_EFUSE_CTRL_VALID))) {
  27                 memset(data, 0xff, 16);
  28                 return 0;
  29         }
  30 
  31         for (i = 0; i < 4; i++) {
  32                 val = mt76_rr(dev, base + MT_EFUSE_RDATA(i));
  33                 put_unaligned_le32(val, data + 4 * i);
  34         }
  35 
  36         return 0;
  37 }
  38 
  39 static int
  40 mt7603_efuse_init(struct mt7603_dev *dev)
  41 {
  42         u32 base = mt7603_reg_map(dev, MT_EFUSE_BASE);
  43         int len = MT7603_EEPROM_SIZE;
  44         void *buf;
  45         int ret, i;
  46 
  47         if (mt76_rr(dev, base + MT_EFUSE_BASE_CTRL) & MT_EFUSE_BASE_CTRL_EMPTY)
  48                 return 0;
  49 
  50         dev->mt76.otp.data = devm_kzalloc(dev->mt76.dev, len, GFP_KERNEL);
  51         dev->mt76.otp.size = len;
  52         if (!dev->mt76.otp.data)
  53                 return -ENOMEM;
  54 
  55         buf = dev->mt76.otp.data;
  56         for (i = 0; i + 16 <= len; i += 16) {
  57                 ret = mt7603_efuse_read(dev, base, i, buf + i);
  58                 if (ret)
  59                         return ret;
  60         }
  61 
  62         return 0;
  63 }
  64 
  65 static bool
  66 mt7603_has_cal_free_data(struct mt7603_dev *dev, u8 *efuse)
  67 {
  68         if (!efuse[MT_EE_TEMP_SENSOR_CAL])
  69                 return false;
  70 
  71         if (get_unaligned_le16(efuse + MT_EE_TX_POWER_0_START_2G) == 0)
  72                 return false;
  73 
  74         if (get_unaligned_le16(efuse + MT_EE_TX_POWER_1_START_2G) == 0)
  75                 return false;
  76 
  77         if (!efuse[MT_EE_CP_FT_VERSION])
  78                 return false;
  79 
  80         if (!efuse[MT_EE_XTAL_FREQ_OFFSET])
  81                 return false;
  82 
  83         if (!efuse[MT_EE_XTAL_WF_RFCAL])
  84                 return false;
  85 
  86         return true;
  87 }
  88 
  89 static void
  90 mt7603_apply_cal_free_data(struct mt7603_dev *dev, u8 *efuse)
  91 {
  92         static const u8 cal_free_bytes[] = {
  93                 MT_EE_TEMP_SENSOR_CAL,
  94                 MT_EE_CP_FT_VERSION,
  95                 MT_EE_XTAL_FREQ_OFFSET,
  96                 MT_EE_XTAL_WF_RFCAL,
  97                 /* Skip for MT7628 */
  98                 MT_EE_TX_POWER_0_START_2G,
  99                 MT_EE_TX_POWER_0_START_2G + 1,
 100                 MT_EE_TX_POWER_1_START_2G,
 101                 MT_EE_TX_POWER_1_START_2G + 1,
 102         };
 103         u8 *eeprom = dev->mt76.eeprom.data;
 104         int n = ARRAY_SIZE(cal_free_bytes);
 105         int i;
 106 
 107         if (!mt7603_has_cal_free_data(dev, efuse))
 108                 return;
 109 
 110         if (is_mt7628(dev))
 111                 n -= 4;
 112 
 113         for (i = 0; i < n; i++) {
 114                 int offset = cal_free_bytes[i];
 115 
 116                 eeprom[offset] = efuse[offset];
 117         }
 118 }
 119 
 120 static int
 121 mt7603_eeprom_load(struct mt7603_dev *dev)
 122 {
 123         int ret;
 124 
 125         ret = mt76_eeprom_init(&dev->mt76, MT7603_EEPROM_SIZE);
 126         if (ret < 0)
 127                 return ret;
 128 
 129         return mt7603_efuse_init(dev);
 130 }
 131 
 132 static int mt7603_check_eeprom(struct mt76_dev *dev)
 133 {
 134         u16 val = get_unaligned_le16(dev->eeprom.data);
 135 
 136         switch (val) {
 137         case 0x7628:
 138         case 0x7603:
 139                 return 0;
 140         default:
 141                 return -EINVAL;
 142         }
 143 }
 144 
 145 int mt7603_eeprom_init(struct mt7603_dev *dev)
 146 {
 147         int ret;
 148 
 149         ret = mt7603_eeprom_load(dev);
 150         if (ret < 0)
 151                 return ret;
 152 
 153         if (dev->mt76.otp.data) {
 154                 if (mt7603_check_eeprom(&dev->mt76) == 0)
 155                         mt7603_apply_cal_free_data(dev, dev->mt76.otp.data);
 156                 else
 157                         memcpy(dev->mt76.eeprom.data, dev->mt76.otp.data,
 158                                MT7603_EEPROM_SIZE);
 159         }
 160 
 161         dev->mt76.cap.has_2ghz = true;
 162         memcpy(dev->mt76.macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR,
 163                ETH_ALEN);
 164 
 165         mt76_eeprom_override(&dev->mt76);
 166 
 167         return 0;
 168 }

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