131244e396fa9e4854cfd6dfe305983e77802c156Mark Brown/*
231244e396fa9e4854cfd6dfe305983e77802c156Mark Brown * Register map access API - debugfs
331244e396fa9e4854cfd6dfe305983e77802c156Mark Brown *
431244e396fa9e4854cfd6dfe305983e77802c156Mark Brown * Copyright 2011 Wolfson Microelectronics plc
531244e396fa9e4854cfd6dfe305983e77802c156Mark Brown *
631244e396fa9e4854cfd6dfe305983e77802c156Mark Brown * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
731244e396fa9e4854cfd6dfe305983e77802c156Mark Brown *
831244e396fa9e4854cfd6dfe305983e77802c156Mark Brown * This program is free software; you can redistribute it and/or modify
931244e396fa9e4854cfd6dfe305983e77802c156Mark Brown * it under the terms of the GNU General Public License version 2 as
1031244e396fa9e4854cfd6dfe305983e77802c156Mark Brown * published by the Free Software Foundation.
1131244e396fa9e4854cfd6dfe305983e77802c156Mark Brown */
1231244e396fa9e4854cfd6dfe305983e77802c156Mark Brown
1331244e396fa9e4854cfd6dfe305983e77802c156Mark Brown#include <linux/slab.h>
1431244e396fa9e4854cfd6dfe305983e77802c156Mark Brown#include <linux/mutex.h>
1531244e396fa9e4854cfd6dfe305983e77802c156Mark Brown#include <linux/debugfs.h>
1631244e396fa9e4854cfd6dfe305983e77802c156Mark Brown#include <linux/uaccess.h>
1751990e825431089747f8896244b5c17d3a6423f1Paul Gortmaker#include <linux/device.h>
1831244e396fa9e4854cfd6dfe305983e77802c156Mark Brown
1931244e396fa9e4854cfd6dfe305983e77802c156Mark Brown#include "internal.h"
2031244e396fa9e4854cfd6dfe305983e77802c156Mark Brown
2131244e396fa9e4854cfd6dfe305983e77802c156Mark Brownstatic struct dentry *regmap_debugfs_root;
2231244e396fa9e4854cfd6dfe305983e77802c156Mark Brown
2321f555445676e5c7d30bb9b3487cb183d02e45e3Mark Brown/* Calculate the length of a fixed format  */
2421f555445676e5c7d30bb9b3487cb183d02e45e3Mark Brownstatic size_t regmap_calc_reg_len(int max_val, char *buf, size_t buf_size)
2521f555445676e5c7d30bb9b3487cb183d02e45e3Mark Brown{
2621f555445676e5c7d30bb9b3487cb183d02e45e3Mark Brown	snprintf(buf, buf_size, "%x", max_val);
2721f555445676e5c7d30bb9b3487cb183d02e45e3Mark Brown	return strlen(buf);
2821f555445676e5c7d30bb9b3487cb183d02e45e3Mark Brown}
2921f555445676e5c7d30bb9b3487cb183d02e45e3Mark Brown
30f0c2319f9f196726ebe4d7508fd8fbd804988db3Dimitris Papastamosstatic ssize_t regmap_name_read_file(struct file *file,
31f0c2319f9f196726ebe4d7508fd8fbd804988db3Dimitris Papastamos				     char __user *user_buf, size_t count,
32f0c2319f9f196726ebe4d7508fd8fbd804988db3Dimitris Papastamos				     loff_t *ppos)
33f0c2319f9f196726ebe4d7508fd8fbd804988db3Dimitris Papastamos{
34f0c2319f9f196726ebe4d7508fd8fbd804988db3Dimitris Papastamos	struct regmap *map = file->private_data;
35f0c2319f9f196726ebe4d7508fd8fbd804988db3Dimitris Papastamos	int ret;
36f0c2319f9f196726ebe4d7508fd8fbd804988db3Dimitris Papastamos	char *buf;
37f0c2319f9f196726ebe4d7508fd8fbd804988db3Dimitris Papastamos
38f0c2319f9f196726ebe4d7508fd8fbd804988db3Dimitris Papastamos	buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
39f0c2319f9f196726ebe4d7508fd8fbd804988db3Dimitris Papastamos	if (!buf)
40f0c2319f9f196726ebe4d7508fd8fbd804988db3Dimitris Papastamos		return -ENOMEM;
41f0c2319f9f196726ebe4d7508fd8fbd804988db3Dimitris Papastamos
42f0c2319f9f196726ebe4d7508fd8fbd804988db3Dimitris Papastamos	ret = snprintf(buf, PAGE_SIZE, "%s\n", map->dev->driver->name);
43f0c2319f9f196726ebe4d7508fd8fbd804988db3Dimitris Papastamos	if (ret < 0) {
44f0c2319f9f196726ebe4d7508fd8fbd804988db3Dimitris Papastamos		kfree(buf);
45f0c2319f9f196726ebe4d7508fd8fbd804988db3Dimitris Papastamos		return ret;
46f0c2319f9f196726ebe4d7508fd8fbd804988db3Dimitris Papastamos	}
47f0c2319f9f196726ebe4d7508fd8fbd804988db3Dimitris Papastamos
48f0c2319f9f196726ebe4d7508fd8fbd804988db3Dimitris Papastamos	ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
49f0c2319f9f196726ebe4d7508fd8fbd804988db3Dimitris Papastamos	kfree(buf);
50f0c2319f9f196726ebe4d7508fd8fbd804988db3Dimitris Papastamos	return ret;
51f0c2319f9f196726ebe4d7508fd8fbd804988db3Dimitris Papastamos}
52f0c2319f9f196726ebe4d7508fd8fbd804988db3Dimitris Papastamos
53f0c2319f9f196726ebe4d7508fd8fbd804988db3Dimitris Papastamosstatic const struct file_operations regmap_name_fops = {
54234e340582901211f40d8c732afc49f0630ecf05Stephen Boyd	.open = simple_open,
55f0c2319f9f196726ebe4d7508fd8fbd804988db3Dimitris Papastamos	.read = regmap_name_read_file,
56f0c2319f9f196726ebe4d7508fd8fbd804988db3Dimitris Papastamos	.llseek = default_llseek,
57f0c2319f9f196726ebe4d7508fd8fbd804988db3Dimitris Papastamos};
58f0c2319f9f196726ebe4d7508fd8fbd804988db3Dimitris Papastamos
5931244e396fa9e4854cfd6dfe305983e77802c156Mark Brownstatic ssize_t regmap_map_read_file(struct file *file, char __user *user_buf,
6031244e396fa9e4854cfd6dfe305983e77802c156Mark Brown				    size_t count, loff_t *ppos)
6131244e396fa9e4854cfd6dfe305983e77802c156Mark Brown{
62cb3c2dcfa34072b785cf292ca0b66494496572b9Mark Brown	int reg_len, val_len, tot_len;
6331244e396fa9e4854cfd6dfe305983e77802c156Mark Brown	size_t buf_pos = 0;
6431244e396fa9e4854cfd6dfe305983e77802c156Mark Brown	loff_t p = 0;
6531244e396fa9e4854cfd6dfe305983e77802c156Mark Brown	ssize_t ret;
6631244e396fa9e4854cfd6dfe305983e77802c156Mark Brown	int i;
6731244e396fa9e4854cfd6dfe305983e77802c156Mark Brown	struct regmap *map = file->private_data;
6831244e396fa9e4854cfd6dfe305983e77802c156Mark Brown	char *buf;
6931244e396fa9e4854cfd6dfe305983e77802c156Mark Brown	unsigned int val;
7031244e396fa9e4854cfd6dfe305983e77802c156Mark Brown
7131244e396fa9e4854cfd6dfe305983e77802c156Mark Brown	if (*ppos < 0 || !count)
7231244e396fa9e4854cfd6dfe305983e77802c156Mark Brown		return -EINVAL;
7331244e396fa9e4854cfd6dfe305983e77802c156Mark Brown
7431244e396fa9e4854cfd6dfe305983e77802c156Mark Brown	buf = kmalloc(count, GFP_KERNEL);
7531244e396fa9e4854cfd6dfe305983e77802c156Mark Brown	if (!buf)
7631244e396fa9e4854cfd6dfe305983e77802c156Mark Brown		return -ENOMEM;
7731244e396fa9e4854cfd6dfe305983e77802c156Mark Brown
7831244e396fa9e4854cfd6dfe305983e77802c156Mark Brown	/* Calculate the length of a fixed format  */
7921f555445676e5c7d30bb9b3487cb183d02e45e3Mark Brown	reg_len = regmap_calc_reg_len(map->max_register, buf, count);
8031244e396fa9e4854cfd6dfe305983e77802c156Mark Brown	val_len = 2 * map->format.val_bytes;
8131244e396fa9e4854cfd6dfe305983e77802c156Mark Brown	tot_len = reg_len + val_len + 3;      /* : \n */
8231244e396fa9e4854cfd6dfe305983e77802c156Mark Brown
83d813ae9a105219255c07d382059de831186c10d0Mark Brown	for (i = 0; i < map->max_register + 1; i++) {
848de2f081ef8ee716663f916df9f2a7d015fa0dadMark Brown		if (!regmap_readable(map, i))
8531244e396fa9e4854cfd6dfe305983e77802c156Mark Brown			continue;
8631244e396fa9e4854cfd6dfe305983e77802c156Mark Brown
878de2f081ef8ee716663f916df9f2a7d015fa0dadMark Brown		if (regmap_precious(map, i))
882efe1642b73e74604498175de032b8a604868fb7Mark Brown			continue;
892efe1642b73e74604498175de032b8a604868fb7Mark Brown
9031244e396fa9e4854cfd6dfe305983e77802c156Mark Brown		/* If we're in the region the user is trying to read */
9131244e396fa9e4854cfd6dfe305983e77802c156Mark Brown		if (p >= *ppos) {
9231244e396fa9e4854cfd6dfe305983e77802c156Mark Brown			/* ...but not beyond it */
9331244e396fa9e4854cfd6dfe305983e77802c156Mark Brown			if (buf_pos >= count - 1 - tot_len)
9431244e396fa9e4854cfd6dfe305983e77802c156Mark Brown				break;
9531244e396fa9e4854cfd6dfe305983e77802c156Mark Brown
9631244e396fa9e4854cfd6dfe305983e77802c156Mark Brown			/* Format the register */
9731244e396fa9e4854cfd6dfe305983e77802c156Mark Brown			snprintf(buf + buf_pos, count - buf_pos, "%.*x: ",
9831244e396fa9e4854cfd6dfe305983e77802c156Mark Brown				 reg_len, i);
9931244e396fa9e4854cfd6dfe305983e77802c156Mark Brown			buf_pos += reg_len + 2;
10031244e396fa9e4854cfd6dfe305983e77802c156Mark Brown
10131244e396fa9e4854cfd6dfe305983e77802c156Mark Brown			/* Format the value, write all X if we can't read */
10231244e396fa9e4854cfd6dfe305983e77802c156Mark Brown			ret = regmap_read(map, i, &val);
10331244e396fa9e4854cfd6dfe305983e77802c156Mark Brown			if (ret == 0)
10431244e396fa9e4854cfd6dfe305983e77802c156Mark Brown				snprintf(buf + buf_pos, count - buf_pos,
10531244e396fa9e4854cfd6dfe305983e77802c156Mark Brown					 "%.*x", val_len, val);
10631244e396fa9e4854cfd6dfe305983e77802c156Mark Brown			else
10731244e396fa9e4854cfd6dfe305983e77802c156Mark Brown				memset(buf + buf_pos, 'X', val_len);
10831244e396fa9e4854cfd6dfe305983e77802c156Mark Brown			buf_pos += 2 * map->format.val_bytes;
10931244e396fa9e4854cfd6dfe305983e77802c156Mark Brown
11031244e396fa9e4854cfd6dfe305983e77802c156Mark Brown			buf[buf_pos++] = '\n';
11131244e396fa9e4854cfd6dfe305983e77802c156Mark Brown		}
11231244e396fa9e4854cfd6dfe305983e77802c156Mark Brown		p += tot_len;
11331244e396fa9e4854cfd6dfe305983e77802c156Mark Brown	}
11431244e396fa9e4854cfd6dfe305983e77802c156Mark Brown
11531244e396fa9e4854cfd6dfe305983e77802c156Mark Brown	ret = buf_pos;
11631244e396fa9e4854cfd6dfe305983e77802c156Mark Brown
11731244e396fa9e4854cfd6dfe305983e77802c156Mark Brown	if (copy_to_user(user_buf, buf, buf_pos)) {
11831244e396fa9e4854cfd6dfe305983e77802c156Mark Brown		ret = -EFAULT;
11931244e396fa9e4854cfd6dfe305983e77802c156Mark Brown		goto out;
12031244e396fa9e4854cfd6dfe305983e77802c156Mark Brown	}
12131244e396fa9e4854cfd6dfe305983e77802c156Mark Brown
12231244e396fa9e4854cfd6dfe305983e77802c156Mark Brown	*ppos += buf_pos;
12331244e396fa9e4854cfd6dfe305983e77802c156Mark Brown
12431244e396fa9e4854cfd6dfe305983e77802c156Mark Brownout:
12531244e396fa9e4854cfd6dfe305983e77802c156Mark Brown	kfree(buf);
12631244e396fa9e4854cfd6dfe305983e77802c156Mark Brown	return ret;
12731244e396fa9e4854cfd6dfe305983e77802c156Mark Brown}
12831244e396fa9e4854cfd6dfe305983e77802c156Mark Brown
12909c6ecd394105c4864a0e409e181c9b1578c2a63Dimitris Papastamos#undef REGMAP_ALLOW_WRITE_DEBUGFS
13009c6ecd394105c4864a0e409e181c9b1578c2a63Dimitris Papastamos#ifdef REGMAP_ALLOW_WRITE_DEBUGFS
13109c6ecd394105c4864a0e409e181c9b1578c2a63Dimitris Papastamos/*
13209c6ecd394105c4864a0e409e181c9b1578c2a63Dimitris Papastamos * This can be dangerous especially when we have clients such as
13309c6ecd394105c4864a0e409e181c9b1578c2a63Dimitris Papastamos * PMICs, therefore don't provide any real compile time configuration option
13409c6ecd394105c4864a0e409e181c9b1578c2a63Dimitris Papastamos * for this feature, people who want to use this will need to modify
13509c6ecd394105c4864a0e409e181c9b1578c2a63Dimitris Papastamos * the source code directly.
13609c6ecd394105c4864a0e409e181c9b1578c2a63Dimitris Papastamos */
13709c6ecd394105c4864a0e409e181c9b1578c2a63Dimitris Papastamosstatic ssize_t regmap_map_write_file(struct file *file,
13809c6ecd394105c4864a0e409e181c9b1578c2a63Dimitris Papastamos				     const char __user *user_buf,
13909c6ecd394105c4864a0e409e181c9b1578c2a63Dimitris Papastamos				     size_t count, loff_t *ppos)
14009c6ecd394105c4864a0e409e181c9b1578c2a63Dimitris Papastamos{
14109c6ecd394105c4864a0e409e181c9b1578c2a63Dimitris Papastamos	char buf[32];
14209c6ecd394105c4864a0e409e181c9b1578c2a63Dimitris Papastamos	size_t buf_size;
14309c6ecd394105c4864a0e409e181c9b1578c2a63Dimitris Papastamos	char *start = buf;
14409c6ecd394105c4864a0e409e181c9b1578c2a63Dimitris Papastamos	unsigned long reg, value;
14509c6ecd394105c4864a0e409e181c9b1578c2a63Dimitris Papastamos	struct regmap *map = file->private_data;
14609c6ecd394105c4864a0e409e181c9b1578c2a63Dimitris Papastamos
14709c6ecd394105c4864a0e409e181c9b1578c2a63Dimitris Papastamos	buf_size = min(count, (sizeof(buf)-1));
14809c6ecd394105c4864a0e409e181c9b1578c2a63Dimitris Papastamos	if (copy_from_user(buf, user_buf, buf_size))
14909c6ecd394105c4864a0e409e181c9b1578c2a63Dimitris Papastamos		return -EFAULT;
15009c6ecd394105c4864a0e409e181c9b1578c2a63Dimitris Papastamos	buf[buf_size] = 0;
15109c6ecd394105c4864a0e409e181c9b1578c2a63Dimitris Papastamos
15209c6ecd394105c4864a0e409e181c9b1578c2a63Dimitris Papastamos	while (*start == ' ')
15309c6ecd394105c4864a0e409e181c9b1578c2a63Dimitris Papastamos		start++;
15409c6ecd394105c4864a0e409e181c9b1578c2a63Dimitris Papastamos	reg = simple_strtoul(start, &start, 16);
15509c6ecd394105c4864a0e409e181c9b1578c2a63Dimitris Papastamos	while (*start == ' ')
15609c6ecd394105c4864a0e409e181c9b1578c2a63Dimitris Papastamos		start++;
15709c6ecd394105c4864a0e409e181c9b1578c2a63Dimitris Papastamos	if (strict_strtoul(start, 16, &value))
15809c6ecd394105c4864a0e409e181c9b1578c2a63Dimitris Papastamos		return -EINVAL;
15909c6ecd394105c4864a0e409e181c9b1578c2a63Dimitris Papastamos
16009c6ecd394105c4864a0e409e181c9b1578c2a63Dimitris Papastamos	/* Userspace has been fiddling around behind the kernel's back */
16109c6ecd394105c4864a0e409e181c9b1578c2a63Dimitris Papastamos	add_taint(TAINT_USER);
16209c6ecd394105c4864a0e409e181c9b1578c2a63Dimitris Papastamos
16309c6ecd394105c4864a0e409e181c9b1578c2a63Dimitris Papastamos	regmap_write(map, reg, value);
16409c6ecd394105c4864a0e409e181c9b1578c2a63Dimitris Papastamos	return buf_size;
16509c6ecd394105c4864a0e409e181c9b1578c2a63Dimitris Papastamos}
16609c6ecd394105c4864a0e409e181c9b1578c2a63Dimitris Papastamos#else
16709c6ecd394105c4864a0e409e181c9b1578c2a63Dimitris Papastamos#define regmap_map_write_file NULL
16809c6ecd394105c4864a0e409e181c9b1578c2a63Dimitris Papastamos#endif
16909c6ecd394105c4864a0e409e181c9b1578c2a63Dimitris Papastamos
17031244e396fa9e4854cfd6dfe305983e77802c156Mark Brownstatic const struct file_operations regmap_map_fops = {
171234e340582901211f40d8c732afc49f0630ecf05Stephen Boyd	.open = simple_open,
17231244e396fa9e4854cfd6dfe305983e77802c156Mark Brown	.read = regmap_map_read_file,
17309c6ecd394105c4864a0e409e181c9b1578c2a63Dimitris Papastamos	.write = regmap_map_write_file,
17431244e396fa9e4854cfd6dfe305983e77802c156Mark Brown	.llseek = default_llseek,
17531244e396fa9e4854cfd6dfe305983e77802c156Mark Brown};
17631244e396fa9e4854cfd6dfe305983e77802c156Mark Brown
177449e38427fe57a6120fecd1051981c89ee862b3dMark Brownstatic ssize_t regmap_access_read_file(struct file *file,
178449e38427fe57a6120fecd1051981c89ee862b3dMark Brown				       char __user *user_buf, size_t count,
179449e38427fe57a6120fecd1051981c89ee862b3dMark Brown				       loff_t *ppos)
180449e38427fe57a6120fecd1051981c89ee862b3dMark Brown{
181449e38427fe57a6120fecd1051981c89ee862b3dMark Brown	int reg_len, tot_len;
182449e38427fe57a6120fecd1051981c89ee862b3dMark Brown	size_t buf_pos = 0;
183449e38427fe57a6120fecd1051981c89ee862b3dMark Brown	loff_t p = 0;
184449e38427fe57a6120fecd1051981c89ee862b3dMark Brown	ssize_t ret;
185449e38427fe57a6120fecd1051981c89ee862b3dMark Brown	int i;
186449e38427fe57a6120fecd1051981c89ee862b3dMark Brown	struct regmap *map = file->private_data;
187449e38427fe57a6120fecd1051981c89ee862b3dMark Brown	char *buf;
188449e38427fe57a6120fecd1051981c89ee862b3dMark Brown
189449e38427fe57a6120fecd1051981c89ee862b3dMark Brown	if (*ppos < 0 || !count)
190449e38427fe57a6120fecd1051981c89ee862b3dMark Brown		return -EINVAL;
191449e38427fe57a6120fecd1051981c89ee862b3dMark Brown
192449e38427fe57a6120fecd1051981c89ee862b3dMark Brown	buf = kmalloc(count, GFP_KERNEL);
193449e38427fe57a6120fecd1051981c89ee862b3dMark Brown	if (!buf)
194449e38427fe57a6120fecd1051981c89ee862b3dMark Brown		return -ENOMEM;
195449e38427fe57a6120fecd1051981c89ee862b3dMark Brown
196449e38427fe57a6120fecd1051981c89ee862b3dMark Brown	/* Calculate the length of a fixed format  */
197449e38427fe57a6120fecd1051981c89ee862b3dMark Brown	reg_len = regmap_calc_reg_len(map->max_register, buf, count);
198449e38427fe57a6120fecd1051981c89ee862b3dMark Brown	tot_len = reg_len + 10; /* ': R W V P\n' */
199449e38427fe57a6120fecd1051981c89ee862b3dMark Brown
200d813ae9a105219255c07d382059de831186c10d0Mark Brown	for (i = 0; i < map->max_register + 1; i++) {
201449e38427fe57a6120fecd1051981c89ee862b3dMark Brown		/* Ignore registers which are neither readable nor writable */
202449e38427fe57a6120fecd1051981c89ee862b3dMark Brown		if (!regmap_readable(map, i) && !regmap_writeable(map, i))
203449e38427fe57a6120fecd1051981c89ee862b3dMark Brown			continue;
204449e38427fe57a6120fecd1051981c89ee862b3dMark Brown
205449e38427fe57a6120fecd1051981c89ee862b3dMark Brown		/* If we're in the region the user is trying to read */
206449e38427fe57a6120fecd1051981c89ee862b3dMark Brown		if (p >= *ppos) {
207449e38427fe57a6120fecd1051981c89ee862b3dMark Brown			/* ...but not beyond it */
208449e38427fe57a6120fecd1051981c89ee862b3dMark Brown			if (buf_pos >= count - 1 - tot_len)
209449e38427fe57a6120fecd1051981c89ee862b3dMark Brown				break;
210449e38427fe57a6120fecd1051981c89ee862b3dMark Brown
211449e38427fe57a6120fecd1051981c89ee862b3dMark Brown			/* Format the register */
212449e38427fe57a6120fecd1051981c89ee862b3dMark Brown			snprintf(buf + buf_pos, count - buf_pos,
213449e38427fe57a6120fecd1051981c89ee862b3dMark Brown				 "%.*x: %c %c %c %c\n",
214449e38427fe57a6120fecd1051981c89ee862b3dMark Brown				 reg_len, i,
215449e38427fe57a6120fecd1051981c89ee862b3dMark Brown				 regmap_readable(map, i) ? 'y' : 'n',
216449e38427fe57a6120fecd1051981c89ee862b3dMark Brown				 regmap_writeable(map, i) ? 'y' : 'n',
217449e38427fe57a6120fecd1051981c89ee862b3dMark Brown				 regmap_volatile(map, i) ? 'y' : 'n',
218449e38427fe57a6120fecd1051981c89ee862b3dMark Brown				 regmap_precious(map, i) ? 'y' : 'n');
219449e38427fe57a6120fecd1051981c89ee862b3dMark Brown
220449e38427fe57a6120fecd1051981c89ee862b3dMark Brown			buf_pos += tot_len;
221449e38427fe57a6120fecd1051981c89ee862b3dMark Brown		}
222449e38427fe57a6120fecd1051981c89ee862b3dMark Brown		p += tot_len;
223449e38427fe57a6120fecd1051981c89ee862b3dMark Brown	}
224449e38427fe57a6120fecd1051981c89ee862b3dMark Brown
225449e38427fe57a6120fecd1051981c89ee862b3dMark Brown	ret = buf_pos;
226449e38427fe57a6120fecd1051981c89ee862b3dMark Brown
227449e38427fe57a6120fecd1051981c89ee862b3dMark Brown	if (copy_to_user(user_buf, buf, buf_pos)) {
228449e38427fe57a6120fecd1051981c89ee862b3dMark Brown		ret = -EFAULT;
229449e38427fe57a6120fecd1051981c89ee862b3dMark Brown		goto out;
230449e38427fe57a6120fecd1051981c89ee862b3dMark Brown	}
231449e38427fe57a6120fecd1051981c89ee862b3dMark Brown
232449e38427fe57a6120fecd1051981c89ee862b3dMark Brown	*ppos += buf_pos;
233449e38427fe57a6120fecd1051981c89ee862b3dMark Brown
234449e38427fe57a6120fecd1051981c89ee862b3dMark Brownout:
235449e38427fe57a6120fecd1051981c89ee862b3dMark Brown	kfree(buf);
236449e38427fe57a6120fecd1051981c89ee862b3dMark Brown	return ret;
237449e38427fe57a6120fecd1051981c89ee862b3dMark Brown}
238449e38427fe57a6120fecd1051981c89ee862b3dMark Brown
239449e38427fe57a6120fecd1051981c89ee862b3dMark Brownstatic const struct file_operations regmap_access_fops = {
240234e340582901211f40d8c732afc49f0630ecf05Stephen Boyd	.open = simple_open,
241449e38427fe57a6120fecd1051981c89ee862b3dMark Brown	.read = regmap_access_read_file,
242449e38427fe57a6120fecd1051981c89ee862b3dMark Brown	.llseek = default_llseek,
243449e38427fe57a6120fecd1051981c89ee862b3dMark Brown};
24431244e396fa9e4854cfd6dfe305983e77802c156Mark Brown
24531244e396fa9e4854cfd6dfe305983e77802c156Mark Brownvoid regmap_debugfs_init(struct regmap *map)
24631244e396fa9e4854cfd6dfe305983e77802c156Mark Brown{
24731244e396fa9e4854cfd6dfe305983e77802c156Mark Brown	map->debugfs = debugfs_create_dir(dev_name(map->dev),
24831244e396fa9e4854cfd6dfe305983e77802c156Mark Brown					  regmap_debugfs_root);
24931244e396fa9e4854cfd6dfe305983e77802c156Mark Brown	if (!map->debugfs) {
25031244e396fa9e4854cfd6dfe305983e77802c156Mark Brown		dev_warn(map->dev, "Failed to create debugfs directory\n");
25131244e396fa9e4854cfd6dfe305983e77802c156Mark Brown		return;
25231244e396fa9e4854cfd6dfe305983e77802c156Mark Brown	}
25331244e396fa9e4854cfd6dfe305983e77802c156Mark Brown
254f0c2319f9f196726ebe4d7508fd8fbd804988db3Dimitris Papastamos	debugfs_create_file("name", 0400, map->debugfs,
255f0c2319f9f196726ebe4d7508fd8fbd804988db3Dimitris Papastamos			    map, &regmap_name_fops);
256f0c2319f9f196726ebe4d7508fd8fbd804988db3Dimitris Papastamos
257449e38427fe57a6120fecd1051981c89ee862b3dMark Brown	if (map->max_register) {
25831244e396fa9e4854cfd6dfe305983e77802c156Mark Brown		debugfs_create_file("registers", 0400, map->debugfs,
25931244e396fa9e4854cfd6dfe305983e77802c156Mark Brown				    map, &regmap_map_fops);
260449e38427fe57a6120fecd1051981c89ee862b3dMark Brown		debugfs_create_file("access", 0400, map->debugfs,
261449e38427fe57a6120fecd1051981c89ee862b3dMark Brown				    map, &regmap_access_fops);
262449e38427fe57a6120fecd1051981c89ee862b3dMark Brown	}
263028a01e601487b5991b70dba506dfe87d83543f6Mark Brown
264028a01e601487b5991b70dba506dfe87d83543f6Mark Brown	if (map->cache_type) {
265028a01e601487b5991b70dba506dfe87d83543f6Mark Brown		debugfs_create_bool("cache_only", 0400, map->debugfs,
266028a01e601487b5991b70dba506dfe87d83543f6Mark Brown				    &map->cache_only);
267028a01e601487b5991b70dba506dfe87d83543f6Mark Brown		debugfs_create_bool("cache_dirty", 0400, map->debugfs,
268028a01e601487b5991b70dba506dfe87d83543f6Mark Brown				    &map->cache_dirty);
269028a01e601487b5991b70dba506dfe87d83543f6Mark Brown		debugfs_create_bool("cache_bypass", 0400, map->debugfs,
270028a01e601487b5991b70dba506dfe87d83543f6Mark Brown				    &map->cache_bypass);
271028a01e601487b5991b70dba506dfe87d83543f6Mark Brown	}
27231244e396fa9e4854cfd6dfe305983e77802c156Mark Brown}
27331244e396fa9e4854cfd6dfe305983e77802c156Mark Brown
27431244e396fa9e4854cfd6dfe305983e77802c156Mark Brownvoid regmap_debugfs_exit(struct regmap *map)
27531244e396fa9e4854cfd6dfe305983e77802c156Mark Brown{
27631244e396fa9e4854cfd6dfe305983e77802c156Mark Brown	debugfs_remove_recursive(map->debugfs);
27731244e396fa9e4854cfd6dfe305983e77802c156Mark Brown}
27831244e396fa9e4854cfd6dfe305983e77802c156Mark Brown
27931244e396fa9e4854cfd6dfe305983e77802c156Mark Brownvoid regmap_debugfs_initcall(void)
28031244e396fa9e4854cfd6dfe305983e77802c156Mark Brown{
28131244e396fa9e4854cfd6dfe305983e77802c156Mark Brown	regmap_debugfs_root = debugfs_create_dir("regmap", NULL);
28231244e396fa9e4854cfd6dfe305983e77802c156Mark Brown	if (!regmap_debugfs_root) {
28331244e396fa9e4854cfd6dfe305983e77802c156Mark Brown		pr_warn("regmap: Failed to create debugfs root\n");
28431244e396fa9e4854cfd6dfe305983e77802c156Mark Brown		return;
28531244e396fa9e4854cfd6dfe305983e77802c156Mark Brown	}
28631244e396fa9e4854cfd6dfe305983e77802c156Mark Brown}
287