aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2013-01-27 09:07:38 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2013-01-28 23:14:52 -0500
commit0d509f2b112b21411712f0bf789b372987967e49 (patch)
tree138bac0e613916bbf725f0ee1939080dfc4dbedb
parent07c320dc31d757b8cb59c64dab320215c929bf02 (diff)
regmap: Add asynchronous I/O support
Some use cases like firmware download can transfer a lot of data in quick succession. With high speed buses these use cases can benefit from having multiple transfers scheduled at once since this allows the bus to minimise the delay between transfers. Support this by adding regmap_raw_write_async(), allowing raw transfers to be scheduled, and regmap_async_complete() to wait for them to finish. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-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)