regmap: Add the rbtree cache support
[linux-2.6-block.git] / drivers / base / regmap / regcache.c
CommitLineData
9fabe24e
DP
1/*
2 * Register cache access API
3 *
4 * Copyright 2011 Wolfson Microelectronics plc
5 *
6 * Author: Dimitris Papastamos <dp@opensource.wolfsonmicro.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/slab.h>
14#include <trace/events/regmap.h>
15
16#include "internal.h"
17
18static const struct regcache_ops *cache_types[] = {
195af65c 19 &regcache_indexed_ops,
28644c80 20 &regcache_rbtree_ops,
9fabe24e
DP
21};
22
23static int regcache_hw_init(struct regmap *map)
24{
25 int i, j;
26 int ret;
27 int count;
28 unsigned int val;
29 void *tmp_buf;
30
31 if (!map->num_reg_defaults_raw)
32 return -EINVAL;
33
34 if (!map->reg_defaults_raw) {
35 dev_warn(map->dev, "No cache defaults, reading back from HW\n");
36 tmp_buf = kmalloc(map->cache_size_raw, GFP_KERNEL);
37 if (!tmp_buf)
38 return -EINVAL;
39 ret = regmap_bulk_read(map, 0, tmp_buf,
40 map->num_reg_defaults_raw);
41 if (ret < 0) {
42 kfree(tmp_buf);
43 return ret;
44 }
45 map->reg_defaults_raw = tmp_buf;
46 map->cache_free = 1;
47 }
48
49 /* calculate the size of reg_defaults */
50 for (count = 0, i = 0; i < map->num_reg_defaults_raw; i++) {
51 val = regcache_get_val(map->reg_defaults_raw,
52 i, map->cache_word_size);
53 if (!val)
54 continue;
55 count++;
56 }
57
58 map->reg_defaults = kmalloc(count * sizeof(struct reg_default),
59 GFP_KERNEL);
60 if (!map->reg_defaults)
61 return -ENOMEM;
62
63 /* fill the reg_defaults */
64 map->num_reg_defaults = count;
65 for (i = 0, j = 0; i < map->num_reg_defaults_raw; i++) {
66 val = regcache_get_val(map->reg_defaults_raw,
67 i, map->cache_word_size);
68 if (!val)
69 continue;
70 map->reg_defaults[j].reg = i;
71 map->reg_defaults[j].def = val;
72 j++;
73 }
74
75 return 0;
76}
77
78int regcache_init(struct regmap *map)
79{
80 int ret;
81 int i;
82 void *tmp_buf;
83
84 if (map->cache_type == REGCACHE_NONE)
85 return 0;
86
87 for (i = 0; i < ARRAY_SIZE(cache_types); i++)
88 if (cache_types[i]->type == map->cache_type)
89 break;
90
91 if (i == ARRAY_SIZE(cache_types)) {
92 dev_err(map->dev, "Could not match compress type: %d\n",
93 map->cache_type);
94 return -EINVAL;
95 }
96
97 map->cache = NULL;
98 map->cache_ops = cache_types[i];
99
100 if (!map->cache_ops->read ||
101 !map->cache_ops->write ||
102 !map->cache_ops->name)
103 return -EINVAL;
104
105 /* We still need to ensure that the reg_defaults
106 * won't vanish from under us. We'll need to make
107 * a copy of it.
108 */
109 if (map->reg_defaults) {
110 if (!map->num_reg_defaults)
111 return -EINVAL;
112 tmp_buf = kmemdup(map->reg_defaults, map->num_reg_defaults *
113 sizeof(struct reg_default), GFP_KERNEL);
114 if (!tmp_buf)
115 return -ENOMEM;
116 map->reg_defaults = tmp_buf;
117 } else {
118 /* Some devices such as PMIC's don't have cache defaults,
119 * we cope with this by reading back the HW registers and
120 * crafting the cache defaults by hand.
121 */
122 ret = regcache_hw_init(map);
123 if (ret < 0)
124 return ret;
125 }
126
127 if (!map->max_register)
128 map->max_register = map->num_reg_defaults_raw;
129
130 if (map->cache_ops->init) {
131 dev_dbg(map->dev, "Initializing %s cache\n",
132 map->cache_ops->name);
133 return map->cache_ops->init(map);
134 }
135 return 0;
136}
137
138void regcache_exit(struct regmap *map)
139{
140 if (map->cache_type == REGCACHE_NONE)
141 return;
142
143 BUG_ON(!map->cache_ops);
144
145 kfree(map->reg_defaults);
146 if (map->cache_free)
147 kfree(map->reg_defaults_raw);
148
149 if (map->cache_ops->exit) {
150 dev_dbg(map->dev, "Destroying %s cache\n",
151 map->cache_ops->name);
152 map->cache_ops->exit(map);
153 }
154}
155
156/**
157 * regcache_read: Fetch the value of a given register from the cache.
158 *
159 * @map: map to configure.
160 * @reg: The register index.
161 * @value: The value to be returned.
162 *
163 * Return a negative value on failure, 0 on success.
164 */
165int regcache_read(struct regmap *map,
166 unsigned int reg, unsigned int *value)
167{
168 if (map->cache_type == REGCACHE_NONE)
169 return -ENOSYS;
170
171 BUG_ON(!map->cache_ops);
172
173 if (!regmap_readable(map, reg))
174 return -EIO;
175
176 if (!regmap_volatile(map, reg))
177 return map->cache_ops->read(map, reg, value);
178
179 return -EINVAL;
180}
181EXPORT_SYMBOL_GPL(regcache_read);
182
183/**
184 * regcache_write: Set the value of a given register in the cache.
185 *
186 * @map: map to configure.
187 * @reg: The register index.
188 * @value: The new register value.
189 *
190 * Return a negative value on failure, 0 on success.
191 */
192int regcache_write(struct regmap *map,
193 unsigned int reg, unsigned int value)
194{
195 if (map->cache_type == REGCACHE_NONE)
196 return 0;
197
198 BUG_ON(!map->cache_ops);
199
200 if (!regmap_writeable(map, reg))
201 return -EIO;
202
203 if (!regmap_volatile(map, reg))
204 return map->cache_ops->write(map, reg, value);
205
206 return 0;
207}
208EXPORT_SYMBOL_GPL(regcache_write);
209
210/**
211 * regcache_sync: Sync the register cache with the hardware.
212 *
213 * @map: map to configure.
214 *
215 * Any registers that should not be synced should be marked as
216 * volatile. In general drivers can choose not to use the provided
217 * syncing functionality if they so require.
218 *
219 * Return a negative value on failure, 0 on success.
220 */
221int regcache_sync(struct regmap *map)
222{
223 BUG_ON(!map->cache_ops);
224
225 if (map->cache_ops->sync) {
226 dev_dbg(map->dev, "Syncing %s cache\n",
227 map->cache_ops->name);
228 return map->cache_ops->sync(map);
229 }
230 return 0;
231}
232EXPORT_SYMBOL_GPL(regcache_sync);
233
234bool regcache_set_val(void *base, unsigned int idx,
235 unsigned int val, unsigned int word_size)
236{
237 switch (word_size) {
238 case 1: {
239 u8 *cache = base;
240 if (cache[idx] == val)
241 return true;
242 cache[idx] = val;
243 break;
244 }
245 case 2: {
246 u16 *cache = base;
247 if (cache[idx] == val)
248 return true;
249 cache[idx] = val;
250 break;
251 }
252 default:
253 BUG();
254 }
255 /* unreachable */
256 return false;
257}
258
259unsigned int regcache_get_val(const void *base, unsigned int idx,
260 unsigned int word_size)
261{
262 if (!base)
263 return -EINVAL;
264
265 switch (word_size) {
266 case 1: {
267 const u8 *cache = base;
268 return cache[idx];
269 }
270 case 2: {
271 const u16 *cache = base;
272 return cache[idx];
273 }
274 default:
275 BUG();
276 }
277 /* unreachable */
278 return -1;
279}
280
281int regcache_lookup_reg(struct regmap *map, unsigned int reg)
282{
283 unsigned int i;
284
285 for (i = 0; i < map->num_reg_defaults; i++)
286 if (map->reg_defaults[i].reg == reg)
287 return i;
288 return -1;
289}
290
291int regcache_insert_reg(struct regmap *map, unsigned int reg,
292 unsigned int val)
293{
294 void *tmp;
295
296 tmp = krealloc(map->reg_defaults,
297 (map->num_reg_defaults + 1) * sizeof(struct reg_default),
298 GFP_KERNEL);
299 if (!tmp)
300 return -ENOMEM;
301 map->reg_defaults = tmp;
302 map->num_reg_defaults++;
303 map->reg_defaults[map->num_reg_defaults - 1].reg = reg;
304 map->reg_defaults[map->num_reg_defaults - 1].def = val;
305 return 0;
306}