blob: 7b56f6864e3737913d4befc83eb6035de0b6d581 [file] [log] [blame]
developera20cdc22024-05-31 18:57:31 +08001From 4f16df4de5a3b2d9080a7c07bfc1f0496de442cd Mon Sep 17 00:00:00 2001
developer1a173672023-12-21 14:49:33 +08002From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
3Date: Thu, 30 Mar 2023 15:12:37 +0800
developera20cdc22024-05-31 18:57:31 +08004Subject: [PATCH] wifi: mt76: mt7915: add cal free data merge support
developer1a173672023-12-21 14:49:33 +08005
61. add basic cal free data support
72. add E3 low yield rate workaround for panther E3 with 7976 adie
83. add Harrier freq offset workaround
developer753619c2024-02-22 13:42:45 +080094. add efuse dump command for verification
10 (/sys/kernel/debug/ieee80211/phyX/mt76/otp)
developer1a173672023-12-21 14:49:33 +080011
12Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
13---
developera46f6132024-03-26 14:09:54 +080014 mt7915/debugfs.c | 41 ++++++++++
15 mt7915/eeprom.c | 199 ++++++++++++++++++++++++++++++++++++++++++++++-
developer753619c2024-02-22 13:42:45 +080016 mt7915/eeprom.h | 2 +
17 mt7915/mcu.c | 13 +++-
18 mt7915/mt7915.h | 1 +
developera46f6132024-03-26 14:09:54 +080019 5 files changed, 250 insertions(+), 6 deletions(-)
developer1a173672023-12-21 14:49:33 +080020
developer753619c2024-02-22 13:42:45 +080021diff --git a/mt7915/debugfs.c b/mt7915/debugfs.c
developera20cdc22024-05-31 18:57:31 +080022index 909df24..c369296 100644
developer753619c2024-02-22 13:42:45 +080023--- a/mt7915/debugfs.c
24+++ b/mt7915/debugfs.c
developera20cdc22024-05-31 18:57:31 +080025@@ -1286,6 +1286,46 @@ static const struct file_operations mt7915_csi_ops = {
26 };
27 #endif
developer753619c2024-02-22 13:42:45 +080028
29+static ssize_t
30+mt7915_efuse_get(struct file *file, char __user *user_buf,
31+ size_t count, loff_t *ppos)
32+{
33+ struct mt7915_dev *dev = file->private_data;
34+ struct mt76_dev *mdev = &dev->mt76;
35+ u8 *buff = mdev->otp.data;
36+ int i;
37+ ssize_t ret;
38+ u32 block_num;
39+
40+ mdev->otp.size = mt7915_eeprom_size(dev);
41+ if (is_mt7986(&dev->mt76))
42+ mdev->otp.size += MT_EE_ADIE1_BASE_7896;
43+
44+ if (!mdev->otp.data) {
45+ mdev->otp.data = devm_kzalloc(mdev->dev, mdev->otp.size, GFP_KERNEL);
46+ if (!mdev->otp.data)
47+ return -ENOMEM;
48+
49+ block_num = DIV_ROUND_UP(mdev->otp.size, MT7915_EEPROM_BLOCK_SIZE);
50+ for (i = 0; i < block_num; i++) {
51+ buff = mdev->otp.data + i * MT7915_EEPROM_BLOCK_SIZE;
52+ ret = mt7915_mcu_get_eeprom(dev, i * MT7915_EEPROM_BLOCK_SIZE, buff);
53+ if (ret)
54+ continue;
55+ }
56+ }
57+
58+ ret = simple_read_from_buffer(user_buf, count, ppos, mdev->otp.data, mdev->otp.size);
59+
60+ return ret;
61+}
62+
63+static const struct file_operations mt7915_efuse_ops = {
64+ .read = mt7915_efuse_get,
65+ .open = simple_open,
66+ .llseek = default_llseek,
67+};
68+
69 int mt7915_init_debugfs(struct mt7915_phy *phy)
70 {
71 struct mt7915_dev *dev = phy->dev;
developera20cdc22024-05-31 18:57:31 +080072@@ -1328,6 +1368,7 @@ int mt7915_init_debugfs(struct mt7915_phy *phy)
developer753619c2024-02-22 13:42:45 +080073 debugfs_create_devm_seqfile(dev->mt76.dev, "rdd_monitor", dir,
74 mt7915_rdd_monitor);
75 }
76+ debugfs_create_file("otp", 0400, dir, dev, &mt7915_efuse_ops);
developera20cdc22024-05-31 18:57:31 +080077 #ifdef CONFIG_MTK_VENDOR
78 debugfs_create_file("csi_stats", 0400, dir, phy, &mt7915_csi_ops);
79 #endif
developer1a173672023-12-21 14:49:33 +080080diff --git a/mt7915/eeprom.c b/mt7915/eeprom.c
developerdc9eeae2024-04-08 14:36:46 +080081index c8b1c18..6133c20 100644
developer1a173672023-12-21 14:49:33 +080082--- a/mt7915/eeprom.c
83+++ b/mt7915/eeprom.c
developera46f6132024-03-26 14:09:54 +080084@@ -48,8 +48,13 @@ static int mt7915_eeprom_load_precal(struct mt7915_dev *dev)
85
86 offs = is_mt7915(&dev->mt76) ? MT_EE_PRECAL : MT_EE_PRECAL_V2;
87
88- if (dev->bin_file_mode)
89- return mt7915_eeprom_load_precal_binfile(dev, offs, size);
90+ if (dev->bin_file_mode) {
91+ ret = mt7915_eeprom_load_precal_binfile(dev, offs, size);
92+ if (ret)
93+ goto out;
94+
95+ return 0;
96+ }
97
98 ret = mt76_get_of_data_from_mtd(mdev, dev->cal, offs, size);
99 if (!ret)
100@@ -59,6 +64,7 @@ static int mt7915_eeprom_load_precal(struct mt7915_dev *dev)
101 if (!ret)
102 return ret;
103
104+out:
105 dev_warn(mdev->dev, "missing precal data, size=%d\n", size);
106 devm_kfree(mdev->dev, dev->cal);
107 dev->cal = NULL;
108@@ -283,6 +289,191 @@ void mt7915_eeprom_parse_hw_cap(struct mt7915_dev *dev,
developer1a173672023-12-21 14:49:33 +0800109 dev->chainshift = hweight8(dev->mphy.chainmask);
110 }
111
112+static int mt7915_apply_cal_free_data(struct mt7915_dev *dev)
113+{
114+#define MT_EE_CAL_FREE_MAX_SIZE 70
115+#define MT_EE_FREQ_OFFSET 0x77
116+#define MT_EE_ADIE1_MT7976C_OFFSET 0x270
117+#define MT_EE_ADIE1_E3_OFFSET 0x271
118+#define MT_EE_END_OFFSET 0xffff
developer1a173672023-12-21 14:49:33 +0800119+ enum adie_type {
120+ ADIE_7975,
121+ ADIE_7976,
122+ };
123+ enum ddie_type {
124+ DDIE_7915,
125+ DDIE_7916,
126+ };
127+ static const u16 ddie_offs_list[][MT_EE_CAL_FREE_MAX_SIZE] = {
128+ [DDIE_7915] = {0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
129+ 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x20, 0x21, 0x22, 0x23, 0x24,
130+ 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e,
131+ 0x52, 0x70, 0x71, 0x72, 0x76, 0xa8, 0xa9, 0xaa, 0xab, 0xac,
132+ 0xad, 0xae, 0xaf, -1},
133+ [DDIE_7916] = {0x30, 0x31, 0x34, 0x35, 0x36, 0x38, 0x3c, 0x3a, 0x3d, 0x44,
134+ 0x46, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xe0, -1},
135+ };
136+ static const u16 adie_offs_list[][MT_EE_CAL_FREE_MAX_SIZE] = {
137+ [ADIE_7975] = {0x7cd, 0x7cf, 0x7d1, 0x7d3, 0x802, 0x803, 0x804, 0x805, 0x806,
138+ 0x808, 0x80a, 0x80b, 0x80c, 0x80d, 0x80e, 0x810, 0x812, 0x813,
139+ 0x814, 0x815, 0x816, 0x818, 0x81a, 0x81b, 0x81c, 0x81d, 0x81e,
140+ 0x820, 0x822, 0x823, 0x824, 0x825, 0x826, 0x827, 0x828, 0x829,
141+ 0x82f, 0x8c0, 0x8c1, 0x8c2, 0x8c3, 0x9a0, 0x8d0, 0x8d1, 0x8d7,
142+ 0x8d8, 0x8fa, 0x9a1, 0x9a5, 0x9a6, 0x9a8, 0x9aa, 0x9b0, 0x9b1,
143+ 0x9b2, 0x9b3, 0x9b4, 0x9b5, 0x9b6, 0x9b7, -1},
144+ [ADIE_7976] = {0x24c, 0x24d, 0x24e, 0x24f, 0x250, 0x251, 0x253, 0x255, 0x257,
145+ 0x259, 0x990, 0x991, 0x994, 0x995, 0x9a6, 0x9a8, 0x9aa, -1},
146+ };
147+ static const u16 eep_offs_list[][MT_EE_CAL_FREE_MAX_SIZE] = {
148+ [ADIE_7975] = {0xe00, 0xe01, 0xe02, 0xe03, 0xe04, 0xe05, 0xe06, 0xe07, 0xe08,
149+ 0xe09, 0xe0a, 0xe0b, 0xe0c, 0xe0d, 0x80e, 0xe0f, 0xe10, 0xe11,
150+ 0xe12, 0xe13, 0xe14, 0xe15, 0xe16, 0xe17, 0xe18, 0xe19, 0xe1a,
151+ 0xe1b, 0xe1c, 0xe1d, 0xe1e, 0xe1f, 0xe20, 0xe21, 0xe22, 0xe23,
152+ 0xe24, 0xe25, 0xe26, 0xe27, 0xe28, 0xe29, 0xe2a, 0xe2b, 0xe2c,
153+ 0xe2d, 0xe2e, 0xe2f, 0xe33, 0xe34, 0xe36, 0xe38, 0xe39, 0xe3a,
154+ 0xe3b, 0xe3c, 0xe3d, 0xe3e, 0xe3f, 0xe40, -1},
155+ [ADIE_7976] = {0x33c, 0x33d, 0x33e, 0x33f, 0x340, 0x341, 0x343, 0x345, 0x347,
156+ 0x349, 0x359, 0x35a, 0x35d, 0x35e, 0x36a, 0x36c, 0x36e, -1},
157+ };
158+ static const u16 *ddie_offs;
159+ static const u16 *adie_offs[__MT_MAX_BAND];
160+ static const u16 *eep_offs[__MT_MAX_BAND];
161+ static u16 adie_base[__MT_MAX_BAND] = {0};
162+ u8 *eeprom = dev->mt76.eeprom.data;
163+ u8 buf[MT7915_EEPROM_BLOCK_SIZE];
164+ int adie_id, band, i, ret;
165+
166+ switch (mt76_chip(&dev->mt76)) {
167+ case 0x7915:
168+ ddie_offs = ddie_offs_list[DDIE_7915];
169+ ret = mt7915_mcu_get_eeprom(dev, MT_EE_ADIE_FT_VERSION, buf);
developera46f6132024-03-26 14:09:54 +0800170+ if (ret == -EINVAL)
171+ return 0;
172+ else if (ret)
developer1a173672023-12-21 14:49:33 +0800173+ return ret;
174+ adie_id = buf[MT_EE_ADIE_FT_VERSION % MT7915_EEPROM_BLOCK_SIZE] - 1;
175+ adie_offs[0] = adie_offs_list[ADIE_7975];
176+ /* same as adie offset */
177+ eep_offs[0] = NULL;
178+ break;
179+ case 0x7906:
180+ case 0x7981:
181+ if (is_mt7916(&dev->mt76))
182+ ddie_offs = ddie_offs_list[DDIE_7916];
183+ adie_offs[0] = adie_offs_list[ADIE_7976];
184+ eep_offs[0] = NULL;
185+ break;
186+ case 0x7986:
187+ adie_id = mt7915_check_adie(dev, true);
188+ switch (adie_id) {
189+ case MT7975_ONE_ADIE:
190+ case MT7975_DUAL_ADIE:
191+ adie_offs[0] = adie_offs_list[ADIE_7975];
192+ eep_offs[0] = NULL;
193+ if (adie_id == MT7975_DUAL_ADIE) {
194+ adie_offs[1] = adie_offs_list[ADIE_7975];
195+ eep_offs[1] = eep_offs_list[ADIE_7975];
196+ }
197+ break;
198+ case MT7976_ONE_ADIE_DBDC:
199+ case MT7976_ONE_ADIE:
200+ case MT7976_DUAL_ADIE: {
201+ u16 base = 0, offset = MT_EE_ADIE1_MT7976C_OFFSET;
202+
203+ adie_offs[0] = adie_offs_list[ADIE_7976];
204+ eep_offs[0] = NULL;
205+ if (adie_id == MT7976_DUAL_ADIE) {
206+ adie_offs[1] = adie_offs_list[ADIE_7976];
207+ eep_offs[1] = eep_offs_list[ADIE_7976];
208+ base = MT_EE_ADIE1_BASE_7896;
209+ }
210+
211+ /* E3 re-bonding workaround */
212+ ret = mt7915_mcu_get_eeprom(dev, offset + base, buf);
213+ if (ret)
214+ break;
215+ offset = (offset + base) % MT7915_EEPROM_BLOCK_SIZE;
216+ eeprom[MT_EE_ADIE1_MT7976C_OFFSET] = buf[offset];
217+ offset = (MT_EE_ADIE1_E3_OFFSET + base) % MT7915_EEPROM_BLOCK_SIZE;
218+ eeprom[MT_EE_ADIE1_E3_OFFSET] = buf[offset];
219+ break;
220+ }
221+ default:
222+ return -EINVAL;
223+ }
224+ adie_base[1] = MT_EE_ADIE1_BASE_7896;
225+ break;
226+ default:
227+ return -EINVAL;
228+ }
229+
230+ /* ddie */
231+ if (ddie_offs) {
232+ u16 ddie_offset;
233+ u32 block_num, prev_block_num = -1;
234+
235+ for (i = 0; i < MT_EE_CAL_FREE_MAX_SIZE; i++) {
236+ ddie_offset = ddie_offs[i];
237+ block_num = ddie_offset / MT7915_EEPROM_BLOCK_SIZE;
238+
239+ if (ddie_offset == MT_EE_END_OFFSET)
240+ break;
241+
242+ if (prev_block_num != block_num) {
243+ ret = mt7915_mcu_get_eeprom(dev, ddie_offset, buf);
244+ if (ret) {
245+ prev_block_num = -1;
246+ continue;
247+ }
248+ }
249+
250+ eeprom[ddie_offset] = buf[ddie_offset % MT7915_EEPROM_BLOCK_SIZE];
251+ prev_block_num = block_num;
252+ }
253+ }
254+
255+ /* adie */
256+ for (band = 0; band < __MT_MAX_BAND; band++) {
257+ u16 adie_offset, eep_offset;
258+ u32 block_num, prev_block_num = -1;
259+
260+ if (!adie_offs[band])
261+ continue;
262+
263+ for (i = 0; i < MT_EE_CAL_FREE_MAX_SIZE; i++) {
264+ adie_offset = adie_offs[band][i] + adie_base[band];
265+ eep_offset = adie_offset;
266+ if (eep_offs[band])
267+ eep_offset = eep_offs[band][i];
268+ block_num = adie_offset / MT7915_EEPROM_BLOCK_SIZE;
269+
270+ if (adie_offs[band][i] == MT_EE_END_OFFSET)
271+ break;
272+
273+ if (is_mt7915(&dev->mt76) && !adie_id &&
274+ adie_offset >= 0x8c0 && adie_offset <= 0x8c3)
275+ continue;
276+
277+ if (prev_block_num != block_num) {
278+ ret = mt7915_mcu_get_eeprom(dev, adie_offset, buf);
279+ if (ret) {
280+ prev_block_num = -1;
281+ continue;
282+ }
283+ }
284+
285+ eeprom[eep_offset] = buf[adie_offset % MT7915_EEPROM_BLOCK_SIZE];
286+ prev_block_num = block_num;
287+
288+ /* workaround for Harrier */
289+ if (is_mt7915(&dev->mt76) && adie_offset == 0x9a1)
290+ eeprom[MT_EE_FREQ_OFFSET] = eeprom[adie_offset];
291+ }
292+ }
293+
294+ return 0;
295+}
296+
297 int mt7915_eeprom_init(struct mt7915_dev *dev)
298 {
299 int ret;
developera46f6132024-03-26 14:09:54 +0800300@@ -320,6 +511,10 @@ int mt7915_eeprom_init(struct mt7915_dev *dev)
301 }
developer1a173672023-12-21 14:49:33 +0800302
developera46f6132024-03-26 14:09:54 +0800303 mt7915_eeprom_load_precal(dev);
developer1a173672023-12-21 14:49:33 +0800304+ ret = mt7915_apply_cal_free_data(dev);
305+ if (ret)
306+ return ret;
307+
308 mt7915_eeprom_parse_hw_cap(dev, &dev->phy);
309 memcpy(dev->mphy.macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR,
310 ETH_ALEN);
developer753619c2024-02-22 13:42:45 +0800311diff --git a/mt7915/eeprom.h b/mt7915/eeprom.h
developerdc9eeae2024-04-08 14:36:46 +0800312index 99101f9..70fca0b 100644
developer753619c2024-02-22 13:42:45 +0800313--- a/mt7915/eeprom.h
314+++ b/mt7915/eeprom.h
developera46f6132024-03-26 14:09:54 +0800315@@ -68,6 +68,8 @@ enum mt7915_eeprom_field {
developer753619c2024-02-22 13:42:45 +0800316 #define MT_EE_RATE_DELTA_SIGN BIT(6)
317 #define MT_EE_RATE_DELTA_EN BIT(7)
318
319+#define MT_EE_ADIE1_BASE_7896 0x1000
320+
321 enum mt7915_adie_sku {
322 MT7976_ONE_ADIE_DBDC = 0x7,
323 MT7975_ONE_ADIE = 0x8,
developer1a173672023-12-21 14:49:33 +0800324diff --git a/mt7915/mcu.c b/mt7915/mcu.c
developera20cdc22024-05-31 18:57:31 +0800325index cf622de..7bc5182 100644
developer1a173672023-12-21 14:49:33 +0800326--- a/mt7915/mcu.c
327+++ b/mt7915/mcu.c
developer753619c2024-02-22 13:42:45 +0800328@@ -2968,6 +2968,7 @@ int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset, u8 *read_buf)
developer1a173672023-12-21 14:49:33 +0800329 };
330 struct mt7915_mcu_eeprom_info *res;
331 struct sk_buff *skb;
332+ bool valid;
333 int ret;
334 u8 *buf = read_buf;
335
developer753619c2024-02-22 13:42:45 +0800336@@ -2978,10 +2979,14 @@ int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset, u8 *read_buf)
developer1a173672023-12-21 14:49:33 +0800337 return ret;
338
339 res = (struct mt7915_mcu_eeprom_info *)skb->data;
340-
341- if (!buf)
342- buf = dev->mt76.eeprom.data + le32_to_cpu(res->addr);
343- memcpy(buf, res->data, MT7915_EEPROM_BLOCK_SIZE);
344+ valid = !!le32_to_cpu(res->valid);
345+ if (valid) {
346+ if (!buf)
347+ buf = dev->mt76.eeprom.data + le32_to_cpu(res->addr);
348+ memcpy(buf, res->data, MT7915_EEPROM_BLOCK_SIZE);
349+ } else {
350+ ret = -EINVAL;
351+ }
352
353 dev_kfree_skb(skb);
354
355diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h
developera20cdc22024-05-31 18:57:31 +0800356index 3fe901d..5ba6986 100644
developer1a173672023-12-21 14:49:33 +0800357--- a/mt7915/mt7915.h
358+++ b/mt7915/mt7915.h
developera20cdc22024-05-31 18:57:31 +0800359@@ -581,6 +581,7 @@ u32 mt7915_wed_init_buf(void *ptr, dma_addr_t phys, int token_id);
developer1a173672023-12-21 14:49:33 +0800360
361 int mt7915_register_device(struct mt7915_dev *dev);
362 void mt7915_unregister_device(struct mt7915_dev *dev);
363+void mt7915_eeprom_rebonding(struct mt7915_dev *dev);
364 int mt7915_eeprom_init(struct mt7915_dev *dev);
365 void mt7915_eeprom_parse_hw_cap(struct mt7915_dev *dev,
366 struct mt7915_phy *phy);
367--
3682.18.0
369