diff options
author | Ashish Jangam <ashish.jangam@kpitcummins.com> | 2012-04-30 18:23:40 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2012-04-30 18:29:56 -0400 |
commit | 2e33caf16f7a1903d226ef7f9f5ec6a234fee18e (patch) | |
tree | b557691a1197a035eee85df52d4eb05bcb9f02fb | |
parent | 56806555de5485d6786bf0f8df01b8ed9fc5d006 (diff) |
regmap: Converts group operation into single read write operations
Some devices does not support bulk read and write operations, for them
we have series of single write and read operations.
Signed-off-by: Anthony Olech <Anthony.Olech@diasemi.com>
Signed-off-by: Ashish Jangam <ashish.jangam@kpitcummins.com>
[Fixed coding style, don't check use_single_rw before assign --broonie ]
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-rw-r--r-- | drivers/base/regmap/internal.h | 3 | ||||
-rw-r--r-- | drivers/base/regmap/regmap.c | 40 | ||||
-rw-r--r-- | include/linux/regmap.h | 5 |
3 files changed, 44 insertions, 4 deletions
diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h index d92e9b1cb83c..2eb719704885 100644 --- a/drivers/base/regmap/internal.h +++ b/drivers/base/regmap/internal.h | |||
@@ -91,6 +91,9 @@ struct regmap { | |||
91 | 91 | ||
92 | struct reg_default *patch; | 92 | struct reg_default *patch; |
93 | int patch_regs; | 93 | int patch_regs; |
94 | |||
95 | /* if set, converts bulk rw to single rw */ | ||
96 | bool use_single_rw; | ||
94 | }; | 97 | }; |
95 | 98 | ||
96 | struct regcache_ops { | 99 | struct regcache_ops { |
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index 8a25006b2a4d..0a05a706e141 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c | |||
@@ -247,6 +247,7 @@ struct regmap *regmap_init(struct device *dev, | |||
247 | map->reg_stride = config->reg_stride; | 247 | map->reg_stride = config->reg_stride; |
248 | else | 248 | else |
249 | map->reg_stride = 1; | 249 | map->reg_stride = 1; |
250 | map->use_single_rw = config->use_single_rw; | ||
250 | map->dev = dev; | 251 | map->dev = dev; |
251 | map->bus = bus; | 252 | map->bus = bus; |
252 | map->bus_context = bus_context; | 253 | map->bus_context = bus_context; |
@@ -686,7 +687,22 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val, | |||
686 | for (i = 0; i < val_count * val_bytes; i += val_bytes) | 687 | for (i = 0; i < val_count * val_bytes; i += val_bytes) |
687 | map->format.parse_val(wval + i); | 688 | map->format.parse_val(wval + i); |
688 | } | 689 | } |
689 | ret = _regmap_raw_write(map, reg, wval, val_bytes * val_count); | 690 | /* |
691 | * Some devices does not support bulk write, for | ||
692 | * them we have a series of single write operations. | ||
693 | */ | ||
694 | if (map->use_single_rw) { | ||
695 | for (i = 0; i < val_count; i++) { | ||
696 | ret = regmap_raw_write(map, | ||
697 | reg + (i * map->reg_stride), | ||
698 | val + (i * val_bytes), | ||
699 | val_bytes); | ||
700 | if (ret != 0) | ||
701 | return ret; | ||
702 | } | ||
703 | } else { | ||
704 | ret = _regmap_raw_write(map, reg, wval, val_bytes * val_count); | ||
705 | } | ||
690 | 706 | ||
691 | if (val_bytes != 1) | 707 | if (val_bytes != 1) |
692 | kfree(wval); | 708 | kfree(wval); |
@@ -855,9 +871,25 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val, | |||
855 | return -EINVAL; | 871 | return -EINVAL; |
856 | 872 | ||
857 | if (vol || map->cache_type == REGCACHE_NONE) { | 873 | if (vol || map->cache_type == REGCACHE_NONE) { |
858 | ret = regmap_raw_read(map, reg, val, val_bytes * val_count); | 874 | /* |
859 | if (ret != 0) | 875 | * Some devices does not support bulk read, for |
860 | return ret; | 876 | * them we have a series of single read operations. |
877 | */ | ||
878 | if (map->use_single_rw) { | ||
879 | for (i = 0; i < val_count; i++) { | ||
880 | ret = regmap_raw_read(map, | ||
881 | reg + (i * map->reg_stride), | ||
882 | val + (i * val_bytes), | ||
883 | val_bytes); | ||
884 | if (ret != 0) | ||
885 | return ret; | ||
886 | } | ||
887 | } else { | ||
888 | ret = regmap_raw_read(map, reg, val, | ||
889 | val_bytes * val_count); | ||
890 | if (ret != 0) | ||
891 | return ret; | ||
892 | } | ||
861 | 893 | ||
862 | for (i = 0; i < val_count * val_bytes; i += val_bytes) | 894 | for (i = 0; i < val_count * val_bytes; i += val_bytes) |
863 | map->format.parse_val(val + i); | 895 | map->format.parse_val(val + i); |
diff --git a/include/linux/regmap.h b/include/linux/regmap.h index 0258bcd6258d..ae797b142aa8 100644 --- a/include/linux/regmap.h +++ b/include/linux/regmap.h | |||
@@ -76,6 +76,9 @@ struct reg_default { | |||
76 | * @write_flag_mask: Mask to be set in the top byte of the register when doing | 76 | * @write_flag_mask: Mask to be set in the top byte of the register when doing |
77 | * a write. If both read_flag_mask and write_flag_mask are | 77 | * a write. If both read_flag_mask and write_flag_mask are |
78 | * empty the regmap_bus default masks are used. | 78 | * empty the regmap_bus default masks are used. |
79 | * @use_single_rw: If set, converts the bulk read and write operations into | ||
80 | * a series of single read and write operations. This is useful | ||
81 | * for device that does not support bulk read and write. | ||
79 | * | 82 | * |
80 | * @cache_type: The actual cache type. | 83 | * @cache_type: The actual cache type. |
81 | * @reg_defaults_raw: Power on reset values for registers (for use with | 84 | * @reg_defaults_raw: Power on reset values for registers (for use with |
@@ -104,6 +107,8 @@ struct regmap_config { | |||
104 | 107 | ||
105 | u8 read_flag_mask; | 108 | u8 read_flag_mask; |
106 | u8 write_flag_mask; | 109 | u8 write_flag_mask; |
110 | |||
111 | bool use_single_rw; | ||
107 | }; | 112 | }; |
108 | 113 | ||
109 | typedef int (*regmap_hw_write)(void *context, const void *data, | 114 | typedef int (*regmap_hw_write)(void *context, const void *data, |