diff options
Diffstat (limited to 'drivers/base/regmap')
-rw-r--r-- | drivers/base/regmap/Kconfig | 3 | ||||
-rw-r--r-- | drivers/base/regmap/Makefile | 1 | ||||
-rw-r--r-- | drivers/base/regmap/internal.h | 21 | ||||
-rw-r--r-- | drivers/base/regmap/regcache-rbtree.c | 4 | ||||
-rw-r--r-- | drivers/base/regmap/regcache.c | 20 | ||||
-rw-r--r-- | drivers/base/regmap/regmap-debugfs.c | 14 | ||||
-rw-r--r-- | drivers/base/regmap/regmap-i2c.c | 13 | ||||
-rw-r--r-- | drivers/base/regmap/regmap-mmio.c | 211 | ||||
-rw-r--r-- | drivers/base/regmap/regmap-spi.c | 13 | ||||
-rw-r--r-- | drivers/base/regmap/regmap.c | 139 |
10 files changed, 373 insertions, 66 deletions
diff --git a/drivers/base/regmap/Kconfig b/drivers/base/regmap/Kconfig index 0f6c7fb418e8..9ef0a5326f17 100644 --- a/drivers/base/regmap/Kconfig +++ b/drivers/base/regmap/Kconfig | |||
@@ -14,5 +14,8 @@ config REGMAP_I2C | |||
14 | config REGMAP_SPI | 14 | config REGMAP_SPI |
15 | tristate | 15 | tristate |
16 | 16 | ||
17 | config REGMAP_MMIO | ||
18 | tristate | ||
19 | |||
17 | config REGMAP_IRQ | 20 | config REGMAP_IRQ |
18 | bool | 21 | bool |
diff --git a/drivers/base/regmap/Makefile b/drivers/base/regmap/Makefile index defd57963c84..5e75d1b683e2 100644 --- a/drivers/base/regmap/Makefile +++ b/drivers/base/regmap/Makefile | |||
@@ -3,4 +3,5 @@ obj-$(CONFIG_REGMAP) += regcache-rbtree.o regcache-lzo.o | |||
3 | obj-$(CONFIG_DEBUG_FS) += regmap-debugfs.o | 3 | obj-$(CONFIG_DEBUG_FS) += regmap-debugfs.o |
4 | obj-$(CONFIG_REGMAP_I2C) += regmap-i2c.o | 4 | obj-$(CONFIG_REGMAP_I2C) += regmap-i2c.o |
5 | obj-$(CONFIG_REGMAP_SPI) += regmap-spi.o | 5 | obj-$(CONFIG_REGMAP_SPI) += regmap-spi.o |
6 | obj-$(CONFIG_REGMAP_MMIO) += regmap-mmio.o | ||
6 | obj-$(CONFIG_REGMAP_IRQ) += regmap-irq.o | 7 | obj-$(CONFIG_REGMAP_IRQ) += regmap-irq.o |
diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h index fcafc5b2e651..99b28fffbd0e 100644 --- a/drivers/base/regmap/internal.h +++ b/drivers/base/regmap/internal.h | |||
@@ -26,21 +26,29 @@ struct regmap_format { | |||
26 | size_t val_bytes; | 26 | size_t val_bytes; |
27 | void (*format_write)(struct regmap *map, | 27 | void (*format_write)(struct regmap *map, |
28 | unsigned int reg, unsigned int val); | 28 | unsigned int reg, unsigned int val); |
29 | void (*format_reg)(void *buf, unsigned int reg); | 29 | void (*format_reg)(void *buf, unsigned int reg, unsigned int shift); |
30 | void (*format_val)(void *buf, unsigned int val); | 30 | void (*format_val)(void *buf, unsigned int val, unsigned int shift); |
31 | unsigned int (*parse_val)(void *buf); | 31 | unsigned int (*parse_val)(void *buf); |
32 | }; | 32 | }; |
33 | 33 | ||
34 | typedef void (*regmap_lock)(struct regmap *map); | ||
35 | typedef void (*regmap_unlock)(struct regmap *map); | ||
36 | |||
34 | struct regmap { | 37 | struct regmap { |
35 | struct mutex lock; | 38 | struct mutex mutex; |
39 | spinlock_t spinlock; | ||
40 | regmap_lock lock; | ||
41 | regmap_unlock unlock; | ||
36 | 42 | ||
37 | struct device *dev; /* Device we do I/O on */ | 43 | struct device *dev; /* Device we do I/O on */ |
38 | void *work_buf; /* Scratch buffer used to format I/O */ | 44 | void *work_buf; /* Scratch buffer used to format I/O */ |
39 | struct regmap_format format; /* Buffer format */ | 45 | struct regmap_format format; /* Buffer format */ |
40 | const struct regmap_bus *bus; | 46 | const struct regmap_bus *bus; |
47 | void *bus_context; | ||
41 | 48 | ||
42 | #ifdef CONFIG_DEBUG_FS | 49 | #ifdef CONFIG_DEBUG_FS |
43 | struct dentry *debugfs; | 50 | struct dentry *debugfs; |
51 | const char *debugfs_name; | ||
44 | #endif | 52 | #endif |
45 | 53 | ||
46 | unsigned int max_register; | 54 | unsigned int max_register; |
@@ -52,6 +60,9 @@ struct regmap { | |||
52 | u8 read_flag_mask; | 60 | u8 read_flag_mask; |
53 | u8 write_flag_mask; | 61 | u8 write_flag_mask; |
54 | 62 | ||
63 | /* number of bits to (left) shift the reg value when formatting*/ | ||
64 | int reg_shift; | ||
65 | |||
55 | /* regcache specific members */ | 66 | /* regcache specific members */ |
56 | const struct regcache_ops *cache_ops; | 67 | const struct regcache_ops *cache_ops; |
57 | enum regcache_type cache_type; | 68 | enum regcache_type cache_type; |
@@ -101,11 +112,11 @@ int _regmap_write(struct regmap *map, unsigned int reg, | |||
101 | 112 | ||
102 | #ifdef CONFIG_DEBUG_FS | 113 | #ifdef CONFIG_DEBUG_FS |
103 | extern void regmap_debugfs_initcall(void); | 114 | extern void regmap_debugfs_initcall(void); |
104 | extern void regmap_debugfs_init(struct regmap *map); | 115 | extern void regmap_debugfs_init(struct regmap *map, const char *name); |
105 | extern void regmap_debugfs_exit(struct regmap *map); | 116 | extern void regmap_debugfs_exit(struct regmap *map); |
106 | #else | 117 | #else |
107 | static inline void regmap_debugfs_initcall(void) { } | 118 | static inline void regmap_debugfs_initcall(void) { } |
108 | static inline void regmap_debugfs_init(struct regmap *map) { } | 119 | static inline void regmap_debugfs_init(struct regmap *map, const char *name) { } |
109 | static inline void regmap_debugfs_exit(struct regmap *map) { } | 120 | static inline void regmap_debugfs_exit(struct regmap *map) { } |
110 | #endif | 121 | #endif |
111 | 122 | ||
diff --git a/drivers/base/regmap/regcache-rbtree.c b/drivers/base/regmap/regcache-rbtree.c index 92b779ee002b..e49e71fab184 100644 --- a/drivers/base/regmap/regcache-rbtree.c +++ b/drivers/base/regmap/regcache-rbtree.c | |||
@@ -140,7 +140,7 @@ static int rbtree_show(struct seq_file *s, void *ignored) | |||
140 | int registers = 0; | 140 | int registers = 0; |
141 | int average; | 141 | int average; |
142 | 142 | ||
143 | mutex_lock(&map->lock); | 143 | map->lock(map); |
144 | 144 | ||
145 | for (node = rb_first(&rbtree_ctx->root); node != NULL; | 145 | for (node = rb_first(&rbtree_ctx->root); node != NULL; |
146 | node = rb_next(node)) { | 146 | node = rb_next(node)) { |
@@ -161,7 +161,7 @@ static int rbtree_show(struct seq_file *s, void *ignored) | |||
161 | seq_printf(s, "%d nodes, %d registers, average %d registers\n", | 161 | seq_printf(s, "%d nodes, %d registers, average %d registers\n", |
162 | nodes, registers, average); | 162 | nodes, registers, average); |
163 | 163 | ||
164 | mutex_unlock(&map->lock); | 164 | map->unlock(map); |
165 | 165 | ||
166 | return 0; | 166 | return 0; |
167 | } | 167 | } |
diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c index 74b69095def6..d4368e8b6f9d 100644 --- a/drivers/base/regmap/regcache.c +++ b/drivers/base/regmap/regcache.c | |||
@@ -264,7 +264,7 @@ int regcache_sync(struct regmap *map) | |||
264 | 264 | ||
265 | BUG_ON(!map->cache_ops || !map->cache_ops->sync); | 265 | BUG_ON(!map->cache_ops || !map->cache_ops->sync); |
266 | 266 | ||
267 | mutex_lock(&map->lock); | 267 | map->lock(map); |
268 | /* Remember the initial bypass state */ | 268 | /* Remember the initial bypass state */ |
269 | bypass = map->cache_bypass; | 269 | bypass = map->cache_bypass; |
270 | dev_dbg(map->dev, "Syncing %s cache\n", | 270 | dev_dbg(map->dev, "Syncing %s cache\n", |
@@ -296,7 +296,7 @@ out: | |||
296 | trace_regcache_sync(map->dev, name, "stop"); | 296 | trace_regcache_sync(map->dev, name, "stop"); |
297 | /* Restore the bypass state */ | 297 | /* Restore the bypass state */ |
298 | map->cache_bypass = bypass; | 298 | map->cache_bypass = bypass; |
299 | mutex_unlock(&map->lock); | 299 | map->unlock(map); |
300 | 300 | ||
301 | return ret; | 301 | return ret; |
302 | } | 302 | } |
@@ -323,7 +323,7 @@ int regcache_sync_region(struct regmap *map, unsigned int min, | |||
323 | 323 | ||
324 | BUG_ON(!map->cache_ops || !map->cache_ops->sync); | 324 | BUG_ON(!map->cache_ops || !map->cache_ops->sync); |
325 | 325 | ||
326 | mutex_lock(&map->lock); | 326 | map->lock(map); |
327 | 327 | ||
328 | /* Remember the initial bypass state */ | 328 | /* Remember the initial bypass state */ |
329 | bypass = map->cache_bypass; | 329 | bypass = map->cache_bypass; |
@@ -342,7 +342,7 @@ out: | |||
342 | trace_regcache_sync(map->dev, name, "stop region"); | 342 | trace_regcache_sync(map->dev, name, "stop region"); |
343 | /* Restore the bypass state */ | 343 | /* Restore the bypass state */ |
344 | map->cache_bypass = bypass; | 344 | map->cache_bypass = bypass; |
345 | mutex_unlock(&map->lock); | 345 | map->unlock(map); |
346 | 346 | ||
347 | return ret; | 347 | return ret; |
348 | } | 348 | } |
@@ -362,11 +362,11 @@ EXPORT_SYMBOL_GPL(regcache_sync_region); | |||
362 | */ | 362 | */ |
363 | void regcache_cache_only(struct regmap *map, bool enable) | 363 | void regcache_cache_only(struct regmap *map, bool enable) |
364 | { | 364 | { |
365 | mutex_lock(&map->lock); | 365 | map->lock(map); |
366 | WARN_ON(map->cache_bypass && enable); | 366 | WARN_ON(map->cache_bypass && enable); |
367 | map->cache_only = enable; | 367 | map->cache_only = enable; |
368 | trace_regmap_cache_only(map->dev, enable); | 368 | trace_regmap_cache_only(map->dev, enable); |
369 | mutex_unlock(&map->lock); | 369 | map->unlock(map); |
370 | } | 370 | } |
371 | EXPORT_SYMBOL_GPL(regcache_cache_only); | 371 | EXPORT_SYMBOL_GPL(regcache_cache_only); |
372 | 372 | ||
@@ -381,9 +381,9 @@ EXPORT_SYMBOL_GPL(regcache_cache_only); | |||
381 | */ | 381 | */ |
382 | void regcache_mark_dirty(struct regmap *map) | 382 | void regcache_mark_dirty(struct regmap *map) |
383 | { | 383 | { |
384 | mutex_lock(&map->lock); | 384 | map->lock(map); |
385 | map->cache_dirty = true; | 385 | map->cache_dirty = true; |
386 | mutex_unlock(&map->lock); | 386 | map->unlock(map); |
387 | } | 387 | } |
388 | EXPORT_SYMBOL_GPL(regcache_mark_dirty); | 388 | EXPORT_SYMBOL_GPL(regcache_mark_dirty); |
389 | 389 | ||
@@ -400,11 +400,11 @@ EXPORT_SYMBOL_GPL(regcache_mark_dirty); | |||
400 | */ | 400 | */ |
401 | void regcache_cache_bypass(struct regmap *map, bool enable) | 401 | void regcache_cache_bypass(struct regmap *map, bool enable) |
402 | { | 402 | { |
403 | mutex_lock(&map->lock); | 403 | map->lock(map); |
404 | WARN_ON(map->cache_only && enable); | 404 | WARN_ON(map->cache_only && enable); |
405 | map->cache_bypass = enable; | 405 | map->cache_bypass = enable; |
406 | trace_regmap_cache_bypass(map->dev, enable); | 406 | trace_regmap_cache_bypass(map->dev, enable); |
407 | mutex_unlock(&map->lock); | 407 | map->unlock(map); |
408 | } | 408 | } |
409 | EXPORT_SYMBOL_GPL(regcache_cache_bypass); | 409 | EXPORT_SYMBOL_GPL(regcache_cache_bypass); |
410 | 410 | ||
diff --git a/drivers/base/regmap/regmap-debugfs.c b/drivers/base/regmap/regmap-debugfs.c index 251eb70f83e7..df97c93efa8e 100644 --- a/drivers/base/regmap/regmap-debugfs.c +++ b/drivers/base/regmap/regmap-debugfs.c | |||
@@ -242,10 +242,17 @@ static const struct file_operations regmap_access_fops = { | |||
242 | .llseek = default_llseek, | 242 | .llseek = default_llseek, |
243 | }; | 243 | }; |
244 | 244 | ||
245 | void regmap_debugfs_init(struct regmap *map) | 245 | void regmap_debugfs_init(struct regmap *map, const char *name) |
246 | { | 246 | { |
247 | map->debugfs = debugfs_create_dir(dev_name(map->dev), | 247 | if (name) { |
248 | regmap_debugfs_root); | 248 | map->debugfs_name = kasprintf(GFP_KERNEL, "%s-%s", |
249 | dev_name(map->dev), name); | ||
250 | name = map->debugfs_name; | ||
251 | } else { | ||
252 | name = dev_name(map->dev); | ||
253 | } | ||
254 | |||
255 | map->debugfs = debugfs_create_dir(name, regmap_debugfs_root); | ||
249 | if (!map->debugfs) { | 256 | if (!map->debugfs) { |
250 | dev_warn(map->dev, "Failed to create debugfs directory\n"); | 257 | dev_warn(map->dev, "Failed to create debugfs directory\n"); |
251 | return; | 258 | return; |
@@ -274,6 +281,7 @@ void regmap_debugfs_init(struct regmap *map) | |||
274 | void regmap_debugfs_exit(struct regmap *map) | 281 | void regmap_debugfs_exit(struct regmap *map) |
275 | { | 282 | { |
276 | debugfs_remove_recursive(map->debugfs); | 283 | debugfs_remove_recursive(map->debugfs); |
284 | kfree(map->debugfs_name); | ||
277 | } | 285 | } |
278 | 286 | ||
279 | void regmap_debugfs_initcall(void) | 287 | void regmap_debugfs_initcall(void) |
diff --git a/drivers/base/regmap/regmap-i2c.c b/drivers/base/regmap/regmap-i2c.c index 9a3a8c564389..5f6b2478bf17 100644 --- a/drivers/base/regmap/regmap-i2c.c +++ b/drivers/base/regmap/regmap-i2c.c | |||
@@ -15,8 +15,9 @@ | |||
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/init.h> | 16 | #include <linux/init.h> |
17 | 17 | ||
18 | static int regmap_i2c_write(struct device *dev, const void *data, size_t count) | 18 | static int regmap_i2c_write(void *context, const void *data, size_t count) |
19 | { | 19 | { |
20 | struct device *dev = context; | ||
20 | struct i2c_client *i2c = to_i2c_client(dev); | 21 | struct i2c_client *i2c = to_i2c_client(dev); |
21 | int ret; | 22 | int ret; |
22 | 23 | ||
@@ -29,10 +30,11 @@ static int regmap_i2c_write(struct device *dev, const void *data, size_t count) | |||
29 | return -EIO; | 30 | return -EIO; |
30 | } | 31 | } |
31 | 32 | ||
32 | static int regmap_i2c_gather_write(struct device *dev, | 33 | static int regmap_i2c_gather_write(void *context, |
33 | const void *reg, size_t reg_size, | 34 | const void *reg, size_t reg_size, |
34 | const void *val, size_t val_size) | 35 | const void *val, size_t val_size) |
35 | { | 36 | { |
37 | struct device *dev = context; | ||
36 | struct i2c_client *i2c = to_i2c_client(dev); | 38 | struct i2c_client *i2c = to_i2c_client(dev); |
37 | struct i2c_msg xfer[2]; | 39 | struct i2c_msg xfer[2]; |
38 | int ret; | 40 | int ret; |
@@ -62,10 +64,11 @@ static int regmap_i2c_gather_write(struct device *dev, | |||
62 | return -EIO; | 64 | return -EIO; |
63 | } | 65 | } |
64 | 66 | ||
65 | static int regmap_i2c_read(struct device *dev, | 67 | static int regmap_i2c_read(void *context, |
66 | const void *reg, size_t reg_size, | 68 | const void *reg, size_t reg_size, |
67 | void *val, size_t val_size) | 69 | void *val, size_t val_size) |
68 | { | 70 | { |
71 | struct device *dev = context; | ||
69 | struct i2c_client *i2c = to_i2c_client(dev); | 72 | struct i2c_client *i2c = to_i2c_client(dev); |
70 | struct i2c_msg xfer[2]; | 73 | struct i2c_msg xfer[2]; |
71 | int ret; | 74 | int ret; |
@@ -107,7 +110,7 @@ static struct regmap_bus regmap_i2c = { | |||
107 | struct regmap *regmap_init_i2c(struct i2c_client *i2c, | 110 | struct regmap *regmap_init_i2c(struct i2c_client *i2c, |
108 | const struct regmap_config *config) | 111 | const struct regmap_config *config) |
109 | { | 112 | { |
110 | return regmap_init(&i2c->dev, ®map_i2c, config); | 113 | return regmap_init(&i2c->dev, ®map_i2c, &i2c->dev, config); |
111 | } | 114 | } |
112 | EXPORT_SYMBOL_GPL(regmap_init_i2c); | 115 | EXPORT_SYMBOL_GPL(regmap_init_i2c); |
113 | 116 | ||
@@ -124,7 +127,7 @@ EXPORT_SYMBOL_GPL(regmap_init_i2c); | |||
124 | struct regmap *devm_regmap_init_i2c(struct i2c_client *i2c, | 127 | struct regmap *devm_regmap_init_i2c(struct i2c_client *i2c, |
125 | const struct regmap_config *config) | 128 | const struct regmap_config *config) |
126 | { | 129 | { |
127 | return devm_regmap_init(&i2c->dev, ®map_i2c, config); | 130 | return devm_regmap_init(&i2c->dev, ®map_i2c, &i2c->dev, config); |
128 | } | 131 | } |
129 | EXPORT_SYMBOL_GPL(devm_regmap_init_i2c); | 132 | EXPORT_SYMBOL_GPL(devm_regmap_init_i2c); |
130 | 133 | ||
diff --git a/drivers/base/regmap/regmap-mmio.c b/drivers/base/regmap/regmap-mmio.c new file mode 100644 index 000000000000..bdf4dc865293 --- /dev/null +++ b/drivers/base/regmap/regmap-mmio.c | |||
@@ -0,0 +1,211 @@ | |||
1 | /* | ||
2 | * Register map access API - MMIO support | ||
3 | * | ||
4 | * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms and conditions of the GNU General Public License, | ||
8 | * version 2, as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
13 | * more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | */ | ||
18 | |||
19 | #include <linux/err.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/io.h> | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/regmap.h> | ||
24 | #include <linux/slab.h> | ||
25 | |||
26 | struct regmap_mmio_context { | ||
27 | void __iomem *regs; | ||
28 | unsigned val_bytes; | ||
29 | }; | ||
30 | |||
31 | static int regmap_mmio_gather_write(void *context, | ||
32 | const void *reg, size_t reg_size, | ||
33 | const void *val, size_t val_size) | ||
34 | { | ||
35 | struct regmap_mmio_context *ctx = context; | ||
36 | u32 offset; | ||
37 | |||
38 | BUG_ON(reg_size != 4); | ||
39 | |||
40 | offset = be32_to_cpup(reg); | ||
41 | |||
42 | while (val_size) { | ||
43 | switch (ctx->val_bytes) { | ||
44 | case 1: | ||
45 | writeb(*(u8 *)val, ctx->regs + offset); | ||
46 | break; | ||
47 | case 2: | ||
48 | writew(be16_to_cpup(val), ctx->regs + offset); | ||
49 | break; | ||
50 | case 4: | ||
51 | writel(be32_to_cpup(val), ctx->regs + offset); | ||
52 | break; | ||
53 | #ifdef CONFIG_64BIT | ||
54 | case 8: | ||
55 | writeq(be64_to_cpup(val), ctx->regs + offset); | ||
56 | break; | ||
57 | #endif | ||
58 | default: | ||
59 | /* Should be caught by regmap_mmio_check_config */ | ||
60 | BUG(); | ||
61 | } | ||
62 | val_size -= ctx->val_bytes; | ||
63 | val += ctx->val_bytes; | ||
64 | offset += ctx->val_bytes; | ||
65 | } | ||
66 | |||
67 | return 0; | ||
68 | } | ||
69 | |||
70 | static int regmap_mmio_write(void *context, const void *data, size_t count) | ||
71 | { | ||
72 | BUG_ON(count < 4); | ||
73 | |||
74 | return regmap_mmio_gather_write(context, data, 4, data + 4, count - 4); | ||
75 | } | ||
76 | |||
77 | static int regmap_mmio_read(void *context, | ||
78 | const void *reg, size_t reg_size, | ||
79 | void *val, size_t val_size) | ||
80 | { | ||
81 | struct regmap_mmio_context *ctx = context; | ||
82 | u32 offset; | ||
83 | |||
84 | BUG_ON(reg_size != 4); | ||
85 | |||
86 | offset = be32_to_cpup(reg); | ||
87 | |||
88 | while (val_size) { | ||
89 | switch (ctx->val_bytes) { | ||
90 | case 1: | ||
91 | *(u8 *)val = readb(ctx->regs + offset); | ||
92 | break; | ||
93 | case 2: | ||
94 | *(u16 *)val = cpu_to_be16(readw(ctx->regs + offset)); | ||
95 | break; | ||
96 | case 4: | ||
97 | *(u32 *)val = cpu_to_be32(readl(ctx->regs + offset)); | ||
98 | break; | ||
99 | #ifdef CONFIG_64BIT | ||
100 | case 8: | ||
101 | *(u64 *)val = cpu_to_be32(readq(ctx->regs + offset)); | ||
102 | break; | ||
103 | #endif | ||
104 | default: | ||
105 | /* Should be caught by regmap_mmio_check_config */ | ||
106 | BUG(); | ||
107 | } | ||
108 | val_size -= ctx->val_bytes; | ||
109 | val += ctx->val_bytes; | ||
110 | offset += ctx->val_bytes; | ||
111 | } | ||
112 | |||
113 | return 0; | ||
114 | } | ||
115 | |||
116 | static void regmap_mmio_free_context(void *context) | ||
117 | { | ||
118 | kfree(context); | ||
119 | } | ||
120 | |||
121 | static struct regmap_bus regmap_mmio = { | ||
122 | .fast_io = true, | ||
123 | .write = regmap_mmio_write, | ||
124 | .gather_write = regmap_mmio_gather_write, | ||
125 | .read = regmap_mmio_read, | ||
126 | .free_context = regmap_mmio_free_context, | ||
127 | }; | ||
128 | |||
129 | struct regmap_mmio_context *regmap_mmio_gen_context(void __iomem *regs, | ||
130 | const struct regmap_config *config) | ||
131 | { | ||
132 | struct regmap_mmio_context *ctx; | ||
133 | |||
134 | if (config->reg_bits != 32) | ||
135 | return ERR_PTR(-EINVAL); | ||
136 | |||
137 | if (config->pad_bits) | ||
138 | return ERR_PTR(-EINVAL); | ||
139 | |||
140 | switch (config->val_bits) { | ||
141 | case 8: | ||
142 | case 16: | ||
143 | case 32: | ||
144 | #ifdef CONFIG_64BIT | ||
145 | case 64: | ||
146 | #endif | ||
147 | break; | ||
148 | default: | ||
149 | return ERR_PTR(-EINVAL); | ||
150 | } | ||
151 | |||
152 | ctx = kzalloc(GFP_KERNEL, sizeof(*ctx)); | ||
153 | if (!ctx) | ||
154 | return ERR_PTR(-ENOMEM); | ||
155 | |||
156 | ctx->regs = regs; | ||
157 | ctx->val_bytes = config->val_bits / 8; | ||
158 | |||
159 | return ctx; | ||
160 | } | ||
161 | |||
162 | /** | ||
163 | * regmap_init_mmio(): Initialise register map | ||
164 | * | ||
165 | * @dev: Device that will be interacted with | ||
166 | * @regs: Pointer to memory-mapped IO region | ||
167 | * @config: Configuration for register map | ||
168 | * | ||
169 | * The return value will be an ERR_PTR() on error or a valid pointer to | ||
170 | * a struct regmap. | ||
171 | */ | ||
172 | struct regmap *regmap_init_mmio(struct device *dev, | ||
173 | void __iomem *regs, | ||
174 | const struct regmap_config *config) | ||
175 | { | ||
176 | struct regmap_mmio_context *ctx; | ||
177 | |||
178 | ctx = regmap_mmio_gen_context(regs, config); | ||
179 | if (IS_ERR(ctx)) | ||
180 | return ERR_CAST(ctx); | ||
181 | |||
182 | return regmap_init(dev, ®map_mmio, ctx, config); | ||
183 | } | ||
184 | EXPORT_SYMBOL_GPL(regmap_init_mmio); | ||
185 | |||
186 | /** | ||
187 | * devm_regmap_init_mmio(): Initialise managed register map | ||
188 | * | ||
189 | * @dev: Device that will be interacted with | ||
190 | * @regs: Pointer to memory-mapped IO region | ||
191 | * @config: Configuration for register map | ||
192 | * | ||
193 | * The return value will be an ERR_PTR() on error or a valid pointer | ||
194 | * to a struct regmap. The regmap will be automatically freed by the | ||
195 | * device management code. | ||
196 | */ | ||
197 | struct regmap *devm_regmap_init_mmio(struct device *dev, | ||
198 | void __iomem *regs, | ||
199 | const struct regmap_config *config) | ||
200 | { | ||
201 | struct regmap_mmio_context *ctx; | ||
202 | |||
203 | ctx = regmap_mmio_gen_context(regs, config); | ||
204 | if (IS_ERR(ctx)) | ||
205 | return ERR_CAST(ctx); | ||
206 | |||
207 | return devm_regmap_init(dev, ®map_mmio, ctx, config); | ||
208 | } | ||
209 | EXPORT_SYMBOL_GPL(devm_regmap_init_mmio); | ||
210 | |||
211 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/base/regmap/regmap-spi.c b/drivers/base/regmap/regmap-spi.c index 7c0c35a39c33..ffa46a92ad33 100644 --- a/drivers/base/regmap/regmap-spi.c +++ b/drivers/base/regmap/regmap-spi.c | |||
@@ -15,17 +15,19 @@ | |||
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | 17 | ||
18 | static int regmap_spi_write(struct device *dev, const void *data, size_t count) | 18 | static int regmap_spi_write(void *context, const void *data, size_t count) |
19 | { | 19 | { |
20 | struct device *dev = context; | ||
20 | struct spi_device *spi = to_spi_device(dev); | 21 | struct spi_device *spi = to_spi_device(dev); |
21 | 22 | ||
22 | return spi_write(spi, data, count); | 23 | return spi_write(spi, data, count); |
23 | } | 24 | } |
24 | 25 | ||
25 | static int regmap_spi_gather_write(struct device *dev, | 26 | static int regmap_spi_gather_write(void *context, |
26 | const void *reg, size_t reg_len, | 27 | const void *reg, size_t reg_len, |
27 | const void *val, size_t val_len) | 28 | const void *val, size_t val_len) |
28 | { | 29 | { |
30 | struct device *dev = context; | ||
29 | struct spi_device *spi = to_spi_device(dev); | 31 | struct spi_device *spi = to_spi_device(dev); |
30 | struct spi_message m; | 32 | struct spi_message m; |
31 | struct spi_transfer t[2] = { { .tx_buf = reg, .len = reg_len, }, | 33 | struct spi_transfer t[2] = { { .tx_buf = reg, .len = reg_len, }, |
@@ -38,10 +40,11 @@ static int regmap_spi_gather_write(struct device *dev, | |||
38 | return spi_sync(spi, &m); | 40 | return spi_sync(spi, &m); |
39 | } | 41 | } |
40 | 42 | ||
41 | static int regmap_spi_read(struct device *dev, | 43 | static int regmap_spi_read(void *context, |
42 | const void *reg, size_t reg_size, | 44 | const void *reg, size_t reg_size, |
43 | void *val, size_t val_size) | 45 | void *val, size_t val_size) |
44 | { | 46 | { |
47 | struct device *dev = context; | ||
45 | struct spi_device *spi = to_spi_device(dev); | 48 | struct spi_device *spi = to_spi_device(dev); |
46 | 49 | ||
47 | return spi_write_then_read(spi, reg, reg_size, val, val_size); | 50 | return spi_write_then_read(spi, reg, reg_size, val, val_size); |
@@ -66,7 +69,7 @@ static struct regmap_bus regmap_spi = { | |||
66 | struct regmap *regmap_init_spi(struct spi_device *spi, | 69 | struct regmap *regmap_init_spi(struct spi_device *spi, |
67 | const struct regmap_config *config) | 70 | const struct regmap_config *config) |
68 | { | 71 | { |
69 | return regmap_init(&spi->dev, ®map_spi, config); | 72 | return regmap_init(&spi->dev, ®map_spi, &spi->dev, config); |
70 | } | 73 | } |
71 | EXPORT_SYMBOL_GPL(regmap_init_spi); | 74 | EXPORT_SYMBOL_GPL(regmap_init_spi); |
72 | 75 | ||
@@ -83,7 +86,7 @@ EXPORT_SYMBOL_GPL(regmap_init_spi); | |||
83 | struct regmap *devm_regmap_init_spi(struct spi_device *spi, | 86 | struct regmap *devm_regmap_init_spi(struct spi_device *spi, |
84 | const struct regmap_config *config) | 87 | const struct regmap_config *config) |
85 | { | 88 | { |
86 | return devm_regmap_init(&spi->dev, ®map_spi, config); | 89 | return devm_regmap_init(&spi->dev, ®map_spi, &spi->dev, config); |
87 | } | 90 | } |
88 | EXPORT_SYMBOL_GPL(devm_regmap_init_spi); | 91 | EXPORT_SYMBOL_GPL(devm_regmap_init_spi); |
89 | 92 | ||
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index 7a3f535e481c..40f910162781 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c | |||
@@ -112,25 +112,36 @@ static void regmap_format_10_14_write(struct regmap *map, | |||
112 | out[0] = reg >> 2; | 112 | out[0] = reg >> 2; |
113 | } | 113 | } |
114 | 114 | ||
115 | static void regmap_format_8(void *buf, unsigned int val) | 115 | static void regmap_format_8(void *buf, unsigned int val, unsigned int shift) |
116 | { | 116 | { |
117 | u8 *b = buf; | 117 | u8 *b = buf; |
118 | 118 | ||
119 | b[0] = val; | 119 | b[0] = val << shift; |
120 | } | 120 | } |
121 | 121 | ||
122 | static void regmap_format_16(void *buf, unsigned int val) | 122 | static void regmap_format_16(void *buf, unsigned int val, unsigned int shift) |
123 | { | 123 | { |
124 | __be16 *b = buf; | 124 | __be16 *b = buf; |
125 | 125 | ||
126 | b[0] = cpu_to_be16(val); | 126 | b[0] = cpu_to_be16(val << shift); |
127 | } | 127 | } |
128 | 128 | ||
129 | static void regmap_format_32(void *buf, unsigned int val) | 129 | static void regmap_format_24(void *buf, unsigned int val, unsigned int shift) |
130 | { | ||
131 | u8 *b = buf; | ||
132 | |||
133 | val <<= shift; | ||
134 | |||
135 | b[0] = val >> 16; | ||
136 | b[1] = val >> 8; | ||
137 | b[2] = val; | ||
138 | } | ||
139 | |||
140 | static void regmap_format_32(void *buf, unsigned int val, unsigned int shift) | ||
130 | { | 141 | { |
131 | __be32 *b = buf; | 142 | __be32 *b = buf; |
132 | 143 | ||
133 | b[0] = cpu_to_be32(val); | 144 | b[0] = cpu_to_be32(val << shift); |
134 | } | 145 | } |
135 | 146 | ||
136 | static unsigned int regmap_parse_8(void *buf) | 147 | static unsigned int regmap_parse_8(void *buf) |
@@ -149,6 +160,16 @@ static unsigned int regmap_parse_16(void *buf) | |||
149 | return b[0]; | 160 | return b[0]; |
150 | } | 161 | } |
151 | 162 | ||
163 | static unsigned int regmap_parse_24(void *buf) | ||
164 | { | ||
165 | u8 *b = buf; | ||
166 | unsigned int ret = b[2]; | ||
167 | ret |= ((unsigned int)b[1]) << 8; | ||
168 | ret |= ((unsigned int)b[0]) << 16; | ||
169 | |||
170 | return ret; | ||
171 | } | ||
172 | |||
152 | static unsigned int regmap_parse_32(void *buf) | 173 | static unsigned int regmap_parse_32(void *buf) |
153 | { | 174 | { |
154 | __be32 *b = buf; | 175 | __be32 *b = buf; |
@@ -158,11 +179,32 @@ static unsigned int regmap_parse_32(void *buf) | |||
158 | return b[0]; | 179 | return b[0]; |
159 | } | 180 | } |
160 | 181 | ||
182 | static void regmap_lock_mutex(struct regmap *map) | ||
183 | { | ||
184 | mutex_lock(&map->mutex); | ||
185 | } | ||
186 | |||
187 | static void regmap_unlock_mutex(struct regmap *map) | ||
188 | { | ||
189 | mutex_unlock(&map->mutex); | ||
190 | } | ||
191 | |||
192 | static void regmap_lock_spinlock(struct regmap *map) | ||
193 | { | ||
194 | spin_lock(&map->spinlock); | ||
195 | } | ||
196 | |||
197 | static void regmap_unlock_spinlock(struct regmap *map) | ||
198 | { | ||
199 | spin_unlock(&map->spinlock); | ||
200 | } | ||
201 | |||
161 | /** | 202 | /** |
162 | * regmap_init(): Initialise register map | 203 | * regmap_init(): Initialise register map |
163 | * | 204 | * |
164 | * @dev: Device that will be interacted with | 205 | * @dev: Device that will be interacted with |
165 | * @bus: Bus-specific callbacks to use with device | 206 | * @bus: Bus-specific callbacks to use with device |
207 | * @bus_context: Data passed to bus-specific callbacks | ||
166 | * @config: Configuration for register map | 208 | * @config: Configuration for register map |
167 | * | 209 | * |
168 | * The return value will be an ERR_PTR() on error or a valid pointer to | 210 | * The return value will be an ERR_PTR() on error or a valid pointer to |
@@ -171,6 +213,7 @@ static unsigned int regmap_parse_32(void *buf) | |||
171 | */ | 213 | */ |
172 | struct regmap *regmap_init(struct device *dev, | 214 | struct regmap *regmap_init(struct device *dev, |
173 | const struct regmap_bus *bus, | 215 | const struct regmap_bus *bus, |
216 | void *bus_context, | ||
174 | const struct regmap_config *config) | 217 | const struct regmap_config *config) |
175 | { | 218 | { |
176 | struct regmap *map; | 219 | struct regmap *map; |
@@ -185,14 +228,24 @@ struct regmap *regmap_init(struct device *dev, | |||
185 | goto err; | 228 | goto err; |
186 | } | 229 | } |
187 | 230 | ||
188 | mutex_init(&map->lock); | 231 | if (bus->fast_io) { |
232 | spin_lock_init(&map->spinlock); | ||
233 | map->lock = regmap_lock_spinlock; | ||
234 | map->unlock = regmap_unlock_spinlock; | ||
235 | } else { | ||
236 | mutex_init(&map->mutex); | ||
237 | map->lock = regmap_lock_mutex; | ||
238 | map->unlock = regmap_unlock_mutex; | ||
239 | } | ||
189 | map->format.buf_size = (config->reg_bits + config->val_bits) / 8; | 240 | map->format.buf_size = (config->reg_bits + config->val_bits) / 8; |
190 | map->format.reg_bytes = DIV_ROUND_UP(config->reg_bits, 8); | 241 | map->format.reg_bytes = DIV_ROUND_UP(config->reg_bits, 8); |
191 | map->format.pad_bytes = config->pad_bits / 8; | 242 | map->format.pad_bytes = config->pad_bits / 8; |
192 | map->format.val_bytes = DIV_ROUND_UP(config->val_bits, 8); | 243 | map->format.val_bytes = DIV_ROUND_UP(config->val_bits, 8); |
193 | map->format.buf_size += map->format.pad_bytes; | 244 | map->format.buf_size += map->format.pad_bytes; |
245 | map->reg_shift = config->pad_bits % 8; | ||
194 | map->dev = dev; | 246 | map->dev = dev; |
195 | map->bus = bus; | 247 | map->bus = bus; |
248 | map->bus_context = bus_context; | ||
196 | map->max_register = config->max_register; | 249 | map->max_register = config->max_register; |
197 | map->writeable_reg = config->writeable_reg; | 250 | map->writeable_reg = config->writeable_reg; |
198 | map->readable_reg = config->readable_reg; | 251 | map->readable_reg = config->readable_reg; |
@@ -207,7 +260,7 @@ struct regmap *regmap_init(struct device *dev, | |||
207 | map->read_flag_mask = bus->read_flag_mask; | 260 | map->read_flag_mask = bus->read_flag_mask; |
208 | } | 261 | } |
209 | 262 | ||
210 | switch (config->reg_bits) { | 263 | switch (config->reg_bits + map->reg_shift) { |
211 | case 2: | 264 | case 2: |
212 | switch (config->val_bits) { | 265 | switch (config->val_bits) { |
213 | case 6: | 266 | case 6: |
@@ -273,6 +326,10 @@ struct regmap *regmap_init(struct device *dev, | |||
273 | map->format.format_val = regmap_format_16; | 326 | map->format.format_val = regmap_format_16; |
274 | map->format.parse_val = regmap_parse_16; | 327 | map->format.parse_val = regmap_parse_16; |
275 | break; | 328 | break; |
329 | case 24: | ||
330 | map->format.format_val = regmap_format_24; | ||
331 | map->format.parse_val = regmap_parse_24; | ||
332 | break; | ||
276 | case 32: | 333 | case 32: |
277 | map->format.format_val = regmap_format_32; | 334 | map->format.format_val = regmap_format_32; |
278 | map->format.parse_val = regmap_parse_32; | 335 | map->format.parse_val = regmap_parse_32; |
@@ -289,7 +346,7 @@ struct regmap *regmap_init(struct device *dev, | |||
289 | goto err_map; | 346 | goto err_map; |
290 | } | 347 | } |
291 | 348 | ||
292 | regmap_debugfs_init(map); | 349 | regmap_debugfs_init(map, config->name); |
293 | 350 | ||
294 | ret = regcache_init(map, config); | 351 | ret = regcache_init(map, config); |
295 | if (ret < 0) | 352 | if (ret < 0) |
@@ -316,6 +373,7 @@ static void devm_regmap_release(struct device *dev, void *res) | |||
316 | * | 373 | * |
317 | * @dev: Device that will be interacted with | 374 | * @dev: Device that will be interacted with |
318 | * @bus: Bus-specific callbacks to use with device | 375 | * @bus: Bus-specific callbacks to use with device |
376 | * @bus_context: Data passed to bus-specific callbacks | ||
319 | * @config: Configuration for register map | 377 | * @config: Configuration for register map |
320 | * | 378 | * |
321 | * The return value will be an ERR_PTR() on error or a valid pointer | 379 | * The return value will be an ERR_PTR() on error or a valid pointer |
@@ -325,6 +383,7 @@ static void devm_regmap_release(struct device *dev, void *res) | |||
325 | */ | 383 | */ |
326 | struct regmap *devm_regmap_init(struct device *dev, | 384 | struct regmap *devm_regmap_init(struct device *dev, |
327 | const struct regmap_bus *bus, | 385 | const struct regmap_bus *bus, |
386 | void *bus_context, | ||
328 | const struct regmap_config *config) | 387 | const struct regmap_config *config) |
329 | { | 388 | { |
330 | struct regmap **ptr, *regmap; | 389 | struct regmap **ptr, *regmap; |
@@ -333,7 +392,7 @@ struct regmap *devm_regmap_init(struct device *dev, | |||
333 | if (!ptr) | 392 | if (!ptr) |
334 | return ERR_PTR(-ENOMEM); | 393 | return ERR_PTR(-ENOMEM); |
335 | 394 | ||
336 | regmap = regmap_init(dev, bus, config); | 395 | regmap = regmap_init(dev, bus, bus_context, config); |
337 | if (!IS_ERR(regmap)) { | 396 | if (!IS_ERR(regmap)) { |
338 | *ptr = regmap; | 397 | *ptr = regmap; |
339 | devres_add(dev, ptr); | 398 | devres_add(dev, ptr); |
@@ -360,7 +419,7 @@ int regmap_reinit_cache(struct regmap *map, const struct regmap_config *config) | |||
360 | { | 419 | { |
361 | int ret; | 420 | int ret; |
362 | 421 | ||
363 | mutex_lock(&map->lock); | 422 | map->lock(map); |
364 | 423 | ||
365 | regcache_exit(map); | 424 | regcache_exit(map); |
366 | regmap_debugfs_exit(map); | 425 | regmap_debugfs_exit(map); |
@@ -372,14 +431,14 @@ int regmap_reinit_cache(struct regmap *map, const struct regmap_config *config) | |||
372 | map->precious_reg = config->precious_reg; | 431 | map->precious_reg = config->precious_reg; |
373 | map->cache_type = config->cache_type; | 432 | map->cache_type = config->cache_type; |
374 | 433 | ||
375 | regmap_debugfs_init(map); | 434 | regmap_debugfs_init(map, config->name); |
376 | 435 | ||
377 | map->cache_bypass = false; | 436 | map->cache_bypass = false; |
378 | map->cache_only = false; | 437 | map->cache_only = false; |
379 | 438 | ||
380 | ret = regcache_init(map, config); | 439 | ret = regcache_init(map, config); |
381 | 440 | ||
382 | mutex_unlock(&map->lock); | 441 | map->unlock(map); |
383 | 442 | ||
384 | return ret; | 443 | return ret; |
385 | } | 444 | } |
@@ -391,6 +450,8 @@ void regmap_exit(struct regmap *map) | |||
391 | { | 450 | { |
392 | regcache_exit(map); | 451 | regcache_exit(map); |
393 | regmap_debugfs_exit(map); | 452 | regmap_debugfs_exit(map); |
453 | if (map->bus->free_context) | ||
454 | map->bus->free_context(map->bus_context); | ||
394 | kfree(map->work_buf); | 455 | kfree(map->work_buf); |
395 | kfree(map); | 456 | kfree(map); |
396 | } | 457 | } |
@@ -431,7 +492,7 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg, | |||
431 | } | 492 | } |
432 | } | 493 | } |
433 | 494 | ||
434 | map->format.format_reg(map->work_buf, reg); | 495 | map->format.format_reg(map->work_buf, reg, map->reg_shift); |
435 | 496 | ||
436 | u8[0] |= map->write_flag_mask; | 497 | u8[0] |= map->write_flag_mask; |
437 | 498 | ||
@@ -444,12 +505,12 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg, | |||
444 | */ | 505 | */ |
445 | if (val == (map->work_buf + map->format.pad_bytes + | 506 | if (val == (map->work_buf + map->format.pad_bytes + |
446 | map->format.reg_bytes)) | 507 | map->format.reg_bytes)) |
447 | ret = map->bus->write(map->dev, map->work_buf, | 508 | ret = map->bus->write(map->bus_context, map->work_buf, |
448 | map->format.reg_bytes + | 509 | map->format.reg_bytes + |
449 | map->format.pad_bytes + | 510 | map->format.pad_bytes + |
450 | val_len); | 511 | val_len); |
451 | else if (map->bus->gather_write) | 512 | else if (map->bus->gather_write) |
452 | ret = map->bus->gather_write(map->dev, map->work_buf, | 513 | ret = map->bus->gather_write(map->bus_context, map->work_buf, |
453 | map->format.reg_bytes + | 514 | map->format.reg_bytes + |
454 | map->format.pad_bytes, | 515 | map->format.pad_bytes, |
455 | val, val_len); | 516 | val, val_len); |
@@ -464,7 +525,7 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg, | |||
464 | memcpy(buf, map->work_buf, map->format.reg_bytes); | 525 | memcpy(buf, map->work_buf, map->format.reg_bytes); |
465 | memcpy(buf + map->format.reg_bytes + map->format.pad_bytes, | 526 | memcpy(buf + map->format.reg_bytes + map->format.pad_bytes, |
466 | val, val_len); | 527 | val, val_len); |
467 | ret = map->bus->write(map->dev, buf, len); | 528 | ret = map->bus->write(map->bus_context, buf, len); |
468 | 529 | ||
469 | kfree(buf); | 530 | kfree(buf); |
470 | } | 531 | } |
@@ -498,7 +559,7 @@ int _regmap_write(struct regmap *map, unsigned int reg, | |||
498 | 559 | ||
499 | trace_regmap_hw_write_start(map->dev, reg, 1); | 560 | trace_regmap_hw_write_start(map->dev, reg, 1); |
500 | 561 | ||
501 | ret = map->bus->write(map->dev, map->work_buf, | 562 | ret = map->bus->write(map->bus_context, map->work_buf, |
502 | map->format.buf_size); | 563 | map->format.buf_size); |
503 | 564 | ||
504 | trace_regmap_hw_write_done(map->dev, reg, 1); | 565 | trace_regmap_hw_write_done(map->dev, reg, 1); |
@@ -506,7 +567,7 @@ int _regmap_write(struct regmap *map, unsigned int reg, | |||
506 | return ret; | 567 | return ret; |
507 | } else { | 568 | } else { |
508 | map->format.format_val(map->work_buf + map->format.reg_bytes | 569 | map->format.format_val(map->work_buf + map->format.reg_bytes |
509 | + map->format.pad_bytes, val); | 570 | + map->format.pad_bytes, val, 0); |
510 | return _regmap_raw_write(map, reg, | 571 | return _regmap_raw_write(map, reg, |
511 | map->work_buf + | 572 | map->work_buf + |
512 | map->format.reg_bytes + | 573 | map->format.reg_bytes + |
@@ -529,11 +590,11 @@ int regmap_write(struct regmap *map, unsigned int reg, unsigned int val) | |||
529 | { | 590 | { |
530 | int ret; | 591 | int ret; |
531 | 592 | ||
532 | mutex_lock(&map->lock); | 593 | map->lock(map); |
533 | 594 | ||
534 | ret = _regmap_write(map, reg, val); | 595 | ret = _regmap_write(map, reg, val); |
535 | 596 | ||
536 | mutex_unlock(&map->lock); | 597 | map->unlock(map); |
537 | 598 | ||
538 | return ret; | 599 | return ret; |
539 | } | 600 | } |
@@ -560,11 +621,14 @@ int regmap_raw_write(struct regmap *map, unsigned int reg, | |||
560 | { | 621 | { |
561 | int ret; | 622 | int ret; |
562 | 623 | ||
563 | mutex_lock(&map->lock); | 624 | if (val_len % map->format.val_bytes) |
625 | return -EINVAL; | ||
626 | |||
627 | map->lock(map); | ||
564 | 628 | ||
565 | ret = _regmap_raw_write(map, reg, val, val_len); | 629 | ret = _regmap_raw_write(map, reg, val, val_len); |
566 | 630 | ||
567 | mutex_unlock(&map->lock); | 631 | map->unlock(map); |
568 | 632 | ||
569 | return ret; | 633 | return ret; |
570 | } | 634 | } |
@@ -594,7 +658,7 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val, | |||
594 | if (!map->format.parse_val) | 658 | if (!map->format.parse_val) |
595 | return -EINVAL; | 659 | return -EINVAL; |
596 | 660 | ||
597 | mutex_lock(&map->lock); | 661 | map->lock(map); |
598 | 662 | ||
599 | /* No formatting is require if val_byte is 1 */ | 663 | /* No formatting is require if val_byte is 1 */ |
600 | if (val_bytes == 1) { | 664 | if (val_bytes == 1) { |
@@ -615,7 +679,7 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val, | |||
615 | kfree(wval); | 679 | kfree(wval); |
616 | 680 | ||
617 | out: | 681 | out: |
618 | mutex_unlock(&map->lock); | 682 | map->unlock(map); |
619 | return ret; | 683 | return ret; |
620 | } | 684 | } |
621 | EXPORT_SYMBOL_GPL(regmap_bulk_write); | 685 | EXPORT_SYMBOL_GPL(regmap_bulk_write); |
@@ -626,7 +690,7 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val, | |||
626 | u8 *u8 = map->work_buf; | 690 | u8 *u8 = map->work_buf; |
627 | int ret; | 691 | int ret; |
628 | 692 | ||
629 | map->format.format_reg(map->work_buf, reg); | 693 | map->format.format_reg(map->work_buf, reg, map->reg_shift); |
630 | 694 | ||
631 | /* | 695 | /* |
632 | * Some buses or devices flag reads by setting the high bits in the | 696 | * Some buses or devices flag reads by setting the high bits in the |
@@ -639,7 +703,7 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val, | |||
639 | trace_regmap_hw_read_start(map->dev, reg, | 703 | trace_regmap_hw_read_start(map->dev, reg, |
640 | val_len / map->format.val_bytes); | 704 | val_len / map->format.val_bytes); |
641 | 705 | ||
642 | ret = map->bus->read(map->dev, map->work_buf, | 706 | ret = map->bus->read(map->bus_context, map->work_buf, |
643 | map->format.reg_bytes + map->format.pad_bytes, | 707 | map->format.reg_bytes + map->format.pad_bytes, |
644 | val, val_len); | 708 | val, val_len); |
645 | 709 | ||
@@ -689,11 +753,11 @@ int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val) | |||
689 | { | 753 | { |
690 | int ret; | 754 | int ret; |
691 | 755 | ||
692 | mutex_lock(&map->lock); | 756 | map->lock(map); |
693 | 757 | ||
694 | ret = _regmap_read(map, reg, val); | 758 | ret = _regmap_read(map, reg, val); |
695 | 759 | ||
696 | mutex_unlock(&map->lock); | 760 | map->unlock(map); |
697 | 761 | ||
698 | return ret; | 762 | return ret; |
699 | } | 763 | } |
@@ -718,7 +782,10 @@ int regmap_raw_read(struct regmap *map, unsigned int reg, void *val, | |||
718 | unsigned int v; | 782 | unsigned int v; |
719 | int ret, i; | 783 | int ret, i; |
720 | 784 | ||
721 | mutex_lock(&map->lock); | 785 | if (val_len % map->format.val_bytes) |
786 | return -EINVAL; | ||
787 | |||
788 | map->lock(map); | ||
722 | 789 | ||
723 | if (regmap_volatile_range(map, reg, val_count) || map->cache_bypass || | 790 | if (regmap_volatile_range(map, reg, val_count) || map->cache_bypass || |
724 | map->cache_type == REGCACHE_NONE) { | 791 | map->cache_type == REGCACHE_NONE) { |
@@ -734,12 +801,12 @@ int regmap_raw_read(struct regmap *map, unsigned int reg, void *val, | |||
734 | if (ret != 0) | 801 | if (ret != 0) |
735 | goto out; | 802 | goto out; |
736 | 803 | ||
737 | map->format.format_val(val + (i * val_bytes), v); | 804 | map->format.format_val(val + (i * val_bytes), v, 0); |
738 | } | 805 | } |
739 | } | 806 | } |
740 | 807 | ||
741 | out: | 808 | out: |
742 | mutex_unlock(&map->lock); | 809 | map->unlock(map); |
743 | 810 | ||
744 | return ret; | 811 | return ret; |
745 | } | 812 | } |
@@ -792,7 +859,7 @@ static int _regmap_update_bits(struct regmap *map, unsigned int reg, | |||
792 | int ret; | 859 | int ret; |
793 | unsigned int tmp, orig; | 860 | unsigned int tmp, orig; |
794 | 861 | ||
795 | mutex_lock(&map->lock); | 862 | map->lock(map); |
796 | 863 | ||
797 | ret = _regmap_read(map, reg, &orig); | 864 | ret = _regmap_read(map, reg, &orig); |
798 | if (ret != 0) | 865 | if (ret != 0) |
@@ -809,7 +876,7 @@ static int _regmap_update_bits(struct regmap *map, unsigned int reg, | |||
809 | } | 876 | } |
810 | 877 | ||
811 | out: | 878 | out: |
812 | mutex_unlock(&map->lock); | 879 | map->unlock(map); |
813 | 880 | ||
814 | return ret; | 881 | return ret; |
815 | } | 882 | } |
@@ -876,7 +943,7 @@ int regmap_register_patch(struct regmap *map, const struct reg_default *regs, | |||
876 | if (map->patch) | 943 | if (map->patch) |
877 | return -EBUSY; | 944 | return -EBUSY; |
878 | 945 | ||
879 | mutex_lock(&map->lock); | 946 | map->lock(map); |
880 | 947 | ||
881 | bypass = map->cache_bypass; | 948 | bypass = map->cache_bypass; |
882 | 949 | ||
@@ -904,7 +971,7 @@ int regmap_register_patch(struct regmap *map, const struct reg_default *regs, | |||
904 | out: | 971 | out: |
905 | map->cache_bypass = bypass; | 972 | map->cache_bypass = bypass; |
906 | 973 | ||
907 | mutex_unlock(&map->lock); | 974 | map->unlock(map); |
908 | 975 | ||
909 | return ret; | 976 | return ret; |
910 | } | 977 | } |