blob: e96a9fb1ee488924710a88490b2f64a340a1e989 [file] [log] [blame]
developera46f6132024-03-26 14:09:54 +08001From 668d96f2685432f602994676ff31f826fb98a99f Mon Sep 17 00:00:00 2001
developerf552fec2023-03-27 11:22:06 +08002From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
3Date: Fri, 24 Mar 2023 23:35:30 +0800
developereb155692024-01-11 14:08:37 +08004Subject: [PATCH 1007/1044] mtk: wifi: mt76: mt7996: add txpower support
developerf552fec2023-03-27 11:22:06 +08005
6Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
developerf552fec2023-03-27 11:22:06 +08007---
developereb155692024-01-11 14:08:37 +08008 mt7996/eeprom.c | 34 +++++
9 mt7996/eeprom.h | 42 ++++++
developerf552fec2023-03-27 11:22:06 +080010 mt7996/mcu.h | 2 +
developer1a173672023-12-21 14:49:33 +080011 mt7996/mt7996.h | 1 +
developereb155692024-01-11 14:08:37 +080012 mt7996/mtk_debugfs.c | 326 +++++++++++++++++++++++++++++++++++++++++++
13 mt7996/mtk_mcu.c | 23 +++
14 mt7996/mtk_mcu.h | 92 ++++++++++++
15 mt7996/regs.h | 29 ++--
16 8 files changed, 538 insertions(+), 11 deletions(-)
developerf552fec2023-03-27 11:22:06 +080017
18diff --git a/mt7996/eeprom.c b/mt7996/eeprom.c
developereb155692024-01-11 14:08:37 +080019index 3aeffdfb..acc33cfe 100644
developerf552fec2023-03-27 11:22:06 +080020--- a/mt7996/eeprom.c
21+++ b/mt7996/eeprom.c
developereb155692024-01-11 14:08:37 +080022@@ -404,3 +404,37 @@ s8 mt7996_eeprom_get_power_delta(struct mt7996_dev *dev, int band)
developerf552fec2023-03-27 11:22:06 +080023
24 return val & MT_EE_RATE_DELTA_SIGN ? delta : -delta;
25 }
26+
27+const u8 mt7996_sku_group_len[] = {
28+ [SKU_CCK] = 4,
29+ [SKU_OFDM] = 8,
30+ [SKU_HT20] = 8,
31+ [SKU_HT40] = 9,
32+ [SKU_VHT20] = 12,
33+ [SKU_VHT40] = 12,
34+ [SKU_VHT80] = 12,
35+ [SKU_VHT160] = 12,
36+ [SKU_HE26] = 12,
37+ [SKU_HE52] = 12,
38+ [SKU_HE106] = 12,
39+ [SKU_HE242] = 12,
40+ [SKU_HE484] = 12,
41+ [SKU_HE996] = 12,
42+ [SKU_HE2x996] = 12,
43+ [SKU_EHT26] = 16,
44+ [SKU_EHT52] = 16,
45+ [SKU_EHT106] = 16,
46+ [SKU_EHT242] = 16,
47+ [SKU_EHT484] = 16,
48+ [SKU_EHT996] = 16,
49+ [SKU_EHT2x996] = 16,
50+ [SKU_EHT4x996] = 16,
51+ [SKU_EHT26_52] = 16,
52+ [SKU_EHT26_106] = 16,
53+ [SKU_EHT484_242] = 16,
54+ [SKU_EHT996_484] = 16,
55+ [SKU_EHT996_484_242] = 16,
56+ [SKU_EHT2x996_484] = 16,
57+ [SKU_EHT3x996] = 16,
58+ [SKU_EHT3x996_484] = 16,
59+};
60diff --git a/mt7996/eeprom.h b/mt7996/eeprom.h
developer1a173672023-12-21 14:49:33 +080061index 849b8bca..23d4929d 100644
developerf552fec2023-03-27 11:22:06 +080062--- a/mt7996/eeprom.h
63+++ b/mt7996/eeprom.h
developer1a173672023-12-21 14:49:33 +080064@@ -123,4 +123,46 @@ mt7996_get_channel_group_6g(int channel)
developerf552fec2023-03-27 11:22:06 +080065 return DIV_ROUND_UP(channel - 29, 32);
66 }
67
68+enum mt7996_sku_rate_group {
69+ SKU_CCK,
70+ SKU_OFDM,
71+
72+ SKU_HT20,
73+ SKU_HT40,
74+
75+ SKU_VHT20,
76+ SKU_VHT40,
77+ SKU_VHT80,
78+ SKU_VHT160,
79+
80+ SKU_HE26,
81+ SKU_HE52,
82+ SKU_HE106,
83+ SKU_HE242,
84+ SKU_HE484,
85+ SKU_HE996,
86+ SKU_HE2x996,
87+
88+ SKU_EHT26,
89+ SKU_EHT52,
90+ SKU_EHT106,
91+ SKU_EHT242,
92+ SKU_EHT484,
93+ SKU_EHT996,
94+ SKU_EHT2x996,
95+ SKU_EHT4x996,
96+ SKU_EHT26_52,
97+ SKU_EHT26_106,
98+ SKU_EHT484_242,
99+ SKU_EHT996_484,
100+ SKU_EHT996_484_242,
101+ SKU_EHT2x996_484,
102+ SKU_EHT3x996,
103+ SKU_EHT3x996_484,
104+
105+ MAX_SKU_RATE_GROUP_NUM,
106+};
107+
108+extern const u8 mt7996_sku_group_len[MAX_SKU_RATE_GROUP_NUM];
109+
110 #endif
111diff --git a/mt7996/mcu.h b/mt7996/mcu.h
developer1a173672023-12-21 14:49:33 +0800112index 4f4994d8..887d9b49 100644
developerf552fec2023-03-27 11:22:06 +0800113--- a/mt7996/mcu.h
114+++ b/mt7996/mcu.h
developer1a173672023-12-21 14:49:33 +0800115@@ -911,6 +911,7 @@ struct tx_power_ctrl {
developerf552fec2023-03-27 11:22:06 +0800116 bool ate_mode_enable;
117 bool percentage_ctrl_enable;
118 bool bf_backoff_enable;
119+ u8 show_info_category;
120 u8 power_drop_level;
121 };
122 u8 band_idx;
developer1a173672023-12-21 14:49:33 +0800123@@ -924,6 +925,7 @@ enum {
developerf552fec2023-03-27 11:22:06 +0800124 UNI_TXPOWER_BACKOFF_POWER_LIMIT_CTRL = 3,
125 UNI_TXPOWER_POWER_LIMIT_TABLE_CTRL = 4,
126 UNI_TXPOWER_ATE_MODE_CTRL = 6,
127+ UNI_TXPOWER_SHOW_INFO = 7,
128 };
129
130 enum {
131diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
developer1a173672023-12-21 14:49:33 +0800132index 384157c8..18a6a46d 100644
developerf552fec2023-03-27 11:22:06 +0800133--- a/mt7996/mt7996.h
134+++ b/mt7996/mt7996.h
developer1a173672023-12-21 14:49:33 +0800135@@ -609,6 +609,7 @@ int mt7996_mcu_set_tx_power_ctrl(struct mt7996_phy *phy, u8 power_ctrl_id, u8 da
136 #ifdef CONFIG_NL80211_TESTMODE
137 void mt7996_tm_rf_test_event(struct mt7996_dev *dev, struct sk_buff *skb);
138 #endif
developerf552fec2023-03-27 11:22:06 +0800139+int mt7996_mcu_get_tx_power_info(struct mt7996_phy *phy, u8 category, void *event);
developer692ed9b2023-06-19 12:03:50 +0800140 int mt7996_mcu_set_scs(struct mt7996_phy *phy, u8 enable);
141 void mt7996_mcu_scs_sta_poll(struct work_struct *work);
developerf552fec2023-03-27 11:22:06 +0800142
developerf552fec2023-03-27 11:22:06 +0800143diff --git a/mt7996/mtk_debugfs.c b/mt7996/mtk_debugfs.c
developera46f6132024-03-26 14:09:54 +0800144index 7e4ac77c..c47d65c9 100644
developerf552fec2023-03-27 11:22:06 +0800145--- a/mt7996/mtk_debugfs.c
146+++ b/mt7996/mtk_debugfs.c
developereb155692024-01-11 14:08:37 +0800147@@ -2417,6 +2417,328 @@ mt7996_scs_enable_set(void *data, u64 val)
developer1a173672023-12-21 14:49:33 +0800148 DEFINE_DEBUGFS_ATTRIBUTE(fops_scs_enable, NULL,
149 mt7996_scs_enable_set, "%lld\n");
developerf552fec2023-03-27 11:22:06 +0800150
151+static int
152+mt7996_txpower_level_set(void *data, u64 val)
153+{
154+ struct mt7996_phy *phy = data;
155+ int ret;
156+
157+ if (val > 100)
158+ return -EINVAL;
159+
160+ ret = mt7996_mcu_set_tx_power_ctrl(phy, UNI_TXPOWER_PERCENTAGE_CTRL, !!val);
161+ if (ret)
162+ return ret;
163+
164+ return mt7996_mcu_set_tx_power_ctrl(phy, UNI_TXPOWER_PERCENTAGE_DROP_CTRL, val);
165+}
166+
167+DEFINE_DEBUGFS_ATTRIBUTE(fops_txpower_level, NULL,
168+ mt7996_txpower_level_set, "%lld\n");
169+
170+static ssize_t
171+mt7996_get_txpower_info(struct file *file, char __user *user_buf,
172+ size_t count, loff_t *ppos)
173+{
174+ struct mt7996_phy *phy = file->private_data;
175+ struct mt7996_mcu_txpower_event *event;
176+ struct txpower_basic_info *basic_info;
177+ static const size_t size = 2048;
178+ int len = 0;
179+ ssize_t ret;
180+ char *buf;
181+
182+ buf = kzalloc(size, GFP_KERNEL);
183+ event = kzalloc(sizeof(*event), GFP_KERNEL);
developereb155692024-01-11 14:08:37 +0800184+ if (!buf || !event) {
185+ ret = -ENOMEM;
186+ goto out;
187+ }
developerf552fec2023-03-27 11:22:06 +0800188+
189+ ret = mt7996_mcu_get_tx_power_info(phy, BASIC_INFO, event);
190+ if (ret ||
191+ le32_to_cpu(event->basic_info.category) != UNI_TXPOWER_BASIC_INFO)
192+ goto out;
193+
194+ basic_info = &event->basic_info;
195+
196+ len += scnprintf(buf + len, size - len,
197+ "======================== BASIC INFO ========================\n");
198+ len += scnprintf(buf + len, size - len, " Band Index: %d, Channel Band: %d\n",
199+ basic_info->band_idx, basic_info->band);
200+ len += scnprintf(buf + len, size - len, " PA Type: %s\n",
201+ basic_info->is_epa ? "ePA" : "iPA");
202+ len += scnprintf(buf + len, size - len, " LNA Type: %s\n",
203+ basic_info->is_elna ? "eLNA" : "iLNA");
204+
205+ len += scnprintf(buf + len, size - len,
206+ "------------------------------------------------------------\n");
207+ len += scnprintf(buf + len, size - len, " SKU: %s\n",
208+ basic_info->sku_enable ? "enable" : "disable");
209+ len += scnprintf(buf + len, size - len, " Percentage Control: %s\n",
210+ basic_info->percentage_ctrl_enable ? "enable" : "disable");
211+ len += scnprintf(buf + len, size - len, " Power Drop: %d [dBm]\n",
212+ basic_info->power_drop_level >> 1);
213+ len += scnprintf(buf + len, size - len, " Backoff: %s\n",
214+ basic_info->bf_backoff_enable ? "enable" : "disable");
215+ len += scnprintf(buf + len, size - len, " TX Front-end Loss: %d, %d, %d, %d\n",
216+ basic_info->front_end_loss_tx[0], basic_info->front_end_loss_tx[1],
217+ basic_info->front_end_loss_tx[2], basic_info->front_end_loss_tx[3]);
218+ len += scnprintf(buf + len, size - len, " RX Front-end Loss: %d, %d, %d, %d\n",
219+ basic_info->front_end_loss_rx[0], basic_info->front_end_loss_rx[1],
220+ basic_info->front_end_loss_rx[2], basic_info->front_end_loss_rx[3]);
221+ len += scnprintf(buf + len, size - len,
222+ " MU TX Power Mode: %s\n",
223+ basic_info->mu_tx_power_manual_enable ? "manual" : "auto");
224+ len += scnprintf(buf + len, size - len,
225+ " MU TX Power (Auto / Manual): %d / %d [0.5 dBm]\n",
226+ basic_info->mu_tx_power_auto, basic_info->mu_tx_power_manual);
227+ len += scnprintf(buf + len, size - len,
228+ " Thermal Compensation: %s\n",
229+ basic_info->thermal_compensate_enable ? "enable" : "disable");
230+ len += scnprintf(buf + len, size - len,
231+ " Theraml Compensation Value: %d\n",
232+ basic_info->thermal_compensate_value);
233+
234+ ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
235+
236+out:
237+ kfree(buf);
238+ kfree(event);
239+ return ret;
240+}
241+
242+static const struct file_operations mt7996_txpower_info_fops = {
243+ .read = mt7996_get_txpower_info,
244+ .open = simple_open,
245+ .owner = THIS_MODULE,
246+ .llseek = default_llseek,
247+};
248+
249+#define mt7996_txpower_puts(rate) \
250+({ \
251+ len += scnprintf(buf + len, size - len, "%-21s:", #rate " (TMAC)"); \
252+ for (i = 0; i < mt7996_sku_group_len[SKU_##rate]; i++, offs++) \
253+ len += scnprintf(buf + len, size - len, " %6d", \
254+ event->phy_rate_info.frame_power[offs][band_idx]); \
255+ len += scnprintf(buf + len, size - len, "\n"); \
256+})
257+
258+static ssize_t
259+mt7996_get_txpower_sku(struct file *file, char __user *user_buf,
260+ size_t count, loff_t *ppos)
261+{
262+ struct mt7996_phy *phy = file->private_data;
263+ struct mt7996_dev *dev = phy->dev;
264+ struct mt7996_mcu_txpower_event *event;
265+ u8 band_idx = phy->mt76->band_idx;
266+ static const size_t size = 5120;
267+ int i, offs = 0, len = 0;
268+ ssize_t ret;
269+ char *buf;
270+ u32 reg;
271+
272+ buf = kzalloc(size, GFP_KERNEL);
273+ event = kzalloc(sizeof(*event), GFP_KERNEL);
developereb155692024-01-11 14:08:37 +0800274+ if (!buf || !event) {
275+ ret = -ENOMEM;
276+ goto out;
277+ }
developerf552fec2023-03-27 11:22:06 +0800278+
279+ ret = mt7996_mcu_get_tx_power_info(phy, PHY_RATE_INFO, event);
280+ if (ret ||
281+ le32_to_cpu(event->phy_rate_info.category) != UNI_TXPOWER_PHY_RATE_INFO)
282+ goto out;
283+
284+ len += scnprintf(buf + len, size - len,
285+ "\nPhy %d TX Power Table (Channel %d)\n",
286+ band_idx, phy->mt76->chandef.chan->hw_value);
287+ len += scnprintf(buf + len, size - len, "%-21s %6s %6s %6s %6s\n",
288+ " ", "1m", "2m", "5m", "11m");
289+ mt7996_txpower_puts(CCK);
290+
291+ len += scnprintf(buf + len, size - len,
292+ "%-21s %6s %6s %6s %6s %6s %6s %6s %6s\n",
293+ " ", "6m", "9m", "12m", "18m", "24m", "36m", "48m",
294+ "54m");
295+ mt7996_txpower_puts(OFDM);
296+
297+ len += scnprintf(buf + len, size - len,
298+ "%-21s %6s %6s %6s %6s %6s %6s %6s %6s\n",
299+ " ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4",
300+ "mcs5", "mcs6", "mcs7");
301+ mt7996_txpower_puts(HT20);
302+
303+ len += scnprintf(buf + len, size - len,
304+ "%-21s %6s %6s %6s %6s %6s %6s %6s %6s %6s\n",
305+ " ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5",
306+ "mcs6", "mcs7", "mcs32");
307+ mt7996_txpower_puts(HT40);
308+
309+ len += scnprintf(buf + len, size - len,
310+ "%-21s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s\n",
311+ " ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5",
312+ "mcs6", "mcs7", "mcs8", "mcs9", "mcs10", "mcs11");
313+ mt7996_txpower_puts(VHT20);
314+ mt7996_txpower_puts(VHT40);
315+ mt7996_txpower_puts(VHT80);
316+ mt7996_txpower_puts(VHT160);
317+ mt7996_txpower_puts(HE26);
318+ mt7996_txpower_puts(HE52);
319+ mt7996_txpower_puts(HE106);
320+ mt7996_txpower_puts(HE242);
321+ mt7996_txpower_puts(HE484);
322+ mt7996_txpower_puts(HE996);
323+ mt7996_txpower_puts(HE2x996);
324+
325+ len += scnprintf(buf + len, size - len,
326+ "%-21s %6s %6s %6s %6s %6s %6s %6s %6s ",
327+ " ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5", "mcs6", "mcs7");
328+ len += scnprintf(buf + len, size - len,
329+ "%6s %6s %6s %6s %6s %6s %6s %6s\n",
330+ "mcs8", "mcs9", "mcs10", "mcs11", "mcs12", "mcs13", "mcs14", "mcs15");
331+ mt7996_txpower_puts(EHT26);
332+ mt7996_txpower_puts(EHT52);
333+ mt7996_txpower_puts(EHT106);
334+ mt7996_txpower_puts(EHT242);
335+ mt7996_txpower_puts(EHT484);
336+ mt7996_txpower_puts(EHT996);
337+ mt7996_txpower_puts(EHT2x996);
338+ mt7996_txpower_puts(EHT4x996);
339+ mt7996_txpower_puts(EHT26_52);
340+ mt7996_txpower_puts(EHT26_106);
341+ mt7996_txpower_puts(EHT484_242);
342+ mt7996_txpower_puts(EHT996_484);
343+ mt7996_txpower_puts(EHT996_484_242);
344+ mt7996_txpower_puts(EHT2x996_484);
345+ mt7996_txpower_puts(EHT3x996);
346+ mt7996_txpower_puts(EHT3x996_484);
347+
348+ len += scnprintf(buf + len, size - len, "\nePA Gain: %d\n",
349+ event->phy_rate_info.epa_gain);
350+ len += scnprintf(buf + len, size - len, "Max Power Bound: %d\n",
351+ event->phy_rate_info.max_power_bound);
352+ len += scnprintf(buf + len, size - len, "Min Power Bound: %d\n",
353+ event->phy_rate_info.min_power_bound);
354+
355+ reg = MT_WF_PHYDFE_BAND_TPC_CTRL_STAT0(band_idx);
356+ len += scnprintf(buf + len, size - len,
357+ "BBP TX Power (target power from TMAC) : %6ld [0.5 dBm]\n",
358+ mt76_get_field(dev, reg, MT_WF_PHY_TPC_POWER_TMAC));
359+ len += scnprintf(buf + len, size - len,
360+ "BBP TX Power (target power from RMAC) : %6ld [0.5 dBm]\n",
361+ mt76_get_field(dev, reg, MT_WF_PHY_TPC_POWER_RMAC));
362+ len += scnprintf(buf + len, size - len,
363+ "BBP TX Power (TSSI module power input) : %6ld [0.5 dBm]\n",
364+ mt76_get_field(dev, reg, MT_WF_PHY_TPC_POWER_TSSI));
365+
366+ ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
367+
368+out:
369+ kfree(buf);
370+ kfree(event);
371+ return ret;
372+}
373+
374+static const struct file_operations mt7996_txpower_sku_fops = {
375+ .read = mt7996_get_txpower_sku,
376+ .open = simple_open,
377+ .owner = THIS_MODULE,
378+ .llseek = default_llseek,
379+};
380+
developereb155692024-01-11 14:08:37 +0800381+#define mt7996_txpower_path_puts(rate, arr_length) \
382+({ \
383+ len += scnprintf(buf + len, size - len, "%-23s:", #rate " (TMAC)"); \
384+ for (i = 0; i < arr_length; i++, offs++) \
385+ len += scnprintf(buf + len, size - len, " %4d", \
386+ event->backoff_table_info.frame_power[offs]); \
387+ len += scnprintf(buf + len, size - len, "\n"); \
388+})
389+
390+static ssize_t
391+mt7996_get_txpower_path(struct file *file, char __user *user_buf,
392+ size_t count, loff_t *ppos)
393+{
394+ struct mt7996_phy *phy = file->private_data;
395+ struct mt7996_mcu_txpower_event *event;
396+ static const size_t size = 5120;
397+ int i, offs = 0, len = 0;
398+ ssize_t ret;
399+ char *buf;
400+
401+ buf = kzalloc(size, GFP_KERNEL);
402+ event = kzalloc(sizeof(*event), GFP_KERNEL);
403+ if (!buf || !event) {
404+ ret = -ENOMEM;
405+ goto out;
406+ }
407+
408+ ret = mt7996_mcu_get_tx_power_info(phy, BACKOFF_TABLE_INFO, event);
409+ if (ret ||
410+ le32_to_cpu(event->phy_rate_info.category) != UNI_TXPOWER_BACKOFF_TABLE_SHOW_INFO)
411+ goto out;
412+
413+ len += scnprintf(buf + len, size - len, "\n%*c", 25, ' ');
414+ len += scnprintf(buf + len, size - len, "1T1S/2T1S/3T1S/4T1S/5T1S/2T2S/3T2S/4T2S/5T2S/"
415+ "3T3S/4T3S/5T3S/4T4S/5T4S/5T5S\n");
416+
417+ mt7996_txpower_path_puts(CCK, 5);
418+ mt7996_txpower_path_puts(OFDM, 5);
419+ mt7996_txpower_path_puts(BF-OFDM, 4);
420+
421+ mt7996_txpower_path_puts(RU26, 15);
422+ mt7996_txpower_path_puts(BF-RU26, 15);
423+ mt7996_txpower_path_puts(RU52, 15);
424+ mt7996_txpower_path_puts(BF-RU52, 15);
425+ mt7996_txpower_path_puts(RU26_52, 15);
426+ mt7996_txpower_path_puts(BF-RU26_52, 15);
427+ mt7996_txpower_path_puts(RU106, 15);
428+ mt7996_txpower_path_puts(BF-RU106, 15);
429+ mt7996_txpower_path_puts(RU106_52, 15);
430+ mt7996_txpower_path_puts(BF-RU106_52, 15);
431+
432+ mt7996_txpower_path_puts(BW20/RU242, 15);
433+ mt7996_txpower_path_puts(BF-BW20/RU242, 15);
434+ mt7996_txpower_path_puts(BW40/RU484, 15);
435+ mt7996_txpower_path_puts(BF-BW40/RU484, 15);
436+ mt7996_txpower_path_puts(RU242_484, 15);
437+ mt7996_txpower_path_puts(BF-RU242_484, 15);
438+ mt7996_txpower_path_puts(BW80/RU996, 15);
439+ mt7996_txpower_path_puts(BF-BW80/RU996, 15);
440+ mt7996_txpower_path_puts(RU484_996, 15);
441+ mt7996_txpower_path_puts(BF-RU484_996, 15);
442+ mt7996_txpower_path_puts(RU242_484_996, 15);
443+ mt7996_txpower_path_puts(BF-RU242_484_996, 15);
444+ mt7996_txpower_path_puts(BW160/RU996x2, 15);
445+ mt7996_txpower_path_puts(BF-BW160/RU996x2, 15);
446+ mt7996_txpower_path_puts(RU484_996x2, 15);
447+ mt7996_txpower_path_puts(BF-RU484_996x2, 15);
448+ mt7996_txpower_path_puts(RU996x3, 15);
449+ mt7996_txpower_path_puts(BF-RU996x3, 15);
450+ mt7996_txpower_path_puts(RU484_996x3, 15);
451+ mt7996_txpower_path_puts(BF-RU484_996x3, 15);
452+ mt7996_txpower_path_puts(BW320/RU996x4, 15);
453+ mt7996_txpower_path_puts(BF-BW320/RU996x4, 15);
454+
455+ len += scnprintf(buf + len, size - len, "\nBackoff table: %s\n",
456+ event->backoff_table_info.backoff_en ? "enable" : "disable");
457+
458+ ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
459+
460+out:
461+ kfree(buf);
462+ kfree(event);
463+ return ret;
464+}
465+
466+static const struct file_operations mt7996_txpower_path_fops = {
467+ .read = mt7996_get_txpower_path,
468+ .open = simple_open,
469+ .owner = THIS_MODULE,
470+ .llseek = default_llseek,
471+};
472+
developerf552fec2023-03-27 11:22:06 +0800473 int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir)
474 {
475 struct mt7996_dev *dev = phy->dev;
developereb155692024-01-11 14:08:37 +0800476@@ -2480,6 +2802,10 @@ int mt7996_mtk_init_debugfs(struct mt7996_phy *phy, struct dentry *dir)
developerf552fec2023-03-27 11:22:06 +0800477
478 debugfs_create_devm_seqfile(dev->mt76.dev, "tr_info", dir,
479 mt7996_trinfo_read);
480+ debugfs_create_file("txpower_level", 0600, dir, phy, &fops_txpower_level);
481+ debugfs_create_file("txpower_info", 0600, dir, phy, &mt7996_txpower_info_fops);
482+ debugfs_create_file("txpower_sku", 0600, dir, phy, &mt7996_txpower_sku_fops);
developereb155692024-01-11 14:08:37 +0800483+ debugfs_create_file("txpower_path", 0600, dir, phy, &mt7996_txpower_path_fops);
developerf552fec2023-03-27 11:22:06 +0800484
485 debugfs_create_devm_seqfile(dev->mt76.dev, "wtbl_info", dir,
486 mt7996_wtbl_read);
487diff --git a/mt7996/mtk_mcu.c b/mt7996/mtk_mcu.c
developer1a173672023-12-21 14:49:33 +0800488index c16b25ab..e56ddd8f 100644
developerf552fec2023-03-27 11:22:06 +0800489--- a/mt7996/mtk_mcu.c
490+++ b/mt7996/mtk_mcu.c
developer1a173672023-12-21 14:49:33 +0800491@@ -12,8 +12,31 @@
developerf552fec2023-03-27 11:22:06 +0800492
493 #ifdef CONFIG_MTK_DEBUG
494
495+int mt7996_mcu_get_tx_power_info(struct mt7996_phy *phy, u8 category, void *event)
496+{
497+ struct mt7996_dev *dev = phy->dev;
498+ struct tx_power_ctrl req = {
499+ .tag = cpu_to_le16(UNI_TXPOWER_SHOW_INFO),
500+ .len = cpu_to_le16(sizeof(req) - 4),
501+ .power_ctrl_id = UNI_TXPOWER_SHOW_INFO,
502+ .show_info_category = category,
503+ .band_idx = phy->mt76->band_idx,
504+ };
505+ struct sk_buff *skb;
506+ int ret;
507
508+ ret = mt76_mcu_send_and_get_msg(&dev->mt76,
509+ MCU_WM_UNI_CMD_QUERY(TXPOWER),
510+ &req, sizeof(req), true, &skb);
511+ if (ret)
512+ return ret;
513
514+ memcpy(event, skb->data, sizeof(struct mt7996_mcu_txpower_event));
515+
516+ dev_kfree_skb(skb);
517+
518+ return 0;
519+}
520
developer1a173672023-12-21 14:49:33 +0800521 int mt7996_mcu_muru_dbg_info(struct mt7996_dev *dev, u16 item, u8 val)
522 {
developerf552fec2023-03-27 11:22:06 +0800523diff --git a/mt7996/mtk_mcu.h b/mt7996/mtk_mcu.h
developereb155692024-01-11 14:08:37 +0800524index 7f4d4e02..c30418ca 100644
developerf552fec2023-03-27 11:22:06 +0800525--- a/mt7996/mtk_mcu.h
526+++ b/mt7996/mtk_mcu.h
developereb155692024-01-11 14:08:37 +0800527@@ -14,6 +14,98 @@ enum {
developer1a173672023-12-21 14:49:33 +0800528 UNI_CMD_MURU_DBG_INFO = 0x18,
529 };
developerf552fec2023-03-27 11:22:06 +0800530
531+struct txpower_basic_info {
532+ u8 category;
533+ u8 rsv1;
534+
535+ /* basic info */
536+ u8 band_idx;
537+ u8 band;
538+
539+ /* board type info */
540+ bool is_epa;
541+ bool is_elna;
542+
543+ /* power percentage info */
544+ bool percentage_ctrl_enable;
developerbd9fa1e2023-10-16 11:04:00 +0800545+ s8 power_drop_level;
developerf552fec2023-03-27 11:22:06 +0800546+
547+ /* frond-end loss TX info */
developerbd9fa1e2023-10-16 11:04:00 +0800548+ s8 front_end_loss_tx[4];
developerf552fec2023-03-27 11:22:06 +0800549+
550+ /* frond-end loss RX info */
developerbd9fa1e2023-10-16 11:04:00 +0800551+ s8 front_end_loss_rx[4];
developerf552fec2023-03-27 11:22:06 +0800552+
553+ /* thermal info */
554+ bool thermal_compensate_enable;
developerbd9fa1e2023-10-16 11:04:00 +0800555+ s8 thermal_compensate_value;
developerf552fec2023-03-27 11:22:06 +0800556+ u8 rsv2;
557+
558+ /* TX power max/min limit info */
developerbd9fa1e2023-10-16 11:04:00 +0800559+ s8 max_power_bound;
560+ s8 min_power_bound;
developerf552fec2023-03-27 11:22:06 +0800561+
562+ /* power limit info */
563+ bool sku_enable;
564+ bool bf_backoff_enable;
565+
566+ /* MU TX power info */
567+ bool mu_tx_power_manual_enable;
developerbd9fa1e2023-10-16 11:04:00 +0800568+ s8 mu_tx_power_auto;
569+ s8 mu_tx_power_manual;
developerf552fec2023-03-27 11:22:06 +0800570+ u8 rsv3;
571+};
572+
573+struct txpower_phy_rate_info {
574+ u8 category;
575+ u8 band_idx;
576+ u8 band;
577+ u8 epa_gain;
578+
579+ /* rate power info [dBm] */
580+ s8 frame_power[MT7996_SKU_RATE_NUM][__MT_MAX_BAND];
581+
582+ /* TX power max/min limit info */
583+ s8 max_power_bound;
584+ s8 min_power_bound;
585+ u8 rsv1;
586+};
587+
developereb155692024-01-11 14:08:37 +0800588+struct txpower_backoff_table_info {
589+ u8 category;
590+ u8 band_idx;
591+ u8 band;
592+ u8 backoff_en;
593+
594+ s8 frame_power[MT7996_SKU_PATH_NUM];
595+ u8 rsv[3];
596+};
597+
developerf552fec2023-03-27 11:22:06 +0800598+struct mt7996_mcu_txpower_event {
599+ u8 _rsv[4];
600+
601+ __le16 tag;
602+ __le16 len;
603+
604+ union {
605+ struct txpower_basic_info basic_info;
606+ struct txpower_phy_rate_info phy_rate_info;
developereb155692024-01-11 14:08:37 +0800607+ struct txpower_backoff_table_info backoff_table_info;
developerf552fec2023-03-27 11:22:06 +0800608+ };
609+};
610+
611+enum txpower_category {
612+ BASIC_INFO,
developereb155692024-01-11 14:08:37 +0800613+ BACKOFF_TABLE_INFO,
614+ PHY_RATE_INFO,
developerf552fec2023-03-27 11:22:06 +0800615+};
616+
617+enum txpower_event {
618+ UNI_TXPOWER_BASIC_INFO = 0,
developereb155692024-01-11 14:08:37 +0800619+ UNI_TXPOWER_BACKOFF_TABLE_SHOW_INFO = 3,
developerf552fec2023-03-27 11:22:06 +0800620+ UNI_TXPOWER_PHY_RATE_INFO = 5,
621+};
developer1a173672023-12-21 14:49:33 +0800622+
developerf552fec2023-03-27 11:22:06 +0800623 #endif
624
developer1a173672023-12-21 14:49:33 +0800625 #endif
developerf552fec2023-03-27 11:22:06 +0800626diff --git a/mt7996/regs.h b/mt7996/regs.h
developer1a173672023-12-21 14:49:33 +0800627index 4c20a67d..e94f9a90 100644
developerf552fec2023-03-27 11:22:06 +0800628--- a/mt7996/regs.h
629+++ b/mt7996/regs.h
developer1a173672023-12-21 14:49:33 +0800630@@ -693,24 +693,31 @@ enum offs_rev {
developerbd9fa1e2023-10-16 11:04:00 +0800631 ((_wf) << 16) + (ofs))
632 #define MT_WF_PHYRX_CSD_IRPI(_band, _wf) MT_WF_PHYRX_CSD(_band, _wf, 0x1000)
developerf552fec2023-03-27 11:22:06 +0800633
634-/* PHYRX CTRL */
635-#define MT_WF_PHYRX_BAND_BASE 0x83080000
636-#define MT_WF_PHYRX_BAND(_band, ofs) (MT_WF_PHYRX_BAND_BASE + \
637+/* PHY CTRL */
638+#define MT_WF_PHY_BAND_BASE 0x83080000
639+#define MT_WF_PHY_BAND(_band, ofs) (MT_WF_PHY_BAND_BASE + \
640 ((_band) << 20) + (ofs))
641
developerbd9fa1e2023-10-16 11:04:00 +0800642-#define MT_WF_PHYRX_BAND_GID_TAB_VLD0(_band) MT_WF_PHYRX_BAND(_band, 0x1054)
643-#define MT_WF_PHYRX_BAND_GID_TAB_VLD1(_band) MT_WF_PHYRX_BAND(_band, 0x1058)
644-#define MT_WF_PHYRX_BAND_GID_TAB_POS0(_band) MT_WF_PHYRX_BAND(_band, 0x105c)
645-#define MT_WF_PHYRX_BAND_GID_TAB_POS1(_band) MT_WF_PHYRX_BAND(_band, 0x1060)
646-#define MT_WF_PHYRX_BAND_GID_TAB_POS2(_band) MT_WF_PHYRX_BAND(_band, 0x1064)
647-#define MT_WF_PHYRX_BAND_GID_TAB_POS3(_band) MT_WF_PHYRX_BAND(_band, 0x1068)
648+#define MT_WF_PHYRX_BAND_GID_TAB_VLD0(_band) MT_WF_PHY_BAND(_band, 0x1054)
649+#define MT_WF_PHYRX_BAND_GID_TAB_VLD1(_band) MT_WF_PHY_BAND(_band, 0x1058)
650+#define MT_WF_PHYRX_BAND_GID_TAB_POS0(_band) MT_WF_PHY_BAND(_band, 0x105c)
651+#define MT_WF_PHYRX_BAND_GID_TAB_POS1(_band) MT_WF_PHY_BAND(_band, 0x1060)
652+#define MT_WF_PHYRX_BAND_GID_TAB_POS2(_band) MT_WF_PHY_BAND(_band, 0x1064)
653+#define MT_WF_PHYRX_BAND_GID_TAB_POS3(_band) MT_WF_PHY_BAND(_band, 0x1068)
654
developerf552fec2023-03-27 11:22:06 +0800655-#define MT_WF_PHYRX_BAND_RX_CTRL1(_band) MT_WF_PHYRX_BAND(_band, 0x2004)
656+/* PHYRX CTRL */
657+#define MT_WF_PHYRX_BAND_RX_CTRL1(_band) MT_WF_PHY_BAND(_band, 0x2004)
658 #define MT_WF_PHYRX_BAND_RX_CTRL1_IPI_EN GENMASK(2, 0)
659 #define MT_WF_PHYRX_BAND_RX_CTRL1_STSCNT_EN GENMASK(11, 9)
660
661+/* PHYDFE CTRL */
662+#define MT_WF_PHYDFE_BAND_TPC_CTRL_STAT0(_phy) MT_WF_PHY_BAND(_phy, 0xe7a0)
663+#define MT_WF_PHY_TPC_POWER_TMAC GENMASK(15, 8)
664+#define MT_WF_PHY_TPC_POWER_RMAC GENMASK(23, 16)
665+#define MT_WF_PHY_TPC_POWER_TSSI GENMASK(31, 24)
666+
developerf552fec2023-03-27 11:22:06 +0800667 /* PHYRX CSD BAND */
668-#define MT_WF_PHYRX_CSD_BAND_RXTD12(_band) MT_WF_PHYRX_BAND(_band, 0x8230)
669+#define MT_WF_PHYRX_CSD_BAND_RXTD12(_band) MT_WF_PHY_BAND(_band, 0x8230)
670 #define MT_WF_PHYRX_CSD_BAND_RXTD12_IRPI_SW_CLR_ONLY BIT(18)
671 #define MT_WF_PHYRX_CSD_BAND_RXTD12_IRPI_SW_CLR BIT(29)
672
673--
developerbd9fa1e2023-10-16 11:04:00 +08006742.18.0
developerf552fec2023-03-27 11:22:06 +0800675