2 * Copyright (C) 2012-2017 ARM Limited or its affiliates.
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.
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.
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/>.
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"
23 #ifdef ENABLE_CC_SYSFS
25 static struct ssi_drvdata *sys_get_drvdata(void);
27 static ssize_t ssi_sys_regdump_show(struct kobject *kobj,
28 struct kobj_attribute *attr, char *buf)
30 struct ssi_drvdata *drvdata = sys_get_drvdata();
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);
47 static ssize_t ssi_sys_help_show(struct kobject *kobj,
48 struct kobj_attribute *attr, char *buf)
51 "cat reg_dump ", "Print several of CC register values",
53 int i = 0, offset = 0;
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]);
62 /********************************************************
64 ********************************************************/
66 * Structure used to create a directory
67 * and its attributes in sysfs.
70 struct kobject *sys_dir_kobj;
71 struct attribute_group sys_dir_attr_group;
72 struct attribute **sys_dir_attr_list;
74 struct ssi_drvdata *drvdata; /* Associated driver context */
77 /* top level directory structures */
78 static struct sys_dir sys_top_dir;
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),
91 static struct ssi_drvdata *sys_get_drvdata(void)
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
97 return sys_top_dir.drvdata;
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)
106 memset(sys_dir, 0, sizeof(struct sys_dir));
108 sys_dir->drvdata = drvdata;
110 /* initialize directory kobject */
111 sys_dir->sys_dir_kobj =
112 kobject_create_and_add(dir_name, parent_dir_kobj);
114 if (!(sys_dir->sys_dir_kobj))
116 /* allocate memory for directory's attributes list */
117 sys_dir->sys_dir_attr_list =
118 kcalloc(num_of_attrs + 1, sizeof(struct attribute *),
121 if (!(sys_dir->sys_dir_attr_list)) {
122 kobject_put(sys_dir->sys_dir_kobj);
126 sys_dir->num_of_attrs = num_of_attrs;
128 /* initialize attributes list */
129 for (i = 0; i < num_of_attrs; ++i)
130 sys_dir->sys_dir_attr_list[i] = &attrs[i].attr;
132 /* last list entry should be NULL */
133 sys_dir->sys_dir_attr_list[num_of_attrs] = NULL;
135 sys_dir->sys_dir_attr_group.attrs = sys_dir->sys_dir_attr_list;
137 return sysfs_create_group(sys_dir->sys_dir_kobj,
138 &sys_dir->sys_dir_attr_group);
141 static void sys_free_dir(struct sys_dir *sys_dir)
146 kfree(sys_dir->sys_dir_attr_list);
148 if (sys_dir->sys_dir_kobj)
149 kobject_put(sys_dir->sys_dir_kobj);
152 int ssi_sysfs_init(struct kobject *sys_dev_obj, struct ssi_drvdata *drvdata)
155 struct device *dev = drvdata_to_dev(drvdata);
157 dev_info(dev, "setup sysfs under %s\n", sys_dev_obj->name);
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));
166 void ssi_sysfs_fini(void)
168 sys_free_dir(&sys_top_dir);
171 #endif /*ENABLE_CC_SYSFS*/