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

Commit 84fb9015 authored by Mark Brown's avatar Mark Brown
Browse files

Merge remote-tracking branches 'regmap/topic/debugfs' and...

Merge remote-tracking branches 'regmap/topic/debugfs' and 'regmap/topic/force-update' into regmap-next
Loading
Loading
Loading
Loading
+91 −8
Original line number Diff line number Diff line
@@ -469,6 +469,87 @@ static const struct file_operations regmap_access_fops = {
	.llseek = default_llseek,
};

static ssize_t regmap_cache_only_write_file(struct file *file,
					    const char __user *user_buf,
					    size_t count, loff_t *ppos)
{
	struct regmap *map = container_of(file->private_data,
					  struct regmap, cache_only);
	ssize_t result;
	bool was_enabled, require_sync = false;
	int err;

	map->lock(map->lock_arg);

	was_enabled = map->cache_only;

	result = debugfs_write_file_bool(file, user_buf, count, ppos);
	if (result < 0) {
		map->unlock(map->lock_arg);
		return result;
	}

	if (map->cache_only && !was_enabled) {
		dev_warn(map->dev, "debugfs cache_only=Y forced\n");
		add_taint(TAINT_USER, LOCKDEP_STILL_OK);
	} else if (!map->cache_only && was_enabled) {
		dev_warn(map->dev, "debugfs cache_only=N forced: syncing cache\n");
		require_sync = true;
	}

	map->unlock(map->lock_arg);

	if (require_sync) {
		err = regcache_sync(map);
		if (err)
			dev_err(map->dev, "Failed to sync cache %d\n", err);
	}

	return result;
}

static const struct file_operations regmap_cache_only_fops = {
	.open = simple_open,
	.read = debugfs_read_file_bool,
	.write = regmap_cache_only_write_file,
};

static ssize_t regmap_cache_bypass_write_file(struct file *file,
					      const char __user *user_buf,
					      size_t count, loff_t *ppos)
{
	struct regmap *map = container_of(file->private_data,
					  struct regmap, cache_bypass);
	ssize_t result;
	bool was_enabled;

	map->lock(map->lock_arg);

	was_enabled = map->cache_bypass;

	result = debugfs_write_file_bool(file, user_buf, count, ppos);
	if (result < 0)
		goto out;

	if (map->cache_bypass && !was_enabled) {
		dev_warn(map->dev, "debugfs cache_bypass=Y forced\n");
		add_taint(TAINT_USER, LOCKDEP_STILL_OK);
	} else if (!map->cache_bypass && was_enabled) {
		dev_warn(map->dev, "debugfs cache_bypass=N forced\n");
	}

out:
	map->unlock(map->lock_arg);

	return result;
}

static const struct file_operations regmap_cache_bypass_fops = {
	.open = simple_open,
	.read = debugfs_read_file_bool,
	.write = regmap_cache_bypass_write_file,
};

void regmap_debugfs_init(struct regmap *map, const char *name)
{
	struct rb_node *next;
@@ -518,10 +599,11 @@ void regmap_debugfs_init(struct regmap *map, const char *name)
	if (map->max_register || regmap_readable(map, 0)) {
		umode_t registers_mode;

		if (IS_ENABLED(REGMAP_ALLOW_WRITE_DEBUGFS))
#if defined(REGMAP_ALLOW_WRITE_DEBUGFS)
		registers_mode = 0600;
		else
#else
		registers_mode = 0400;
#endif

		debugfs_create_file("registers", registers_mode, map->debugfs,
				    map, &regmap_map_fops);
@@ -530,12 +612,13 @@ void regmap_debugfs_init(struct regmap *map, const char *name)
	}

	if (map->cache_type) {
		debugfs_create_bool("cache_only", 0400, map->debugfs,
				    &map->cache_only);
		debugfs_create_file("cache_only", 0600, map->debugfs,
				    &map->cache_only, &regmap_cache_only_fops);
		debugfs_create_bool("cache_dirty", 0400, map->debugfs,
				    &map->cache_dirty);
		debugfs_create_bool("cache_bypass", 0400, map->debugfs,
				    &map->cache_bypass);
		debugfs_create_file("cache_bypass", 0600, map->debugfs,
				    &map->cache_bypass,
				    &regmap_cache_bypass_fops);
	}

	next = rb_first(&map->range_tree);
+43 −8
Original line number Diff line number Diff line
@@ -34,7 +34,7 @@

static int _regmap_update_bits(struct regmap *map, unsigned int reg,
			       unsigned int mask, unsigned int val,
			       bool *change);
			       bool *change, bool force_write);

static int _regmap_bus_reg_read(void *context, unsigned int reg,
				unsigned int *val);
@@ -1186,7 +1186,7 @@ static int _regmap_select_page(struct regmap *map, unsigned int *reg,
		ret = _regmap_update_bits(map, range->selector_reg,
					  range->selector_mask,
					  win_page << range->selector_shift,
					  &page_chg);
					  &page_chg, false);

		map->work_buf = orig_work_buf;

@@ -1657,6 +1657,18 @@ int regmap_fields_write(struct regmap_field *field, unsigned int id,
}
EXPORT_SYMBOL_GPL(regmap_fields_write);

int regmap_fields_force_write(struct regmap_field *field, unsigned int id,
			unsigned int val)
{
	if (id >= field->id_size)
		return -EINVAL;

	return regmap_write_bits(field->regmap,
				  field->reg + (field->id_offset * id),
				  field->mask, val << field->shift);
}
EXPORT_SYMBOL_GPL(regmap_fields_force_write);

/**
 * regmap_fields_update_bits():	Perform a read/modify/write cycle
 *                              on the register field
@@ -2466,7 +2478,7 @@ EXPORT_SYMBOL_GPL(regmap_bulk_read);

static int _regmap_update_bits(struct regmap *map, unsigned int reg,
			       unsigned int mask, unsigned int val,
			       bool *change)
			       bool *change, bool force_write)
{
	int ret;
	unsigned int tmp, orig;
@@ -2478,7 +2490,7 @@ static int _regmap_update_bits(struct regmap *map, unsigned int reg,
	tmp = orig & ~mask;
	tmp |= val & mask;

	if (tmp != orig) {
	if (force_write || (tmp != orig)) {
		ret = _regmap_write(map, reg, tmp);
		if (change)
			*change = true;
@@ -2506,13 +2518,36 @@ int regmap_update_bits(struct regmap *map, unsigned int reg,
	int ret;

	map->lock(map->lock_arg);
	ret = _regmap_update_bits(map, reg, mask, val, NULL);
	ret = _regmap_update_bits(map, reg, mask, val, NULL, false);
	map->unlock(map->lock_arg);

	return ret;
}
EXPORT_SYMBOL_GPL(regmap_update_bits);

/**
 * regmap_write_bits: Perform a read/modify/write cycle on the register map
 *
 * @map: Register map to update
 * @reg: Register to update
 * @mask: Bitmask to change
 * @val: New value for bitmask
 *
 * Returns zero for success, a negative number on error.
 */
int regmap_write_bits(struct regmap *map, unsigned int reg,
		      unsigned int mask, unsigned int val)
{
	int ret;

	map->lock(map->lock_arg);
	ret = _regmap_update_bits(map, reg, mask, val, NULL, true);
	map->unlock(map->lock_arg);

	return ret;
}
EXPORT_SYMBOL_GPL(regmap_write_bits);

/**
 * regmap_update_bits_async: Perform a read/modify/write cycle on the register
 *                           map asynchronously
@@ -2537,7 +2572,7 @@ int regmap_update_bits_async(struct regmap *map, unsigned int reg,

	map->async = true;

	ret = _regmap_update_bits(map, reg, mask, val, NULL);
	ret = _regmap_update_bits(map, reg, mask, val, NULL, false);

	map->async = false;

@@ -2566,7 +2601,7 @@ int regmap_update_bits_check(struct regmap *map, unsigned int reg,
	int ret;

	map->lock(map->lock_arg);
	ret = _regmap_update_bits(map, reg, mask, val, change);
	ret = _regmap_update_bits(map, reg, mask, val, change, false);
	map->unlock(map->lock_arg);
	return ret;
}
@@ -2599,7 +2634,7 @@ int regmap_update_bits_check_async(struct regmap *map, unsigned int reg,

	map->async = true;

	ret = _regmap_update_bits(map, reg, mask, val, change);
	ret = _regmap_update_bits(map, reg, mask, val, change, false);

	map->async = false;

+1 −1
Original line number Diff line number Diff line
@@ -1244,7 +1244,7 @@ static struct regulator *create_regulator(struct regulator_dev *rdev,
	regulator->debugfs = debugfs_create_dir(regulator->supply_name,
						rdev->debugfs);
	if (!regulator->debugfs) {
		rdev_warn(rdev, "Failed to create debugfs directory\n");
		rdev_dbg(rdev, "Failed to create debugfs directory\n");
	} else {
		debugfs_create_u32("uA_load", 0444, regulator->debugfs,
				   &regulator->uA_load);
+8 −6
Original line number Diff line number Diff line
@@ -435,7 +435,7 @@ struct dentry *debugfs_create_atomic_t(const char *name, umode_t mode,
}
EXPORT_SYMBOL_GPL(debugfs_create_atomic_t);

static ssize_t read_file_bool(struct file *file, char __user *user_buf,
ssize_t debugfs_read_file_bool(struct file *file, char __user *user_buf,
			       size_t count, loff_t *ppos)
{
	char buf[3];
@@ -449,8 +449,9 @@ static ssize_t read_file_bool(struct file *file, char __user *user_buf,
	buf[2] = 0x00;
	return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
}
EXPORT_SYMBOL_GPL(debugfs_read_file_bool);

static ssize_t write_file_bool(struct file *file, const char __user *user_buf,
ssize_t debugfs_write_file_bool(struct file *file, const char __user *user_buf,
				size_t count, loff_t *ppos)
{
	char buf[32];
@@ -468,10 +469,11 @@ static ssize_t write_file_bool(struct file *file, const char __user *user_buf,

	return count;
}
EXPORT_SYMBOL_GPL(debugfs_write_file_bool);

static const struct file_operations fops_bool = {
	.read =		read_file_bool,
	.write =	write_file_bool,
	.read =		debugfs_read_file_bool,
	.write =	debugfs_write_file_bool,
	.open =		simple_open,
	.llseek =	default_llseek,
};
+20 −0
Original line number Diff line number Diff line
@@ -116,6 +116,12 @@ struct dentry *debugfs_create_devm_seqfile(struct device *dev, const char *name,

bool debugfs_initialized(void);

ssize_t debugfs_read_file_bool(struct file *file, char __user *user_buf,
			       size_t count, loff_t *ppos);

ssize_t debugfs_write_file_bool(struct file *file, const char __user *user_buf,
				size_t count, loff_t *ppos);

#else

#include <linux/err.h>
@@ -282,6 +288,20 @@ static inline struct dentry *debugfs_create_devm_seqfile(struct device *dev,
	return ERR_PTR(-ENODEV);
}

static inline ssize_t debugfs_read_file_bool(struct file *file,
					     char __user *user_buf,
					     size_t count, loff_t *ppos)
{
	return -ENODEV;
}

static inline ssize_t debugfs_write_file_bool(struct file *file,
					      const char __user *user_buf,
					      size_t count, loff_t *ppos)
{
	return -ENODEV;
}

#endif

#endif
Loading