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;
|
||||
|
||||
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 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,
|
||||
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,
|
||||
const struct regmap_range *ranges,
|
||||
|
@ -580,6 +584,11 @@ struct regmap *regmap_init(struct device *dev,
|
|||
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;
|
||||
for (i = 0; i < config->num_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;
|
||||
}
|
||||
|
||||
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,
|
||||
unsigned int val)
|
||||
{
|
||||
struct regmap_range_node *range;
|
||||
int ret;
|
||||
BUG_ON(!map->format.format_write && !map->format.format_val);
|
||||
|
||||
if (!map->cache_bypass && map->format.format_write) {
|
||||
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);
|
||||
|
||||
if (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;
|
||||
} 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);
|
||||
}
|
||||
return map->reg_write(map, reg, val);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in a new issue