Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/base/regmap/regcache-flat.c
48901 views
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 <[email protected]>
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
19
static 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
25
struct regcache_flat_data {
26
unsigned long *valid;
27
unsigned int data[];
28
};
29
30
static 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
51
err_free:
52
kfree(cache);
53
return -ENOMEM;
54
}
55
56
static 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
69
static 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
85
static 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
101
static 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
115
static 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
127
static 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
139
struct 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
149
struct 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
};
159
160