aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base
diff options
context:
space:
mode:
authorAndrey Smirnov <andrew.smirnov@gmail.com>2013-01-27 13:49:05 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2013-01-28 22:42:49 -0500
commitd2a5884a64161b524cc6749ee11b95d252e497f3 (patch)
treecf94ee33306a752e68977324e9b990538b44f8ab /drivers/base
parent07c320dc31d757b8cb59c64dab320215c929bf02 (diff)
regmap: Add "no-bus" option for regmap API
This commit adds provision for "no-bus" usage of the regmap API. In this configuration user can provide API with two callbacks 'reg_read' and 'reg_write' which are to be called when reads and writes to one of device's registers is performed. This is useful for devices that expose registers but whose register access sequence does not fit the 'bus' abstraction. Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'drivers/base')
-rw-r--r--drivers/base/regmap/internal.h2
-rw-r--r--drivers/base/regmap/regmap.c58
2 files changed, 48 insertions, 12 deletions
diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h
index 51f057405647..b55fde5d216a 100644
--- a/drivers/base/regmap/internal.h
+++ b/drivers/base/regmap/internal.h
@@ -77,6 +77,8 @@ struct regmap {
77 int (*reg_read)(void *context, unsigned int reg, unsigned int *val); 77 int (*reg_read)(void *context, unsigned int reg, unsigned int *val);
78 int (*reg_write)(void *context, unsigned int reg, unsigned int val); 78 int (*reg_write)(void *context, unsigned int reg, unsigned int val);
79 79
80 bool defer_caching;
81
80 u8 read_flag_mask; 82 u8 read_flag_mask;
81 u8 write_flag_mask; 83 u8 write_flag_mask;
82 84
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index 6845a077bd84..9592030a0dc3 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -379,7 +379,7 @@ struct regmap *regmap_init(struct device *dev,
379 enum regmap_endian reg_endian, val_endian; 379 enum regmap_endian reg_endian, val_endian;
380 int i, j; 380 int i, j;
381 381
382 if (!bus || !config) 382 if (!config)
383 goto err; 383 goto err;
384 384
385 map = kzalloc(sizeof(*map), GFP_KERNEL); 385 map = kzalloc(sizeof(*map), GFP_KERNEL);
@@ -393,7 +393,8 @@ struct regmap *regmap_init(struct device *dev,
393 map->unlock = config->unlock; 393 map->unlock = config->unlock;
394 map->lock_arg = config->lock_arg; 394 map->lock_arg = config->lock_arg;
395 } else { 395 } else {
396 if (bus->fast_io) { 396 if ((bus && bus->fast_io) ||
397 config->fast_io) {
397 spin_lock_init(&map->spinlock); 398 spin_lock_init(&map->spinlock);
398 map->lock = regmap_lock_spinlock; 399 map->lock = regmap_lock_spinlock;
399 map->unlock = regmap_unlock_spinlock; 400 map->unlock = regmap_unlock_spinlock;
@@ -433,11 +434,19 @@ struct regmap *regmap_init(struct device *dev,
433 if (config->read_flag_mask || config->write_flag_mask) { 434 if (config->read_flag_mask || config->write_flag_mask) {
434 map->read_flag_mask = config->read_flag_mask; 435 map->read_flag_mask = config->read_flag_mask;
435 map->write_flag_mask = config->write_flag_mask; 436 map->write_flag_mask = config->write_flag_mask;
436 } else { 437 } else if (bus) {
437 map->read_flag_mask = bus->read_flag_mask; 438 map->read_flag_mask = bus->read_flag_mask;
438 } 439 }
439 440
440 map->reg_read = _regmap_bus_read; 441 if (!bus) {
442 map->reg_read = config->reg_read;
443 map->reg_write = config->reg_write;
444
445 map->defer_caching = false;
446 goto skip_format_initialization;
447 } else {
448 map->reg_read = _regmap_bus_read;
449 }
441 450
442 reg_endian = config->reg_format_endian; 451 reg_endian = config->reg_format_endian;
443 if (reg_endian == REGMAP_ENDIAN_DEFAULT) 452 if (reg_endian == REGMAP_ENDIAN_DEFAULT)
@@ -584,10 +593,15 @@ struct regmap *regmap_init(struct device *dev,
584 goto err_map; 593 goto err_map;
585 } 594 }
586 595
587 if (map->format.format_write) 596 if (map->format.format_write) {
597 map->defer_caching = false;
588 map->reg_write = _regmap_bus_formatted_write; 598 map->reg_write = _regmap_bus_formatted_write;
589 else if (map->format.format_val) 599 } else if (map->format.format_val) {
600 map->defer_caching = true;
590 map->reg_write = _regmap_bus_raw_write; 601 map->reg_write = _regmap_bus_raw_write;
602 }
603
604skip_format_initialization:
591 605
592 map->range_tree = RB_ROOT; 606 map->range_tree = RB_ROOT;
593 for (i = 0; i < config->num_ranges; i++) { 607 for (i = 0; i < config->num_ranges; i++) {
@@ -790,7 +804,7 @@ void regmap_exit(struct regmap *map)
790 regcache_exit(map); 804 regcache_exit(map);
791 regmap_debugfs_exit(map); 805 regmap_debugfs_exit(map);
792 regmap_range_exit(map); 806 regmap_range_exit(map);
793 if (map->bus->free_context) 807 if (map->bus && map->bus->free_context)
794 map->bus->free_context(map->bus_context); 808 map->bus->free_context(map->bus_context);
795 kfree(map->work_buf); 809 kfree(map->work_buf);
796 kfree(map); 810 kfree(map);
@@ -893,6 +907,8 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg,
893 size_t len; 907 size_t len;
894 int i; 908 int i;
895 909
910 BUG_ON(!map->bus);
911
896 /* Check for unwritable registers before we start */ 912 /* Check for unwritable registers before we start */
897 if (map->writeable_reg) 913 if (map->writeable_reg)
898 for (i = 0; i < val_len / map->format.val_bytes; i++) 914 for (i = 0; i < val_len / map->format.val_bytes; i++)
@@ -1002,7 +1018,7 @@ static int _regmap_bus_formatted_write(void *context, unsigned int reg,
1002 struct regmap_range_node *range; 1018 struct regmap_range_node *range;
1003 struct regmap *map = context; 1019 struct regmap *map = context;
1004 1020
1005 BUG_ON(!map->format.format_write); 1021 BUG_ON(!map->bus || !map->format.format_write);
1006 1022
1007 range = _regmap_range_lookup(map, reg); 1023 range = _regmap_range_lookup(map, reg);
1008 if (range) { 1024 if (range) {
@@ -1028,7 +1044,7 @@ static int _regmap_bus_raw_write(void *context, unsigned int reg,
1028{ 1044{
1029 struct regmap *map = context; 1045 struct regmap *map = context;
1030 1046
1031 BUG_ON(!map->format.format_val); 1047 BUG_ON(!map->bus || !map->format.format_val);
1032 1048
1033 map->format.format_val(map->work_buf + map->format.reg_bytes 1049 map->format.format_val(map->work_buf + map->format.reg_bytes
1034 + map->format.pad_bytes, val, 0); 1050 + map->format.pad_bytes, val, 0);
@@ -1039,12 +1055,18 @@ static int _regmap_bus_raw_write(void *context, unsigned int reg,
1039 map->format.val_bytes); 1055 map->format.val_bytes);
1040} 1056}
1041 1057
1058static inline void *_regmap_map_get_context(struct regmap *map)
1059{
1060 return (map->bus) ? map : map->bus_context;
1061}
1062
1042int _regmap_write(struct regmap *map, unsigned int reg, 1063int _regmap_write(struct regmap *map, unsigned int reg,
1043 unsigned int val) 1064 unsigned int val)
1044{ 1065{
1045 int ret; 1066 int ret;
1067 void *context = _regmap_map_get_context(map);
1046 1068
1047 if (!map->cache_bypass && map->format.format_write) { 1069 if (!map->cache_bypass && !map->defer_caching) {
1048 ret = regcache_write(map, reg, val); 1070 ret = regcache_write(map, reg, val);
1049 if (ret != 0) 1071 if (ret != 0)
1050 return ret; 1072 return ret;
@@ -1061,7 +1083,7 @@ int _regmap_write(struct regmap *map, unsigned int reg,
1061 1083
1062 trace_regmap_reg_write(map->dev, reg, val); 1084 trace_regmap_reg_write(map->dev, reg, val);
1063 1085
1064 return map->reg_write(map, reg, val); 1086 return map->reg_write(context, reg, val);
1065} 1087}
1066 1088
1067/** 1089/**
@@ -1112,6 +1134,8 @@ int regmap_raw_write(struct regmap *map, unsigned int reg,
1112{ 1134{
1113 int ret; 1135 int ret;
1114 1136
1137 if (!map->bus)
1138 return -EINVAL;
1115 if (val_len % map->format.val_bytes) 1139 if (val_len % map->format.val_bytes)
1116 return -EINVAL; 1140 return -EINVAL;
1117 if (reg % map->reg_stride) 1141 if (reg % map->reg_stride)
@@ -1148,6 +1172,8 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,
1148 size_t val_bytes = map->format.val_bytes; 1172 size_t val_bytes = map->format.val_bytes;
1149 void *wval; 1173 void *wval;
1150 1174
1175 if (!map->bus)
1176 return -EINVAL;
1151 if (!map->format.parse_val) 1177 if (!map->format.parse_val)
1152 return -EINVAL; 1178 return -EINVAL;
1153 if (reg % map->reg_stride) 1179 if (reg % map->reg_stride)
@@ -1201,6 +1227,8 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
1201 u8 *u8 = map->work_buf; 1227 u8 *u8 = map->work_buf;
1202 int ret; 1228 int ret;
1203 1229
1230 BUG_ON(!map->bus);
1231
1204 range = _regmap_range_lookup(map, reg); 1232 range = _regmap_range_lookup(map, reg);
1205 if (range) { 1233 if (range) {
1206 ret = _regmap_select_page(map, &reg, range, 1234 ret = _regmap_select_page(map, &reg, range,
@@ -1252,6 +1280,8 @@ static int _regmap_read(struct regmap *map, unsigned int reg,
1252 unsigned int *val) 1280 unsigned int *val)
1253{ 1281{
1254 int ret; 1282 int ret;
1283 void *context = _regmap_map_get_context(map);
1284
1255 BUG_ON(!map->reg_read); 1285 BUG_ON(!map->reg_read);
1256 1286
1257 if (!map->cache_bypass) { 1287 if (!map->cache_bypass) {
@@ -1263,7 +1293,7 @@ static int _regmap_read(struct regmap *map, unsigned int reg,
1263 if (map->cache_only) 1293 if (map->cache_only)
1264 return -EBUSY; 1294 return -EBUSY;
1265 1295
1266 ret = map->reg_read(map, reg, val); 1296 ret = map->reg_read(context, reg, val);
1267 if (ret == 0) { 1297 if (ret == 0) {
1268#ifdef LOG_DEVICE 1298#ifdef LOG_DEVICE
1269 if (strcmp(dev_name(map->dev), LOG_DEVICE) == 0) 1299 if (strcmp(dev_name(map->dev), LOG_DEVICE) == 0)
@@ -1325,6 +1355,8 @@ int regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
1325 unsigned int v; 1355 unsigned int v;
1326 int ret, i; 1356 int ret, i;
1327 1357
1358 if (!map->bus)
1359 return -EINVAL;
1328 if (val_len % map->format.val_bytes) 1360 if (val_len % map->format.val_bytes)
1329 return -EINVAL; 1361 return -EINVAL;
1330 if (reg % map->reg_stride) 1362 if (reg % map->reg_stride)
@@ -1376,6 +1408,8 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
1376 size_t val_bytes = map->format.val_bytes; 1408 size_t val_bytes = map->format.val_bytes;
1377 bool vol = regmap_volatile_range(map, reg, val_count); 1409 bool vol = regmap_volatile_range(map, reg, val_count);
1378 1410
1411 if (!map->bus)
1412 return -EINVAL;
1379 if (!map->format.parse_val) 1413 if (!map->format.parse_val)
1380 return -EINVAL; 1414 return -EINVAL;
1381 if (reg % map->reg_stride) 1415 if (reg % map->reg_stride)