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