aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/base/regmap/internal.h18
-rw-r--r--drivers/base/regmap/regmap-spi.c54
-rw-r--r--drivers/base/regmap/regmap.c301
-rw-r--r--include/linux/regmap.h28
4 files changed, 354 insertions, 47 deletions
diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h
index 401d1919635a..202518641779 100644
--- a/drivers/base/regmap/internal.h
+++ b/drivers/base/regmap/internal.h
@@ -16,6 +16,7 @@
16#include <linux/regmap.h> 16#include <linux/regmap.h>
17#include <linux/fs.h> 17#include <linux/fs.h>
18#include <linux/list.h> 18#include <linux/list.h>
19#include <linux/wait.h>
19 20
20struct regmap; 21struct regmap;
21struct regcache_ops; 22struct regcache_ops;
@@ -39,6 +40,13 @@ struct regmap_format {
39 unsigned int (*parse_val)(void *buf); 40 unsigned int (*parse_val)(void *buf);
40}; 41};
41 42
43struct regmap_async {
44 struct list_head list;
45 struct work_struct cleanup;
46 struct regmap *map;
47 void *work_buf;
48};
49
42struct regmap { 50struct regmap {
43 struct mutex mutex; 51 struct mutex mutex;
44 spinlock_t spinlock; 52 spinlock_t spinlock;
@@ -53,6 +61,11 @@ struct regmap {
53 void *bus_context; 61 void *bus_context;
54 const char *name; 62 const char *name;
55 63
64 spinlock_t async_lock;
65 wait_queue_head_t async_waitq;
66 struct list_head async_list;
67 int async_ret;
68
56#ifdef CONFIG_DEBUG_FS 69#ifdef CONFIG_DEBUG_FS
57 struct dentry *debugfs; 70 struct dentry *debugfs;
58 const char *debugfs_name; 71 const char *debugfs_name;
@@ -74,6 +87,9 @@ struct regmap {
74 const struct regmap_access_table *volatile_table; 87 const struct regmap_access_table *volatile_table;
75 const struct regmap_access_table *precious_table; 88 const struct regmap_access_table *precious_table;
76 89
90 int (*reg_read)(void *context, unsigned int reg, unsigned int *val);
91 int (*reg_write)(void *context, unsigned int reg, unsigned int val);
92
77 u8 read_flag_mask; 93 u8 read_flag_mask;
78 u8 write_flag_mask; 94 u8 write_flag_mask;
79 95
@@ -175,6 +191,8 @@ bool regcache_set_val(void *base, unsigned int idx,
175 unsigned int val, unsigned int word_size); 191 unsigned int val, unsigned int word_size);
176int regcache_lookup_reg(struct regmap *map, unsigned int reg); 192int regcache_lookup_reg(struct regmap *map, unsigned int reg);
177 193
194void regmap_async_complete_cb(struct regmap_async *async, int ret);
195
178extern struct regcache_ops regcache_rbtree_ops; 196extern struct regcache_ops regcache_rbtree_ops;
179extern struct regcache_ops regcache_lzo_ops; 197extern struct regcache_ops regcache_lzo_ops;
180 198
diff --git a/drivers/base/regmap/regmap-spi.c b/drivers/base/regmap/regmap-spi.c
index ffa46a92ad33..4c506bd940f3 100644
--- a/drivers/base/regmap/regmap-spi.c
+++ b/drivers/base/regmap/regmap-spi.c
@@ -15,6 +15,21 @@
15#include <linux/init.h> 15#include <linux/init.h>
16#include <linux/module.h> 16#include <linux/module.h>
17 17
18#include "internal.h"
19
20struct regmap_async_spi {
21 struct regmap_async core;
22 struct spi_message m;
23 struct spi_transfer t[2];
24};
25
26static void regmap_spi_complete(void *data)
27{
28 struct regmap_async_spi *async = data;
29
30 regmap_async_complete_cb(&async->core, async->m.status);
31}
32
18static int regmap_spi_write(void *context, const void *data, size_t count) 33static int regmap_spi_write(void *context, const void *data, size_t count)
19{ 34{
20 struct device *dev = context; 35 struct device *dev = context;
@@ -40,6 +55,43 @@ static int regmap_spi_gather_write(void *context,
40 return spi_sync(spi, &m); 55 return spi_sync(spi, &m);
41} 56}
42 57
58static int regmap_spi_async_write(void *context,
59 const void *reg, size_t reg_len,
60 const void *val, size_t val_len,
61 struct regmap_async *a)
62{
63 struct regmap_async_spi *async = container_of(a,
64 struct regmap_async_spi,
65 core);
66 struct device *dev = context;
67 struct spi_device *spi = to_spi_device(dev);
68
69 async->t[0].tx_buf = reg;
70 async->t[0].len = reg_len;
71 async->t[1].tx_buf = val;
72 async->t[1].len = val_len;
73
74 spi_message_init(&async->m);
75 spi_message_add_tail(&async->t[0], &async->m);
76 spi_message_add_tail(&async->t[1], &async->m);
77
78 async->m.complete = regmap_spi_complete;
79 async->m.context = async;
80
81 return spi_async(spi, &async->m);
82}
83
84static struct regmap_async *regmap_spi_async_alloc(void)
85{
86 struct regmap_async_spi *async_spi;
87
88 async_spi = kzalloc(sizeof(*async_spi), GFP_KERNEL);
89 if (!async_spi)
90 return NULL;
91
92 return &async_spi->core;
93}
94
43static int regmap_spi_read(void *context, 95static int regmap_spi_read(void *context,
44 const void *reg, size_t reg_size, 96 const void *reg, size_t reg_size,
45 void *val, size_t val_size) 97 void *val, size_t val_size)
@@ -53,6 +105,8 @@ static int regmap_spi_read(void *context,
53static struct regmap_bus regmap_spi = { 105static struct regmap_bus regmap_spi = {
54 .write = regmap_spi_write, 106 .write = regmap_spi_write,
55 .gather_write = regmap_spi_gather_write, 107 .gather_write = regmap_spi_gather_write,
108 .async_write = regmap_spi_async_write,
109 .async_alloc = regmap_spi_async_alloc,
56 .read = regmap_spi_read, 110 .read = regmap_spi_read,
57 .read_flag_mask = 0x80, 111 .read_flag_mask = 0x80,
58}; 112};
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index dc19026d28e9..b1d962434cb2 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -16,6 +16,7 @@
16#include <linux/mutex.h> 16#include <linux/mutex.h>
17#include <linux/err.h> 17#include <linux/err.h>
18#include <linux/rbtree.h> 18#include <linux/rbtree.h>
19#include <linux/sched.h>
19 20
20#define CREATE_TRACE_POINTS 21#define CREATE_TRACE_POINTS
21#include <trace/events/regmap.h> 22#include <trace/events/regmap.h>
@@ -34,6 +35,22 @@ static int _regmap_update_bits(struct regmap *map, unsigned int reg,
34 unsigned int mask, unsigned int val, 35 unsigned int mask, unsigned int val,
35 bool *change); 36 bool *change);
36 37
38static int _regmap_bus_read(void *context, unsigned int reg,
39 unsigned int *val);
40static int _regmap_bus_formatted_write(void *context, unsigned int reg,
41 unsigned int val);
42static int _regmap_bus_raw_write(void *context, unsigned int reg,
43 unsigned int val);
44
45static void async_cleanup(struct work_struct *work)
46{
47 struct regmap_async *async = container_of(work, struct regmap_async,
48 cleanup);
49
50 kfree(async->work_buf);
51 kfree(async);
52}
53
37bool regmap_reg_in_ranges(unsigned int reg, 54bool regmap_reg_in_ranges(unsigned int reg,
38 const struct regmap_range *ranges, 55 const struct regmap_range *ranges,
39 unsigned int nranges) 56 unsigned int nranges)
@@ -423,6 +440,10 @@ struct regmap *regmap_init(struct device *dev,
423 map->cache_type = config->cache_type; 440 map->cache_type = config->cache_type;
424 map->name = config->name; 441 map->name = config->name;
425 442
443 spin_lock_init(&map->async_lock);