1 /* 2 * Register map access API - debugfs 3 * 4 * Copyright 2011 Wolfson Microelectronics plc 5 * 6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> 7 * 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. 11 */ 12 13 #include <linux/slab.h> 14 #include <linux/mutex.h> 15 #include <linux/debugfs.h> 16 #include <linux/uaccess.h> 17 #include <linux/device.h> 18 19 #include "internal.h" 20 21 static struct dentry *regmap_debugfs_root; 22 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) 25 { 26 snprintf(buf, buf_size, "%x", max_val); 27 return strlen(buf); 28 } 29 30 static ssize_t regmap_name_read_file(struct file *file, 31 char __user *user_buf, size_t count, 32 loff_t *ppos) 33 { 34 struct regmap *map = file->private_data; 35 int ret; 36 char *buf; 37 38 buf = kmalloc(PAGE_SIZE, GFP_KERNEL); 39 if (!buf) 40 return -ENOMEM; 41 42 ret = snprintf(buf, PAGE_SIZE, "%s\n", map->dev->driver->name); 43 if (ret < 0) { 44 kfree(buf); 45 return ret; 46 } 47 48 ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret); 49 kfree(buf); 50 return ret; 51 } 52 53 static const struct file_operations regmap_name_fops = { 54 .open = simple_open, 55 .read = regmap_name_read_file, 56 .llseek = default_llseek, 57 }; 58 59 /* 60 * Work out where the start offset maps into register numbers, bearing 61 * in mind that we suppress hidden registers. 62 */ 63 static unsigned int regmap_debugfs_get_dump_start(struct regmap *map, 64 unsigned int base, 65 loff_t from, 66 loff_t *pos) 67 { 68 struct regmap_debugfs_off_cache *c = NULL; 69 loff_t p = 0; 70 unsigned int i, ret; 71 72 /* 73 * If we don't have a cache build one so we don't have to do a 74 * linear scan each time. 75 */ 76 if (list_empty(&map->debugfs_off_cache)) { 77 for (i = base; i <= map->max_register; i += map->reg_stride) { 78 /* Skip unprinted registers, closing off cache entry */ 79 if (!regmap_readable(map, i) || 80 regmap_precious(map, i)) { 81 if (c) { 82 c->max = p - 1; 83 list_add_tail(&c->list, 84 &map->debugfs_off_cache); 85 c = NULL; 86 } 87 88 continue; 89 } 90 91 /* No cache entry? Start a new one */ 92 if (!c) { 93 c = kzalloc(sizeof(*c), GFP_KERNEL); 94 if (!c) 95 break; 96 c->min = p; 97 c->base_reg = i; 98 } 99 100 p += map->debugfs_tot_len; 101 } 102 } 103 104 /* Find the relevant block */ 105 list_for_each_entry(c, &map->debugfs_off_cache, list) { 106 if (*pos >= c->min && *pos <= c->max) { 107 *pos = c->min; 108 return c->base_reg; 109 } 110 111 ret = c->max; 112 } 113 114 return ret; 115 } 116 117 static ssize_t regmap_read_debugfs(struct regmap *map, unsigned int from, 118 unsigned int to, char __user *user_buf, 119 size_t count, loff_t *ppos) 120 { 121 size_t buf_pos = 0; 122 loff_t p = *ppos; 123 ssize_t ret; 124 int i; 125 char *buf; 126 unsigned int val, start_reg; 127 128 if (*ppos < 0 || !count) 129 return -EINVAL; 130 131 buf = kmalloc(count, GFP_KERNEL); 132 if (!buf) 133 return -ENOMEM; 134 135 /* Calculate the length of a fixed format */ 136 if (!map->debugfs_tot_len) { 137 map->debugfs_reg_len = regmap_calc_reg_len(map->max_register, 138 buf, count); 139 map->debugfs_val_len = 2 * map->format.val_bytes; 140 map->debugfs_tot_len = map->debugfs_reg_len + 141 map->debugfs_val_len + 3; /* : \n */ 142 } 143 144 /* Work out which register we're starting at */ 145 start_reg = regmap_debugfs_get_dump_start(map, from, *ppos, &p); 146 147 for (i = start_reg; i <= to; i += map->reg_stride) { 148 if (!regmap_readable(map, i)) 149 continue; 150 151 if (regmap_precious(map, i)) 152 continue; 153 154 /* If we're in the region the user is trying to read */ 155 if (p >= *ppos) { 156 /* ...but not beyond it */ 157 if (buf_pos + 1 + map->debugfs_tot_len >= count) 158 break; 159 160 /* Format the register */ 161 snprintf(buf + buf_pos, count - buf_pos, "%.*x: ", 162 map->debugfs_reg_len, i - from); 163 buf_pos += map->debugfs_reg_len + 2; 164 165 /* Format the value, write all X if we can't read */ 166 ret = regmap_read(map, i, &val); 167 if (ret == 0) 168 snprintf(buf + buf_pos, count - buf_pos, 169 "%.*x", map->debugfs_val_len, val); 170 else 171 memset(buf + buf_pos, 'X', 172 map->debugfs_val_len); 173 buf_pos += 2 * map->format.val_bytes; 174 175 buf[buf_pos++] = '\n'; 176 } 177 p += map->debugfs_tot_len; 178 } 179 180 ret = buf_pos; 181 182 if (copy_to_user(user_buf, buf, buf_pos)) { 183 ret = -EFAULT; 184 goto out; 185 } 186 187 *ppos += buf_pos; 188 189 out: 190 kfree(buf); 191 return ret; 192 } 193 194 static ssize_t regmap_map_read_file(struct file *file, char __user *user_buf, 195 size_t count, loff_t *ppos) 196 { 197 struct regmap *map = file->private_data; 198 199 return regmap_read_debugfs(map, 0, map->max_register, user_buf, 200 count, ppos); 201 } 202 203 #undef REGMAP_ALLOW_WRITE_DEBUGFS 204 #ifdef REGMAP_ALLOW_WRITE_DEBUGFS 205 /* 206 * This can be dangerous especially when we have clients such as 207 * PMICs, therefore don't provide any real compile time configuration option 208 * for this feature, people who want to use this will need to modify 209 * the source code directly. 210 */ 211 static ssize_t regmap_map_write_file(struct file *file, 212 const char __user *user_buf, 213 size_t count, loff_t *ppos) 214 { 215 char buf[32]; 216 size_t buf_size; 217 char *start = buf; 218 unsigned long reg, value; 219 struct regmap *map = file->private_data; 220 221 buf_size = min(count, (sizeof(buf)-1)); 222 if (copy_from_user(buf, user_buf, buf_size)) 223 return -EFAULT; 224 buf[buf_size] = 0; 225 226 while (*start == ' ') 227 start++; 228 reg = simple_strtoul(start, &start, 16); 229 while (*start == ' ') 230 start++; 231 if (strict_strtoul(start, 16, &value)) 232 return -EINVAL; 233 234 /* Userspace has been fiddling around behind the kernel's back */ 235 add_taint(TAINT_USER); 236 237 regmap_write(map, reg, value); 238 return buf_size; 239 } 240 #else 241 #define regmap_map_write_file NULL 242 #endif 243 244 static const struct file_operations regmap_map_fops = { 245 .open = simple_open, 246 .read = regmap_map_read_file, 247 .write = regmap_map_write_file, 248 .llseek = default_llseek, 249 }; 250 251 static ssize_t regmap_range_read_file(struct file *file, char __user *user_buf, 252 size_t count, loff_t *ppos) 253 { 254 struct regmap_range_node *range = file->private_data; 255 struct regmap *map = range->map; 256 257 return regmap_read_debugfs(map, range->range_min, range->range_max, 258 user_buf, count, ppos); 259 } 260 261 static const struct file_operations regmap_range_fops = { 262 .open = simple_open, 263 .read = regmap_range_read_file, 264 .llseek = default_llseek, 265 }; 266 267 static ssize_t regmap_access_read_file(struct file *file, 268 char __user *user_buf, size_t count, 269 loff_t *ppos) 270 { 271 int reg_len, tot_len; 272 size_t buf_pos = 0; 273 loff_t p = 0; 274 ssize_t ret; 275 int i; 276 struct regmap *map = file->private_data; 277 char *buf; 278 279 if (*ppos < 0 || !count) 280 return -EINVAL; 281 282 buf = kmalloc(count, GFP_KERNEL); 283 if (!buf) 284 return -ENOMEM; 285 286 /* Calculate the length of a fixed format */ 287 reg_len = regmap_calc_reg_len(map->max_register, buf, count); 288 tot_len = reg_len + 10; /* ': R W V P\n' */ 289 290 for (i = 0; i <= map->max_register; i += map->reg_stride) { 291 /* Ignore registers which are neither readable nor writable */ 292 if (!regmap_readable(map, i) && !regmap_writeable(map, i)) 293 continue; 294 295 /* If we're in the region the user is trying to read */ 296 if (p >= *ppos) { 297 /* ...but not beyond it */ 298 if (buf_pos >= count - 1 - tot_len) 299 break; 300 301 /* Format the register */ 302 snprintf(buf + buf_pos, count - buf_pos, 303 "%.*x: %c %c %c %c\n", 304 reg_len, i, 305 regmap_readable(map, i) ? 'y' : 'n', 306 regmap_writeable(map, i) ? 'y' : 'n', 307 regmap_volatile(map, i) ? 'y' : 'n', 308 regmap_precious(map, i) ? 'y' : 'n'); 309 310 buf_pos += tot_len; 311 } 312 p += tot_len; 313 } 314 315 ret = buf_pos; 316 317 if (copy_to_user(user_buf, buf, buf_pos)) { 318 ret = -EFAULT; 319 goto out; 320 } 321 322 *ppos += buf_pos; 323 324 out: 325 kfree(buf); 326 return ret; 327 } 328 329 static const struct file_operations regmap_access_fops = { 330 .open = simple_open, 331 .read = regmap_access_read_file, 332 .llseek = default_llseek, 333 }; 334 335 void regmap_debugfs_init(struct regmap *map, const char *name) 336 { 337 struct rb_node *next; 338 struct regmap_range_node *range_node; 339 340 INIT_LIST_HEAD(&map->debugfs_off_cache); 341 342 if (name) { 343 map->debugfs_name = kasprintf(GFP_KERNEL, "%s-%s", 344 dev_name(map->dev), name); 345 name = map->debugfs_name; 346 } else { 347 name = dev_name(map->dev); 348 } 349 350 map->debugfs = debugfs_create_dir(name, regmap_debugfs_root); 351 if (!map->debugfs) { 352 dev_warn(map->dev, "Failed to create debugfs directory\n"); 353 return; 354 } 355 356 debugfs_create_file("name", 0400, map->debugfs, 357 map, ®map_name_fops); 358 359 if (map->max_register) { 360 debugfs_create_file("registers", 0400, map->debugfs, 361 map, ®map_map_fops); 362 debugfs_create_file("access", 0400, map->debugfs, 363 map, ®map_access_fops); 364 } 365 366 if (map->cache_type) { 367 debugfs_create_bool("cache_only", 0400, map->debugfs, 368 &map->cache_only); 369 debugfs_create_bool("cache_dirty", 0400, map->debugfs, 370 &map->cache_dirty); 371 debugfs_create_bool("cache_bypass", 0400, map->debugfs, 372 &map->cache_bypass); 373 } 374 375 next = rb_first(&map->range_tree); 376 while (next) { 377 range_node = rb_entry(next, struct regmap_range_node, node); 378 379 if (range_node->name) 380 debugfs_create_file(range_node->name, 0400, 381 map->debugfs, range_node, 382 ®map_range_fops); 383 384 next = rb_next(&range_node->node); 385 } 386 } 387 388 void regmap_debugfs_exit(struct regmap *map) 389 { 390 struct regmap_debugfs_off_cache *c; 391 392 debugfs_remove_recursive(map->debugfs); 393 while (!list_empty(&map->debugfs_off_cache)) { 394 c = list_first_entry(&map->debugfs_off_cache, 395 struct regmap_debugfs_off_cache, 396 list); 397 list_del(&c->list); 398 kfree(c); 399 } 400 kfree(map->debugfs_name); 401 } 402 403 void regmap_debugfs_initcall(void) 404 { 405 regmap_debugfs_root = debugfs_create_dir("regmap", NULL); 406 if (!regmap_debugfs_root) { 407 pr_warn("regmap: Failed to create debugfs root\n"); 408 return; 409 } 410 } 411