Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 686d2158 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "regmap: improve debugfs interface to dump specific addresses"

parents 67cf9acd 1a113794
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -53,3 +53,12 @@ config REGMAP_SCCB
config REGMAP_I3C
	tristate
	depends on I3C

config REGMAP_QTI_DEBUG
	bool "Regmap QTI debug feature support"
	depends on REGMAP && DEBUG_FS && QGKI
	help
	  Say yes to enable QTI debug features.  This provides a runtime debugfs
	  interface to read and write a subset of regmap registers.  This
	  interface is more performant and easier to use than the traditional
	  method which dumps all registers defined in a given regmap.
+5 −0
Original line number Diff line number Diff line
@@ -84,6 +84,11 @@ struct regmap {

	struct list_head debugfs_off_cache;
	struct mutex cache_lock;

#ifdef CONFIG_REGMAP_QTI_DEBUG
	unsigned int dump_address;
	unsigned int dump_count;
#endif
#endif

	unsigned int max_register;
+73 −0
Original line number Diff line number Diff line
@@ -339,6 +339,69 @@ static const struct file_operations regmap_map_fops = {
	.llseek = default_llseek,
};

#ifdef CONFIG_REGMAP_QTI_DEBUG
static ssize_t regmap_data_read_file(struct file *file, char __user *user_buf,
				    size_t count, loff_t *ppos)
{
	struct regmap *map = file->private_data;
	int new_count;

	regmap_calc_tot_len(map, NULL, 0);
	new_count = map->dump_count * map->debugfs_tot_len;
	if (new_count > count)
		new_count = count;

	if (*ppos == 0)
		*ppos = map->dump_address * map->debugfs_tot_len;
	else if (*ppos >= map->dump_address * map->debugfs_tot_len
			+ map->dump_count * map->debugfs_tot_len)
		return 0;
	return regmap_read_debugfs(map, 0, map->max_register, user_buf,
			new_count, ppos);
}

#ifdef REGMAP_ALLOW_WRITE_DEBUGFS
static ssize_t regmap_data_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 value;
	struct regmap *map = file->private_data;
	int ret;

	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++;
	if (kstrtoul(start, 16, &value))
		return -EINVAL;

	/* Userspace has been fiddling around behind the kernel's back */
	add_taint(TAINT_USER, LOCKDEP_STILL_OK);

	ret = regmap_write(map, map->dump_address, value);
	if (ret < 0)
		return ret;
	return buf_size;
}
#else
#define regmap_data_write_file NULL
#endif

static const struct file_operations regmap_data_fops = {
	.open = simple_open,
	.read = regmap_data_read_file,
	.write = regmap_data_write_file,
	.llseek = default_llseek,
};
#endif

static ssize_t regmap_range_read_file(struct file *file, char __user *user_buf,
				      size_t count, loff_t *ppos)
{
@@ -608,6 +671,16 @@ void regmap_debugfs_init(struct regmap *map, const char *name)
				    map, &regmap_map_fops);
		debugfs_create_file("access", 0400, map->debugfs,
				    map, &regmap_access_fops);

#ifdef CONFIG_REGMAP_QTI_DEBUG
		debugfs_create_x32("address", 0600, map->debugfs,
				    &map->dump_address);
		map->dump_count = 1;
		debugfs_create_u32("count", 0600, map->debugfs,
				    &map->dump_count);
		debugfs_create_file("data", registers_mode, map->debugfs,
				    map, &regmap_data_fops);
#endif
	}

	if (map->cache_type) {