aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2013-04-16 11:05:46 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2013-04-16 11:05:46 -0400
commit5b3b44847590b3cbaafdf01d4ad260fa53d04167 (patch)
treeaf353c62902fce0cb8c1205da0977346bd2c915f /drivers/base
parentb508c80c553c03baf5c9ad5612ac8caceb13c5f4 (diff)
parent5a08d15602987bbdff3407d7645f95b7a70f1a6f (diff)
Merge remote-tracking branch 'regmap/topic/cache' into regmap-next
Diffstat (limited to 'drivers/base')
-rw-r--r--drivers/base/regmap/internal.h39
-rw-r--r--drivers/base/regmap/regcache-lzo.c6
-rw-r--r--drivers/base/regmap/regcache-rbtree.c100
-rw-r--r--drivers/base/regmap/regcache.c196
-rw-r--r--drivers/base/regmap/regmap.c84
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
44struct regmap_async { 45struct 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,
187int regcache_write(struct regmap *map, 191int regcache_write(struct regmap *map,
188 unsigned int reg, unsigned int value); 192 unsigned int reg, unsigned int value);
189int regcache_sync(struct regmap *map); 193int regcache_sync(struct regmap *map);
190 194int regcache_sync_block(struct regmap *map, void *block,
191unsigned 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);
193bool regcache_set_val(void *base, unsigned int idx, 197
194 unsigned int val, unsigned int word_size); 198static 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
205unsigned int regcache_get_val(struct regmap *map, const void *base,
206 unsigned int idx);
207bool regcache_set_val(struct regmap *map, void *base, unsigned int idx,
208 unsigned int val);
195int regcache_lookup_reg(struct regmap *map, unsigned int reg); 209int regcache_lookup_reg(struct regmap *map, unsigned int reg);
210int regcache_set_reg_present(struct regmap *map, unsigned int reg);
211
212static 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
221int _regmap_raw_write(struct regmap *map, unsigned int reg,
222 const void *val, size_t val_len, bool async);
196 223
197void regmap_async_complete_cb(struct regmap_async *async, int ret); 224void 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
50static unsigned int regcache_rbtree_get_register( 50static 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
57static void regcache_rbtree_set_register(struct regcache_rbtree_node *rbnode, 56static 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
64static struct regcache_rbtree_node *regcache_rbtree_lookup(struct regmap *map, 63static 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
273static int regcache_rbtree_insert_to_block(struct regcache_rbtree_node *rbnode, 279static 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
428struct regcache_ops regcache_rbtree_ops = { 420struct 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}
418EXPORT_SYMBOL_GPL(regcache_cache_bypass); 419EXPORT_SYMBOL_GPL(regcache_cache_bypass);
419 420
420bool regcache_set_val(void *base, unsigned int idx, 421int 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
457bool 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
451unsigned int regcache_get_val(const void *base, unsigned int idx, 492unsigned 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
548static 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
582static 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
608static 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
650int 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
231static unsigned int regmap_parse_8(void *buf) 231static void regmap_parse_inplace_noop(void *buf)
232{ 232{
233 u8 *b = buf; 233}
234
235static 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
238static unsigned int regmap_parse_16_be(void *buf) 242static 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
249static 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
247static unsigned int regmap_parse_16_native(void *buf) 256static unsigned int regmap_parse_16_native(const void *buf)
248{ 257{
249 return *(u16 *)buf; 258 return *(u16 *)buf;
250} 259}
251 260
252static unsigned int regmap_parse_24(void *buf) 261static 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
262static unsigned int regmap_parse_32_be(void *buf) 271static 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
278static 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
271static unsigned int regmap_parse_32_native(void *buf) 285static 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
920static int _regmap_raw_write(struct regmap *map, unsigned int reg, 940int _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 */
1108bool regmap_can_raw_write(struct regmap *map)
1109{
1110 return map->bus && map->format.format_val && map->format.format_reg;
1111}
1112EXPORT_SYMBOL_GPL(regmap_can_raw_write);
1113
1084static int _regmap_bus_formatted_write(void *context, unsigned int reg, 1114static 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;