diff options
Diffstat (limited to 'drivers/base/regmap/regmap.c')
-rw-r--r-- | drivers/base/regmap/regmap.c | 139 |
1 files changed, 103 insertions, 36 deletions
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index 7a3f535e481c..40f910162781 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c | |||
@@ -112,25 +112,36 @@ static void regmap_format_10_14_write(struct regmap *map, | |||
112 | out[0] = reg >> 2; | 112 | out[0] = reg >> 2; |
113 | } | 113 | } |
114 | 114 | ||
115 | static void regmap_format_8(void *buf, unsigned int val) | 115 | static void regmap_format_8(void *buf, unsigned int val, unsigned int shift) |
116 | { | 116 | { |
117 | u8 *b = buf; | 117 | u8 *b = buf; |
118 | 118 | ||
119 | b[0] = val; | 119 | b[0] = val << shift; |
120 | } | 120 | } |
121 | 121 | ||
122 | static void regmap_format_16(void *buf, unsigned int val) | 122 | static void regmap_format_16(void *buf, unsigned int val, unsigned int shift) |
123 | { | 123 | { |
124 | __be16 *b = buf; | 124 | __be16 *b = buf; |
125 | 125 | ||
126 | b[0] = cpu_to_be16(val); | 126 | b[0] = cpu_to_be16(val << shift); |
127 | } | 127 | } |
128 | 128 | ||
129 | static void regmap_format_32(void *buf, unsigned int val) | 129 | static void regmap_format_24(void *buf, unsigned int val, unsigned int shift) |
130 | { | ||
131 | u8 *b = buf; | ||
132 | |||
133 | val <<= shift; | ||
134 | |||
135 | b[0] = val >> 16; | ||
136 | b[1] = val >> 8; | ||
137 | b[2] = val; | ||
138 | } | ||
139 | |||
140 | static void regmap_format_32(void *buf, unsigned int val, unsigned int shift) | ||
130 | { | 141 | { |
131 | __be32 *b = buf; | 142 | __be32 *b = buf; |
132 | 143 | ||
133 | b[0] = cpu_to_be32(val); | 144 | b[0] = cpu_to_be32(val << shift); |
134 | } | 145 | } |
135 | 146 | ||
136 | static unsigned int regmap_parse_8(void *buf) | 147 | static unsigned int regmap_parse_8(void *buf) |
@@ -149,6 +160,16 @@ static unsigned int regmap_parse_16(void *buf) | |||
149 | return b[0]; | 160 | return b[0]; |
150 | } | 161 | } |
151 | 162 | ||
163 | static unsigned int regmap_parse_24(void *buf) | ||
164 | { | ||
165 | u8 *b = buf; | ||
166 | unsigned int ret = b[2]; | ||
167 | ret |= ((unsigned int)b[1]) << 8; | ||
168 | ret |= ((unsigned int)b[0]) << 16; | ||
169 | |||
170 | return ret; | ||
171 | } | ||
172 | |||
152 | static unsigned int regmap_parse_32(void *buf) | 173 | static unsigned int regmap_parse_32(void *buf) |
153 | { | 174 | { |
154 | __be32 *b = buf; | 175 | __be32 *b = buf; |
@@ -158,11 +179,32 @@ static unsigned int regmap_parse_32(void *buf) | |||
158 | return b[0]; | 179 | return b[0]; |
159 | } | 180 | } |
160 | 181 | ||
182 | static void regmap_lock_mutex(struct regmap *map) | ||
183 | { | ||
184 | mutex_lock(&map->mutex); | ||
185 | } | ||
186 | |||
187 | static void regmap_unlock_mutex(struct regmap *map) | ||
188 | { | ||
189 | mutex_unlock(&map->mutex); | ||
190 | } | ||
191 | |||
192 | static void regmap_lock_spinlock(struct regmap *map) | ||
193 | { | ||
194 | spin_lock(&map->spinlock); | ||
195 | } | ||
196 | |||
197 | static void regmap_unlock_spinlock(struct regmap *map) | ||
198 | { | ||
199 | spin_unlock(&map->spinlock); | ||
200 | } | ||
201 | |||
161 | /** | 202 | /** |
162 | * regmap_init(): Initialise register map | 203 | * regmap_init(): Initialise register map |
163 | * | 204 | * |
164 | * @dev: Device that will be interacted with | 205 | * @dev: Device that will be interacted with |
165 | * @bus: Bus-specific callbacks to use with device | 206 | * @bus: Bus-specific callbacks to use with device |
207 | * @bus_context: Data passed to bus-specific callbacks | ||
166 | * @config: Configuration for register map | 208 | * @config: Configuration for register map |
167 | * | 209 | * |
168 | * The return value will be an ERR_PTR() on error or a valid pointer to | 210 | * The return value will be an ERR_PTR() on error or a valid pointer to |
@@ -171,6 +213,7 @@ static unsigned int regmap_parse_32(void *buf) | |||
171 | */ | 213 | */ |
172 | struct regmap *regmap_init(struct device *dev, | 214 | struct regmap *regmap_init(struct device *dev, |
173 | const struct regmap_bus *bus, | 215 | const struct regmap_bus *bus, |
216 | void *bus_context, | ||
174 | const struct regmap_config *config) | 217 | const struct regmap_config *config) |
175 | { | 218 | { |
176 | struct regmap *map; | 219 | struct regmap *map; |
@@ -185,14 +228,24 @@ struct regmap *regmap_init(struct device *dev, | |||
185 | goto err; | 228 | goto err; |
186 | } | 229 | } |
187 | 230 | ||
188 | mutex_init(&map->lock); | 231 | if (bus->fast_io) { |
232 | spin_lock_init(&map->spinlock); | ||
233 | map->lock = regmap_lock_spinlock; | ||
234 | map->unlock = regmap_unlock_spinlock; | ||
235 | } else { | ||
236 | mutex_init(&map->mutex); | ||
237 | map->lock = regmap_lock_mutex; | ||
238 | map->unlock = regmap_unlock_mutex; | ||
239 | } | ||
189 | map->format.buf_size = (config->reg_bits + config->val_bits) / 8; | 240 | map->format.buf_size = (config->reg_bits + config->val_bits) / 8; |
190 | map->format.reg_bytes = DIV_ROUND_UP(config->reg_bits, 8); | 241 | map->format.reg_bytes = DIV_ROUND_UP(config->reg_bits, 8); |
191 | map->format.pad_bytes = config->pad_bits / 8; | 242 | map->format.pad_bytes = config->pad_bits / 8; |
192 | map->format.val_bytes = DIV_ROUND_UP(config->val_bits, 8); | 243 | map->format.val_bytes = DIV_ROUND_UP(config->val_bits, 8); |
193 | map->format.buf_size += map->format.pad_bytes; | 244 | map->format.buf_size += map->format.pad_bytes; |
245 | map->reg_shift = config->pad_bits % 8; | ||
194 | map->dev = dev; | 246 | map->dev = dev; |
195 | map->bus = bus; | 247 | map->bus = bus; |
248 | map->bus_context = bus_context; | ||
196 | map->max_register = config->max_register; | 249 | map->max_register = config->max_register; |
197 | map->writeable_reg = config->writeable_reg; | 250 | map->writeable_reg = config->writeable_reg; |
198 | map->readable_reg = config->readable_reg; | 251 | map->readable_reg = config->readable_reg; |
@@ -207,7 +260,7 @@ struct regmap *regmap_init(struct device *dev, | |||
207 | map->read_flag_mask = bus->read_flag_mask; | 260 | map->read_flag_mask = bus->read_flag_mask; |
208 | } | 261 | } |
209 | 262 | ||
210 | switch (config->reg_bits) { | 263 | switch (config->reg_bits + map->reg_shift) { |
211 | case 2: | 264 | case 2: |
212 | switch (config->val_bits) { | 265 | switch (config->val_bits) { |
213 | case 6: | 266 | case 6: |
@@ -273,6 +326,10 @@ struct regmap *regmap_init(struct device *dev, | |||
273 | map->format.format_val = regmap_format_16; | 326 | map->format.format_val = regmap_format_16; |
274 | map->format.parse_val = regmap_parse_16; | 327 | map->format.parse_val = regmap_parse_16; |
275 | break; | 328 | break; |
329 | case 24: | ||
330 | map->format.format_val = regmap_format_24; | ||
331 | map->format.parse_val = regmap_parse_24; | ||
332 | break; | ||
276 | case 32: | 333 | case 32: |
277 | map->format.format_val = regmap_format_32; | 334 | map->format.format_val = regmap_format_32; |
278 | map->format.parse_val = regmap_parse_32; | 335 | map->format.parse_val = regmap_parse_32; |
@@ -289,7 +346,7 @@ struct regmap *regmap_init(struct device *dev, | |||
289 | goto err_map; | 346 | goto err_map; |
290 | } | 347 | } |
291 | 348 | ||
292 | regmap_debugfs_init(map); | 349 | regmap_debugfs_init(map, config->name); |
293 | 350 | ||
294 | ret = regcache_init(map, config); | 351 | ret = regcache_init(map, config); |
295 | if (ret < 0) | 352 | if (ret < 0) |
@@ -316,6 +373,7 @@ static void devm_regmap_release(struct device *dev, void *res) | |||
316 | * | 373 | * |
317 | * @dev: Device that will be interacted with | 374 | * @dev: Device that will be interacted with |
318 | * @bus: Bus-specific callbacks to use with device | 375 | * @bus: Bus-specific callbacks to use with device |
376 | * @bus_context: Data passed to bus-specific callbacks | ||
319 | * @config: Configuration for register map | 377 | * @config: Configuration for register map |
320 | * | 378 | * |
321 | * The return value will be an ERR_PTR() on error or a valid pointer | 379 | * The return value will be an ERR_PTR() on error or a valid pointer |
@@ -325,6 +383,7 @@ static void devm_regmap_release(struct device *dev, void *res) | |||
325 | */ | 383 | */ |
326 | struct regmap *devm_regmap_init(struct device *dev, | 384 | struct regmap *devm_regmap_init(struct device *dev, |
327 | const struct regmap_bus *bus, | 385 | const struct regmap_bus *bus, |
386 | void *bus_context, | ||
328 | const struct regmap_config *config) | 387 | const struct regmap_config *config) |
329 | { | 388 | { |
330 | struct regmap **ptr, *regmap; | 389 | struct regmap **ptr, *regmap; |
@@ -333,7 +392,7 @@ struct regmap *devm_regmap_init(struct device *dev, | |||
333 | if (!ptr) | 392 | if (!ptr) |
334 | return ERR_PTR(-ENOMEM); | 393 | return ERR_PTR(-ENOMEM); |
335 | 394 | ||
336 | regmap = regmap_init(dev, bus, config); | 395 | regmap = regmap_init(dev, bus, bus_context, config); |
337 | if (!IS_ERR(regmap)) { | 396 | if (!IS_ERR(regmap)) { |
338 | *ptr = regmap; | 397 | *ptr = regmap; |
339 | devres_add(dev, ptr); | 398 | devres_add(dev, ptr); |
@@ -360,7 +419,7 @@ int regmap_reinit_cache(struct regmap *map, const struct regmap_config *config) | |||
360 | { | 419 | { |
361 | int ret; | 420 | int ret; |
362 | 421 | ||
363 | mutex_lock(&map->lock); | 422 | map->lock(map); |
364 | 423 | ||
365 | regcache_exit(map); | 424 | regcache_exit(map); |
366 | regmap_debugfs_exit(map); | 425 | regmap_debugfs_exit(map); |
@@ -372,14 +431,14 @@ int regmap_reinit_cache(struct regmap *map, const struct regmap_config *config) | |||
372 | map->precious_reg = config->precious_reg; | 431 | map->precious_reg = config->precious_reg; |
373 | map->cache_type = config->cache_type; | 432 | map->cache_type = config->cache_type; |
374 | 433 | ||
375 | regmap_debugfs_init(map); | 434 | regmap_debugfs_init(map, config->name); |
376 | 435 | ||
377 | map->cache_bypass = false; | 436 | map->cache_bypass = false; |
378 | map->cache_only = false; | 437 | map->cache_only = false; |
379 | 438 | ||
380 | ret = regcache_init(map, config); | 439 | ret = regcache_init(map, config); |
381 | 440 | ||
382 | mutex_unlock(&map->lock); | 441 | map->unlock(map); |
383 | 442 | ||
384 | return ret; | 443 | return ret; |
385 | } | 444 | } |
@@ -391,6 +450,8 @@ void regmap_exit(struct regmap *map) | |||
391 | { | 450 | { |
392 | regcache_exit(map); | 451 | regcache_exit(map); |
393 | regmap_debugfs_exit(map); | 452 | regmap_debugfs_exit(map); |
453 | if (map->bus->free_context) | ||
454 | map->bus->free_context(map->bus_context); | ||
394 | kfree(map->work_buf); | 455 | kfree(map->work_buf); |
395 | kfree(map); | 456 | kfree(map); |
396 | } | 457 | } |
@@ -431,7 +492,7 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg, | |||
431 | } | 492 | } |
432 | } | 493 | } |
433 | 494 | ||
434 | map->format.format_reg(map->work_buf, reg); | 495 | map->format.format_reg(map->work_buf, reg, map->reg_shift); |
435 | 496 | ||
436 | u8[0] |= map->write_flag_mask; | 497 | u8[0] |= map->write_flag_mask; |
437 | 498 | ||
@@ -444,12 +505,12 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg, | |||
444 | */ | 505 | */ |
445 | if (val == (map->work_buf + map->format.pad_bytes + | 506 | if (val == (map->work_buf + map->format.pad_bytes + |
446 | map->format.reg_bytes)) | 507 | map->format.reg_bytes)) |
447 | ret = map->bus->write(map->dev, map->work_buf, | 508 | ret = map->bus->write(map->bus_context, map->work_buf, |
448 | map->format.reg_bytes + | 509 | map->format.reg_bytes + |
449 | map->format.pad_bytes + | 510 | map->format.pad_bytes + |
450 | val_len); | 511 | val_len); |
451 | else if (map->bus->gather_write) | 512 | else if (map->bus->gather_write) |
452 | ret = map->bus->gather_write(map->dev, map->work_buf, | 513 | ret = map->bus->gather_write(map->bus_context, map->work_buf, |
453 | map->format.reg_bytes + | 514 | map->format.reg_bytes + |
454 | map->format.pad_bytes, | 515 | map->format.pad_bytes, |
455 | val, val_len); | 516 | val, val_len); |
@@ -464,7 +525,7 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg, | |||
464 | memcpy(buf, map->work_buf, map->format.reg_bytes); | 525 | memcpy(buf, map->work_buf, map->format.reg_bytes); |
465 | memcpy(buf + map->format.reg_bytes + map->format.pad_bytes, | 526 | memcpy(buf + map->format.reg_bytes + map->format.pad_bytes, |
466 | val, val_len); | 527 | val, val_len); |
467 | ret = map->bus->write(map->dev, buf, len); | 528 | ret = map->bus->write(map->bus_context, buf, len); |
468 | 529 | ||
469 | kfree(buf); | 530 | kfree(buf); |
470 | } | 531 | } |
@@ -498,7 +559,7 @@ int _regmap_write(struct regmap *map, unsigned int reg, | |||
498 | 559 | ||
499 | trace_regmap_hw_write_start(map->dev, reg, 1); | 560 | trace_regmap_hw_write_start(map->dev, reg, 1); |
500 | 561 | ||
501 | ret = map->bus->write(map->dev, map->work_buf, | 562 | ret = map->bus->write(map->bus_context, map->work_buf, |
502 | map->format.buf_size); | 563 | map->format.buf_size); |
503 | 564 | ||
504 | trace_regmap_hw_write_done(map->dev, reg, 1); | 565 | trace_regmap_hw_write_done(map->dev, reg, 1); |
@@ -506,7 +567,7 @@ int _regmap_write(struct regmap *map, unsigned int reg, | |||
506 | return ret; | 567 | return ret; |
507 | } else { | 568 | } else { |
508 | map->format.format_val(map->work_buf + map->format.reg_bytes | 569 | map->format.format_val(map->work_buf + map->format.reg_bytes |
509 | + map->format.pad_bytes, val); | 570 | + map->format.pad_bytes, val, 0); |
510 | return _regmap_raw_write(map, reg, | 571 | return _regmap_raw_write(map, reg, |
511 | map->work_buf + | 572 | map->work_buf + |
512 | map->format.reg_bytes + | 573 | map->format.reg_bytes + |
@@ -529,11 +590,11 @@ int regmap_write(struct regmap *map, unsigned int reg, unsigned int val) | |||
529 | { | 590 | { |
530 | int ret; | 591 | int ret; |
531 | 592 | ||
532 | mutex_lock(&map->lock); | 593 | map->lock(map); |
533 | 594 | ||
534 | ret = _regmap_write(map, reg, val); | 595 | ret = _regmap_write(map, reg, val); |
535 | 596 | ||
536 | mutex_unlock(&map->lock); | 597 | map->unlock(map); |
537 | 598 | ||
538 | return ret; | 599 | return ret; |
539 | } | 600 | } |
@@ -560,11 +621,14 @@ int regmap_raw_write(struct regmap *map, unsigned int reg, | |||
560 | { | 621 | { |
561 | int ret; | 622 | int ret; |
562 | 623 | ||
563 | mutex_lock(&map->lock); | 624 | if (val_len % map->format.val_bytes) |
625 | return -EINVAL; | ||
626 | |||
627 | map->lock(map); | ||
564 | 628 | ||
565 | ret = _regmap_raw_write(map, reg, val, val_len); | 629 | ret = _regmap_raw_write(map, reg, val, val_len); |
566 | 630 | ||
567 | mutex_unlock(&map->lock); | 631 | map->unlock(map); |
568 | 632 | ||
569 | return ret; | 633 | return ret; |
570 | } | 634 | } |
@@ -594,7 +658,7 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val, | |||
594 | if (!map->format.parse_val) | 658 | if (!map->format.parse_val) |
595 | return -EINVAL; | 659 | return -EINVAL; |
596 | 660 | ||
597 | mutex_lock(&map->lock); | 661 | map->lock(map); |
598 | 662 | ||
599 | /* No formatting is require if val_byte is 1 */ | 663 | /* No formatting is require if val_byte is 1 */ |
600 | if (val_bytes == 1) { | 664 | if (val_bytes == 1) { |
@@ -615,7 +679,7 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val, | |||
615 | kfree(wval); | 679 | kfree(wval); |
616 | 680 | ||
617 | out: | 681 | out: |
618 | mutex_unlock(&map->lock); | 682 | map->unlock(map); |
619 | return ret; | 683 | return ret; |
620 | } | 684 | } |
621 | EXPORT_SYMBOL_GPL(regmap_bulk_write); | 685 | EXPORT_SYMBOL_GPL(regmap_bulk_write); |
@@ -626,7 +690,7 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val, | |||
626 | u8 *u8 = map->work_buf; | 690 | u8 *u8 = map->work_buf; |
627 | int ret; | 691 | int ret; |
628 | 692 | ||
629 | map->format.format_reg(map->work_buf, reg); | 693 | map->format.format_reg(map->work_buf, reg, map->reg_shift); |
630 | 694 | ||
631 | /* | 695 | /* |
632 | * Some buses or devices flag reads by setting the high bits in the | 696 | * Some buses or devices flag reads by setting the high bits in the |
@@ -639,7 +703,7 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val, | |||
639 | trace_regmap_hw_read_start(map->dev, reg, | 703 | trace_regmap_hw_read_start(map->dev, reg, |
640 | val_len / map->format.val_bytes); | 704 | val_len / map->format.val_bytes); |
641 | 705 | ||
642 | ret = map->bus->read(map->dev, map->work_buf, | 706 | ret = map->bus->read(map->bus_context, map->work_buf, |
643 | map->format.reg_bytes + map->format.pad_bytes, | 707 | map->format.reg_bytes + map->format.pad_bytes, |
644 | val, val_len); | 708 | val, val_len); |
645 | 709 | ||
@@ -689,11 +753,11 @@ int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val) | |||
689 | { | 753 | { |
690 | int ret; | 754 | int ret; |
691 | 755 | ||
692 | mutex_lock(&map->lock); | 756 | map->lock(map); |
693 | 757 | ||
694 | ret = _regmap_read(map, reg, val); | 758 | ret = _regmap_read(map, reg, val); |
695 | 759 | ||
696 | mutex_unlock(&map->lock); | 760 | map->unlock(map); |
697 | 761 | ||
698 | return ret; | 762 | return ret; |
699 | } | 763 | } |
@@ -718,7 +782,10 @@ int regmap_raw_read(struct regmap *map, unsigned int reg, void *val, | |||
718 | unsigned int v; | 782 | unsigned int v; |
719 | int ret, i; | 783 | int ret, i; |
720 | 784 | ||
721 | mutex_lock(&map->lock); | 785 | if (val_len % map->format.val_bytes) |
786 | return -EINVAL; | ||
787 | |||
788 | map->lock(map); | ||
722 | 789 | ||
723 | if (regmap_volatile_range(map, reg, val_count) || map->cache_bypass || | 790 | if (regmap_volatile_range(map, reg, val_count) || map->cache_bypass || |
724 | map->cache_type == REGCACHE_NONE) { | 791 | map->cache_type == REGCACHE_NONE) { |
@@ -734,12 +801,12 @@ int regmap_raw_read(struct regmap *map, unsigned int reg, void *val, | |||
734 | if (ret != 0) | 801 | if (ret != 0) |
735 | goto out; | 802 | goto out; |
736 | 803 | ||
737 | map->format.format_val(val + (i * val_bytes), v); | 804 | map->format.format_val(val + (i * val_bytes), v, 0); |
738 | } | 805 | } |
739 | } | 806 | } |
740 | 807 | ||
741 | out: | 808 | out: |
742 | mutex_unlock(&map->lock); | 809 | map->unlock(map); |
743 | 810 | ||
744 | return ret; | 811 | return ret; |
745 | } | 812 | } |
@@ -792,7 +859,7 @@ static int _regmap_update_bits(struct regmap *map, unsigned int reg, | |||
792 | int ret; | 859 | int ret; |
793 | unsigned int tmp, orig; | 860 | unsigned int tmp, orig; |
794 | 861 | ||
795 | mutex_lock(&map->lock); | 862 | map->lock(map); |
796 | 863 | ||
797 | ret = _regmap_read(map, reg, &orig); | 864 | ret = _regmap_read(map, reg, &orig); |
798 | if (ret != 0) | 865 | if (ret != 0) |
@@ -809,7 +876,7 @@ static int _regmap_update_bits(struct regmap *map, unsigned int reg, | |||
809 | } | 876 | } |
810 | 877 | ||
811 | out: | 878 | out: |
812 | mutex_unlock(&map->lock); | 879 | map->unlock(map); |
813 | 880 | ||
814 | return ret; | 881 | return ret; |
815 | } | 882 | } |
@@ -876,7 +943,7 @@ int regmap_register_patch(struct regmap *map, const struct reg_default *regs, | |||
876 | if (map->patch) | 943 | if (map->patch) |
877 | return -EBUSY; | 944 | return -EBUSY; |
878 | 945 | ||
879 | mutex_lock(&map->lock); | 946 | map->lock(map); |
880 | 947 | ||
881 | bypass = map->cache_bypass; | 948 | bypass = map->cache_bypass; |
882 | 949 | ||
@@ -904,7 +971,7 @@ int regmap_register_patch(struct regmap *map, const struct reg_default *regs, | |||
904 | out: | 971 | out: |
905 | map->cache_bypass = bypass; | 972 | map->cache_bypass = bypass; |
906 | 973 | ||
907 | mutex_unlock(&map->lock); | 974 | map->unlock(map); |
908 | 975 | ||
909 | return ret; | 976 | return ret; |
910 | } | 977 | } |