Merge tag 'device-for-3.4' of git://git.kernel.org/pub/scm/linux/kernel/git/paulg...
[linux-2.6.git] / drivers / base / regmap / regmap-debugfs.c
index 8c90a83..58517a5 100644 (file)
@@ -11,7 +11,6 @@
  */
 
 #include <linux/slab.h>
-#include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/debugfs.h>
 #include <linux/uaccess.h>
@@ -34,6 +33,35 @@ static int regmap_open_file(struct inode *inode, struct file *file)
        return 0;
 }
 
+static ssize_t regmap_name_read_file(struct file *file,
+                                    char __user *user_buf, size_t count,
+                                    loff_t *ppos)
+{
+       struct regmap *map = file->private_data;
+       int ret;
+       char *buf;
+
+       buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+
+       ret = snprintf(buf, PAGE_SIZE, "%s\n", map->dev->driver->name);
+       if (ret < 0) {
+               kfree(buf);
+               return ret;
+       }
+
+       ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
+       kfree(buf);
+       return ret;
+}
+
+static const struct file_operations regmap_name_fops = {
+       .open = regmap_open_file,
+       .read = regmap_name_read_file,
+       .llseek = default_llseek,
+};
+
 static ssize_t regmap_map_read_file(struct file *file, char __user *user_buf,
                                    size_t count, loff_t *ppos)
 {
@@ -104,9 +132,51 @@ out:
        return ret;
 }
 
+#undef REGMAP_ALLOW_WRITE_DEBUGFS
+#ifdef REGMAP_ALLOW_WRITE_DEBUGFS
+/*
+ * This can be dangerous especially when we have clients such as
+ * PMICs, therefore don't provide any real compile time configuration option
+ * for this feature, people who want to use this will need to modify
+ * the source code directly.
+ */
+static ssize_t regmap_map_write_file(struct file *file,
+                                    const char __user *user_buf,
+                                    size_t count, loff_t *ppos)
+{
+       char buf[32];
+       size_t buf_size;
+       char *start = buf;
+       unsigned long reg, value;
+       struct regmap *map = file->private_data;
+
+       buf_size = min(count, (sizeof(buf)-1));
+       if (copy_from_user(buf, user_buf, buf_size))
+               return -EFAULT;
+       buf[buf_size] = 0;
+
+       while (*start == ' ')
+               start++;
+       reg = simple_strtoul(start, &start, 16);
+       while (*start == ' ')
+               start++;
+       if (strict_strtoul(start, 16, &value))
+               return -EINVAL;
+
+       /* Userspace has been fiddling around behind the kernel's back */
+       add_taint(TAINT_USER);
+
+       regmap_write(map, reg, value);
+       return buf_size;
+}
+#else
+#define regmap_map_write_file NULL
+#endif
+
 static const struct file_operations regmap_map_fops = {
        .open = regmap_open_file,
        .read = regmap_map_read_file,
+       .write = regmap_map_write_file,
        .llseek = default_llseek,
 };
 
@@ -187,12 +257,24 @@ void regmap_debugfs_init(struct regmap *map)
                return;
        }
 
+       debugfs_create_file("name", 0400, map->debugfs,
+                           map, &regmap_name_fops);
+
        if (map->max_register) {
                debugfs_create_file("registers", 0400, map->debugfs,
                                    map, &regmap_map_fops);
                debugfs_create_file("access", 0400, map->debugfs,
                                    map, &regmap_access_fops);
        }
+
+       if (map->cache_type) {
+               debugfs_create_bool("cache_only", 0400, map->debugfs,
+                                   &map->cache_only);
+               debugfs_create_bool("cache_dirty", 0400, map->debugfs,
+                                   &map->cache_dirty);
+               debugfs_create_bool("cache_bypass", 0400, map->debugfs,
+                                   &map->cache_bypass);
+       }
 }
 
 void regmap_debugfs_exit(struct regmap *map)