1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/seq_file.h>
3 #include <linux/debugfs.h>
4 
5 #include "nitrox_csr.h"
6 #include "nitrox_dev.h"
7 
8 static int firmware_show(struct seq_file *s, void *v)
9 {
10 	struct nitrox_device *ndev = s->private;
11 
12 	seq_printf(s, "Version: %s\n", ndev->hw.fw_name);
13 	return 0;
14 }
15 
16 static int firmware_open(struct inode *inode, struct file *file)
17 {
18 	return single_open(file, firmware_show, inode->i_private);
19 }
20 
21 static const struct file_operations firmware_fops = {
22 	.owner = THIS_MODULE,
23 	.open = firmware_open,
24 	.read = seq_read,
25 	.llseek = seq_lseek,
26 	.release = single_release,
27 };
28 
29 static int device_show(struct seq_file *s, void *v)
30 {
31 	struct nitrox_device *ndev = s->private;
32 
33 	seq_printf(s, "NITROX [%d]\n", ndev->idx);
34 	seq_printf(s, "  Part Name: %s\n", ndev->hw.partname);
35 	seq_printf(s, "  Frequency: %d MHz\n", ndev->hw.freq);
36 	seq_printf(s, "  Device ID: 0x%0x\n", ndev->hw.device_id);
37 	seq_printf(s, "  Revision ID: 0x%0x\n", ndev->hw.revision_id);
38 	seq_printf(s, "  Cores: [AE=%u  SE=%u  ZIP=%u]\n",
39 		   ndev->hw.ae_cores, ndev->hw.se_cores, ndev->hw.zip_cores);
40 
41 	return 0;
42 }
43 
44 static int nitrox_open(struct inode *inode, struct file *file)
45 {
46 	return single_open(file, device_show, inode->i_private);
47 }
48 
49 static const struct file_operations nitrox_fops = {
50 	.owner = THIS_MODULE,
51 	.open = nitrox_open,
52 	.read = seq_read,
53 	.llseek = seq_lseek,
54 	.release = single_release,
55 };
56 
57 static int stats_show(struct seq_file *s, void *v)
58 {
59 	struct nitrox_device *ndev = s->private;
60 
61 	seq_printf(s, "NITROX [%d] Request Statistics\n", ndev->idx);
62 	seq_printf(s, "  Posted: %llu\n",
63 		   (u64)atomic64_read(&ndev->stats.posted));
64 	seq_printf(s, "  Completed: %llu\n",
65 		   (u64)atomic64_read(&ndev->stats.completed));
66 	seq_printf(s, "  Dropped: %llu\n",
67 		   (u64)atomic64_read(&ndev->stats.dropped));
68 
69 	return 0;
70 }
71 
72 static int nitrox_stats_open(struct inode *inode, struct file *file)
73 {
74 	return single_open(file, stats_show, inode->i_private);
75 }
76 
77 static const struct file_operations nitrox_stats_fops = {
78 	.owner = THIS_MODULE,
79 	.open = nitrox_stats_open,
80 	.read = seq_read,
81 	.llseek = seq_lseek,
82 	.release = single_release,
83 };
84 
85 void nitrox_debugfs_exit(struct nitrox_device *ndev)
86 {
87 	debugfs_remove_recursive(ndev->debugfs_dir);
88 	ndev->debugfs_dir = NULL;
89 }
90 
91 int nitrox_debugfs_init(struct nitrox_device *ndev)
92 {
93 	struct dentry *dir, *f;
94 
95 	dir = debugfs_create_dir(KBUILD_MODNAME, NULL);
96 	if (!dir)
97 		return -ENOMEM;
98 
99 	ndev->debugfs_dir = dir;
100 	f = debugfs_create_file("firmware", 0400, dir, ndev, &firmware_fops);
101 	if (!f)
102 		goto err;
103 	f = debugfs_create_file("device", 0400, dir, ndev, &nitrox_fops);
104 	if (!f)
105 		goto err;
106 	f = debugfs_create_file("stats", 0400, dir, ndev, &nitrox_stats_fops);
107 	if (!f)
108 		goto err;
109 
110 	return 0;
111 
112 err:
113 	nitrox_debugfs_exit(ndev);
114 	return -ENODEV;
115 }
116