Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.6.
  1// SPDX-License-Identifier: ISC
  2/* Copyright (C) 2023 MediaTek Inc. */
  3
  4#include "mt7925.h"
  5#include "mcu.h"
  6
  7static int
  8mt7925_reg_set(void *data, u64 val)
  9{
 10	struct mt792x_dev *dev = data;
 11	u32 regval = val;
 12
 13	mt792x_mutex_acquire(dev);
 14	mt7925_mcu_regval(dev, dev->mt76.debugfs_reg, &regval, true);
 15	mt792x_mutex_release(dev);
 16
 17	return 0;
 18}
 19
 20static int
 21mt7925_reg_get(void *data, u64 *val)
 22{
 23	struct mt792x_dev *dev = data;
 24	u32 regval;
 25	int ret;
 26
 27	mt792x_mutex_acquire(dev);
 28	ret = mt7925_mcu_regval(dev, dev->mt76.debugfs_reg, &regval, false);
 29	mt792x_mutex_release(dev);
 30	if (!ret)
 31		*val = regval;
 32
 33	return 0;
 34}
 35
 36DEFINE_DEBUGFS_ATTRIBUTE(fops_regval, mt7925_reg_get, mt7925_reg_set,
 37			 "0x%08llx\n");
 38static int
 39mt7925_fw_debug_set(void *data, u64 val)
 40{
 41	struct mt792x_dev *dev = data;
 42
 43	mt792x_mutex_acquire(dev);
 44
 45	dev->fw_debug = (u8)val;
 46	mt7925_mcu_fw_log_2_host(dev, dev->fw_debug);
 47
 48	mt792x_mutex_release(dev);
 49
 50	return 0;
 51}
 52
 53static int
 54mt7925_fw_debug_get(void *data, u64 *val)
 55{
 56	struct mt792x_dev *dev = data;
 57
 58	*val = dev->fw_debug;
 59
 60	return 0;
 61}
 62
 63DEFINE_DEBUGFS_ATTRIBUTE(fops_fw_debug, mt7925_fw_debug_get,
 64			 mt7925_fw_debug_set, "%lld\n");
 65
 66DEFINE_SHOW_ATTRIBUTE(mt792x_tx_stats);
 67
 68static void
 69mt7925_seq_puts_array(struct seq_file *file, const char *str,
 70		      s8 val[][2], int len, u8 band_idx)
 71{
 72	int i;
 73
 74	seq_printf(file, "%-22s:", str);
 75	for (i = 0; i < len; i++)
 76		if (val[i][band_idx] == 127)
 77			seq_printf(file, " %6s", "N.A");
 78		else
 79			seq_printf(file, " %6d", val[i][band_idx]);
 80	seq_puts(file, "\n");
 81}
 82
 83#define mt7925_print_txpwr_entry(prefix, rate, idx)	\
 84({							\
 85	mt7925_seq_puts_array(s, #prefix " (tmac)",	\
 86			      txpwr->rate,		\
 87			      ARRAY_SIZE(txpwr->rate),	\
 88			      idx);			\
 89})
 90
 91static inline void
 92mt7925_eht_txpwr(struct seq_file *s, struct mt7925_txpwr *txpwr, u8 band_idx)
 93{
 94	seq_printf(s, "%-22s  %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s\n",
 95		   " ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5",
 96		   "mcs6", "mcs7", "mcs8", "mcs9", "mcs10", "mcs11",
 97		   "mcs12", "mcs13", "mcs14", "mcs15");
 98	mt7925_print_txpwr_entry(EHT26, eht26, band_idx);
 99	mt7925_print_txpwr_entry(EHT52, eht52, band_idx);
100	mt7925_print_txpwr_entry(EHT106, eht106, band_idx);
101	mt7925_print_txpwr_entry(EHT242, eht242, band_idx);
102	mt7925_print_txpwr_entry(EHT484, eht484, band_idx);
103
104	mt7925_print_txpwr_entry(EHT996, eht996, band_idx);
105	mt7925_print_txpwr_entry(EHT996x2, eht996x2, band_idx);
106	mt7925_print_txpwr_entry(EHT996x4, eht996x4, band_idx);
107	mt7925_print_txpwr_entry(EHT26_52, eht26_52, band_idx);
108	mt7925_print_txpwr_entry(EHT26_106, eht26_106, band_idx);
109	mt7925_print_txpwr_entry(EHT484_242, eht484_242, band_idx);
110	mt7925_print_txpwr_entry(EHT996_484, eht996_484, band_idx);
111	mt7925_print_txpwr_entry(EHT996_484_242, eht996_484_242, band_idx);
112	mt7925_print_txpwr_entry(EHT996x2_484, eht996x2_484, band_idx);
113	mt7925_print_txpwr_entry(EHT996x3, eht996x3, band_idx);
114	mt7925_print_txpwr_entry(EHT996x3_484, eht996x3_484, band_idx);
115}
116
117static int
118mt7925_txpwr(struct seq_file *s, void *data)
119{
120	struct mt792x_dev *dev = dev_get_drvdata(s->private);
121	struct mt7925_txpwr *txpwr = NULL;
122	u8 band_idx = dev->mphy.band_idx;
123	int ret = 0;
124
125	txpwr = devm_kmalloc(dev->mt76.dev, sizeof(*txpwr), GFP_KERNEL);
126
127	if (!txpwr)
128		return -ENOMEM;
129
130	mt792x_mutex_acquire(dev);
131	ret = mt7925_get_txpwr_info(dev, band_idx, txpwr);
132	mt792x_mutex_release(dev);
133
134	if (ret)
135		goto out;
136
137	seq_printf(s, "%-22s  %6s %6s %6s %6s\n",
138		   " ", "1m", "2m", "5m", "11m");
139	mt7925_print_txpwr_entry(CCK, cck, band_idx);
140
141	seq_printf(s, "%-22s  %6s %6s %6s %6s %6s %6s %6s %6s\n",
142		   " ", "6m", "9m", "12m", "18m", "24m", "36m",
143		   "48m", "54m");
144	mt7925_print_txpwr_entry(OFDM, ofdm, band_idx);
145
146	seq_printf(s, "%-22s  %6s %6s %6s %6s %6s %6s %6s %6s\n",
147		   " ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5",
148		   "mcs6", "mcs7");
149	mt7925_print_txpwr_entry(HT20, ht20, band_idx);
150
151	seq_printf(s, "%-22s  %6s %6s %6s %6s %6s %6s %6s %6s %6s\n",
152		   " ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5",
153		   "mcs6", "mcs7", "mcs32");
154	mt7925_print_txpwr_entry(HT40, ht40, band_idx);
155
156	seq_printf(s, "%-22s  %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s\n",
157		   " ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5",
158		   "mcs6", "mcs7", "mcs8", "mcs9", "mcs10", "mcs11");
159	mt7925_print_txpwr_entry(VHT20, vht20, band_idx);
160	mt7925_print_txpwr_entry(VHT40, vht40, band_idx);
161
162	mt7925_print_txpwr_entry(VHT80, vht80, band_idx);
163	mt7925_print_txpwr_entry(VHT160, vht160, band_idx);
164
165	mt7925_print_txpwr_entry(HE26, he26, band_idx);
166	mt7925_print_txpwr_entry(HE52, he52, band_idx);
167	mt7925_print_txpwr_entry(HE106, he106, band_idx);
168	mt7925_print_txpwr_entry(HE242, he242, band_idx);
169	mt7925_print_txpwr_entry(HE484, he484, band_idx);
170
171	mt7925_print_txpwr_entry(HE996, he996, band_idx);
172	mt7925_print_txpwr_entry(HE996x2, he996x2, band_idx);
173
174	mt7925_eht_txpwr(s, txpwr, band_idx);
175
176out:
177	devm_kfree(dev->mt76.dev, txpwr);
178	return ret;
179}
180
181static int
182mt7925_pm_set(void *data, u64 val)
183{
184	struct mt792x_dev *dev = data;
185	struct mt76_connac_pm *pm = &dev->pm;
186
187	if (mt76_is_usb(&dev->mt76))
188		return -EOPNOTSUPP;
189
190	mutex_lock(&dev->mt76.mutex);
191
192	if (val == pm->enable_user)
193		goto out;
194
195	if (!pm->enable_user) {
196		pm->stats.last_wake_event = jiffies;
197		pm->stats.last_doze_event = jiffies;
198	}
199	/* make sure the chip is awake here and ps_work is scheduled
200	 * just at end of the this routine.
201	 */
202	pm->enable = false;
203	mt76_connac_pm_wake(&dev->mphy, pm);
204
205	pm->enable_user = val;
206	mt7925_set_runtime_pm(dev);
207	mt76_connac_power_save_sched(&dev->mphy, pm);
208out:
209	mutex_unlock(&dev->mt76.mutex);
210
211	return 0;
212}
213
214static int
215mt7925_pm_get(void *data, u64 *val)
216{
217	struct mt792x_dev *dev = data;
218
219	*val = dev->pm.enable_user;
220
221	return 0;
222}
223
224DEFINE_DEBUGFS_ATTRIBUTE(fops_pm, mt7925_pm_get, mt7925_pm_set, "%lld\n");
225
226static int
227mt7925_deep_sleep_set(void *data, u64 val)
228{
229	struct mt792x_dev *dev = data;
230	struct mt76_connac_pm *pm = &dev->pm;
231	bool monitor = !!(dev->mphy.hw->conf.flags & IEEE80211_CONF_MONITOR);
232	bool enable = !!val;
233
234	if (mt76_is_usb(&dev->mt76))
235		return -EOPNOTSUPP;
236
237	mt792x_mutex_acquire(dev);
238	if (pm->ds_enable_user == enable)
239		goto out;
240
241	pm->ds_enable_user = enable;
242	pm->ds_enable = enable && !monitor;
243	mt7925_mcu_set_deep_sleep(dev, pm->ds_enable);
244out:
245	mt792x_mutex_release(dev);
246
247	return 0;
248}
249
250static int
251mt7925_deep_sleep_get(void *data, u64 *val)
252{
253	struct mt792x_dev *dev = data;
254
255	*val = dev->pm.ds_enable_user;
256
257	return 0;
258}
259
260DEFINE_DEBUGFS_ATTRIBUTE(fops_ds, mt7925_deep_sleep_get,
261			 mt7925_deep_sleep_set, "%lld\n");
262
263DEFINE_DEBUGFS_ATTRIBUTE(fops_pm_idle_timeout, mt792x_pm_idle_timeout_get,
264			 mt792x_pm_idle_timeout_set, "%lld\n");
265
266static int mt7925_chip_reset(void *data, u64 val)
267{
268	struct mt792x_dev *dev = data;
269	int ret = 0;
270
271	switch (val) {
272	case 1:
273		/* Reset wifisys directly. */
274		mt792x_reset(&dev->mt76);
275		break;
276	default:
277		/* Collect the core dump before reset wifisys. */
278		mt792x_mutex_acquire(dev);
279		ret = mt7925_mcu_chip_config(dev, "assert");
280		mt792x_mutex_release(dev);
281		break;
282	}
283
284	return ret;
285}
286
287DEFINE_DEBUGFS_ATTRIBUTE(fops_reset, NULL, mt7925_chip_reset, "%lld\n");
288
289int mt7925_init_debugfs(struct mt792x_dev *dev)
290{
291	struct dentry *dir;
292
293	dir = mt76_register_debugfs_fops(&dev->mphy, &fops_regval);
294	if (!dir)
295		return -ENOMEM;
296
297	if (mt76_is_mmio(&dev->mt76))
298		debugfs_create_devm_seqfile(dev->mt76.dev, "xmit-queues",
299					    dir, mt792x_queues_read);
300	else
301		debugfs_create_devm_seqfile(dev->mt76.dev, "xmit-queues",
302					    dir, mt76_queues_read);
303
304	debugfs_create_devm_seqfile(dev->mt76.dev, "acq", dir,
305				    mt792x_queues_acq);
306	debugfs_create_devm_seqfile(dev->mt76.dev, "txpower_sku", dir,
307				    mt7925_txpwr);
308	debugfs_create_file("tx_stats", 0400, dir, dev, &mt792x_tx_stats_fops);
309	debugfs_create_file("fw_debug", 0600, dir, dev, &fops_fw_debug);
310	debugfs_create_file("runtime-pm", 0600, dir, dev, &fops_pm);
311	debugfs_create_file("idle-timeout", 0600, dir, dev,
312			    &fops_pm_idle_timeout);
313	debugfs_create_file("chip_reset", 0600, dir, dev, &fops_reset);
314	debugfs_create_devm_seqfile(dev->mt76.dev, "runtime_pm_stats", dir,
315				    mt792x_pm_stats);
316	debugfs_create_file("deep-sleep", 0600, dir, dev, &fops_ds);
317
318	return 0;
319}