1
2
3
4
5#include <linux/debugfs.h>
6#include <linux/seq_file.h>
7#include "main.h"
8#include "sec.h"
9#include "fw.h"
10#include "debug.h"
11
12#ifdef CONFIG_RTW88_DEBUGFS
13
14struct rtw_debugfs_priv {
15 struct rtw_dev *rtwdev;
16 int (*cb_read)(struct seq_file *m, void *v);
17 ssize_t (*cb_write)(struct file *filp, const char __user *buffer,
18 size_t count, loff_t *loff);
19 union {
20 u32 cb_data;
21 u8 *buf;
22 struct {
23 u32 page_offset;
24 u32 page_num;
25 } rsvd_page;
26 struct {
27 u8 rf_path;
28 u32 rf_addr;
29 u32 rf_mask;
30 };
31 struct {
32 u32 addr;
33 u32 len;
34 } read_reg;
35 };
36};
37
38static int rtw_debugfs_single_show(struct seq_file *m, void *v)
39{
40 struct rtw_debugfs_priv *debugfs_priv = m->private;
41
42 return debugfs_priv->cb_read(m, v);
43}
44
45static ssize_t rtw_debugfs_common_write(struct file *filp,
46 const char __user *buffer,
47 size_t count, loff_t *loff)
48{
49 struct rtw_debugfs_priv *debugfs_priv = filp->private_data;
50
51 return debugfs_priv->cb_write(filp, buffer, count, loff);
52}
53
54static ssize_t rtw_debugfs_single_write(struct file *filp,
55 const char __user *buffer,
56 size_t count, loff_t *loff)
57{
58 struct seq_file *seqpriv = (struct seq_file *)filp->private_data;
59 struct rtw_debugfs_priv *debugfs_priv = seqpriv->private;
60
61 return debugfs_priv->cb_write(filp, buffer, count, loff);
62}
63
64static int rtw_debugfs_single_open_rw(struct inode *inode, struct file *filp)
65{
66 return single_open(filp, rtw_debugfs_single_show, inode->i_private);
67}
68
69static int rtw_debugfs_close(struct inode *inode, struct file *filp)
70{
71 return 0;
72}
73
74static const struct file_operations file_ops_single_r = {
75 .owner = THIS_MODULE,
76 .open = rtw_debugfs_single_open_rw,
77 .read = seq_read,
78 .llseek = seq_lseek,
79 .release = seq_release,
80};
81
82static const struct file_operations file_ops_single_rw = {
83 .owner = THIS_MODULE,
84 .open = rtw_debugfs_single_open_rw,
85 .release = single_release,
86 .read = seq_read,
87 .llseek = seq_lseek,
88 .write = rtw_debugfs_single_write,
89};
90
91static const struct file_operations file_ops_common_write = {
92 .owner = THIS_MODULE,
93 .write = rtw_debugfs_common_write,
94 .open = simple_open,
95 .release = rtw_debugfs_close,
96};
97
98static int rtw_debugfs_get_read_reg(struct seq_file *m, void *v)
99{
100 struct rtw_debugfs_priv *debugfs_priv = m->private;
101 struct rtw_dev *rtwdev = debugfs_priv->rtwdev;
102 u32 val, len, addr;
103
104 len = debugfs_priv->read_reg.len;
105 addr = debugfs_priv->read_reg.addr;
106 switch (len) {
107 case 1:
108 val = rtw_read8(rtwdev, addr);
109 seq_printf(m, "reg 0x%03x: 0x%02x\n", addr, val);
110 break;
111 case 2:
112 val = rtw_read16(rtwdev, addr);
113 seq_printf(m, "reg 0x%03x: 0x%04x\n", addr, val);
114 break;
115 case 4:
116 val = rtw_read32(rtwdev, addr);
117 seq_printf(m, "reg 0x%03x: 0x%08x\n", addr, val);
118 break;
119 }
120 return 0;
121}
122
123static int rtw_debugfs_get_rf_read(struct seq_file *m, void *v)
124{
125 struct rtw_debugfs_priv *debugfs_priv = m->private;
126 struct rtw_dev *rtwdev = debugfs_priv->rtwdev;
127 u32 val, addr, mask;
128 u8 path;
129
130 path = debugfs_priv->rf_path;
131 addr = debugfs_priv->rf_addr;
132 mask = debugfs_priv->rf_mask;
133
134 val = rtw_read_rf(rtwdev, path, addr, mask);
135
136 seq_printf(m, "rf_read path:%d addr:0x%08x mask:0x%08x val=0x%08x\n",
137 path, addr, mask, val);
138
139 return 0;
140}
141
142static int rtw_debugfs_copy_from_user(char tmp[], int size,
143 const char __user *buffer, size_t count,
144 int num)
145{
146 int tmp_len;
147
148 if (count < num)
149 return -EFAULT;
150
151 tmp_len = (count > size - 1 ? size - 1 : count);
152
153 if (!buffer || copy_from_user(tmp, buffer, tmp_len))
154 return count;
155
156 tmp[tmp_len] = '\0';
157
158 return 0;
159}
160
161static ssize_t rtw_debugfs_set_read_reg(struct file *filp,
162 const char __user *buffer,
163 size_t count, loff_t *loff)
164{
165 struct seq_file *seqpriv = (struct seq_file *)filp->private_data;
166 struct rtw_debugfs_priv *debugfs_priv = seqpriv->private;
167 struct rtw_dev *rtwdev = debugfs_priv->rtwdev;
168 char tmp[32 + 1];
169 u32 addr, len;
170 int num;
171
172 rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 2);
173
174 num = sscanf(tmp, "%x %x", &addr, &len);
175
176 if (num != 2)
177 return count;
178
179 if (len != 1 && len != 2 && len != 4) {
180 rtw_warn(rtwdev, "read reg setting wrong len\n");
181 return -EINVAL;
182 }
183 debugfs_priv->read_reg.addr = addr;
184 debugfs_priv->read_reg.len = len;
185
186 return count;
187}
188
189static int rtw_debugfs_get_dump_cam(struct seq_file *m, void *v)
190{
191 struct rtw_debugfs_priv *debugfs_priv = m->private;
192 struct rtw_dev *rtwdev = debugfs_priv->rtwdev;
193 u32 val, command;
194 u32 hw_key_idx = debugfs_priv->cb_data << RTW_SEC_CAM_ENTRY_SHIFT;
195 u32 read_cmd = RTW_SEC_CMD_POLLING;
196 int i;
197
198 seq_printf(m, "cam entry%d\n", debugfs_priv->cb_data);
199 seq_puts(m, "0x0 0x1 0x2 0x3 ");
200 seq_puts(m, "0x4 0x5\n");
201 mutex_lock(&rtwdev->mutex);
202 for (i = 0; i <= 5; i++) {
203 command = read_cmd | (hw_key_idx + i);
204 rtw_write32(rtwdev, RTW_SEC_CMD_REG, command);
205 val = rtw_read32(rtwdev, RTW_SEC_READ_REG);
206 seq_printf(m, "%8.8x", val);
207 if (i < 2)
208 seq_puts(m, " ");
209 }
210 seq_puts(m, "\n");
211 mutex_unlock(&rtwdev->mutex);
212 return 0;
213}
214
215static int rtw_debugfs_get_rsvd_page(struct seq_file *m, void *v)
216{
217 struct rtw_debugfs_priv *debugfs_priv = m->private;
218 struct rtw_dev *rtwdev = debugfs_priv->rtwdev;
219 u8 page_size = rtwdev->chip->page_size;
220 u32 buf_size = debugfs_priv->rsvd_page.page_num * page_size;
221 u32 offset = debugfs_priv->rsvd_page.page_offset * page_size;
222 u8 *buf;
223 int i;
224 int ret;
225
226 buf = vzalloc(buf_size);
227 if (!buf)
228 return -ENOMEM;
229
230 ret = rtw_dump_drv_rsvd_page(rtwdev, offset, buf_size, (u32 *)buf);
231 if (ret) {
232 rtw_err(rtwdev, "failed to dump rsvd page\n");
233 vfree(buf);
234 return ret;
235 }
236
237 for (i = 0 ; i < buf_size ; i += 8) {
238 if (i % page_size == 0)
239 seq_printf(m, "PAGE %d\n", (i + offset) / page_size);
240 seq_printf(m, "%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n",
241 *(buf + i), *(buf + i + 1),
242 *(buf + i + 2), *(buf + i + 3),
243 *(buf + i + 4), *(buf + i + 5),
244 *(buf + i + 6), *(buf + i + 7));
245 }
246 vfree(buf);
247
248 return 0;
249}
250
251static ssize_t rtw_debugfs_set_rsvd_page(struct file *filp,
252 const char __user *buffer,
253 size_t count, loff_t *loff)
254{
255 struct seq_file *seqpriv = (struct seq_file *)filp->private_data;
256 struct rtw_debugfs_priv *debugfs_priv = seqpriv->private;
257 struct rtw_dev *rtwdev = debugfs_priv->rtwdev;
258 char tmp[32 + 1];
259 u32 offset, page_num;
260 int num;
261
262 rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 2);
263
264 num = sscanf(tmp, "%d %d", &offset, &page_num);
265
266 if (num != 2) {
267 rtw_warn(rtwdev, "invalid arguments\n");
268 return num;
269 }
270
271 debugfs_priv->rsvd_page.page_offset = offset;
272 debugfs_priv->rsvd_page.page_num = page_num;
273
274 return count;
275}
276
277static ssize_t rtw_debugfs_set_single_input(struct file *filp,
278 const char __user *buffer,
279 size_t count, loff_t *loff)
280{
281 struct seq_file *seqpriv = (struct seq_file *)filp->private_data;
282 struct rtw_debugfs_priv *debugfs_priv = seqpriv->private;
283 struct rtw_dev *rtwdev = debugfs_priv->rtwdev;
284 char tmp[32 + 1];
285 u32 input;
286 int num;
287
288 rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 1);
289
290 num = kstrtoint(tmp, 0, &input);
291
292 if (num) {
293 rtw_warn(rtwdev, "kstrtoint failed\n");
294 return num;
295 }
296
297 debugfs_priv->cb_data = input;
298
299 return count;
300}
301
302static ssize_t rtw_debugfs_set_write_reg(struct file *filp,
303 const char __user *buffer,
304 size_t count, loff_t *loff)
305{
306 struct rtw_debugfs_priv *debugfs_priv = filp->private_data;
307 struct rtw_dev *rtwdev = debugfs_priv->rtwdev;
308 char tmp[32 + 1];
309 u32 addr, val, len;
310 int num;
311
312 rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 3);
313
314
315 num = sscanf(tmp, "%x %x %x", &addr, &val, &len);
316
317 if (num != 3)
318 return count;
319
320 switch (len) {
321 case 1:
322 rtw_dbg(rtwdev, RTW_DBG_DEBUGFS,
323 "reg write8 0x%03x: 0x%08x\n", addr, val);
324 rtw_write8(rtwdev, addr, (u8)val);
325 break;
326 case 2:
327 rtw_dbg(rtwdev, RTW_DBG_DEBUGFS,
328 "reg write16 0x%03x: 0x%08x\n", addr, val);
329 rtw_write16(rtwdev, addr, (u16)val);
330 break;
331 case 4:
332 rtw_dbg(rtwdev, RTW_DBG_DEBUGFS,
333 "reg write32 0x%03x: 0x%08x\n", addr, val);
334 rtw_write32(rtwdev, addr, (u32)val);
335 break;
336 default:
337 rtw_dbg(rtwdev, RTW_DBG_DEBUGFS,
338 "error write length = %d\n", len);
339 break;
340 }
341
342 return count;
343}
344
345static ssize_t rtw_debugfs_set_rf_write(struct file *filp,
346 const char __user *buffer,
347 size_t count, loff_t *loff)
348{
349 struct rtw_debugfs_priv *debugfs_priv = filp->private_data;
350 struct rtw_dev *rtwdev = debugfs_priv->rtwdev;
351 char tmp[32 + 1];
352 u32 path, addr, mask, val;
353 int num;
354
355 rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 4);
356
357 num = sscanf(tmp, "%x %x %x %x", &path, &addr, &mask, &val);
358
359 if (num != 4) {
360 rtw_warn(rtwdev, "invalid args, [path] [addr] [mask] [val]\n");
361 return count;
362 }
363
364 rtw_write_rf(rtwdev, path, addr, mask, val);
365 rtw_dbg(rtwdev, RTW_DBG_DEBUGFS,
366 "write_rf path:%d addr:0x%08x mask:0x%08x, val:0x%08x\n",
367 path, addr, mask, val);
368
369 return count;
370}
371
372static ssize_t rtw_debugfs_set_rf_read(struct file *filp,
373 const char __user *buffer,
374 size_t count, loff_t *loff)
375{
376 struct seq_file *seqpriv = (struct seq_file *)filp->private_data;
377 struct rtw_debugfs_priv *debugfs_priv = seqpriv->private;
378 struct rtw_dev *rtwdev = debugfs_priv->rtwdev;
379 char tmp[32 + 1];
380 u32 path, addr, mask;
381 int num;
382
383 rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 3);
384
385 num = sscanf(tmp, "%x %x %x", &path, &addr, &mask);
386
387 if (num != 3) {
388 rtw_warn(rtwdev, "invalid args, [path] [addr] [mask] [val]\n");
389 return count;
390 }
391
392 debugfs_priv->rf_path = path;
393 debugfs_priv->rf_addr = addr;
394 debugfs_priv->rf_mask = mask;
395
396 return count;
397}
398
399static int rtw_debug_get_mac_page(struct seq_file *m, void *v)
400{
401 struct rtw_debugfs_priv *debugfs_priv = m->private;
402 struct rtw_dev *rtwdev = debugfs_priv->rtwdev;
403 u32 val;
404 u32 page = debugfs_priv->cb_data;
405 int i, n;
406 int max = 0xff;
407
408 val = rtw_read32(rtwdev, debugfs_priv->cb_data);
409 for (n = 0; n <= max; ) {
410 seq_printf(m, "\n%8.8x ", n + page);
411 for (i = 0; i < 4 && n <= max; i++, n += 4)
412 seq_printf(m, "%8.8x ",
413 rtw_read32(rtwdev, (page | n)));
414 }
415 seq_puts(m, "\n");
416 return 0;
417}
418
419static int rtw_debug_get_bb_page(struct seq_file *m, void *v)
420{
421 struct rtw_debugfs_priv *debugfs_priv = m->private;
422 struct rtw_dev *rtwdev = debugfs_priv->rtwdev;
423 u32 val;
424 u32 page = debugfs_priv->cb_data;
425 int i, n;
426 int max = 0xff;
427
428 val = rtw_read32(rtwdev, debugfs_priv->cb_data);
429 for (n = 0; n <= max; ) {
430 seq_printf(m, "\n%8.8x ", n + page);
431 for (i = 0; i < 4 && n <= max; i++, n += 4)
432 seq_printf(m, "%8.8x ",
433 rtw_read32(rtwdev, (page | n)));
434 }
435 seq_puts(m, "\n");
436 return 0;
437}
438
439static int rtw_debug_get_rf_dump(struct seq_file *m, void *v)
440{
441 struct rtw_debugfs_priv *debugfs_priv = m->private;
442 struct rtw_dev *rtwdev = debugfs_priv->rtwdev;
443 u32 addr, offset, data;
444 u8 path;
445
446 for (path = 0; path < rtwdev->hal.rf_path_num; path++) {
447 seq_printf(m, "RF path:%d\n", path);
448 for (addr = 0; addr < 0x100; addr += 4) {
449 seq_printf(m, "%8.8x ", addr);
450 for (offset = 0; offset < 4; offset++) {
451 data = rtw_read_rf(rtwdev, path, addr + offset,
452 0xffffffff);
453 seq_printf(m, "%8.8x ", data);
454 }
455 seq_puts(m, "\n");
456 }
457 seq_puts(m, "\n");
458 }
459
460 return 0;
461}
462
463#define rtw_debug_impl_mac(page, addr) \
464static struct rtw_debugfs_priv rtw_debug_priv_mac_ ##page = { \
465 .cb_read = rtw_debug_get_mac_page, \
466 .cb_data = addr, \
467}
468
469rtw_debug_impl_mac(0, 0x0000);
470rtw_debug_impl_mac(1, 0x0100);
471rtw_debug_impl_mac(2, 0x0200);
472rtw_debug_impl_mac(3, 0x0300);
473rtw_debug_impl_mac(4, 0x0400);
474rtw_debug_impl_mac(5, 0x0500);
475rtw_debug_impl_mac(6, 0x0600);
476rtw_debug_impl_mac(7, 0x0700);
477rtw_debug_impl_mac(10, 0x1000);
478rtw_debug_impl_mac(11, 0x1100);
479rtw_debug_impl_mac(12, 0x1200);
480rtw_debug_impl_mac(13, 0x1300);
481rtw_debug_impl_mac(14, 0x1400);
482rtw_debug_impl_mac(15, 0x1500);
483rtw_debug_impl_mac(16, 0x1600);
484rtw_debug_impl_mac(17, 0x1700);
485
486#define rtw_debug_impl_bb(page, addr) \
487static struct rtw_debugfs_priv rtw_debug_priv_bb_ ##page = { \
488 .cb_read = rtw_debug_get_bb_page, \
489 .cb_data = addr, \
490}
491
492rtw_debug_impl_bb(8, 0x0800);
493rtw_debug_impl_bb(9, 0x0900);
494rtw_debug_impl_bb(a, 0x0a00);
495rtw_debug_impl_bb(b, 0x0b00);
496rtw_debug_impl_bb(c, 0x0c00);
497rtw_debug_impl_bb(d, 0x0d00);
498rtw_debug_impl_bb(e, 0x0e00);
499rtw_debug_impl_bb(f, 0x0f00);
500rtw_debug_impl_bb(18, 0x1800);
501rtw_debug_impl_bb(19, 0x1900);
502rtw_debug_impl_bb(1a, 0x1a00);
503rtw_debug_impl_bb(1b, 0x1b00);
504rtw_debug_impl_bb(1c, 0x1c00);
505rtw_debug_impl_bb(1d, 0x1d00);
506rtw_debug_impl_bb(1e, 0x1e00);
507rtw_debug_impl_bb(1f, 0x1f00);
508rtw_debug_impl_bb(2c, 0x2c00);
509rtw_debug_impl_bb(2d, 0x2d00);
510rtw_debug_impl_bb(40, 0x4000);
511rtw_debug_impl_bb(41, 0x4100);
512
513static struct rtw_debugfs_priv rtw_debug_priv_rf_dump = {
514 .cb_read = rtw_debug_get_rf_dump,
515};
516
517static struct rtw_debugfs_priv rtw_debug_priv_write_reg = {
518 .cb_write = rtw_debugfs_set_write_reg,
519};
520
521static struct rtw_debugfs_priv rtw_debug_priv_rf_write = {
522 .cb_write = rtw_debugfs_set_rf_write,
523};
524
525static struct rtw_debugfs_priv rtw_debug_priv_rf_read = {
526 .cb_write = rtw_debugfs_set_rf_read,
527 .cb_read = rtw_debugfs_get_rf_read,
528};
529
530static struct rtw_debugfs_priv rtw_debug_priv_read_reg = {
531 .cb_write = rtw_debugfs_set_read_reg,
532 .cb_read = rtw_debugfs_get_read_reg,
533};
534
535static struct rtw_debugfs_priv rtw_debug_priv_dump_cam = {
536 .cb_write = rtw_debugfs_set_single_input,
537 .cb_read = rtw_debugfs_get_dump_cam,
538};
539
540static struct rtw_debugfs_priv rtw_debug_priv_rsvd_page = {
541 .cb_write = rtw_debugfs_set_rsvd_page,
542 .cb_read = rtw_debugfs_get_rsvd_page,
543};
544
545#define rtw_debugfs_add_core(name, mode, fopname, parent) \
546 do { \
547 rtw_debug_priv_ ##name.rtwdev = rtwdev; \
548 if (!debugfs_create_file(#name, mode, \
549 parent, &rtw_debug_priv_ ##name,\
550 &file_ops_ ##fopname)) \
551 pr_debug("Unable to initialize debugfs:%s\n", \
552 #name); \
553 } while (0)
554
555#define rtw_debugfs_add_w(name) \
556 rtw_debugfs_add_core(name, S_IFREG | 0222, common_write, debugfs_topdir)
557#define rtw_debugfs_add_rw(name) \
558 rtw_debugfs_add_core(name, S_IFREG | 0666, single_rw, debugfs_topdir)
559#define rtw_debugfs_add_r(name) \
560 rtw_debugfs_add_core(name, S_IFREG | 0444, single_r, debugfs_topdir)
561
562void rtw_debugfs_init(struct rtw_dev *rtwdev)
563{
564 struct dentry *debugfs_topdir = rtwdev->debugfs;
565
566 debugfs_topdir = debugfs_create_dir("rtw88",
567 rtwdev->hw->wiphy->debugfsdir);
568 rtw_debugfs_add_w(write_reg);
569 rtw_debugfs_add_rw(read_reg);
570 rtw_debugfs_add_w(rf_write);
571 rtw_debugfs_add_rw(rf_read);
572 rtw_debugfs_add_rw(dump_cam);
573 rtw_debugfs_add_rw(rsvd_page);
574 rtw_debugfs_add_r(mac_0);
575 rtw_debugfs_add_r(mac_1);
576 rtw_debugfs_add_r(mac_2);
577 rtw_debugfs_add_r(mac_3);
578 rtw_debugfs_add_r(mac_4);
579 rtw_debugfs_add_r(mac_5);
580 rtw_debugfs_add_r(mac_6);
581 rtw_debugfs_add_r(mac_7);
582 rtw_debugfs_add_r(bb_8);
583 rtw_debugfs_add_r(bb_9);
584 rtw_debugfs_add_r(bb_a);
585 rtw_debugfs_add_r(bb_b);
586 rtw_debugfs_add_r(bb_c);
587 rtw_debugfs_add_r(bb_d);
588 rtw_debugfs_add_r(bb_e);
589 rtw_debugfs_add_r(bb_f);
590 rtw_debugfs_add_r(mac_10);
591 rtw_debugfs_add_r(mac_11);
592 rtw_debugfs_add_r(mac_12);
593 rtw_debugfs_add_r(mac_13);
594 rtw_debugfs_add_r(mac_14);
595 rtw_debugfs_add_r(mac_15);
596 rtw_debugfs_add_r(mac_16);
597 rtw_debugfs_add_r(mac_17);
598 rtw_debugfs_add_r(bb_18);
599 rtw_debugfs_add_r(bb_19);
600 rtw_debugfs_add_r(bb_1a);
601 rtw_debugfs_add_r(bb_1b);
602 rtw_debugfs_add_r(bb_1c);
603 rtw_debugfs_add_r(bb_1d);
604 rtw_debugfs_add_r(bb_1e);
605 rtw_debugfs_add_r(bb_1f);
606 if (rtwdev->chip->id == RTW_CHIP_TYPE_8822C) {
607 rtw_debugfs_add_r(bb_2c);
608 rtw_debugfs_add_r(bb_2d);
609 rtw_debugfs_add_r(bb_40);
610 rtw_debugfs_add_r(bb_41);
611 }
612 rtw_debugfs_add_r(rf_dump);
613}
614
615#endif
616
617#ifdef CONFIG_RTW88_DEBUG
618
619void __rtw_dbg(struct rtw_dev *rtwdev, enum rtw_debug_mask mask,
620 const char *fmt, ...)
621{
622 struct va_format vaf = {
623 .fmt = fmt,
624 };
625 va_list args;
626
627 va_start(args, fmt);
628 vaf.va = &args;
629
630 if (rtw_debug_mask & mask)
631 dev_printk(KERN_DEBUG, rtwdev->dev, "%pV", &vaf);
632
633 va_end(args);
634}
635EXPORT_SYMBOL(__rtw_dbg);
636
637#endif
638