diff options
| -rw-r--r-- | drivers/base/regmap/internal.h | 18 | ||||
| -rw-r--r-- | drivers/base/regmap/regmap-spi.c | 54 | ||||
| -rw-r--r-- | drivers/base/regmap/regmap.c | 301 | ||||
| -rw-r--r-- | include/linux/regmap.h | 28 |
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 | ||
| 20 | struct regmap; | 21 | struct regmap; |
| 21 | struct regcache_ops; | 22 | struct 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 | ||
| 43 | struct regmap_async { | ||
| 44 | struct list_head list; | ||
| 45 | struct work_struct cleanup; | ||
| 46 | struct regmap *map; | ||
| 47 | void *work_buf; | ||
| 48 | }; | ||
| 49 | |||
| 42 | struct regmap { | 50 | struct 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); |
| 176 | int regcache_lookup_reg(struct regmap *map, unsigned int reg); | 192 | int regcache_lookup_reg(struct regmap *map, unsigned int reg); |
| 177 | 193 | ||
| 194 | void regmap_async_complete_cb(struct regmap_async *async, int ret); | ||
| 195 | |||
| 178 | extern struct regcache_ops regcache_rbtree_ops; | 196 | extern struct regcache_ops regcache_rbtree_ops; |
| 179 | extern struct regcache_ops regcache_lzo_ops; | 197 | extern 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 | |||
| 20 | struct regmap_async_spi { | ||
| 21 | struct regmap_async core; | ||
| 22 | struct spi_message m; | ||
| 23 | struct spi_transfer t[2]; | ||
| 24 | }; | ||
| 25 | |||
| 26 | static 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 | |||
| 18 | static int regmap_spi_write(void *context, const void *data, size_t count) | 33 | static 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 | ||
| 58 | static 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 | |||
| 84 | static 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 | |||
| 43 | static int regmap_spi_read(void *context, | 95 | static 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, | |||
| 53 | static struct regmap_bus regmap_spi = { | 105 | static 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 | ||
| 38 | static int _regmap_bus_read(void *context, unsigned int reg, | ||
| 39 | unsigned int *val); | ||
| 40 | static int _regmap_bus_formatted_write(void *context, unsigned int reg, | ||
| 41 | unsigned int val); | ||
| 42 | static int _regmap_bus_raw_write(void *context, unsigned int reg, | ||
| 43 | unsigned int val); | ||
| 44 | |||
| 45 | static 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 | |||
| 37 | bool regmap_reg_in_ranges(unsigned int reg, | 54 | bool 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); | ||
