Merge remote-tracking branches 'regmap/topic/debugfs' and 'regmap/topic/force-update' into regmap-next
This commit is contained in:
commit
84fb9015d2
6 changed files with 174 additions and 23 deletions
|
@ -469,6 +469,87 @@ static const struct file_operations regmap_access_fops = {
|
||||||
.llseek = default_llseek,
|
.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)
|
void regmap_debugfs_init(struct regmap *map, const char *name)
|
||||||
{
|
{
|
||||||
struct rb_node *next;
|
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)) {
|
if (map->max_register || regmap_readable(map, 0)) {
|
||||||
umode_t registers_mode;
|
umode_t registers_mode;
|
||||||
|
|
||||||
if (IS_ENABLED(REGMAP_ALLOW_WRITE_DEBUGFS))
|
#if defined(REGMAP_ALLOW_WRITE_DEBUGFS)
|
||||||
registers_mode = 0600;
|
registers_mode = 0600;
|
||||||
else
|
#else
|
||||||
registers_mode = 0400;
|
registers_mode = 0400;
|
||||||
|
#endif
|
||||||
|
|
||||||
debugfs_create_file("registers", registers_mode, map->debugfs,
|
debugfs_create_file("registers", registers_mode, map->debugfs,
|
||||||
map, ®map_map_fops);
|
map, ®map_map_fops);
|
||||||
|
@ -530,12 +612,13 @@ void regmap_debugfs_init(struct regmap *map, const char *name)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (map->cache_type) {
|
if (map->cache_type) {
|
||||||
debugfs_create_bool("cache_only", 0400, map->debugfs,
|
debugfs_create_file("cache_only", 0600, map->debugfs,
|
||||||
&map->cache_only);
|
&map->cache_only, ®map_cache_only_fops);
|
||||||
debugfs_create_bool("cache_dirty", 0400, map->debugfs,
|
debugfs_create_bool("cache_dirty", 0400, map->debugfs,
|
||||||
&map->cache_dirty);
|
&map->cache_dirty);
|
||||||
debugfs_create_bool("cache_bypass", 0400, map->debugfs,
|
debugfs_create_file("cache_bypass", 0600, map->debugfs,
|
||||||
&map->cache_bypass);
|
&map->cache_bypass,
|
||||||
|
®map_cache_bypass_fops);
|
||||||
}
|
}
|
||||||
|
|
||||||
next = rb_first(&map->range_tree);
|
next = rb_first(&map->range_tree);
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
|
|
||||||
static int _regmap_update_bits(struct regmap *map, unsigned int reg,
|
static int _regmap_update_bits(struct regmap *map, unsigned int reg,
|
||||||
unsigned int mask, unsigned int val,
|
unsigned int mask, unsigned int val,
|
||||||
bool *change);
|
bool *change, bool force_write);
|
||||||
|
|
||||||
static int _regmap_bus_reg_read(void *context, unsigned int reg,
|
static int _regmap_bus_reg_read(void *context, unsigned int reg,
|
||||||
unsigned int *val);
|
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,
|
ret = _regmap_update_bits(map, range->selector_reg,
|
||||||
range->selector_mask,
|
range->selector_mask,
|
||||||
win_page << range->selector_shift,
|
win_page << range->selector_shift,
|
||||||
&page_chg);
|
&page_chg, false);
|
||||||
|
|
||||||
map->work_buf = orig_work_buf;
|
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);
|
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
|
* regmap_fields_update_bits(): Perform a read/modify/write cycle
|
||||||
* on the register field
|
* 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,
|
static int _regmap_update_bits(struct regmap *map, unsigned int reg,
|
||||||
unsigned int mask, unsigned int val,
|
unsigned int mask, unsigned int val,
|
||||||
bool *change)
|
bool *change, bool force_write)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
unsigned int tmp, orig;
|
unsigned int tmp, orig;
|
||||||
|
@ -2478,7 +2490,7 @@ static int _regmap_update_bits(struct regmap *map, unsigned int reg,
|
||||||
tmp = orig & ~mask;
|
tmp = orig & ~mask;
|
||||||
tmp |= val & mask;
|
tmp |= val & mask;
|
||||||
|
|
||||||
if (tmp != orig) {
|
if (force_write || (tmp != orig)) {
|
||||||
ret = _regmap_write(map, reg, tmp);
|
ret = _regmap_write(map, reg, tmp);
|
||||||
if (change)
|
if (change)
|
||||||
*change = true;
|
*change = true;
|
||||||
|
@ -2506,13 +2518,36 @@ int regmap_update_bits(struct regmap *map, unsigned int reg,
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
map->lock(map->lock_arg);
|
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);
|
map->unlock(map->lock_arg);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(regmap_update_bits);
|
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
|
* regmap_update_bits_async: Perform a read/modify/write cycle on the register
|
||||||
* map asynchronously
|
* map asynchronously
|
||||||
|
@ -2537,7 +2572,7 @@ int regmap_update_bits_async(struct regmap *map, unsigned int reg,
|
||||||
|
|
||||||
map->async = true;
|
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;
|
map->async = false;
|
||||||
|
|
||||||
|
@ -2566,7 +2601,7 @@ int regmap_update_bits_check(struct regmap *map, unsigned int reg,
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
map->lock(map->lock_arg);
|
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);
|
map->unlock(map->lock_arg);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -2599,7 +2634,7 @@ int regmap_update_bits_check_async(struct regmap *map, unsigned int reg,
|
||||||
|
|
||||||
map->async = true;
|
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;
|
map->async = false;
|
||||||
|
|
||||||
|
|
|
@ -1244,7 +1244,7 @@ static struct regulator *create_regulator(struct regulator_dev *rdev,
|
||||||
regulator->debugfs = debugfs_create_dir(regulator->supply_name,
|
regulator->debugfs = debugfs_create_dir(regulator->supply_name,
|
||||||
rdev->debugfs);
|
rdev->debugfs);
|
||||||
if (!regulator->debugfs) {
|
if (!regulator->debugfs) {
|
||||||
rdev_warn(rdev, "Failed to create debugfs directory\n");
|
rdev_dbg(rdev, "Failed to create debugfs directory\n");
|
||||||
} else {
|
} else {
|
||||||
debugfs_create_u32("uA_load", 0444, regulator->debugfs,
|
debugfs_create_u32("uA_load", 0444, regulator->debugfs,
|
||||||
®ulator->uA_load);
|
®ulator->uA_load);
|
||||||
|
|
|
@ -435,8 +435,8 @@ struct dentry *debugfs_create_atomic_t(const char *name, umode_t mode,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(debugfs_create_atomic_t);
|
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)
|
size_t count, loff_t *ppos)
|
||||||
{
|
{
|
||||||
char buf[3];
|
char buf[3];
|
||||||
u32 *val = file->private_data;
|
u32 *val = file->private_data;
|
||||||
|
@ -449,9 +449,10 @@ static ssize_t read_file_bool(struct file *file, char __user *user_buf,
|
||||||
buf[2] = 0x00;
|
buf[2] = 0x00;
|
||||||
return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
|
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)
|
size_t count, loff_t *ppos)
|
||||||
{
|
{
|
||||||
char buf[32];
|
char buf[32];
|
||||||
size_t buf_size;
|
size_t buf_size;
|
||||||
|
@ -468,10 +469,11 @@ static ssize_t write_file_bool(struct file *file, const char __user *user_buf,
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(debugfs_write_file_bool);
|
||||||
|
|
||||||
static const struct file_operations fops_bool = {
|
static const struct file_operations fops_bool = {
|
||||||
.read = read_file_bool,
|
.read = debugfs_read_file_bool,
|
||||||
.write = write_file_bool,
|
.write = debugfs_write_file_bool,
|
||||||
.open = simple_open,
|
.open = simple_open,
|
||||||
.llseek = default_llseek,
|
.llseek = default_llseek,
|
||||||
};
|
};
|
||||||
|
|
|
@ -116,6 +116,12 @@ struct dentry *debugfs_create_devm_seqfile(struct device *dev, const char *name,
|
||||||
|
|
||||||
bool debugfs_initialized(void);
|
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
|
#else
|
||||||
|
|
||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
|
@ -282,6 +288,20 @@ static inline struct dentry *debugfs_create_devm_seqfile(struct device *dev,
|
||||||
return ERR_PTR(-ENODEV);
|
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
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -431,6 +431,8 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
|
||||||
size_t val_count);
|
size_t val_count);
|
||||||
int regmap_update_bits(struct regmap *map, unsigned int reg,
|
int regmap_update_bits(struct regmap *map, unsigned int reg,
|
||||||
unsigned int mask, unsigned int val);
|
unsigned int mask, unsigned int val);
|
||||||
|
int regmap_write_bits(struct regmap *map, unsigned int reg,
|
||||||
|
unsigned int mask, unsigned int val);
|
||||||
int regmap_update_bits_async(struct regmap *map, unsigned int reg,
|
int regmap_update_bits_async(struct regmap *map, unsigned int reg,
|
||||||
unsigned int mask, unsigned int val);
|
unsigned int mask, unsigned int val);
|
||||||
int regmap_update_bits_check(struct regmap *map, unsigned int reg,
|
int regmap_update_bits_check(struct regmap *map, unsigned int reg,
|
||||||
|
@ -512,6 +514,8 @@ int regmap_field_update_bits(struct regmap_field *field,
|
||||||
|
|
||||||
int regmap_fields_write(struct regmap_field *field, unsigned int id,
|
int regmap_fields_write(struct regmap_field *field, unsigned int id,
|
||||||
unsigned int val);
|
unsigned int val);
|
||||||
|
int regmap_fields_force_write(struct regmap_field *field, unsigned int id,
|
||||||
|
unsigned int val);
|
||||||
int regmap_fields_read(struct regmap_field *field, unsigned int id,
|
int regmap_fields_read(struct regmap_field *field, unsigned int id,
|
||||||
unsigned int *val);
|
unsigned int *val);
|
||||||
int regmap_fields_update_bits(struct regmap_field *field, unsigned int id,
|
int regmap_fields_update_bits(struct regmap_field *field, unsigned int id,
|
||||||
|
@ -654,6 +658,13 @@ static inline int regmap_update_bits(struct regmap *map, unsigned int reg,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int regmap_write_bits(struct regmap *map, unsigned int reg,
|
||||||
|
unsigned int mask, unsigned int val)
|
||||||
|
{
|
||||||
|
WARN_ONCE(1, "regmap API is disabled");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
static inline int regmap_update_bits_async(struct regmap *map,
|
static inline int regmap_update_bits_async(struct regmap *map,
|
||||||
unsigned int reg,
|
unsigned int reg,
|
||||||
unsigned int mask, unsigned int val)
|
unsigned int mask, unsigned int val)
|
||||||
|
|
Loading…
Add table
Reference in a new issue