blob: e104a027fbd68acc6e95782f73aa272856d6a777 [file] [log] [blame]
From 5e847c789f6a3b7e234067e33171207fb32f46ea Mon Sep 17 00:00:00 2001
From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
Date: Fri, 24 Nov 2023 09:49:08 +0800
Subject: [PATCH 1041/1044] mtk: wifi: mt76: mt7996: add adie efuse merge
support
Merge adie-dependent parameters in efuse into eeprom after FT.
Note that Eagle BE14000 is not considered yet.
Add efuse dump command.
Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
---
mt7996/debugfs.c | 41 ++++++++++++++
mt7996/eeprom.c | 145 +++++++++++++++++++++++++++++++++++++++++++++++
mt7996/mcu.c | 6 +-
3 files changed, 190 insertions(+), 2 deletions(-)
diff --git a/mt7996/debugfs.c b/mt7996/debugfs.c
index 7a03de12..50ac6d4d 100644
--- a/mt7996/debugfs.c
+++ b/mt7996/debugfs.c
@@ -862,6 +862,46 @@ mt7996_rf_regval_set(void *data, u64 val)
DEFINE_DEBUGFS_ATTRIBUTE(fops_rf_regval, mt7996_rf_regval_get,
mt7996_rf_regval_set, "0x%08llx\n");
+static ssize_t
+mt7996_efuse_get(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct mt7996_dev *dev = file->private_data;
+ struct mt76_dev *mdev = &dev->mt76;
+ u8 *buff = mdev->otp.data;
+ int i;
+ ssize_t ret;
+ u32 block_num;
+
+ mdev->otp.size = MT7996_EEPROM_SIZE;
+ if (is_mt7996(&dev->mt76) && dev->chip_sku == MT7996_SKU_444)
+ mdev->otp.size += 3 * MT_EE_CAL_UNIT;
+
+ if (!mdev->otp.data) {
+ mdev->otp.data = devm_kzalloc(mdev->dev, mdev->otp.size, GFP_KERNEL);
+ if (!mdev->otp.data)
+ return -ENOMEM;
+
+ block_num = DIV_ROUND_UP(mdev->otp.size, MT7996_EEPROM_BLOCK_SIZE);
+ for (i = 0; i < block_num; i++) {
+ buff = mdev->otp.data + i * MT7996_EEPROM_BLOCK_SIZE;
+ ret = mt7996_mcu_get_eeprom(dev, i * MT7996_EEPROM_BLOCK_SIZE, buff);
+ if (ret)
+ continue;
+ }
+ }
+
+ ret = simple_read_from_buffer(user_buf, count, ppos, mdev->otp.data, mdev->otp.size);
+
+ return ret;
+}
+
+static const struct file_operations mt7996_efuse_ops = {
+ .read = mt7996_efuse_get,
+ .open = simple_open,
+ .llseek = default_llseek,
+};
+
int mt7996_init_debugfs(struct mt7996_phy *phy)
{
struct mt7996_dev *dev = phy->dev;
@@ -888,6 +928,7 @@ int mt7996_init_debugfs(struct mt7996_phy *phy)
debugfs_create_devm_seqfile(dev->mt76.dev, "twt_stats", dir,
mt7996_twt_stats);
debugfs_create_file("rf_regval", 0600, dir, dev, &fops_rf_regval);
+ debugfs_create_file("otp", 0400, dir, dev, &mt7996_efuse_ops);
if (phy->mt76->cap.has_5ghz) {
debugfs_create_u32("dfs_hw_pattern", 0400, dir,
diff --git a/mt7996/eeprom.c b/mt7996/eeprom.c
index 39e65010..45cbd03d 100644
--- a/mt7996/eeprom.c
+++ b/mt7996/eeprom.c
@@ -464,6 +464,147 @@ static int mt7996_eeprom_load_precal(struct mt7996_dev *dev)
return mt76_get_of_data_from_nvmem(mdev, dev->cal, "precal", size);
}
+static int mt7996_apply_cal_free_data(struct mt7996_dev *dev)
+{
+#define MT_EE_CAL_FREE_MAX_SIZE 30
+#define MT_EE_7977BN_OFFSET (0x1200 - 0x500)
+#define MT_EE_END_OFFSET 0xffff
+ enum adie_type {
+ ADIE_7975,
+ ADIE_7976,
+ ADIE_7977,
+ ADIE_7978,
+ ADIE_7979,
+ };
+ static const u16 adie_offs_list[][MT_EE_CAL_FREE_MAX_SIZE] = {
+ [ADIE_7975] = {0x5cd, 0x5cf, 0x5d1, 0x5d3, 0x6c0, 0x6c1, 0x6c2, 0x6c3,
+ 0x7a1, 0x7a6, 0x7a8, 0x7aa, -1},
+ [ADIE_7976] = {0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x53, 0x55, 0x57, 0x59,
+ 0x70, 0x71, 0x790, 0x791, 0x794, 0x795, 0x7a6, 0x7a8, 0x7aa, -1},
+ [ADIE_7977] = {0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x53, 0x55, 0x57, 0x59,
+ 0x69, 0x6a, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, -1},
+ [ADIE_7978] = {0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x53, 0x55, 0x57, 0x59,
+ 0x90, 0x91, 0x94, 0x95, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa,
+ 0x100, 0x101, 0x102, 0x103, 0x104, 0x105, -1},
+ [ADIE_7979] = {0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x53, 0x55, 0x57, 0x59,
+ 0x69, 0x6a, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, -1},
+ };
+ static const u16 eep_offs_list[][MT_EE_CAL_FREE_MAX_SIZE] = {
+ [ADIE_7975] = {0x451, 0x453, 0x455, 0x457, 0x44c, 0x44d, 0x44e, 0x44f,
+ 0xba1, 0xba6, 0xba8, 0xbaa, -1},
+ [ADIE_7976] = {0x44c, 0x44d, 0x44e, 0x44f, 0x450,
+ 0x451, 0x453, 0x455, 0x457, 0x459,
+ 0x470, 0x471, 0xb90, 0xb91, 0xb94, 0xb95,
+ 0xba6, 0xba8, 0xbaa, -1},
+ [ADIE_7977] = {0x124c, 0x124d, 0x124e, 0x124f, 0x1250,
+ 0x1251, 0x1253, 0x1255, 0x1257, 0x1259,
+ 0x1269, 0x126a, 0x127a, 0x127b, 0x127c, 0x127d, 0x127e, -1},
+ [ADIE_7978] = {0x44c, 0x44d, 0x44e, 0x44f, 0x450,
+ 0x451, 0x453, 0x455, 0x457, 0x459,
+ 0xb90, 0xb91, 0xb94, 0xb95,
+ 0xba6, 0xba7, 0xba8, 0xba9, 0xbaa,
+ 0x480, 0x481, 0x482, 0x483, 0x484, 0x485, -1},
+ [ADIE_7979] = {0x124c, 0x124d, 0x124e, 0x124f, 0x1250,
+ 0x1251, 0x1253, 0x1255, 0x1257, 0x1259,
+ 0x1269, 0x126a, 0x127a, 0x127b, 0x127c, 0x127d, 0x127e, -1},
+ };
+ static const u16 adie_base_7996[] = {
+ 0x400, 0x1e00, 0x1200
+ };
+ static const u16 adie_base_7992[] = {
+ 0x400, 0x1200, 0x0
+ };
+ static const u16 *adie_offs[__MT_MAX_BAND];
+ static const u16 *eep_offs[__MT_MAX_BAND];
+ static const u16 *adie_base;
+ u8 *eeprom = dev->mt76.eeprom.data;
+ u8 buf[MT7996_EEPROM_BLOCK_SIZE];
+ int adie_id, band, i, ret;
+
+ switch (mt76_chip(&dev->mt76)) {
+ case 0x7990:
+ adie_base = adie_base_7996;
+ /* adie 0 */
+ if (dev->fem_type == MT7996_FEM_INT)
+ adie_id = ADIE_7975;
+ else
+ adie_id = ADIE_7976;
+ adie_offs[0] = adie_offs_list[adie_id];
+ eep_offs[0] = eep_offs_list[adie_id];
+
+ /* adie 1 */
+ if (dev->chip_sku != MT7996_SKU_404) {
+ adie_offs[1] = adie_offs_list[ADIE_7977];
+ eep_offs[1] = eep_offs_list[ADIE_7977];
+ }
+
+ /* adie 2 */
+ adie_offs[2] = adie_offs_list[ADIE_7977];
+ eep_offs[2] = eep_offs_list[ADIE_7977];
+ break;
+ case 0x7992:
+ adie_base = adie_base_7992;
+ /* adie 0 */
+ if (dev->chip_sku == MT7992_SKU_44 &&
+ dev->fem_type != MT7996_FEM_EXT)
+ adie_id = ADIE_7975;
+ else if (dev->chip_sku == MT7992_SKU_24)
+ adie_id = ADIE_7978;
+ else
+ adie_id = ADIE_7976;
+ adie_offs[0] = adie_offs_list[adie_id];
+ eep_offs[0] = eep_offs_list[adie_id];
+
+ /* adie 1 */
+ if (dev->chip_sku == MT7992_SKU_44 &&
+ dev->fem_type != MT7996_FEM_INT)
+ adie_id = ADIE_7977;
+ else if (dev->chip_sku != MT7992_SKU_23)
+ adie_id = ADIE_7979;
+ else
+ break;
+ adie_offs[1] = adie_offs_list[adie_id];
+ eep_offs[1] = eep_offs_list[adie_id];
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ for (band = 0; band < __MT_MAX_BAND; band++) {
+ u16 adie_offset, eep_offset;
+ u32 block_num, prev_block_num = -1;
+
+ if (!adie_offs[band])
+ continue;
+
+ for (i = 0; i < MT_EE_CAL_FREE_MAX_SIZE; i++) {
+ adie_offset = adie_offs[band][i] + adie_base[band];
+ eep_offset = eep_offs[band][i];
+ block_num = adie_offset / MT7996_EEPROM_BLOCK_SIZE;
+
+ if (adie_offs[band][i] == MT_EE_END_OFFSET)
+ break;
+
+ if (is_mt7996(&dev->mt76) && dev->chip_sku == MT7996_SKU_444 &&
+ band == MT_BAND1)
+ eep_offset -= MT_EE_7977BN_OFFSET;
+
+ if (prev_block_num != block_num) {
+ ret = mt7996_mcu_get_eeprom(dev, adie_offset, buf);
+ if (ret) {
+ prev_block_num = -1;
+ continue;
+ }
+ }
+
+ eeprom[eep_offset] = buf[adie_offset % MT7996_EEPROM_BLOCK_SIZE];
+ prev_block_num = block_num;
+ }
+ }
+
+ return 0;
+}
+
int mt7996_eeprom_init(struct mt7996_dev *dev)
{
int ret;
@@ -489,6 +630,10 @@ int mt7996_eeprom_init(struct mt7996_dev *dev)
if (ret)
return ret;
+ ret = mt7996_apply_cal_free_data(dev);
+ if (ret)
+ return ret;
+
ret = mt7996_eeprom_parse_hw_cap(dev, &dev->phy);
if (ret < 0)
return ret;
diff --git a/mt7996/mcu.c b/mt7996/mcu.c
index c97a3204..26d0a1c1 100644
--- a/mt7996/mcu.c
+++ b/mt7996/mcu.c
@@ -3620,7 +3620,7 @@ int mt7996_mcu_get_eeprom(struct mt7996_dev *dev, u32 offset, u8 *read_buf)
};
struct sk_buff *skb;
bool valid;
- int ret;
+ int ret = 0;
u8 *buf = read_buf;
ret = mt76_mcu_send_and_get_msg(&dev->mt76,
@@ -3638,11 +3638,13 @@ int mt7996_mcu_get_eeprom(struct mt7996_dev *dev, u32 offset, u8 *read_buf)
skb_pull(skb, 48);
memcpy(buf, skb->data, MT7996_EEPROM_BLOCK_SIZE);
+ } else {
+ ret = -EINVAL;
}
dev_kfree_skb(skb);
- return 0;
+ return ret;
}
int mt7996_mcu_get_eeprom_free_block(struct mt7996_dev *dev, u8 *block_num)
--
2.18.0