diff options
author | Mark Brown <broonie@kernel.org> | 2016-02-02 07:16:51 -0500 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2016-02-02 12:58:22 -0500 |
commit | 3245d460a1eb55b5c3ca31dde7b5c5ac71546edf (patch) | |
tree | 656fb73fa195f877a5e09f37ea60c145b67c56ef | |
parent | bb2bb45d1be28987e6cb50f50e4819795537ab83 (diff) |
regmap: cache: Fall back to register by register read for cache defaults
If we are unable to read the cache defaults for a regmap then fall back
on attempting to read them word by word. This is going to be painfully
slow for large regmaps but might be adequate for smaller ones.
Signed-off-by: Mark Brown <broonie@kernel.org>
[maciej: Use cache_bypass around read and skipping of unreadable regs]
Signed-off-by: Maciej S. Szmigiero <mail@maciej.szmigiero.name>
Signed-off-by: Fabio Estevam <fabio.estevam@nxp.com>
Tested-by: Fabio Estevam <fabio.estevam@nxp.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r-- | drivers/base/regmap/regcache.c | 41 |
1 files changed, 30 insertions, 11 deletions
diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c index 348be3a35410..cccceb599b02 100644 --- a/drivers/base/regmap/regcache.c +++ b/drivers/base/regmap/regcache.c | |||
@@ -30,7 +30,7 @@ static int regcache_hw_init(struct regmap *map) | |||
30 | int i, j; | 30 | int i, j; |
31 | int ret; | 31 | int ret; |
32 | int count; | 32 | int count; |
33 | unsigned int val; | 33 | unsigned int reg, val; |
34 | void *tmp_buf; | 34 | void *tmp_buf; |
35 | 35 | ||
36 | if (!map->num_reg_defaults_raw) | 36 | if (!map->num_reg_defaults_raw) |
@@ -67,27 +67,46 @@ static int regcache_hw_init(struct regmap *map) | |||
67 | ret = regmap_raw_read(map, 0, tmp_buf, | 67 | ret = regmap_raw_read(map, 0, tmp_buf, |
68 | map->num_reg_defaults_raw); | 68 | map->num_reg_defaults_raw); |
69 | map->cache_bypass = cache_bypass; | 69 | map->cache_bypass = cache_bypass; |
70 | if (ret < 0) | 70 | if (ret == 0) { |
71 | goto err_cache_free; | 71 | map->reg_defaults_raw = tmp_buf; |
72 | 72 | map->cache_free = 1; | |
73 | map->reg_defaults_raw = tmp_buf; | 73 | } else { |
74 | map->cache_free = 1; | 74 | kfree(tmp_buf); |
75 | } | ||
75 | } | 76 | } |
76 | 77 | ||
77 | /* fill the reg_defaults */ | 78 | /* fill the reg_defaults */ |
78 | for (i = 0, j = 0; i < map->num_reg_defaults_raw; i++) { | 79 | for (i = 0, j = 0; i < map->num_reg_defaults_raw; i++) { |
79 | if (regmap_volatile(map, i * map->reg_stride)) | 80 | reg = i * map->reg_stride; |
81 | |||
82 | if (!regmap_readable(map, reg)) | ||
80 | continue; | 83 | continue; |
81 | val = regcache_get_val(map, map->reg_defaults_raw, i); | 84 | |
82 | map->reg_defaults[j].reg = i * map->reg_stride; | 85 | if (regmap_volatile(map, reg)) |
86 | continue; | ||
87 | |||
88 | if (map->reg_defaults_raw) { | ||
89 | val = regcache_get_val(map, map->reg_defaults_raw, i); | ||
90 | } else { | ||
91 | bool cache_bypass = map->cache_bypass; | ||
92 | |||
93 | map->cache_bypass = true; | ||
94 | ret = regmap_read(map, reg, &val); | ||
95 | map->cache_bypass = cache_bypass; | ||
96 | if (ret != 0) { | ||
97 | dev_err(map->dev, "Failed to read %d: %d\n", | ||
98 | reg, ret); | ||
99 | goto err_free; | ||
100 | } | ||
101 | } | ||
102 | |||
103 | map->reg_defaults[j].reg = reg; | ||
83 | map->reg_defaults[j].def = val; | 104 | map->reg_defaults[j].def = val; |
84 | j++; | 105 | j++; |
85 | } | 106 | } |
86 | 107 | ||
87 | return 0; | 108 | return 0; |
88 | 109 | ||
89 | err_cache_free: | ||
90 | kfree(tmp_buf); | ||
91 | err_free: | 110 | err_free: |
92 | kfree(map->reg_defaults); | 111 | kfree(map->reg_defaults); |
93 | 112 | ||