staging: ccree: simplify ioread/iowrite
[linux-2.6-block.git] / drivers / staging / ccree / ssi_sysfs.c
1 /*
2  * Copyright (C) 2012-2017 ARM Limited or its affiliates.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, see <http://www.gnu.org/licenses/>.
15  */
16
17 #include <linux/kernel.h>
18 #include "ssi_config.h"
19 #include "ssi_driver.h"
20 #include "cc_crypto_ctx.h"
21 #include "ssi_sysfs.h"
22
23 #ifdef ENABLE_CC_SYSFS
24
25 static struct ssi_drvdata *sys_get_drvdata(void);
26
27 static ssize_t ssi_sys_regdump_show(struct kobject *kobj,
28                                     struct kobj_attribute *attr, char *buf)
29 {
30         struct ssi_drvdata *drvdata = sys_get_drvdata();
31         u32 register_value;
32         int offset = 0;
33
34         register_value = cc_ioread(drvdata, CC_REG(HOST_SIGNATURE));
35         offset += scnprintf(buf + offset, PAGE_SIZE - offset, "%s \t(0x%lX)\t 0x%08X\n", "HOST_SIGNATURE       ", DX_HOST_SIGNATURE_REG_OFFSET, register_value);
36         register_value = cc_ioread(drvdata, CC_REG(HOST_IRR));
37         offset += scnprintf(buf + offset, PAGE_SIZE - offset, "%s \t(0x%lX)\t 0x%08X\n", "HOST_IRR             ", DX_HOST_IRR_REG_OFFSET, register_value);
38         register_value = cc_ioread(drvdata, CC_REG(HOST_POWER_DOWN_EN));
39         offset += scnprintf(buf + offset, PAGE_SIZE - offset, "%s \t(0x%lX)\t 0x%08X\n", "HOST_POWER_DOWN_EN   ", DX_HOST_POWER_DOWN_EN_REG_OFFSET, register_value);
40         register_value =  cc_ioread(drvdata, CC_REG(AXIM_MON_ERR));
41         offset += scnprintf(buf + offset, PAGE_SIZE - offset, "%s \t(0x%lX)\t 0x%08X\n", "AXIM_MON_ERR         ", DX_AXIM_MON_ERR_REG_OFFSET, register_value);
42         register_value = cc_ioread(drvdata, CC_REG(DSCRPTR_QUEUE_CONTENT));
43         offset += scnprintf(buf + offset, PAGE_SIZE - offset, "%s \t(0x%lX)\t 0x%08X\n", "DSCRPTR_QUEUE_CONTENT", DX_DSCRPTR_QUEUE_CONTENT_REG_OFFSET, register_value);
44         return offset;
45 }
46
47 static ssize_t ssi_sys_help_show(struct kobject *kobj,
48                                  struct kobj_attribute *attr, char *buf)
49 {
50         char *help_str[] = {
51                                 "cat reg_dump              ", "Print several of CC register values",
52                                 };
53         int i = 0, offset = 0;
54
55         offset += scnprintf(buf + offset, PAGE_SIZE - offset, "Usage:\n");
56         for (i = 0; i < ARRAY_SIZE(help_str); i += 2)
57            offset += scnprintf(buf + offset, PAGE_SIZE - offset, "%s\t\t%s\n", help_str[i], help_str[i + 1]);
58
59         return offset;
60 }
61
62 /********************************************************
63  *              SYSFS objects                           *
64  ********************************************************/
65 /*
66  * Structure used to create a directory
67  * and its attributes in sysfs.
68  */
69 struct sys_dir {
70         struct kobject *sys_dir_kobj;
71         struct attribute_group sys_dir_attr_group;
72         struct attribute **sys_dir_attr_list;
73         u32 num_of_attrs;
74         struct ssi_drvdata *drvdata; /* Associated driver context */
75 };
76
77 /* top level directory structures */
78 static struct sys_dir sys_top_dir;
79
80 /* TOP LEVEL ATTRIBUTES */
81 static struct kobj_attribute ssi_sys_top_level_attrs[] = {
82         __ATTR(dump_regs, 0444, ssi_sys_regdump_show, NULL),
83         __ATTR(help, 0444, ssi_sys_help_show, NULL),
84 #if defined CC_CYCLE_COUNT
85         __ATTR(stats_host, 0664, ssi_sys_stat_host_db_show, ssi_sys_stats_host_db_clear),
86         __ATTR(stats_cc, 0664, ssi_sys_stat_cc_db_show, ssi_sys_stats_cc_db_clear),
87 #endif
88
89 };
90
91 static struct ssi_drvdata *sys_get_drvdata(void)
92 {
93         /* TODO: supporting multiple SeP devices would require avoiding
94          * global "top_dir" and finding associated "top_dir" by traversing
95          * up the tree to the kobject which matches one of the top_dir's
96          */
97         return sys_top_dir.drvdata;
98 }
99
100 static int sys_init_dir(struct sys_dir *sys_dir, struct ssi_drvdata *drvdata,
101                         struct kobject *parent_dir_kobj, const char *dir_name,
102                         struct kobj_attribute *attrs, u32 num_of_attrs)
103 {
104         int i;
105
106         memset(sys_dir, 0, sizeof(struct sys_dir));
107
108         sys_dir->drvdata = drvdata;
109
110         /* initialize directory kobject */
111         sys_dir->sys_dir_kobj =
112                 kobject_create_and_add(dir_name, parent_dir_kobj);
113
114         if (!(sys_dir->sys_dir_kobj))
115                 return -ENOMEM;
116         /* allocate memory for directory's attributes list */
117         sys_dir->sys_dir_attr_list =
118                 kcalloc(num_of_attrs + 1, sizeof(struct attribute *),
119                         GFP_KERNEL);
120
121         if (!(sys_dir->sys_dir_attr_list)) {
122                 kobject_put(sys_dir->sys_dir_kobj);
123                 return -ENOMEM;
124         }
125
126         sys_dir->num_of_attrs = num_of_attrs;
127
128         /* initialize attributes list */
129         for (i = 0; i < num_of_attrs; ++i)
130                 sys_dir->sys_dir_attr_list[i] = &attrs[i].attr;
131
132         /* last list entry should be NULL */
133         sys_dir->sys_dir_attr_list[num_of_attrs] = NULL;
134
135         sys_dir->sys_dir_attr_group.attrs = sys_dir->sys_dir_attr_list;
136
137         return sysfs_create_group(sys_dir->sys_dir_kobj,
138                         &sys_dir->sys_dir_attr_group);
139 }
140
141 static void sys_free_dir(struct sys_dir *sys_dir)
142 {
143         if (!sys_dir)
144                 return;
145
146         kfree(sys_dir->sys_dir_attr_list);
147
148         if (sys_dir->sys_dir_kobj)
149                 kobject_put(sys_dir->sys_dir_kobj);
150 }
151
152 int ssi_sysfs_init(struct kobject *sys_dev_obj, struct ssi_drvdata *drvdata)
153 {
154         int retval;
155         struct device *dev = drvdata_to_dev(drvdata);
156
157         dev_info(dev, "setup sysfs under %s\n", sys_dev_obj->name);
158
159         /* Initialize top directory */
160         retval = sys_init_dir(&sys_top_dir, drvdata, sys_dev_obj, "cc_info",
161                               ssi_sys_top_level_attrs,
162                               ARRAY_SIZE(ssi_sys_top_level_attrs));
163         return retval;
164 }
165
166 void ssi_sysfs_fini(void)
167 {
168         sys_free_dir(&sys_top_dir);
169 }
170
171 #endif /*ENABLE_CC_SYSFS*/
172