diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2012-03-14 09:14:24 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2012-03-14 09:14:24 -0400 |
commit | 4a6be7bb7474500a69f6d8f25899b8038491bdbb (patch) | |
tree | a2645b0f707fcf1ea94a9e7ef7a59b298fb5ecac /drivers/base | |
parent | 7d9aca39dcacd2b3f42e2e287162329f410f93e1 (diff) | |
parent | f9353e70bcebd00cd182d946083afd7d8eddd259 (diff) |
Merge remote-tracking branches 'regmap/topic/patch' and 'regmap/topic/sync' into regmap-next
Diffstat (limited to 'drivers/base')
-rw-r--r-- | drivers/base/regmap/internal.h | 2 | ||||
-rw-r--r-- | drivers/base/regmap/regcache-lzo.c | 10 | ||||
-rw-r--r-- | drivers/base/regmap/regcache-rbtree.c | 25 | ||||
-rw-r--r-- | drivers/base/regmap/regcache.c | 69 |
4 files changed, 81 insertions, 25 deletions
diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h index abd76678ed73..fcafc5b2e651 100644 --- a/drivers/base/regmap/internal.h +++ b/drivers/base/regmap/internal.h | |||
@@ -88,7 +88,7 @@ struct regcache_ops { | |||
88 | int (*exit)(struct regmap *map); | 88 | int (*exit)(struct regmap *map); |
89 | int (*read)(struct regmap *map, unsigned int reg, unsigned int *value); | 89 | int (*read)(struct regmap *map, unsigned int reg, unsigned int *value); |
90 | int (*write)(struct regmap *map, unsigned int reg, unsigned int value); | 90 | int (*write)(struct regmap *map, unsigned int reg, unsigned int value); |
91 | int (*sync)(struct regmap *map); | 91 | int (*sync)(struct regmap *map, unsigned int min, unsigned int max); |
92 | }; | 92 | }; |
93 | 93 | ||
94 | bool regmap_writeable(struct regmap *map, unsigned int reg); | 94 | bool regmap_writeable(struct regmap *map, unsigned int reg); |
diff --git a/drivers/base/regmap/regcache-lzo.c b/drivers/base/regmap/regcache-lzo.c index 3025cf920f25..8d0061569326 100644 --- a/drivers/base/regmap/regcache-lzo.c +++ b/drivers/base/regmap/regcache-lzo.c | |||
@@ -331,7 +331,8 @@ out: | |||
331 | return ret; | 331 | return ret; |
332 | } | 332 | } |
333 | 333 | ||
334 | static int regcache_lzo_sync(struct regmap *map) | 334 | static int regcache_lzo_sync(struct regmap *map, unsigned int min, |
335 | unsigned int max) | ||
335 | { | 336 | { |
336 | struct regcache_lzo_ctx **lzo_blocks; | 337 | struct regcache_lzo_ctx **lzo_blocks; |
337 | unsigned int val; | 338 | unsigned int val; |
@@ -339,7 +340,12 @@ static int regcache_lzo_sync(struct regmap *map) | |||
339 | int ret; | 340 | int ret; |
340 | 341 | ||
341 | lzo_blocks = map->cache; | 342 | lzo_blocks = map->cache; |
342 | for_each_set_bit(i, lzo_blocks[0]->sync_bmp, lzo_blocks[0]->sync_bmp_nbits) { | 343 | i = min; |
344 | for_each_set_bit_cont(i, lzo_blocks[0]->sync_bmp, | ||
345 | lzo_blocks[0]->sync_bmp_nbits) { | ||
346 | if (i > max) | ||
347 | continue; | ||
348 | |||
343 | ret = regcache_read(map, i, &val); | 349 | ret = regcache_read(map, i, &val); |
344 | if (ret) | 350 | if (ret) |
345 | return ret; | 351 | return ret; |
diff --git a/drivers/base/regmap/regcache-rbtree.c b/drivers/base/regmap/regcache-rbtree.c index 861ad2c81dff..8d51916a283d 100644 --- a/drivers/base/regmap/regcache-rbtree.c +++ b/drivers/base/regmap/regcache-rbtree.c | |||
@@ -357,7 +357,8 @@ static int regcache_rbtree_write(struct regmap *map, unsigned int reg, | |||
357 | return 0; | 357 | return 0; |
358 | } | 358 | } |
359 | 359 | ||
360 | static int regcache_rbtree_sync(struct regmap *map) | 360 | static int regcache_rbtree_sync(struct regmap *map, unsigned int min, |
361 | unsigned int max) | ||
361 | { | 362 | { |
362 | struct regcache_rbtree_ctx *rbtree_ctx; | 363 | struct regcache_rbtree_ctx *rbtree_ctx; |
363 | struct rb_node *node; | 364 | struct rb_node *node; |
@@ -365,12 +366,30 @@ static int regcache_rbtree_sync(struct regmap *map) | |||
365 | unsigned int regtmp; | 366 | unsigned int regtmp; |
366 | unsigned int val; | 367 | unsigned int val; |
367 | int ret; | 368 | int ret; |
368 | int i; | 369 | int i, base, end; |
369 | 370 | ||
370 | rbtree_ctx = map->cache; | 371 | rbtree_ctx = map->cache; |
371 | for (node = rb_first(&rbtree_ctx->root); node; node = rb_next(node)) { | 372 | for (node = rb_first(&rbtree_ctx->root); node; node = rb_next(node)) { |
372 | rbnode = rb_entry(node, struct regcache_rbtree_node, node); | 373 | rbnode = rb_entry(node, struct regcache_rbtree_node, node); |
373 | for (i = 0; i < rbnode->blklen; i++) { | 374 | |
375 | if (rbnode->base_reg < min) | ||
376 | continue; | ||
377 | if (rbnode->base_reg > max) | ||
378 | break; | ||
379 | if (rbnode->base_reg + rbnode->blklen < min) | ||
380 | continue; | ||
381 | |||
382 | if (min > rbnode->base_reg) | ||
383 | base = min - rbnode->base_reg; | ||
384 | else | ||
385 | base = 0; | ||
386 | |||
387 | if (max < rbnode->base_reg + rbnode->blklen) | ||
388 | end = rbnode->base_reg + rbnode->blklen - max; | ||
389 | else | ||
390 | end = rbnode->blklen; | ||
391 | |||
392 | for (i = base; i < end; i++) { | ||
374 | regtmp = rbnode->base_reg + i; | 393 | regtmp = rbnode->base_reg + i; |
375 | val = regcache_rbtree_get_register(rbnode, i, | 394 | val = regcache_rbtree_get_register(rbnode, i, |
376 | map->cache_word_size); | 395 | map->cache_word_size); |
diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c index 8db713ffef66..fb84d711fbb4 100644 --- a/drivers/base/regmap/regcache.c +++ b/drivers/base/regmap/regcache.c | |||
@@ -252,12 +252,11 @@ int regcache_write(struct regmap *map, | |||
252 | int regcache_sync(struct regmap *map) | 252 | int regcache_sync(struct regmap *map) |
253 | { | 253 | { |
254 | int ret = 0; | 254 | int ret = 0; |
255 | unsigned int val; | ||
256 | unsigned int i; | 255 | unsigned int i; |
257 | const char *name; | 256 | const char *name; |
258 | unsigned int bypass; | 257 | unsigned int bypass; |
259 | 258 | ||
260 | BUG_ON(!map->cache_ops); | 259 | BUG_ON(!map->cache_ops || !map->cache_ops->sync); |
261 | 260 | ||
262 | mutex_lock(&map->lock); | 261 | mutex_lock(&map->lock); |
263 | /* Remember the initial bypass state */ | 262 | /* Remember the initial bypass state */ |
@@ -282,24 +281,11 @@ int regcache_sync(struct regmap *map) | |||
282 | } | 281 | } |
283 | map->cache_bypass = 0; | 282 | map->cache_bypass = 0; |
284 | 283 | ||
285 | if (map->cache_ops->sync) { | 284 | ret = map->cache_ops->sync(map, 0, map->max_register); |
286 | ret = map->cache_ops->sync(map); | 285 | |
287 | } else { | 286 | if (ret == 0) |
288 | for (i = 0; i < map->num_reg_defaults; i++) { | 287 | map->cache_dirty = false; |
289 | ret = regcache_read(map, i, &val); | ||
290 | if (ret < 0) | ||
291 | goto out; | ||
292 | map->cache_bypass = 1; | ||
293 | ret = _regmap_write(map, i, val); | ||
294 | map->cache_bypass = 0; | ||
295 | if (ret < 0) | ||
296 | goto out; | ||
297 | dev_dbg(map->dev, "Synced register %#x, value %#x\n", | ||
298 | map->reg_defaults[i].reg, | ||
299 | map->reg_defaults[i].def); | ||
300 | } | ||
301 | 288 | ||
302 | } | ||
303 | out: | 289 | out: |
304 | trace_regcache_sync(map->dev, name, "stop"); | 290 | trace_regcache_sync(map->dev, name, "stop"); |
305 | /* Restore the bypass state */ | 291 | /* Restore the bypass state */ |
@@ -311,6 +297,51 @@ out: | |||
311 | EXPORT_SYMBOL_GPL(regcache_sync); | 297 | EXPORT_SYMBOL_GPL(regcache_sync); |
312 | 298 | ||
313 | /** | 299 | /** |
300 | * regcache_sync_region: Sync part of the register cache with the hardware. | ||
301 | * | ||
302 | * @map: map to sync. | ||
303 | * @min: first register to sync | ||
304 | * @max: last register to sync | ||
305 | * | ||
306 | * Write all non-default register values in the specified region to | ||
307 | * the hardware. | ||
308 | * | ||
309 | * Return a negative value on failure, 0 on success. | ||
310 | */ | ||
311 | int regcache_sync_region(struct regmap *map, unsigned int min, | ||
312 | unsigned int max) | ||
313 | { | ||
314 | int ret = 0; | ||
315 | const char *name; | ||
316 | unsigned int bypass; | ||
317 | |||
318 | BUG_ON(!map->cache_ops || !map->cache_ops->sync); | ||
319 | |||
320 | mutex_lock(&map->lock); | ||
321 | |||
322 | /* Remember the initial bypass state */ | ||
323 | bypass = map->cache_bypass; | ||
324 | |||
325 | name = map->cache_ops->name; | ||
326 | dev_dbg(map->dev, "Syncing %s cache from %d-%d\n", name, min, max); | ||
327 | |||
328 | trace_regcache_sync(map->dev, name, "start region"); | ||
329 | |||
330 | if (!map->cache_dirty) | ||
331 | goto out; | ||
332 | |||
333 | ret = map->cache_ops->sync(map, min, max); | ||
334 | |||
335 | out: | ||
336 | trace_regcache_sync(map->dev, name, "stop region"); | ||
337 | /* Restore the bypass state */ | ||
338 | map->cache_bypass = bypass; | ||
339 | mutex_unlock(&map->lock); | ||
340 | |||
341 | return ret; | ||
342 | } | ||
343 | |||
344 | /** | ||
314 | * regcache_cache_only: Put a register map into cache only mode | 345 | * regcache_cache_only: Put a register map into cache only mode |
315 | * | 346 | * |
316 | * @map: map to configure | 347 | * @map: map to configure |