aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/regmap/regmap.c
diff options
context:
space:
mode:
authorAndrey Smirnov <andrew.smirnov@gmail.com>2013-01-12 15:54:13 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2013-01-13 18:04:05 -0500
commit07c320dc31d757b8cb59c64dab320215c929bf02 (patch)
treed3b9925be0e16ac0c5a35fae799d7ddea3f35b5b /drivers/base/regmap/regmap.c
parentad278406b3b8b8e454af23b63df3c3d63f6aee94 (diff)
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>
Diffstat (limited to 'drivers/base/regmap/regmap.c')
-rw-r--r--drivers/base/regmap/regmap.c83
1 files changed, 54 insertions, 29 deletions
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,
36 36
37static int _regmap_bus_read(void *context, unsigned int reg, 37static int _regmap_bus_read(void *context, unsigned int reg,
38 unsigned int *val); 38 unsigned int *val);
39static int _regmap_bus_formatted_write(void *context, unsigned int reg,
40 unsigned int val);
41static int _regmap_bus_raw_write(void *context, unsigned int reg,
42 unsigned int val);
39 43
40bool regmap_reg_in_ranges(unsigned int reg, 44bool regmap_reg_in_ranges(unsigned int reg,
41 const struct regmap_range *ranges, 45 const struct regmap_range *ranges,
@@ -580,6 +584,11 @@ struct regmap *regmap_init(struct device *dev,
580 goto err_map; 584 goto err_map;
581 } 585 }
582 586
587 if (map->format.format_write)
588 map->reg_write = _regmap_bus_formatted_write;
589 else if (map->format.format_val)
590 map->reg_write = _regmap_bus_raw_write;
591
583 map->range_tree = RB_ROOT; 592 map->range_tree = RB_ROOT;
584 for (i = 0; i < config->num_ranges; i++) { 593 for (i = 0; i < config->num_ranges; i++) {
585 const struct regmap_range_cfg *range_cfg = &config->ranges[i]; 594 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,
986 return ret; 995 return ret;
987} 996}
988 997
998static int _regmap_bus_formatted_write(void *context, unsigned int reg,
999 unsigned int val)
1000{
1001 int ret;
1002 struct regmap_range_node *range;
1003 struct regmap *map = context;
1004
1005 BUG_ON(!map->format.format_write);
1006
1007 range = _regmap_range_lookup(map, reg);
1008 if (range) {
1009 ret = _regmap_select_page(map, &reg, range, 1);
1010 if (ret != 0)
1011 return ret;
1012 }
1013
1014 map->format.format_write(map, reg, val);
1015
1016 trace_regmap_hw_write_start(map->dev, reg, 1);
1017
1018 ret = map->bus->write(map->bus_context, map->work_buf,
1019 map->format.buf_size);
1020
1021 trace_regmap_hw_write_done(map->dev, reg, 1);
1022
1023 return ret;
1024}
1025
1026static int _regmap_bus_raw_write(void *context, unsigned int reg,
1027 unsigned int val)
1028{
1029 struct regmap *map = context;
1030
1031 BUG_ON(!map->format.format_val);
1032
1033 map->format.format_val(map->work_buf + map->format.reg_bytes
1034 + map->format.pad_bytes, val, 0);
1035 return _regmap_raw_write(map, reg,
1036 map->work_buf +
1037 map->format.reg_bytes +
1038 map->format.pad_bytes,
1039 map->format.val_bytes);
1040}
1041
989int _regmap_write(struct regmap *map, unsigned int reg, 1042int _regmap_write(struct regmap *map, unsigned int reg,
990 unsigned int val) 1043 unsigned int val)
991{ 1044{
992 struct regmap_range_node *range;
993 int ret; 1045 int ret;
994 BUG_ON(!map->format.format_write && !map->format.format_val);
995 1046
996 if (!map->cache_bypass && map->format.format_write) { 1047 if (!map->cache_bypass && map->format.format_write) {
997 ret = regcache_write(map, reg, val); 1048 ret = regcache_write(map, reg, val);
@@ -1010,33 +1061,7 @@ int _regmap_write(struct regmap *map, unsigned int reg,
1010 1061
1011 trace_regmap_reg_write(map->dev, reg, val); 1062 trace_regmap_reg_write(map->dev, reg, val);
1012 1063
1013 if (map->format.format_write) { 1064 return map->reg_write(map, reg, val);
1014 range = _regmap_range_lookup(map, reg);
1015 if (range) {
1016 ret = _regmap_select_page(map, &reg, range, 1);
1017 if (ret != 0)
1018 return ret;
1019 }
1020
1021 map->format.format_write(map, reg, val);
1022
1023 trace_regmap_hw_write_start(map->dev, reg, 1);
1024
1025 ret = map->bus->write(map->bus_context, map->work_buf,
1026 map->format.buf_size);
1027
1028 trace_regmap_hw_write_done(map->dev, reg, 1);
1029
1030 return ret;
1031 } else {
1032 map->format.format_val(map->work_buf + map->format.reg_bytes
1033 + map->format.pad_bytes, val, 0);
1034 return _regmap_raw_write(map, reg,
1035 map->work_buf +
1036 map->format.reg_bytes +
1037 map->format.pad_bytes,
1038 map->format.val_bytes);
1039 }
1040} 1065}
1041 1066
1042/** 1067/**