regmap: Add provisions to have user-defined write operation
This commit is a preparatory commit to provide "no-bus" configuration option for regmap API. It adds necessary plumbing needed to have the ability to provide user define register write function. Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
This commit is contained in:
parent
ad278406b3
commit
07c320dc31
2 changed files with 55 additions and 29 deletions
|
@ -75,6 +75,7 @@ struct regmap {
|
||||||
const struct regmap_access_table *precious_table;
|
const struct regmap_access_table *precious_table;
|
||||||
|
|
||||||
int (*reg_read)(void *context, unsigned int reg, unsigned int *val);
|
int (*reg_read)(void *context, unsigned int reg, unsigned int *val);
|
||||||
|
int (*reg_write)(void *context, unsigned int reg, unsigned int val);
|
||||||
|
|
||||||
u8 read_flag_mask;
|
u8 read_flag_mask;
|
||||||
u8 write_flag_mask;
|
u8 write_flag_mask;
|
||||||
|
|
|
@ -36,6 +36,10 @@ static int _regmap_update_bits(struct regmap *map, unsigned int reg,
|
||||||
|
|
||||||
static int _regmap_bus_read(void *context, unsigned int reg,
|
static int _regmap_bus_read(void *context, unsigned int reg,
|
||||||
unsigned int *val);
|
unsigned int *val);
|
||||||
|
static int _regmap_bus_formatted_write(void *context, unsigned int reg,
|
||||||
|
unsigned int val);
|
||||||
|
static int _regmap_bus_raw_write(void *context, unsigned int reg,
|
||||||
|
unsigned int val);
|
||||||
|
|
||||||
bool regmap_reg_in_ranges(unsigned int reg,
|
bool regmap_reg_in_ranges(unsigned int reg,
|
||||||
const struct regmap_range *ranges,
|
const struct regmap_range *ranges,
|
||||||
|
@ -580,6 +584,11 @@ struct regmap *regmap_init(struct device *dev,
|
||||||
goto err_map;
|
goto err_map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (map->format.format_write)
|
||||||
|
map->reg_write = _regmap_bus_formatted_write;
|
||||||
|
else if (map->format.format_val)
|
||||||
|
map->reg_write = _regmap_bus_raw_write;
|
||||||
|
|
||||||
map->range_tree = RB_ROOT;
|
map->range_tree = RB_ROOT;
|
||||||
for (i = 0; i < config->num_ranges; i++) {
|
for (i = 0; i < config->num_ranges; i++) {
|
||||||
const struct regmap_range_cfg *range_cfg = &config->ranges[i];
|
const struct regmap_range_cfg *range_cfg = &config->ranges[i];
|
||||||
|
@ -986,12 +995,54 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int _regmap_bus_formatted_write(void *context, unsigned int reg,
|
||||||
|
unsigned int val)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct regmap_range_node *range;
|
||||||
|
struct regmap *map = context;
|
||||||
|
|
||||||
|
BUG_ON(!map->format.format_write);
|
||||||
|
|
||||||
|
range = _regmap_range_lookup(map, reg);
|
||||||
|
if (range) {
|
||||||
|
ret = _regmap_select_page(map, ®, range, 1);
|
||||||
|
if (ret != 0)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
map->format.format_write(map, reg, val);
|
||||||
|
|
||||||
|
trace_regmap_hw_write_start(map->dev, reg, 1);
|
||||||
|
|
||||||
|
ret = map->bus->write(map->bus_context, map->work_buf,
|
||||||
|
map->format.buf_size);
|
||||||
|
|
||||||
|
trace_regmap_hw_write_done(map->dev, reg, 1);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _regmap_bus_raw_write(void *context, unsigned int reg,
|
||||||
|
unsigned int val)
|
||||||
|
{
|
||||||
|
struct regmap *map = context;
|
||||||
|
|
||||||
|
BUG_ON(!map->format.format_val);
|
||||||
|
|
||||||
|
map->format.format_val(map->work_buf + map->format.reg_bytes
|
||||||
|
+ map->format.pad_bytes, val, 0);
|
||||||
|
return _regmap_raw_write(map, reg,
|
||||||
|
map->work_buf +
|
||||||
|
map->format.reg_bytes +
|
||||||
|
map->format.pad_bytes,
|
||||||
|
map->format.val_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
int _regmap_write(struct regmap *map, unsigned int reg,
|
int _regmap_write(struct regmap *map, unsigned int reg,
|
||||||
unsigned int val)
|
unsigned int val)
|
||||||
{
|
{
|
||||||
struct regmap_range_node *range;
|
|
||||||
int ret;
|
int ret;
|
||||||
BUG_ON(!map->format.format_write && !map->format.format_val);
|
|
||||||
|
|
||||||
if (!map->cache_bypass && map->format.format_write) {
|
if (!map->cache_bypass && map->format.format_write) {
|
||||||
ret = regcache_write(map, reg, val);
|
ret = regcache_write(map, reg, val);
|
||||||
|
@ -1010,33 +1061,7 @@ int _regmap_write(struct regmap *map, unsigned int reg,
|
||||||
|
|
||||||
trace_regmap_reg_write(map->dev, reg, val);
|
trace_regmap_reg_write(map->dev, reg, val);
|
||||||
|
|
||||||
if (map->format.format_write) {
|
return map->reg_write(map, reg, val);
|
||||||
range = _regmap_range_lookup(map, reg);
|
|
||||||
if (range) {
|
|
||||||
ret = _regmap_select_page(map, ®, range, 1);
|
|
||||||
if (ret != 0)
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
map->format.format_write(map, reg, val);
|
|
||||||
|
|
||||||
trace_regmap_hw_write_start(map->dev, reg, 1);
|
|
||||||
|
|
||||||
ret = map->bus->write(map->bus_context, map->work_buf,
|
|
||||||
map->format.buf_size);
|
|
||||||
|
|
||||||
trace_regmap_hw_write_done(map->dev, reg, 1);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
} else {
|
|
||||||
map->format.format_val(map->work_buf + map->format.reg_bytes
|
|
||||||
+ map->format.pad_bytes, val, 0);
|
|
||||||
return _regmap_raw_write(map, reg,
|
|
||||||
map->work_buf +
|
|
||||||
map->format.reg_bytes +
|
|
||||||
map->format.pad_bytes,
|
|
||||||
map->format.val_bytes);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Add table
Reference in a new issue