File Index
Files and directories
Sign in
FILE

regcache-flat.c

File preview with syntax highlighting.

linux-6.19.14/drivers/base/regmap/regcache-flat.c C
  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
  9#include <linux/bitmap.h>
 10#include <linux/bitops.h>
 11#include <linux/device.h>
 12#include <linux/limits.h>
 13#include <linux/overflow.h>
 14#include <linux/seq_file.h>
 15#include <linux/slab.h>
 16
 17#include "internal.h"
 18
 19static inline unsigned int regcache_flat_get_index(const struct regmap *map,
 20						   unsigned int reg)
 21{
 22	return regcache_get_index_by_order(map, reg);
 23}
 24
 25struct regcache_flat_data {
 26	unsigned long *valid;
 27	unsigned int data[];
 28};
 29
 30static int regcache_flat_init(struct regmap *map)
 31{
 32	unsigned int cache_size;
 33	struct regcache_flat_data *cache;
 34
 35	if (!map || map->reg_stride_order < 0 || !map->max_register_is_set)
 36		return -EINVAL;
 37
 38	cache_size = regcache_flat_get_index(map, map->max_register) + 1;
 39	cache = kzalloc(struct_size(cache, data, cache_size), map->alloc_flags);
 40	if (!cache)
 41		return -ENOMEM;
 42
 43	cache->valid = bitmap_zalloc(cache_size, map->alloc_flags);
 44	if (!cache->valid)
 45		goto err_free;
 46
 47	map->cache = cache;
 48
 49	return 0;
 50
 51err_free:
 52	kfree(cache);
 53	return -ENOMEM;
 54}
 55
 56static int regcache_flat_exit(struct regmap *map)
 57{
 58	struct regcache_flat_data *cache = map->cache;
 59
 60	if (cache)
 61		bitmap_free(cache->valid);
 62
 63	kfree(cache);
 64	map->cache = NULL;
 65
 66	return 0;
 67}
 68
 69static int regcache_flat_populate(struct regmap *map)
 70{
 71	struct regcache_flat_data *cache = map->cache;
 72	unsigned int i;
 73
 74	for (i = 0; i < map->num_reg_defaults; i++) {
 75		unsigned int reg = map->reg_defaults[i].reg;
 76		unsigned int index = regcache_flat_get_index(map, reg);
 77
 78		cache->data[index] = map->reg_defaults[i].def;
 79		__set_bit(index, cache->valid);
 80	}
 81
 82	return 0;
 83}
 84
 85static int regcache_flat_read(struct regmap *map,
 86			      unsigned int reg, unsigned int *value)
 87{
 88	struct regcache_flat_data *cache = map->cache;
 89	unsigned int index = regcache_flat_get_index(map, reg);
 90
 91	/* legacy behavior: ignore validity, but warn the user */
 92	if (unlikely(!test_bit(index, cache->valid)))
 93		dev_warn_once(map->dev,
 94			"using zero-initialized flat cache, this may cause unexpected behavior");
 95
 96	*value = cache->data[index];
 97
 98	return 0;
 99}
100
101static int regcache_flat_sparse_read(struct regmap *map,
102				     unsigned int reg, unsigned int *value)
103{
104	struct regcache_flat_data *cache = map->cache;
105	unsigned int index = regcache_flat_get_index(map, reg);
106
107	if (unlikely(!test_bit(index, cache->valid)))
108		return -ENOENT;
109
110	*value = cache->data[index];
111
112	return 0;
113}
114
115static int regcache_flat_write(struct regmap *map, unsigned int reg,
116			       unsigned int value)
117{
118	struct regcache_flat_data *cache = map->cache;
119	unsigned int index = regcache_flat_get_index(map, reg);
120
121	cache->data[index] = value;
122	__set_bit(index, cache->valid);
123
124	return 0;
125}
126
127static int regcache_flat_drop(struct regmap *map, unsigned int min,
128			      unsigned int max)
129{
130	struct regcache_flat_data *cache = map->cache;
131	unsigned int bitmap_min = regcache_flat_get_index(map, min);
132	unsigned int bitmap_max = regcache_flat_get_index(map, max);
133
134	bitmap_clear(cache->valid, bitmap_min, bitmap_max + 1 - bitmap_min);
135
136	return 0;
137}
138
139struct regcache_ops regcache_flat_ops = {
140	.type = REGCACHE_FLAT,
141	.name = "flat",
142	.init = regcache_flat_init,
143	.exit = regcache_flat_exit,
144	.populate = regcache_flat_populate,
145	.read = regcache_flat_read,
146	.write = regcache_flat_write,
147};
148
149struct regcache_ops regcache_flat_sparse_ops = {
150	.type = REGCACHE_FLAT_S,
151	.name = "flat-sparse",
152	.init = regcache_flat_init,
153	.exit = regcache_flat_exit,
154	.populate = regcache_flat_populate,
155	.read = regcache_flat_sparse_read,
156	.write = regcache_flat_write,
157	.drop = regcache_flat_drop,
158};
~/ Read-only file preview.