66//
77// Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
88
9+ #include <linux/bitmap.h>
10+ #include <linux/bitops.h>
911#include <linux/device.h>
12+ #include <linux/limits.h>
13+ #include <linux/overflow.h>
1014#include <linux/seq_file.h>
1115#include <linux/slab.h>
1216
@@ -18,57 +22,116 @@ static inline unsigned int regcache_flat_get_index(const struct regmap *map,
1822 return regcache_get_index_by_order (map , reg );
1923}
2024
25+ struct regcache_flat_data {
26+ unsigned long * valid ;
27+ unsigned int data [];
28+ };
29+
2130static int regcache_flat_init (struct regmap * map )
2231{
23- int i ;
24- unsigned int * cache ;
32+ unsigned int cache_size ;
33+ struct regcache_flat_data * cache ;
2534
2635 if (!map || map -> reg_stride_order < 0 || !map -> max_register_is_set )
2736 return - EINVAL ;
2837
29- map -> cache = kcalloc ( regcache_flat_get_index (map , map -> max_register )
30- + 1 , sizeof ( unsigned int ), map -> alloc_flags );
31- if (!map -> cache )
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 )
3241 return - ENOMEM ;
3342
34- cache = map -> cache ;
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 ;
3573
3674 for (i = 0 ; i < map -> num_reg_defaults ; i ++ ) {
3775 unsigned int reg = map -> reg_defaults [i ].reg ;
3876 unsigned int index = regcache_flat_get_index (map , reg );
3977
40- cache [index ] = map -> reg_defaults [i ].def ;
78+ cache -> data [index ] = map -> reg_defaults [i ].def ;
79+ __set_bit (index , cache -> valid );
4180 }
4281
4382 return 0 ;
4483}
4584
46- static int regcache_flat_exit (struct regmap * map )
85+ static int regcache_flat_read (struct regmap * map ,
86+ unsigned int reg , unsigned int * value )
4787{
48- kfree (map -> cache );
49- map -> cache = NULL ;
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 ];
5097
5198 return 0 ;
5299}
53100
54- static int regcache_flat_read (struct regmap * map ,
55- unsigned int reg , unsigned int * value )
101+ static int regcache_flat_sparse_read (struct regmap * map ,
102+ unsigned int reg , unsigned int * value )
56103{
57- unsigned int * cache = map -> cache ;
104+ struct regcache_flat_data * cache = map -> cache ;
58105 unsigned int index = regcache_flat_get_index (map , reg );
59106
60- * value = cache [index ];
107+ if (unlikely (!test_bit (index , cache -> valid )))
108+ return - ENOENT ;
109+
110+ * value = cache -> data [index ];
61111
62112 return 0 ;
63113}
64114
65115static int regcache_flat_write (struct regmap * map , unsigned int reg ,
66116 unsigned int value )
67117{
68- unsigned int * cache = map -> cache ;
118+ struct regcache_flat_data * cache = map -> cache ;
69119 unsigned int index = regcache_flat_get_index (map , reg );
70120
71- cache [index ] = value ;
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 );
72135
73136 return 0 ;
74137}
@@ -78,6 +141,18 @@ struct regcache_ops regcache_flat_ops = {
78141 .name = "flat" ,
79142 .init = regcache_flat_init ,
80143 .exit = regcache_flat_exit ,
144+ .populate = regcache_flat_populate ,
81145 .read = regcache_flat_read ,
82146 .write = regcache_flat_write ,
83147};
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+ };
0 commit comments