From: Andrey Smirnov Date: Sat, 12 Jan 2013 20:54:13 +0000 (-0800) Subject: regmap: Add provisions to have user-defined write operation X-Git-Url: http://git.cdn.openwrt.org/?a=commitdiff_plain;h=07c320dc31d757b8cb59c64dab320215c929bf02;p=openwrt%2Fstaging%2Fblogic.git 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 Signed-off-by: Mark Brown --- diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h index 471eb90276e4..51f057405647 100644 --- a/drivers/base/regmap/internal.h +++ b/drivers/base/regmap/internal.h @@ -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; diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index ceaefcfda8de..6845a077bd84 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c @@ -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); } /**