aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/base/regmap/internal.h15
-rw-r--r--drivers/base/regmap/regmap.c182
-rw-r--r--include/linux/regmap.h28
3 files changed, 215 insertions, 10 deletions
diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h
index 51f057405647..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;
@@ -178,6 +191,8 @@ bool regcache_set_val(void *base, unsigned int idx,
178 unsigned int val, unsigned int word_size); 191 unsigned int val, unsigned int word_size);
179int regcache_lookup_reg(struct regmap *map, unsigned int reg); 192int regcache_lookup_reg(struct regmap *map, unsigned int reg);
180 193
194void regmap_async_complete_cb(struct regmap_async *async, int ret);
195
181extern struct regcache_ops regcache_rbtree_ops; 196extern struct regcache_ops regcache_rbtree_ops;
182extern struct regcache_ops regcache_lzo_ops; 197extern struct regcache_ops regcache_lzo_ops;
183 198
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index 6845a077bd84..e57b7bc035fc 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -41,6 +41,15 @@ static int _regmap_bus_formatted_write(void *context, unsigned int reg,
41static int _regmap_bus_raw_write(void *context, unsigned int reg, 41static int _regmap_bus_raw_write(void *context, unsigned int reg,
42 unsigned int val); 42 unsigned int val);
43 43
44static void async_cleanup(struct work_struct *work)
45{
46 struct regmap_async *async = container_of(work, struct regmap_async,
47 cleanup);
48
49 kfree(async->work_buf);
50 kfree(async);
51}
52
44bool regmap_reg_in_ranges(unsigned int reg, 53bool regmap_reg_in_ranges(unsigned int reg,
45 const struct regmap_range *ranges, 54 const struct regmap_range *ranges,
46 unsigned int nranges) 55 unsigned int nranges)
@@ -430,6 +439,10 @@ struct regmap *regmap_init(struct device *dev,
430 map->cache_type = config->cache_type; 439 map->cache_type = config->cache_type;
431 map->name = config->name; 440 map->name = config->name;
432 441
442 spin_lock_init(&map->async_lock);
443 INIT_LIST_HEAD(&map->async_list);
444 init_waitqueue_head(&map->async_waitq);
445
433 if (config->read_flag_mask || config->write_flag_mask) { 446 if (config->read_flag_mask || config->write_flag_mask) {
434 map->read_flag_mask = config->read_flag_mask; 447 map->read_flag_mask = config->read_flag_mask;
435 map->write_flag_mask = config->write_flag_mask; 448 map->write_flag_mask = config->write_flag_mask;
@@ -884,10 +897,13 @@ static int _regmap_select_page(struct regmap *map, unsigned int *reg,
884} 897}
885 898
886static int _regmap_raw_write(struct regmap *map, unsigned int reg, 899static int _regmap_raw_write(struct regmap *map, unsigned int reg,
887 const void *val, size_t val_len) 900 const void *val, size_t val_len, bool async)
888{ 901{
889 struct regmap_range_node *range; 902 struct regmap_range_node *range;
903 unsigned long flags;
890 u8 *u8 = map->work_buf; 904 u8 *u8 = map->work_buf;
905 void *work_val = map->work_buf + map->format.reg_bytes +
906 map->format.pad_bytes;
891 void *buf; 907 void *buf;
892 int ret = -ENOTSUPP; 908 int ret = -ENOTSUPP;
893 size_t len; 909 size_t len;
@@ -932,7 +948,7 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg,
932 dev_dbg(map->dev, "Writing window %d/%zu\n", 948 dev_dbg(map->dev, "Writing window %d/%zu\n",
933 win_residue, val_len / map->format.val_bytes); 949 win_residue, val_len / map->format.val_bytes);
934 ret = _regmap_raw_write(map, reg, val, win_residue * 950 ret = _regmap_raw_write(map, reg, val, win_residue *
935 map->format.val_bytes); 951 map->format.val_bytes, async);
936 if (ret != 0) 952 if (ret != 0)
937 return ret; 953 return ret;
938 954
@@ -955,6 +971,50 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg,
955 971
956 u8[0] |= map->write_flag_mask; 972 u8[0] |= map->write_flag_mask;
957 973
974 if (async && map->bus->async_write) {
975 struct regmap_async *async = map->bus->async_alloc();
976 if (!async)
977 return -ENOMEM;
978
979 async->work_buf = kzalloc(map->format.buf_size,
980 GFP_KERNEL | GFP_DMA);
981 if (!async->work_buf) {
982 kfree(async);
983 return -ENOMEM;
984 }
985
986 INIT_WORK(&async->cleanup, async_cleanup);
987 async->map = map;
988
989 /* If the caller supplied the value we can use it safely. */
990 memcpy(async->work_buf, map->work_buf, map->format.pad_bytes +
991 map->format.reg_bytes + map->format.val_bytes);
992 if (val == work_val)
993 val = async->work_buf + map->format.pad_bytes +
994 map->format.reg_bytes;
995
996 spin_lock_irqsave(&map->async_lock, flags);
997 list_add_tail(&async->list, &map->async_list);
998 spin_unlock_irqrestore(&map->async_lock, flags);
999
1000 ret = map->bus->async_write(map->bus_context, async->work_buf,
1001 map->format.reg_bytes +
1002 map->format.pad_bytes,
1003 val, val_len, async);
1004
1005 if (ret != 0) {
1006 dev_err(map->dev, "Failed to schedule write: %d\n",
1007 ret);
1008
1009 spin_lock_irqsave(&map->async_lock, flags);
1010 list_del(&async->list);
1011 spin_unlock_irqrestore(&map->async_lock, flags);
1012
1013 kfree(async->work_buf);
1014 kfree(async);
1015 }
1016 }
1017
958 trace_regmap_hw_write_start(map->dev, reg, 1018 trace_regmap_hw_write_start(map->dev, reg,
959 val_len / map->format.val_bytes); 1019 val_len / map->format.val_bytes);
960 1020
@@ -962,8 +1022,7 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg,
962 * send the work_buf directly, otherwise try to do a gather 1022 * send the work_buf directly, otherwise try to do a gather
963 * write. 1023 * write.
964 */ 1024 */
965 if (val == (map->work_buf + map->format.pad_bytes + 1025 if (val == work_val)
966 map->format.reg_bytes))
967 ret = map->bus->write(map->bus_context, map->work_buf, 1026 ret = map->bus->write(map->bus_context, map->work_buf,
968 map->format.reg_bytes + 1027 map->format.reg_bytes +
969 map->format.pad_bytes + 1028 map->format.pad_bytes +
@@ -1036,7 +1095,7 @@ static int _regmap_bus_raw_write(void *context, unsigned int reg,
1036 map->work_buf + 1095 map->work_buf +
1037 map->format.reg_bytes + 1096 map->format.reg_bytes +
1038 map->format.pad_bytes, 1097 map->format.pad_bytes,
1039 map->format.val_bytes); 1098 map->format.val_bytes, false);
1040} 1099}
1041 1100
1042int _regmap_write(struct regmap *map, unsigned int reg, 1101int _regmap_write(struct regmap *map, unsigned int reg,
@@ -1119,7 +1178,7 @@ int regmap_raw_write(struct regmap *map, unsigned int reg,
1119 1178
1120 map->lock(map->lock_arg); 1179 map->lock(map->lock_arg);
1121 1180
1122 ret = _regmap_raw_write(map, reg, val, val_len); 1181 ret = _regmap_raw_write(map, reg, val, val_len, false);
1123 1182
1124 map->unlock(map->lock_arg); 1183 map->unlock(map->lock_arg);
1125 1184
@@ -1175,14 +1234,15 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,
1175 if (map->use_single_rw) { 1234 if (map->use_single_rw) {
1176 for (i = 0; i < val_count; i++) { 1235 for (i = 0; i < val_count; i++) {
1177 ret = regmap_raw_write(map, 1236 ret = regmap_raw_write(map,
1178 reg + (i * map->reg_stride), 1237 reg + (i * map->reg_stride),
1179 val + (i * val_bytes), 1238 val + (i * val_bytes),
1180 val_bytes); 1239 val_bytes);
1181 if (ret != 0) 1240 if (ret != 0)
1182 return ret; 1241 return ret;
1183 } 1242 }
1184 } else { 1243 } else {
1185 ret = _regmap_raw_write(map, reg, wval, val_bytes * val_count); 1244 ret = _regmap_raw_write(map, reg, wval, val_bytes * val_count,
1245 false);
1186 } 1246 }
1187 1247
1188 if (val_bytes != 1) 1248 if (val_bytes != 1)
@@ -1194,6 +1254,48 @@ out:
1194} 1254}
1195EXPORT_SYMBOL_GPL(regmap_bulk_write); 1255EXPORT_SYMBOL_GPL(regmap_bulk_write);
1196 1256
1257/**
1258 * regmap_raw_write_async(): Write raw values to one or more registers
1259 * asynchronously
1260 *
1261 * @map: Register map to write to
1262 * @reg: Initial register to write to
1263 * @val: Block of data to be written, laid out for direct transmission to the
1264 * device. Must be valid until regmap_async_complete() is called.
1265 * @val_len: Length of data pointed to by val.
1266 *
1267 * This function is intended to be used for things like firmware
1268 * download where a large block of data needs to be transferred to the
1269 * device. No formatting will be done on the data provided.
1270 *
1271 * If supported by the underlying bus the write will be scheduled
1272 * asynchronously, helping maximise I/O speed on higher speed buses
1273 * like SPI. regmap_async_complete() can be called to ensure that all
1274 * asynchrnous writes have been completed.
1275 *
1276 * A value of zero will be returned on success, a negative errno will
1277 * be returned in error cases.
1278 */
1279int regmap_raw_write_async(struct regmap *map, unsigned int reg,
1280 const void *val, size_t val_len)
1281{
1282 int ret;
1283
1284 if (val_len % map->format.val_bytes)
1285 return -EINVAL;
1286 if (reg % map->reg_stride)
1287 return -EINVAL;
1288
1289 map->lock(map->lock_arg);
1290
1291 ret = _regmap_raw_write(map, reg, val, val_len, true);
1292
1293 map->unlock(map->lock_arg);
1294
1295 return ret;
1296}
1297EXPORT_SYMBOL_GPL(regmap_raw_write_async);
1298
1197static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val, 1299static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
1198 unsigned int val_len) 1300 unsigned int val_len)
1199{ 1301{
@@ -1492,6 +1594,66 @@ int regmap_update_bits_check(struct regmap *map, unsigned int reg,
1492} 1594}
1493EXPORT_SYMBOL_GPL(regmap_update_bits_check); 1595EXPORT_SYMBOL_GPL(regmap_update_bits_check);
1494 1596
1597void regmap_async_complete_cb(struct regmap_async *async, int ret)
1598{
1599 struct regmap *map = async->map;
1600 bool wake;
1601
1602 spin_lock(&map->async_lock);
1603
1604 list_del(&async->list);
1605 wake = list_empty(&map->async_list);
1606
1607 if (ret != 0)
1608 map->async_ret = ret;
1609
1610 spin_unlock(&map->async_lock);
1611
1612 schedule_work(&async->cleanup);
1613
1614 if (wake)
1615 wake_up(&map->async_waitq);
1616}
1617
1618static int regmap_async_is_done(struct regmap *map)
1619{
1620 unsigned long flags;
1621 int ret;
1622
1623 spin_lock_irqsave(&map->async_lock, flags);
1624 ret = list_empty(&map->async_list);
1625 spin_unlock_irqrestore(&map->async_lock, flags);
1626
1627 return ret;
1628}
1629
1630/**
1631 * regmap_async_complete: Ensure all asynchronous I/O has completed.
1632 *
1633 * @map: Map to operate on.
1634 *
1635 * Blocks until any pending asynchronous I/O has completed. Returns
1636 * an error code for any failed I/O operations.
1637 */
1638int regmap_async_complete(struct regmap *map)
1639{
1640 unsigned long flags;
1641 int ret;
1642
1643 /* Nothing to do with no async support */
1644 if (!map->bus->async_write)
1645 return 0;
1646
1647 wait_event(map->async_waitq, regmap_async_is_done(map));
1648
1649 spin_lock_irqsave(&map->async_lock, flags);
1650 ret = map->async_ret;
1651 map->async_ret = 0;
1652 spin_unlock_irqrestore(&map->async_lock, flags);
1653
1654 return ret;
1655}
1656
1495/** 1657/**
1496 * regmap_register_patch: Register and apply register updates to be applied 1658 * regmap_register_patch: Register and apply register updates to be applied
1497 * on device initialistion 1659 * on device initialistion
diff --git a/include/linux/regmap.h b/include/linux/regmap.h
index b7e95bf942c9..f9b7fbe35ab1 100644
--- a/include/linux/regmap.h
+++ b/include/linux/regmap.h
@@ -235,14 +235,21 @@ struct regmap_range_cfg {
235 unsigned int window_len; 235 unsigned int window_len;
236}; 236};
237 237
238struct regmap_async;
239
238typedef int (*regmap_hw_write)(void *context, const void *data, 240typedef int (*regmap_hw_write)(void *context, const void *data,
239 size_t count); 241 size_t count);
240typedef int (*regmap_hw_gather_write)(void *context, 242typedef int (*regmap_hw_gather_write)(void *context,
241 const void *reg, size_t reg_len, 243 const void *reg, size_t reg_len,
242 const void *val, size_t val_len); 244 const void *val, size_t val_len);
245typedef int (*regmap_hw_async_write)(void *context,
246 const void *reg, size_t reg_len,
247 const void *val, size_t val_len,
248 struct regmap_async *async);
243typedef int (*regmap_hw_read)(void *context, 249typedef int (*regmap_hw_read)(void *context,
244 const void *reg_buf, size_t reg_size, 250 const void *reg_buf, size_t reg_size,
245 void *val_buf, size_t val_size); 251 void *val_buf, size_t val_size);
252typedef struct regmap_async *(*regmap_hw_async_alloc)(void);
246typedef void (*regmap_hw_free_context)(void *context); 253typedef void (*regmap_hw_free_context)(void *context);
247 254
248/** 255/**
@@ -255,8 +262,11 @@ typedef void (*regmap_hw_free_context)(void *context);
255 * @write: Write operation. 262 * @write: Write operation.
256 * @gather_write: Write operation with split register/value, return -ENOTSUPP 263 * @gather_write: Write operation with split register/value, return -ENOTSUPP
257 * if not implemented on a given device. 264 * if not implemented on a given device.
265 * @async_write: Write operation which completes asynchronously, optional and
266 * must serialise with respect to non-async I/O.
258 * @read: Read operation. Data is returned in the buffer used to transmit 267 * @read: Read operation. Data is returned in the buffer used to transmit
259 * data. 268 * data.
269 * @async_alloc: Allocate a regmap_async() structure.
260 * @read_flag_mask: Mask to be set in the top byte of the register when doing 270 * @read_flag_mask: Mask to be set in the top byte of the register when doing
261 * a read. 271 * a read.
262 * @reg_format_endian_default: Default endianness for formatted register 272 * @reg_format_endian_default: Default endianness for formatted register
@@ -265,13 +275,16 @@ typedef void (*regmap_hw_free_context)(void *context);
265 * @val_format_endian_default: Default endianness for formatted register 275 * @val_format_endian_default: Default endianness for formatted register
266 * values. Used when the regmap_config specifies DEFAULT. If this is 276 * values. Used when the regmap_config specifies DEFAULT. If this is
267 * DEFAULT, BIG is assumed. 277 * DEFAULT, BIG is assumed.
278 * @async_size: Size of struct used for async work.
268 */ 279 */
269struct regmap_bus { 280struct regmap_bus {
270 bool fast_io; 281 bool fast_io;
271 regmap_hw_write write; 282 regmap_hw_write write;
272 regmap_hw_gather_write gather_write; 283 regmap_hw_gather_write gather_write;
284 regmap_hw_async_write async_write;
273 regmap_hw_read read; 285 regmap_hw_read read;
274 regmap_hw_free_context free_context; 286 regmap_hw_free_context free_context;
287 regmap_hw_async_alloc async_alloc;
275 u8 read_flag_mask; 288 u8 read_flag_mask;
276 enum regmap_endian reg_format_endian_default; 289 enum regmap_endian reg_format_endian_default;
277 enum regmap_endian val_format_endian_default; 290 enum regmap_endian val_format_endian_default;
@@ -310,6 +323,8 @@ int regmap_raw_write(struct regmap *map, unsigned int reg,
310 const void *val, size_t val_len); 323 const void *val, size_t val_len);
311int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val, 324int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,
312 size_t val_count); 325 size_t val_count);
326int regmap_raw_write_async(struct regmap *map, unsigned int reg,
327 const void *val, size_t val_len);
313int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val); 328int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val);
314int regmap_raw_read(struct regmap *map, unsigned int reg, 329int regmap_raw_read(struct regmap *map, unsigned int reg,
315 void *val, size_t val_len); 330 void *val, size_t val_len);
@@ -321,6 +336,7 @@ int regmap_update_bits_check(struct regmap *map, unsigned int reg,
321 unsigned int mask, unsigned int val, 336 unsigned int mask, unsigned int val,
322 bool *change); 337 bool *change);
323int regmap_get_val_bytes(struct regmap *map); 338int regmap_get_val_bytes(struct regmap *map);
339int regmap_async_complete(struct regmap *map);
324 340
325int regcache_sync(struct regmap *map); 341int regcache_sync(struct regmap *map);
326int regcache_sync_region(struct regmap *map, unsigned int min, 342int regcache_sync_region(struct regmap *map, unsigned int min,
@@ -422,6 +438,13 @@ static inline int regmap_raw_write(struct regmap *map, unsigned int reg,
422 return -EINVAL; 438 return -EINVAL;
423} 439}
424 440
441static inline int regmap_raw_write_async(struct regmap *map, unsigned int reg,
442 const void *val, size_t val_len)
443{
444 WARN_ONCE(1, "regmap API is disabled");
445 return -EINVAL;
446}
447
425static inline int regmap_bulk_write(struct regmap *map, unsigned int reg, 448static inline int regmap_bulk_write(struct regmap *map, unsigned int reg,
426 const void *val, size_t val_count) 449 const void *val, size_t val_count)
427{ 450{
@@ -500,6 +523,11 @@ static inline void regcache_mark_dirty(struct regmap *map)
500 WARN_ONCE(1, "regmap API is disabled"); 523 WARN_ONCE(1, "regmap API is disabled");
501} 524}
502 525
526static inline void regmap_async_complete(struct regmap *map)
527{
528 WARN_ONCE(1, "regmap API is disabled");
529}
530
503static inline int regmap_register_patch(struct regmap *map, 531static inline int regmap_register_patch(struct regmap *map,
504 const struct reg_default *regs, 532 const struct reg_default *regs,
505 int num_regs) 533 int num_regs)