aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-01-08 16:35:24 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2012-01-08 16:35:24 -0500
commitb7d845f8825b058b80e76320f573505afbf4a1fc (patch)
treedc66dec44b489723427c9c4a9a92ef6e9f17c55b /drivers/base
parent2943c833222ef87c111ee0c6b7b8519ad2983e99 (diff)
parent0a92815db789bd5a922d882826cf710f9b0b9d85 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap: (36 commits) mfd: Clearing events requires event registers to be writable for da9052-core mfd: Fix annotations in da9052-core gpiolib: Mark da9052 driver broken mfd: Declare da9052_regmap_config for the bus drivers MFD: DA9052/53 MFD core module add SPI support v2 MFD: DA9052/53 MFD core module regmap: Add irq_base accessor to regmap_irq regmap: Allow drivers to reinitialise the register cache at runtime regmap: Add trace event for successful cache reads regmap: Allow regmap_update_bits() users to detect changes regmap: Report if we actually handled an interrupt in regmap-irq regmap: Fix rbtreee build when not using debugfs regmap: Provide debugfs dump of the rbtree cache data regmap: Do debugfs init before cache init regmap: Suppress noop writes in regmap_update_bits() regmap: Remove indexed cache type regmap: Drop check whether a register is readable in regcache_read regmap: Properly round cache_word_size regmap: Add support for 10/14 register formating regmap: Try cached read before checking if a hardware read is possible ...
Diffstat (limited to 'drivers/base')
-rw-r--r--drivers/base/regmap/Kconfig3
-rw-r--r--drivers/base/regmap/Makefile4
-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-irq.c302
-rw-r--r--drivers/base/regmap/regmap.c179
9 files changed, 574 insertions, 153 deletions
diff --git a/drivers/base/regmap/Kconfig b/drivers/base/regmap/Kconfig
index 2fc6a66f39a4..0f6c7fb418e8 100644
--- a/drivers/base/regmap/Kconfig
+++ b/drivers/base/regmap/Kconfig
@@ -13,3 +13,6 @@ config REGMAP_I2C
13 13
14config REGMAP_SPI 14config REGMAP_SPI
15 tristate 15 tristate
16
17config REGMAP_IRQ
18 bool
diff --git a/drivers/base/regmap/Makefile b/drivers/base/regmap/Makefile
index 0573c8a9dacb..defd57963c84 100644
--- a/drivers/base/regmap/Makefile
+++ b/drivers/base/regmap/Makefile
@@ -1,4 +1,6 @@
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
6obj-$(CONFIG_REGMAP_IRQ) += regmap-irq.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-irq.c b/drivers/base/regmap/regmap-irq.c
new file mode 100644
index 000000000000..428836fc5835
--- /dev/null
+++ b/drivers/base/regmap/regmap-irq.c
@@ -0,0 +1,302 @@
1/*
2 * regmap based irq_chip
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/export.h>
14#include <linux/regmap.h>
15#include <linux/irq.h>
16#include <linux/interrupt.h>
17#include <linux/slab.h>
18
19#include "internal.h"
20
21struct regmap_irq_chip_data {
22 struct mutex lock;
23
24 struct regmap *map;
25 struct regmap_irq_chip *chip;
26
27 int irq_base;
28
29 void *status_reg_buf;
30 unsigned int *status_buf;
31 unsigned int *mask_buf;
32 unsigned int *mask_buf_def;
33};
34
35static inline const
36struct regmap_irq *irq_to_regmap_irq(struct regmap_irq_chip_data *data,
37 int irq)
38{
39 return &data->chip->irqs[irq - data->irq_base];
40}
41
42static void regmap_irq_lock(struct irq_data *data)
43{
44 struct regmap_irq_chip_data *d = irq_data_get_irq_chip_data(data);
45
46 mutex_lock(&d->lock);
47}
48
49static void regmap_irq_sync_unlock(struct irq_data *data)
50{
51 struct regmap_irq_chip_data *d = irq_data_get_irq_chip_data(data);
52 int i, ret;
53
54 /*
55 * If there's been a change in the mask write it back to the
56 * hardware. We rely on the use of the regmap core cache to
57 * suppress pointless writes.
58 */
59 for (i = 0; i < d->chip->num_regs; i++) {
60 ret = regmap_update_bits(d->map, d->chip->mask_base + i,
61 d->mask_buf_def[i], d->mask_buf[i]);
62 if (ret != 0)
63 dev_err(d->map->dev, "Failed to sync masks in %x\n",
64 d->chip->mask_base + i);
65 }
66
67 mutex_unlock(&d->lock);
68}
69
70static void regmap_irq_enable(struct irq_data *data)
71{
72 struct regmap_irq_chip_data *d = irq_data_get_irq_chip_data(data);
73 const struct regmap_irq *irq_data = irq_to_regmap_irq(d, data->irq);
74
75 d->mask_buf[irq_data->reg_offset] &= ~irq_data->mask;
76}
77
78static void regmap_irq_disable(struct irq_data *data)
79{
80 struct regmap_irq_chip_data *d = irq_data_get_irq_chip_data(data);
81 const struct regmap_irq *irq_data = irq_to_regmap_irq(d, data->irq);
82
83 d->mask_buf[irq_data->reg_offset] |= irq_data->mask;
84}
85
86static struct irq_chip regmap_irq_chip = {
87 .name = "regmap",
88 .irq_bus_lock = regmap_irq_lock,
89 .irq_bus_sync_unlock = regmap_irq_sync_unlock,
90 .irq_disable = regmap_irq_disable,
91 .irq_enable = regmap_irq_enable,
92};
93
94static irqreturn_t regmap_irq_thread(int irq, void *d)
95{
96 struct regmap_irq_chip_data *data = d;
97 struct regmap_irq_chip *chip = data->chip;
98 struct regmap *map = data->map;
99 int ret, i;
100 u8 *buf8 = data->status_reg_buf;
101 u16 *buf16 = data->status_reg_buf;
102 u32 *buf32 = data->status_reg_buf;
103 bool handled = false;
104
105 ret = regmap_bulk_read(map, chip->status_base, data->status_reg_buf,
106 chip->num_regs);
107 if (ret != 0) {
108 dev_err(map->dev, "Failed to read IRQ status: %d\n", ret);
109 return IRQ_NONE;
110 }
111
112 /*
113 * Ignore masked IRQs and ack if we need to; we ack early so
114 * there is no race between handling and acknowleding the
115 * interrupt. We assume that typically few of the interrupts
116 * will fire simultaneously so don't worry about overhead from
117 * doing a write per register.
118 */
119 for (i = 0; i < data->chip->num_regs; i++) {
120 switch (map->format.val_bytes) {
121 case 1:
122 data->status_buf[i] = buf8[i];
123 break;
124 case 2:
125 data->status_buf[i] = buf16[i];
126 break;
127 case 4:
128 data->status_buf[i] = buf32[i];
129 break;
130 default:
131 BUG();
132 return IRQ_NONE;
133 }
134
135 data->status_buf[i] &= ~data->mask_buf[i];
136
137 if (data->status_buf[i] && chip->ack_base) {
138 ret = regmap_write(map, chip->ack_base + i,
139 data->status_buf[i]);
140 if (ret != 0)
141 dev_err(map->dev, "Failed to ack 0x%x: %d\n",
142 chip->ack_base + i, ret);
143 }
144 }
145
146 for (i = 0; i < chip->num_irqs; i++) {
147 if (data->status_buf[chip->irqs[i].reg_offset] &
148 chip->irqs[i].mask) {
149 handle_nested_irq(data->irq_base + i);
150 handled = true;
151 }
152 }
153
154 if (handled)
155 return IRQ_HANDLED;
156 else
157 return IRQ_NONE;
158}
159
160/**
161 * regmap_add_irq_chip(): Use standard regmap IRQ controller handling
162 *
163 * map: The regmap for the device.
164 * irq: The IRQ the device uses to signal interrupts
165 * irq_flags: The IRQF_ flags to use for the primary interrupt.
166 * chip: Configuration for the interrupt controller.
167 * data: Runtime data structure for the controller, allocated on success
168 *
169 * Returns 0 on success or an errno on failure.
170 *
171 * In order for this to be efficient the chip really should use a
172 * register cache. The chip driver is responsible for restoring the
173 * register values used by the IRQ controller over suspend and resume.
174 */
175int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
176 int irq_base, struct regmap_irq_chip *chip,
177 struct regmap_irq_chip_data **data)
178{
179 struct regmap_irq_chip_data *d;
180 int cur_irq, i;
181 int ret = -ENOMEM;
182
183 irq_base = irq_alloc_descs(irq_base, 0, chip->num_irqs, 0);
184 if (irq_base < 0) {
185 dev_warn(map->dev, "Failed to allocate IRQs: %d\n",
186 irq_base);
187 return irq_base;
188 }
189
190 d = kzalloc(sizeof(*d), GFP_KERNEL);
191 if (!d)
192 return -ENOMEM;
193
194 d->status_buf = kzalloc(sizeof(unsigned int) * chip->num_regs,
195 GFP_KERNEL);
196 if (!d->status_buf)
197 goto err_alloc;
198
199 d->status_reg_buf = kzalloc(map->format.val_bytes * chip->num_regs,
200 GFP_KERNEL);
201 if (!d->status_reg_buf)
202 goto err_alloc;
203
204 d->mask_buf = kzalloc(sizeof(unsigned int) * chip->num_regs,
205 GFP_KERNEL);
206 if (!d->mask_buf)
207 goto err_alloc;
208
209 d->mask_buf_def = kzalloc(sizeof(unsigned int) * chip->num_regs,
210 GFP_KERNEL);
211 if (!d->mask_buf_def)
212 goto err_alloc;
213
214 d->map = map;
215 d->chip = chip;
216 d->irq_base = irq_base;
217 mutex_init(&d->lock);
218
219 for (i = 0; i < chip->num_irqs; i++)
220 d->mask_buf_def[chip->irqs[i].reg_offset]
221 |= chip->irqs[i].mask;
222
223 /* Mask all the interrupts by default */
224 for (i = 0; i < chip->num_regs; i++) {
225 d->mask_buf[i] = d->mask_buf_def[i];
226 ret = regmap_write(map, chip->mask_base + i, d->mask_buf[i]);
227 if (ret != 0) {
228 dev_err(map->dev, "Failed to set masks in 0x%x: %d\n",
229 chip->mask_base + i, ret);
230 goto err_alloc;
231 }
232 }
233
234 /* Register them with genirq */
235 for (cur_irq = irq_base;
236 cur_irq < chip->num_irqs + irq_base;
237 cur_irq++) {
238 irq_set_chip_data(cur_irq, d);
239 irq_set_chip_and_handler(cur_irq, &regmap_irq_chip,
240 handle_edge_irq);
241 irq_set_nested_thread(cur_irq, 1);
242
243 /* ARM needs us to explicitly flag the IRQ as valid
244 * and will set them noprobe when we do so. */
245#ifdef CONFIG_ARM
246 set_irq_flags(cur_irq, IRQF_VALID);
247#else
248 irq_set_noprobe(cur_irq);
249#endif
250 }
251
252 ret = request_threaded_irq(irq, NULL, regmap_irq_thread, irq_flags,
253 chip->name, d);
254 if (ret != 0) {
255 dev_err(map->dev, "Failed to request IRQ %d: %d\n", irq, ret);
256 goto err_alloc;
257 }
258
259 return 0;
260
261err_alloc:
262 kfree(d->mask_buf_def);
263 kfree(d->mask_buf);
264 kfree(d->status_reg_buf);
265 kfree(d->status_buf);
266 kfree(d);
267 return ret;
268}
269EXPORT_SYMBOL_GPL(regmap_add_irq_chip);
270
271/**
272 * regmap_del_irq_chip(): Stop interrupt handling for a regmap IRQ chip
273 *
274 * @irq: Primary IRQ for the device
275 * @d: regmap_irq_chip_data allocated by regmap_add_irq_chip()
276 */
277void regmap_del_irq_chip(int irq, struct regmap_irq_chip_data *d)
278{
279 if (!d)
280 return;
281
282 free_irq(irq, d);
283 kfree(d->mask_buf_def);
284 kfree(d->mask_buf);
285 kfree(d->status_reg_buf);
286 kfree(d->status_buf);
287 kfree(d);
288}
289EXPORT_SYMBOL_GPL(regmap_del_irq_chip);
290
291/**
292 * regmap_irq_chip_get_base(): Retrieve interrupt base for a regmap IRQ chip
293 *
294 * Useful for drivers to request their own IRQs.
295 *
296 * @data: regmap_irq controller to operate on.
297 */
298int regmap_irq_chip_get_base(struct regmap_irq_chip_data *data)
299{
300 return data->irq_base;
301}
302EXPORT_SYMBOL_GPL(regmap_irq_chip_get_base);
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();