blob: 273176bec26b3231ee31466eafacdabfe94a95af [file] [log] [blame]
developer918874f2023-11-27 13:41:04 +08001From 671c3c630c861155a465df211772e12fb6f7d48a Mon Sep 17 00:00:00 2001
2From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
3Date: Thu, 30 Mar 2023 15:12:37 +0800
4Subject: [PATCH] wifi: mt76: mt7915: add cal free data merge support
5
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
9
10Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
11---
12 mt7915/eeprom.c | 188 ++++++++++++++++++++++++++++++++++++++++++++++++
13 mt7915/mcu.c | 13 ++--
14 mt7915/mt7915.h | 1 +
15 3 files changed, 198 insertions(+), 4 deletions(-)
16
17diff --git a/mt7915/eeprom.c b/mt7915/eeprom.c
18index 5eb9f88..b96776d 100644
19--- a/mt7915/eeprom.c
20+++ b/mt7915/eeprom.c
21@@ -271,6 +271,190 @@ void mt7915_eeprom_parse_hw_cap(struct mt7915_dev *dev,
22 dev->chainshift = hweight8(dev->mphy.chainmask);
23 }
24
25+static int mt7915_apply_cal_free_data(struct mt7915_dev *dev)
26+{
27+#define MT_EE_CAL_FREE_MAX_SIZE 70
28+#define MT_EE_FREQ_OFFSET 0x77
29+#define MT_EE_ADIE1_MT7976C_OFFSET 0x270
30+#define MT_EE_ADIE1_E3_OFFSET 0x271
31+#define MT_EE_END_OFFSET 0xffff
32+#define MT_EE_ADIE1_BASE_7896 0x1000
33+ enum adie_type {
34+ ADIE_7975,
35+ ADIE_7976,
36+ };
37+ enum ddie_type {
38+ DDIE_7915,
39+ DDIE_7916,
40+ };
41+ static const u16 ddie_offs_list[][MT_EE_CAL_FREE_MAX_SIZE] = {
42+ [DDIE_7915] = {0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
43+ 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x20, 0x21, 0x22, 0x23, 0x24,
44+ 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e,
45+ 0x52, 0x70, 0x71, 0x72, 0x76, 0xa8, 0xa9, 0xaa, 0xab, 0xac,
46+ 0xad, 0xae, 0xaf, -1},
47+ [DDIE_7916] = {0x30, 0x31, 0x34, 0x35, 0x36, 0x38, 0x3c, 0x3a, 0x3d, 0x44,
48+ 0x46, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xe0, -1},
49+ };
50+ static const u16 adie_offs_list[][MT_EE_CAL_FREE_MAX_SIZE] = {
51+ [ADIE_7975] = {0x7cd, 0x7cf, 0x7d1, 0x7d3, 0x802, 0x803, 0x804, 0x805, 0x806,
52+ 0x808, 0x80a, 0x80b, 0x80c, 0x80d, 0x80e, 0x810, 0x812, 0x813,
53+ 0x814, 0x815, 0x816, 0x818, 0x81a, 0x81b, 0x81c, 0x81d, 0x81e,
54+ 0x820, 0x822, 0x823, 0x824, 0x825, 0x826, 0x827, 0x828, 0x829,
55+ 0x82f, 0x8c0, 0x8c1, 0x8c2, 0x8c3, 0x9a0, 0x8d0, 0x8d1, 0x8d7,
56+ 0x8d8, 0x8fa, 0x9a1, 0x9a5, 0x9a6, 0x9a8, 0x9aa, 0x9b0, 0x9b1,
57+ 0x9b2, 0x9b3, 0x9b4, 0x9b5, 0x9b6, 0x9b7, -1},
58+ [ADIE_7976] = {0x24c, 0x24d, 0x24e, 0x24f, 0x250, 0x251, 0x253, 0x255, 0x257,
59+ 0x259, 0x990, 0x991, 0x994, 0x995, 0x9a6, 0x9a8, 0x9aa, -1},
60+ };
61+ static const u16 eep_offs_list[][MT_EE_CAL_FREE_MAX_SIZE] = {
62+ [ADIE_7975] = {0xe00, 0xe01, 0xe02, 0xe03, 0xe04, 0xe05, 0xe06, 0xe07, 0xe08,
63+ 0xe09, 0xe0a, 0xe0b, 0xe0c, 0xe0d, 0x80e, 0xe0f, 0xe10, 0xe11,
64+ 0xe12, 0xe13, 0xe14, 0xe15, 0xe16, 0xe17, 0xe18, 0xe19, 0xe1a,
65+ 0xe1b, 0xe1c, 0xe1d, 0xe1e, 0xe1f, 0xe20, 0xe21, 0xe22, 0xe23,
66+ 0xe24, 0xe25, 0xe26, 0xe27, 0xe28, 0xe29, 0xe2a, 0xe2b, 0xe2c,
67+ 0xe2d, 0xe2e, 0xe2f, 0xe33, 0xe34, 0xe36, 0xe38, 0xe39, 0xe3a,
68+ 0xe3b, 0xe3c, 0xe3d, 0xe3e, 0xe3f, 0xe40, -1},
69+ [ADIE_7976] = {0x33c, 0x33d, 0x33e, 0x33f, 0x340, 0x341, 0x343, 0x345, 0x347,
70+ 0x349, 0x359, 0x35a, 0x35d, 0x35e, 0x36a, 0x36c, 0x36e, -1},
71+ };
72+ static const u16 *ddie_offs;
73+ static const u16 *adie_offs[__MT_MAX_BAND];
74+ static const u16 *eep_offs[__MT_MAX_BAND];
75+ static u16 adie_base[__MT_MAX_BAND] = {0};
76+ u8 *eeprom = dev->mt76.eeprom.data;
77+ u8 buf[MT7915_EEPROM_BLOCK_SIZE];
78+ int adie_id, band, i, ret;
79+
80+ switch (mt76_chip(&dev->mt76)) {
81+ case 0x7915:
82+ ddie_offs = ddie_offs_list[DDIE_7915];
83+ ret = mt7915_mcu_get_eeprom(dev, MT_EE_ADIE_FT_VERSION, buf);
84+ if (ret)
85+ return ret;
86+ adie_id = buf[MT_EE_ADIE_FT_VERSION % MT7915_EEPROM_BLOCK_SIZE] - 1;
87+ adie_offs[0] = adie_offs_list[ADIE_7975];
88+ /* same as adie offset */
89+ eep_offs[0] = NULL;
90+ break;
91+ case 0x7906:
92+ case 0x7981:
93+ if (is_mt7916(&dev->mt76))
94+ ddie_offs = ddie_offs_list[DDIE_7916];
95+ adie_offs[0] = adie_offs_list[ADIE_7976];
96+ eep_offs[0] = NULL;
97+ break;
98+ case 0x7986:
99+ adie_id = mt7915_check_adie(dev, true);
100+ switch (adie_id) {
101+ case MT7975_ONE_ADIE:
102+ case MT7975_DUAL_ADIE:
103+ adie_offs[0] = adie_offs_list[ADIE_7975];
104+ eep_offs[0] = NULL;
105+ if (adie_id == MT7975_DUAL_ADIE) {
106+ adie_offs[1] = adie_offs_list[ADIE_7975];
107+ eep_offs[1] = eep_offs_list[ADIE_7975];
108+ }
109+ break;
110+ case MT7976_ONE_ADIE_DBDC:
111+ case MT7976_ONE_ADIE:
112+ case MT7976_DUAL_ADIE: {
113+ u16 base = 0, offset = MT_EE_ADIE1_MT7976C_OFFSET;
114+
115+ adie_offs[0] = adie_offs_list[ADIE_7976];
116+ eep_offs[0] = NULL;
117+ if (adie_id == MT7976_DUAL_ADIE) {
118+ adie_offs[1] = adie_offs_list[ADIE_7976];
119+ eep_offs[1] = eep_offs_list[ADIE_7976];
120+ base = MT_EE_ADIE1_BASE_7896;
121+ }
122+
123+ /* E3 re-bonding workaround */
124+ ret = mt7915_mcu_get_eeprom(dev, offset + base, buf);
125+ if (ret)
126+ break;
127+ offset = (offset + base) % MT7915_EEPROM_BLOCK_SIZE;
128+ eeprom[MT_EE_ADIE1_MT7976C_OFFSET] = buf[offset];
129+ offset = (MT_EE_ADIE1_E3_OFFSET + base) % MT7915_EEPROM_BLOCK_SIZE;
130+ eeprom[MT_EE_ADIE1_E3_OFFSET] = buf[offset];
131+ break;
132+ }
133+ default:
134+ return -EINVAL;
135+ }
136+ adie_base[1] = MT_EE_ADIE1_BASE_7896;
137+ break;
138+ default:
139+ return -EINVAL;
140+ }
141+
142+ /* ddie */
143+ if (ddie_offs) {
144+ u16 ddie_offset;
145+ u32 block_num, prev_block_num = -1;
146+
147+ for (i = 0; i < MT_EE_CAL_FREE_MAX_SIZE; i++) {
148+ ddie_offset = ddie_offs[i];
149+ block_num = ddie_offset / MT7915_EEPROM_BLOCK_SIZE;
150+
151+ if (ddie_offset == MT_EE_END_OFFSET)
152+ break;
153+
154+ if (prev_block_num != block_num) {
155+ ret = mt7915_mcu_get_eeprom(dev, ddie_offset, buf);
156+ if (ret) {
157+ prev_block_num = -1;
158+ continue;
159+ }
160+ }
161+
162+ eeprom[ddie_offset] = buf[ddie_offset % MT7915_EEPROM_BLOCK_SIZE];
163+ prev_block_num = block_num;
164+ }
165+ }
166+
167+ /* adie */
168+ for (band = 0; band < __MT_MAX_BAND; band++) {
169+ u16 adie_offset, eep_offset;
170+ u32 block_num, prev_block_num = -1;
171+
172+ if (!adie_offs[band])
173+ continue;
174+
175+ for (i = 0; i < MT_EE_CAL_FREE_MAX_SIZE; i++) {
176+ adie_offset = adie_offs[band][i] + adie_base[band];
177+ eep_offset = adie_offset;
178+ if (eep_offs[band])
179+ eep_offset = eep_offs[band][i];
180+ block_num = adie_offset / MT7915_EEPROM_BLOCK_SIZE;
181+
182+ if (adie_offs[band][i] == MT_EE_END_OFFSET)
183+ break;
184+
185+ if (is_mt7915(&dev->mt76) && !adie_id &&
186+ adie_offset >= 0x8c0 && adie_offset <= 0x8c3)
187+ continue;
188+
189+ if (prev_block_num != block_num) {
190+ ret = mt7915_mcu_get_eeprom(dev, adie_offset, buf);
191+ if (ret) {
192+ prev_block_num = -1;
193+ continue;
194+ }
195+ }
196+
197+ eeprom[eep_offset] = buf[adie_offset % MT7915_EEPROM_BLOCK_SIZE];
198+ prev_block_num = block_num;
199+
200+ /* workaround for Harrier */
201+ if (is_mt7915(&dev->mt76) && adie_offset == 0x9a1)
202+ eeprom[MT_EE_FREQ_OFFSET] = eeprom[adie_offset];
203+ }
204+ }
205+
206+ return 0;
207+}
208+
209 int mt7915_eeprom_init(struct mt7915_dev *dev)
210 {
211 int ret;
212@@ -311,6 +495,10 @@ int mt7915_eeprom_init(struct mt7915_dev *dev)
213 if (ret)
214 return ret;
215
216+ ret = mt7915_apply_cal_free_data(dev);
217+ if (ret)
218+ return ret;
219+
220 mt7915_eeprom_parse_hw_cap(dev, &dev->phy);
221 memcpy(dev->mphy.macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR,
222 ETH_ALEN);
223diff --git a/mt7915/mcu.c b/mt7915/mcu.c
224index 7e33386..28e023d 100644
225--- a/mt7915/mcu.c
226+++ b/mt7915/mcu.c
227@@ -2879,6 +2879,7 @@ int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset, u8 *read_buf)
228 };
229 struct mt7915_mcu_eeprom_info *res;
230 struct sk_buff *skb;
231+ bool valid;
232 int ret;
233 u8 *buf = read_buf;
234
235@@ -2889,10 +2890,14 @@ int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset, u8 *read_buf)
236 return ret;
237
238 res = (struct mt7915_mcu_eeprom_info *)skb->data;
239-
240- if (!buf)
241- buf = dev->mt76.eeprom.data + le32_to_cpu(res->addr);
242- memcpy(buf, res->data, MT7915_EEPROM_BLOCK_SIZE);
243+ valid = !!le32_to_cpu(res->valid);
244+ if (valid) {
245+ if (!buf)
246+ buf = dev->mt76.eeprom.data + le32_to_cpu(res->addr);
247+ memcpy(buf, res->data, MT7915_EEPROM_BLOCK_SIZE);
248+ } else {
249+ ret = -EINVAL;
250+ }
251
252 dev_kfree_skb(skb);
253
254diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h
255index 8730655..25a6815 100644
256--- a/mt7915/mt7915.h
257+++ b/mt7915/mt7915.h
258@@ -507,6 +507,7 @@ u32 mt7915_wed_init_buf(void *ptr, dma_addr_t phys, int token_id);
259
260 int mt7915_register_device(struct mt7915_dev *dev);
261 void mt7915_unregister_device(struct mt7915_dev *dev);
262+void mt7915_eeprom_rebonding(struct mt7915_dev *dev);
263 int mt7915_eeprom_init(struct mt7915_dev *dev);
264 void mt7915_eeprom_parse_hw_cap(struct mt7915_dev *dev,
265 struct mt7915_phy *phy);
266--
2672.18.0
268