1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) Rockchip Electronics Co., Ltd. */
3 #include <linux/clk.h>
4 #include <linux/proc_fs.h>
5 #include <linux/sem.h>
6 #include <linux/seq_file.h>
7
8 #include "procfs.h"
9
10 #ifdef CONFIG_PROC_FS
11
12 static const char *alg_type2name[ALG_TYPE_MAX] = {
13 [ALG_TYPE_HASH] = "HASH",
14 [ALG_TYPE_HMAC] = "HMAC",
15 [ALG_TYPE_CIPHER] = "CIPHER",
16 [ALG_TYPE_ASYM] = "ASYM",
17 [ALG_TYPE_AEAD] = "AEAD",
18 };
19
crypto_show_clock(struct seq_file * p,struct clk_bulk_data * clk_bulks,int clks_num)20 static void crypto_show_clock(struct seq_file *p, struct clk_bulk_data *clk_bulks, int clks_num)
21 {
22 int i;
23
24 seq_puts(p, "clock info:\n");
25
26 for (i = 0; i < clks_num; i++)
27 seq_printf(p, "\t%-10s %ld\n", clk_bulks[i].id, clk_get_rate(clk_bulks[i].clk));
28
29 seq_puts(p, "\n");
30 }
31
crypto_show_stat(struct seq_file * p,struct rk_crypto_stat * stat)32 static void crypto_show_stat(struct seq_file *p, struct rk_crypto_stat *stat)
33 {
34 /* show statistic info */
35 seq_puts(p, "Statistic info:\n");
36 seq_printf(p, "\tbusy_cnt : %llu\n", stat->busy_cnt);
37 seq_printf(p, "\tequeue_cnt : %llu\n", stat->equeue_cnt);
38 seq_printf(p, "\tdequeue_cnt : %llu\n", stat->dequeue_cnt);
39 seq_printf(p, "\tdone_cnt : %llu\n", stat->done_cnt);
40 seq_printf(p, "\tcomplete_cnt : %llu\n", stat->complete_cnt);
41 seq_printf(p, "\tfake_cnt : %llu\n", stat->fake_cnt);
42 seq_printf(p, "\tirq_cnt : %llu\n", stat->irq_cnt);
43 seq_printf(p, "\ttimeout_cnt : %llu\n", stat->timeout_cnt);
44 seq_printf(p, "\terror_cnt : %llu\n", stat->error_cnt);
45 seq_printf(p, "\tlast_error : %d\n", stat->last_error);
46 seq_puts(p, "\n");
47 }
48
crypto_show_queue_info(struct seq_file * p,struct rk_crypto_dev * rk_dev)49 static void crypto_show_queue_info(struct seq_file *p, struct rk_crypto_dev *rk_dev)
50 {
51 bool busy;
52 unsigned long flags;
53 u32 qlen, max_qlen;
54
55 spin_lock_irqsave(&rk_dev->lock, flags);
56
57 qlen = rk_dev->queue.qlen;
58 max_qlen = rk_dev->queue.max_qlen;
59 busy = rk_dev->busy;
60
61 spin_unlock_irqrestore(&rk_dev->lock, flags);
62
63 seq_printf(p, "Crypto queue usage [%u/%u], ever_max = %llu, status: %s\n",
64 qlen, max_qlen, rk_dev->stat.ever_queue_max, busy ? "busy" : "idle");
65
66 seq_puts(p, "\n");
67 }
68
crypto_show_valid_algo_single(struct seq_file * p,enum alg_type type,struct rk_crypto_algt ** algs,u32 algs_num)69 static void crypto_show_valid_algo_single(struct seq_file *p, enum alg_type type,
70 struct rk_crypto_algt **algs, u32 algs_num)
71 {
72 u32 i;
73 struct rk_crypto_algt *tmp_algs;
74
75 seq_printf(p, "\t%s:\n", alg_type2name[type]);
76
77 for (i = 0; i < algs_num; i++, algs++) {
78 tmp_algs = *algs;
79
80 if (!(tmp_algs->valid_flag) || tmp_algs->type != type)
81 continue;
82
83 seq_printf(p, "\t\t%s\n", tmp_algs->name);
84 }
85
86 seq_puts(p, "\n");
87 }
88
crypto_show_valid_algos(struct seq_file * p,struct rk_crypto_soc_data * soc_data)89 static void crypto_show_valid_algos(struct seq_file *p, struct rk_crypto_soc_data *soc_data)
90 {
91 u32 algs_num = 0;
92 struct rk_crypto_algt **algs;
93
94 seq_puts(p, "Valid algorithms:\n");
95
96 algs = soc_data->hw_get_algts(&algs_num);
97 if (!algs || algs_num == 0)
98 return;
99
100 crypto_show_valid_algo_single(p, ALG_TYPE_CIPHER, algs, algs_num);
101 crypto_show_valid_algo_single(p, ALG_TYPE_AEAD, algs, algs_num);
102 crypto_show_valid_algo_single(p, ALG_TYPE_HASH, algs, algs_num);
103 crypto_show_valid_algo_single(p, ALG_TYPE_HMAC, algs, algs_num);
104 crypto_show_valid_algo_single(p, ALG_TYPE_ASYM, algs, algs_num);
105 }
106
crypto_show_all(struct seq_file * p,void * v)107 static int crypto_show_all(struct seq_file *p, void *v)
108 {
109 struct rk_crypto_dev *rk_dev = p->private;
110 struct rk_crypto_soc_data *soc_data = rk_dev->soc_data;
111 struct rk_crypto_stat *stat = &rk_dev->stat;
112
113 seq_printf(p, "Rockchip Crypto Version: %s\n\n",
114 soc_data->crypto_ver);
115
116 seq_printf(p, "use_soft_aes192 : %s\n\n", soc_data->use_soft_aes192 ? "true" : "false");
117
118 crypto_show_clock(p, rk_dev->clk_bulks, rk_dev->clks_num);
119
120 crypto_show_valid_algos(p, soc_data);
121
122 crypto_show_stat(p, stat);
123
124 crypto_show_queue_info(p, rk_dev);
125
126 return 0;
127 }
128
crypto_open(struct inode * inode,struct file * file)129 static int crypto_open(struct inode *inode, struct file *file)
130 {
131 struct rk_crypto_dev *data = PDE_DATA(inode);
132
133 return single_open(file, crypto_show_all, data);
134 }
135
136 static const struct proc_ops ops = {
137 .proc_open = crypto_open,
138 .proc_read = seq_read,
139 .proc_lseek = seq_lseek,
140 .proc_release = single_release,
141 };
142
rkcrypto_proc_init(struct rk_crypto_dev * rk_dev)143 int rkcrypto_proc_init(struct rk_crypto_dev *rk_dev)
144 {
145 rk_dev->procfs = proc_create_data(rk_dev->name, 0, NULL, &ops, rk_dev);
146 if (!rk_dev->procfs)
147 return -EINVAL;
148
149 return 0;
150 }
151
rkcrypto_proc_cleanup(struct rk_crypto_dev * rk_dev)152 void rkcrypto_proc_cleanup(struct rk_crypto_dev *rk_dev)
153 {
154 if (rk_dev->procfs)
155 remove_proc_entry(rk_dev->name, NULL);
156
157 rk_dev->procfs = NULL;
158 }
159
160 #endif /* CONFIG_PROC_FS */
161