diff options
-rw-r--r-- | drivers/base/regmap/internal.h | 2 | ||||
-rw-r--r-- | drivers/base/regmap/regmap.c | 58 | ||||
-rw-r--r-- | include/linux/regmap.h | 18 |
3 files changed, 65 insertions, 13 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 | |||
604 | skip_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 | ||
1058 | static inline void *_regmap_map_get_context(struct regmap *map) | ||
1059 | { | ||
1060 | return (map->bus) ? map : map->bus_context; | ||
1061 | } | ||
1062 | |||
1042 | int _regmap_write(struct regmap *map, unsigned int reg, | 1063 | int _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, ®, range, | 1234 | ret = _regmap_select_page(map, ®, 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) |
diff --git a/include/linux/regmap.h b/include/linux/regmap.h index b7e95bf942c9..28dde941c783 100644 --- a/include/linux/regmap.h +++ b/include/linux/regmap.h | |||
@@ -127,7 +127,18 @@ typedef void (*regmap_unlock)(void *); | |||
127 | * @lock_arg: this field is passed as the only argument of lock/unlock | 127 | * @lock_arg: this field is passed as the only argument of lock/unlock |
128 | * functions (ignored in case regular lock/unlock functions | 128 | * functions (ignored in case regular lock/unlock functions |
129 | * are not overridden). | 129 | * are not overridden). |
130 | * | 130 | * @reg_read: Optional callback that if filled will be used to perform |
131 | * all the reads from the registers. Should only be provided for | ||
132 | * devices whos read operation cannot be represented as a simple read | ||
133 | * operation on a bus such as SPI, I2C, etc. Most of the devices do | ||
134 | * not need this. | ||
135 | * @reg_write: Same as above for writing. | ||
136 | * @fast_io: Register IO is fast. Use a spinlock instead of a mutex | ||
137 | * to perform locking. This field is ignored if custom lock/unlock | ||
138 | * functions are used (see fields lock/unlock of struct regmap_config). | ||
139 | * This field is a duplicate of a similar file in | ||
140 | * 'struct regmap_bus' and serves exact same purpose. | ||
141 | * Use it only for "no-bus" cases. | ||
131 | * @max_register: Optional, specifies the maximum valid register index. | 142 | * @max_register: Optional, specifies the maximum valid register index. |
132 | * @wr_table: Optional, points to a struct regmap_access_table specifying | 143 | * @wr_table: Optional, points to a struct regmap_access_table specifying |
133 | * valid ranges for write access. | 144 | * valid ranges for write access. |
@@ -177,6 +188,11 @@ struct regmap_config { | |||
177 | regmap_unlock unlock; | 188 | regmap_unlock unlock; |
178 | void *lock_arg; | 189 | void *lock_arg; |
179 | 190 | ||
191 | int (*reg_read)(void *context, unsigned int reg, unsigned int *val); | ||
192 | int (*reg_write)(void *context, unsigned int reg, unsigned int val); | ||
193 | |||
194 | bool fast_io; | ||
195 | |||
180 | unsigned int max_register; | 196 | unsigned int max_register; |
181 | const struct regmap_access_table *wr_table; | 197 | const struct regmap_access_table *wr_table; |
182 | const struct regmap_access_table *rd_table; | 198 | const struct regmap_access_table *rd_table; |