regcache-flat.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. // SPDX-License-Identifier: GPL-2.0
  2. //
  3. // Register cache access API - flat caching support
  4. //
  5. // Copyright 2012 Wolfson Microelectronics plc
  6. //
  7. // Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
  8. #include <linux/bitmap.h>
  9. #include <linux/bitops.h>
  10. #include <linux/device.h>
  11. #include <linux/limits.h>
  12. #include <linux/overflow.h>
  13. #include <linux/seq_file.h>
  14. #include <linux/slab.h>
  15. #include "internal.h"
  16. static inline unsigned int regcache_flat_get_index(const struct regmap *map,
  17. unsigned int reg)
  18. {
  19. return regcache_get_index_by_order(map, reg);
  20. }
  21. struct regcache_flat_data {
  22. unsigned long *valid;
  23. unsigned int data[];
  24. };
  25. static int regcache_flat_init(struct regmap *map)
  26. {
  27. unsigned int cache_size;
  28. struct regcache_flat_data *cache;
  29. if (!map || map->reg_stride_order < 0 || !map->max_register_is_set)
  30. return -EINVAL;
  31. cache_size = regcache_flat_get_index(map, map->max_register) + 1;
  32. cache = kzalloc_flex(*cache, data, cache_size, map->alloc_flags);
  33. if (!cache)
  34. return -ENOMEM;
  35. cache->valid = bitmap_zalloc(cache_size, map->alloc_flags);
  36. if (!cache->valid)
  37. goto err_free;
  38. map->cache = cache;
  39. return 0;
  40. err_free:
  41. kfree(cache);
  42. return -ENOMEM;
  43. }
  44. static int regcache_flat_exit(struct regmap *map)
  45. {
  46. struct regcache_flat_data *cache = map->cache;
  47. if (cache)
  48. bitmap_free(cache->valid);
  49. kfree(cache);
  50. map->cache = NULL;
  51. return 0;
  52. }
  53. static int regcache_flat_populate(struct regmap *map)
  54. {
  55. struct regcache_flat_data *cache = map->cache;
  56. unsigned int i;
  57. for (i = 0; i < map->num_reg_defaults; i++) {
  58. unsigned int reg = map->reg_defaults[i].reg;
  59. unsigned int index = regcache_flat_get_index(map, reg);
  60. cache->data[index] = map->reg_defaults[i].def;
  61. __set_bit(index, cache->valid);
  62. }
  63. if (map->reg_default_cb) {
  64. dev_dbg(map->dev,
  65. "Populating regcache_flat using reg_default_cb callback\n");
  66. for (i = 0; i <= map->max_register; i += map->reg_stride) {
  67. unsigned int index = regcache_flat_get_index(map, i);
  68. unsigned int value;
  69. if (test_bit(index, cache->valid))
  70. continue;
  71. if (map->reg_default_cb(map->dev, i, &value))
  72. continue;
  73. cache->data[index] = value;
  74. __set_bit(index, cache->valid);
  75. }
  76. }
  77. return 0;
  78. }
  79. static int regcache_flat_read(struct regmap *map,
  80. unsigned int reg, unsigned int *value)
  81. {
  82. struct regcache_flat_data *cache = map->cache;
  83. unsigned int index = regcache_flat_get_index(map, reg);
  84. /* legacy behavior: ignore validity, but warn the user */
  85. if (unlikely(!test_bit(index, cache->valid)))
  86. dev_warn_once(map->dev,
  87. "using zero-initialized flat cache, this may cause unexpected behavior");
  88. *value = cache->data[index];
  89. return 0;
  90. }
  91. static int regcache_flat_sparse_read(struct regmap *map,
  92. unsigned int reg, unsigned int *value)
  93. {
  94. struct regcache_flat_data *cache = map->cache;
  95. unsigned int index = regcache_flat_get_index(map, reg);
  96. if (unlikely(!test_bit(index, cache->valid)))
  97. return -ENOENT;
  98. *value = cache->data[index];
  99. return 0;
  100. }
  101. static int regcache_flat_write(struct regmap *map, unsigned int reg,
  102. unsigned int value)
  103. {
  104. struct regcache_flat_data *cache = map->cache;
  105. unsigned int index = regcache_flat_get_index(map, reg);
  106. cache->data[index] = value;
  107. __set_bit(index, cache->valid);
  108. return 0;
  109. }
  110. static int regcache_flat_drop(struct regmap *map, unsigned int min,
  111. unsigned int max)
  112. {
  113. struct regcache_flat_data *cache = map->cache;
  114. unsigned int bitmap_min = regcache_flat_get_index(map, min);
  115. unsigned int bitmap_max = regcache_flat_get_index(map, max);
  116. bitmap_clear(cache->valid, bitmap_min, bitmap_max + 1 - bitmap_min);
  117. return 0;
  118. }
  119. struct regcache_ops regcache_flat_ops = {
  120. .type = REGCACHE_FLAT,
  121. .name = "flat",
  122. .init = regcache_flat_init,
  123. .exit = regcache_flat_exit,
  124. .populate = regcache_flat_populate,
  125. .read = regcache_flat_read,
  126. .write = regcache_flat_write,
  127. };
  128. struct regcache_ops regcache_flat_sparse_ops = {
  129. .type = REGCACHE_FLAT_S,
  130. .name = "flat-sparse",
  131. .init = regcache_flat_init,
  132. .exit = regcache_flat_exit,
  133. .populate = regcache_flat_populate,
  134. .read = regcache_flat_sparse_read,
  135. .write = regcache_flat_write,
  136. .drop = regcache_flat_drop,
  137. };