2 * Register map access API - debugfs
4 * Copyright 2011 Wolfson Microelectronics plc
6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
13 #include <linux/slab.h>
14 #include <linux/module.h>
15 #include <linux/mutex.h>
16 #include <linux/debugfs.h>
17 #include <linux/uaccess.h>
21 static struct dentry *regmap_debugfs_root;
23 /* Calculate the length of a fixed format */
24 static size_t regmap_calc_reg_len(int max_val, char *buf, size_t buf_size)
26 snprintf(buf, buf_size, "%x", max_val);
30 static int regmap_open_file(struct inode *inode, struct file *file)
32 file->private_data = inode->i_private;
36 static ssize_t regmap_name_read_file(struct file *file,
37 char __user *user_buf, size_t count,
40 struct regmap *map = file->private_data;
44 buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
48 ret = snprintf(buf, PAGE_SIZE, "%s\n", map->dev->driver->name);
54 ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
59 static const struct file_operations regmap_name_fops = {
60 .open = regmap_open_file,
61 .read = regmap_name_read_file,
62 .llseek = default_llseek,
65 static ssize_t regmap_map_read_file(struct file *file, char __user *user_buf,
66 size_t count, loff_t *ppos)
68 int reg_len, val_len, tot_len;
73 struct regmap *map = file->private_data;
77 if (*ppos < 0 || !count)
80 buf = kmalloc(count, GFP_KERNEL);
84 /* Calculate the length of a fixed format */
85 reg_len = regmap_calc_reg_len(map->max_register, buf, count);
86 val_len = 2 * map->format.val_bytes;
87 tot_len = reg_len + val_len + 3; /* : \n */
89 for (i = 0; i < map->max_register + 1; i++) {
90 if (!regmap_readable(map, i))
93 if (regmap_precious(map, i))
96 /* If we're in the region the user is trying to read */
98 /* ...but not beyond it */
99 if (buf_pos >= count - 1 - tot_len)
102 /* Format the register */
103 snprintf(buf + buf_pos, count - buf_pos, "%.*x: ",
105 buf_pos += reg_len + 2;
107 /* Format the value, write all X if we can't read */
108 ret = regmap_read(map, i, &val);
110 snprintf(buf + buf_pos, count - buf_pos,
111 "%.*x", val_len, val);
113 memset(buf + buf_pos, 'X', val_len);
114 buf_pos += 2 * map->format.val_bytes;
116 buf[buf_pos++] = '\n';
123 if (copy_to_user(user_buf, buf, buf_pos)) {
135 #undef REGMAP_ALLOW_WRITE_DEBUGFS
136 #ifdef REGMAP_ALLOW_WRITE_DEBUGFS
138 * This can be dangerous especially when we have clients such as
139 * PMICs, therefore don't provide any real compile time configuration option
140 * for this feature, people who want to use this will need to modify
141 * the source code directly.
143 static ssize_t regmap_map_write_file(struct file *file,
144 const char __user *user_buf,
145 size_t count, loff_t *ppos)
150 unsigned long reg, value;
151 struct regmap *map = file->private_data;
153 buf_size = min(count, (sizeof(buf)-1));
154 if (copy_from_user(buf, user_buf, buf_size))
158 while (*start == ' ')
160 reg = simple_strtoul(start, &start, 16);
161 while (*start == ' ')
163 if (strict_strtoul(start, 16, &value))
166 /* Userspace has been fiddling around behind the kernel's back */
167 add_taint(TAINT_USER);
169 regmap_write(map, reg, value);
173 #define regmap_map_write_file NULL
176 static const struct file_operations regmap_map_fops = {
177 .open = regmap_open_file,
178 .read = regmap_map_read_file,
179 .write = regmap_map_write_file,
180 .llseek = default_llseek,
183 static ssize_t regmap_access_read_file(struct file *file,
184 char __user *user_buf, size_t count,
187 int reg_len, tot_len;
192 struct regmap *map = file->private_data;
195 if (*ppos < 0 || !count)
198 buf = kmalloc(count, GFP_KERNEL);
202 /* Calculate the length of a fixed format */
203 reg_len = regmap_calc_reg_len(map->max_register, buf, count);
204 tot_len = reg_len + 10; /* ': R W V P\n' */
206 for (i = 0; i < map->max_register + 1; i++) {
207 /* Ignore registers which are neither readable nor writable */
208 if (!regmap_readable(map, i) && !regmap_writeable(map, i))
211 /* If we're in the region the user is trying to read */
213 /* ...but not beyond it */
214 if (buf_pos >= count - 1 - tot_len)
217 /* Format the register */
218 snprintf(buf + buf_pos, count - buf_pos,
219 "%.*x: %c %c %c %c\n",
221 regmap_readable(map, i) ? 'y' : 'n',
222 regmap_writeable(map, i) ? 'y' : 'n',
223 regmap_volatile(map, i) ? 'y' : 'n',
224 regmap_precious(map, i) ? 'y' : 'n');
233 if (copy_to_user(user_buf, buf, buf_pos)) {
245 static const struct file_operations regmap_access_fops = {
246 .open = regmap_open_file,
247 .read = regmap_access_read_file,
248 .llseek = default_llseek,
251 void regmap_debugfs_init(struct regmap *map)
253 map->debugfs = debugfs_create_dir(dev_name(map->dev),
254 regmap_debugfs_root);
256 dev_warn(map->dev, "Failed to create debugfs directory\n");
260 debugfs_create_file("name", 0400, map->debugfs,
261 map, ®map_name_fops);
263 if (map->max_register) {
264 debugfs_create_file("registers", 0400, map->debugfs,
265 map, ®map_map_fops);
266 debugfs_create_file("access", 0400, map->debugfs,
267 map, ®map_access_fops);
270 if (map->cache_type) {
271 debugfs_create_bool("cache_only", 0400, map->debugfs,
273 debugfs_create_bool("cache_dirty", 0400, map->debugfs,
275 debugfs_create_bool("cache_bypass", 0400, map->debugfs,
280 void regmap_debugfs_exit(struct regmap *map)
282 debugfs_remove_recursive(map->debugfs);
285 void regmap_debugfs_initcall(void)
287 regmap_debugfs_root = debugfs_create_dir("regmap", NULL);
288 if (!regmap_debugfs_root) {
289 pr_warn("regmap: Failed to create debugfs root\n");