diff options
Diffstat (limited to 'drivers/base/regmap/regmap.c')
-rw-r--r-- | drivers/base/regmap/regmap.c | 161 |
1 files changed, 139 insertions, 22 deletions
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index 46b2bd742ee6..e3ee9cabccb4 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c | |||
@@ -10,8 +10,9 @@ | |||
10 | * published by the Free Software Foundation. | 10 | * published by the Free Software Foundation. |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/device.h> | ||
13 | #include <linux/slab.h> | 14 | #include <linux/slab.h> |
14 | #include <linux/module.h> | 15 | #include <linux/export.h> |
15 | #include <linux/mutex.h> | 16 | #include <linux/mutex.h> |
16 | #include <linux/err.h> | 17 | #include <linux/err.h> |
17 | 18 | ||
@@ -36,6 +37,9 @@ bool regmap_readable(struct regmap *map, unsigned int reg) | |||
36 | if (map->max_register && reg > map->max_register) | 37 | if (map->max_register && reg > map->max_register) |
37 | return false; | 38 | return false; |
38 | 39 | ||
40 | if (map->format.format_write) | ||
41 | return false; | ||
42 | |||
39 | if (map->readable_reg) | 43 | if (map->readable_reg) |
40 | return map->readable_reg(map->dev, reg); | 44 | return map->readable_reg(map->dev, reg); |
41 | 45 | ||
@@ -44,7 +48,7 @@ bool regmap_readable(struct regmap *map, unsigned int reg) | |||
44 | 48 | ||
45 | bool regmap_volatile(struct regmap *map, unsigned int reg) | 49 | bool regmap_volatile(struct regmap *map, unsigned int reg) |
46 | { | 50 | { |
47 | if (map->max_register && reg > map->max_register) | 51 | if (!regmap_readable(map, reg)) |
48 | return false; | 52 | return false; |
49 | 53 | ||
50 | if (map->volatile_reg) | 54 | if (map->volatile_reg) |
@@ -55,7 +59,7 @@ bool regmap_volatile(struct regmap *map, unsigned int reg) | |||
55 | 59 | ||
56 | bool regmap_precious(struct regmap *map, unsigned int reg) | 60 | bool regmap_precious(struct regmap *map, unsigned int reg) |
57 | { | 61 | { |
58 | if (map->max_register && reg > map->max_register) | 62 | if (!regmap_readable(map, reg)) |
59 | return false; | 63 | return false; |
60 | 64 | ||
61 | if (map->precious_reg) | 65 | if (map->precious_reg) |
@@ -76,6 +80,14 @@ static bool regmap_volatile_range(struct regmap *map, unsigned int reg, | |||
76 | return true; | 80 | return true; |
77 | } | 81 | } |
78 | 82 | ||
83 | static void regmap_format_2_6_write(struct regmap *map, | ||
84 | unsigned int reg, unsigned int val) | ||
85 | { | ||
86 | u8 *out = map->work_buf; | ||
87 | |||
88 | *out = (reg << 6) | val; | ||
89 | } | ||
90 | |||
79 | static void regmap_format_4_12_write(struct regmap *map, | 91 | static void regmap_format_4_12_write(struct regmap *map, |
80 | unsigned int reg, unsigned int val) | 92 | unsigned int reg, unsigned int val) |
81 | { | 93 | { |
@@ -114,6 +126,13 @@ static void regmap_format_16(void *buf, unsigned int val) | |||
114 | b[0] = cpu_to_be16(val); | 126 | b[0] = cpu_to_be16(val); |
115 | } | 127 | } |
116 | 128 | ||
129 | static void regmap_format_32(void *buf, unsigned int val) | ||
130 | { | ||
131 | __be32 *b = buf; | ||
132 | |||
133 | b[0] = cpu_to_be32(val); | ||
134 | } | ||
135 | |||
117 | static unsigned int regmap_parse_8(void *buf) | 136 | static unsigned int regmap_parse_8(void *buf) |
118 | { | 137 | { |
119 | u8 *b = buf; | 138 | u8 *b = buf; |
@@ -130,6 +149,15 @@ static unsigned int regmap_parse_16(void *buf) | |||
130 | return b[0]; | 149 | return b[0]; |
131 | } | 150 | } |
132 | 151 | ||
152 | static unsigned int regmap_parse_32(void *buf) | ||
153 | { | ||
154 | __be32 *b = buf; | ||
155 | |||
156 | b[0] = be32_to_cpu(b[0]); | ||
157 | |||
158 | return b[0]; | ||
159 | } | ||
160 | |||
133 | /** | 161 | /** |
134 | * regmap_init(): Initialise register map | 162 | * regmap_init(): Initialise register map |
135 | * | 163 | * |
@@ -159,8 +187,10 @@ struct regmap *regmap_init(struct device *dev, | |||
159 | 187 | ||
160 | mutex_init(&map->lock); | 188 | mutex_init(&map->lock); |
161 | map->format.buf_size = (config->reg_bits + config->val_bits) / 8; | 189 | map->format.buf_size = (config->reg_bits + config->val_bits) / 8; |
162 | map->format.reg_bytes = config->reg_bits / 8; | 190 | map->format.reg_bytes = DIV_ROUND_UP(config->reg_bits, 8); |
163 | map->format.val_bytes = config->val_bits / 8; | 191 | map->format.pad_bytes = config->pad_bits / 8; |
192 | map->format.val_bytes = DIV_ROUND_UP(config->val_bits, 8); | ||
193 | map->format.buf_size += map->format.pad_bytes; | ||
164 | map->dev = dev; | 194 | map->dev = dev; |
165 | map->bus = bus; | 195 | map->bus = bus; |
166 | map->max_register = config->max_register; | 196 | map->max_register = config->max_register; |
@@ -178,6 +208,16 @@ struct regmap *regmap_init(struct device *dev, | |||
178 | } | 208 | } |
179 | 209 | ||
180 | switch (config->reg_bits) { | 210 | switch (config->reg_bits) { |
211 | case 2: | ||
212 | switch (config->val_bits) { | ||
213 | case 6: | ||
214 | map->format.format_write = regmap_format_2_6_write; | ||
215 | break; | ||
216 | default: | ||
217 | goto err_map; | ||
218 | } | ||
219 | break; | ||
220 | |||
181 | case 4: | 221 | case 4: |
182 | switch (config->val_bits) { | 222 | switch (config->val_bits) { |
183 | case 12: | 223 | case 12: |
@@ -216,6 +256,10 @@ struct regmap *regmap_init(struct device *dev, | |||
216 | map->format.format_reg = regmap_format_16; | 256 | map->format.format_reg = regmap_format_16; |
217 | break; | 257 | break; |
218 | 258 | ||
259 | case 32: | ||
260 | map->format.format_reg = regmap_format_32; | ||
261 | break; | ||
262 | |||
219 | default: | 263 | default: |
220 | goto err_map; | 264 | goto err_map; |
221 | } | 265 | } |
@@ -229,13 +273,17 @@ struct regmap *regmap_init(struct device *dev, | |||
229 | map->format.format_val = regmap_format_16; | 273 | map->format.format_val = regmap_format_16; |
230 | map->format.parse_val = regmap_parse_16; | 274 | map->format.parse_val = regmap_parse_16; |
231 | break; | 275 | break; |
276 | case 32: | ||
277 | map->format.format_val = regmap_format_32; | ||
278 | map->format.parse_val = regmap_parse_32; | ||
279 | break; | ||
232 | } | 280 | } |
233 | 281 | ||
234 | if (!map->format.format_write && | 282 | if (!map->format.format_write && |
235 | !(map->format.format_reg && map->format.format_val)) | 283 | !(map->format.format_reg && map->format.format_val)) |
236 | goto err_map; | 284 | goto err_map; |
237 | 285 | ||
238 | map->work_buf = kmalloc(map->format.buf_size, GFP_KERNEL); | 286 | map->work_buf = kzalloc(map->format.buf_size, GFP_KERNEL); |
239 | if (map->work_buf == NULL) { | 287 | if (map->work_buf == NULL) { |
240 | ret = -ENOMEM; | 288 | ret = -ENOMEM; |
241 | goto err_map; | 289 | goto err_map; |
@@ -258,6 +306,45 @@ err: | |||
258 | } | 306 | } |
259 | EXPORT_SYMBOL_GPL(regmap_init); | 307 | EXPORT_SYMBOL_GPL(regmap_init); |
260 | 308 | ||
309 | static void devm_regmap_release(struct device *dev, void *res) | ||
310 | { | ||
311 | regmap_exit(*(struct regmap **)res); | ||
312 | } | ||
313 | |||
314 | /** | ||
315 | * devm_regmap_init(): Initialise managed register map | ||
316 | * | ||
317 | * @dev: Device that will be interacted with | ||
318 | * @bus: Bus-specific callbacks to use with device | ||
319 | * @config: Configuration for register map | ||
320 | * | ||
321 | * The return value will be an ERR_PTR() on error or a valid pointer | ||
322 | * to a struct regmap. This function should generally not be called | ||
323 | * directly, it should be called by bus-specific init functions. The | ||
324 | * map will be automatically freed by the device management code. | ||
325 | */ | ||
326 | struct regmap *devm_regmap_init(struct device *dev, | ||
327 | const struct regmap_bus *bus, | ||
328 | const struct regmap_config *config) | ||
329 | { | ||
330 | struct regmap **ptr, *regmap; | ||
331 | |||
332 | ptr = devres_alloc(devm_regmap_release, sizeof(*ptr), GFP_KERNEL); | ||
333 | if (!ptr) | ||
334 | return ERR_PTR(-ENOMEM); | ||
335 | |||
336 | regmap = regmap_init(dev, bus, config); | ||
337 | if (!IS_ERR(regmap)) { | ||
338 | *ptr = regmap; | ||
339 | devres_add(dev, ptr); | ||
340 | } else { | ||
341 | devres_free(ptr); | ||
342 | } | ||
343 | |||
344 | return regmap; | ||
345 | } | ||
346 | EXPORT_SYMBOL_GPL(devm_regmap_init); | ||
347 | |||
261 | /** | 348 | /** |
262 | * regmap_reinit_cache(): Reinitialise the current register cache | 349 | * regmap_reinit_cache(): Reinitialise the current register cache |
263 | * | 350 | * |
@@ -276,6 +363,7 @@ int regmap_reinit_cache(struct regmap *map, const struct regmap_config *config) | |||
276 | mutex_lock(&map->lock); | 363 | mutex_lock(&map->lock); |
277 | 364 | ||
278 | regcache_exit(map); | 365 | regcache_exit(map); |
366 | regmap_debugfs_exit(map); | ||
279 | 367 | ||
280 | map->max_register = config->max_register; | 368 | map->max_register = config->max_register; |
281 | map->writeable_reg = config->writeable_reg; | 369 | map->writeable_reg = config->writeable_reg; |
@@ -284,6 +372,11 @@ int regmap_reinit_cache(struct regmap *map, const struct regmap_config *config) | |||
284 | map->precious_reg = config->precious_reg; | 372 | map->precious_reg = config->precious_reg; |
285 | map->cache_type = config->cache_type; | 373 | map->cache_type = config->cache_type; |
286 | 374 | ||
375 | regmap_debugfs_init(map); | ||
376 | |||
377 | map->cache_bypass = false; | ||
378 | map->cache_only = false; | ||
379 | |||
287 | ret = regcache_init(map, config); | 380 | ret = regcache_init(map, config); |
288 | 381 | ||
289 | mutex_unlock(&map->lock); | 382 | mutex_unlock(&map->lock); |
@@ -329,23 +422,28 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg, | |||
329 | * send the work_buf directly, otherwise try to do a gather | 422 | * send the work_buf directly, otherwise try to do a gather |
330 | * write. | 423 | * write. |
331 | */ | 424 | */ |
332 | if (val == map->work_buf + map->format.reg_bytes) | 425 | if (val == (map->work_buf + map->format.pad_bytes + |
426 | map->format.reg_bytes)) | ||
333 | ret = map->bus->write(map->dev, map->work_buf, | 427 | ret = map->bus->write(map->dev, map->work_buf, |
334 | map->format.reg_bytes + val_len); | 428 | map->format.reg_bytes + |
429 | map->format.pad_bytes + | ||
430 | val_len); | ||
335 | else if (map->bus->gather_write) | 431 | else if (map->bus->gather_write) |
336 | ret = map->bus->gather_write(map->dev, map->work_buf, | 432 | ret = map->bus->gather_write(map->dev, map->work_buf, |
337 | map->format.reg_bytes, | 433 | map->format.reg_bytes + |
434 | map->format.pad_bytes, | ||
338 | val, val_len); | 435 | val, val_len); |
339 | 436 | ||
340 | /* If that didn't work fall back on linearising by hand. */ | 437 | /* If that didn't work fall back on linearising by hand. */ |
341 | if (ret == -ENOTSUPP) { | 438 | if (ret == -ENOTSUPP) { |
342 | len = map->format.reg_bytes + val_len; | 439 | len = map->format.reg_bytes + map->format.pad_bytes + val_len; |
343 | buf = kmalloc(len, GFP_KERNEL); | 440 | buf = kzalloc(len, GFP_KERNEL); |
344 | if (!buf) | 441 | if (!buf) |
345 | return -ENOMEM; | 442 | return -ENOMEM; |
346 | 443 | ||
347 | memcpy(buf, map->work_buf, map->format.reg_bytes); | 444 | memcpy(buf, map->work_buf, map->format.reg_bytes); |
348 | memcpy(buf + map->format.reg_bytes, val, val_len); | 445 | memcpy(buf + map->format.reg_bytes + map->format.pad_bytes, |
446 | val, val_len); | ||
349 | ret = map->bus->write(map->dev, buf, len); | 447 | ret = map->bus->write(map->dev, buf, len); |
350 | 448 | ||
351 | kfree(buf); | 449 | kfree(buf); |
@@ -387,10 +485,12 @@ int _regmap_write(struct regmap *map, unsigned int reg, | |||
387 | 485 | ||
388 | return ret; | 486 | return ret; |
389 | } else { | 487 | } else { |
390 | map->format.format_val(map->work_buf + map->format.reg_bytes, | 488 | map->format.format_val(map->work_buf + map->format.reg_bytes |
391 | val); | 489 | + map->format.pad_bytes, val); |
392 | return _regmap_raw_write(map, reg, | 490 | return _regmap_raw_write(map, reg, |
393 | map->work_buf + map->format.reg_bytes, | 491 | map->work_buf + |
492 | map->format.reg_bytes + | ||
493 | map->format.pad_bytes, | ||
394 | map->format.val_bytes); | 494 | map->format.val_bytes); |
395 | } | 495 | } |
396 | } | 496 | } |
@@ -473,7 +573,8 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val, | |||
473 | trace_regmap_hw_read_start(map->dev, reg, | 573 | trace_regmap_hw_read_start(map->dev, reg, |
474 | val_len / map->format.val_bytes); | 574 | val_len / map->format.val_bytes); |
475 | 575 | ||
476 | ret = map->bus->read(map->dev, map->work_buf, map->format.reg_bytes, | 576 | ret = map->bus->read(map->dev, map->work_buf, |
577 | map->format.reg_bytes + map->format.pad_bytes, | ||
477 | val, val_len); | 578 | val, val_len); |
478 | 579 | ||
479 | trace_regmap_hw_read_done(map->dev, reg, | 580 | trace_regmap_hw_read_done(map->dev, reg, |
@@ -546,16 +647,32 @@ EXPORT_SYMBOL_GPL(regmap_read); | |||
546 | int regmap_raw_read(struct regmap *map, unsigned int reg, void *val, | 647 | int regmap_raw_read(struct regmap *map, unsigned int reg, void *val, |
547 | size_t val_len) | 648 | size_t val_len) |
548 | { | 649 | { |
549 | size_t val_count = val_len / map->format.val_bytes; | 650 | size_t val_bytes = map->format.val_bytes; |
550 | int ret; | 651 | size_t val_count = val_len / val_bytes; |
551 | 652 | unsigned int v; | |
552 | WARN_ON(!regmap_volatile_range(map, reg, val_count) && | 653 | int ret, i; |
553 | map->cache_type != REGCACHE_NONE); | ||
554 | 654 | ||
555 | mutex_lock(&map->lock); | 655 | mutex_lock(&map->lock); |
556 | 656 | ||
557 | ret = _regmap_raw_read(map, reg, val, val_len); | 657 | if (regmap_volatile_range(map, reg, val_count) || map->cache_bypass || |
658 | map->cache_type == REGCACHE_NONE) { | ||
659 | /* Physical block read if there's no cache involved */ | ||
660 | ret = _regmap_raw_read(map, reg, val, val_len); | ||
661 | |||
662 | } else { | ||
663 | /* Otherwise go word by word for the cache; should be low | ||
664 | * cost as we expect to hit the cache. | ||
665 | */ | ||
666 | for (i = 0; i < val_count; i++) { | ||
667 | ret = _regmap_read(map, reg + i, &v); | ||
668 | if (ret != 0) | ||
669 | goto out; | ||
670 | |||
671 | map->format.format_val(val + (i * val_bytes), v); | ||
672 | } | ||
673 | } | ||
558 | 674 | ||
675 | out: | ||
559 | mutex_unlock(&map->lock); | 676 | mutex_unlock(&map->lock); |
560 | 677 | ||
561 | return ret; | 678 | return ret; |