Merge remote-tracking branches 'regmap/topic/debugfs' and 'regmap/topic/force-update' into regmap-next

This commit is contained in:
Mark Brown
2015-09-04 17:22:09 +01:00
6 changed files with 174 additions and 23 deletions

View File

@@ -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))
registers_mode = 0600;
else
registers_mode = 0400;
#if defined(REGMAP_ALLOW_WRITE_DEBUGFS)
registers_mode = 0600;
#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);

View File

@@ -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;