aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/regmap
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-10-25 07:57:45 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-10-25 07:57:45 -0400
commit4e7e2a2008f5d8c49791c412849d5b0232d39bb3 (patch)
tree32c3fa2d5cefb388689cb795225022769bf7b413 /drivers/base/regmap
parent8a9ea3237e7eb5c25f09e429ad242ae5a3d5ea22 (diff)
parent7cccbdc84487616c3dbe493b04bfa1f362f4bc56 (diff)
Merge branch 'for-linus' of git://opensource.wolfsonmicro.com/regmap
* 'for-linus' of git://opensource.wolfsonmicro.com/regmap: (62 commits) mfd: Enable rbtree cache for wm831x devices regmap: Support some block operations on cached devices regmap: Allow caches for devices with no defaults regmap: Ensure rbtree syncs registers set to zero properly regmap: Allow rbtree to cache zero default values regmap: Warn on raw I/O as well as bulk reads that bypass cache regmap: Return a sensible error code if we fail to read the cache regmap: Use bsearch() to search the register defaults regmap: Fix doc comment regmap: Optimize the lookup path to use binary search regmap: Ensure we scream if we enable cache bypass/only at the same time regmap: Implement regcache_cache_bypass helper function regmap: Save/restore the bypass state upon syncing regmap: Lock the sync path, ensure we use the lockless _regmap_write() regmap: Fix apostrophe usage regmap: Make _regmap_write() global regmap: Fix lock used for regcache_cache_only() regmap: Grab the lock in regcache_cache_only() regmap: Modify map->cache_bypass directly regmap: Fix regcache_sync generic implementation ...
Diffstat (limited to 'drivers/base/regmap')
-rw-r--r--drivers/base/regmap/Kconfig2
-rw-r--r--drivers/base/regmap/Makefile3
-rw-r--r--drivers/base/regmap/internal.h128
-rw-r--r--drivers/base/regmap/regcache-indexed.c64
-rw-r--r--drivers/base/regmap/regcache-lzo.c361
-rw-r--r--drivers/base/regmap/regcache-rbtree.c345
-rw-r--r--drivers/base/regmap/regcache.c401
-rw-r--r--drivers/base/regmap/regmap-debugfs.c209
-rw-r--r--drivers/base/regmap/regmap-i2c.c2
-rw-r--r--drivers/base/regmap/regmap-spi.c2
-rw-r--r--drivers/base/regmap/regmap.c221
11 files changed, 1691 insertions, 47 deletions
diff --git a/drivers/base/regmap/Kconfig b/drivers/base/regmap/Kconfig
index fabbf6cc5367..2fc6a66f39a4 100644
--- a/drivers/base/regmap/Kconfig
+++ b/drivers/base/regmap/Kconfig
@@ -4,6 +4,8 @@
4 4
5config REGMAP 5config REGMAP
6 default y if (REGMAP_I2C || REGMAP_SPI) 6 default y if (REGMAP_I2C || REGMAP_SPI)
7 select LZO_COMPRESS
8 select LZO_DECOMPRESS
7 bool 9 bool
8 10
9config REGMAP_I2C 11config REGMAP_I2C
diff --git a/drivers/base/regmap/Makefile b/drivers/base/regmap/Makefile
index f476f4571295..0573c8a9dacb 100644
--- a/drivers/base/regmap/Makefile
+++ b/drivers/base/regmap/Makefile
@@ -1,3 +1,4 @@
1obj-$(CONFIG_REGMAP) += regmap.o 1obj-$(CONFIG_REGMAP) += regmap.o regcache.o regcache-indexed.o regcache-rbtree.o regcache-lzo.o
2obj-$(CONFIG_DEBUG_FS) += regmap-debugfs.o
2obj-$(CONFIG_REGMAP_I2C) += regmap-i2c.o 3obj-$(CONFIG_REGMAP_I2C) += regmap-i2c.o
3obj-$(CONFIG_REGMAP_SPI) += regmap-spi.o 4obj-$(CONFIG_REGMAP_SPI) += regmap-spi.o
diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h
new file mode 100644
index 000000000000..348ff02eb93e
--- /dev/null
+++ b/drivers/base/regmap/internal.h
@@ -0,0 +1,128 @@
1/*
2 * Register map access API internal header
3 *
4 * Copyright 2011 Wolfson Microelectronics plc
5 *
6 * Author: Mark Brown <broonie@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#ifndef _REGMAP_INTERNAL_H
14#define _REGMAP_INTERNAL_H
15
16#include <linux/regmap.h>
17#include <linux/fs.h>
18
19struct regmap;
20struct regcache_ops;
21
22struct regmap_format {
23 size_t buf_size;
24 size_t reg_bytes;
25 size_t val_bytes;
26 void (*format_write)(struct regmap *map,
27 unsigned int reg, unsigned int val);
28 void (*format_reg)(void *buf, unsigned int reg);
29 void (*format_val)(void *buf, unsigned int val);
30 unsigned int (*parse_val)(void *buf);
31};
32
33struct regmap {
34 struct mutex lock;
35
36 struct device *dev; /* Device we do I/O on */
37 void *work_buf; /* Scratch buffer used to format I/O */
38 struct regmap_format format; /* Buffer format */
39 const struct regmap_bus *bus;
40
41#ifdef CONFIG_DEBUG_FS
42 struct dentry *debugfs;
43#endif
44
45 unsigned int max_register;
46 bool (*writeable_reg)(struct device *dev, unsigned int reg);
47 bool (*readable_reg)(struct device *dev, unsigned int reg);
48 bool (*volatile_reg)(struct device *dev, unsigned int reg);
49 bool (*precious_reg)(struct device *dev, unsigned int reg);
50
51 u8 read_flag_mask;
52 u8 write_flag_mask;
53
54 /* regcache specific members */
55 const struct regcache_ops *cache_ops;
56 enum regcache_type cache_type;
57
58 /* number of bytes in reg_defaults_raw */
59 unsigned int cache_size_raw;
60 /* number of bytes per word in reg_defaults_raw */
61 unsigned int cache_word_size;
62 /* number of entries in reg_defaults */
63 unsigned int num_reg_defaults;
64 /* number of entries in reg_defaults_raw */
65 unsigned int num_reg_defaults_raw;
66
67 /* if set, only the cache is modified not the HW */
68 unsigned int cache_only:1;
69 /* if set, only the HW is modified not the cache */
70 unsigned int cache_bypass:1;
71 /* if set, remember to free reg_defaults_raw */
72 unsigned int cache_free:1;
73
74 struct reg_default *reg_defaults;
75 const void *reg_defaults_raw;
76 void *cache;
77};
78
79struct regcache_ops {
80 const char *name;
81 enum regcache_type type;
82 int (*init)(struct regmap *map);
83 int (*exit)(struct regmap *map);
84 int (*read)(struct regmap *map, unsigned int reg, unsigned int *value);
85 int (*write)(struct regmap *map, unsigned int reg, unsigned int value);
86 int (*sync)(struct regmap *map);
87};
88
89bool regmap_writeable(struct regmap *map, unsigned int reg);
90bool regmap_readable(struct regmap *map, unsigned int reg);
91bool regmap_volatile(struct regmap *map, unsigned int reg);
92bool regmap_precious(struct regmap *map, unsigned int reg);
93
94int _regmap_write(struct regmap *map, unsigned int reg,
95 unsigned int val);
96
97#ifdef CONFIG_DEBUG_FS
98extern void regmap_debugfs_initcall(void);
99extern void regmap_debugfs_init(struct regmap *map);
100extern void regmap_debugfs_exit(struct regmap *map);
101#else
102static inline void regmap_debugfs_initcall(void) { }
103static inline void regmap_debugfs_init(struct regmap *map) { }
104static inline void regmap_debugfs_exit(struct regmap *map) { }
105#endif
106
107/* regcache core declarations */
108int regcache_init(struct regmap *map);
109void regcache_exit(struct regmap *map);
110int regcache_read(struct regmap *map,
111 unsigned int reg, unsigned int *value);
112int regcache_write(struct regmap *map,
113 unsigned int reg, unsigned int value);
114int regcache_sync(struct regmap *map);
115
116unsigned int regcache_get_val(const void *base, unsigned int idx,
117 unsigned int word_size);
118bool regcache_set_val(void *base, unsigned int idx,
119 unsigned int val, unsigned int word_size);
120int regcache_lookup_reg(struct regmap *map, unsigned int reg);
121int regcache_insert_reg(struct regmap *map, unsigned int reg,
122 unsigned int val);
123
124extern struct regcache_ops regcache_indexed_ops;
125extern struct regcache_ops regcache_rbtree_ops;
126extern struct regcache_ops regcache_lzo_ops;
127
128#endif
diff --git a/drivers/base/regmap/regcache-indexed.c b/drivers/base/regmap/regcache-indexed.c
new file mode 100644
index 000000000000..507731ad8ec1
--- /dev/null
+++ b/drivers/base/regmap/regcache-indexed.c
@@ -0,0 +1,64 @@
1/*
2 * Register cache access API - indexed caching support
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
15#include "internal.h"
16
17static int regcache_indexed_read(struct regmap *map, unsigned int reg,
18 unsigned int *value)
19{
20 int ret;
21
22 ret = regcache_lookup_reg(map, reg);
23 if (ret >= 0)
24 *value = map->reg_defaults[ret].def;
25
26 return ret;
27}
28
29static int regcache_indexed_write(struct regmap *map, unsigned int reg,
30 unsigned int value)
31{
32 int ret;
33
34 ret = regcache_lookup_reg(map, reg);
35 if (ret < 0)
36 return regcache_insert_reg(map, reg, value);
37 map->reg_defaults[ret].def = value;
38 return 0;
39}
40
41static int regcache_indexed_sync(struct regmap *map)
42{
43 unsigned int i;
44 int ret;
45
46 for (i = 0; i < map->num_reg_defaults; i++) {
47 ret = _regmap_write(map, map->reg_defaults[i].reg,
48 map->reg_defaults[i].def);
49 if (ret < 0)
50 return ret;
51 dev_dbg(map->dev, "Synced register %#x, value %#x\n",
52 map->reg_defaults[i].reg,
53 map->reg_defaults[i].def);
54 }
55 return 0;
56}
57
58struct regcache_ops regcache_indexed_ops = {
59 .type = REGCACHE_INDEXED,
60 .name = "indexed",
61 .read = regcache_indexed_read,
62 .write = regcache_indexed_write,
63 .sync = regcache_indexed_sync
64};
diff --git a/drivers/base/regmap/regcache-lzo.c b/drivers/base/regmap/regcache-lzo.c
new file mode 100644
index 000000000000..066aeece3626
--- /dev/null
+++ b/drivers/base/regmap/regcache-lzo.c
@@ -0,0 +1,361 @@
1/*
2 * Register cache access API - LZO caching support
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 <linux/lzo.h>
15
16#include "internal.h"
17
18struct regcache_lzo_ctx {
19 void *wmem;
20 void *dst;
21 const void *src;
22 size_t src_len;
23 size_t dst_len;
24 size_t decompressed_size;
25 unsigned long *sync_bmp;
26 int sync_bmp_nbits;
27};
28
29#define LZO_BLOCK_NUM 8
30static int regcache_lzo_block_count(void)
31{
32 return LZO_BLOCK_NUM;
33}
34
35static int regcache_lzo_prepare(struct regcache_lzo_ctx *lzo_ctx)
36{
37 lzo_ctx->wmem = kmalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL);
38 if (!lzo_ctx->wmem)
39 return -ENOMEM;
40 return 0;
41}
42
43static int regcache_lzo_compress(struct regcache_lzo_ctx *lzo_ctx)
44{
45 size_t compress_size;
46 int ret;
47
48 ret = lzo1x_1_compress(lzo_ctx->src, lzo_ctx->src_len,
49 lzo_ctx->dst, &compress_size, lzo_ctx->wmem);
50 if (ret != LZO_E_OK || compress_size > lzo_ctx->dst_len)
51 return -EINVAL;
52 lzo_ctx->dst_len = compress_size;
53 return 0;
54}
55
56static int regcache_lzo_decompress(struct regcache_lzo_ctx *lzo_ctx)
57{
58 size_t dst_len;
59 int ret;
60
61 dst_len = lzo_ctx->dst_len;
62 ret = lzo1x_decompress_safe(lzo_ctx->src, lzo_ctx->src_len,
63 lzo_ctx->dst, &dst_len);
64 if (ret != LZO_E_OK || dst_len != lzo_ctx->dst_len)
65 return -EINVAL;
66 return 0;
67}
68
69static int regcache_lzo_compress_cache_block(struct regmap *map,
70 struct regcache_lzo_ctx *lzo_ctx)
71{
72 int ret;
73
74 lzo_ctx->dst_len = lzo1x_worst_compress(PAGE_SIZE);
75 lzo_ctx->dst = kmalloc(lzo_ctx->dst_len, GFP_KERNEL);
76 if (!lzo_ctx->dst) {
77 lzo_ctx->dst_len = 0;
78 return -ENOMEM;
79 }
80
81 ret = regcache_lzo_compress(lzo_ctx);
82 if (ret < 0)
83 return ret;
84 return 0;
85}
86
87static int regcache_lzo_decompress_cache_block(struct regmap *map,
88 struct regcache_lzo_ctx *lzo_ctx)
89{
90 int ret;
91
92 lzo_ctx->dst_len = lzo_ctx->decompressed_size;
93 lzo_ctx->dst = kmalloc(lzo_ctx->dst_len, GFP_KERNEL);
94 if (!lzo_ctx->dst) {
95 lzo_ctx->dst_len = 0;
96 return -ENOMEM;
97 }
98
99 ret = regcache_lzo_decompress(lzo_ctx);
100 if (ret < 0)
101 return ret;
102 return 0;
103}
104
105static inline int regcache_lzo_get_blkindex(struct regmap *map,
106 unsigned int reg)
107{
108 return (reg * map->cache_word_size) /
109 DIV_ROUND_UP(map->cache_size_raw, regcache_lzo_block_count());
110}
111
112static inline int regcache_lzo_get_blkpos(struct regmap *map,
113 unsigned int reg)
114{
115 return reg % (DIV_ROUND_UP(map->cache_size_raw, regcache_lzo_block_count()) /
116 map->cache_word_size);
117}
118
119static inline int regcache_lzo_get_blksize(struct regmap *map)
120{
121 return DIV_ROUND_UP(map->cache_size_raw, regcache_lzo_block_count());
122}
123
124static int regcache_lzo_init(struct regmap *map)
125{
126 struct regcache_lzo_ctx **lzo_blocks;
127 size_t bmp_size;
128 int ret, i, blksize, blkcount;
129 const char *p, *end;
130 unsigned long *sync_bmp;
131
132 ret = 0;
133
134 blkcount = regcache_lzo_block_count();
135 map->cache = kzalloc(blkcount * sizeof *lzo_blocks,
136 GFP_KERNEL);
137 if (!map->cache)
138 return -ENOMEM;
139 lzo_blocks = map->cache;
140
141 /*
142 * allocate a bitmap to be used when syncing the cache with
143 * the hardware. Each time a register is modified, the corresponding
144 * bit is set in the bitmap, so we know that we have to sync
145 * that register.
146 */
147 bmp_size = map->num_reg_defaults_raw;
148 sync_bmp = kmalloc(BITS_TO_LONGS(bmp_size) * sizeof(long),
149 GFP_KERNEL);
150 if (!sync_bmp) {
151 ret = -ENOMEM;
152 goto err;
153 }
154 bitmap_zero(sync_bmp, bmp_size);
155
156 /* allocate the lzo blocks and initialize them */
157 for (i = 0; i < blkcount; i++) {
158 lzo_blocks[i] = kzalloc(sizeof **lzo_blocks,
159 GFP_KERNEL);
160 if (!lzo_blocks[i]) {
161 kfree(sync_bmp);
162 ret = -ENOMEM;
163 goto err;
164 }
165 lzo_blocks[i]->sync_bmp = sync_bmp;
166 lzo_blocks[i]->sync_bmp_nbits = bmp_size;
167 /* alloc the working space for the compressed block */
168 ret = regcache_lzo_prepare(lzo_blocks[i]);
169 if (ret < 0)
170 goto err;
171 }
172
173 blksize = regcache_lzo_get_blksize(map);
174 p = map->reg_defaults_raw;
175 end = map->reg_defaults_raw + map->cache_size_raw;
176 /* compress the register map and fill the lzo blocks */
177 for (i = 0; i < blkcount; i++, p += blksize) {
178 lzo_blocks[i]->src = p;
179 if (p + blksize > end)
180 lzo_blocks[i]->src_len = end - p;
181 else
182 lzo_blocks[i]->src_len = blksize;
183 ret = regcache_lzo_compress_cache_block(map,
184 lzo_blocks[i]);
185 if (ret < 0)
186 goto err;
187 lzo_blocks[i]->decompressed_size =
188 lzo_blocks[i]->src_len;
189 }
190
191 return 0;
192err:
193 regcache_exit(map);
194 return ret;
195}
196
197static int regcache_lzo_exit(struct regmap *map)
198{
199 struct regcache_lzo_ctx **lzo_blocks;
200 int i, blkcount;
201
202 lzo_blocks = map->cache;
203 if (!lzo_blocks)
204 return 0;
205
206 blkcount = regcache_lzo_block_count();
207 /*
208 * the pointer to the bitmap used for syncing the cache
209 * is shared amongst all lzo_blocks. Ensure it is freed
210 * only once.
211 */
212 if (lzo_blocks[0])
213 kfree(lzo_blocks[0]->sync_bmp);
214 for (i = 0; i < blkcount; i++) {
215 if (lzo_blocks[i]) {
216 kfree(lzo_blocks[i]->wmem);
217 kfree(lzo_blocks[i]->dst);
218 }
219 /* each lzo_block is a pointer returned by kmalloc or NULL */
220 kfree(lzo_blocks[i]);
221 }
222 kfree(lzo_blocks);
223 map->cache = NULL;
224 return 0;
225}
226
227static int regcache_lzo_read(struct regmap *map,
228 unsigned int reg, unsigned int *value)
229{
230 struct regcache_lzo_ctx *lzo_block, **lzo_blocks;
231 int ret, blkindex, blkpos;
232 size_t blksize, tmp_dst_len;
233 void *tmp_dst;
234
235 /* index of the compressed lzo block */
236 blkindex = regcache_lzo_get_blkindex(map, reg);
237 /* register index within the decompressed block */
238 blkpos = regcache_lzo_get_blkpos(map, reg);
239 /* size of the compressed block */
240 blksize = regcache_lzo_get_blksize(map);
241 lzo_blocks = map->cache;
242 lzo_block = lzo_blocks[blkindex];
243
244 /* save the pointer and length of the compressed block */
245 tmp_dst = lzo_block->dst;
246 tmp_dst_len = lzo_block->dst_len;
247
248 /* prepare the source to be the compressed block */
249 lzo_block->src = lzo_block->dst;
250 lzo_block->src_len = lzo_block->dst_len;
251
252 /* decompress the block */
253 ret = regcache_lzo_decompress_cache_block(map, lzo_block);
254 if (ret >= 0)
255 /* fetch the value from the cache */
256 *value = regcache_get_val(lzo_block->dst, blkpos,
257 map->cache_word_size);
258
259 kfree(lzo_block->dst);
260 /* restore the pointer and length of the compressed block */
261 lzo_block->dst = tmp_dst;
262 lzo_block->dst_len = tmp_dst_len;
263
264 return ret;
265}
266
267static int regcache_lzo_write(struct regmap *map,
268 unsigned int reg, unsigned int value)
269{
270 struct regcache_lzo_ctx *lzo_block, **lzo_blocks;
271 int ret, blkindex, blkpos;
272 size_t blksize, tmp_dst_len;
273 void *tmp_dst;
274
275 /* index of the compressed lzo block */
276 blkindex = regcache_lzo_get_blkindex(map, reg);
277 /* register index within the decompressed block */
278 blkpos = regcache_lzo_get_blkpos(map, reg);
279 /* size of the compressed block */
280 blksize = regcache_lzo_get_blksize(map);
281 lzo_blocks = map->cache;
282 lzo_block = lzo_blocks[blkindex];
283
284 /* save the pointer and length of the compressed block */
285 tmp_dst = lzo_block->dst;
286 tmp_dst_len = lzo_block->dst_len;
287
288 /* prepare the source to be the compressed block */
289 lzo_block->src = lzo_block->dst;
290 lzo_block->src_len = lzo_block->dst_len;
291
292 /* decompress the block */
293 ret = regcache_lzo_decompress_cache_block(map, lzo_block);
294 if (ret < 0) {
295 kfree(lzo_block->dst);
296 goto out;
297 }
298
299 /* write the new value to the cache */
300 if (regcache_set_val(lzo_block->dst, blkpos, value,
301 map->cache_word_size)) {
302 kfree(lzo_block->dst);
303 goto out;
304 }
305
306 /* prepare the source to be the decompressed block */
307 lzo_block->src = lzo_block->dst;
308 lzo_block->src_len = lzo_block->dst_len;
309
310 /* compress the block */
311 ret = regcache_lzo_compress_cache_block(map, lzo_block);
312 if (ret < 0) {
313 kfree(lzo_block->dst);
314 kfree(lzo_block->src);
315 goto out;
316 }
317
318 /* set the bit so we know we have to sync this register */
319 set_bit(reg, lzo_block->sync_bmp);
320 kfree(tmp_dst);
321 kfree(lzo_block->src);
322 return 0;
323out:
324 lzo_block->dst = tmp_dst;
325 lzo_block->dst_len = tmp_dst_len;
326 return ret;
327}
328
329static int regcache_lzo_sync(struct regmap *map)
330{
331 struct regcache_lzo_ctx **lzo_blocks;
332 unsigned int val;
333 int i;
334 int ret;
335
336 lzo_blocks = map->cache;
337 for_each_set_bit(i, lzo_blocks[0]->sync_bmp, lzo_blocks[0]->sync_bmp_nbits) {
338 ret = regcache_read(map, i, &val);
339 if (ret)
340 return ret;
341 map->cache_bypass = 1;
342 ret = _regmap_write(map, i, val);
343 map->cache_bypass = 0;
344 if (ret)
345 return ret;
346 dev_dbg(map->dev, "Synced register %#x, value %#x\n",
347 i, val);
348 }
349
350 return 0;
351}
352
353struct regcache_ops regcache_lzo_ops = {
354 .type = REGCACHE_LZO,
355 .name = "lzo",
356 .init = regcache_lzo_init,
357 .exit = regcache_lzo_exit,
358 .read = regcache_lzo_read,
359 .write = regcache_lzo_write,
360 .sync = regcache_lzo_sync
361};
diff --git a/drivers/base/regmap/regcache-rbtree.c b/drivers/base/regmap/regcache-rbtree.c
new file mode 100644
index 000000000000..e31498499b0f
--- /dev/null
+++ b/drivers/base/regmap/regcache-rbtree.c
@@ -0,0 +1,345 @@
1/*
2 * Register cache access API - rbtree caching support
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 <linux/rbtree.h>
15
16#include "internal.h"
17
18static int regcache_rbtree_write(struct regmap *map, unsigned int reg,
19 unsigned int value);
20
21struct regcache_rbtree_node {
22 /* the actual rbtree node holding this block */
23 struct rb_node node;
24 /* base register handled by this block */
25 unsigned int base_reg;
26 /* block of adjacent registers */
27 void *block;
28 /* number of registers available in the block */
29 unsigned int blklen;
30} __attribute__ ((packed));
31
32struct regcache_rbtree_ctx {
33 struct rb_root root;
34 struct regcache_rbtree_node *cached_rbnode;
35};
36
37static inline void regcache_rbtree_get_base_top_reg(
38 struct regcache_rbtree_node *rbnode,
39 unsigned int *base, unsigned int *top)
40{
41 *base = rbnode->base_reg;
42 *top = rbnode->base_reg + rbnode->blklen - 1;
43}
44
45static unsigned int regcache_rbtree_get_register(
46 struct regcache_rbtree_node *rbnode, unsigned int idx,
47 unsigned int word_size)
48{
49 return regcache_get_val(rbnode->block, idx, word_size);
50}
51
52static void regcache_rbtree_set_register(struct regcache_rbtree_node *rbnode,
53 unsigned int idx, unsigned int val,
54 unsigned int word_size)
55{
56 regcache_set_val(rbnode->block, idx, val, word_size);
57}
58
59static struct regcache_rbtree_node *regcache_rbtree_lookup(struct regmap *map,
60 unsigned int reg)
61{
62 struct regcache_rbtree_ctx *rbtree_ctx = map->cache;
63 struct rb_node *node;
64 struct regcache_rbtree_node *rbnode;
65 unsigned int base_reg, top_reg;
66
67 rbnode = rbtree_ctx->cached_rbnode;
68 if (rbnode) {
69 regcache_rbtree_get_base_top_reg(rbnode, &base_reg, &top_reg);
70 if (reg >= base_reg && reg <= top_reg)
71 return rbnode;
72 }
73
74 node = rbtree_ctx->root.rb_node;
75 while (node) {
76 rbnode = container_of(node, struct regcache_rbtree_node, node);
77 regcache_rbtree_get_base_top_reg(rbnode, &base_reg, &top_reg);
78 if (reg >= base_reg && reg <= top_reg) {
79 rbtree_ctx->cached_rbnode = rbnode;
80 return rbnode;
81 } else if (reg > top_reg) {
82 node = node->rb_right;
83 } else if (reg < base_reg) {
84 node = node->rb_left;
85 }
86 }
87
88 return NULL;
89}
90
91static int regcache_rbtree_insert(struct rb_root *root,
92 struct regcache_rbtree_node *rbnode)
93{
94 struct rb_node **new, *parent;
95 struct regcache_rbtree_node *rbnode_tmp;
96 unsigned int base_reg_tmp, top_reg_tmp;
97 unsigned int base_reg;
98
99 parent = NULL;
100 new = &root->rb_node;
101 while (*new) {
102 rbnode_tmp = container_of(*new, struct regcache_rbtree_node,
103 node);
104 /* base and top registers of the current rbnode */
105 regcache_rbtree_get_base_top_reg(rbnode_tmp, &base_reg_tmp,
106 &top_reg_tmp);
107 /* base register of the rbnode to be added */
108 base_reg = rbnode->base_reg;
109 parent = *new;
110 /* if this register has already been inserted, just return */
111 if (base_reg >= base_reg_tmp &&
112 base_reg <= top_reg_tmp)
113 return 0;
114 else if (base_reg > top_reg_tmp)
115 new = &((*new)->rb_right);
116 else if (base_reg < base_reg_tmp)
117 new = &((*new)->rb_left);
118 }
119
120 /* insert the node into the rbtree */
121 rb_link_node(&rbnode->node, parent, new);
122 rb_insert_color(&rbnode->node, root);
123
124 return 1;
125}
126
127static int regcache_rbtree_init(struct regmap *map)
128{
129 struct regcache_rbtree_ctx *rbtree_ctx;
130 int i;
131 int ret;
132
133 map->cache = kmalloc(sizeof *rbtree_ctx, GFP_KERNEL);
134 if (!map->cache)
135 return -ENOMEM;
136
137 rbtree_ctx = map->cache;
138 rbtree_ctx->root = RB_ROOT;
139 rbtree_ctx->cached_rbnode = NULL;
140
141 for (i = 0; i < map->num_reg_defaults; i++) {
142 ret = regcache_rbtree_write(map,
143 map->reg_defaults[i].reg,
144 map->reg_defaults[i].def);
145 if (ret)
146 goto err;
147 }
148
149 return 0;
150
151err:
152 regcache_exit(map);
153 return ret;
154}
155
156static int regcache_rbtree_exit(struct regmap *map)
157{
158 struct rb_node *next;
159 struct regcache_rbtree_ctx *rbtree_ctx;
160 struct regcache_rbtree_node *rbtree_node;
161
162 /* if we've already been called then just return */
163 rbtree_ctx = map->cache;
164 if (!rbtree_ctx)
165 return 0;
166
167 /* free up the rbtree */
168 next = rb_first(&rbtree_ctx->root);
169 while (next) {
170 rbtree_node = rb_entry(next, struct regcache_rbtree_node, node);
171 next = rb_next(&rbtree_node->node);
172 rb_erase(&rbtree_node->node, &rbtree_ctx->root);
173 kfree(rbtree_node->block);
174 kfree(rbtree_node);
175 }
176
177 /* release the resources */
178 kfree(map->cache);
179 map->cache = NULL;
180
181 return 0;
182}
183
184static int regcache_rbtree_read(struct regmap *map,
185 unsigned int reg, unsigned int *value)
186{
187 struct regcache_rbtree_node *rbnode;
188 unsigned int reg_tmp;
189
190 rbnode = regcache_rbtree_lookup(map, reg);
191 if (rbnode) {
192 reg_tmp = reg - rbnode->base_reg;
193 *value = regcache_rbtree_get_register(rbnode, reg_tmp,
194 map->cache_word_size);
195 } else {
196 return -ENOENT;
197 }
198
199 return 0;
200}
201
202
203static int regcache_rbtree_insert_to_block(struct regcache_rbtree_node *rbnode,
204 unsigned int pos, unsigned int reg,
205 unsigned int value, unsigned int word_size)
206{
207 u8 *blk;
208
209 blk = krealloc(rbnode->block,
210 (rbnode->blklen + 1) * word_size, GFP_KERNEL);
211 if (!blk)
212 return -ENOMEM;
213
214 /* insert the register value in the correct place in the rbnode block */
215 memmove(blk + (pos + 1) * word_size,
216 blk + pos * word_size,
217 (rbnode->blklen - pos) * word_size);
218
219 /* update the rbnode block, its size and the base register */
220 rbnode->block = blk;
221 rbnode->blklen++;
222 if (!pos)
223 rbnode->base_reg = reg;
224
225 regcache_rbtree_set_register(rbnode, pos, value, word_size);
226 return 0;
227}
228
229static int regcache_rbtree_write(struct regmap *map, unsigned int reg,
230 unsigned int value)
231{
232 struct regcache_rbtree_ctx *rbtree_ctx;
233 struct regcache_rbtree_node *rbnode, *rbnode_tmp;
234 struct rb_node *node;
235 unsigned int val;
236 unsigned int reg_tmp;
237 unsigned int pos;
238 int i;
239 int ret;
240
241 rbtree_ctx = map->cache;
242 /* if we can't locate it in the cached rbnode we'll have
243 * to traverse the rbtree looking for it.
244 */
245 rbnode = regcache_rbtree_lookup(map, reg);
246 if (rbnode) {
247 reg_tmp = reg - rbnode->base_reg;
248 val = regcache_rbtree_get_register(rbnode, reg_tmp,
249 map->cache_word_size);
250 if (val == value)
251 return 0;
252 regcache_rbtree_set_register(rbnode, reg_tmp, value,
253 map->cache_word_size);
254 } else {
255 /* look for an adjacent register to the one we are about to add */
256 for (node = rb_first(&rbtree_ctx->root); node;
257 node = rb_next(node)) {
258 rbnode_tmp = rb_entry(node, struct regcache_rbtree_node, node);
259 for (i = 0; i < rbnode_tmp->blklen; i++) {
260 reg_tmp = rbnode_tmp->base_reg + i;
261 if (abs(reg_tmp - reg) != 1)
262 continue;
263 /* decide where in the block to place our register */
264 if (reg_tmp + 1 == reg)
265 pos = i + 1;
266 else
267 pos = i;
268 ret = regcache_rbtree_insert_to_block(rbnode_tmp, pos,
269 reg, value,
270 map->cache_word_size);
271 if (ret)
272 return ret;
273 rbtree_ctx->cached_rbnode = rbnode_tmp;
274 return 0;
275 }
276 }
277 /* we did not manage to find a place to insert it in an existing
278 * block so create a new rbnode with a single register in its block.
279 * This block will get populated further if any other adjacent
280 * registers get modified in the future.
281 */
282 rbnode = kzalloc(sizeof *rbnode, GFP_KERNEL);
283 if (!rbnode)
284 return -ENOMEM;
285 rbnode->blklen = 1;
286 rbnode->base_reg = reg;
287 rbnode->block = kmalloc(rbnode->blklen * map->cache_word_size,
288 GFP_KERNEL);
289 if (!rbnode->block) {
290 kfree(rbnode);
291 return -ENOMEM;
292 }
293 regcache_rbtree_set_register(rbnode, 0, value, map->cache_word_size);
294 regcache_rbtree_insert(&rbtree_ctx->root, rbnode);
295 rbtree_ctx->cached_rbnode = rbnode;
296 }
297
298 return 0;
299}
300
301static int regcache_rbtree_sync(struct regmap *map)
302{
303 struct regcache_rbtree_ctx *rbtree_ctx;
304 struct rb_node *node;
305 struct regcache_rbtree_node *rbnode;
306 unsigned int regtmp;
307 unsigned int val;
308 int ret;
309 int i;
310
311 rbtree_ctx = map->cache;
312 for (node = rb_first(&rbtree_ctx->root); node; node = rb_next(node)) {
313 rbnode = rb_entry(node, struct regcache_rbtree_node, node);
314 for (i = 0; i < rbnode->blklen; i++) {
315 regtmp = rbnode->base_reg + i;
316 val = regcache_rbtree_get_register(rbnode, i,
317 map->cache_word_size);
318
319 /* Is this the hardware default? If so skip. */
320 ret = regcache_lookup_reg(map, i);
321 if (ret > 0 && val == map->reg_defaults[ret].def)
322 continue;
323
324 map->cache_bypass = 1;
325 ret = _regmap_write(map, regtmp, val);
326 map->cache_bypass = 0;
327 if (ret)
328 return ret;
329 dev_dbg(map->dev, "Synced register %#x, value %#x\n",
330 regtmp, val);
331 }
332 }
333
334 return 0;
335}
336
337struct regcache_ops regcache_rbtree_ops = {
338 .type = REGCACHE_RBTREE,
339 .name = "rbtree",
340 .init = regcache_rbtree_init,
341 .exit = regcache_rbtree_exit,
342 .read = regcache_rbtree_read,
343 .write = regcache_rbtree_write,
344 .sync = regcache_rbtree_sync
345};
diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c
new file mode 100644
index 000000000000..afcfef838263
--- /dev/null
+++ b/drivers/base/regmap/regcache.c
@@ -0,0 +1,401 @@
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#include <linux/bsearch.h>
16#include <linux/sort.h>
17
18#include "internal.h"
19
20static const struct regcache_ops *cache_types[] = {
21 &regcache_indexed_ops,
22 &regcache_rbtree_ops,
23 &regcache_lzo_ops,
24};
25
26static int regcache_hw_init(struct regmap *map)
27{
28 int i, j;
29 int ret;
30 int count;
31 unsigned int val;
32 void *tmp_buf;
33
34 if (!map->num_reg_defaults_raw)
35 return -EINVAL;
36
37 if (!map->reg_defaults_raw) {
38 dev_warn(map->dev, "No cache defaults, reading back from HW\n");
39 tmp_buf = kmalloc(map->cache_size_raw, GFP_KERNEL);
40 if (!tmp_buf)
41 return -EINVAL;
42 ret = regmap_bulk_read(map, 0, tmp_buf,
43 map->num_reg_defaults_raw);
44 if (ret < 0) {
45 kfree(tmp_buf);
46 return ret;
47 }
48 map->reg_defaults_raw = tmp_buf;
49 map->cache_free = 1;
50 }
51
52 /* calculate the size of reg_defaults */
53 for (count = 0, i = 0; i < map->num_reg_defaults_raw; i++) {
54 val = regcache_get_val(map->reg_defaults_raw,
55 i, map->cache_word_size);
56 if (!val)
57 continue;
58 count++;
59 }
60
61 map->reg_defaults = kmalloc(count * sizeof(struct reg_default),
62 GFP_KERNEL);
63 if (!map->reg_defaults)
64 return -ENOMEM;
65
66 /* fill the reg_defaults */
67 map->num_reg_defaults = count;
68 for (i = 0, j = 0; i < map->num_reg_defaults_raw; i++) {
69 val = regcache_get_val(map->reg_defaults_raw,
70 i, map->cache_word_size);
71 if (!val)
72 continue;
73 map->reg_defaults[j].reg = i;
74 map->reg_defaults[j].def = val;
75 j++;
76 }
77
78 return 0;
79}
80
81int regcache_init(struct regmap *map)
82{
83 int ret;
84 int i;
85 void *tmp_buf;
86
87 if (map->cache_type == REGCACHE_NONE) {
88 map->cache_bypass = true;
89 return 0;
90 }
91
92 for (i = 0; i < ARRAY_SIZE(cache_types); i++)
93 if (cache_types[i]->type == map->cache_type)
94 break;
95
96 if (i == ARRAY_SIZE(cache_types)) {
97 dev_err(map->dev, "Could not match compress type: %d\n",
98 map->cache_type);
99 return -EINVAL;
100 }
101
102 map->cache = NULL;
103 map->cache_ops = cache_types[i];
104
105 if (!map->cache_ops->read ||
106 !map->cache_ops->write ||
107 !map->cache_ops->name)
108 return -EINVAL;
109
110 /* We still need to ensure that the reg_defaults
111 * won't vanish from under us. We'll need to make
112 * a copy of it.
113 */
114 if (map->reg_defaults) {
115 if (!map->num_reg_defaults)
116 return -EINVAL;
117 tmp_buf = kmemdup(map->reg_defaults, map->num_reg_defaults *
118 sizeof(struct reg_default), GFP_KERNEL);
119 if (!tmp_buf)
120 return -ENOMEM;
121 map->reg_defaults = tmp_buf;
122 } else if (map->num_reg_defaults_raw) {
123 /* Some devices such as PMICs don't have cache defaults,
124 * we cope with this by reading back the HW registers and
125 * crafting the cache defaults by hand.
126 */
127 ret = regcache_hw_init(map);
128 if (ret < 0)
129 return ret;
130 }
131
132 if (!map->max_register)
133 map->max_register = map->num_reg_defaults_raw;
134
135 if (map->cache_ops->init) {
136 dev_dbg(map->dev, "Initializing %s cache\n",
137 map->cache_ops->name);
138 return map->cache_ops->init(map);
139 }
140 return 0;
141}
142
143void regcache_exit(struct regmap *map)
144{
145 if (map->cache_type == REGCACHE_NONE)
146 return;
147
148 BUG_ON(!map->cache_ops);
149
150 kfree(map->reg_defaults);
151 if (map->cache_free)
152 kfree(map->reg_defaults_raw);
153
154 if (map->cache_ops->exit) {
155 dev_dbg(map->dev, "Destroying %s cache\n",
156 map->cache_ops->name);
157 map->cache_ops->exit(map);
158 }
159}
160
161/**
162 * regcache_read: Fetch the value of a given register from the cache.
163 *
164 * @map: map to configure.
165 * @reg: The register index.
166 * @value: The value to be returned.
167 *
168 * Return a negative value on failure, 0 on success.
169 */
170int regcache_read(struct regmap *map,
171 unsigned int reg, unsigned int *value)
172{
173 if (map->cache_type == REGCACHE_NONE)
174 return -ENOSYS;
175
176 BUG_ON(!map->cache_ops);
177
178 if (!regmap_readable(map, reg))
179 return -EIO;
180
181 if (!regmap_volatile(map, reg))
182 return map->cache_ops->read(map, reg, value);
183
184 return -EINVAL;
185}
186EXPORT_SYMBOL_GPL(regcache_read);
187
188/**
189 * regcache_write: Set the value of a given register in the cache.
190 *
191 * @map: map to configure.
192 * @reg: The register index.
193 * @value: The new register value.
194 *
195 * Return a negative value on failure, 0 on success.
196 */
197int regcache_write(struct regmap *map,
198 unsigned int reg, unsigned int value)
199{
200 if (map->cache_type == REGCACHE_NONE)
201 return 0;
202
203 BUG_ON(!map->cache_ops);
204
205 if (!regmap_writeable(map, reg))
206 return -EIO;
207
208 if (!regmap_volatile(map, reg))
209 return map->cache_ops->write(map, reg, value);
210
211 return 0;
212}
213EXPORT_SYMBOL_GPL(regcache_write);
214
215/**
216 * regcache_sync: Sync the register cache with the hardware.
217 *
218 * @map: map to configure.
219 *
220 * Any registers that should not be synced should be marked as
221 * volatile. In general drivers can choose not to use the provided
222 * syncing functionality if they so require.
223 *
224 * Return a negative value on failure, 0 on success.
225 */
226int regcache_sync(struct regmap *map)
227{
228 int ret = 0;
229 unsigned int val;
230 unsigned int i;
231 const char *name;
232 unsigned int bypass;
233
234 BUG_ON(!map->cache_ops);
235
236 mutex_lock(&map->lock);
237 /* Remember the initial bypass state */
238 bypass = map->cache_bypass;
239 dev_dbg(map->dev, "Syncing %s cache\n",
240 map->cache_ops->name);
241 name = map->cache_ops->name;
242 trace_regcache_sync(map->dev, name, "start");
243 if (map->cache_ops->sync) {
244 ret = map->cache_ops->sync(map);
245 } else {
246 for (i = 0; i < map->num_reg_defaults; i++) {
247 ret = regcache_read(map, i, &val);
248 if (ret < 0)
249 goto out;
250 map->cache_bypass = 1;
251 ret = _regmap_write(map, i, val);
252 map->cache_bypass = 0;
253 if (ret < 0)
254 goto out;
255 dev_dbg(map->dev, "Synced register %#x, value %#x\n",
256 map->reg_defaults[i].reg,
257 map->reg_defaults[i].def);
258 }
259
260 }
261out:
262 trace_regcache_sync(map->dev, name, "stop");
263 /* Restore the bypass state */
264 map->cache_bypass = bypass;
265 mutex_unlock(&map->lock);
266
267 return ret;
268}
269EXPORT_SYMBOL_GPL(regcache_sync);
270
271/**
272 * regcache_cache_only: Put a register map into cache only mode
273 *
274 * @map: map to configure
275 * @cache_only: flag if changes should be written to the hardware
276 *
277 * When a register map is marked as cache only writes to the register
278 * map API will only update the register cache, they will not cause
279 * any hardware changes. This is useful for allowing portions of
280 * drivers to act as though the device were functioning as normal when
281 * it is disabled for power saving reasons.
282 */
283void regcache_cache_only(struct regmap *map, bool enable)
284{
285 mutex_lock(&map->lock);
286 WARN_ON(map->cache_bypass && enable);
287 map->cache_only = enable;
288 mutex_unlock(&map->lock);
289}
290EXPORT_SYMBOL_GPL(regcache_cache_only);
291
292/**
293 * regcache_cache_bypass: Put a register map into cache bypass mode
294 *
295 * @map: map to configure
296 * @cache_bypass: flag if changes should not be written to the hardware
297 *
298 * When a register map is marked with the cache bypass option, writes
299 * to the register map API will only update the hardware and not the
300 * the cache directly. This is useful when syncing the cache back to
301 * the hardware.
302 */
303void regcache_cache_bypass(struct regmap *map, bool enable)
304{
305 mutex_lock(&map->lock);
306 WARN_ON(map->cache_only && enable);
307 map->cache_bypass = enable;
308 mutex_unlock(&map->lock);
309}
310EXPORT_SYMBOL_GPL(regcache_cache_bypass);
311
312bool regcache_set_val(void *base, unsigned int idx,
313 unsigned int val, unsigned int word_size)
314{
315 switch (word_size) {
316 case 1: {
317 u8 *cache = base;
318 if (cache[idx] == val)
319 return true;
320 cache[idx] = val;
321 break;
322 }
323 case 2: {
324 u16 *cache = base;
325 if (cache[idx] == val)
326 return true;
327 cache[idx] = val;
328 break;
329 }
330 default:
331 BUG();
332 }
333 /* unreachable */
334 return false;
335}
336
337unsigned int regcache_get_val(const void *base, unsigned int idx,
338 unsigned int word_size)
339{
340 if (!base)
341 return -EINVAL;
342
343 switch (word_size) {
344 case 1: {
345 const u8 *cache = base;
346 return cache[idx];
347 }
348 case 2: {
349 const u16 *cache = base;
350 return cache[idx];
351 }
352 default:
353 BUG();
354 }
355 /* unreachable */
356 return -1;
357}
358
359static int regcache_default_cmp(const void *a, const void *b)
360{
361 const struct reg_default *_a = a;
362 const struct reg_default *_b = b;
363
364 return _a->reg - _b->reg;
365}
366
367int regcache_lookup_reg(struct regmap *map, unsigned int reg)
368{
369 struct reg_default key;
370 struct reg_default *r;
371
372 key.reg = reg;
373 key.def = 0;
374
375 r = bsearch(&key, map->reg_defaults, map->num_reg_defaults,
376 sizeof(struct reg_default), regcache_default_cmp);
377
378 if (r)
379 return r - map->reg_defaults;
380 else
381 return -ENOENT;
382}
383
384int 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;
398 sort(map->reg_defaults, map->num_reg_defaults,
399 sizeof(struct reg_default), regcache_default_cmp, NULL);
400 return 0;
401}
diff --git a/drivers/base/regmap/regmap-debugfs.c b/drivers/base/regmap/regmap-debugfs.c
new file mode 100644
index 000000000000..6f397476e27c
--- /dev/null
+++ b/drivers/base/regmap/regmap-debugfs.c
@@ -0,0 +1,209 @@
1/*
2 * Register map access API - debugfs
3 *
4 * Copyright 2011 Wolfson Microelectronics plc
5 *
6 * Author: Mark Brown <broonie@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 <linux/module.h>
15#include <linux/mutex.h>
16#include <linux/debugfs.h>
17#include <linux/uaccess.h>
18
19#include "internal.h"
20
21static struct dentry *regmap_debugfs_root;
22
23/* Calculate the length of a fixed format */
24static size_t regmap_calc_reg_len(int max_val, char *buf, size_t buf_size)
25{
26 snprintf(buf, buf_size, "%x", max_val);
27 return strlen(buf);
28}
29
30static int regmap_open_file(struct inode *inode, struct file *file)
31{
32 file->private_data = inode->i_private;
33 return 0;
34}
35
36static ssize_t regmap_map_read_file(struct file *file, char __user *user_buf,
37 size_t count, loff_t *ppos)
38{
39 int reg_len, val_len, tot_len;
40 size_t buf_pos = 0;
41 loff_t p = 0;
42 ssize_t ret;
43 int i;
44 struct regmap *map = file->private_data;
45 char *buf;
46 unsigned int val;
47
48 if (*ppos < 0 || !count)
49 return -EINVAL;
50
51 buf = kmalloc(count, GFP_KERNEL);
52 if (!buf)
53 return -ENOMEM;
54
55 /* Calculate the length of a fixed format */
56 reg_len = regmap_calc_reg_len(map->max_register, buf, count);
57 val_len = 2 * map->format.val_bytes;
58 tot_len = reg_len + val_len + 3; /* : \n */
59
60 for (i = 0; i < map->max_register + 1; i++) {
61 if (!regmap_readable(map, i))
62 continue;
63
64 if (regmap_precious(map, i))
65 continue;
66
67 /* If we're in the region the user is trying to read */
68 if (p >= *ppos) {
69 /* ...but not beyond it */
70 if (buf_pos >= count - 1 - tot_len)
71 break;
72
73 /* Format the register */
74 snprintf(buf + buf_pos, count - buf_pos, "%.*x: ",
75 reg_len, i);
76 buf_pos += reg_len + 2;
77
78 /* Format the value, write all X if we can't read */
79 ret = regmap_read(map, i, &val);
80 if (ret == 0)
81 snprintf(buf + buf_pos, count - buf_pos,
82 "%.*x", val_len, val);
83 else
84 memset(buf + buf_pos, 'X', val_len);
85 buf_pos += 2 * map->format.val_bytes;
86
87 buf[buf_pos++] = '\n';
88 }
89 p += tot_len;
90 }
91
92 ret = buf_pos;
93
94 if (copy_to_user(user_buf, buf, buf_pos)) {
95 ret = -EFAULT;
96 goto out;
97 }
98
99 *ppos += buf_pos;
100
101out:
102 kfree(buf);
103 return ret;
104}
105
106static const struct file_operations regmap_map_fops = {
107 .open = regmap_open_file,
108 .read = regmap_map_read_file,
109 .llseek = default_llseek,
110};
111
112static ssize_t regmap_access_read_file(struct file *file,
113 char __user *user_buf, size_t count,
114 loff_t *ppos)
115{
116 int reg_len, tot_len;
117 size_t buf_pos = 0;
118 loff_t p = 0;
119 ssize_t ret;
120 int i;
121 struct regmap *map = file->private_data;
122 char *buf;
123
124 if (*ppos < 0 || !count)
125 return -EINVAL;
126
127 buf = kmalloc(count, GFP_KERNEL);
128 if (!buf)
129 return -ENOMEM;
130
131 /* Calculate the length of a fixed format */
132 reg_len = regmap_calc_reg_len(map->max_register, buf, count);
133 tot_len = reg_len + 10; /* ': R W V P\n' */
134
135 for (i = 0; i < map->max_register + 1; i++) {
136 /* Ignore registers which are neither readable nor writable */
137 if (!regmap_readable(map, i) && !regmap_writeable(map, i))
138 continue;
139
140 /* If we're in the region the user is trying to read */
141 if (p >= *ppos) {
142 /* ...but not beyond it */
143 if (buf_pos >= count - 1 - tot_len)
144 break;
145
146 /* Format the register */
147 snprintf(buf + buf_pos, count - buf_pos,
148 "%.*x: %c %c %c %c\n",
149 reg_len, i,
150 regmap_readable(map, i) ? 'y' : 'n',
151 regmap_writeable(map, i) ? 'y' : 'n',
152 regmap_volatile(map, i) ? 'y' : 'n',
153 regmap_precious(map, i) ? 'y' : 'n');
154
155 buf_pos += tot_len;
156 }
157 p += tot_len;
158 }
159
160 ret = buf_pos;
161
162 if (copy_to_user(user_buf, buf, buf_pos)) {
163 ret = -EFAULT;
164 goto out;
165 }
166
167 *ppos += buf_pos;
168
169out:
170 kfree(buf);
171 return ret;
172}
173
174static const struct file_operations regmap_access_fops = {
175 .open = regmap_open_file,
176 .read = regmap_access_read_file,
177 .llseek = default_llseek,
178};
179
180void regmap_debugfs_init(struct regmap *map)
181{
182 map->debugfs = debugfs_create_dir(dev_name(map->dev),
183 regmap_debugfs_root);
184 if (!map->debugfs) {
185 dev_warn(map->dev, "Failed to create debugfs directory\n");
186 return;
187 }
188
189 if (map->max_register) {
190 debugfs_create_file("registers", 0400, map->debugfs,
191 map, &regmap_map_fops);
192 debugfs_create_file("access", 0400, map->debugfs,
193 map, &regmap_access_fops);
194 }
195}
196
197void regmap_debugfs_exit(struct regmap *map)
198{
199 debugfs_remove_recursive(map->debugfs);
200}
201
202void regmap_debugfs_initcall(void)
203{
204 regmap_debugfs_root = debugfs_create_dir("regmap", NULL);
205 if (!regmap_debugfs_root) {
206 pr_warn("regmap: Failed to create debugfs root\n");
207 return;
208 }
209}
diff --git a/drivers/base/regmap/regmap-i2c.c b/drivers/base/regmap/regmap-i2c.c
index c4f7a45cd2c3..38621ec87c05 100644
--- a/drivers/base/regmap/regmap-i2c.c
+++ b/drivers/base/regmap/regmap-i2c.c
@@ -90,11 +90,9 @@ static int regmap_i2c_read(struct device *dev,
90} 90}
91 91
92static struct regmap_bus regmap_i2c = { 92static struct regmap_bus regmap_i2c = {
93 .type = &i2c_bus_type,
94 .write = regmap_i2c_write, 93 .write = regmap_i2c_write,
95 .gather_write = regmap_i2c_gather_write, 94 .gather_write = regmap_i2c_gather_write,
96 .read = regmap_i2c_read, 95 .read = regmap_i2c_read,
97 .owner = THIS_MODULE,
98}; 96};
99 97
100/** 98/**
diff --git a/drivers/base/regmap/regmap-spi.c b/drivers/base/regmap/regmap-spi.c
index f8396945d6ed..2560658de344 100644
--- a/drivers/base/regmap/regmap-spi.c
+++ b/drivers/base/regmap/regmap-spi.c
@@ -48,11 +48,9 @@ static int regmap_spi_read(struct device *dev,
48} 48}
49 49
50static struct regmap_bus regmap_spi = { 50static struct regmap_bus regmap_spi = {
51 .type = &spi_bus_type,
52 .write = regmap_spi_write, 51 .write = regmap_spi_write,
53 .gather_write = regmap_spi_gather_write, 52 .gather_write = regmap_spi_gather_write,
54 .read = regmap_spi_read, 53 .read = regmap_spi_read,
55 .owner = THIS_MODULE,
56 .read_flag_mask = 0x80, 54 .read_flag_mask = 0x80,
57}; 55};
58 56
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index 20663f8dae45..bf441db1ee90 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -15,29 +15,54 @@
15#include <linux/mutex.h> 15#include <linux/mutex.h>
16#include <linux/err.h> 16#include <linux/err.h>
17 17
18#include <linux/regmap.h> 18#define CREATE_TRACE_POINTS
19 19#include <trace/events/regmap.h>
20struct regmap; 20
21 21#include "internal.h"
22struct regmap_format { 22
23 size_t buf_size; 23bool regmap_writeable(struct regmap *map, unsigned int reg)
24 size_t reg_bytes; 24{
25 size_t val_bytes; 25 if (map->max_register && reg > map->max_register)
26 void (*format_write)(struct regmap *map, 26 return false;
27 unsigned int reg, unsigned int val); 27
28 void (*format_reg)(void *buf, unsigned int reg); 28 if (map->writeable_reg)
29 void (*format_val)(void *buf, unsigned int val); 29 return map->writeable_reg(map->dev, reg);
30 unsigned int (*parse_val)(void *buf); 30
31}; 31 return true;
32 32}
33struct regmap { 33
34 struct mutex lock; 34bool regmap_readable(struct regmap *map, unsigned int reg)
35 35{
36 struct device *dev; /* Device we do I/O on */ 36 if (map->max_register && reg > map->max_register)
37 void *work_buf; /* Scratch buffer used to format I/O */ 37 return false;
38 struct regmap_format format; /* Buffer format */ 38
39 const struct regmap_bus *bus; 39 if (map->readable_reg)
40}; 40 return map->readable_reg(map->dev, reg);
41
42 return true;
43}
44
45bool regmap_volatile(struct regmap *map, unsigned int reg)
46{
47 if (map->max_register && reg > map->max_register)
48 return false;
49
50 if (map->volatile_reg)
51 return map->volatile_reg(map->dev, reg);
52
53 return true;
54}
55
56bool regmap_precious(struct regmap *map, unsigned int reg)
57{
58 if (map->max_register && reg > map->max_register)
59 return false;
60
61 if (map->precious_reg)
62 return map->precious_reg(map->dev, reg);
63
64 return false;
65}
41 66
42static void regmap_format_4_12_write(struct regmap *map, 67static void regmap_format_4_12_write(struct regmap *map,
43 unsigned int reg, unsigned int val) 68 unsigned int reg, unsigned int val)
@@ -116,6 +141,25 @@ struct regmap *regmap_init(struct device *dev,
116 map->format.val_bytes = config->val_bits / 8; 141 map->format.val_bytes = config->val_bits / 8;
117 map->dev = dev; 142 map->dev = dev;
118 map->bus = bus; 143 map->bus = bus;
144 map->max_register = config->max_register;
145 map->writeable_reg = config->writeable_reg;
146 map->readable_reg = config->readable_reg;
147 map->volatile_reg = config->volatile_reg;
148 map->precious_reg = config->precious_reg;
149 map->cache_type = config->cache_type;
150 map->reg_defaults = config->reg_defaults;
151 map->num_reg_defaults = config->num_reg_defaults;
152 map->num_reg_defaults_raw = config->num_reg_defaults_raw;
153 map->reg_defaults_raw = config->reg_defaults_raw;
154 map->cache_size_raw = (config->val_bits / 8) * config->num_reg_defaults_raw;
155 map->cache_word_size = config->val_bits / 8;
156
157 if (config->read_flag_mask || config->write_flag_mask) {
158 map->read_flag_mask = config->read_flag_mask;
159 map->write_flag_mask = config->write_flag_mask;
160 } else {
161 map->read_flag_mask = bus->read_flag_mask;
162 }
119 163
120 switch (config->reg_bits) { 164 switch (config->reg_bits) {
121 case 4: 165 case 4:
@@ -171,6 +215,12 @@ struct regmap *regmap_init(struct device *dev,
171 goto err_map; 215 goto err_map;
172 } 216 }
173 217
218 ret = regcache_init(map);
219 if (ret < 0)
220 goto err_map;
221
222 regmap_debugfs_init(map);
223
174 return map; 224 return map;
175 225
176err_map: 226err_map:
@@ -185,6 +235,8 @@ EXPORT_SYMBOL_GPL(regmap_init);
185 */ 235 */
186void regmap_exit(struct regmap *map) 236void regmap_exit(struct regmap *map)
187{ 237{
238 regcache_exit(map);
239 regmap_debugfs_exit(map);
188 kfree(map->work_buf); 240 kfree(map->work_buf);
189 kfree(map); 241 kfree(map);
190} 242}
@@ -193,19 +245,38 @@ EXPORT_SYMBOL_GPL(regmap_exit);
193static int _regmap_raw_write(struct regmap *map, unsigned int reg, 245static int _regmap_raw_write(struct regmap *map, unsigned int reg,
194 const void *val, size_t val_len) 246 const void *val, size_t val_len)
195{ 247{
248 u8 *u8 = map->work_buf;
196 void *buf; 249 void *buf;
197 int ret = -ENOTSUPP; 250 int ret = -ENOTSUPP;
198 size_t len; 251 size_t len;
252 int i;
253
254 /* Check for unwritable registers before we start */
255 if (map->writeable_reg)
256 for (i = 0; i < val_len / map->format.val_bytes; i++)
257 if (!map->writeable_reg(map->dev, reg + i))
258 return -EINVAL;
199 259
200 map->format.format_reg(map->work_buf, reg); 260 map->format.format_reg(map->work_buf, reg);
201 261
202 /* Try to do a gather write if we can */ 262 u8[0] |= map->write_flag_mask;
203 if (map->bus->gather_write) 263
264 trace_regmap_hw_write_start(map->dev, reg,
265 val_len / map->format.val_bytes);
266
267 /* If we're doing a single register write we can probably just
268 * send the work_buf directly, otherwise try to do a gather
269 * write.
270 */
271 if (val == map->work_buf + map->format.reg_bytes)
272 ret = map->bus->write(map->dev, map->work_buf,
273 map->format.reg_bytes + val_len);
274 else if (map->bus->gather_write)
204 ret = map->bus->gather_write(map->dev, map->work_buf, 275 ret = map->bus->gather_write(map->dev, map->work_buf,
205 map->format.reg_bytes, 276 map->format.reg_bytes,
206 val, val_len); 277 val, val_len);
207 278
208 /* Otherwise fall back on linearising by hand. */ 279 /* If that didn't work fall back on linearising by hand. */
209 if (ret == -ENOTSUPP) { 280 if (ret == -ENOTSUPP) {
210 len = map->format.reg_bytes + val_len; 281 len = map->format.reg_bytes + val_len;
211 buf = kmalloc(len, GFP_KERNEL); 282 buf = kmalloc(len, GFP_KERNEL);
@@ -219,19 +290,39 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg,
219 kfree(buf); 290 kfree(buf);
220 } 291 }
221 292
293 trace_regmap_hw_write_done(map->dev, reg,
294 val_len / map->format.val_bytes);
295
222 return ret; 296 return ret;
223} 297}
224 298
225static int _regmap_write(struct regmap *map, unsigned int reg, 299int _regmap_write(struct regmap *map, unsigned int reg,
226 unsigned int val) 300 unsigned int val)
227{ 301{
302 int ret;
228 BUG_ON(!map->format.format_write && !map->format.format_val); 303 BUG_ON(!map->format.format_write && !map->format.format_val);
229 304
305 if (!map->cache_bypass) {
306 ret = regcache_write(map, reg, val);
307 if (ret != 0)
308 return ret;
309 if (map->cache_only)
310 return 0;
311 }
312
313 trace_regmap_reg_write(map->dev, reg, val);
314
230 if (map->format.format_write) { 315 if (map->format.format_write) {
231 map->format.format_write(map, reg, val); 316 map->format.format_write(map, reg, val);
232 317
233 return map->bus->write(map->dev, map->work_buf, 318 trace_regmap_hw_write_start(map->dev, reg, 1);
234 map->format.buf_size); 319
320 ret = map->bus->write(map->dev, map->work_buf,
321 map->format.buf_size);
322
323 trace_regmap_hw_write_done(map->dev, reg, 1);
324
325 return ret;
235 } else { 326 } else {
236 map->format.format_val(map->work_buf + map->format.reg_bytes, 327 map->format.format_val(map->work_buf + map->format.reg_bytes,
237 val); 328 val);
@@ -286,6 +377,8 @@ int regmap_raw_write(struct regmap *map, unsigned int reg,
286{ 377{
287 int ret; 378 int ret;
288 379
380 WARN_ON(map->cache_type != REGCACHE_NONE);
381
289 mutex_lock(&map->lock); 382 mutex_lock(&map->lock);
290 383
291 ret = _regmap_raw_write(map, reg, val, val_len); 384 ret = _regmap_raw_write(map, reg, val, val_len);
@@ -305,20 +398,23 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
305 map->format.format_reg(map->work_buf, reg); 398 map->format.format_reg(map->work_buf, reg);
306 399
307 /* 400 /*
308 * Some buses flag reads by setting the high bits in the 401 * Some buses or devices flag reads by setting the high bits in the
309 * register addresss; since it's always the high bits for all 402 * register addresss; since it's always the high bits for all
310 * current formats we can do this here rather than in 403 * current formats we can do this here rather than in
311 * formatting. This may break if we get interesting formats. 404 * formatting. This may break if we get interesting formats.
312 */ 405 */
313 if (map->bus->read_flag_mask) 406 u8[0] |= map->read_flag_mask;
314 u8[0] |= map->bus->read_flag_mask; 407
408 trace_regmap_hw_read_start(map->dev, reg,
409 val_len / map->format.val_bytes);
315 410
316 ret = map->bus->read(map->dev, map->work_buf, map->format.reg_bytes, 411 ret = map->bus->read(map->dev, map->work_buf, map->format.reg_bytes,
317 val, val_len); 412 val, val_len);
318 if (ret != 0)
319 return ret;
320 413
321 return 0; 414 trace_regmap_hw_read_done(map->dev, reg,
415 val_len / map->format.val_bytes);
416
417 return ret;
322} 418}
323 419
324static int _regmap_read(struct regmap *map, unsigned int reg, 420static int _regmap_read(struct regmap *map, unsigned int reg,
@@ -329,9 +425,20 @@ static int _regmap_read(struct regmap *map, unsigned int reg,
329 if (!map->format.parse_val) 425 if (!map->format.parse_val)
330 return -EINVAL; 426 return -EINVAL;
331 427
428 if (!map->cache_bypass) {
429 ret = regcache_read(map, reg, val);
430 if (ret == 0)
431 return 0;
432 }
433
434 if (map->cache_only)
435 return -EBUSY;
436
332 ret = _regmap_raw_read(map, reg, map->work_buf, map->format.val_bytes); 437 ret = _regmap_raw_read(map, reg, map->work_buf, map->format.val_bytes);
333 if (ret == 0) 438 if (ret == 0) {
334 *val = map->format.parse_val(map->work_buf); 439 *val = map->format.parse_val(map->work_buf);
440 trace_regmap_reg_read(map->dev, reg, *val);
441 }
335 442
336 return ret; 443 return ret;
337} 444}
@@ -375,6 +482,14 @@ int regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
375 size_t val_len) 482 size_t val_len)
376{ 483{
377 int ret; 484 int ret;
485 int i;
486 bool vol = true;
487
488 for (i = 0; i < val_len / map->format.val_bytes; i++)
489 if (!regmap_volatile(map, reg + i))
490 vol = false;
491
492 WARN_ON(!vol && map->cache_type != REGCACHE_NONE);
378 493
379 mutex_lock(&map->lock); 494 mutex_lock(&map->lock);
380 495
@@ -402,16 +517,30 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
402{ 517{
403 int ret, i; 518 int ret, i;
404 size_t val_bytes = map->format.val_bytes; 519 size_t val_bytes = map->format.val_bytes;
520 bool vol = true;
405 521
406 if (!map->format.parse_val) 522 if (!map->format.parse_val)
407 return -EINVAL; 523 return -EINVAL;
408 524
409 ret = regmap_raw_read(map, reg, val, val_bytes * val_count); 525 /* Is this a block of volatile registers? */
410 if (ret != 0) 526 for (i = 0; i < val_count; i++)
411 return ret; 527 if (!regmap_volatile(map, reg + i))
528 vol = false;
529
530 if (vol || map->cache_type == REGCACHE_NONE) {
531 ret = regmap_raw_read(map, reg, val, val_bytes * val_count);
532 if (ret != 0)
533 return ret;
412 534
413 for (i = 0; i < val_count * val_bytes; i += val_bytes) 535 for (i = 0; i < val_count * val_bytes; i += val_bytes)
414 map->format.parse_val(val + i); 536 map->format.parse_val(val + i);
537 } else {
538 for (i = 0; i < val_count; i++) {
539 ret = regmap_read(map, reg + i, val + (i * val_bytes));
540 if (ret != 0)
541 return ret;
542 }
543 }
415 544
416 return 0; 545 return 0;
417} 546}
@@ -450,3 +579,11 @@ out:
450 return ret; 579 return ret;
451} 580}
452EXPORT_SYMBOL_GPL(regmap_update_bits); 581EXPORT_SYMBOL_GPL(regmap_update_bits);
582
583static int __init regmap_initcall(void)
584{
585 regmap_debugfs_initcall();
586
587 return 0;
588}
589postcore_initcall(regmap_initcall);