1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (C) Rockchip Electronics Co.Ltd
4 * Author: Felix Zeng <felix.zeng@rock-chips.com>
5 */
6
7 #include <linux/slab.h>
8 #include <linux/delay.h>
9 #include <linux/syscalls.h>
10 #include <linux/debugfs.h>
11 #include <linux/proc_fs.h>
12 #include <linux/devfreq.h>
13 #include <linux/clk.h>
14 #include <asm/div64.h>
15
16 #ifndef FPGA_PLATFORM
17 #ifdef CONFIG_PM_DEVFREQ
18 #include <../drivers/devfreq/governor.h>
19 #endif
20 #endif
21
22 #include "rknpu_drv.h"
23 #include "rknpu_mm.h"
24 #include "rknpu_reset.h"
25 #include "rknpu_debugger.h"
26
27 #define RKNPU_DEBUGGER_ROOT_NAME "rknpu"
28
29 #if defined(CONFIG_ROCKCHIP_RKNPU_DEBUG_FS) || \
30 defined(CONFIG_ROCKCHIP_RKNPU_PROC_FS)
rknpu_version_show(struct seq_file * m,void * data)31 static int rknpu_version_show(struct seq_file *m, void *data)
32 {
33 seq_printf(m, "%s: v%d.%d.%d\n", DRIVER_DESC, DRIVER_MAJOR,
34 DRIVER_MINOR, DRIVER_PATCHLEVEL);
35
36 return 0;
37 }
38
rknpu_load_show(struct seq_file * m,void * data)39 static int rknpu_load_show(struct seq_file *m, void *data)
40 {
41 struct rknpu_debugger_node *node = m->private;
42 struct rknpu_debugger *debugger = node->debugger;
43 struct rknpu_device *rknpu_dev =
44 container_of(debugger, struct rknpu_device, debugger);
45 struct rknpu_subcore_data *subcore_data = NULL;
46 unsigned long flags;
47 int i;
48 int load;
49 uint64_t busy_time_total, div_value;
50
51 seq_puts(m, "NPU load: ");
52 for (i = 0; i < rknpu_dev->config->num_irqs; i++) {
53 subcore_data = &rknpu_dev->subcore_datas[i];
54
55 if (rknpu_dev->config->num_irqs > 1)
56 seq_printf(m, " Core%d: ", i);
57
58 spin_lock_irqsave(&rknpu_dev->irq_lock, flags);
59
60 busy_time_total = subcore_data->timer.busy_time_record;
61
62 spin_unlock_irqrestore(&rknpu_dev->irq_lock, flags);
63
64 div_value = (RKNPU_LOAD_INTERVAL / 100000);
65 do_div(busy_time_total, div_value);
66 load = busy_time_total;
67
68 if (rknpu_dev->config->num_irqs > 1)
69 seq_printf(m, "%2.d%%,", load);
70 else
71 seq_printf(m, "%2.d%%", load);
72 }
73 seq_puts(m, "\n");
74
75 return 0;
76 }
77
rknpu_power_show(struct seq_file * m,void * data)78 static int rknpu_power_show(struct seq_file *m, void *data)
79 {
80 struct rknpu_debugger_node *node = m->private;
81 struct rknpu_debugger *debugger = node->debugger;
82 struct rknpu_device *rknpu_dev =
83 container_of(debugger, struct rknpu_device, debugger);
84
85 if (atomic_read(&rknpu_dev->power_refcount) > 0)
86 seq_puts(m, "on\n");
87 else
88 seq_puts(m, "off\n");
89
90 return 0;
91 }
92
rknpu_power_set(struct file * file,const char __user * ubuf,size_t len,loff_t * offp)93 static ssize_t rknpu_power_set(struct file *file, const char __user *ubuf,
94 size_t len, loff_t *offp)
95 {
96 struct seq_file *priv = file->private_data;
97 struct rknpu_debugger_node *node = priv->private;
98 struct rknpu_debugger *debugger = node->debugger;
99 struct rknpu_device *rknpu_dev =
100 container_of(debugger, struct rknpu_device, debugger);
101 char buf[8];
102
103 if (len > sizeof(buf) - 1)
104 return -EINVAL;
105 if (copy_from_user(buf, ubuf, len))
106 return -EFAULT;
107 buf[len - 1] = '\0';
108
109 if (strcmp(buf, "on") == 0) {
110 atomic_inc(&rknpu_dev->cmdline_power_refcount);
111 rknpu_power_get(rknpu_dev);
112 LOG_INFO("rknpu power is on!");
113 } else if (strcmp(buf, "off") == 0) {
114 if (atomic_read(&rknpu_dev->power_refcount) > 0 &&
115 atomic_dec_if_positive(
116 &rknpu_dev->cmdline_power_refcount) >= 0) {
117 atomic_sub(
118 atomic_read(&rknpu_dev->cmdline_power_refcount),
119 &rknpu_dev->power_refcount);
120 atomic_set(&rknpu_dev->cmdline_power_refcount, 0);
121 rknpu_power_put(rknpu_dev);
122 }
123 if (atomic_read(&rknpu_dev->power_refcount) <= 0)
124 LOG_INFO("rknpu power is off!");
125 } else {
126 LOG_ERROR("rknpu power node params is invalid!");
127 }
128
129 return len;
130 }
131
rknpu_power_put_delay_show(struct seq_file * m,void * data)132 static int rknpu_power_put_delay_show(struct seq_file *m, void *data)
133 {
134 struct rknpu_debugger_node *node = m->private;
135 struct rknpu_debugger *debugger = node->debugger;
136 struct rknpu_device *rknpu_dev =
137 container_of(debugger, struct rknpu_device, debugger);
138
139 seq_printf(m, "%lu\n", rknpu_dev->power_put_delay);
140
141 return 0;
142 }
143
rknpu_power_put_delay_set(struct file * file,const char __user * ubuf,size_t len,loff_t * offp)144 static ssize_t rknpu_power_put_delay_set(struct file *file,
145 const char __user *ubuf, size_t len,
146 loff_t *offp)
147 {
148 struct seq_file *priv = file->private_data;
149 struct rknpu_debugger_node *node = priv->private;
150 struct rknpu_debugger *debugger = node->debugger;
151 struct rknpu_device *rknpu_dev =
152 container_of(debugger, struct rknpu_device, debugger);
153 char buf[16];
154 unsigned long power_put_delay = 0;
155 int ret = 0;
156
157 if (len > sizeof(buf) - 1)
158 return -EINVAL;
159 if (copy_from_user(buf, ubuf, len))
160 return -EFAULT;
161 buf[len - 1] = '\0';
162
163 ret = kstrtoul(buf, 10, &power_put_delay);
164 if (ret) {
165 LOG_ERROR("failed to parse power put delay string: %s\n", buf);
166 return -EFAULT;
167 }
168
169 rknpu_dev->power_put_delay = power_put_delay;
170
171 LOG_INFO("set rknpu power put delay time %lums\n",
172 rknpu_dev->power_put_delay);
173
174 return len;
175 }
176
rknpu_freq_show(struct seq_file * m,void * data)177 static int rknpu_freq_show(struct seq_file *m, void *data)
178 {
179 struct rknpu_debugger_node *node = m->private;
180 struct rknpu_debugger *debugger = node->debugger;
181 struct rknpu_device *rknpu_dev =
182 container_of(debugger, struct rknpu_device, debugger);
183 unsigned long current_freq = 0;
184
185 rknpu_power_get(rknpu_dev);
186
187 current_freq = clk_get_rate(rknpu_dev->clks[0].clk);
188
189 rknpu_power_put(rknpu_dev);
190
191 seq_printf(m, "%lu\n", current_freq);
192
193 return 0;
194 }
195
196 #ifdef CONFIG_PM_DEVFREQ
rknpu_freq_set(struct file * file,const char __user * ubuf,size_t len,loff_t * offp)197 static ssize_t rknpu_freq_set(struct file *file, const char __user *ubuf,
198 size_t len, loff_t *offp)
199 {
200 struct seq_file *priv = file->private_data;
201 struct rknpu_debugger_node *node = priv->private;
202 struct rknpu_debugger *debugger = node->debugger;
203 struct rknpu_device *rknpu_dev =
204 container_of(debugger, struct rknpu_device, debugger);
205 unsigned long current_freq = 0;
206 char buf[16];
207 unsigned long freq = 0;
208 int ret = 0;
209
210 if (len > sizeof(buf) - 1)
211 return -EINVAL;
212 if (copy_from_user(buf, ubuf, len))
213 return -EFAULT;
214 buf[len - 1] = '\0';
215
216 ret = kstrtoul(buf, 10, &freq);
217 if (ret) {
218 LOG_ERROR("failed to parse freq string: %s\n", buf);
219 return -EFAULT;
220 }
221
222 if (!rknpu_dev->devfreq)
223 return -EFAULT;
224
225 rknpu_power_get(rknpu_dev);
226
227 current_freq = clk_get_rate(rknpu_dev->clks[0].clk);
228 if (freq != current_freq) {
229 rknpu_dev->ondemand_freq = freq;
230 mutex_lock(&rknpu_dev->devfreq->lock);
231 update_devfreq(rknpu_dev->devfreq);
232 mutex_unlock(&rknpu_dev->devfreq->lock);
233 }
234
235 rknpu_power_put(rknpu_dev);
236
237 return len;
238 }
239 #else
rknpu_freq_set(struct file * file,const char __user * ubuf,size_t len,loff_t * offp)240 static ssize_t rknpu_freq_set(struct file *file, const char __user *ubuf,
241 size_t len, loff_t *offp)
242 {
243 return -EFAULT;
244 }
245 #endif
246
rknpu_volt_show(struct seq_file * m,void * data)247 static int rknpu_volt_show(struct seq_file *m, void *data)
248 {
249 struct rknpu_debugger_node *node = m->private;
250 struct rknpu_debugger *debugger = node->debugger;
251 struct rknpu_device *rknpu_dev =
252 container_of(debugger, struct rknpu_device, debugger);
253 unsigned long current_volt = 0;
254
255 current_volt = regulator_get_voltage(rknpu_dev->vdd);
256
257 seq_printf(m, "%lu\n", current_volt);
258
259 return 0;
260 }
261
rknpu_reset_show(struct seq_file * m,void * data)262 static int rknpu_reset_show(struct seq_file *m, void *data)
263 {
264 struct rknpu_debugger_node *node = m->private;
265 struct rknpu_debugger *debugger = node->debugger;
266 struct rknpu_device *rknpu_dev =
267 container_of(debugger, struct rknpu_device, debugger);
268
269 if (!rknpu_dev->bypass_soft_reset)
270 seq_puts(m, "on\n");
271 else
272 seq_puts(m, "off\n");
273
274 return 0;
275 }
276
rknpu_reset_set(struct file * file,const char __user * ubuf,size_t len,loff_t * offp)277 static ssize_t rknpu_reset_set(struct file *file, const char __user *ubuf,
278 size_t len, loff_t *offp)
279 {
280 struct seq_file *priv = file->private_data;
281 struct rknpu_debugger_node *node = priv->private;
282 struct rknpu_debugger *debugger = node->debugger;
283 struct rknpu_device *rknpu_dev =
284 container_of(debugger, struct rknpu_device, debugger);
285 char buf[8];
286
287 if (len > sizeof(buf) - 1)
288 return -EINVAL;
289 if (copy_from_user(buf, ubuf, len))
290 return -EFAULT;
291 buf[len - 1] = '\0';
292
293 if (strcmp(buf, "1") == 0 &&
294 atomic_read(&rknpu_dev->power_refcount) > 0)
295 rknpu_soft_reset(rknpu_dev);
296 else if (strcmp(buf, "on") == 0)
297 rknpu_dev->bypass_soft_reset = 0;
298 else if (strcmp(buf, "off") == 0)
299 rknpu_dev->bypass_soft_reset = 1;
300
301 return len;
302 }
303
304 static struct rknpu_debugger_list rknpu_debugger_root_list[] = {
305 { "version", rknpu_version_show, NULL, NULL },
306 { "load", rknpu_load_show, NULL, NULL },
307 { "power", rknpu_power_show, rknpu_power_set, NULL },
308 { "freq", rknpu_freq_show, rknpu_freq_set, NULL },
309 { "volt", rknpu_volt_show, NULL, NULL },
310 { "delayms", rknpu_power_put_delay_show, rknpu_power_put_delay_set,
311 NULL },
312 { "reset", rknpu_reset_show, rknpu_reset_set, NULL },
313 #ifdef CONFIG_ROCKCHIP_RKNPU_SRAM
314 { "mm", rknpu_mm_dump, NULL, NULL },
315 #endif
316 };
317
rknpu_debugger_write(struct file * file,const char __user * ubuf,size_t len,loff_t * offp)318 static ssize_t rknpu_debugger_write(struct file *file, const char __user *ubuf,
319 size_t len, loff_t *offp)
320 {
321 struct seq_file *priv = file->private_data;
322 struct rknpu_debugger_node *node = priv->private;
323
324 if (node->info_ent->write)
325 return node->info_ent->write(file, ubuf, len, offp);
326 else
327 return len;
328 }
329
rknpu_debugfs_open(struct inode * inode,struct file * file)330 static int rknpu_debugfs_open(struct inode *inode, struct file *file)
331 {
332 struct rknpu_debugger_node *node = inode->i_private;
333
334 return single_open(file, node->info_ent->show, node);
335 }
336
337 static const struct file_operations rknpu_debugfs_fops = {
338 .owner = THIS_MODULE,
339 .open = rknpu_debugfs_open,
340 .read = seq_read,
341 .llseek = seq_lseek,
342 .release = single_release,
343 .write = rknpu_debugger_write,
344 };
345 #endif /* #if defined(CONFIG_ROCKCHIP_RKNPU_DEBUG_FS) || defined(CONFIG_ROCKCHIP_RKNPU_PROC_FS) */
346
347 #ifdef CONFIG_ROCKCHIP_RKNPU_DEBUG_FS
rknpu_debugfs_remove_files(struct rknpu_debugger * debugger)348 static int rknpu_debugfs_remove_files(struct rknpu_debugger *debugger)
349 {
350 struct rknpu_debugger_node *pos, *q;
351 struct list_head *entry_list;
352
353 mutex_lock(&debugger->debugfs_lock);
354
355 /* Delete debugfs entry list */
356 entry_list = &debugger->debugfs_entry_list;
357 list_for_each_entry_safe(pos, q, entry_list, list) {
358 if (pos->dent == NULL)
359 continue;
360 list_del(&pos->list);
361 kfree(pos);
362 pos = NULL;
363 }
364
365 /* Delete all debugfs node in this directory */
366 debugfs_remove_recursive(debugger->debugfs_dir);
367 debugger->debugfs_dir = NULL;
368
369 mutex_unlock(&debugger->debugfs_lock);
370
371 return 0;
372 }
373
rknpu_debugfs_create_files(const struct rknpu_debugger_list * files,int count,struct dentry * root,struct rknpu_debugger * debugger)374 static int rknpu_debugfs_create_files(const struct rknpu_debugger_list *files,
375 int count, struct dentry *root,
376 struct rknpu_debugger *debugger)
377 {
378 int i;
379 struct dentry *ent;
380 struct rknpu_debugger_node *tmp;
381
382 for (i = 0; i < count; i++) {
383 tmp = kmalloc(sizeof(struct rknpu_debugger_node), GFP_KERNEL);
384 if (tmp == NULL) {
385 LOG_ERROR(
386 "Cannot alloc node path /sys/kernel/debug/%pd/%s\n",
387 root, files[i].name);
388 goto MALLOC_FAIL;
389 }
390
391 tmp->info_ent = &files[i];
392 tmp->debugger = debugger;
393
394 ent = debugfs_create_file(files[i].name, S_IFREG | S_IRUGO,
395 root, tmp, &rknpu_debugfs_fops);
396 if (!ent) {
397 LOG_ERROR("Cannot create /sys/kernel/debug/%pd/%s\n",
398 root, files[i].name);
399 goto CREATE_FAIL;
400 }
401
402 tmp->dent = ent;
403
404 mutex_lock(&debugger->debugfs_lock);
405 list_add_tail(&tmp->list, &debugger->debugfs_entry_list);
406 mutex_unlock(&debugger->debugfs_lock);
407 }
408
409 return 0;
410
411 CREATE_FAIL:
412 kfree(tmp);
413 MALLOC_FAIL:
414 rknpu_debugfs_remove_files(debugger);
415
416 return -1;
417 }
418
rknpu_debugfs_remove(struct rknpu_debugger * debugger)419 static int rknpu_debugfs_remove(struct rknpu_debugger *debugger)
420 {
421 rknpu_debugfs_remove_files(debugger);
422
423 return 0;
424 }
425
rknpu_debugfs_init(struct rknpu_debugger * debugger)426 static int rknpu_debugfs_init(struct rknpu_debugger *debugger)
427 {
428 int ret;
429
430 debugger->debugfs_dir =
431 debugfs_create_dir(RKNPU_DEBUGGER_ROOT_NAME, NULL);
432 if (IS_ERR_OR_NULL(debugger->debugfs_dir)) {
433 LOG_ERROR("failed on mkdir /sys/kernel/debug/%s\n",
434 RKNPU_DEBUGGER_ROOT_NAME);
435 debugger->debugfs_dir = NULL;
436 return -EIO;
437 }
438
439 ret = rknpu_debugfs_create_files(rknpu_debugger_root_list,
440 ARRAY_SIZE(rknpu_debugger_root_list),
441 debugger->debugfs_dir, debugger);
442 if (ret) {
443 LOG_ERROR(
444 "Could not install rknpu_debugger_root_list debugfs\n");
445 goto CREATE_FAIL;
446 }
447
448 return 0;
449
450 CREATE_FAIL:
451 rknpu_debugfs_remove(debugger);
452
453 return ret;
454 }
455 #endif /* #ifdef CONFIG_ROCKCHIP_RKNPU_DEBUG_FS */
456
457 #ifdef CONFIG_ROCKCHIP_RKNPU_PROC_FS
rknpu_procfs_open(struct inode * inode,struct file * file)458 static int rknpu_procfs_open(struct inode *inode, struct file *file)
459 {
460 #if KERNEL_VERSION(6, 1, 0) > LINUX_VERSION_CODE
461 struct rknpu_debugger_node *node = PDE_DATA(inode);
462 #else
463 struct rknpu_debugger_node *node = pde_data(inode);
464 #endif
465
466 return single_open(file, node->info_ent->show, node);
467 }
468
469 static const struct proc_ops rknpu_procfs_fops = {
470 .proc_open = rknpu_procfs_open,
471 .proc_read = seq_read,
472 .proc_lseek = seq_lseek,
473 .proc_release = single_release,
474 .proc_write = rknpu_debugger_write,
475 };
476
rknpu_procfs_remove_files(struct rknpu_debugger * debugger)477 static int rknpu_procfs_remove_files(struct rknpu_debugger *debugger)
478 {
479 struct rknpu_debugger_node *pos, *q;
480 struct list_head *entry_list;
481
482 mutex_lock(&debugger->procfs_lock);
483
484 /* Delete procfs entry list */
485 entry_list = &debugger->procfs_entry_list;
486 list_for_each_entry_safe(pos, q, entry_list, list) {
487 if (pos->pent == NULL)
488 continue;
489 list_del(&pos->list);
490 kfree(pos);
491 pos = NULL;
492 }
493
494 /* Delete all procfs node in this directory */
495 proc_remove(debugger->procfs_dir);
496 debugger->procfs_dir = NULL;
497
498 mutex_unlock(&debugger->procfs_lock);
499
500 return 0;
501 }
502
rknpu_procfs_create_files(const struct rknpu_debugger_list * files,int count,struct proc_dir_entry * root,struct rknpu_debugger * debugger)503 static int rknpu_procfs_create_files(const struct rknpu_debugger_list *files,
504 int count, struct proc_dir_entry *root,
505 struct rknpu_debugger *debugger)
506 {
507 int i;
508 struct proc_dir_entry *ent;
509 struct rknpu_debugger_node *tmp;
510
511 for (i = 0; i < count; i++) {
512 tmp = kmalloc(sizeof(struct rknpu_debugger_node), GFP_KERNEL);
513 if (tmp == NULL) {
514 LOG_ERROR("Cannot alloc node path for /proc/%s/%s\n",
515 RKNPU_DEBUGGER_ROOT_NAME, files[i].name);
516 goto MALLOC_FAIL;
517 }
518
519 tmp->info_ent = &files[i];
520 tmp->debugger = debugger;
521
522 ent = proc_create_data(files[i].name, S_IFREG | S_IRUGO, root,
523 &rknpu_procfs_fops, tmp);
524 if (!ent) {
525 LOG_ERROR("Cannot create /proc/%s/%s\n",
526 RKNPU_DEBUGGER_ROOT_NAME, files[i].name);
527 goto CREATE_FAIL;
528 }
529
530 tmp->pent = ent;
531
532 mutex_lock(&debugger->procfs_lock);
533 list_add_tail(&tmp->list, &debugger->procfs_entry_list);
534 mutex_unlock(&debugger->procfs_lock);
535 }
536
537 return 0;
538
539 CREATE_FAIL:
540 kfree(tmp);
541 MALLOC_FAIL:
542 rknpu_procfs_remove_files(debugger);
543 return -1;
544 }
545
rknpu_procfs_remove(struct rknpu_debugger * debugger)546 static int rknpu_procfs_remove(struct rknpu_debugger *debugger)
547 {
548 rknpu_procfs_remove_files(debugger);
549
550 return 0;
551 }
552
rknpu_procfs_init(struct rknpu_debugger * debugger)553 static int rknpu_procfs_init(struct rknpu_debugger *debugger)
554 {
555 int ret;
556
557 debugger->procfs_dir = proc_mkdir(RKNPU_DEBUGGER_ROOT_NAME, NULL);
558 if (IS_ERR_OR_NULL(debugger->procfs_dir)) {
559 pr_err("failed on mkdir /proc/%s\n", RKNPU_DEBUGGER_ROOT_NAME);
560 debugger->procfs_dir = NULL;
561 return -EIO;
562 }
563
564 ret = rknpu_procfs_create_files(rknpu_debugger_root_list,
565 ARRAY_SIZE(rknpu_debugger_root_list),
566 debugger->procfs_dir, debugger);
567 if (ret) {
568 pr_err("Could not install rknpu_debugger_root_list procfs\n");
569 goto CREATE_FAIL;
570 }
571
572 return 0;
573
574 CREATE_FAIL:
575 rknpu_procfs_remove(debugger);
576
577 return ret;
578 }
579 #endif /* #ifdef CONFIG_ROCKCHIP_RKNPU_PROC_FS */
580
rknpu_debugger_init(struct rknpu_device * rknpu_dev)581 int rknpu_debugger_init(struct rknpu_device *rknpu_dev)
582 {
583 #ifdef CONFIG_ROCKCHIP_RKNPU_DEBUG_FS
584 mutex_init(&rknpu_dev->debugger.debugfs_lock);
585 INIT_LIST_HEAD(&rknpu_dev->debugger.debugfs_entry_list);
586 rknpu_debugfs_init(&rknpu_dev->debugger);
587 #endif
588 #ifdef CONFIG_ROCKCHIP_RKNPU_PROC_FS
589 mutex_init(&rknpu_dev->debugger.procfs_lock);
590 INIT_LIST_HEAD(&rknpu_dev->debugger.procfs_entry_list);
591 rknpu_procfs_init(&rknpu_dev->debugger);
592 #endif
593 return 0;
594 }
595
rknpu_debugger_remove(struct rknpu_device * rknpu_dev)596 int rknpu_debugger_remove(struct rknpu_device *rknpu_dev)
597 {
598 #ifdef CONFIG_ROCKCHIP_RKNPU_DEBUG_FS
599 rknpu_debugfs_remove(&rknpu_dev->debugger);
600 #endif
601 #ifdef CONFIG_ROCKCHIP_RKNPU_PROC_FS
602 rknpu_procfs_remove(&rknpu_dev->debugger);
603 #endif
604 return 0;
605 }
606