diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2013-04-16 11:05:46 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2013-04-16 11:05:46 -0400 |
commit | 5b3b44847590b3cbaafdf01d4ad260fa53d04167 (patch) | |
tree | af353c62902fce0cb8c1205da0977346bd2c915f /drivers/base | |
parent | b508c80c553c03baf5c9ad5612ac8caceb13c5f4 (diff) | |
parent | 5a08d15602987bbdff3407d7645f95b7a70f1a6f (diff) |
Merge remote-tracking branch 'regmap/topic/cache' into regmap-next
Diffstat (limited to 'drivers/base')
-rw-r--r-- | drivers/base/regmap/internal.h | 39 | ||||
-rw-r--r-- | drivers/base/regmap/regcache-lzo.c | 6 | ||||
-rw-r--r-- | drivers/base/regmap/regcache-rbtree.c | 100 | ||||
-rw-r--r-- | drivers/base/regmap/regcache.c | 196 | ||||
-rw-r--r-- | drivers/base/regmap/regmap.c | 84 |
5 files changed, 315 insertions, 110 deletions
diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h index 5a22bd33ce3d..01fbe48e8155 100644 --- a/drivers/base/regmap/internal.h +++ b/drivers/base/regmap/internal.h | |||
@@ -38,7 +38,8 @@ struct regmap_format { | |||
38 | unsigned int reg, unsigned int val); | 38 | unsigned int reg, unsigned int val); |
39 | void (*format_reg)(void *buf, unsigned int reg, unsigned int shift); | 39 | void (*format_reg)(void *buf, unsigned int reg, unsigned int shift); |
40 | void (*format_val)(void *buf, unsigned int val, unsigned int shift); | 40 | void (*format_val)(void *buf, unsigned int val, unsigned int shift); |
41 | unsigned int (*parse_val)(void *buf); | 41 | unsigned int (*parse_val)(const void *buf); |
42 | void (*parse_inplace)(void *buf); | ||
42 | }; | 43 | }; |
43 | 44 | ||
44 | struct regmap_async { | 45 | struct regmap_async { |
@@ -125,6 +126,9 @@ struct regmap { | |||
125 | void *cache; | 126 | void *cache; |
126 | u32 cache_dirty; | 127 | u32 cache_dirty; |
127 | 128 | ||
129 | unsigned long *cache_present; | ||
130 | unsigned int cache_present_nbits; | ||
131 | |||
128 | struct reg_default *patch; | 132 | struct reg_default *patch; |
129 | int patch_regs; | 133 | int patch_regs; |
130 | 134 | ||
@@ -187,12 +191,35 @@ int regcache_read(struct regmap *map, | |||
187 | int regcache_write(struct regmap *map, | 191 | int regcache_write(struct regmap *map, |
188 | unsigned int reg, unsigned int value); | 192 | unsigned int reg, unsigned int value); |
189 | int regcache_sync(struct regmap *map); | 193 | int regcache_sync(struct regmap *map); |
190 | 194 | int regcache_sync_block(struct regmap *map, void *block, | |
191 | unsigned int regcache_get_val(const void *base, unsigned int idx, | 195 | unsigned int block_base, unsigned int start, |
192 | unsigned int word_size); | 196 | unsigned int end); |
193 | bool regcache_set_val(void *base, unsigned int idx, | 197 | |
194 | unsigned int val, unsigned int word_size); | 198 | static inline const void *regcache_get_val_addr(struct regmap *map, |
199 | const void *base, | ||
200 | unsigned int idx) | ||
201 | { | ||
202 | return base + (map->cache_word_size * idx); | ||
203 | } | ||
204 | |||
205 | unsigned int regcache_get_val(struct regmap *map, const void *base, | ||
206 | unsigned int idx); | ||
207 | bool regcache_set_val(struct regmap *map, void *base, unsigned int idx, | ||
208 | unsigned int val); | ||
195 | int regcache_lookup_reg(struct regmap *map, unsigned int reg); | 209 | int regcache_lookup_reg(struct regmap *map, unsigned int reg); |
210 | int regcache_set_reg_present(struct regmap *map, unsigned int reg); | ||
211 | |||
212 | static inline bool regcache_reg_present(struct regmap *map, unsigned int reg) | ||
213 | { | ||
214 | if (!map->cache_present) | ||
215 | return true; | ||
216 | if (reg > map->cache_present_nbits) | ||
217 | return false; | ||
218 | return map->cache_present[BIT_WORD(reg)] & BIT_MASK(reg); | ||
219 | } | ||
220 | |||
221 | int _regmap_raw_write(struct regmap *map, unsigned int reg, | ||
222 | const void *val, size_t val_len, bool async); | ||
196 | 223 | ||
197 | void regmap_async_complete_cb(struct regmap_async *async, int ret); | 224 | void regmap_async_complete_cb(struct regmap_async *async, int ret); |
198 | 225 | ||
diff --git a/drivers/base/regmap/regcache-lzo.c b/drivers/base/regmap/regcache-lzo.c index afd6aa91a0df..e210a6d1406a 100644 --- a/drivers/base/regmap/regcache-lzo.c +++ b/drivers/base/regmap/regcache-lzo.c | |||
@@ -260,8 +260,7 @@ static int regcache_lzo_read(struct regmap *map, | |||
260 | ret = regcache_lzo_decompress_cache_block(map, lzo_block); | 260 | ret = regcache_lzo_decompress_cache_block(map, lzo_block); |
261 | if (ret >= 0) | 261 | if (ret >= 0) |
262 | /* fetch the value from the cache */ | 262 | /* fetch the value from the cache */ |
263 | *value = regcache_get_val(lzo_block->dst, blkpos, | 263 | *value = regcache_get_val(map, lzo_block->dst, blkpos); |
264 | map->cache_word_size); | ||
265 | 264 | ||
266 | kfree(lzo_block->dst); | 265 | kfree(lzo_block->dst); |
267 | /* restore the pointer and length of the compressed block */ | 266 | /* restore the pointer and length of the compressed block */ |
@@ -304,8 +303,7 @@ static int regcache_lzo_write(struct regmap *map, | |||
304 | } | 303 | } |
305 | 304 | ||
306 | /* write the new value to the cache */ | 305 | /* write the new value to the cache */ |
307 | if (regcache_set_val(lzo_block->dst, blkpos, value, | 306 | if (regcache_set_val(map, lzo_block->dst, blkpos, value)) { |
308 | map->cache_word_size)) { | ||
309 | kfree(lzo_block->dst); | 307 | kfree(lzo_block->dst); |
310 | goto out; | 308 | goto out; |
311 | } | 309 | } |
diff --git a/drivers/base/regmap/regcache-rbtree.c b/drivers/base/regmap/regcache-rbtree.c index 79f4fca9877a..aa0875f6f1b7 100644 --- a/drivers/base/regmap/regcache-rbtree.c +++ b/drivers/base/regmap/regcache-rbtree.c | |||
@@ -47,22 +47,21 @@ static inline void regcache_rbtree_get_base_top_reg( | |||
47 | *top = rbnode->base_reg + ((rbnode->blklen - 1) * map->reg_stride); | 47 | *top = rbnode->base_reg + ((rbnode->blklen - 1) * map->reg_stride); |
48 | } | 48 | } |
49 | 49 | ||
50 | static unsigned int regcache_rbtree_get_register( | 50 | static unsigned int regcache_rbtree_get_register(struct regmap *map, |
51 | struct regcache_rbtree_node *rbnode, unsigned int idx, | 51 | struct regcache_rbtree_node *rbnode, unsigned int idx) |
52 | unsigned int word_size) | ||
53 | { | 52 | { |
54 | return regcache_get_val(rbnode->block, idx, word_size); | 53 | return regcache_get_val(map, rbnode->block, idx); |
55 | } | 54 | } |
56 | 55 | ||
57 | static void regcache_rbtree_set_register(struct regcache_rbtree_node *rbnode, | 56 | static void regcache_rbtree_set_register(struct regmap *map, |
58 | unsigned int idx, unsigned int val, | 57 | struct regcache_rbtree_node *rbnode, |
59 | unsigned int word_size) | 58 | unsigned int idx, unsigned int val) |
60 | { | 59 | { |
61 | regcache_set_val(rbnode->block, idx, val, word_size); | 60 | regcache_set_val(map, rbnode->block, idx, val); |
62 | } | 61 | } |
63 | 62 | ||
64 | static struct regcache_rbtree_node *regcache_rbtree_lookup(struct regmap *map, | 63 | static struct regcache_rbtree_node *regcache_rbtree_lookup(struct regmap *map, |
65 | unsigned int reg) | 64 | unsigned int reg) |
66 | { | 65 | { |
67 | struct regcache_rbtree_ctx *rbtree_ctx = map->cache; | 66 | struct regcache_rbtree_ctx *rbtree_ctx = map->cache; |
68 | struct rb_node *node; | 67 | struct rb_node *node; |
@@ -139,15 +138,21 @@ static int rbtree_show(struct seq_file *s, void *ignored) | |||
139 | struct regcache_rbtree_node *n; | 138 | struct regcache_rbtree_node *n; |
140 | struct rb_node *node; | 139 | struct rb_node *node; |
141 | unsigned int base, top; | 140 | unsigned int base, top; |
141 | size_t mem_size; | ||
142 | int nodes = 0; | 142 | int nodes = 0; |
143 | int registers = 0; | 143 | int registers = 0; |
144 | int this_registers, average; | 144 | int this_registers, average; |
145 | 145 | ||
146 | map->lock(map); | 146 | map->lock(map); |
147 | 147 | ||
148 | mem_size = sizeof(*rbtree_ctx); | ||
149 | mem_size += BITS_TO_LONGS(map->cache_present_nbits) * sizeof(long); | ||
150 | |||
148 | for (node = rb_first(&rbtree_ctx->root); node != NULL; | 151 | for (node = rb_first(&rbtree_ctx->root); node != NULL; |
149 | node = rb_next(node)) { | 152 | node = rb_next(node)) { |
150 | n = container_of(node, struct regcache_rbtree_node, node); | 153 | n = container_of(node, struct regcache_rbtree_node, node); |
154 | mem_size += sizeof(*n); | ||
155 | mem_size += (n->blklen * map->cache_word_size); | ||
151 | 156 | ||
152 | regcache_rbtree_get_base_top_reg(map, n, &base, &top); | 157 | regcache_rbtree_get_base_top_reg(map, n, &base, &top); |
153 | this_registers = ((top - base) / map->reg_stride) + 1; | 158 | this_registers = ((top - base) / map->reg_stride) + 1; |
@@ -162,8 +167,8 @@ static int rbtree_show(struct seq_file *s, void *ignored) | |||
162 | else | 167 | else |
163 | average = 0; | 168 | average = 0; |
164 | 169 | ||
165 | seq_printf(s, "%d nodes, %d registers, average %d registers\n", | 170 | seq_printf(s, "%d nodes, %d registers, average %d registers, used %zu bytes\n", |
166 | nodes, registers, average); | 171 | nodes, registers, average, mem_size); |
167 | 172 | ||
168 | map->unlock(map); | 173 | map->unlock(map); |
169 | 174 | ||
@@ -260,8 +265,9 @@ static int regcache_rbtree_read(struct regmap *map, | |||
260 | rbnode = regcache_rbtree_lookup(map, reg); | 265 | rbnode = regcache_rbtree_lookup(map, reg); |
261 | if (rbnode) { | 266 | if (rbnode) { |
262 | reg_tmp = (reg - rbnode->base_reg) / map->reg_stride; | 267 | reg_tmp = (reg - rbnode->base_reg) / map->reg_stride; |
263 | *value = regcache_rbtree_get_register(rbnode, reg_tmp, | 268 | if (!regcache_reg_present(map, reg)) |
264 | map->cache_word_size); | 269 | return -ENOENT; |
270 | *value = regcache_rbtree_get_register(map, rbnode, reg_tmp); | ||
265 | } else { | 271 | } else { |
266 | return -ENOENT; | 272 | return -ENOENT; |
267 | } | 273 | } |
@@ -270,21 +276,23 @@ static int regcache_rbtree_read(struct regmap *map, | |||
270 | } | 276 | } |
271 | 277 | ||
272 | 278 | ||
273 | static int regcache_rbtree_insert_to_block(struct regcache_rbtree_node *rbnode, | 279 | static int regcache_rbtree_insert_to_block(struct regmap *map, |
280 | struct regcache_rbtree_node *rbnode, | ||
274 | unsigned int pos, unsigned int reg, | 281 | unsigned int pos, unsigned int reg, |
275 | unsigned int value, unsigned int word_size) | 282 | unsigned int value) |
276 | { | 283 | { |
277 | u8 *blk; | 284 | u8 *blk; |
278 | 285 | ||
279 | blk = krealloc(rbnode->block, | 286 | blk = krealloc(rbnode->block, |
280 | (rbnode->blklen + 1) * word_size, GFP_KERNEL); | 287 | (rbnode->blklen + 1) * map->cache_word_size, |
288 | GFP_KERNEL); | ||
281 | if (!blk) | 289 | if (!blk) |
282 | return -ENOMEM; | 290 | return -ENOMEM; |
283 | 291 | ||
284 | /* insert the register value in the correct place in the rbnode block */ | 292 | /* insert the register value in the correct place in the rbnode block */ |
285 | memmove(blk + (pos + 1) * word_size, | 293 | memmove(blk + (pos + 1) * map->cache_word_size, |
286 | blk + pos * word_size, | 294 | blk + pos * map->cache_word_size, |
287 | (rbnode->blklen - pos) * word_size); | 295 | (rbnode->blklen - pos) * map->cache_word_size); |
288 | 296 | ||
289 | /* update the rbnode block, its size and the base register */ | 297 | /* update the rbnode block, its size and the base register */ |
290 | rbnode->block = blk; | 298 | rbnode->block = blk; |
@@ -292,7 +300,7 @@ static int regcache_rbtree_insert_to_block(struct regcache_rbtree_node *rbnode, | |||
292 | if (!pos) | 300 | if (!pos) |
293 | rbnode->base_reg = reg; | 301 | rbnode->base_reg = reg; |
294 | 302 | ||
295 | regcache_rbtree_set_register(rbnode, pos, value, word_size); | 303 | regcache_rbtree_set_register(map, rbnode, pos, value); |
296 | return 0; | 304 | return 0; |
297 | } | 305 | } |
298 | 306 | ||
@@ -302,25 +310,24 @@ static int regcache_rbtree_write(struct regmap *map, unsigned int reg, | |||
302 | struct regcache_rbtree_ctx *rbtree_ctx; | 310 | struct regcache_rbtree_ctx *rbtree_ctx; |
303 | struct regcache_rbtree_node *rbnode, *rbnode_tmp; | 311 | struct regcache_rbtree_node *rbnode, *rbnode_tmp; |
304 | struct rb_node *node; | 312 | struct rb_node *node; |
305 | unsigned int val; | ||
306 | unsigned int reg_tmp; | 313 | unsigned int reg_tmp; |
307 | unsigned int pos; | 314 | unsigned int pos; |
308 | int i; | 315 | int i; |
309 | int ret; | 316 | int ret; |
310 | 317 | ||
311 | rbtree_ctx = map->cache; | 318 | rbtree_ctx = map->cache; |
319 | /* update the reg_present bitmap, make space if necessary */ | ||
320 | ret = regcache_set_reg_present(map, reg); | ||
321 | if (ret < 0) | ||
322 | return ret; | ||
323 | |||
312 | /* if we can't locate it in the cached rbnode we'll have | 324 | /* if we can't locate it in the cached rbnode we'll have |
313 | * to traverse the rbtree looking for it. | 325 | * to traverse the rbtree looking for it. |
314 | */ | 326 | */ |
315 | rbnode = regcache_rbtree_lookup(map, reg); | 327 | rbnode = regcache_rbtree_lookup(map, reg); |
316 | if (rbnode) { | 328 | if (rbnode) { |
317 | reg_tmp = (reg - rbnode->base_reg) / map->reg_stride; | 329 | reg_tmp = (reg - rbnode->base_reg) / map->reg_stride; |
318 | val = regcache_rbtree_get_register(rbnode, reg_tmp, | 330 | regcache_rbtree_set_register(map, rbnode, reg_tmp, value); |
319 | map->cache_word_size); | ||
320 | if (val == value) | ||
321 | return 0; | ||
322 | regcache_rbtree_set_register(rbnode, reg_tmp, value, | ||
323 | map->cache_word_size); | ||
324 | } else { | 331 | } else { |
325 | /* look for an adjacent register to the one we are about to add */ | 332 | /* look for an adjacent register to the one we are about to add */ |
326 | for (node = rb_first(&rbtree_ctx->root); node; | 333 | for (node = rb_first(&rbtree_ctx->root); node; |
@@ -337,9 +344,10 @@ static int regcache_rbtree_write(struct regmap *map, unsigned int reg, | |||
337 | pos = i + 1; | 344 | pos = i + 1; |
338 | else | 345 | else |
339 | pos = i; | 346 | pos = i; |
340 | ret = regcache_rbtree_insert_to_block(rbnode_tmp, pos, | 347 | ret = regcache_rbtree_insert_to_block(map, |
341 | reg, value, | 348 | rbnode_tmp, |
342 | map->cache_word_size); | 349 | pos, reg, |
350 | value); | ||
343 | if (ret) | 351 | if (ret) |
344 | return ret; | 352 | return ret; |
345 | rbtree_ctx->cached_rbnode = rbnode_tmp; | 353 | rbtree_ctx->cached_rbnode = rbnode_tmp; |
@@ -354,7 +362,7 @@ static int regcache_rbtree_write(struct regmap *map, unsigned int reg, | |||
354 | rbnode = kzalloc(sizeof *rbnode, GFP_KERNEL); | 362 | rbnode = kzalloc(sizeof *rbnode, GFP_KERNEL); |
355 | if (!rbnode) | 363 | if (!rbnode) |
356 | return -ENOMEM; | 364 | return -ENOMEM; |
357 | rbnode->blklen = 1; | 365 | rbnode->blklen = sizeof(*rbnode); |
358 | rbnode->base_reg = reg; | 366 | rbnode->base_reg = reg; |
359 | rbnode->block = kmalloc(rbnode->blklen * map->cache_word_size, | 367 | rbnode->block = kmalloc(rbnode->blklen * map->cache_word_size, |
360 | GFP_KERNEL); | 368 | GFP_KERNEL); |
@@ -362,7 +370,7 @@ static int regcache_rbtree_write(struct regmap *map, unsigned int reg, | |||
362 | kfree(rbnode); | 370 | kfree(rbnode); |
363 | return -ENOMEM; | 371 | return -ENOMEM; |
364 | } | 372 | } |
365 | regcache_rbtree_set_register(rbnode, 0, value, map->cache_word_size); | 373 | regcache_rbtree_set_register(map, rbnode, 0, value); |
366 | regcache_rbtree_insert(map, &rbtree_ctx->root, rbnode); | 374 | regcache_rbtree_insert(map, &rbtree_ctx->root, rbnode); |
367 | rbtree_ctx->cached_rbnode = rbnode; | 375 | rbtree_ctx->cached_rbnode = rbnode; |
368 | } | 376 | } |
@@ -376,10 +384,8 @@ static int regcache_rbtree_sync(struct regmap *map, unsigned int min, | |||
376 | struct regcache_rbtree_ctx *rbtree_ctx; | 384 | struct regcache_rbtree_ctx *rbtree_ctx; |
377 | struct rb_node *node; | 385 | struct rb_node *node; |
378 | struct regcache_rbtree_node *rbnode; | 386 | struct regcache_rbtree_node *rbnode; |
379 | unsigned int regtmp; | ||
380 | unsigned int val; | ||
381 | int ret; | 387 | int ret; |
382 | int i, base, end; | 388 | int base, end; |
383 | 389 | ||
384 | rbtree_ctx = map->cache; | 390 | rbtree_ctx = map->cache; |
385 | for (node = rb_first(&rbtree_ctx->root); node; node = rb_next(node)) { | 391 | for (node = rb_first(&rbtree_ctx->root); node; node = rb_next(node)) { |
@@ -402,27 +408,13 @@ static int regcache_rbtree_sync(struct regmap *map, unsigned int min, | |||
402 | else | 408 | else |
403 | end = rbnode->blklen; | 409 | end = rbnode->blklen; |
404 | 410 | ||
405 | for (i = base; i < end; i++) { | 411 | ret = regcache_sync_block(map, rbnode->block, rbnode->base_reg, |
406 | regtmp = rbnode->base_reg + (i * map->reg_stride); | 412 | base, end); |
407 | val = regcache_rbtree_get_register(rbnode, i, | 413 | if (ret != 0) |
408 | map->cache_word_size); | 414 | return ret; |
409 | |||
410 | /* Is this the hardware default? If so skip. */ | ||
411 | ret = regcache_lookup_reg(map, regtmp); | ||
412 | if (ret >= 0 && val == map->reg_defaults[ret].def) | ||
413 | continue; | ||
414 | |||
415 | map->cache_bypass = 1; | ||
416 | ret = _regmap_write(map, regtmp, val); | ||
417 | map->cache_bypass = 0; | ||
418 | if (ret) | ||
419 | return ret; | ||
420 | dev_dbg(map->dev, "Synced register %#x, value %#x\n", | ||
421 | regtmp, val); | ||
422 | } | ||
423 | } | 415 | } |
424 | 416 | ||
425 | return 0; | 417 | return regmap_async_complete(map); |
426 | } | 418 | } |
427 | 419 | ||
428 | struct regcache_ops regcache_rbtree_ops = { | 420 | struct regcache_ops regcache_rbtree_ops = { |
diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c index e69ff3e4742c..75923f2396bd 100644 --- a/drivers/base/regmap/regcache.c +++ b/drivers/base/regmap/regcache.c | |||
@@ -45,8 +45,8 @@ static int regcache_hw_init(struct regmap *map) | |||
45 | tmp_buf = kmalloc(map->cache_size_raw, GFP_KERNEL); | 45 | tmp_buf = kmalloc(map->cache_size_raw, GFP_KERNEL); |
46 | if (!tmp_buf) | 46 | if (!tmp_buf) |
47 | return -EINVAL; | 47 | return -EINVAL; |
48 | ret = regmap_bulk_read(map, 0, tmp_buf, | 48 | ret = regmap_raw_read(map, 0, tmp_buf, |
49 | map->num_reg_defaults_raw); | 49 | map->num_reg_defaults_raw); |
50 | map->cache_bypass = cache_bypass; | 50 | map->cache_bypass = cache_bypass; |
51 | if (ret < 0) { | 51 | if (ret < 0) { |
52 | kfree(tmp_buf); | 52 | kfree(tmp_buf); |
@@ -58,8 +58,7 @@ static int regcache_hw_init(struct regmap *map) | |||
58 | 58 | ||
59 | /* calculate the size of reg_defaults */ | 59 | /* calculate the size of reg_defaults */ |
60 | for (count = 0, i = 0; i < map->num_reg_defaults_raw; i++) { | 60 | for (count = 0, i = 0; i < map->num_reg_defaults_raw; i++) { |
61 | val = regcache_get_val(map->reg_defaults_raw, | 61 | val = regcache_get_val(map, map->reg_defaults_raw, i); |
62 | i, map->cache_word_size); | ||
63 | if (regmap_volatile(map, i * map->reg_stride)) | 62 | if (regmap_volatile(map, i * map->reg_stride)) |
64 | continue; | 63 | continue; |
65 | count++; | 64 | count++; |
@@ -75,8 +74,7 @@ static int regcache_hw_init(struct regmap *map) | |||
75 | /* fill the reg_defaults */ | 74 | /* fill the reg_defaults */ |
76 | map->num_reg_defaults = count; | 75 | map->num_reg_defaults = count; |
77 | for (i = 0, j = 0; i < map->num_reg_defaults_raw; i++) { | 76 | for (i = 0, j = 0; i < map->num_reg_defaults_raw; i++) { |
78 | val = regcache_get_val(map->reg_defaults_raw, | 77 | val = regcache_get_val(map, map->reg_defaults_raw, i); |
79 | i, map->cache_word_size); | ||
80 | if (regmap_volatile(map, i * map->reg_stride)) | 78 | if (regmap_volatile(map, i * map->reg_stride)) |
81 | continue; | 79 | continue; |
82 | map->reg_defaults[j].reg = i * map->reg_stride; | 80 | map->reg_defaults[j].reg = i * map->reg_stride; |
@@ -123,6 +121,8 @@ int regcache_init(struct regmap *map, const struct regmap_config *config) | |||
123 | map->reg_defaults_raw = config->reg_defaults_raw; | 121 | map->reg_defaults_raw = config->reg_defaults_raw; |
124 | map->cache_word_size = DIV_ROUND_UP(config->val_bits, 8); | 122 | map->cache_word_size = DIV_ROUND_UP(config->val_bits, 8); |
125 | map->cache_size_raw = map->cache_word_size * config->num_reg_defaults_raw; | 123 | map->cache_size_raw = map->cache_word_size * config->num_reg_defaults_raw; |
124 | map->cache_present = NULL; | ||
125 | map->cache_present_nbits = 0; | ||
126 | 126 | ||
127 | map->cache = NULL; | 127 | map->cache = NULL; |
128 | map->cache_ops = cache_types[i]; | 128 | map->cache_ops = cache_types[i]; |
@@ -181,6 +181,7 @@ void regcache_exit(struct regmap *map) | |||
181 | 181 | ||
182 | BUG_ON(!map->cache_ops); | 182 | BUG_ON(!map->cache_ops); |
183 | 183 | ||
184 | kfree(map->cache_present); | ||
184 | kfree(map->reg_defaults); | 185 | kfree(map->reg_defaults); |
185 | if (map->cache_free) | 186 | if (map->cache_free) |
186 | kfree(map->reg_defaults_raw); | 187 | kfree(map->reg_defaults_raw); |
@@ -417,28 +418,68 @@ void regcache_cache_bypass(struct regmap *map, bool enable) | |||
417 | } | 418 | } |
418 | EXPORT_SYMBOL_GPL(regcache_cache_bypass); | 419 | EXPORT_SYMBOL_GPL(regcache_cache_bypass); |
419 | 420 | ||
420 | bool regcache_set_val(void *base, unsigned int idx, | 421 | int regcache_set_reg_present(struct regmap *map, unsigned int reg) |
421 | unsigned int val, unsigned int word_size) | ||
422 | { | 422 | { |
423 | switch (word_size) { | 423 | unsigned long *cache_present; |
424 | unsigned int cache_present_size; | ||
425 | unsigned int nregs; | ||
426 | int i; | ||
427 | |||
428 | nregs = reg + 1; | ||
429 | cache_present_size = BITS_TO_LONGS(nregs); | ||
430 | cache_present_size *= sizeof(long); | ||
431 | |||
432 | if (!map->cache_present) { | ||
433 | cache_present = kmalloc(cache_present_size, GFP_KERNEL); | ||
434 | if (!cache_present) | ||
435 | return -ENOMEM; | ||
436 | bitmap_zero(cache_present, nregs); | ||
437 | map->cache_present = cache_present; | ||
438 | map->cache_present_nbits = nregs; | ||
439 | } | ||
440 | |||
441 | if (nregs > map->cache_present_nbits) { | ||
442 | cache_present = krealloc(map->cache_present, | ||
443 | cache_present_size, GFP_KERNEL); | ||
444 | if (!cache_present) | ||
445 | return -ENOMEM; | ||
446 | for (i = 0; i < nregs; i++) | ||
447 | if (i >= map->cache_present_nbits) | ||
448 | clear_bit(i, cache_present); | ||
449 | map->cache_present = cache_present; | ||
450 | map->cache_present_nbits = nregs; | ||
451 | } | ||
452 | |||
453 | set_bit(reg, map->cache_present); | ||
454 | return 0; | ||
455 | } | ||
456 | |||
457 | bool regcache_set_val(struct regmap *map, void *base, unsigned int idx, | ||
458 | unsigned int val) | ||
459 | { | ||
460 | if (regcache_get_val(map, base, idx) == val) | ||
461 | return true; | ||
462 | |||
463 | /* Use device native format if possible */ | ||
464 | if (map->format.format_val) { | ||
465 | map->format.format_val(base + (map->cache_word_size * idx), | ||
466 | val, 0); | ||
467 | return false; | ||
468 | } | ||
469 | |||
470 | switch (map->cache_word_size) { | ||
424 | case 1: { | 471 | case 1: { |
425 | u8 *cache = base; | 472 | u8 *cache = base; |
426 | if (cache[idx] == val) | ||
427 | return true; | ||
428 | cache[idx] = val; | 473 | cache[idx] = val; |
429 | break; | 474 | break; |
430 | } | 475 | } |
431 | case 2: { | 476 | case 2: { |
432 | u16 *cache = base; | 477 | u16 *cache = base; |
433 | if (cache[idx] == val) | ||
434 | return true; | ||
435 | cache[idx] = val; | 478 | cache[idx] = val; |
436 | break; | 479 | break; |
437 | } | 480 | } |
438 | case 4: { | 481 | case 4: { |
439 | u32 *cache = base; | 482 | u32 *cache = base; |
440 | if (cache[idx] == val) | ||
441 | return true; | ||
442 | cache[idx] = val; | 483 | cache[idx] = val; |
443 | break; | 484 | break; |
444 | } | 485 | } |
@@ -448,13 +489,18 @@ bool regcache_set_val(void *base, unsigned int idx, | |||
448 | return false; | 489 | return false; |
449 | } | 490 | } |
450 | 491 | ||
451 | unsigned int regcache_get_val(const void *base, unsigned int idx, | 492 | unsigned int regcache_get_val(struct regmap *map, const void *base, |
452 | unsigned int word_size) | 493 | unsigned int idx) |
453 | { | 494 | { |
454 | if (!base) | 495 | if (!base) |
455 | return -EINVAL; | 496 | return -EINVAL; |
456 | 497 | ||
457 | switch (word_size) { | 498 | /* Use device native format if possible */ |
499 | if (map->format.parse_val) | ||
500 | return map->format.parse_val(regcache_get_val_addr(map, base, | ||
501 | idx)); | ||
502 | |||
503 | switch (map->cache_word_size) { | ||
458 | case 1: { | 504 | case 1: { |
459 | const u8 *cache = base; | 505 | const u8 *cache = base; |
460 | return cache[idx]; | 506 | return cache[idx]; |
@@ -498,3 +544,117 @@ int regcache_lookup_reg(struct regmap *map, unsigned int reg) | |||
498 | else | 544 | else |
499 | return -ENOENT; | 545 | return -ENOENT; |
500 | } | 546 | } |
547 | |||
548 | static int regcache_sync_block_single(struct regmap *map, void *block, | ||
549 | unsigned int block_base, | ||
550 | unsigned int start, unsigned int end) | ||
551 | { | ||
552 | unsigned int i, regtmp, val; | ||
553 | int ret; | ||
554 | |||
555 | for (i = start; i < end; i++) { | ||
556 | regtmp = block_base + (i * map->reg_stride); | ||
557 | |||
558 | if (!regcache_reg_present(map, regtmp)) | ||
559 | continue; | ||
560 | |||
561 | val = regcache_get_val(map, block, i); | ||
562 | |||
563 | /* Is this the hardware default? If so skip. */ | ||
564 | ret = regcache_lookup_reg(map, regtmp); | ||
565 | if (ret >= 0 && val == map->reg_defaults[ret].def) | ||
566 | continue; | ||
567 | |||
568 | map->cache_bypass = 1; | ||
569 | |||
570 | ret = _regmap_write(map, regtmp, val); | ||
571 | |||
572 | map->cache_bypass = 0; | ||
573 | if (ret != 0) | ||
574 | return ret; | ||
575 | dev_dbg(map->dev, "Synced register %#x, value %#x\n", | ||
576 | regtmp, val); | ||
577 | } | ||
578 | |||
579 | return 0; | ||
580 | } | ||
581 | |||
582 | static int regcache_sync_block_raw_flush(struct regmap *map, const void **data, | ||
583 | unsigned int base, unsigned int cur) | ||
584 | { | ||
585 | size_t val_bytes = map->format.val_bytes; | ||
586 | int ret, count; | ||
587 | |||
588 | if (*data == NULL) | ||
589 | return 0; | ||
590 | |||
591 | count = cur - base; | ||
592 | |||
593 | dev_dbg(map->dev, "Writing %zu bytes for %d registers from 0x%x-0x%x\n", | ||
594 | count * val_bytes, count, base, cur - 1); | ||
595 | |||
596 | map->cache_bypass = 1; | ||
597 | |||
598 | ret = _regmap_raw_write(map, base, *data, count * val_bytes, | ||
599 | false); | ||
600 | |||
601 | map->cache_bypass = 0; | ||
602 | |||
603 | *data = NULL; | ||
604 | |||
605 | return ret; | ||
606 | } | ||
607 | |||
608 | static int regcache_sync_block_raw(struct regmap *map, void *block, | ||
609 | unsigned int block_base, unsigned int start, | ||
610 | unsigned int end) | ||
611 | { | ||
612 | unsigned int i, val; | ||
613 | unsigned int regtmp = 0; | ||
614 | unsigned int base = 0; | ||
615 | const void *data = NULL; | ||
616 | int ret; | ||
617 | |||
618 | for (i = start; i < end; i++) { | ||
619 | regtmp = block_base + (i * map->reg_stride); | ||
620 | |||
621 | if (!regcache_reg_present(map, regtmp)) { | ||
622 | ret = regcache_sync_block_raw_flush(map, &data, | ||
623 | base, regtmp); | ||
624 | if (ret != 0) | ||
625 | return ret; | ||
626 | continue; | ||
627 | } | ||
628 | |||
629 | val = regcache_get_val(map, block, i); | ||
630 | |||
631 | /* Is this the hardware default? If so skip. */ | ||
632 | ret = regcache_lookup_reg(map, regtmp); | ||
633 | if (ret >= 0 && val == map->reg_defaults[ret].def) { | ||
634 | ret = regcache_sync_block_raw_flush(map, &data, | ||
635 | base, regtmp); | ||
636 | if (ret != 0) | ||
637 | return ret; | ||
638 | continue; | ||
639 | } | ||
640 | |||
641 | if (!data) { | ||
642 | data = regcache_get_val_addr(map, block, i); | ||
643 | base = regtmp; | ||
644 | } | ||
645 | } | ||
646 | |||
647 | return regcache_sync_block_raw_flush(map, &data, base, regtmp); | ||
648 | } | ||
649 | |||
650 | int regcache_sync_block(struct regmap *map, void *block, | ||
651 | unsigned int block_base, unsigned int start, | ||
652 | unsigned int end) | ||
653 | { | ||
654 | if (regmap_can_raw_write(map)) | ||
655 | return regcache_sync_block_raw(map, block, block_base, | ||
656 | start, end); | ||
657 | else | ||
658 | return regcache_sync_block_single(map, block, block_base, | ||
659 | start, end); | ||
660 | } | ||
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index 672ac082cafa..a941dcfe7590 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c | |||
@@ -228,30 +228,39 @@ static void regmap_format_32_native(void *buf, unsigned int val, | |||
228 | *(u32 *)buf = val << shift; | 228 | *(u32 *)buf = val << shift; |
229 | } | 229 | } |
230 | 230 | ||
231 | static unsigned int regmap_parse_8(void *buf) | 231 | static void regmap_parse_inplace_noop(void *buf) |
232 | { | 232 | { |
233 | u8 *b = buf; | 233 | } |
234 | |||
235 | static unsigned int regmap_parse_8(const void *buf) | ||
236 | { | ||
237 | const u8 *b = buf; | ||
234 | 238 | ||
235 | return b[0]; | 239 | return b[0]; |
236 | } | 240 | } |
237 | 241 | ||
238 | static unsigned int regmap_parse_16_be(void *buf) | 242 | static unsigned int regmap_parse_16_be(const void *buf) |
243 | { | ||
244 | const __be16 *b = buf; | ||
245 | |||
246 | return be16_to_cpu(b[0]); | ||
247 | } | ||
248 | |||
249 | static void regmap_parse_16_be_inplace(void *buf) | ||
239 | { | 250 | { |
240 | __be16 *b = buf; | 251 | __be16 *b = buf; |
241 | 252 | ||
242 | b[0] = be16_to_cpu(b[0]); | 253 | b[0] = be16_to_cpu(b[0]); |
243 | |||
244 | return b[0]; | ||
245 | } | 254 | } |
246 | 255 | ||
247 | static unsigned int regmap_parse_16_native(void *buf) | 256 | static unsigned int regmap_parse_16_native(const void *buf) |
248 | { | 257 | { |
249 | return *(u16 *)buf; | 258 | return *(u16 *)buf; |
250 | } | 259 | } |
251 | 260 | ||
252 | static unsigned int regmap_parse_24(void *buf) | 261 | static unsigned int regmap_parse_24(const void *buf) |
253 | { | 262 | { |
254 | u8 *b = buf; | 263 | const u8 *b = buf; |
255 | unsigned int ret = b[2]; | 264 | unsigned int ret = b[2]; |
256 | ret |= ((unsigned int)b[1]) << 8; | 265 | ret |= ((unsigned int)b[1]) << 8; |
257 | ret |= ((unsigned int)b[0]) << 16; | 266 | ret |= ((unsigned int)b[0]) << 16; |
@@ -259,16 +268,21 @@ static unsigned int regmap_parse_24(void *buf) | |||
259 | return ret; | 268 | return ret; |
260 | } | 269 | } |
261 | 270 | ||
262 | static unsigned int regmap_parse_32_be(void *buf) | 271 | static unsigned int regmap_parse_32_be(const void *buf) |
272 | { | ||
273 | const __be32 *b = buf; | ||
274 | |||
275 | return be32_to_cpu(b[0]); | ||
276 | } | ||
277 | |||
278 | static void regmap_parse_32_be_inplace(void *buf) | ||
263 | { | 279 | { |
264 | __be32 *b = buf; | 280 | __be32 *b = buf; |
265 | 281 | ||
266 | b[0] = be32_to_cpu(b[0]); | 282 | b[0] = be32_to_cpu(b[0]); |
267 | |||
268 | return b[0]; | ||
269 | } | 283 | } |
270 | 284 | ||
271 | static unsigned int regmap_parse_32_native(void *buf) | 285 | static unsigned int regmap_parse_32_native(const void *buf) |
272 | { | 286 | { |
273 | return *(u32 *)buf; | 287 | return *(u32 *)buf; |
274 | } | 288 | } |
@@ -555,16 +569,21 @@ struct regmap *regmap_init(struct device *dev, | |||
555 | goto err_map; | 569 | goto err_map; |
556 | } | 570 | } |
557 | 571 | ||
572 | if (val_endian == REGMAP_ENDIAN_NATIVE) | ||
573 | map->format.parse_inplace = regmap_parse_inplace_noop; | ||
574 | |||
558 | switch (config->val_bits) { | 575 | switch (config->val_bits) { |
559 | case 8: | 576 | case 8: |
560 | map->format.format_val = regmap_format_8; | 577 | map->format.format_val = regmap_format_8; |
561 | map->format.parse_val = regmap_parse_8; | 578 | map->format.parse_val = regmap_parse_8; |
579 | map->format.parse_inplace = regmap_parse_inplace_noop; | ||
562 | break; | 580 | break; |
563 | case 16: | 581 | case 16: |
564 | switch (val_endian) { | 582 | switch (val_endian) { |
565 | case REGMAP_ENDIAN_BIG: | 583 | case REGMAP_ENDIAN_BIG: |
566 | map->format.format_val = regmap_format_16_be; | 584 | map->format.format_val = regmap_format_16_be; |
567 | map->format.parse_val = regmap_parse_16_be; | 585 | map->format.parse_val = regmap_parse_16_be; |
586 | map->format.parse_inplace = regmap_parse_16_be_inplace; | ||
568 | break; | 587 | break; |
569 | case REGMAP_ENDIAN_NATIVE: | 588 | case REGMAP_ENDIAN_NATIVE: |
570 | map->format.format_val = regmap_format_16_native; | 589 | map->format.format_val = regmap_format_16_native; |
@@ -585,6 +604,7 @@ struct regmap *regmap_init(struct device *dev, | |||
585 | case REGMAP_ENDIAN_BIG: | 604 | case REGMAP_ENDIAN_BIG: |
586 | map->format.format_val = regmap_format_32_be; | 605 | map->format.format_val = regmap_format_32_be; |
587 | map->format.parse_val = regmap_parse_32_be; | 606 | map->format.parse_val = regmap_parse_32_be; |
607 | map->format.parse_inplace = regmap_parse_32_be_inplace; | ||
588 | break; | 608 | break; |
589 | case REGMAP_ENDIAN_NATIVE: | 609 | case REGMAP_ENDIAN_NATIVE: |
590 | map->format.format_val = regmap_format_32_native; | 610 | map->format.format_val = regmap_format_32_native; |
@@ -917,8 +937,8 @@ static int _regmap_select_page(struct regmap *map, unsigned int *reg, | |||
917 | return 0; | 937 | return 0; |
918 | } | 938 | } |
919 | 939 | ||
920 | static int _regmap_raw_write(struct regmap *map, unsigned int reg, | 940 | int _regmap_raw_write(struct regmap *map, unsigned int reg, |
921 | const void *val, size_t val_len, bool async) | 941 | const void *val, size_t val_len, bool async) |
922 | { | 942 | { |
923 | struct regmap_range_node *range; | 943 | struct regmap_range_node *range; |
924 | unsigned long flags; | 944 | unsigned long flags; |
@@ -930,7 +950,7 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg, | |||
930 | size_t len; | 950 | size_t len; |
931 | int i; | 951 | int i; |
932 | 952 | ||
933 | BUG_ON(!map->bus); | 953 | WARN_ON(!map->bus); |
934 | 954 | ||
935 | /* Check for unwritable registers before we start */ | 955 | /* Check for unwritable registers before we start */ |
936 | if (map->writeable_reg) | 956 | if (map->writeable_reg) |
@@ -943,8 +963,7 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg, | |||
943 | unsigned int ival; | 963 | unsigned int ival; |
944 | int val_bytes = map->format.val_bytes; | 964 | int val_bytes = map->format.val_bytes; |
945 | for (i = 0; i < val_len / val_bytes; i++) { | 965 | for (i = 0; i < val_len / val_bytes; i++) { |
946 | memcpy(map->work_buf, val + (i * val_bytes), val_bytes); | 966 | ival = map->format.parse_val(val + (i * val_bytes)); |
947 | ival = map->format.parse_val(map->work_buf); | ||
948 | ret = regcache_write(map, reg + (i * map->reg_stride), | 967 | ret = regcache_write(map, reg + (i * map->reg_stride), |
949 | ival); | 968 | ival); |
950 | if (ret) { | 969 | if (ret) { |
@@ -1081,6 +1100,17 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg, | |||
1081 | return ret; | 1100 | return ret; |
1082 | } | 1101 | } |
1083 | 1102 | ||
1103 | /** | ||
1104 | * regmap_can_raw_write - Test if regmap_raw_write() is supported | ||
1105 | * | ||
1106 | * @map: Map to check. | ||
1107 | */ | ||
1108 | bool regmap_can_raw_write(struct regmap *map) | ||
1109 | { | ||
1110 | return map->bus && map->format.format_val && map->format.format_reg; | ||
1111 | } | ||
1112 | EXPORT_SYMBOL_GPL(regmap_can_raw_write); | ||
1113 | |||
1084 | static int _regmap_bus_formatted_write(void *context, unsigned int reg, | 1114 | static int _regmap_bus_formatted_write(void *context, unsigned int reg, |
1085 | unsigned int val) | 1115 | unsigned int val) |
1086 | { | 1116 | { |
@@ -1088,7 +1118,7 @@ static int _regmap_bus_formatted_write(void *context, unsigned int reg, | |||
1088 | struct regmap_range_node *range; | 1118 | struct regmap_range_node *range; |
1089 | struct regmap *map = context; | 1119 | struct regmap *map = context; |
1090 | 1120 | ||
1091 | BUG_ON(!map->bus || !map->format.format_write); | 1121 | WARN_ON(!map->bus || !map->format.format_write); |
1092 | 1122 | ||
1093 | range = _regmap_range_lookup(map, reg); | 1123 | range = _regmap_range_lookup(map, reg); |
1094 | if (range) { | 1124 | if (range) { |
@@ -1114,7 +1144,7 @@ static int _regmap_bus_raw_write(void *context, unsigned int reg, | |||
1114 | { | 1144 | { |
1115 | struct regmap *map = context; | 1145 | struct regmap *map = context; |
1116 | 1146 | ||
1117 | BUG_ON(!map->bus || !map->format.format_val); | 1147 | WARN_ON(!map->bus || !map->format.format_val); |
1118 | 1148 | ||
1119 | map->format.format_val(map->work_buf + map->format.reg_bytes | 1149 | map->format.format_val(map->work_buf + map->format.reg_bytes |
1120 | + map->format.pad_bytes, val, 0); | 1150 | + map->format.pad_bytes, val, 0); |
@@ -1204,12 +1234,10 @@ int regmap_raw_write(struct regmap *map, unsigned int reg, | |||
1204 | { | 1234 | { |
1205 | int ret; | 1235 | int ret; |
1206 | 1236 | ||
1207 | if (!map->bus) | 1237 | if (!regmap_can_raw_write(map)) |
1208 | return -EINVAL; | 1238 | return -EINVAL; |
1209 | if (val_len % map->format.val_bytes) | 1239 | if (val_len % map->format.val_bytes) |
1210 | return -EINVAL; | 1240 | return -EINVAL; |
1211 | if (reg % map->reg_stride) | ||
1212 | return -EINVAL; | ||
1213 | 1241 | ||
1214 | map->lock(map->lock_arg); | 1242 | map->lock(map->lock_arg); |
1215 | 1243 | ||
@@ -1244,7 +1272,7 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val, | |||
1244 | 1272 | ||
1245 | if (!map->bus) | 1273 | if (!map->bus) |
1246 | return -EINVAL; | 1274 | return -EINVAL; |
1247 | if (!map->format.parse_val) | 1275 | if (!map->format.parse_inplace) |
1248 | return -EINVAL; | 1276 | return -EINVAL; |
1249 | if (reg % map->reg_stride) | 1277 | if (reg % map->reg_stride) |
1250 | return -EINVAL; | 1278 | return -EINVAL; |
@@ -1262,7 +1290,7 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val, | |||
1262 | goto out; | 1290 | goto out; |
1263 | } | 1291 | } |
1264 | for (i = 0; i < val_count * val_bytes; i += val_bytes) | 1292 | for (i = 0; i < val_count * val_bytes; i += val_bytes) |
1265 | map->format.parse_val(wval + i); | 1293 | map->format.parse_inplace(wval + i); |
1266 | } | 1294 | } |
1267 | /* | 1295 | /* |
1268 | * Some devices does not support bulk write, for | 1296 | * Some devices does not support bulk write, for |
@@ -1340,7 +1368,7 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val, | |||
1340 | u8 *u8 = map->work_buf; | 1368 | u8 *u8 = map->work_buf; |
1341 | int ret; | 1369 | int ret; |
1342 | 1370 | ||
1343 | BUG_ON(!map->bus); | 1371 | WARN_ON(!map->bus); |
1344 | 1372 | ||
1345 | range = _regmap_range_lookup(map, reg); | 1373 | range = _regmap_range_lookup(map, reg); |
1346 | if (range) { | 1374 | if (range) { |
@@ -1395,7 +1423,7 @@ static int _regmap_read(struct regmap *map, unsigned int reg, | |||
1395 | int ret; | 1423 | int ret; |
1396 | void *context = _regmap_map_get_context(map); | 1424 | void *context = _regmap_map_get_context(map); |
1397 | 1425 | ||
1398 | BUG_ON(!map->reg_read); | 1426 | WARN_ON(!map->reg_read); |
1399 | 1427 | ||
1400 | if (!map->cache_bypass) { | 1428 | if (!map->cache_bypass) { |
1401 | ret = regcache_read(map, reg, val); | 1429 | ret = regcache_read(map, reg, val); |
@@ -1523,7 +1551,7 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val, | |||
1523 | 1551 | ||
1524 | if (!map->bus) | 1552 | if (!map->bus) |
1525 | return -EINVAL; | 1553 | return -EINVAL; |
1526 | if (!map->format.parse_val) | 1554 | if (!map->format.parse_inplace) |
1527 | return -EINVAL; | 1555 | return -EINVAL; |
1528 | if (reg % map->reg_stride) | 1556 | if (reg % map->reg_stride) |
1529 | return -EINVAL; | 1557 | return -EINVAL; |
@@ -1550,7 +1578,7 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val, | |||
1550 | } | 1578 | } |
1551 | 1579 | ||
1552 | for (i = 0; i < val_count * val_bytes; i += val_bytes) | 1580 | for (i = 0; i < val_count * val_bytes; i += val_bytes) |
1553 | map->format.parse_val(val + i); | 1581 | map->format.parse_inplace(val + i); |
1554 | } else { | 1582 | } else { |
1555 | for (i = 0; i < val_count; i++) { | 1583 | for (i = 0; i < val_count; i++) { |
1556 | unsigned int ival; | 1584 | unsigned int ival; |