aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/regmap/regcache.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/base/regmap/regcache.c')
-rw-r--r--drivers/base/regmap/regcache.c87
1 files changed, 57 insertions, 30 deletions
diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c
index 666f6f5011dc..1ead66186b7c 100644
--- a/drivers/base/regmap/regcache.c
+++ b/drivers/base/regmap/regcache.c
@@ -19,7 +19,6 @@
19#include "internal.h" 19#include "internal.h"
20 20
21static const struct regcache_ops *cache_types[] = { 21static const struct regcache_ops *cache_types[] = {
22 &regcache_indexed_ops,
23 &regcache_rbtree_ops, 22 &regcache_rbtree_ops,
24 &regcache_lzo_ops, 23 &regcache_lzo_ops,
25}; 24};
@@ -61,8 +60,10 @@ static int regcache_hw_init(struct regmap *map)
61 60
62 map->reg_defaults = kmalloc(count * sizeof(struct reg_default), 61 map->reg_defaults = kmalloc(count * sizeof(struct reg_default),
63 GFP_KERNEL); 62 GFP_KERNEL);
64 if (!map->reg_defaults) 63 if (!map->reg_defaults) {
65 return -ENOMEM; 64 ret = -ENOMEM;
65 goto err_free;
66 }
66 67
67 /* fill the reg_defaults */ 68 /* fill the reg_defaults */
68 map->num_reg_defaults = count; 69 map->num_reg_defaults = count;
@@ -77,9 +78,15 @@ static int regcache_hw_init(struct regmap *map)
77 } 78 }
78 79
79 return 0; 80 return 0;
81
82err_free:
83 if (map->cache_free)
84 kfree(map->reg_defaults_raw);
85
86 return ret;
80} 87}
81 88
82int regcache_init(struct regmap *map) 89int regcache_init(struct regmap *map, const struct regmap_config *config)
83{ 90{
84 int ret; 91 int ret;
85 int i; 92 int i;
@@ -100,6 +107,12 @@ int regcache_init(struct regmap *map)
100 return -EINVAL; 107 return -EINVAL;
101 } 108 }
102 109
110 map->num_reg_defaults = config->num_reg_defaults;
111 map->num_reg_defaults_raw = config->num_reg_defaults_raw;
112 map->reg_defaults_raw = config->reg_defaults_raw;
113 map->cache_word_size = DIV_ROUND_UP(config->val_bits, 8);
114 map->cache_size_raw = map->cache_word_size * config->num_reg_defaults_raw;
115
103 map->cache = NULL; 116 map->cache = NULL;
104 map->cache_ops = cache_types[i]; 117 map->cache_ops = cache_types[i];
105 118
@@ -112,10 +125,10 @@ int regcache_init(struct regmap *map)
112 * won't vanish from under us. We'll need to make 125 * won't vanish from under us. We'll need to make
113 * a copy of it. 126 * a copy of it.
114 */ 127 */
115 if (map->reg_defaults) { 128 if (config->reg_defaults) {
116 if (!map->num_reg_defaults) 129 if (!map->num_reg_defaults)
117 return -EINVAL; 130 return -EINVAL;
118 tmp_buf = kmemdup(map->reg_defaults, map->num_reg_defaults * 131 tmp_buf = kmemdup(config->reg_defaults, map->num_reg_defaults *
119 sizeof(struct reg_default), GFP_KERNEL); 132 sizeof(struct reg_default), GFP_KERNEL);
120 if (!tmp_buf) 133 if (!tmp_buf)
121 return -ENOMEM; 134 return -ENOMEM;
@@ -136,9 +149,18 @@ int regcache_init(struct regmap *map)
136 if (map->cache_ops->init) { 149 if (map->cache_ops->init) {
137 dev_dbg(map->dev, "Initializing %s cache\n", 150 dev_dbg(map->dev, "Initializing %s cache\n",
138 map->cache_ops->name); 151 map->cache_ops->name);
139 return map->cache_ops->init(map); 152 ret = map->cache_ops->init(map);
153 if (ret)
154 goto err_free;
140 } 155 }
141 return 0; 156 return 0;
157
158err_free:
159 kfree(map->reg_defaults);
160 if (map->cache_free)
161 kfree(map->reg_defaults_raw);
162
163 return ret;
142} 164}
143 165
144void regcache_exit(struct regmap *map) 166void regcache_exit(struct regmap *map)
@@ -171,16 +193,21 @@ void regcache_exit(struct regmap *map)
171int regcache_read(struct regmap *map, 193int regcache_read(struct regmap *map,
172 unsigned int reg, unsigned int *value) 194 unsigned int reg, unsigned int *value)
173{ 195{
196 int ret;
197
174 if (map->cache_type == REGCACHE_NONE) 198 if (map->cache_type == REGCACHE_NONE)
175 return -ENOSYS; 199 return -ENOSYS;
176 200
177 BUG_ON(!map->cache_ops); 201 BUG_ON(!map->cache_ops);
178 202
179 if (!regmap_readable(map, reg)) 203 if (!regmap_volatile(map, reg)) {
180 return -EIO; 204 ret = map->cache_ops->read(map, reg, value);
181 205
182 if (!regmap_volatile(map, reg)) 206 if (ret == 0)
183 return map->cache_ops->read(map, reg, value); 207 trace_regmap_reg_read_cache(map->dev, reg, *value);
208
209 return ret;
210 }
184 211
185 return -EINVAL; 212 return -EINVAL;
186} 213}
@@ -241,6 +268,8 @@ int regcache_sync(struct regmap *map)
241 map->cache_ops->name); 268 map->cache_ops->name);
242 name = map->cache_ops->name; 269 name = map->cache_ops->name;
243 trace_regcache_sync(map->dev, name, "start"); 270 trace_regcache_sync(map->dev, name, "start");
271 if (!map->cache_dirty)
272 goto out;
244 if (map->cache_ops->sync) { 273 if (map->cache_ops->sync) {
245 ret = map->cache_ops->sync(map); 274 ret = map->cache_ops->sync(map);
246 } else { 275 } else {
@@ -291,6 +320,23 @@ void regcache_cache_only(struct regmap *map, bool enable)
291EXPORT_SYMBOL_GPL(regcache_cache_only); 320EXPORT_SYMBOL_GPL(regcache_cache_only);
292 321
293/** 322/**
323 * regcache_mark_dirty: Mark the register cache as dirty
324 *
325 * @map: map to mark
326 *
327 * Mark the register cache as dirty, for example due to the device
328 * having been powered down for suspend. If the cache is not marked
329 * as dirty then the cache sync will be suppressed.
330 */
331void regcache_mark_dirty(struct regmap *map)
332{
333 mutex_lock(&map->lock);
334 map->cache_dirty = true;
335 mutex_unlock(&map->lock);
336}
337EXPORT_SYMBOL_GPL(regcache_mark_dirty);
338
339/**
294 * regcache_cache_bypass: Put a register map into cache bypass mode 340 * regcache_cache_bypass: Put a register map into cache bypass mode
295 * 341 *
296 * @map: map to configure 342 * @map: map to configure
@@ -381,22 +427,3 @@ int regcache_lookup_reg(struct regmap *map, unsigned int reg)
381 else 427 else
382 return -ENOENT; 428 return -ENOENT;
383} 429}
384
385int regcache_insert_reg(struct regmap *map, unsigned int reg,
386 unsigned int val)
387{
388 void *tmp;
389
390 tmp = krealloc(map->reg_defaults,
391 (map->num_reg_defaults + 1) * sizeof(struct reg_default),
392 GFP_KERNEL);
393 if (!tmp)
394 return -ENOMEM;
395 map->reg_defaults = tmp;
396 map->num_reg_defaults++;
397 map->reg_defaults[map->num_reg_defaults - 1].reg = reg;
398 map->reg_defaults[map->num_reg_defaults - 1].def = val;
399 sort(map->reg_defaults, map->num_reg_defaults,
400 sizeof(struct reg_default), regcache_default_cmp, NULL);
401 return 0;
402}