diff options
| -rw-r--r-- | drivers/base/regmap/Kconfig | 5 | ||||
| -rw-r--r-- | drivers/base/regmap/Makefile | 1 | ||||
| -rw-r--r-- | drivers/base/regmap/internal.h | 8 | ||||
| -rw-r--r-- | drivers/base/regmap/regcache.c | 19 | ||||
| -rw-r--r-- | drivers/base/regmap/regmap-debugfs.c | 57 | ||||
| -rw-r--r-- | drivers/base/regmap/regmap-irq.c | 16 | ||||
| -rw-r--r-- | drivers/base/regmap/regmap-spi.c | 3 | ||||
| -rw-r--r-- | drivers/base/regmap/regmap-spmi.c | 90 | ||||
| -rw-r--r-- | drivers/base/regmap/regmap.c | 366 | ||||
| -rw-r--r-- | include/linux/regmap.h | 53 |
10 files changed, 560 insertions, 58 deletions
diff --git a/drivers/base/regmap/Kconfig b/drivers/base/regmap/Kconfig index f0d30543fcce..4251570610c9 100644 --- a/drivers/base/regmap/Kconfig +++ b/drivers/base/regmap/Kconfig | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | # subsystems should select the appropriate symbols. | 3 | # subsystems should select the appropriate symbols. |
| 4 | 4 | ||
| 5 | config REGMAP | 5 | config REGMAP |
| 6 | default y if (REGMAP_I2C || REGMAP_SPI || REGMAP_MMIO || REGMAP_IRQ) | 6 | default y if (REGMAP_I2C || REGMAP_SPI || REGMAP_SPMI || REGMAP_MMIO || REGMAP_IRQ) |
| 7 | select LZO_COMPRESS | 7 | select LZO_COMPRESS |
| 8 | select LZO_DECOMPRESS | 8 | select LZO_DECOMPRESS |
| 9 | select IRQ_DOMAIN if REGMAP_IRQ | 9 | select IRQ_DOMAIN if REGMAP_IRQ |
| @@ -15,6 +15,9 @@ config REGMAP_I2C | |||
| 15 | config REGMAP_SPI | 15 | config REGMAP_SPI |
| 16 | tristate | 16 | tristate |
| 17 | 17 | ||
| 18 | config REGMAP_SPMI | ||
| 19 | tristate | ||
| 20 | |||
| 18 | config REGMAP_MMIO | 21 | config REGMAP_MMIO |
| 19 | tristate | 22 | tristate |
| 20 | 23 | ||
diff --git a/drivers/base/regmap/Makefile b/drivers/base/regmap/Makefile index cf129980abd0..a7c670b4123a 100644 --- a/drivers/base/regmap/Makefile +++ b/drivers/base/regmap/Makefile | |||
| @@ -3,5 +3,6 @@ obj-$(CONFIG_REGMAP) += regcache-rbtree.o regcache-lzo.o regcache-flat.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_SPMI) += regmap-spmi.o | ||
| 6 | obj-$(CONFIG_REGMAP_MMIO) += regmap-mmio.o | 7 | obj-$(CONFIG_REGMAP_MMIO) += regmap-mmio.o |
| 7 | obj-$(CONFIG_REGMAP_IRQ) += regmap-irq.o | 8 | obj-$(CONFIG_REGMAP_IRQ) += regmap-irq.o |
diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h index 57f777835d97..33414b1de201 100644 --- a/drivers/base/regmap/internal.h +++ b/drivers/base/regmap/internal.h | |||
| @@ -44,7 +44,6 @@ struct regmap_format { | |||
| 44 | 44 | ||
| 45 | struct regmap_async { | 45 | struct regmap_async { |
| 46 | struct list_head list; | 46 | struct list_head list; |
| 47 | struct work_struct cleanup; | ||
| 48 | struct regmap *map; | 47 | struct regmap *map; |
| 49 | void *work_buf; | 48 | void *work_buf; |
| 50 | }; | 49 | }; |
| @@ -64,9 +63,11 @@ struct regmap { | |||
| 64 | void *bus_context; | 63 | void *bus_context; |
| 65 | const char *name; | 64 | const char *name; |
| 66 | 65 | ||
| 66 | bool async; | ||
| 67 | spinlock_t async_lock; | 67 | spinlock_t async_lock; |
| 68 | wait_queue_head_t async_waitq; | 68 | wait_queue_head_t async_waitq; |
| 69 | struct list_head async_list; | 69 | struct list_head async_list; |
| 70 | struct list_head async_free; | ||
| 70 | int async_ret; | 71 | int async_ret; |
| 71 | 72 | ||
| 72 | #ifdef CONFIG_DEBUG_FS | 73 | #ifdef CONFIG_DEBUG_FS |
| @@ -179,6 +180,9 @@ struct regmap_field { | |||
| 179 | /* lsb */ | 180 | /* lsb */ |
| 180 | unsigned int shift; | 181 | unsigned int shift; |
| 181 | unsigned int reg; | 182 | unsigned int reg; |
| 183 | |||
| 184 | unsigned int id_size; | ||
| 185 | unsigned int id_offset; | ||
| 182 | }; | 186 | }; |
| 183 | 187 | ||
| 184 | #ifdef CONFIG_DEBUG_FS | 188 | #ifdef CONFIG_DEBUG_FS |
| @@ -218,7 +222,7 @@ bool regcache_set_val(struct regmap *map, void *base, unsigned int idx, | |||
| 218 | int regcache_lookup_reg(struct regmap *map, unsigned int reg); | 222 | int regcache_lookup_reg(struct regmap *map, unsigned int reg); |
| 219 | 223 | ||
| 220 | int _regmap_raw_write(struct regmap *map, unsigned int reg, | 224 | int _regmap_raw_write(struct regmap *map, unsigned int reg, |
| 221 | const void *val, size_t val_len, bool async); | 225 | const void *val, size_t val_len); |
| 222 | 226 | ||
| 223 | void regmap_async_complete_cb(struct regmap_async *async, int ret); | 227 | void regmap_async_complete_cb(struct regmap_async *async, int ret); |
| 224 | 228 | ||
diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c index d6c2d691b6e8..d4dd77134814 100644 --- a/drivers/base/regmap/regcache.c +++ b/drivers/base/regmap/regcache.c | |||
| @@ -307,6 +307,8 @@ int regcache_sync(struct regmap *map) | |||
| 307 | if (!map->cache_dirty) | 307 | if (!map->cache_dirty) |
| 308 | goto out; | 308 | goto out; |
| 309 | 309 | ||
| 310 | map->async = true; | ||
| 311 | |||
| 310 | /* Apply any patch first */ | 312 | /* Apply any patch first */ |
| 311 | map->cache_bypass = 1; | 313 | map->cache_bypass = 1; |
| 312 | for (i = 0; i < map->patch_regs; i++) { | 314 | for (i = 0; i < map->patch_regs; i++) { |
| @@ -332,11 +334,15 @@ int regcache_sync(struct regmap *map) | |||
| 332 | map->cache_dirty = false; | 334 | map->cache_dirty = false; |
| 333 | 335 | ||
| 334 | out: | 336 | out: |
| 335 | trace_regcache_sync(map->dev, name, "stop"); | ||
| 336 | /* Restore the bypass state */ | 337 | /* Restore the bypass state */ |
| 338 | map->async = false; | ||
| 337 | map->cache_bypass = bypass; | 339 | map->cache_bypass = bypass; |
| 338 | map->unlock(map->lock_arg); | 340 | map->unlock(map->lock_arg); |
| 339 | 341 | ||
| 342 | regmap_async_complete(map); | ||
| 343 | |||
| 344 | trace_regcache_sync(map->dev, name, "stop"); | ||
| 345 | |||
| 340 | return ret; | 346 | return ret; |
| 341 | } | 347 | } |
| 342 | EXPORT_SYMBOL_GPL(regcache_sync); | 348 | EXPORT_SYMBOL_GPL(regcache_sync); |
| @@ -375,17 +381,23 @@ int regcache_sync_region(struct regmap *map, unsigned int min, | |||
| 375 | if (!map->cache_dirty) | 381 | if (!map->cache_dirty) |
| 376 | goto out; | 382 | goto out; |
| 377 | 383 | ||
| 384 | map->async = true; | ||
| 385 | |||
| 378 | if (map->cache_ops->sync) | 386 | if (map->cache_ops->sync) |
| 379 | ret = map->cache_ops->sync(map, min, max); | 387 | ret = map->cache_ops->sync(map, min, max); |
| 380 | else | 388 | else |
| 381 | ret = regcache_default_sync(map, min, max); | 389 | ret = regcache_default_sync(map, min, max); |
| 382 | 390 | ||
| 383 | out: | 391 | out: |
| 384 | trace_regcache_sync(map->dev, name, "stop region"); | ||
| 385 | /* Restore the bypass state */ | 392 | /* Restore the bypass state */ |
| 386 | map->cache_bypass = bypass; | 393 | map->cache_bypass = bypass; |
| 394 | map->async = false; | ||
| 387 | map->unlock(map->lock_arg); | 395 | map->unlock(map->lock_arg); |
| 388 | 396 | ||
| 397 | regmap_async_complete(map); | ||
| 398 | |||
| 399 | trace_regcache_sync(map->dev, name, "stop region"); | ||
| 400 | |||
| 389 | return ret; | 401 | return ret; |
| 390 | } | 402 | } |
| 391 | EXPORT_SYMBOL_GPL(regcache_sync_region); | 403 | EXPORT_SYMBOL_GPL(regcache_sync_region); |
| @@ -631,8 +643,7 @@ static int regcache_sync_block_raw_flush(struct regmap *map, const void **data, | |||
| 631 | 643 | ||
| 632 | map->cache_bypass = 1; | 644 | map->cache_bypass = 1; |
| 633 | 645 | ||
| 634 | ret = _regmap_raw_write(map, base, *data, count * val_bytes, | 646 | ret = _regmap_raw_write(map, base, *data, count * val_bytes); |
| 635 | false); | ||
| 636 | 647 | ||
| 637 | map->cache_bypass = 0; | 648 | map->cache_bypass = 0; |
| 638 | 649 | ||
diff --git a/drivers/base/regmap/regmap-debugfs.c b/drivers/base/regmap/regmap-debugfs.c index de11ecaf3833..c5471cd6ebb7 100644 --- a/drivers/base/regmap/regmap-debugfs.c +++ b/drivers/base/regmap/regmap-debugfs.c | |||
| @@ -15,10 +15,19 @@ | |||
| 15 | #include <linux/debugfs.h> | 15 | #include <linux/debugfs.h> |
| 16 | #include <linux/uaccess.h> | 16 | #include <linux/uaccess.h> |
| 17 | #include <linux/device.h> | 17 | #include <linux/device.h> |
| 18 | #include <linux/list.h> | ||
| 18 | 19 | ||
| 19 | #include "internal.h" | 20 | #include "internal.h" |
| 20 | 21 | ||
| 22 | struct regmap_debugfs_node { | ||
| 23 | struct regmap *map; | ||
| 24 | const char *name; | ||
| 25 | struct list_head link; | ||
| 26 | }; | ||
| 27 | |||
| 21 | static struct dentry *regmap_debugfs_root; | 28 | static struct dentry *regmap_debugfs_root; |
| 29 | static LIST_HEAD(regmap_debugfs_early_list); | ||
| 30 | static DEFINE_MUTEX(regmap_debugfs_early_lock); | ||
| 22 | 31 | ||
| 23 | /* Calculate the length of a fixed format */ | 32 | /* Calculate the length of a fixed format */ |
| 24 | static size_t regmap_calc_reg_len(int max_val, char *buf, size_t buf_size) | 33 | static size_t regmap_calc_reg_len(int max_val, char *buf, size_t buf_size) |
| @@ -465,6 +474,20 @@ void regmap_debugfs_init(struct regmap *map, const char *name) | |||
| 465 | struct rb_node *next; | 474 | struct rb_node *next; |
| 466 | struct regmap_range_node *range_node; | 475 | struct regmap_range_node *range_node; |
| 467 | 476 | ||
| 477 | /* If we don't have the debugfs root yet, postpone init */ | ||
| 478 | if (!regmap_debugfs_root) { | ||
| 479 | struct regmap_debugfs_node *node; | ||
| 480 | node = kzalloc(sizeof(*node), GFP_KERNEL); | ||
| 481 | if (!node) | ||
| 482 | return; | ||
| 483 | node->map = map; | ||
| 484 | node->name = name; | ||
| 485 | mutex_lock(®map_debugfs_early_lock); | ||
| 486 | list_add(&node->link, ®map_debugfs_early_list); | ||
| 487 | mutex_unlock(®map_debugfs_early_lock); | ||
| 488 | return; | ||
| 489 | } | ||
| 490 | |||
| 468 | INIT_LIST_HEAD(&map->debugfs_off_cache); | 491 | INIT_LIST_HEAD(&map->debugfs_off_cache); |
| 469 | mutex_init(&map->cache_lock); | 492 | mutex_init(&map->cache_lock); |
| 470 | 493 | ||
| @@ -519,18 +542,42 @@ void regmap_debugfs_init(struct regmap *map, const char *name) | |||
| 519 | 542 | ||
| 520 | void regmap_debugfs_exit(struct regmap *map) | 543 | void regmap_debugfs_exit(struct regmap *map) |
| 521 | { | 544 | { |
| 522 | debugfs_remove_recursive(map->debugfs); | 545 | if (map->debugfs) { |
| 523 | mutex_lock(&map->cache_lock); | 546 | debugfs_remove_recursive(map->debugfs); |
| 524 | regmap_debugfs_free_dump_cache(map); | 547 | mutex_lock(&map->cache_lock); |
| 525 | mutex_unlock(&map->cache_lock); | 548 | regmap_debugfs_free_dump_cache(map); |
| 526 | kfree(map->debugfs_name); | 549 | mutex_unlock(&map->cache_lock); |
| 550 | kfree(map->debugfs_name); | ||
| 551 | } else { | ||
| 552 | struct regmap_debugfs_node *node, *tmp; | ||
| 553 | |||
| 554 | mutex_lock(®map_debugfs_early_lock); | ||
| 555 | list_for_each_entry_safe(node, tmp, ®map_debugfs_early_list, | ||
| 556 | link) { | ||
| 557 | if (node->map == map) { | ||
| 558 | list_del(&node->link); | ||
| 559 | kfree(node); | ||
| 560 | } | ||
| 561 | } | ||
| 562 | mutex_unlock(®map_debugfs_early_lock); | ||
| 563 | } | ||
| 527 | } | 564 | } |
| 528 | 565 | ||
| 529 | void regmap_debugfs_initcall(void) | 566 | void regmap_debugfs_initcall(void) |
| 530 | { | 567 | { |
| 568 | struct regmap_debugfs_node *node, *tmp; | ||
| 569 | |||
| 531 | regmap_debugfs_root = debugfs_create_dir("regmap", NULL); | 570 | regmap_debugfs_root = debugfs_create_dir("regmap", NULL); |
| 532 | if (!regmap_debugfs_root) { | 571 | if (!regmap_debugfs_root) { |
| 533 | pr_warn("regmap: Failed to create debugfs root\n"); | 572 | pr_warn("regmap: Failed to create debugfs root\n"); |
| 534 | return; | 573 | return; |
| 535 | } | 574 | } |
| 575 | |||
| 576 | mutex_lock(®map_debugfs_early_lock); | ||
| 577 | list_for_each_entry_safe(node, tmp, ®map_debugfs_early_list, link) { | ||
| 578 | regmap_debugfs_init(node->map, node->name); | ||
| 579 | list_del(&node->link); | ||
| 580 | kfree(node); | ||
| 581 | } | ||
| 582 | mutex_unlock(®map_debugfs_early_lock); | ||
| 536 | } | 583 | } |
diff --git a/drivers/base/regmap/regmap-irq.c b/drivers/base/regmap/regmap-irq.c index d10456ffd811..763c60d3d277 100644 --- a/drivers/base/regmap/regmap-irq.c +++ b/drivers/base/regmap/regmap-irq.c | |||
| @@ -105,6 +105,22 @@ static void regmap_irq_sync_unlock(struct irq_data *data) | |||
| 105 | "Failed to sync wakes in %x: %d\n", | 105 | "Failed to sync wakes in %x: %d\n", |
| 106 | reg, ret); | 106 | reg, ret); |
| 107 | } | 107 | } |
| 108 | |||
| 109 | if (!d->chip->init_ack_masked) | ||
| 110 | continue; | ||
| 111 | /* | ||
| 112 | * Ack all the masked interrupts uncondictionly, | ||
| 113 | * OR if there is masked interrupt which hasn't been Acked, | ||
| 114 | * it'll be ignored in irq handler, then may introduce irq storm | ||
| 115 | */ | ||
| 116 | if (d->mask_buf[i] && d->chip->ack_base) { | ||
| 117 | reg = d->chip->ack_base + | ||
| 118 | (i * map->reg_stride * d->irq_reg_stride); | ||
| 119 | ret = regmap_write(map, reg, d->mask_buf[i]); | ||
| 120 | if (ret != 0) | ||
| 121 | dev_err(d->map->dev, "Failed to ack 0x%x: %d\n", | ||
| 122 | reg, ret); | ||
| 123 | } | ||
| 108 | } | 124 | } |
| 109 | 125 | ||
| 110 | if (d->chip->runtime_pm) | 126 | if (d->chip->runtime_pm) |
diff --git a/drivers/base/regmap/regmap-spi.c b/drivers/base/regmap/regmap-spi.c index 4c506bd940f3..37f12ae7aada 100644 --- a/drivers/base/regmap/regmap-spi.c +++ b/drivers/base/regmap/regmap-spi.c | |||
| @@ -73,7 +73,8 @@ static int regmap_spi_async_write(void *context, | |||
| 73 | 73 | ||
| 74 | spi_message_init(&async->m); | 74 | spi_message_init(&async->m); |
| 75 | spi_message_add_tail(&async->t[0], &async->m); | 75 | spi_message_add_tail(&async->t[0], &async->m); |
| 76 | spi_message_add_tail(&async->t[1], &async->m); | 76 | if (val) |
| 77 | spi_message_add_tail(&async->t[1], &async->m); | ||
| 77 | 78 | ||
| 78 | async->m.complete = regmap_spi_complete; | 79 | async->m.complete = regmap_spi_complete; |
| 79 | async->m.context = async; | 80 | async->m.context = async; |
diff --git a/drivers/base/regmap/regmap-spmi.c b/drivers/base/regmap/regmap-spmi.c new file mode 100644 index 000000000000..ac2391013db1 --- /dev/null +++ b/drivers/base/regmap/regmap-spmi.c | |||
| @@ -0,0 +1,90 @@ | |||
| 1 | /* | ||
| 2 | * Register map access API - SPMI support | ||
| 3 | * | ||
| 4 | * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. | ||
| 5 | * | ||
| 6 | * Based on regmap-i2c.c: | ||
| 7 | * Copyright 2011 Wolfson Microelectronics plc | ||
| 8 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or modify | ||
| 11 | * it under the terms of the GNU General Public License version 2 and | ||
| 12 | * only version 2 as published by the Free Software Foundation. | ||
| 13 | * | ||
| 14 | * This program is distributed in the hope that it will be useful, | ||
| 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | * GNU General Public License for more details. | ||
| 18 | * | ||
| 19 | */ | ||
| 20 | #include <linux/regmap.h> | ||
| 21 | #include <linux/spmi.h> | ||
| 22 | #include <linux/module.h> | ||
| 23 | #include <linux/init.h> | ||
| 24 | |||
| 25 | static int regmap_spmi_read(void *context, | ||
| 26 | const void *reg, size_t reg_size, | ||
| 27 | void *val, size_t val_size) | ||
| 28 | { | ||
| 29 | BUG_ON(reg_size != 2); | ||
| 30 | return spmi_ext_register_readl(context, *(u16 *)reg, | ||
| 31 | val, val_size); | ||
| 32 | } | ||
| 33 | |||
| 34 | static int regmap_spmi_gather_write(void *context, | ||
| 35 | const void *reg, size_t reg_size, | ||
| 36 | const void *val, size_t val_size) | ||
| 37 | { | ||
| 38 | BUG_ON(reg_size != 2); | ||
| 39 | return spmi_ext_register_writel(context, *(u16 *)reg, val, val_size); | ||
| 40 | } | ||
| 41 | |||
| 42 | static int regmap_spmi_write(void *context, const void *data, | ||
| 43 | size_t count) | ||
| 44 | { | ||
| 45 | BUG_ON(count < 2); | ||
| 46 | return regmap_spmi_gather_write(context, data, 2, data + 2, count - 2); | ||
| 47 | } | ||
| 48 | |||
| 49 | static struct regmap_bus regmap_spmi = { | ||
| 50 | .read = regmap_spmi_read, | ||
| 51 | .write = regmap_spmi_write, | ||
| 52 | .gather_write = regmap_spmi_gather_write, | ||
| 53 | .reg_format_endian_default = REGMAP_ENDIAN_NATIVE, | ||
| 54 | .val_format_endian_default = REGMAP_ENDIAN_NATIVE, | ||
| 55 | }; | ||
| 56 | |||
| 57 | /** | ||
| 58 | * regmap_init_spmi(): Initialize register map | ||
| 59 | * | ||
| 60 | * @sdev: Device that will be interacted with | ||
| 61 | * @config: Configuration for register map | ||
| 62 | * | ||
| 63 | * The return value will be an ERR_PTR() on error or a valid pointer to | ||
| 64 | * a struct regmap. | ||
| 65 | */ | ||
| 66 | struct regmap *regmap_init_spmi(struct spmi_device *sdev, | ||
| 67 | const struct regmap_config *config) | ||
| 68 | { | ||
| 69 | return regmap_init(&sdev->dev, ®map_spmi, sdev, config); | ||
| 70 | } | ||
| 71 | EXPORT_SYMBOL_GPL(regmap_init_spmi); | ||
| 72 | |||
| 73 | /** | ||
| 74 | * devm_regmap_init_spmi(): Initialise managed register map | ||
| 75 | * | ||
| 76 | * @sdev: Device that will be interacted with | ||
| 77 | * @config: Configuration for register map | ||
| 78 | * | ||
| 79 | * The return value will be an ERR_PTR() on error or a valid pointer | ||
| 80 | * to a struct regmap. The regmap will be automatically freed by the | ||
| 81 | * device management code. | ||
| 82 | */ | ||
| 83 | struct regmap *devm_regmap_init_spmi(struct spmi_device *sdev, | ||
| 84 | const struct regmap_config *config) | ||
| 85 | { | ||
| 86 | return devm_regmap_init(&sdev->dev, ®map_spmi, sdev, config); | ||
| 87 | } | ||
| 88 | EXPORT_SYMBOL_GPL(devm_regmap_init_spmi); | ||
| 89 | |||
| 90 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index 7d689a15c500..9c021d9cace0 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c | |||
| @@ -42,15 +42,6 @@ static int _regmap_bus_formatted_write(void *context, unsigned int reg, | |||
| 42 | static int _regmap_bus_raw_write(void *context, unsigned int reg, | 42 | static int _regmap_bus_raw_write(void *context, unsigned int reg, |
| 43 | unsigned int val); | 43 | unsigned int val); |
| 44 | 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 | |||
| 54 | bool regmap_reg_in_ranges(unsigned int reg, | 45 | bool regmap_reg_in_ranges(unsigned int reg, |
| 55 | const struct regmap_range *ranges, | 46 | const struct regmap_range *ranges, |
| 56 | unsigned int nranges) | 47 | unsigned int nranges) |
| @@ -465,6 +456,7 @@ struct regmap *regmap_init(struct device *dev, | |||
| 465 | 456 | ||
| 466 | spin_lock_init(&map->async_lock); | 457 | spin_lock_init(&map->async_lock); |
| 467 | INIT_LIST_HEAD(&map->async_list); | 458 | INIT_LIST_HEAD(&map->async_list); |
| 459 | INIT_LIST_HEAD(&map->async_free); | ||
| 468 | init_waitqueue_head(&map->async_waitq); | 460 | init_waitqueue_head(&map->async_waitq); |
| 469 | 461 | ||
| 470 | if (config->read_flag_mask || config->write_flag_mask) { | 462 | if (config->read_flag_mask || config->write_flag_mask) { |
| @@ -821,6 +813,8 @@ static void regmap_field_init(struct regmap_field *rm_field, | |||
| 821 | rm_field->reg = reg_field.reg; | 813 | rm_field->reg = reg_field.reg; |
| 822 | rm_field->shift = reg_field.lsb; | 814 | rm_field->shift = reg_field.lsb; |
| 823 | rm_field->mask = ((BIT(field_bits) - 1) << reg_field.lsb); | 815 | rm_field->mask = ((BIT(field_bits) - 1) << reg_field.lsb); |
| 816 | rm_field->id_size = reg_field.id_size; | ||
| 817 | rm_field->id_offset = reg_field.id_offset; | ||
| 824 | } | 818 | } |
| 825 | 819 | ||
| 826 | /** | 820 | /** |
| @@ -942,12 +936,22 @@ EXPORT_SYMBOL_GPL(regmap_reinit_cache); | |||
| 942 | */ | 936 | */ |
| 943 | void regmap_exit(struct regmap *map) | 937 | void regmap_exit(struct regmap *map) |
| 944 | { | 938 | { |
| 939 | struct regmap_async *async; | ||
| 940 | |||
| 945 | regcache_exit(map); | 941 | regcache_exit(map); |
| 946 | regmap_debugfs_exit(map); | 942 | regmap_debugfs_exit(map); |
| 947 | regmap_range_exit(map); | 943 | regmap_range_exit(map); |
| 948 | if (map->bus && map->bus->free_context) | 944 | if (map->bus && map->bus->free_context) |
| 949 | map->bus->free_context(map->bus_context); | 945 | map->bus->free_context(map->bus_context); |
| 950 | kfree(map->work_buf); | 946 | kfree(map->work_buf); |
| 947 | while (!list_empty(&map->async_free)) { | ||
| 948 | async = list_first_entry_or_null(&map->async_free, | ||
| 949 | struct regmap_async, | ||
| 950 | list); | ||
| 951 | list_del(&async->list); | ||
| 952 | kfree(async->work_buf); | ||
| 953 | kfree(async); | ||
| 954 | } | ||
| 951 | kfree(map); | 955 | kfree(map); |
| 952 | } | 956 | } |
| 953 | EXPORT_SYMBOL_GPL(regmap_exit); | 957 | EXPORT_SYMBOL_GPL(regmap_exit); |
| @@ -1039,7 +1043,7 @@ static int _regmap_select_page(struct regmap *map, unsigned int *reg, | |||
| 1039 | } | 1043 | } |
| 1040 | 1044 | ||
| 1041 | int _regmap_raw_write(struct regmap *map, unsigned int reg, | 1045 | int _regmap_raw_write(struct regmap *map, unsigned int reg, |
| 1042 | const void *val, size_t val_len, bool async) | 1046 | const void *val, size_t val_len) |
| 1043 | { | 1047 | { |
| 1044 | struct regmap_range_node *range; | 1048 | struct regmap_range_node *range; |
| 1045 | unsigned long flags; | 1049 | unsigned long flags; |
| @@ -1091,7 +1095,7 @@ int _regmap_raw_write(struct regmap *map, unsigned int reg, | |||
| 1091 | dev_dbg(map->dev, "Writing window %d/%zu\n", | 1095 | dev_dbg(map->dev, "Writing window %d/%zu\n", |
| 1092 | win_residue, val_len / map->format.val_bytes); | 1096 | win_residue, val_len / map->format.val_bytes); |
| 1093 | ret = _regmap_raw_write(map, reg, val, win_residue * | 1097 | ret = _regmap_raw_write(map, reg, val, win_residue * |
| 1094 | map->format.val_bytes, async); | 1098 | map->format.val_bytes); |
| 1095 | if (ret != 0) | 1099 | if (ret != 0) |
| 1096 | return ret; | 1100 | return ret; |
| 1097 | 1101 | ||
| @@ -1114,49 +1118,72 @@ int _regmap_raw_write(struct regmap *map, unsigned int reg, | |||
| 1114 | 1118 | ||
| 1115 | u8[0] |= map->write_flag_mask; | 1119 | u8[0] |= map->write_flag_mask; |
| 1116 | 1120 | ||
| 1117 | if (async && map->bus->async_write) { | 1121 | /* |
| 1118 | struct regmap_async *async = map->bus->async_alloc(); | 1122 | * Essentially all I/O mechanisms will be faster with a single |
| 1119 | if (!async) | 1123 | * buffer to write. Since register syncs often generate raw |
| 1120 | return -ENOMEM; | 1124 | * writes of single registers optimise that case. |
| 1125 | */ | ||
| 1126 | if (val != work_val && val_len == map->format.val_bytes) { | ||
| 1127 | memcpy(work_val, val, map->format.val_bytes); | ||
| 1128 | val = work_val; | ||
| 1129 | } | ||
| 1130 | |||
| 1131 | if (map->async && map->bus->async_write) { | ||
| 1132 | struct regmap_async *async; | ||
| 1121 | 1133 | ||
| 1122 | trace_regmap_async_write_start(map->dev, reg, val_len); | 1134 | trace_regmap_async_write_start(map->dev, reg, val_len); |
| 1123 | 1135 | ||
| 1124 | async->work_buf = kzalloc(map->format.buf_size, | 1136 | spin_lock_irqsave(&map->async_lock, flags); |
| 1125 | GFP_KERNEL | GFP_DMA); | 1137 | async = list_first_entry_or_null(&map->async_free, |
| 1126 | if (!async->work_buf) { | 1138 | struct regmap_async, |
| 1127 | kfree(async); | 1139 | list); |
| 1128 | return -ENOMEM; | 1140 | if (async) |
| 1141 | list_del(&async->list); | ||
| 1142 | spin_unlock_irqrestore(&map->async_lock, flags); | ||
| 1143 | |||
| 1144 | if (!async) { | ||
| 1145 | async = map->bus->async_alloc(); | ||
| 1146 | if (!async) | ||
| 1147 | return -ENOMEM; | ||
| 1148 | |||
| 1149 | async->work_buf = kzalloc(map->format.buf_size, | ||
| 1150 | GFP_KERNEL | GFP_DMA); | ||
| 1151 | if (!async->work_buf) { | ||
| 1152 | kfree(async); | ||
| 1153 | return -ENOMEM; | ||
| 1154 | } | ||
| 1129 | } | 1155 | } |
| 1130 | 1156 | ||
| 1131 | INIT_WORK(&async->cleanup, async_cleanup); | ||
| 1132 | async->map = map; | 1157 | async->map = map; |
| 1133 | 1158 | ||
| 1134 | /* If the caller supplied the value we can use it safely. */ | 1159 | /* If the caller supplied the value we can use it safely. */ |
| 1135 | memcpy(async->work_buf, map->work_buf, map->format.pad_bytes + | 1160 | memcpy(async->work_buf, map->work_buf, map->format.pad_bytes + |
| 1136 | map->format.reg_bytes + map->format.val_bytes); | 1161 | map->format.reg_bytes + map->format.val_bytes); |
| 1137 | if (val == work_val) | ||
| 1138 | val = async->work_buf + map->format.pad_bytes + | ||
| 1139 | map->format.reg_bytes; | ||
| 1140 | 1162 | ||
| 1141 | spin_lock_irqsave(&map->async_lock, flags); | 1163 | spin_lock_irqsave(&map->async_lock, flags); |
| 1142 | list_add_tail(&async->list, &map->async_list); | 1164 | list_add_tail(&async->list, &map->async_list); |
| 1143 | spin_unlock_irqrestore(&map->async_lock, flags); | 1165 | spin_unlock_irqrestore(&map->async_lock, flags); |
| 1144 | 1166 | ||
| 1145 | ret = map->bus->async_write(map->bus_context, async->work_buf, | 1167 | if (val != work_val) |
| 1146 | map->format.reg_bytes + | 1168 | ret = map->bus->async_write(map->bus_context, |
| 1147 | map->format.pad_bytes, | 1169 | async->work_buf, |
| 1148 | val, val_len, async); | 1170 | map->format.reg_bytes + |
| 1171 | map->format.pad_bytes, | ||
| 1172 | val, val_len, async); | ||
| 1173 | else | ||
| 1174 | ret = map->bus->async_write(map->bus_context, | ||
| 1175 | async->work_buf, | ||
| 1176 | map->format.reg_bytes + | ||
| 1177 | map->format.pad_bytes + | ||
| 1178 | val_len, NULL, 0, async); | ||
| 1149 | 1179 | ||
| 1150 | if (ret != 0) { | 1180 | if (ret != 0) { |
| 1151 | dev_err(map->dev, "Failed to schedule write: %d\n", | 1181 | dev_err(map->dev, "Failed to schedule write: %d\n", |
| 1152 | ret); | 1182 | ret); |
| 1153 | 1183 | ||
| 1154 | spin_lock_irqsave(&map->async_lock, flags); | 1184 | spin_lock_irqsave(&map->async_lock, flags); |
| 1155 | list_del(&async->list); | 1185 | list_move(&async->list, &map->async_free); |
| 1156 | spin_unlock_irqrestore(&map->async_lock, flags); | 1186 | spin_unlock_irqrestore(&map->async_lock, flags); |
| 1157 | |||
| 1158 | kfree(async->work_buf); | ||
| 1159 | kfree(async); | ||
| 1160 | } | 1187 | } |
| 1161 | 1188 | ||
| 1162 | return ret; | 1189 | return ret; |
| @@ -1253,7 +1280,7 @@ static int _regmap_bus_raw_write(void *context, unsigned int reg, | |||
| 1253 | map->work_buf + | 1280 | map->work_buf + |
| 1254 | map->format.reg_bytes + | 1281 | map->format.reg_bytes + |
| 1255 | map->format.pad_bytes, | 1282 | map->format.pad_bytes, |
| 1256 | map->format.val_bytes, false); | 1283 | map->format.val_bytes); |
| 1257 | } | 1284 | } |
| 1258 | 1285 | ||
| 1259 | static inline void *_regmap_map_get_context(struct regmap *map) | 1286 | static inline void *_regmap_map_get_context(struct regmap *map) |
| @@ -1318,6 +1345,37 @@ int regmap_write(struct regmap *map, unsigned int reg, unsigned int val) | |||
| 1318 | EXPORT_SYMBOL_GPL(regmap_write); | 1345 | EXPORT_SYMBOL_GPL(regmap_write); |
| 1319 | 1346 | ||
| 1320 | /** | 1347 | /** |
| 1348 | * regmap_write_async(): Write a value to a single register asynchronously | ||
| 1349 | * | ||
| 1350 | * @map: Register map to write to | ||
| 1351 | * @reg: Register to write to | ||
| 1352 | * @val: Value to be written | ||
| 1353 | * | ||
| 1354 | * A value of zero will be returned on success, a negative errno will | ||
| 1355 | * be returned in error cases. | ||
| 1356 | */ | ||
| 1357 | int regmap_write_async(struct regmap *map, unsigned int reg, unsigned int val) | ||
| 1358 | { | ||
| 1359 | int ret; | ||
| 1360 | |||
| 1361 | if (reg % map->reg_stride) | ||
| 1362 | return -EINVAL; | ||
| 1363 | |||
| 1364 | map->lock(map->lock_arg); | ||
| 1365 | |||
| 1366 | map->async = true; | ||
| 1367 | |||
| 1368 | ret = _regmap_write(map, reg, val); | ||
| 1369 | |||
| 1370 | map->async = false; | ||
| 1371 | |||
| 1372 | map->unlock(map->lock_arg); | ||
| 1373 | |||
| 1374 | return ret; | ||
| 1375 | } | ||
| 1376 | EXPORT_SYMBOL_GPL(regmap_write_async); | ||
| 1377 | |||
| 1378 | /** | ||
| 1321 | * regmap_raw_write(): Write raw values to one or more registers | 1379 | * regmap_raw_write(): Write raw values to one or more registers |
| 1322 | * | 1380 | * |
| 1323 | * @map: Register map to write to | 1381 | * @map: Register map to write to |
| @@ -1345,7 +1403,7 @@ int regmap_raw_write(struct regmap *map, unsigned int reg, | |||
| 1345 | 1403 | ||
| 1346 | map->lock(map->lock_arg); | 1404 | map->lock(map->lock_arg); |
| 1347 | 1405 | ||
| 1348 | ret = _regmap_raw_write(map, reg, val, val_len, false); | 1406 | ret = _regmap_raw_write(map, reg, val, val_len); |
| 1349 | 1407 | ||
| 1350 | map->unlock(map->lock_arg); | 1408 | map->unlock(map->lock_arg); |
| 1351 | 1409 | ||
| @@ -1369,6 +1427,74 @@ int regmap_field_write(struct regmap_field *field, unsigned int val) | |||
| 1369 | } | 1427 | } |
| 1370 | EXPORT_SYMBOL_GPL(regmap_field_write); | 1428 | EXPORT_SYMBOL_GPL(regmap_field_write); |
| 1371 | 1429 | ||
| 1430 | /** | ||
| 1431 | * regmap_field_update_bits(): Perform a read/modify/write cycle | ||
| 1432 | * on the register field | ||
| 1433 | * | ||
| 1434 | * @field: Register field to write to | ||
| 1435 | * @mask: Bitmask to change | ||
| 1436 | * @val: Value to be written | ||
| 1437 | * | ||
| 1438 | * A value of zero will be returned on success, a negative errno will | ||
| 1439 | * be returned in error cases. | ||
| 1440 | */ | ||
| 1441 | int regmap_field_update_bits(struct regmap_field *field, unsigned int mask, unsigned int val) | ||
| 1442 | { | ||
| 1443 | mask = (mask << field->shift) & field->mask; | ||
| 1444 | |||
| 1445 | return regmap_update_bits(field->regmap, field->reg, | ||
| 1446 | mask, val << field->shift); | ||
| 1447 | } | ||
| 1448 | EXPORT_SYMBOL_GPL(regmap_field_update_bits); | ||
| 1449 | |||
| 1450 | /** | ||
| 1451 | * regmap_fields_write(): Write a value to a single register field with port ID | ||
| 1452 | * | ||
| 1453 | * @field: Register field to write to | ||
| 1454 | * @id: port ID | ||
| 1455 | * @val: Value to be written | ||
| 1456 | * | ||
| 1457 | * A value of zero will be returned on success, a negative errno will | ||
| 1458 | * be returned in error cases. | ||
| 1459 | */ | ||
| 1460 | int regmap_fields_write(struct regmap_field *field, unsigned int id, | ||
| 1461 | unsigned int val) | ||
| 1462 | { | ||
| 1463 | if (id >= field->id_size) | ||
| 1464 | return -EINVAL; | ||
| 1465 | |||
| 1466 | return regmap_update_bits(field->regmap, | ||
| 1467 | field->reg + (field->id_offset * id), | ||
| 1468 | field->mask, val << field->shift); | ||
| 1469 | } | ||
| 1470 | EXPORT_SYMBOL_GPL(regmap_fields_write); | ||
| 1471 | |||
| 1472 | /** | ||
| 1473 | * regmap_fields_update_bits(): Perform a read/modify/write cycle | ||
| 1474 | * on the register field | ||
| 1475 | * | ||
| 1476 | * @field: Register field to write to | ||
| 1477 | * @id: port ID | ||
| 1478 | * @mask: Bitmask to change | ||
| 1479 | * @val: Value to be written | ||
| 1480 | * | ||
| 1481 | * A value of zero will be returned on success, a negative errno will | ||
| 1482 | * be returned in error cases. | ||
| 1483 | */ | ||
| 1484 | int regmap_fields_update_bits(struct regmap_field *field, unsigned int id, | ||
| 1485 | unsigned int mask, unsigned int val) | ||
| 1486 | { | ||
| 1487 | if (id >= field->id_size) | ||
| 1488 | return -EINVAL; | ||
| 1489 | |||
| 1490 | mask = (mask << field->shift) & field->mask; | ||
| 1491 | |||
| 1492 | return regmap_update_bits(field->regmap, | ||
| 1493 | field->reg + (field->id_offset * id), | ||
| 1494 | mask, val << field->shift); | ||
| 1495 | } | ||
| 1496 | EXPORT_SYMBOL_GPL(regmap_fields_update_bits); | ||
| 1497 | |||
| 1372 | /* | 1498 | /* |
| 1373 | * regmap_bulk_write(): Write multiple registers to the device | 1499 | * regmap_bulk_write(): Write multiple registers to the device |
| 1374 | * | 1500 | * |
| @@ -1418,16 +1544,15 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val, | |||
| 1418 | */ | 1544 | */ |
| 1419 | if (map->use_single_rw) { | 1545 | if (map->use_single_rw) { |
| 1420 | for (i = 0; i < val_count; i++) { | 1546 | for (i = 0; i < val_count; i++) { |
| 1421 | ret = regmap_raw_write(map, | 1547 | ret = _regmap_raw_write(map, |
| 1422 | reg + (i * map->reg_stride), | 1548 | reg + (i * map->reg_stride), |
| 1423 | val + (i * val_bytes), | 1549 | val + (i * val_bytes), |
| 1424 | val_bytes); | 1550 | val_bytes); |
| 1425 | if (ret != 0) | 1551 | if (ret != 0) |
| 1426 | return ret; | 1552 | return ret; |
| 1427 | } | 1553 | } |
| 1428 | } else { | 1554 | } else { |
| 1429 | ret = _regmap_raw_write(map, reg, wval, val_bytes * val_count, | 1555 | ret = _regmap_raw_write(map, reg, wval, val_bytes * val_count); |
| 1430 | false); | ||
| 1431 | } | 1556 | } |
| 1432 | 1557 | ||
| 1433 | if (val_bytes != 1) | 1558 | if (val_bytes != 1) |
| @@ -1439,6 +1564,47 @@ out: | |||
| 1439 | } | 1564 | } |
| 1440 | EXPORT_SYMBOL_GPL(regmap_bulk_write); | 1565 | EXPORT_SYMBOL_GPL(regmap_bulk_write); |
| 1441 | 1566 | ||
| 1567 | /* | ||
| 1568 | * regmap_multi_reg_write(): Write multiple registers to the device | ||
| 1569 | * | ||
| 1570 | * where the set of register are supplied in any order | ||
| 1571 | * | ||
| 1572 | * @map: Register map to write to | ||
| 1573 | * @regs: Array of structures containing register,value to be written | ||
| 1574 | * @num_regs: Number of registers to write | ||
| 1575 | * | ||
| 1576 | * This function is intended to be used for writing a large block of data | ||
| 1577 | * atomically to the device in single transfer for those I2C client devices | ||
| 1578 | * that implement this alternative block write mode. | ||
| 1579 | * | ||
| 1580 | * A value of zero will be returned on success, a negative errno will | ||
| 1581 | * be returned in error cases. | ||
| 1582 | */ | ||
| 1583 | int regmap_multi_reg_write(struct regmap *map, struct reg_default *regs, | ||
| 1584 | int num_regs) | ||
| 1585 | { | ||
| 1586 | int ret = 0, i; | ||
| 1587 | |||
| 1588 | for (i = 0; i < num_regs; i++) { | ||
| 1589 | int reg = regs[i].reg; | ||
| 1590 | if (reg % map->reg_stride) | ||
| 1591 | return -EINVAL; | ||
| 1592 | } | ||
| 1593 | |||
| 1594 | map->lock(map->lock_arg); | ||
| 1595 | |||
| 1596 | for (i = 0; i < num_regs; i++) { | ||
| 1597 | ret = _regmap_write(map, regs[i].reg, regs[i].def); | ||
| 1598 | if (ret != 0) | ||
| 1599 | goto out; | ||
| 1600 | } | ||
| 1601 | out: | ||
| 1602 | map->unlock(map->lock_arg); | ||
| 1603 | |||
| 1604 | return ret; | ||
| 1605 | } | ||
| 1606 | EXPORT_SYMBOL_GPL(regmap_multi_reg_write); | ||
| 1607 | |||
| 1442 | /** | 1608 | /** |
| 1443 | * regmap_raw_write_async(): Write raw values to one or more registers | 1609 | * regmap_raw_write_async(): Write raw values to one or more registers |
| 1444 | * asynchronously | 1610 | * asynchronously |
| @@ -1473,7 +1639,11 @@ int regmap_raw_write_async(struct regmap *map, unsigned int reg, | |||
| 1473 | 1639 | ||
| 1474 | map->lock(map->lock_arg); | 1640 | map->lock(map->lock_arg); |
| 1475 | 1641 | ||
| 1476 | ret = _regmap_raw_write(map, reg, val, val_len, true); | 1642 | map->async = true; |
| 1643 | |||
| 1644 | ret = _regmap_raw_write(map, reg, val, val_len); | ||
| 1645 | |||
| 1646 | map->async = false; | ||
| 1477 | 1647 | ||
| 1478 | map->unlock(map->lock_arg); | 1648 | map->unlock(map->lock_arg); |
| 1479 | 1649 | ||
| @@ -1677,6 +1847,39 @@ int regmap_field_read(struct regmap_field *field, unsigned int *val) | |||
| 1677 | EXPORT_SYMBOL_GPL(regmap_field_read); | 1847 | EXPORT_SYMBOL_GPL(regmap_field_read); |
| 1678 | 1848 | ||
| 1679 | /** | 1849 | /** |
| 1850 | * regmap_fields_read(): Read a value to a single register field with port ID | ||
| 1851 | * | ||
| 1852 | * @field: Register field to read from | ||
| 1853 | * @id: port ID | ||
| 1854 | * @val: Pointer to store read value | ||
| 1855 | * | ||
| 1856 | * A value of zero will be returned on success, a negative errno will | ||
| 1857 | * be returned in error cases. | ||
| 1858 | */ | ||
| 1859 | int regmap_fields_read(struct regmap_field *field, unsigned int id, | ||
| 1860 | unsigned int *val) | ||
| 1861 | { | ||
| 1862 | int ret; | ||
| 1863 | unsigned int reg_val; | ||
| 1864 | |||
| 1865 | if (id >= field->id_size) | ||
| 1866 | return -EINVAL; | ||
| 1867 | |||
| 1868 | ret = regmap_read(field->regmap, | ||
| 1869 | field->reg + (field->id_offset * id), | ||
| 1870 | ®_val); | ||
| 1871 | if (ret != 0) | ||
| 1872 | return ret; | ||
| 1873 | |||
| 1874 | reg_val &= field->mask; | ||
| 1875 | reg_val >>= field->shift; | ||
| 1876 | *val = reg_val; | ||
| 1877 | |||
| 1878 | return ret; | ||
| 1879 | } | ||
| 1880 | EXPORT_SYMBOL_GPL(regmap_fields_read); | ||
| 1881 | |||
| 1882 | /** | ||
| 1680 | * regmap_bulk_read(): Read multiple registers from the device | 1883 | * regmap_bulk_read(): Read multiple registers from the device |
| 1681 | * | 1884 | * |
| 1682 | * @map: Register map to write to | 1885 | * @map: Register map to write to |
| @@ -1788,6 +1991,41 @@ int regmap_update_bits(struct regmap *map, unsigned int reg, | |||
| 1788 | EXPORT_SYMBOL_GPL(regmap_update_bits); | 1991 | EXPORT_SYMBOL_GPL(regmap_update_bits); |
| 1789 | 1992 | ||
| 1790 | /** | 1993 | /** |
| 1994 | * regmap_update_bits_async: Perform a read/modify/write cycle on the register | ||
| 1995 | * map asynchronously | ||
| 1996 | * | ||
| 1997 | * @map: Register map to update | ||
| 1998 | * @reg: Register to update | ||
| 1999 | * @mask: Bitmask to change | ||
| 2000 | * @val: New value for bitmask | ||
| 2001 | * | ||
| 2002 | * With most buses the read must be done synchronously so this is most | ||
| 2003 | * useful for devices with a cache which do not need to interact with | ||
| 2004 | * the hardware to determine the current register value. | ||
| 2005 | * | ||
| 2006 | * Returns zero for success, a negative number on error. | ||
| 2007 | */ | ||
| 2008 | int regmap_update_bits_async(struct regmap *map, unsigned int reg, | ||
| 2009 | unsigned int mask, unsigned int val) | ||
| 2010 | { | ||
| 2011 | bool change; | ||
| 2012 | int ret; | ||
| 2013 | |||
| 2014 | map->lock(map->lock_arg); | ||
| 2015 | |||
| 2016 | map->async = true; | ||
| 2017 | |||
| 2018 | ret = _regmap_update_bits(map, reg, mask, val, &change); | ||
| 2019 | |||
| 2020 | map->async = false; | ||
| 2021 | |||
| 2022 | map->unlock(map->lock_arg); | ||
| 2023 | |||
| 2024 | return ret; | ||
| 2025 | } | ||
| 2026 | EXPORT_SYMBOL_GPL(regmap_update_bits_async); | ||
| 2027 | |||
| 2028 | /** | ||
| 1791 | * regmap_update_bits_check: Perform a read/modify/write cycle on the | 2029 | * regmap_update_bits_check: Perform a read/modify/write cycle on the |
| 1792 | * register map and report if updated | 2030 | * register map and report if updated |
| 1793 | * | 2031 | * |
| @@ -1812,6 +2050,43 @@ int regmap_update_bits_check(struct regmap *map, unsigned int reg, | |||
| 1812 | } | 2050 | } |
| 1813 | EXPORT_SYMBOL_GPL(regmap_update_bits_check); | 2051 | EXPORT_SYMBOL_GPL(regmap_update_bits_check); |
| 1814 | 2052 | ||
| 2053 | /** | ||
| 2054 | * regmap_update_bits_check_async: Perform a read/modify/write cycle on the | ||
| 2055 | * register map asynchronously and report if | ||
| 2056 | * updated | ||
| 2057 | * | ||
| 2058 | * @map: Register map to update | ||
| 2059 | * @reg: Register to update | ||
| 2060 | * @mask: Bitmask to change | ||
| 2061 | * @val: New value for bitmask | ||
| 2062 | * @change: Boolean indicating if a write was done | ||
| 2063 | * | ||
| 2064 | * With most buses the read must be done synchronously so this is most | ||
| 2065 | * useful for devices with a cache which do not need to interact with | ||
| 2066 | * the hardware to determine the current register value. | ||
| 2067 | * | ||
| 2068 | * Returns zero for success, a negative number on error. | ||
| 2069 | */ | ||
| 2070 | int regmap_update_bits_check_async(struct regmap *map, unsigned int reg, | ||
| 2071 | unsigned int mask, unsigned int val, | ||
| 2072 | bool *change) | ||
| 2073 | { | ||
| 2074 | int ret; | ||
| 2075 | |||
| 2076 | map->lock(map->lock_arg); | ||
| 2077 | |||
| 2078 | map->async = true; | ||
| 2079 | |||
| 2080 | ret = _regmap_update_bits(map, reg, mask, val, change); | ||
| 2081 | |||
| 2082 | map->async = false; | ||
| 2083 | |||
| 2084 | map->unlock(map->lock_arg); | ||
| 2085 | |||
| 2086 | return ret; | ||
| 2087 | } | ||
| 2088 | EXPORT_SYMBOL_GPL(regmap_update_bits_check_async); | ||
| 2089 | |||
| 1815 | void regmap_async_complete_cb(struct regmap_async *async, int ret) | 2090 | void regmap_async_complete_cb(struct regmap_async *async, int ret) |
| 1816 | { | 2091 | { |
| 1817 | struct regmap *map = async->map; | 2092 | struct regmap *map = async->map; |
| @@ -1820,8 +2095,7 @@ void regmap_async_complete_cb(struct regmap_async *async, int ret) | |||
| 1820 | trace_regmap_async_io_complete(map->dev); | 2095 | trace_regmap_async_io_complete(map->dev); |
| 1821 | 2096 | ||
| 1822 | spin_lock(&map->async_lock); | 2097 | spin_lock(&map->async_lock); |
| 1823 | 2098 | list_move(&async->list, &map->async_free); | |
| 1824 | list_del(&async->list); | ||
| 1825 | wake = list_empty(&map->async_list); | 2099 | wake = list_empty(&map->async_list); |
| 1826 | 2100 | ||
| 1827 | if (ret != 0) | 2101 | if (ret != 0) |
| @@ -1829,8 +2103,6 @@ void regmap_async_complete_cb(struct regmap_async *async, int ret) | |||
| 1829 | 2103 | ||
| 1830 | spin_unlock(&map->async_lock); | 2104 | spin_unlock(&map->async_lock); |
| 1831 | 2105 | ||
| 1832 | schedule_work(&async->cleanup); | ||
| 1833 | |||
| 1834 | if (wake) | 2106 | if (wake) |
| 1835 | wake_up(&map->async_waitq); | 2107 | wake_up(&map->async_waitq); |
| 1836 | } | 2108 | } |
| @@ -1906,6 +2178,7 @@ int regmap_register_patch(struct regmap *map, const struct reg_default *regs, | |||
| 1906 | bypass = map->cache_bypass; | 2178 | bypass = map->cache_bypass; |
| 1907 | 2179 | ||
| 1908 | map->cache_bypass = true; | 2180 | map->cache_bypass = true; |
| 2181 | map->async = true; | ||
| 1909 | 2182 | ||
| 1910 | /* Write out first; it's useful to apply even if we fail later. */ | 2183 | /* Write out first; it's useful to apply even if we fail later. */ |
| 1911 | for (i = 0; i < num_regs; i++) { | 2184 | for (i = 0; i < num_regs; i++) { |
| @@ -1929,10 +2202,13 @@ int regmap_register_patch(struct regmap *map, const struct reg_default *regs, | |||
| 1929 | } | 2202 | } |
| 1930 | 2203 | ||
| 1931 | out: | 2204 | out: |
| 2205 | map->async = false; | ||
| 1932 | map->cache_bypass = bypass; | 2206 | map->cache_bypass = bypass; |
| 1933 | 2207 | ||
| 1934 | map->unlock(map->lock_arg); | 2208 | map->unlock(map->lock_arg); |
| 1935 | 2209 | ||
| 2210 | regmap_async_complete(map); | ||
| 2211 | |||
| 1936 | return ret; | 2212 | return ret; |
| 1937 | } | 2213 | } |
| 1938 | EXPORT_SYMBOL_GPL(regmap_register_patch); | 2214 | EXPORT_SYMBOL_GPL(regmap_register_patch); |
diff --git a/include/linux/regmap.h b/include/linux/regmap.h index a10380bfbeac..e55907804d39 100644 --- a/include/linux/regmap.h +++ b/include/linux/regmap.h | |||
| @@ -23,6 +23,7 @@ struct device; | |||
| 23 | struct i2c_client; | 23 | struct i2c_client; |
| 24 | struct irq_domain; | 24 | struct irq_domain; |
| 25 | struct spi_device; | 25 | struct spi_device; |
| 26 | struct spmi_device; | ||
| 26 | struct regmap; | 27 | struct regmap; |
| 27 | struct regmap_range_cfg; | 28 | struct regmap_range_cfg; |
| 28 | struct regmap_field; | 29 | struct regmap_field; |
| @@ -70,6 +71,8 @@ struct regmap_range { | |||
| 70 | unsigned int range_max; | 71 | unsigned int range_max; |
| 71 | }; | 72 | }; |
| 72 | 73 | ||
| 74 | #define regmap_reg_range(low, high) { .range_min = low, .range_max = high, } | ||
| 75 | |||
| 73 | /* | 76 | /* |
| 74 | * A table of ranges including some yes ranges and some no ranges. | 77 | * A table of ranges including some yes ranges and some no ranges. |
| 75 | * If a register belongs to a no_range, the corresponding check function | 78 | * If a register belongs to a no_range, the corresponding check function |
| @@ -318,6 +321,8 @@ struct regmap *regmap_init_i2c(struct i2c_client *i2c, | |||
| 318 | const struct regmap_config *config); | 321 | const struct regmap_config *config); |
| 319 | struct regmap *regmap_init_spi(struct spi_device *dev, | 322 | struct regmap *regmap_init_spi(struct spi_device *dev, |
| 320 | const struct regmap_config *config); | 323 | const struct regmap_config *config); |
| 324 | struct regmap *regmap_init_spmi(struct spmi_device *dev, | ||
| 325 | const struct regmap_config *config); | ||
| 321 | struct regmap *regmap_init_mmio_clk(struct device *dev, const char *clk_id, | 326 | struct regmap *regmap_init_mmio_clk(struct device *dev, const char *clk_id, |
| 322 | void __iomem *regs, | 327 | void __iomem *regs, |
| 323 | const struct regmap_config *config); | 328 | const struct regmap_config *config); |
| @@ -330,6 +335,8 @@ struct regmap *devm_regmap_init_i2c(struct i2c_client *i2c, | |||
| 330 | const struct regmap_config *config); | 335 | const struct regmap_config *config); |
| 331 | struct regmap *devm_regmap_init_spi(struct spi_device *dev, | 336 | struct regmap *devm_regmap_init_spi(struct spi_device *dev, |
| 332 | const struct regmap_config *config); | 337 | const struct regmap_config *config); |
| 338 | struct regmap *devm_regmap_init_spmi(struct spmi_device *dev, | ||
| 339 | const struct regmap_config *config); | ||
| 333 | struct regmap *devm_regmap_init_mmio_clk(struct device *dev, const char *clk_id, | 340 | struct regmap *devm_regmap_init_mmio_clk(struct device *dev, const char *clk_id, |
| 334 | void __iomem *regs, | 341 | void __iomem *regs, |
| 335 | const struct regmap_config *config); | 342 | const struct regmap_config *config); |
| @@ -374,10 +381,13 @@ int regmap_reinit_cache(struct regmap *map, | |||
| 374 | const struct regmap_config *config); | 381 | const struct regmap_config *config); |
| 375 | struct regmap *dev_get_regmap(struct device *dev, const char *name); | 382 | struct regmap *dev_get_regmap(struct device *dev, const char *name); |
| 376 | int regmap_write(struct regmap *map, unsigned int reg, unsigned int val); | 383 | int regmap_write(struct regmap *map, unsigned int reg, unsigned int val); |
| 384 | int regmap_write_async(struct regmap *map, unsigned int reg, unsigned int val); | ||
| 377 | int regmap_raw_write(struct regmap *map, unsigned int reg, | 385 | int regmap_raw_write(struct regmap *map, unsigned int reg, |
| 378 | const void *val, size_t val_len); | 386 | const void *val, size_t val_len); |
| 379 | int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val, | 387 | int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val, |
| 380 | size_t val_count); | 388 | size_t val_count); |
| 389 | int regmap_multi_reg_write(struct regmap *map, struct reg_default *regs, | ||
| 390 | int num_regs); | ||
| 381 | int regmap_raw_write_async(struct regmap *map, unsigned int reg, | 391 | int regmap_raw_write_async(struct regmap *map, unsigned int reg, |
| 382 | const void *val, size_t val_len); | 392 | const void *val, size_t val_len); |
| 383 | int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val); | 393 | int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val); |
| @@ -387,9 +397,14 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val, | |||
| 387 | size_t val_count); | 397 | size_t val_count); |
| 388 | int regmap_update_bits(struct regmap *map, unsigned int reg, | 398 | int regmap_update_bits(struct regmap *map, unsigned int reg, |
| 389 | unsigned int mask, unsigned int val); | 399 | unsigned int mask, unsigned int val); |
| 400 | int regmap_update_bits_async(struct regmap *map, unsigned int reg, | ||
| 401 | unsigned int mask, unsigned int val); | ||
| 390 | int regmap_update_bits_check(struct regmap *map, unsigned int reg, | 402 | int regmap_update_bits_check(struct regmap *map, unsigned int reg, |
| 391 | unsigned int mask, unsigned int val, | 403 | unsigned int mask, unsigned int val, |
| 392 | bool *change); | 404 | bool *change); |
| 405 | int regmap_update_bits_check_async(struct regmap *map, unsigned int reg, | ||
| 406 | unsigned int mask, unsigned int val, | ||
| 407 | bool *change); | ||
| 393 | int regmap_get_val_bytes(struct regmap *map); | 408 | int regmap_get_val_bytes(struct regmap *map); |
| 394 | int regmap_async_complete(struct regmap *map); | 409 | int regmap_async_complete(struct regmap *map); |
| 395 | bool regmap_can_raw_write(struct regmap *map); | 410 | bool regmap_can_raw_write(struct regmap *map); |
| @@ -425,11 +440,15 @@ bool regmap_reg_in_ranges(unsigned int reg, | |||
| 425 | * @reg: Offset of the register within the regmap bank | 440 | * @reg: Offset of the register within the regmap bank |
| 426 | * @lsb: lsb of the register field. | 441 | * @lsb: lsb of the register field. |
| 427 | * @reg: msb of the register field. | 442 | * @reg: msb of the register field. |
| 443 | * @id_size: port size if it has some ports | ||
| 444 | * @id_offset: address offset for each ports | ||
| 428 | */ | 445 | */ |
| 429 | struct reg_field { | 446 | struct reg_field { |
| 430 | unsigned int reg; | 447 | unsigned int reg; |
| 431 | unsigned int lsb; | 448 | unsigned int lsb; |
| 432 | unsigned int msb; | 449 | unsigned int msb; |
| 450 | unsigned int id_size; | ||
| 451 | unsigned int id_offset; | ||
| 433 | }; | 452 | }; |
| 434 | 453 | ||
| 435 | #define REG_FIELD(_reg, _lsb, _msb) { \ | 454 | #define REG_FIELD(_reg, _lsb, _msb) { \ |
| @@ -448,6 +467,15 @@ void devm_regmap_field_free(struct device *dev, struct regmap_field *field); | |||
| 448 | 467 | ||
| 449 | int regmap_field_read(struct regmap_field *field, unsigned int *val); | 468 | int regmap_field_read(struct regmap_field *field, unsigned int *val); |
| 450 | int regmap_field_write(struct regmap_field *field, unsigned int val); | 469 | int regmap_field_write(struct regmap_field *field, unsigned int val); |
| 470 | int regmap_field_update_bits(struct regmap_field *field, | ||
| 471 | unsigned int mask, unsigned int val); | ||
| 472 | |||
| 473 | int regmap_fields_write(struct regmap_field *field, unsigned int id, | ||
| 474 | unsigned int val); | ||
| 475 | int regmap_fields_read(struct regmap_field *field, unsigned int id, | ||
| 476 | unsigned int *val); | ||
| 477 | int regmap_fields_update_bits(struct regmap_field *field, unsigned int id, | ||
| 478 | unsigned int mask, unsigned int val); | ||
| 451 | 479 | ||
| 452 | /** | 480 | /** |
| 453 | * Description of an IRQ for the generic regmap irq_chip. | 481 | * Description of an IRQ for the generic regmap irq_chip. |
| @@ -527,6 +555,13 @@ static inline int regmap_write(struct regmap *map, unsigned int reg, | |||
| 527 | return -EINVAL; | 555 | return -EINVAL; |
| 528 | } | 556 | } |
| 529 | 557 | ||
| 558 | static inline int regmap_write_async(struct regmap *map, unsigned int reg, | ||
| 559 | unsigned int val) | ||
| 560 | { | ||
| 561 | WARN_ONCE(1, "regmap API is disabled"); | ||
| 562 | return -EINVAL; | ||
| 563 | } | ||
| 564 | |||
| 530 | static inline int regmap_raw_write(struct regmap *map, unsigned int reg, | 565 | static inline int regmap_raw_write(struct regmap *map, unsigned int reg, |
| 531 | const void *val, size_t val_len) | 566 | const void *val, size_t val_len) |
| 532 | { | 567 | { |
| @@ -576,6 +611,14 @@ static inline int regmap_update_bits(struct regmap *map, unsigned int reg, | |||
| 576 | return -EINVAL; | 611 | return -EINVAL; |
| 577 | } | 612 | } |
| 578 | 613 | ||
| 614 | static inline int regmap_update_bits_async(struct regmap *map, | ||
| 615 | unsigned int reg, | ||
| 616 | unsigned int mask, unsigned int val) | ||
| 617 | { | ||
| 618 | WARN_ONCE(1, "regmap API is disabled"); | ||
| 619 | return -EINVAL; | ||
| 620 | } | ||
| 621 | |||
| 579 | static inline int regmap_update_bits_check(struct regmap *map, | 622 | static inline int regmap_update_bits_check(struct regmap *map, |
| 580 | unsigned int reg, | 623 | unsigned int reg, |
| 581 | unsigned int mask, unsigned int val, | 624 | unsigned int mask, unsigned int val, |
| @@ -585,6 +628,16 @@ static inline int regmap_update_bits_check(struct regmap *map, | |||
| 585 | return -EINVAL; | 628 | return -EINVAL; |
| 586 | } | 629 | } |
| 587 | 630 | ||
| 631 | static inline int regmap_update_bits_check_async(struct regmap *map, | ||
| 632 | unsigned int reg, | ||
| 633 | unsigned int mask, | ||
| 634 | unsigned int val, | ||
| 635 | bool *change) | ||
| 636 | { | ||
| 637 | WARN_ONCE(1, "regmap API is disabled"); | ||
| 638 | return -EINVAL; | ||
| 639 | } | ||
| 640 | |||
| 588 | static inline int regmap_get_val_bytes(struct regmap *map) | 641 | static inline int regmap_get_val_bytes(struct regmap *map) |
| 589 | { | 642 | { |
| 590 | WARN_ONCE(1, "regmap API is disabled"); | 643 | WARN_ONCE(1, "regmap API is disabled"); |
