diff options
Diffstat (limited to 'drivers/base')
-rw-r--r-- | drivers/base/component.c | 8 | ||||
-rw-r--r-- | drivers/base/dma-buf.c | 25 | ||||
-rw-r--r-- | drivers/base/firmware_class.c | 1 | ||||
-rw-r--r-- | drivers/base/regmap/internal.h | 2 | ||||
-rw-r--r-- | drivers/base/regmap/regcache.c | 13 | ||||
-rw-r--r-- | drivers/base/regmap/regmap-debugfs.c | 2 | ||||
-rw-r--r-- | drivers/base/regmap/regmap-mmio.c | 56 | ||||
-rw-r--r-- | drivers/base/regmap/regmap.c | 353 |
8 files changed, 372 insertions, 88 deletions
diff --git a/drivers/base/component.c b/drivers/base/component.c index c53efe6c6d8e..c4778995cd72 100644 --- a/drivers/base/component.c +++ b/drivers/base/component.c | |||
@@ -133,9 +133,16 @@ static int try_to_bring_up_master(struct master *master, | |||
133 | goto out; | 133 | goto out; |
134 | } | 134 | } |
135 | 135 | ||
136 | if (!devres_open_group(master->dev, NULL, GFP_KERNEL)) { | ||
137 | ret = -ENOMEM; | ||
138 | goto out; | ||
139 | } | ||
140 | |||
136 | /* Found all components */ | 141 | /* Found all components */ |
137 | ret = master->ops->bind(master->dev); | 142 | ret = master->ops->bind(master->dev); |
138 | if (ret < 0) { | 143 | if (ret < 0) { |
144 | devres_release_group(master->dev, NULL); | ||
145 | dev_info(master->dev, "master bind failed: %d\n", ret); | ||
139 | master_remove_components(master); | 146 | master_remove_components(master); |
140 | goto out; | 147 | goto out; |
141 | } | 148 | } |
@@ -166,6 +173,7 @@ static void take_down_master(struct master *master) | |||
166 | { | 173 | { |
167 | if (master->bound) { | 174 | if (master->bound) { |
168 | master->ops->unbind(master->dev); | 175 | master->ops->unbind(master->dev); |
176 | devres_release_group(master->dev, NULL); | ||
169 | master->bound = false; | 177 | master->bound = false; |
170 | } | 178 | } |
171 | 179 | ||
diff --git a/drivers/base/dma-buf.c b/drivers/base/dma-buf.c index 1e16cbd61da2..61d6d62cc0d3 100644 --- a/drivers/base/dma-buf.c +++ b/drivers/base/dma-buf.c | |||
@@ -616,36 +616,35 @@ static int dma_buf_describe(struct seq_file *s) | |||
616 | if (ret) | 616 | if (ret) |
617 | return ret; | 617 | return ret; |
618 | 618 | ||
619 | seq_printf(s, "\nDma-buf Objects:\n"); | 619 | seq_puts(s, "\nDma-buf Objects:\n"); |
620 | seq_printf(s, "\texp_name\tsize\tflags\tmode\tcount\n"); | 620 | seq_puts(s, "size\tflags\tmode\tcount\texp_name\n"); |
621 | 621 | ||
622 | list_for_each_entry(buf_obj, &db_list.head, list_node) { | 622 | list_for_each_entry(buf_obj, &db_list.head, list_node) { |
623 | ret = mutex_lock_interruptible(&buf_obj->lock); | 623 | ret = mutex_lock_interruptible(&buf_obj->lock); |
624 | 624 | ||
625 | if (ret) { | 625 | if (ret) { |
626 | seq_printf(s, | 626 | seq_puts(s, |
627 | "\tERROR locking buffer object: skipping\n"); | 627 | "\tERROR locking buffer object: skipping\n"); |
628 | continue; | 628 | continue; |
629 | } | 629 | } |
630 | 630 | ||
631 | seq_printf(s, "\t"); | 631 | seq_printf(s, "%08zu\t%08x\t%08x\t%08ld\t%s\n", |
632 | 632 | buf_obj->size, | |
633 | seq_printf(s, "\t%s\t%08zu\t%08x\t%08x\t%08ld\n", | ||
634 | buf_obj->exp_name, buf_obj->size, | ||
635 | buf_obj->file->f_flags, buf_obj->file->f_mode, | 633 | buf_obj->file->f_flags, buf_obj->file->f_mode, |
636 | (long)(buf_obj->file->f_count.counter)); | 634 | (long)(buf_obj->file->f_count.counter), |
635 | buf_obj->exp_name); | ||
637 | 636 | ||
638 | seq_printf(s, "\t\tAttached Devices:\n"); | 637 | seq_puts(s, "\tAttached Devices:\n"); |
639 | attach_count = 0; | 638 | attach_count = 0; |
640 | 639 | ||
641 | list_for_each_entry(attach_obj, &buf_obj->attachments, node) { | 640 | list_for_each_entry(attach_obj, &buf_obj->attachments, node) { |
642 | seq_printf(s, "\t\t"); | 641 | seq_puts(s, "\t"); |
643 | 642 | ||
644 | seq_printf(s, "%s\n", attach_obj->dev->init_name); | 643 | seq_printf(s, "%s\n", dev_name(attach_obj->dev)); |
645 | attach_count++; | 644 | attach_count++; |
646 | } | 645 | } |
647 | 646 | ||
648 | seq_printf(s, "\n\t\tTotal %d devices attached\n", | 647 | seq_printf(s, "Total %d devices attached\n\n", |
649 | attach_count); | 648 | attach_count); |
650 | 649 | ||
651 | count++; | 650 | count++; |
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 8a97ddfa6122..c30df50e4440 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c | |||
@@ -1580,6 +1580,7 @@ static int fw_pm_notify(struct notifier_block *notify_block, | |||
1580 | switch (mode) { | 1580 | switch (mode) { |
1581 | case PM_HIBERNATION_PREPARE: | 1581 | case PM_HIBERNATION_PREPARE: |
1582 | case PM_SUSPEND_PREPARE: | 1582 | case PM_SUSPEND_PREPARE: |
1583 | case PM_RESTORE_PREPARE: | ||
1583 | kill_requests_without_uevent(); | 1584 | kill_requests_without_uevent(); |
1584 | device_cache_fw_images(); | 1585 | device_cache_fw_images(); |
1585 | break; | 1586 | break; |
diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h index 33414b1de201..7d1326985bee 100644 --- a/drivers/base/regmap/internal.h +++ b/drivers/base/regmap/internal.h | |||
@@ -134,6 +134,8 @@ struct regmap { | |||
134 | 134 | ||
135 | /* if set, converts bulk rw to single rw */ | 135 | /* if set, converts bulk rw to single rw */ |
136 | bool use_single_rw; | 136 | bool use_single_rw; |
137 | /* if set, the device supports multi write mode */ | ||
138 | bool can_multi_write; | ||
137 | 139 | ||
138 | struct rb_root range_tree; | 140 | struct rb_root range_tree; |
139 | void *selector_work_buf; /* Scratch buffer used for selector */ | 141 | void *selector_work_buf; /* Scratch buffer used for selector */ |
diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c index d4dd77134814..29b4128da0b0 100644 --- a/drivers/base/regmap/regcache.c +++ b/drivers/base/regmap/regcache.c | |||
@@ -249,11 +249,12 @@ static int regcache_default_sync(struct regmap *map, unsigned int min, | |||
249 | { | 249 | { |
250 | unsigned int reg; | 250 | unsigned int reg; |
251 | 251 | ||
252 | for (reg = min; reg <= max; reg++) { | 252 | for (reg = min; reg <= max; reg += map->reg_stride) { |
253 | unsigned int val; | 253 | unsigned int val; |
254 | int ret; | 254 | int ret; |
255 | 255 | ||
256 | if (regmap_volatile(map, reg)) | 256 | if (regmap_volatile(map, reg) || |
257 | !regmap_writeable(map, reg)) | ||
257 | continue; | 258 | continue; |
258 | 259 | ||
259 | ret = regcache_read(map, reg, &val); | 260 | ret = regcache_read(map, reg, &val); |
@@ -312,10 +313,6 @@ int regcache_sync(struct regmap *map) | |||
312 | /* Apply any patch first */ | 313 | /* Apply any patch first */ |
313 | map->cache_bypass = 1; | 314 | map->cache_bypass = 1; |
314 | for (i = 0; i < map->patch_regs; i++) { | 315 | for (i = 0; i < map->patch_regs; i++) { |
315 | if (map->patch[i].reg % map->reg_stride) { | ||
316 | ret = -EINVAL; | ||
317 | goto out; | ||
318 | } | ||
319 | ret = _regmap_write(map, map->patch[i].reg, map->patch[i].def); | 316 | ret = _regmap_write(map, map->patch[i].reg, map->patch[i].def); |
320 | if (ret != 0) { | 317 | if (ret != 0) { |
321 | dev_err(map->dev, "Failed to write %x = %x: %d\n", | 318 | dev_err(map->dev, "Failed to write %x = %x: %d\n", |
@@ -636,10 +633,10 @@ static int regcache_sync_block_raw_flush(struct regmap *map, const void **data, | |||
636 | if (*data == NULL) | 633 | if (*data == NULL) |
637 | return 0; | 634 | return 0; |
638 | 635 | ||
639 | count = cur - base; | 636 | count = (cur - base) / map->reg_stride; |
640 | 637 | ||
641 | dev_dbg(map->dev, "Writing %zu bytes for %d registers from 0x%x-0x%x\n", | 638 | dev_dbg(map->dev, "Writing %zu bytes for %d registers from 0x%x-0x%x\n", |
642 | count * val_bytes, count, base, cur - 1); | 639 | count * val_bytes, count, base, cur - map->reg_stride); |
643 | 640 | ||
644 | map->cache_bypass = 1; | 641 | map->cache_bypass = 1; |
645 | 642 | ||
diff --git a/drivers/base/regmap/regmap-debugfs.c b/drivers/base/regmap/regmap-debugfs.c index c5471cd6ebb7..45d812c0ea77 100644 --- a/drivers/base/regmap/regmap-debugfs.c +++ b/drivers/base/regmap/regmap-debugfs.c | |||
@@ -511,7 +511,7 @@ void regmap_debugfs_init(struct regmap *map, const char *name) | |||
511 | debugfs_create_file("range", 0400, map->debugfs, | 511 | debugfs_create_file("range", 0400, map->debugfs, |
512 | map, ®map_reg_ranges_fops); | 512 | map, ®map_reg_ranges_fops); |
513 | 513 | ||
514 | if (map->max_register) { | 514 | if (map->max_register || regmap_readable(map, 0)) { |
515 | debugfs_create_file("registers", 0400, map->debugfs, | 515 | debugfs_create_file("registers", 0400, map->debugfs, |
516 | map, ®map_map_fops); | 516 | map, ®map_map_fops); |
517 | debugfs_create_file("access", 0400, map->debugfs, | 517 | debugfs_create_file("access", 0400, map->debugfs, |
diff --git a/drivers/base/regmap/regmap-mmio.c b/drivers/base/regmap/regmap-mmio.c index 81f977510775..de45a1e1548f 100644 --- a/drivers/base/regmap/regmap-mmio.c +++ b/drivers/base/regmap/regmap-mmio.c | |||
@@ -26,10 +26,47 @@ | |||
26 | 26 | ||
27 | struct regmap_mmio_context { | 27 | struct regmap_mmio_context { |
28 | void __iomem *regs; | 28 | void __iomem *regs; |
29 | unsigned reg_bytes; | ||
29 | unsigned val_bytes; | 30 | unsigned val_bytes; |
31 | unsigned pad_bytes; | ||
30 | struct clk *clk; | 32 | struct clk *clk; |
31 | }; | 33 | }; |
32 | 34 | ||
35 | static inline void regmap_mmio_regsize_check(size_t reg_size) | ||
36 | { | ||
37 | switch (reg_size) { | ||
38 | case 1: | ||
39 | case 2: | ||
40 | case 4: | ||
41 | #ifdef CONFIG_64BIT | ||
42 | case 8: | ||
43 | #endif | ||
44 | break; | ||
45 | default: | ||
46 | BUG(); | ||
47 | } | ||
48 | } | ||
49 | |||
50 | static int regmap_mmio_regbits_check(size_t reg_bits) | ||
51 | { | ||
52 | switch (reg_bits) { | ||
53 | case 8: | ||
54 | case 16: | ||
55 | case 32: | ||
56 | #ifdef CONFIG_64BIT | ||
57 | case 64: | ||
58 | #endif | ||
59 | return 0; | ||
60 | default: | ||
61 | return -EINVAL; | ||
62 | } | ||
63 | } | ||
64 | |||
65 | static inline void regmap_mmio_count_check(size_t count) | ||
66 | { | ||
67 | BUG_ON(count % 2 != 0); | ||
68 | } | ||
69 | |||
33 | static int regmap_mmio_gather_write(void *context, | 70 | static int regmap_mmio_gather_write(void *context, |
34 | const void *reg, size_t reg_size, | 71 | const void *reg, size_t reg_size, |
35 | const void *val, size_t val_size) | 72 | const void *val, size_t val_size) |
@@ -38,7 +75,7 @@ static int regmap_mmio_gather_write(void *context, | |||
38 | u32 offset; | 75 | u32 offset; |
39 | int ret; | 76 | int ret; |
40 | 77 | ||
41 | BUG_ON(reg_size != 4); | 78 | regmap_mmio_regsize_check(reg_size); |
42 | 79 | ||
43 | if (!IS_ERR(ctx->clk)) { | 80 | if (!IS_ERR(ctx->clk)) { |
44 | ret = clk_enable(ctx->clk); | 81 | ret = clk_enable(ctx->clk); |
@@ -81,9 +118,13 @@ static int regmap_mmio_gather_write(void *context, | |||
81 | 118 | ||
82 | static int regmap_mmio_write(void *context, const void *data, size_t count) | 119 | static int regmap_mmio_write(void *context, const void *data, size_t count) |
83 | { | 120 | { |
84 | BUG_ON(count < 4); | 121 | struct regmap_mmio_context *ctx = context; |
122 | u32 offset = ctx->reg_bytes + ctx->pad_bytes; | ||
123 | |||
124 | regmap_mmio_count_check(count); | ||
85 | 125 | ||
86 | return regmap_mmio_gather_write(context, data, 4, data + 4, count - 4); | 126 | return regmap_mmio_gather_write(context, data, ctx->reg_bytes, |
127 | data + offset, count - offset); | ||
87 | } | 128 | } |
88 | 129 | ||
89 | static int regmap_mmio_read(void *context, | 130 | static int regmap_mmio_read(void *context, |
@@ -94,7 +135,7 @@ static int regmap_mmio_read(void *context, | |||
94 | u32 offset; | 135 | u32 offset; |
95 | int ret; | 136 | int ret; |
96 | 137 | ||
97 | BUG_ON(reg_size != 4); | 138 | regmap_mmio_regsize_check(reg_size); |
98 | 139 | ||
99 | if (!IS_ERR(ctx->clk)) { | 140 | if (!IS_ERR(ctx->clk)) { |
100 | ret = clk_enable(ctx->clk); | 141 | ret = clk_enable(ctx->clk); |
@@ -165,8 +206,9 @@ static struct regmap_mmio_context *regmap_mmio_gen_context(struct device *dev, | |||
165 | int min_stride; | 206 | int min_stride; |
166 | int ret; | 207 | int ret; |
167 | 208 | ||
168 | if (config->reg_bits != 32) | 209 | ret = regmap_mmio_regbits_check(config->reg_bits); |
169 | return ERR_PTR(-EINVAL); | 210 | if (ret) |
211 | return ERR_PTR(ret); | ||
170 | 212 | ||
171 | if (config->pad_bits) | 213 | if (config->pad_bits) |
172 | return ERR_PTR(-EINVAL); | 214 | return ERR_PTR(-EINVAL); |
@@ -209,6 +251,8 @@ static struct regmap_mmio_context *regmap_mmio_gen_context(struct device *dev, | |||
209 | 251 | ||
210 | ctx->regs = regs; | 252 | ctx->regs = regs; |
211 | ctx->val_bytes = config->val_bits / 8; | 253 | ctx->val_bytes = config->val_bits / 8; |
254 | ctx->reg_bytes = config->reg_bits / 8; | ||
255 | ctx->pad_bytes = config->pad_bits / 8; | ||
212 | ctx->clk = ERR_PTR(-ENODEV); | 256 | ctx->clk = ERR_PTR(-ENODEV); |
213 | 257 | ||
214 | if (clk_id == NULL) | 258 | if (clk_id == NULL) |
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index 6a19515f8a45..d0a072463a04 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c | |||
@@ -380,6 +380,28 @@ static void regmap_range_exit(struct regmap *map) | |||
380 | kfree(map->selector_work_buf); | 380 | kfree(map->selector_work_buf); |
381 | } | 381 | } |
382 | 382 | ||
383 | int regmap_attach_dev(struct device *dev, struct regmap *map, | ||
384 | const struct regmap_config *config) | ||
385 | { | ||
386 | struct regmap **m; | ||
387 | |||
388 | map->dev = dev; | ||
389 | |||
390 | regmap_debugfs_init(map, config->name); | ||
391 | |||
392 | /* Add a devres resource for dev_get_regmap() */ | ||
393 | m = devres_alloc(dev_get_regmap_release, sizeof(*m), GFP_KERNEL); | ||
394 | if (!m) { | ||
395 | regmap_debugfs_exit(map); | ||
396 | return -ENOMEM; | ||
397 | } | ||
398 | *m = map; | ||
399 | devres_add(dev, m); | ||
400 | |||
401 | return 0; | ||
402 | } | ||
403 | EXPORT_SYMBOL_GPL(regmap_attach_dev); | ||
404 | |||
383 | /** | 405 | /** |
384 | * regmap_init(): Initialise register map | 406 | * regmap_init(): Initialise register map |
385 | * | 407 | * |
@@ -397,7 +419,7 @@ struct regmap *regmap_init(struct device *dev, | |||
397 | void *bus_context, | 419 | void *bus_context, |
398 | const struct regmap_config *config) | 420 | const struct regmap_config *config) |
399 | { | 421 | { |
400 | struct regmap *map, **m; | 422 | struct regmap *map; |
401 | int ret = -EINVAL; | 423 | int ret = -EINVAL; |
402 | enum regmap_endian reg_endian, val_endian; | 424 | enum regmap_endian reg_endian, val_endian; |
403 | int i, j; | 425 | int i, j; |
@@ -439,6 +461,7 @@ struct regmap *regmap_init(struct device *dev, | |||
439 | else | 461 | else |
440 | map->reg_stride = 1; | 462 | map->reg_stride = 1; |
441 | map->use_single_rw = config->use_single_rw; | 463 | map->use_single_rw = config->use_single_rw; |
464 | map->can_multi_write = config->can_multi_write; | ||
442 | map->dev = dev; | 465 | map->dev = dev; |
443 | map->bus = bus; | 466 | map->bus = bus; |
444 | map->bus_context = bus_context; | 467 | map->bus_context = bus_context; |
@@ -718,7 +741,7 @@ skip_format_initialization: | |||
718 | new->window_start = range_cfg->window_start; | 741 | new->window_start = range_cfg->window_start; |
719 | new->window_len = range_cfg->window_len; | 742 | new->window_len = range_cfg->window_len; |
720 | 743 | ||
721 | if (_regmap_range_add(map, new) == false) { | 744 | if (!_regmap_range_add(map, new)) { |
722 | dev_err(map->dev, "Failed to add range %d\n", i); | 745 | dev_err(map->dev, "Failed to add range %d\n", i); |
723 | kfree(new); | 746 | kfree(new); |
724 | goto err_range; | 747 | goto err_range; |
@@ -734,25 +757,18 @@ skip_format_initialization: | |||
734 | } | 757 | } |
735 | } | 758 | } |
736 | 759 | ||
737 | regmap_debugfs_init(map, config->name); | ||
738 | |||
739 | ret = regcache_init(map, config); | 760 | ret = regcache_init(map, config); |
740 | if (ret != 0) | 761 | if (ret != 0) |
741 | goto err_range; | 762 | goto err_range; |
742 | 763 | ||
743 | /* Add a devres resource for dev_get_regmap() */ | 764 | if (dev) |
744 | m = devres_alloc(dev_get_regmap_release, sizeof(*m), GFP_KERNEL); | 765 | ret = regmap_attach_dev(dev, map, config); |
745 | if (!m) { | 766 | if (ret != 0) |
746 | ret = -ENOMEM; | 767 | goto err_regcache; |
747 | goto err_debugfs; | ||
748 | } | ||
749 | *m = map; | ||
750 | devres_add(dev, m); | ||
751 | 768 | ||
752 | return map; | 769 | return map; |
753 | 770 | ||
754 | err_debugfs: | 771 | err_regcache: |
755 | regmap_debugfs_exit(map); | ||
756 | regcache_exit(map); | 772 | regcache_exit(map); |
757 | err_range: | 773 | err_range: |
758 | regmap_range_exit(map); | 774 | regmap_range_exit(map); |
@@ -1520,12 +1536,12 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val, | |||
1520 | if (reg % map->reg_stride) | 1536 | if (reg % map->reg_stride) |
1521 | return -EINVAL; | 1537 | return -EINVAL; |
1522 | 1538 | ||
1523 | map->lock(map->lock_arg); | ||
1524 | /* | 1539 | /* |
1525 | * Some devices don't support bulk write, for | 1540 | * Some devices don't support bulk write, for |
1526 | * them we have a series of single write operations. | 1541 | * them we have a series of single write operations. |
1527 | */ | 1542 | */ |
1528 | if (!map->bus || map->use_single_rw) { | 1543 | if (!map->bus || map->use_single_rw) { |
1544 | map->lock(map->lock_arg); | ||
1529 | for (i = 0; i < val_count; i++) { | 1545 | for (i = 0; i < val_count; i++) { |
1530 | unsigned int ival; | 1546 | unsigned int ival; |
1531 | 1547 | ||
@@ -1554,31 +1570,239 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val, | |||
1554 | if (ret != 0) | 1570 | if (ret != 0) |
1555 | goto out; | 1571 | goto out; |
1556 | } | 1572 | } |
1573 | out: | ||
1574 | map->unlock(map->lock_arg); | ||
1557 | } else { | 1575 | } else { |
1558 | void *wval; | 1576 | void *wval; |
1559 | 1577 | ||
1560 | wval = kmemdup(val, val_count * val_bytes, GFP_KERNEL); | 1578 | wval = kmemdup(val, val_count * val_bytes, GFP_KERNEL); |
1561 | if (!wval) { | 1579 | if (!wval) { |
1562 | ret = -ENOMEM; | ||
1563 | dev_err(map->dev, "Error in memory allocation\n"); | 1580 | dev_err(map->dev, "Error in memory allocation\n"); |
1564 | goto out; | 1581 | return -ENOMEM; |
1565 | } | 1582 | } |
1566 | for (i = 0; i < val_count * val_bytes; i += val_bytes) | 1583 | for (i = 0; i < val_count * val_bytes; i += val_bytes) |
1567 | map->format.parse_inplace(wval + i); | 1584 | map->format.parse_inplace(wval + i); |
1568 | 1585 | ||
1586 | map->lock(map->lock_arg); | ||
1569 | ret = _regmap_raw_write(map, reg, wval, val_bytes * val_count); | 1587 | ret = _regmap_raw_write(map, reg, wval, val_bytes * val_count); |
1588 | map->unlock(map->lock_arg); | ||
1570 | 1589 | ||
1571 | kfree(wval); | 1590 | kfree(wval); |
1572 | } | 1591 | } |
1573 | out: | ||
1574 | map->unlock(map->lock_arg); | ||
1575 | return ret; | 1592 | return ret; |
1576 | } | 1593 | } |
1577 | EXPORT_SYMBOL_GPL(regmap_bulk_write); | 1594 | EXPORT_SYMBOL_GPL(regmap_bulk_write); |
1578 | 1595 | ||
1579 | /* | 1596 | /* |
1597 | * _regmap_raw_multi_reg_write() | ||
1598 | * | ||
1599 | * the (register,newvalue) pairs in regs have not been formatted, but | ||
1600 | * they are all in the same page and have been changed to being page | ||
1601 | * relative. The page register has been written if that was neccessary. | ||
1602 | */ | ||
1603 | static int _regmap_raw_multi_reg_write(struct regmap *map, | ||
1604 | const struct reg_default *regs, | ||
1605 | size_t num_regs) | ||
1606 | { | ||
1607 | int ret; | ||
1608 | void *buf; | ||
1609 | int i; | ||
1610 | u8 *u8; | ||
1611 | size_t val_bytes = map->format.val_bytes; | ||
1612 | size_t reg_bytes = map->format.reg_bytes; | ||
1613 | size_t pad_bytes = map->format.pad_bytes; | ||
1614 | size_t pair_size = reg_bytes + pad_bytes + val_bytes; | ||
1615 | size_t len = pair_size * num_regs; | ||
1616 | |||
1617 | buf = kzalloc(len, GFP_KERNEL); | ||
1618 | if (!buf) | ||
1619 | return -ENOMEM; | ||
1620 | |||
1621 | /* We have to linearise by hand. */ | ||
1622 | |||
1623 | u8 = buf; | ||
1624 | |||
1625 | for (i = 0; i < num_regs; i++) { | ||
1626 | int reg = regs[i].reg; | ||
1627 | int val = regs[i].def; | ||
1628 | trace_regmap_hw_write_start(map->dev, reg, 1); | ||
1629 | map->format.format_reg(u8, reg, map->reg_shift); | ||
1630 | u8 += reg_bytes + pad_bytes; | ||
1631 | map->format.format_val(u8, val, 0); | ||
1632 | u8 += val_bytes; | ||
1633 | } | ||
1634 | u8 = buf; | ||
1635 | *u8 |= map->write_flag_mask; | ||
1636 | |||
1637 | ret = map->bus->write(map->bus_context, buf, len); | ||
1638 | |||
1639 | kfree(buf); | ||
1640 | |||
1641 | for (i = 0; i < num_regs; i++) { | ||
1642 | int reg = regs[i].reg; | ||
1643 | trace_regmap_hw_write_done(map->dev, reg, 1); | ||
1644 | } | ||
1645 | return ret; | ||
1646 | } | ||
1647 | |||
1648 | static unsigned int _regmap_register_page(struct regmap *map, | ||
1649 | unsigned int reg, | ||
1650 | struct regmap_range_node *range) | ||
1651 | { | ||
1652 | unsigned int win_page = (reg - range->range_min) / range->window_len; | ||
1653 | |||
1654 | return win_page; | ||
1655 | } | ||
1656 | |||
1657 | static int _regmap_range_multi_paged_reg_write(struct regmap *map, | ||
1658 | struct reg_default *regs, | ||
1659 | size_t num_regs) | ||
1660 | { | ||
1661 | int ret; | ||
1662 | int i, n; | ||
1663 | struct reg_default *base; | ||
1664 | unsigned int this_page; | ||
1665 | /* | ||
1666 | * the set of registers are not neccessarily in order, but | ||
1667 | * since the order of write must be preserved this algorithm | ||
1668 | * chops the set each time the page changes | ||
1669 | */ | ||
1670 | base = regs; | ||
1671 | for (i = 0, n = 0; i < num_regs; i++, n++) { | ||
1672 | unsigned int reg = regs[i].reg; | ||
1673 | struct regmap_range_node *range; | ||
1674 | |||
1675 | range = _regmap_range_lookup(map, reg); | ||
1676 | if (range) { | ||
1677 | unsigned int win_page = _regmap_register_page(map, reg, | ||
1678 | range); | ||
1679 | |||
1680 | if (i == 0) | ||
1681 | this_page = win_page; | ||
1682 | if (win_page != this_page) { | ||
1683 | this_page = win_page; | ||
1684 | ret = _regmap_raw_multi_reg_write(map, base, n); | ||
1685 | if (ret != 0) | ||
1686 | return ret; | ||
1687 | base += n; | ||
1688 | n = 0; | ||
1689 | } | ||
1690 | ret = _regmap_select_page(map, &base[n].reg, range, 1); | ||
1691 | if (ret != 0) | ||
1692 | return ret; | ||
1693 | } | ||
1694 | } | ||
1695 | if (n > 0) | ||
1696 | return _regmap_raw_multi_reg_write(map, base, n); | ||
1697 | return 0; | ||
1698 | } | ||
1699 | |||
1700 | static int _regmap_multi_reg_write(struct regmap *map, | ||
1701 | const struct reg_default *regs, | ||
1702 | size_t num_regs) | ||
1703 | { | ||
1704 | int i; | ||
1705 | int ret; | ||
1706 | |||
1707 | if (!map->can_multi_write) { | ||
1708 | for (i = 0; i < num_regs; i++) { | ||
1709 | ret = _regmap_write(map, regs[i].reg, regs[i].def); | ||
1710 | if (ret != 0) | ||
1711 | return ret; | ||
1712 | } | ||
1713 | return 0; | ||
1714 | } | ||
1715 | |||
1716 | if (!map->format.parse_inplace) | ||
1717 | return -EINVAL; | ||
1718 | |||
1719 | if (map->writeable_reg) | ||
1720 | for (i = 0; i < num_regs; i++) { | ||
1721 | int reg = regs[i].reg; | ||
1722 | if (!map->writeable_reg(map->dev, reg)) | ||
1723 | return -EINVAL; | ||
1724 | if (reg % map->reg_stride) | ||
1725 | return -EINVAL; | ||
1726 | } | ||
1727 | |||
1728 | if (!map->cache_bypass) { | ||
1729 | for (i = 0; i < num_regs; i++) { | ||
1730 | unsigned int val = regs[i].def; | ||
1731 | unsigned int reg = regs[i].reg; | ||
1732 | ret = regcache_write(map, reg, val); | ||
1733 | if (ret) { | ||
1734 | dev_err(map->dev, | ||
1735 | "Error in caching of register: %x ret: %d\n", | ||
1736 | reg, ret); | ||
1737 | return ret; | ||
1738 | } | ||
1739 | } | ||
1740 | if (map->cache_only) { | ||
1741 | map->cache_dirty = true; | ||
1742 | return 0; | ||
1743 | } | ||
1744 | } | ||
1745 | |||
1746 | WARN_ON(!map->bus); | ||
1747 | |||
1748 | for (i = 0; i < num_regs; i++) { | ||
1749 | unsigned int reg = regs[i].reg; | ||
1750 | struct regmap_range_node *range; | ||
1751 | range = _regmap_range_lookup(map, reg); | ||
1752 | if (range) { | ||
1753 | size_t len = sizeof(struct reg_default)*num_regs; | ||
1754 | struct reg_default *base = kmemdup(regs, len, | ||
1755 | GFP_KERNEL); | ||
1756 | if (!base) | ||
1757 | return -ENOMEM; | ||
1758 | ret = _regmap_range_multi_paged_reg_write(map, base, | ||
1759 | num_regs); | ||
1760 | kfree(base); | ||
1761 | |||
1762 | return ret; | ||
1763 | } | ||
1764 | } | ||
1765 | return _regmap_raw_multi_reg_write(map, regs, num_regs); | ||
1766 | } | ||
1767 | |||
1768 | /* | ||
1580 | * regmap_multi_reg_write(): Write multiple registers to the device | 1769 | * regmap_multi_reg_write(): Write multiple registers to the device |
1581 | * | 1770 | * |
1771 | * where the set of register,value pairs are supplied in any order, | ||
1772 | * possibly not all in a single range. | ||
1773 | * | ||
1774 | * @map: Register map to write to | ||
1775 | * @regs: Array of structures containing register,value to be written | ||
1776 | * @num_regs: Number of registers to write | ||
1777 | * | ||
1778 | * The 'normal' block write mode will send ultimately send data on the | ||
1779 | * target bus as R,V1,V2,V3,..,Vn where successively higer registers are | ||
1780 | * addressed. However, this alternative block multi write mode will send | ||
1781 | * the data as R1,V1,R2,V2,..,Rn,Vn on the target bus. The target device | ||
1782 | * must of course support the mode. | ||
1783 | * | ||
1784 | * A value of zero will be returned on success, a negative errno will be | ||
1785 | * returned in error cases. | ||
1786 | */ | ||
1787 | int regmap_multi_reg_write(struct regmap *map, const struct reg_default *regs, | ||
1788 | int num_regs) | ||
1789 | { | ||
1790 | int ret; | ||
1791 | |||
1792 | map->lock(map->lock_arg); | ||
1793 | |||
1794 | ret = _regmap_multi_reg_write(map, regs, num_regs); | ||
1795 | |||
1796 | map->unlock(map->lock_arg); | ||
1797 | |||
1798 | return ret; | ||
1799 | } | ||
1800 | EXPORT_SYMBOL_GPL(regmap_multi_reg_write); | ||
1801 | |||
1802 | /* | ||
1803 | * regmap_multi_reg_write_bypassed(): Write multiple registers to the | ||
1804 | * device but not the cache | ||
1805 | * | ||
1582 | * where the set of register are supplied in any order | 1806 | * where the set of register are supplied in any order |
1583 | * | 1807 | * |
1584 | * @map: Register map to write to | 1808 | * @map: Register map to write to |
@@ -1592,30 +1816,27 @@ EXPORT_SYMBOL_GPL(regmap_bulk_write); | |||
1592 | * A value of zero will be returned on success, a negative errno will | 1816 | * A value of zero will be returned on success, a negative errno will |
1593 | * be returned in error cases. | 1817 | * be returned in error cases. |
1594 | */ | 1818 | */ |
1595 | int regmap_multi_reg_write(struct regmap *map, struct reg_default *regs, | 1819 | int regmap_multi_reg_write_bypassed(struct regmap *map, |
1596 | int num_regs) | 1820 | const struct reg_default *regs, |
1821 | int num_regs) | ||
1597 | { | 1822 | { |
1598 | int ret = 0, i; | 1823 | int ret; |
1599 | 1824 | bool bypass; | |
1600 | for (i = 0; i < num_regs; i++) { | ||
1601 | int reg = regs[i].reg; | ||
1602 | if (reg % map->reg_stride) | ||
1603 | return -EINVAL; | ||
1604 | } | ||
1605 | 1825 | ||
1606 | map->lock(map->lock_arg); | 1826 | map->lock(map->lock_arg); |
1607 | 1827 | ||
1608 | for (i = 0; i < num_regs; i++) { | 1828 | bypass = map->cache_bypass; |
1609 | ret = _regmap_write(map, regs[i].reg, regs[i].def); | 1829 | map->cache_bypass = true; |
1610 | if (ret != 0) | 1830 | |
1611 | goto out; | 1831 | ret = _regmap_multi_reg_write(map, regs, num_regs); |
1612 | } | 1832 | |
1613 | out: | 1833 | map->cache_bypass = bypass; |
1834 | |||
1614 | map->unlock(map->lock_arg); | 1835 | map->unlock(map->lock_arg); |
1615 | 1836 | ||
1616 | return ret; | 1837 | return ret; |
1617 | } | 1838 | } |
1618 | EXPORT_SYMBOL_GPL(regmap_multi_reg_write); | 1839 | EXPORT_SYMBOL_GPL(regmap_multi_reg_write_bypassed); |
1619 | 1840 | ||
1620 | /** | 1841 | /** |
1621 | * regmap_raw_write_async(): Write raw values to one or more registers | 1842 | * regmap_raw_write_async(): Write raw values to one or more registers |
@@ -1736,6 +1957,9 @@ static int _regmap_read(struct regmap *map, unsigned int reg, | |||
1736 | if (map->cache_only) | 1957 | if (map->cache_only) |
1737 | return -EBUSY; | 1958 | return -EBUSY; |
1738 | 1959 | ||
1960 | if (!regmap_readable(map, reg)) | ||
1961 | return -EIO; | ||
1962 | |||
1739 | ret = map->reg_read(context, reg, val); | 1963 | ret = map->reg_read(context, reg, val); |
1740 | if (ret == 0) { | 1964 | if (ret == 0) { |
1741 | #ifdef LOG_DEVICE | 1965 | #ifdef LOG_DEVICE |
@@ -1966,9 +2190,11 @@ static int _regmap_update_bits(struct regmap *map, unsigned int reg, | |||
1966 | 2190 | ||
1967 | if (tmp != orig) { | 2191 | if (tmp != orig) { |
1968 | ret = _regmap_write(map, reg, tmp); | 2192 | ret = _regmap_write(map, reg, tmp); |
1969 | *change = true; | 2193 | if (change) |
2194 | *change = true; | ||
1970 | } else { | 2195 | } else { |
1971 | *change = false; | 2196 | if (change) |
2197 | *change = false; | ||
1972 | } | 2198 | } |
1973 | 2199 | ||
1974 | return ret; | 2200 | return ret; |
@@ -1987,11 +2213,10 @@ static int _regmap_update_bits(struct regmap *map, unsigned int reg, | |||
1987 | int regmap_update_bits(struct regmap *map, unsigned int reg, | 2213 | int regmap_update_bits(struct regmap *map, unsigned int reg, |
1988 | unsigned int mask, unsigned int val) | 2214 | unsigned int mask, unsigned int val) |
1989 | { | 2215 | { |
1990 | bool change; | ||
1991 | int ret; | 2216 | int ret; |
1992 | 2217 | ||
1993 | map->lock(map->lock_arg); | 2218 | map->lock(map->lock_arg); |
1994 | ret = _regmap_update_bits(map, reg, mask, val, &change); | 2219 | ret = _regmap_update_bits(map, reg, mask, val, NULL); |
1995 | map->unlock(map->lock_arg); | 2220 | map->unlock(map->lock_arg); |
1996 | 2221 | ||
1997 | return ret; | 2222 | return ret; |
@@ -2016,14 +2241,13 @@ EXPORT_SYMBOL_GPL(regmap_update_bits); | |||
2016 | int regmap_update_bits_async(struct regmap *map, unsigned int reg, | 2241 | int regmap_update_bits_async(struct regmap *map, unsigned int reg, |
2017 | unsigned int mask, unsigned int val) | 2242 | unsigned int mask, unsigned int val) |
2018 | { | 2243 | { |
2019 | bool change; | ||
2020 | int ret; | 2244 | int ret; |
2021 | 2245 | ||
2022 | map->lock(map->lock_arg); | 2246 | map->lock(map->lock_arg); |
2023 | 2247 | ||
2024 | map->async = true; | 2248 | map->async = true; |
2025 | 2249 | ||
2026 | ret = _regmap_update_bits(map, reg, mask, val, &change); | 2250 | ret = _regmap_update_bits(map, reg, mask, val, NULL); |
2027 | 2251 | ||
2028 | map->async = false; | 2252 | map->async = false; |
2029 | 2253 | ||
@@ -2173,35 +2397,21 @@ EXPORT_SYMBOL_GPL(regmap_async_complete); | |||
2173 | * apply them immediately. Typically this is used to apply | 2397 | * apply them immediately. Typically this is used to apply |
2174 | * corrections to be applied to the device defaults on startup, such | 2398 | * corrections to be applied to the device defaults on startup, such |
2175 | * as the updates some vendors provide to undocumented registers. | 2399 | * as the updates some vendors provide to undocumented registers. |
2400 | * | ||
2401 | * The caller must ensure that this function cannot be called | ||
2402 | * concurrently with either itself or regcache_sync(). | ||
2176 | */ | 2403 | */ |
2177 | int regmap_register_patch(struct regmap *map, const struct reg_default *regs, | 2404 | int regmap_register_patch(struct regmap *map, const struct reg_default *regs, |
2178 | int num_regs) | 2405 | int num_regs) |
2179 | { | 2406 | { |
2180 | struct reg_default *p; | 2407 | struct reg_default *p; |
2181 | int i, ret; | 2408 | int ret; |
2182 | bool bypass; | 2409 | bool bypass; |
2183 | 2410 | ||
2184 | if (WARN_ONCE(num_regs <= 0, "invalid registers number (%d)\n", | 2411 | if (WARN_ONCE(num_regs <= 0, "invalid registers number (%d)\n", |
2185 | num_regs)) | 2412 | num_regs)) |
2186 | return 0; | 2413 | return 0; |
2187 | 2414 | ||
2188 | map->lock(map->lock_arg); | ||
2189 | |||
2190 | bypass = map->cache_bypass; | ||
2191 | |||
2192 | map->cache_bypass = true; | ||
2193 | map->async = true; | ||
2194 | |||
2195 | /* Write out first; it's useful to apply even if we fail later. */ | ||
2196 | for (i = 0; i < num_regs; i++) { | ||
2197 | ret = _regmap_write(map, regs[i].reg, regs[i].def); | ||
2198 | if (ret != 0) { | ||
2199 | dev_err(map->dev, "Failed to write %x = %x: %d\n", | ||
2200 | regs[i].reg, regs[i].def, ret); | ||
2201 | goto out; | ||
2202 | } | ||
2203 | } | ||
2204 | |||
2205 | p = krealloc(map->patch, | 2415 | p = krealloc(map->patch, |
2206 | sizeof(struct reg_default) * (map->patch_regs + num_regs), | 2416 | sizeof(struct reg_default) * (map->patch_regs + num_regs), |
2207 | GFP_KERNEL); | 2417 | GFP_KERNEL); |
@@ -2210,9 +2420,20 @@ int regmap_register_patch(struct regmap *map, const struct reg_default *regs, | |||
2210 | map->patch = p; | 2420 | map->patch = p; |
2211 | map->patch_regs += num_regs; | 2421 | map->patch_regs += num_regs; |
2212 | } else { | 2422 | } else { |
2213 | ret = -ENOMEM; | 2423 | return -ENOMEM; |
2214 | } | 2424 | } |
2215 | 2425 | ||
2426 | map->lock(map->lock_arg); | ||
2427 | |||
2428 | bypass = map->cache_bypass; | ||
2429 | |||
2430 | map->cache_bypass = true; | ||
2431 | map->async = true; | ||
2432 | |||
2433 | ret = _regmap_multi_reg_write(map, regs, num_regs); | ||
2434 | if (ret != 0) | ||
2435 | goto out; | ||
2436 | |||
2216 | out: | 2437 | out: |
2217 | map->async = false; | 2438 | map->async = false; |
2218 | map->cache_bypass = bypass; | 2439 | map->cache_bypass = bypass; |
@@ -2240,6 +2461,18 @@ int regmap_get_val_bytes(struct regmap *map) | |||
2240 | } | 2461 | } |
2241 | EXPORT_SYMBOL_GPL(regmap_get_val_bytes); | 2462 | EXPORT_SYMBOL_GPL(regmap_get_val_bytes); |
2242 | 2463 | ||
2464 | int regmap_parse_val(struct regmap *map, const void *buf, | ||
2465 | unsigned int *val) | ||
2466 | { | ||
2467 | if (!map->format.parse_val) | ||
2468 | return -EINVAL; | ||
2469 | |||
2470 | *val = map->format.parse_val(buf); | ||
2471 | |||
2472 | return 0; | ||
2473 | } | ||
2474 | EXPORT_SYMBOL_GPL(regmap_parse_val); | ||
2475 | |||
2243 | static int __init regmap_initcall(void) | 2476 | static int __init regmap_initcall(void) |
2244 | { | 2477 | { |
2245 | regmap_debugfs_initcall(); | 2478 | regmap_debugfs_initcall(); |