aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/base')
-rw-r--r--drivers/base/regmap/Makefile3
-rw-r--r--drivers/base/regmap/internal.h6
-rw-r--r--drivers/base/regmap/regcache-indexed.c64
-rw-r--r--drivers/base/regmap/regcache-lzo.c21
-rw-r--r--drivers/base/regmap/regcache-rbtree.c61
-rw-r--r--drivers/base/regmap/regcache.c87
-rw-r--r--drivers/base/regmap/regmap.c179
7 files changed, 268 insertions, 153 deletions
diff --git a/drivers/base/regmap/Makefile b/drivers/base/regmap/Makefile
index ce2d18a6465b..defd57963c84 100644
--- a/drivers/base/regmap/Makefile
+++ b/drivers/base/regmap/Makefile
@@ -1,4 +1,5 @@
1obj-$(CONFIG_REGMAP) += regmap.o regcache.o regcache-indexed.o regcache-rbtree.o regcache-lzo.o 1obj-$(CONFIG_REGMAP) += regmap.o regcache.o
2obj-$(CONFIG_REGMAP) += regcache-rbtree.o regcache-lzo.o
2obj-$(CONFIG_DEBUG_FS) += regmap-debugfs.o 3obj-$(CONFIG_DEBUG_FS) += regmap-debugfs.o
3obj-$(CONFIG_REGMAP_I2C) += regmap-i2c.o 4obj-$(CONFIG_REGMAP_I2C) += regmap-i2c.o
4obj-$(CONFIG_REGMAP_SPI) += regmap-spi.o 5obj-$(CONFIG_REGMAP_SPI) += regmap-spi.o
diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h
index 348ff02eb93e..1a02b7537c8b 100644
--- a/drivers/base/regmap/internal.h
+++ b/drivers/base/regmap/internal.h
@@ -74,6 +74,7 @@ struct regmap {
74 struct reg_default *reg_defaults; 74 struct reg_default *reg_defaults;
75 const void *reg_defaults_raw; 75 const void *reg_defaults_raw;
76 void *cache; 76 void *cache;
77 bool cache_dirty;
77}; 78};
78 79
79struct regcache_ops { 80struct regcache_ops {
@@ -105,7 +106,7 @@ static inline void regmap_debugfs_exit(struct regmap *map) { }
105#endif 106#endif
106 107
107/* regcache core declarations */ 108/* regcache core declarations */
108int regcache_init(struct regmap *map); 109int regcache_init(struct regmap *map, const struct regmap_config *config);
109void regcache_exit(struct regmap *map); 110void regcache_exit(struct regmap *map);
110int regcache_read(struct regmap *map, 111int regcache_read(struct regmap *map,
111 unsigned int reg, unsigned int *value); 112 unsigned int reg, unsigned int *value);
@@ -118,10 +119,7 @@ unsigned int regcache_get_val(const void *base, unsigned int idx,
118bool regcache_set_val(void *base, unsigned int idx, 119bool regcache_set_val(void *base, unsigned int idx,
119 unsigned int val, unsigned int word_size); 120 unsigned int val, unsigned int word_size);
120int regcache_lookup_reg(struct regmap *map, unsigned int reg); 121int regcache_lookup_reg(struct regmap *map, unsigned int reg);
121int regcache_insert_reg(struct regmap *map, unsigned int reg,
122 unsigned int val);
123 122
124extern struct regcache_ops regcache_indexed_ops;
125extern struct regcache_ops regcache_rbtree_ops; 123extern struct regcache_ops regcache_rbtree_ops;
126extern struct regcache_ops regcache_lzo_ops; 124extern struct regcache_ops regcache_lzo_ops;
127 125
diff --git a/drivers/base/regmap/regcache-indexed.c b/drivers/base/regmap/regcache-indexed.c
deleted file mode 100644
index 507731ad8ec1..000000000000
--- a/drivers/base/regmap/regcache-indexed.c
+++ /dev/null
@@ -1,64 +0,0 @@
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
index 066aeece3626..b7d16143edeb 100644
--- a/drivers/base/regmap/regcache-lzo.c
+++ b/drivers/base/regmap/regcache-lzo.c
@@ -15,6 +15,8 @@
15 15
16#include "internal.h" 16#include "internal.h"
17 17
18static int regcache_lzo_exit(struct regmap *map);
19
18struct regcache_lzo_ctx { 20struct regcache_lzo_ctx {
19 void *wmem; 21 void *wmem;
20 void *dst; 22 void *dst;
@@ -27,7 +29,7 @@ struct regcache_lzo_ctx {
27}; 29};
28 30
29#define LZO_BLOCK_NUM 8 31#define LZO_BLOCK_NUM 8
30static int regcache_lzo_block_count(void) 32static int regcache_lzo_block_count(struct regmap *map)
31{ 33{
32 return LZO_BLOCK_NUM; 34 return LZO_BLOCK_NUM;
33} 35}
@@ -106,19 +108,22 @@ static inline int regcache_lzo_get_blkindex(struct regmap *map,
106 unsigned int reg) 108 unsigned int reg)
107{ 109{
108 return (reg * map->cache_word_size) / 110 return (reg * map->cache_word_size) /
109 DIV_ROUND_UP(map->cache_size_raw, regcache_lzo_block_count()); 111 DIV_ROUND_UP(map->cache_size_raw,
112 regcache_lzo_block_count(map));
110} 113}
111 114
112static inline int regcache_lzo_get_blkpos(struct regmap *map, 115static inline int regcache_lzo_get_blkpos(struct regmap *map,
113 unsigned int reg) 116 unsigned int reg)
114{ 117{
115 return reg % (DIV_ROUND_UP(map->cache_size_raw, regcache_lzo_block_count()) / 118 return reg % (DIV_ROUND_UP(map->cache_size_raw,
119 regcache_lzo_block_count(map)) /
116 map->cache_word_size); 120 map->cache_word_size);
117} 121}
118 122
119static inline int regcache_lzo_get_blksize(struct regmap *map) 123static inline int regcache_lzo_get_blksize(struct regmap *map)
120{ 124{
121 return DIV_ROUND_UP(map->cache_size_raw, regcache_lzo_block_count()); 125 return DIV_ROUND_UP(map->cache_size_raw,
126 regcache_lzo_block_count(map));
122} 127}
123 128
124static int regcache_lzo_init(struct regmap *map) 129static int regcache_lzo_init(struct regmap *map)
@@ -131,7 +136,7 @@ static int regcache_lzo_init(struct regmap *map)
131 136
132 ret = 0; 137 ret = 0;
133 138
134 blkcount = regcache_lzo_block_count(); 139 blkcount = regcache_lzo_block_count(map);
135 map->cache = kzalloc(blkcount * sizeof *lzo_blocks, 140 map->cache = kzalloc(blkcount * sizeof *lzo_blocks,
136 GFP_KERNEL); 141 GFP_KERNEL);
137 if (!map->cache) 142 if (!map->cache)
@@ -190,7 +195,7 @@ static int regcache_lzo_init(struct regmap *map)
190 195
191 return 0; 196 return 0;
192err: 197err:
193 regcache_exit(map); 198 regcache_lzo_exit(map);
194 return ret; 199 return ret;
195} 200}
196 201
@@ -203,7 +208,7 @@ static int regcache_lzo_exit(struct regmap *map)
203 if (!lzo_blocks) 208 if (!lzo_blocks)
204 return 0; 209 return 0;
205 210
206 blkcount = regcache_lzo_block_count(); 211 blkcount = regcache_lzo_block_count(map);
207 /* 212 /*
208 * the pointer to the bitmap used for syncing the cache 213 * the pointer to the bitmap used for syncing the cache
209 * is shared amongst all lzo_blocks. Ensure it is freed 214 * is shared amongst all lzo_blocks. Ensure it is freed
@@ -351,7 +356,7 @@ static int regcache_lzo_sync(struct regmap *map)
351} 356}
352 357
353struct regcache_ops regcache_lzo_ops = { 358struct regcache_ops regcache_lzo_ops = {
354 .type = REGCACHE_LZO, 359 .type = REGCACHE_COMPRESSED,
355 .name = "lzo", 360 .name = "lzo",
356 .init = regcache_lzo_init, 361 .init = regcache_lzo_init,
357 .exit = regcache_lzo_exit, 362 .exit = regcache_lzo_exit,
diff --git a/drivers/base/regmap/regcache-rbtree.c b/drivers/base/regmap/regcache-rbtree.c
index e31498499b0f..32620c4f1683 100644
--- a/drivers/base/regmap/regcache-rbtree.c
+++ b/drivers/base/regmap/regcache-rbtree.c
@@ -11,12 +11,15 @@
11 */ 11 */
12 12
13#include <linux/slab.h> 13#include <linux/slab.h>
14#include <linux/debugfs.h>
14#include <linux/rbtree.h> 15#include <linux/rbtree.h>
16#include <linux/seq_file.h>
15 17
16#include "internal.h" 18#include "internal.h"
17 19
18static int regcache_rbtree_write(struct regmap *map, unsigned int reg, 20static int regcache_rbtree_write(struct regmap *map, unsigned int reg,
19 unsigned int value); 21 unsigned int value);
22static int regcache_rbtree_exit(struct regmap *map);
20 23
21struct regcache_rbtree_node { 24struct regcache_rbtree_node {
22 /* the actual rbtree node holding this block */ 25 /* the actual rbtree node holding this block */
@@ -124,6 +127,60 @@ static int regcache_rbtree_insert(struct rb_root *root,
124 return 1; 127 return 1;
125} 128}
126 129
130#ifdef CONFIG_DEBUG_FS
131static int rbtree_show(struct seq_file *s, void *ignored)
132{
133 struct regmap *map = s->private;
134 struct regcache_rbtree_ctx *rbtree_ctx = map->cache;
135 struct regcache_rbtree_node *n;
136 struct rb_node *node;
137 unsigned int base, top;
138 int nodes = 0;
139 int registers = 0;
140
141 mutex_lock(&map->lock);
142
143 for (node = rb_first(&rbtree_ctx->root); node != NULL;
144 node = rb_next(node)) {
145 n = container_of(node, struct regcache_rbtree_node, node);
146
147 regcache_rbtree_get_base_top_reg(n, &base, &top);
148 seq_printf(s, "%x-%x (%d)\n", base, top, top - base + 1);
149
150 nodes++;
151 registers += top - base + 1;
152 }
153
154 seq_printf(s, "%d nodes, %d registers, average %d registers\n",
155 nodes, registers, registers / nodes);
156
157 mutex_unlock(&map->lock);
158
159 return 0;
160}
161
162static int rbtree_open(struct inode *inode, struct file *file)
163{
164 return single_open(file, rbtree_show, inode->i_private);
165}
166
167static const struct file_operations rbtree_fops = {
168 .open = rbtree_open,
169 .read = seq_read,
170 .llseek = seq_lseek,
171 .release = single_release,
172};
173
174static void rbtree_debugfs_init(struct regmap *map)
175{
176 debugfs_create_file("rbtree", 0400, map->debugfs, map, &rbtree_fops);
177}
178#else
179static void rbtree_debugfs_init(struct regmap *map)
180{
181}
182#endif
183
127static int regcache_rbtree_init(struct regmap *map) 184static int regcache_rbtree_init(struct regmap *map)
128{ 185{
129 struct regcache_rbtree_ctx *rbtree_ctx; 186 struct regcache_rbtree_ctx *rbtree_ctx;
@@ -146,10 +203,12 @@ static int regcache_rbtree_init(struct regmap *map)
146 goto err; 203 goto err;
147 } 204 }
148 205
206 rbtree_debugfs_init(map);
207
149 return 0; 208 return 0;
150 209
151err: 210err:
152 regcache_exit(map); 211 regcache_rbtree_exit(map);
153 return ret; 212 return ret;
154} 213}
155 214
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}
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index bf441db1ee90..be10a4ff6609 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -64,6 +64,18 @@ bool regmap_precious(struct regmap *map, unsigned int reg)
64 return false; 64 return false;
65} 65}
66 66
67static bool regmap_volatile_range(struct regmap *map, unsigned int reg,
68 unsigned int num)
69{
70 unsigned int i;
71
72 for (i = 0; i < num; i++)
73 if (!regmap_volatile(map, reg + i))
74 return false;
75
76 return true;
77}
78
67static void regmap_format_4_12_write(struct regmap *map, 79static void regmap_format_4_12_write(struct regmap *map,
68 unsigned int reg, unsigned int val) 80 unsigned int reg, unsigned int val)
69{ 81{
@@ -78,6 +90,16 @@ static void regmap_format_7_9_write(struct regmap *map,
78 *out = cpu_to_be16((reg << 9) | val); 90 *out = cpu_to_be16((reg << 9) | val);
79} 91}
80 92
93static void regmap_format_10_14_write(struct regmap *map,
94 unsigned int reg, unsigned int val)
95{
96 u8 *out = map->work_buf;
97
98 out[2] = val;
99 out[1] = (val >> 8) | (reg << 6);
100 out[0] = reg >> 2;
101}
102
81static void regmap_format_8(void *buf, unsigned int val) 103static void regmap_format_8(void *buf, unsigned int val)
82{ 104{
83 u8 *b = buf; 105 u8 *b = buf;
@@ -127,7 +149,7 @@ struct regmap *regmap_init(struct device *dev,
127 int ret = -EINVAL; 149 int ret = -EINVAL;
128 150
129 if (!bus || !config) 151 if (!bus || !config)
130 return NULL; 152 goto err;
131 153
132 map = kzalloc(sizeof(*map), GFP_KERNEL); 154 map = kzalloc(sizeof(*map), GFP_KERNEL);
133 if (map == NULL) { 155 if (map == NULL) {
@@ -147,12 +169,6 @@ struct regmap *regmap_init(struct device *dev,
147 map->volatile_reg = config->volatile_reg; 169 map->volatile_reg = config->volatile_reg;
148 map->precious_reg = config->precious_reg; 170 map->precious_reg = config->precious_reg;
149 map->cache_type = config->cache_type; 171 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 172
157 if (config->read_flag_mask || config->write_flag_mask) { 173 if (config->read_flag_mask || config->write_flag_mask) {
158 map->read_flag_mask = config->read_flag_mask; 174 map->read_flag_mask = config->read_flag_mask;
@@ -182,6 +198,16 @@ struct regmap *regmap_init(struct device *dev,
182 } 198 }
183 break; 199 break;
184 200
201 case 10:
202 switch (config->val_bits) {
203 case 14:
204 map->format.format_write = regmap_format_10_14_write;
205 break;
206 default:
207 goto err_map;
208 }
209 break;
210
185 case 8: 211 case 8:
186 map->format.format_reg = regmap_format_8; 212 map->format.format_reg = regmap_format_8;
187 break; 213 break;
@@ -215,14 +241,16 @@ struct regmap *regmap_init(struct device *dev,
215 goto err_map; 241 goto err_map;
216 } 242 }
217 243
218 ret = regcache_init(map);
219 if (ret < 0)
220 goto err_map;
221
222 regmap_debugfs_init(map); 244 regmap_debugfs_init(map);
223 245
246 ret = regcache_init(map, config);
247 if (ret < 0)
248 goto err_free_workbuf;
249
224 return map; 250 return map;
225 251
252err_free_workbuf:
253 kfree(map->work_buf);
226err_map: 254err_map:
227 kfree(map); 255 kfree(map);
228err: 256err:
@@ -231,6 +259,39 @@ err:
231EXPORT_SYMBOL_GPL(regmap_init); 259EXPORT_SYMBOL_GPL(regmap_init);
232 260
233/** 261/**
262 * regmap_reinit_cache(): Reinitialise the current register cache
263 *
264 * @map: Register map to operate on.
265 * @config: New configuration. Only the cache data will be used.
266 *
267 * Discard any existing register cache for the map and initialize a
268 * new cache. This can be used to restore the cache to defaults or to
269 * update the cache configuration to reflect runtime discovery of the
270 * hardware.
271 */
272int regmap_reinit_cache(struct regmap *map, const struct regmap_config *config)
273{
274 int ret;
275
276 mutex_lock(&map->lock);
277
278 regcache_exit(map);
279
280 map->max_register = config->max_register;
281 map->writeable_reg = config->writeable_reg;
282 map->readable_reg = config->readable_reg;
283 map->volatile_reg = config->volatile_reg;
284 map->precious_reg = config->precious_reg;
285 map->cache_type = config->cache_type;
286
287 ret = regcache_init(map, config);
288
289 mutex_unlock(&map->lock);
290
291 return ret;
292}
293
294/**
234 * regmap_exit(): Free a previously allocated register map 295 * regmap_exit(): Free a previously allocated register map
235 */ 296 */
236void regmap_exit(struct regmap *map) 297void regmap_exit(struct regmap *map)
@@ -306,8 +367,10 @@ int _regmap_write(struct regmap *map, unsigned int reg,
306 ret = regcache_write(map, reg, val); 367 ret = regcache_write(map, reg, val);
307 if (ret != 0) 368 if (ret != 0)
308 return ret; 369 return ret;
309 if (map->cache_only) 370 if (map->cache_only) {
371 map->cache_dirty = true;
310 return 0; 372 return 0;
373 }
311 } 374 }
312 375
313 trace_regmap_reg_write(map->dev, reg, val); 376 trace_regmap_reg_write(map->dev, reg, val);
@@ -375,9 +438,11 @@ EXPORT_SYMBOL_GPL(regmap_write);
375int regmap_raw_write(struct regmap *map, unsigned int reg, 438int regmap_raw_write(struct regmap *map, unsigned int reg,
376 const void *val, size_t val_len) 439 const void *val, size_t val_len)
377{ 440{
441 size_t val_count = val_len / map->format.val_bytes;
378 int ret; 442 int ret;
379 443
380 WARN_ON(map->cache_type != REGCACHE_NONE); 444 WARN_ON(!regmap_volatile_range(map, reg, val_count) &&
445 map->cache_type != REGCACHE_NONE);
381 446
382 mutex_lock(&map->lock); 447 mutex_lock(&map->lock);
383 448
@@ -422,15 +487,15 @@ static int _regmap_read(struct regmap *map, unsigned int reg,
422{ 487{
423 int ret; 488 int ret;
424 489
425 if (!map->format.parse_val)
426 return -EINVAL;
427
428 if (!map->cache_bypass) { 490 if (!map->cache_bypass) {
429 ret = regcache_read(map, reg, val); 491 ret = regcache_read(map, reg, val);
430 if (ret == 0) 492 if (ret == 0)
431 return 0; 493 return 0;
432 } 494 }
433 495
496 if (!map->format.parse_val)
497 return -EINVAL;
498
434 if (map->cache_only) 499 if (map->cache_only)
435 return -EBUSY; 500 return -EBUSY;
436 501
@@ -481,15 +546,11 @@ EXPORT_SYMBOL_GPL(regmap_read);
481int regmap_raw_read(struct regmap *map, unsigned int reg, void *val, 546int regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
482 size_t val_len) 547 size_t val_len)
483{ 548{
549 size_t val_count = val_len / map->format.val_bytes;
484 int ret; 550 int ret;
485 int i;
486 bool vol = true;
487 551
488 for (i = 0; i < val_len / map->format.val_bytes; i++) 552 WARN_ON(!regmap_volatile_range(map, reg, val_count) &&
489 if (!regmap_volatile(map, reg + i)) 553 map->cache_type != REGCACHE_NONE);
490 vol = false;
491
492 WARN_ON(!vol && map->cache_type != REGCACHE_NONE);
493 554
494 mutex_lock(&map->lock); 555 mutex_lock(&map->lock);
495 556
@@ -517,16 +578,11 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
517{ 578{
518 int ret, i; 579 int ret, i;
519 size_t val_bytes = map->format.val_bytes; 580 size_t val_bytes = map->format.val_bytes;
520 bool vol = true; 581 bool vol = regmap_volatile_range(map, reg, val_count);
521 582
522 if (!map->format.parse_val) 583 if (!map->format.parse_val)
523 return -EINVAL; 584 return -EINVAL;
524 585
525 /* Is this a block of volatile registers? */
526 for (i = 0; i < val_count; i++)
527 if (!regmap_volatile(map, reg + i))
528 vol = false;
529
530 if (vol || map->cache_type == REGCACHE_NONE) { 586 if (vol || map->cache_type == REGCACHE_NONE) {
531 ret = regmap_raw_read(map, reg, val, val_bytes * val_count); 587 ret = regmap_raw_read(map, reg, val, val_bytes * val_count);
532 if (ret != 0) 588 if (ret != 0)
@@ -546,40 +602,73 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
546} 602}
547EXPORT_SYMBOL_GPL(regmap_bulk_read); 603EXPORT_SYMBOL_GPL(regmap_bulk_read);
548 604
549/** 605static int _regmap_update_bits(struct regmap *map, unsigned int reg,
550 * remap_update_bits: Perform a read/modify/write cycle on the register map 606 unsigned int mask, unsigned int val,
551 * 607 bool *change)
552 * @map: Register map to update
553 * @reg: Register to update
554 * @mask: Bitmask to change
555 * @val: New value for bitmask
556 *
557 * Returns zero for success, a negative number on error.
558 */
559int regmap_update_bits(struct regmap *map, unsigned int reg,
560 unsigned int mask, unsigned int val)
561{ 608{
562 int ret; 609 int ret;
563 unsigned int tmp; 610 unsigned int tmp, orig;
564 611
565 mutex_lock(&map->lock); 612 mutex_lock(&map->lock);
566 613
567 ret = _regmap_read(map, reg, &tmp); 614 ret = _regmap_read(map, reg, &orig);
568 if (ret != 0) 615 if (ret != 0)
569 goto out; 616 goto out;
570 617
571 tmp &= ~mask; 618 tmp = orig & ~mask;
572 tmp |= val & mask; 619 tmp |= val & mask;
573 620
574 ret = _regmap_write(map, reg, tmp); 621 if (tmp != orig) {
622 ret = _regmap_write(map, reg, tmp);
623 *change = true;
624 } else {
625 *change = false;
626 }
575 627
576out: 628out:
577 mutex_unlock(&map->lock); 629 mutex_unlock(&map->lock);
578 630
579 return ret; 631 return ret;
580} 632}
633
634/**
635 * regmap_update_bits: Perform a read/modify/write cycle on the register map
636 *
637 * @map: Register map to update
638 * @reg: Register to update
639 * @mask: Bitmask to change
640 * @val: New value for bitmask
641 *
642 * Returns zero for success, a negative number on error.
643 */
644int regmap_update_bits(struct regmap *map, unsigned int reg,
645 unsigned int mask, unsigned int val)
646{
647 bool change;
648 return _regmap_update_bits(map, reg, mask, val, &change);
649}
581EXPORT_SYMBOL_GPL(regmap_update_bits); 650EXPORT_SYMBOL_GPL(regmap_update_bits);
582 651
652/**
653 * regmap_update_bits_check: Perform a read/modify/write cycle on the
654 * register map and report if updated
655 *
656 * @map: Register map to update
657 * @reg: Register to update
658 * @mask: Bitmask to change
659 * @val: New value for bitmask
660 * @change: Boolean indicating if a write was done
661 *
662 * Returns zero for success, a negative number on error.
663 */
664int regmap_update_bits_check(struct regmap *map, unsigned int reg,
665 unsigned int mask, unsigned int val,
666 bool *change)
667{
668 return _regmap_update_bits(map, reg, mask, val, change);
669}
670EXPORT_SYMBOL_GPL(regmap_update_bits_check);
671
583static int __init regmap_initcall(void) 672static int __init regmap_initcall(void)
584{ 673{
585 regmap_debugfs_initcall(); 674 regmap_debugfs_initcall();