]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
wifi: mt76: mt7996: apply calibration-free data from OTP
authorStanleyYP Wang <StanleyYP.Wang@mediatek.com>
Thu, 12 Feb 2026 09:03:10 +0000 (17:03 +0800)
committerFelix Fietkau <nbd@nbd.name>
Tue, 24 Mar 2026 15:49:29 +0000 (15:49 +0000)
Before sending the current EEPROM data to the firmware, read the
calibration-free data (FT data) from the efuse and merge it with
the existing EEPROM data.

Co-developed-by: Shayne Chen <shayne.chen@mediatek.com>
Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
Link: https://patch.msgid.link/20260212090310.3335392-3-shayne.chen@mediatek.com
Signed-off-by: Felix Fietkau <nbd@nbd.name>
drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h

index 81c4e0d4654bb65e8510be18cfd49848ddd3a855..27713399c31897bb77731c86974a9c0284d516ba 100644 (file)
@@ -3952,7 +3952,153 @@ int mt7996_mcu_set_chan_info(struct mt7996_phy *phy, u16 tag)
                                 &req, sizeof(req), true);
 }
 
-static int mt7996_mcu_set_eeprom_flash(struct mt7996_dev *dev)
+static int
+mt7996_mcu_get_cal_free_data(struct mt7996_dev *dev)
+{
+#define MT_EE_7977BN_OFFSET    (0x1200 - 0x500)
+       struct cal_free_data {
+               u16 adie_offs;
+               u16 eep_offs;
+       };
+       static const struct cal_free_data cal_7975[] = {
+               { 0x5cd, 0x451 }, { 0x5cf, 0x453 }, { 0x5d1, 0x455 },
+               { 0x5d3, 0x457 }, { 0x6c0, 0x44c }, { 0x6c1, 0x44d },
+               { 0x6c2, 0x44e }, { 0x6c3, 0x44f }, { 0x7a1, 0xba1 },
+               { 0x7a6, 0xba6 }, { 0x7a8, 0xba8 }, { 0x7aa, 0xbaa },
+       };
+       static const struct cal_free_data cal_7976[] = {
+               {  0x4c, 0x44c }, {  0x4d, 0x44d }, {  0x4e, 0x44e },
+               {  0x4f, 0x44f }, {  0x50, 0x450 }, {  0x51, 0x451 },
+               {  0x53, 0x453 }, {  0x55, 0x455 }, {  0x57, 0x457 },
+               {  0x59, 0x459 }, {  0x70, 0x470 }, {  0x71, 0x471 },
+               { 0x790, 0xb90 }, { 0x791, 0xb91 }, { 0x794, 0xb94 },
+               { 0x795, 0xb95 }, { 0x7a6, 0xba6 }, { 0x7a8, 0xba8 },
+               { 0x7aa, 0xbaa },
+       };
+       static const struct cal_free_data cal_7977[] = {
+               { 0x4c, 0x124c }, { 0x4d, 0x124d }, { 0x4e, 0x124e },
+               { 0x4f, 0x124f }, { 0x50, 0x1250 }, { 0x51, 0x1251 },
+               { 0x53, 0x1253 }, { 0x55, 0x1255 }, { 0x57, 0x1257 },
+               { 0x59, 0x1259 }, { 0x69, 0x1269 }, { 0x6a, 0x126a },
+               { 0x7a, 0x127a }, { 0x7b, 0x127b }, { 0x7c, 0x127c },
+               { 0x7d, 0x127d }, { 0x7e, 0x127e },
+       };
+       static const struct cal_free_data cal_7978[] = {
+               {  0x91, 0xb91 }, {  0x95, 0xb95 }, { 0x100, 0x480 },
+               { 0x102, 0x482 }, { 0x104, 0x484 }, { 0x106, 0x486 },
+               { 0x107, 0x487 }, { 0x108, 0x488 }, { 0x109, 0x489 },
+               { 0x10a, 0x48a }, { 0x10b, 0x48b }, { 0x10c, 0x48c },
+               { 0x10e, 0x48e }, { 0x110, 0x490 },
+       };
+       static const struct cal_free_data cal_7979[] = {
+               { 0x4c, 0x124c }, { 0x4d, 0x124d }, { 0x4e, 0x124e },
+               { 0x4f, 0x124f }, { 0x50, 0x1250 }, { 0x51, 0x1251 },
+               { 0x53, 0x1253 }, { 0x55, 0x1255 }, { 0x57, 0x1257 },
+               { 0x59, 0x1259 }, { 0x69, 0x1269 }, { 0x6a, 0x126a },
+               { 0x7a, 0x127a }, { 0x7b, 0x127b }, { 0x7c, 0x127c },
+               { 0x7e, 0x127e }, { 0x80, 0x1280 },
+       };
+       const struct cal_free_data *cal_arr[__MT_MAX_BAND];
+       u16 cal_arr_len[__MT_MAX_BAND] = {};
+       u8 *eeprom = (u8 *)dev->mt76.eeprom.data;
+       int band, i, ret;
+
+#define CAL_ARR(_band, _adie) do {                             \
+               cal_arr[_band] = cal_##_adie;                   \
+               cal_arr_len[_band] = ARRAY_SIZE(cal_##_adie);   \
+       } while (0)
+
+       switch (mt76_chip(&dev->mt76)) {
+       case MT7996_DEVICE_ID:
+               /* adie 0 */
+               if (dev->var.fem == MT7996_FEM_INT &&
+                   dev->var.type != MT7996_VAR_TYPE_233)
+                       CAL_ARR(0, 7975);
+               else
+                       CAL_ARR(0, 7976);
+
+               /* adie 1 */
+               if (dev->var.type == MT7996_VAR_TYPE_444)
+                       CAL_ARR(1, 7977);
+
+               /* adie 2 */
+               CAL_ARR(2, 7977);
+               break;
+       case MT7992_DEVICE_ID:
+               /* adie 0 */
+               if (dev->var.type == MT7992_VAR_TYPE_44 &&
+                   dev->var.fem != MT7996_FEM_EXT)
+                       CAL_ARR(0, 7975);
+               else if (dev->var.type == MT7992_VAR_TYPE_24)
+                       CAL_ARR(0, 7978);
+               else
+                       CAL_ARR(0, 7976);
+
+               /* adie 1 */
+               if (dev->var.type == MT7992_VAR_TYPE_44 &&
+                   dev->var.fem != MT7996_FEM_INT)
+                       CAL_ARR(1, 7977);
+               else if (dev->var.type != MT7992_VAR_TYPE_23)
+                       CAL_ARR(1, 7979);
+               break;
+       case MT7990_DEVICE_ID:
+               /* adie 0 */
+               CAL_ARR(0, 7976);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       for (band = 0; band < __MT_MAX_BAND; band++) {
+               u8 buf[MT7996_EEPROM_BLOCK_SIZE];
+               const struct cal_free_data *cal;
+               u16 prev_block_idx = -1;
+               u16 adie_base;
+
+               if (!cal_arr_len[band])
+                       continue;
+
+               if (band == MT_BAND0)
+                       adie_base = MT7996_EFUSE_BASE_OFFS_ADIE0;
+               else if (band == MT_BAND1 && is_mt7992(&dev->mt76))
+                       adie_base = MT7992_EFUSE_BASE_OFFS_ADIE1;
+               else if (band == MT_BAND1)
+                       adie_base = MT7996_EFUSE_BASE_OFFS_ADIE1;
+               else
+                       adie_base = MT7996_EFUSE_BASE_OFFS_ADIE2;
+
+               cal = cal_arr[band];
+               for (i = 0; i < cal_arr_len[band]; i++) {
+                       u16 adie_offset = cal[i].adie_offs + adie_base;
+                       u16 eep_offset = cal[i].eep_offs;
+                       u16 block_idx = adie_offset / MT7996_EEPROM_BLOCK_SIZE;
+                       u16 offset = adie_offset % MT7996_EEPROM_BLOCK_SIZE;
+
+                       if (is_mt7996(&dev->mt76) && band == MT_BAND1 &&
+                           dev->var.type == MT7996_VAR_TYPE_444)
+                               eep_offset -= MT_EE_7977BN_OFFSET;
+
+                       if (prev_block_idx != block_idx) {
+                               memset(buf, 0, sizeof(buf));
+                               ret = mt7996_mcu_get_eeprom(dev, adie_offset, buf,
+                                                           MT7996_EEPROM_BLOCK_SIZE,
+                                                           EEPROM_MODE_EFUSE);
+                               if (ret) {
+                                       if (ret != -EINVAL)
+                                               return ret;
+                                       prev_block_idx = -1;
+                                       continue;
+                               }
+                       }
+                       eeprom[eep_offset] = buf[offset];
+                       prev_block_idx = block_idx;
+               }
+       }
+
+       return 0;
+}
+
+int mt7996_mcu_set_eeprom(struct mt7996_dev *dev)
 {
 #define MAX_PAGE_IDX_MASK      GENMASK(7, 5)
 #define PAGE_IDX_MASK          GENMASK(4, 2)
@@ -3964,11 +4110,15 @@ static int mt7996_mcu_set_eeprom_flash(struct mt7996_dev *dev)
        u16 eeprom_size = MT7996_EEPROM_SIZE;
        u8 total = DIV_ROUND_UP(eeprom_size, PER_PAGE_SIZE);
        u8 *eep = (u8 *)dev->mt76.eeprom.data;
-       int eep_len, i;
+       int ret, eep_len, i;
+
+       ret = mt7996_mcu_get_cal_free_data(dev);
+       if (ret)
+               return ret;
 
        for (i = 0; i < total; i++, eep += eep_len) {
                struct sk_buff *skb;
-               int ret, msg_len;
+               int msg_len;
 
                if (i == total - 1 && !!(eeprom_size % PER_PAGE_SIZE))
                        eep_len = eeprom_size % PER_PAGE_SIZE;
@@ -3997,22 +4147,6 @@ static int mt7996_mcu_set_eeprom_flash(struct mt7996_dev *dev)
        return 0;
 }
 
-int mt7996_mcu_set_eeprom(struct mt7996_dev *dev)
-{
-       struct mt7996_mcu_eeprom_update req = {
-               .tag = cpu_to_le16(UNI_EFUSE_BUFFER_MODE),
-               .len = cpu_to_le16(sizeof(req) - 4),
-               .buffer_mode = EE_MODE_EFUSE,
-               .format = EE_FORMAT_WHOLE
-       };
-
-       if (dev->eeprom_mode != EEPROM_MODE_EFUSE)
-               return mt7996_mcu_set_eeprom_flash(dev);
-
-       return mt76_mcu_send_msg(&dev->mt76, MCU_WM_UNI_CMD(EFUSE_CTRL),
-                                &req, sizeof(req), true);
-}
-
 int mt7996_mcu_get_eeprom(struct mt7996_dev *dev, u32 offset, u8 *buf, u32 buf_len,
                          enum mt7996_eeprom_mode mode)
 {
index d36fb5396141a99da6a6faeae4d388288f6ca846..5f574ebe81ccb65ec45c1c8681792f699eea5a7f 100644 (file)
@@ -184,6 +184,11 @@ enum mt7996_eeprom_mode {
        EEPROM_MODE_EXT,
 };
 
+#define MT7996_EFUSE_BASE_OFFS_ADIE0   0x400
+#define MT7996_EFUSE_BASE_OFFS_ADIE1   0x1e00
+#define MT7996_EFUSE_BASE_OFFS_ADIE2   0x1200
+#define MT7992_EFUSE_BASE_OFFS_ADIE1   0x1200
+
 enum mt7996_txq_id {
        MT7996_TXQ_FWDL = 16,
        MT7996_TXQ_MCU_WM,