blob: e1846eb2f171fa0b12714cc0fdd74796da6e42dd [file] [log] [blame]
Dimitris Papastamos9fabe242011-09-19 14:34:00 +01001/*
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>
Dimitris Papastamosc08604b2011-10-03 10:50:14 +010015#include <linux/sort.h>
Dimitris Papastamos9fabe242011-09-19 14:34:00 +010016
17#include "internal.h"
18
19static const struct regcache_ops *cache_types[] = {
Dimitris Papastamos195af652011-09-19 14:34:01 +010020 &regcache_indexed_ops,
Dimitris Papastamos28644c802011-09-19 14:34:02 +010021 &regcache_rbtree_ops,
Dimitris Papastamos2cbbb572011-09-19 14:34:03 +010022 &regcache_lzo_ops,
Dimitris Papastamos9fabe242011-09-19 14:34:00 +010023};
24
25static int regcache_hw_init(struct regmap *map)
26{
27 int i, j;
28 int ret;
29 int count;
30 unsigned int val;
31 void *tmp_buf;
32
33 if (!map->num_reg_defaults_raw)
34 return -EINVAL;
35
36 if (!map->reg_defaults_raw) {
37 dev_warn(map->dev, "No cache defaults, reading back from HW\n");
38 tmp_buf = kmalloc(map->cache_size_raw, GFP_KERNEL);
39 if (!tmp_buf)
40 return -EINVAL;
41 ret = regmap_bulk_read(map, 0, tmp_buf,
42 map->num_reg_defaults_raw);
43 if (ret < 0) {
44 kfree(tmp_buf);
45 return ret;
46 }
47 map->reg_defaults_raw = tmp_buf;
48 map->cache_free = 1;
49 }
50
51 /* calculate the size of reg_defaults */
52 for (count = 0, i = 0; i < map->num_reg_defaults_raw; i++) {
53 val = regcache_get_val(map->reg_defaults_raw,
54 i, map->cache_word_size);
55 if (!val)
56 continue;
57 count++;
58 }
59
60 map->reg_defaults = kmalloc(count * sizeof(struct reg_default),
61 GFP_KERNEL);
62 if (!map->reg_defaults)
63 return -ENOMEM;
64
65 /* fill the reg_defaults */
66 map->num_reg_defaults = count;
67 for (i = 0, j = 0; i < map->num_reg_defaults_raw; i++) {
68 val = regcache_get_val(map->reg_defaults_raw,
69 i, map->cache_word_size);
70 if (!val)
71 continue;
72 map->reg_defaults[j].reg = i;
73 map->reg_defaults[j].def = val;
74 j++;
75 }
76
77 return 0;
78}
79
80int regcache_init(struct regmap *map)
81{
82 int ret;
83 int i;
84 void *tmp_buf;
85
Mark Browne7a6db32011-09-19 16:08:03 +010086 if (map->cache_type == REGCACHE_NONE) {
87 map->cache_bypass = true;
Dimitris Papastamos9fabe242011-09-19 14:34:00 +010088 return 0;
Mark Browne7a6db32011-09-19 16:08:03 +010089 }
Dimitris Papastamos9fabe242011-09-19 14:34:00 +010090
91 for (i = 0; i < ARRAY_SIZE(cache_types); i++)
92 if (cache_types[i]->type == map->cache_type)
93 break;
94
95 if (i == ARRAY_SIZE(cache_types)) {
96 dev_err(map->dev, "Could not match compress type: %d\n",
97 map->cache_type);
98 return -EINVAL;
99 }
100
101 map->cache = NULL;
102 map->cache_ops = cache_types[i];
103
104 if (!map->cache_ops->read ||
105 !map->cache_ops->write ||
106 !map->cache_ops->name)
107 return -EINVAL;
108
109 /* We still need to ensure that the reg_defaults
110 * won't vanish from under us. We'll need to make
111 * a copy of it.
112 */
113 if (map->reg_defaults) {
114 if (!map->num_reg_defaults)
115 return -EINVAL;
116 tmp_buf = kmemdup(map->reg_defaults, map->num_reg_defaults *
117 sizeof(struct reg_default), GFP_KERNEL);
118 if (!tmp_buf)
119 return -ENOMEM;
120 map->reg_defaults = tmp_buf;
121 } else {
Mark Brown5fcd2562011-09-29 15:24:54 +0100122 /* Some devices such as PMICs don't have cache defaults,
Dimitris Papastamos9fabe242011-09-19 14:34:00 +0100123 * we cope with this by reading back the HW registers and
124 * crafting the cache defaults by hand.
125 */
126 ret = regcache_hw_init(map);
127 if (ret < 0)
128 return ret;
129 }
130
131 if (!map->max_register)
132 map->max_register = map->num_reg_defaults_raw;
133
134 if (map->cache_ops->init) {
135 dev_dbg(map->dev, "Initializing %s cache\n",
136 map->cache_ops->name);
137 return map->cache_ops->init(map);
138 }
139 return 0;
140}
141
142void regcache_exit(struct regmap *map)
143{
144 if (map->cache_type == REGCACHE_NONE)
145 return;
146
147 BUG_ON(!map->cache_ops);
148
149 kfree(map->reg_defaults);
150 if (map->cache_free)
151 kfree(map->reg_defaults_raw);
152
153 if (map->cache_ops->exit) {
154 dev_dbg(map->dev, "Destroying %s cache\n",
155 map->cache_ops->name);
156 map->cache_ops->exit(map);
157 }
158}
159
160/**
161 * regcache_read: Fetch the value of a given register from the cache.
162 *
163 * @map: map to configure.
164 * @reg: The register index.
165 * @value: The value to be returned.
166 *
167 * Return a negative value on failure, 0 on success.
168 */
169int regcache_read(struct regmap *map,
170 unsigned int reg, unsigned int *value)
171{
172 if (map->cache_type == REGCACHE_NONE)
173 return -ENOSYS;
174
175 BUG_ON(!map->cache_ops);
176
177 if (!regmap_readable(map, reg))
178 return -EIO;
179
180 if (!regmap_volatile(map, reg))
181 return map->cache_ops->read(map, reg, value);
182
183 return -EINVAL;
184}
185EXPORT_SYMBOL_GPL(regcache_read);
186
187/**
188 * regcache_write: Set the value of a given register in the cache.
189 *
190 * @map: map to configure.
191 * @reg: The register index.
192 * @value: The new register value.
193 *
194 * Return a negative value on failure, 0 on success.
195 */
196int regcache_write(struct regmap *map,
197 unsigned int reg, unsigned int value)
198{
199 if (map->cache_type == REGCACHE_NONE)
200 return 0;
201
202 BUG_ON(!map->cache_ops);
203
204 if (!regmap_writeable(map, reg))
205 return -EIO;
206
207 if (!regmap_volatile(map, reg))
208 return map->cache_ops->write(map, reg, value);
209
210 return 0;
211}
212EXPORT_SYMBOL_GPL(regcache_write);
213
214/**
215 * regcache_sync: Sync the register cache with the hardware.
216 *
217 * @map: map to configure.
218 *
219 * Any registers that should not be synced should be marked as
220 * volatile. In general drivers can choose not to use the provided
221 * syncing functionality if they so require.
222 *
223 * Return a negative value on failure, 0 on success.
224 */
225int regcache_sync(struct regmap *map)
226{
Dimitris Papastamos954757d2011-09-27 11:25:06 +0100227 int ret = 0;
228 unsigned int val;
229 unsigned int i;
Dimitris Papastamos59360082011-09-19 14:34:04 +0100230 const char *name;
Dimitris Papastamosbeb1a102011-09-29 14:36:26 +0100231 unsigned int bypass;
Dimitris Papastamos59360082011-09-19 14:34:04 +0100232
Dimitris Papastamos9fabe242011-09-19 14:34:00 +0100233 BUG_ON(!map->cache_ops);
234
Dimitris Papastamos13753a92011-09-29 14:36:25 +0100235 mutex_lock(&map->lock);
Dimitris Papastamosbeb1a102011-09-29 14:36:26 +0100236 /* Remember the initial bypass state */
237 bypass = map->cache_bypass;
Dimitris Papastamos954757d2011-09-27 11:25:06 +0100238 dev_dbg(map->dev, "Syncing %s cache\n",
239 map->cache_ops->name);
240 name = map->cache_ops->name;
241 trace_regcache_sync(map->dev, name, "start");
Dimitris Papastamos9fabe242011-09-19 14:34:00 +0100242 if (map->cache_ops->sync) {
Dimitris Papastamos59360082011-09-19 14:34:04 +0100243 ret = map->cache_ops->sync(map);
Dimitris Papastamos954757d2011-09-27 11:25:06 +0100244 } else {
245 for (i = 0; i < map->num_reg_defaults; i++) {
246 ret = regcache_read(map, i, &val);
247 if (ret < 0)
248 goto out;
Dimitris Papastamosec8a3652011-09-28 11:43:42 +0100249 map->cache_bypass = 1;
Dimitris Papastamos13753a92011-09-29 14:36:25 +0100250 ret = _regmap_write(map, i, val);
Dimitris Papastamosec8a3652011-09-28 11:43:42 +0100251 map->cache_bypass = 0;
Dimitris Papastamos954757d2011-09-27 11:25:06 +0100252 if (ret < 0)
253 goto out;
254 dev_dbg(map->dev, "Synced register %#x, value %#x\n",
255 map->reg_defaults[i].reg,
256 map->reg_defaults[i].def);
257 }
258
Dimitris Papastamos9fabe242011-09-19 14:34:00 +0100259 }
Dimitris Papastamos954757d2011-09-27 11:25:06 +0100260out:
261 trace_regcache_sync(map->dev, name, "stop");
Dimitris Papastamosbeb1a102011-09-29 14:36:26 +0100262 /* Restore the bypass state */
263 map->cache_bypass = bypass;
Dimitris Papastamos13753a92011-09-29 14:36:25 +0100264 mutex_unlock(&map->lock);
Dimitris Papastamos954757d2011-09-27 11:25:06 +0100265
266 return ret;
Dimitris Papastamos9fabe242011-09-19 14:34:00 +0100267}
268EXPORT_SYMBOL_GPL(regcache_sync);
269
Mark Brown92afb282011-09-19 18:22:14 +0100270/**
271 * regcache_cache_only: Put a register map into cache only mode
272 *
273 * @map: map to configure
274 * @cache_only: flag if changes should be written to the hardware
275 *
276 * When a register map is marked as cache only writes to the register
277 * map API will only update the register cache, they will not cause
278 * any hardware changes. This is useful for allowing portions of
279 * drivers to act as though the device were functioning as normal when
280 * it is disabled for power saving reasons.
281 */
282void regcache_cache_only(struct regmap *map, bool enable)
283{
Mark Brown2cd148f12011-09-29 10:40:55 +0100284 mutex_lock(&map->lock);
Dimitris Papastamosac77a762011-09-29 14:36:28 +0100285 WARN_ON(map->cache_bypass && enable);
Mark Brown92afb282011-09-19 18:22:14 +0100286 map->cache_only = enable;
Mark Brown2cd148f12011-09-29 10:40:55 +0100287 mutex_unlock(&map->lock);
Mark Brown92afb282011-09-19 18:22:14 +0100288}
289EXPORT_SYMBOL_GPL(regcache_cache_only);
290
Dimitris Papastamos6eb0f5e2011-09-29 14:36:27 +0100291/**
292 * regcache_cache_bypass: Put a register map into cache bypass mode
293 *
294 * @map: map to configure
295 * @cache_only: flag if changes should not be written to the hardware
296 *
297 * When a register map is marked with the cache bypass option, writes
298 * to the register map API will only update the hardware and not the
299 * the cache directly. This is useful when syncing the cache back to
300 * the hardware.
301 */
302void regcache_cache_bypass(struct regmap *map, bool enable)
303{
304 mutex_lock(&map->lock);
Dimitris Papastamosac77a762011-09-29 14:36:28 +0100305 WARN_ON(map->cache_only && enable);
Dimitris Papastamos6eb0f5e2011-09-29 14:36:27 +0100306 map->cache_bypass = enable;
307 mutex_unlock(&map->lock);
308}
309EXPORT_SYMBOL_GPL(regcache_cache_bypass);
310
Dimitris Papastamos9fabe242011-09-19 14:34:00 +0100311bool regcache_set_val(void *base, unsigned int idx,
312 unsigned int val, unsigned int word_size)
313{
314 switch (word_size) {
315 case 1: {
316 u8 *cache = base;
317 if (cache[idx] == val)
318 return true;
319 cache[idx] = val;
320 break;
321 }
322 case 2: {
323 u16 *cache = base;
324 if (cache[idx] == val)
325 return true;
326 cache[idx] = val;
327 break;
328 }
329 default:
330 BUG();
331 }
332 /* unreachable */
333 return false;
334}
335
336unsigned int regcache_get_val(const void *base, unsigned int idx,
337 unsigned int word_size)
338{
339 if (!base)
340 return -EINVAL;
341
342 switch (word_size) {
343 case 1: {
344 const u8 *cache = base;
345 return cache[idx];
346 }
347 case 2: {
348 const u16 *cache = base;
349 return cache[idx];
350 }
351 default:
352 BUG();
353 }
354 /* unreachable */
355 return -1;
356}
357
358int regcache_lookup_reg(struct regmap *map, unsigned int reg)
359{
Dimitris Papastamosc08604b2011-10-03 10:50:14 +0100360 unsigned int min, max, index;
Dimitris Papastamos9fabe242011-09-19 14:34:00 +0100361
Dimitris Papastamosc08604b2011-10-03 10:50:14 +0100362 min = 0;
363 max = map->num_reg_defaults - 1;
364 do {
365 index = (min + max) / 2;
366 if (map->reg_defaults[index].reg == reg)
367 return index;
368 if (map->reg_defaults[index].reg < reg)
369 min = index + 1;
370 else
371 max = index;
372 } while (min <= max);
Dimitris Papastamos9fabe242011-09-19 14:34:00 +0100373 return -1;
374}
375
Dimitris Papastamosc08604b2011-10-03 10:50:14 +0100376static int regcache_insert_cmp(const void *a, const void *b)
377{
378 const struct reg_default *_a = a;
379 const struct reg_default *_b = b;
380
381 return _a->reg - _b->reg;
382}
383
Dimitris Papastamos9fabe242011-09-19 14:34:00 +0100384int regcache_insert_reg(struct regmap *map, unsigned int reg,
385 unsigned int val)
386{
387 void *tmp;
388
389 tmp = krealloc(map->reg_defaults,
390 (map->num_reg_defaults + 1) * sizeof(struct reg_default),
391 GFP_KERNEL);
392 if (!tmp)
393 return -ENOMEM;
394 map->reg_defaults = tmp;
395 map->num_reg_defaults++;
396 map->reg_defaults[map->num_reg_defaults - 1].reg = reg;
397 map->reg_defaults[map->num_reg_defaults - 1].def = val;
Dimitris Papastamosc08604b2011-10-03 10:50:14 +0100398 sort(map->reg_defaults, map->num_reg_defaults,
399 sizeof(struct reg_default), regcache_insert_cmp, NULL);
Dimitris Papastamos9fabe242011-09-19 14:34:00 +0100400 return 0;
401}