137613fa5SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
237613fa5SGreg Kroah-Hartman //
337613fa5SGreg Kroah-Hartman // Register cache access API - flat caching support
437613fa5SGreg Kroah-Hartman //
537613fa5SGreg Kroah-Hartman // Copyright 2012 Wolfson Microelectronics plc
637613fa5SGreg Kroah-Hartman //
737613fa5SGreg Kroah-Hartman // Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
82ac902ceSMark Brown 
92ac902ceSMark Brown #include <linux/device.h>
102ac902ceSMark Brown #include <linux/seq_file.h>
11e39be3a3SXiubo Li #include <linux/slab.h>
122ac902ceSMark Brown 
132ac902ceSMark Brown #include "internal.h"
142ac902ceSMark Brown 
regcache_flat_get_index(const struct regmap * map,unsigned int reg)15ce11020fSXiubo Li static inline unsigned int regcache_flat_get_index(const struct regmap *map,
16ce11020fSXiubo Li 						   unsigned int reg)
17ce11020fSXiubo Li {
18ce11020fSXiubo Li 	return regcache_get_index_by_order(map, reg);
19ce11020fSXiubo Li }
20ce11020fSXiubo Li 
regcache_flat_init(struct regmap * map)212ac902ceSMark Brown static int regcache_flat_init(struct regmap *map)
222ac902ceSMark Brown {
232ac902ceSMark Brown 	int i;
242ac902ceSMark Brown 	unsigned int *cache;
252ac902ceSMark Brown 
266e4f2878SAlexander Stein 	if (!map || map->reg_stride_order < 0 || !map->max_register)
27ce11020fSXiubo Li 		return -EINVAL;
28ce11020fSXiubo Li 
29ce11020fSXiubo Li 	map->cache = kcalloc(regcache_flat_get_index(map, map->max_register)
30ce11020fSXiubo Li 			     + 1, sizeof(unsigned int), GFP_KERNEL);
312ac902ceSMark Brown 	if (!map->cache)
322ac902ceSMark Brown 		return -ENOMEM;
332ac902ceSMark Brown 
342ac902ceSMark Brown 	cache = map->cache;
352ac902ceSMark Brown 
3646318b97SAndrew F. Davis 	for (i = 0; i < map->num_reg_defaults; i++) {
3746318b97SAndrew F. Davis 		unsigned int reg = map->reg_defaults[i].reg;
3846318b97SAndrew F. Davis 		unsigned int index = regcache_flat_get_index(map, reg);
3946318b97SAndrew F. Davis 
4046318b97SAndrew F. Davis 		cache[index] = map->reg_defaults[i].def;
4146318b97SAndrew F. Davis 	}
422ac902ceSMark Brown 
432ac902ceSMark Brown 	return 0;
442ac902ceSMark Brown }
452ac902ceSMark Brown 
regcache_flat_exit(struct regmap * map)462ac902ceSMark Brown static int regcache_flat_exit(struct regmap *map)
472ac902ceSMark Brown {
482ac902ceSMark Brown 	kfree(map->cache);
492ac902ceSMark Brown 	map->cache = NULL;
502ac902ceSMark Brown 
512ac902ceSMark Brown 	return 0;
522ac902ceSMark Brown }
532ac902ceSMark Brown 
regcache_flat_read(struct regmap * map,unsigned int reg,unsigned int * value)542ac902ceSMark Brown static int regcache_flat_read(struct regmap *map,
552ac902ceSMark Brown 			      unsigned int reg, unsigned int *value)
562ac902ceSMark Brown {
572ac902ceSMark Brown 	unsigned int *cache = map->cache;
5846318b97SAndrew F. Davis 	unsigned int index = regcache_flat_get_index(map, reg);
592ac902ceSMark Brown 
6046318b97SAndrew F. Davis 	*value = cache[index];
612ac902ceSMark Brown 
622ac902ceSMark Brown 	return 0;
632ac902ceSMark Brown }
642ac902ceSMark Brown 
regcache_flat_write(struct regmap * map,unsigned int reg,unsigned int value)652ac902ceSMark Brown static int regcache_flat_write(struct regmap *map, unsigned int reg,
662ac902ceSMark Brown 			       unsigned int value)
672ac902ceSMark Brown {
682ac902ceSMark Brown 	unsigned int *cache = map->cache;
6946318b97SAndrew F. Davis 	unsigned int index = regcache_flat_get_index(map, reg);
702ac902ceSMark Brown 
7146318b97SAndrew F. Davis 	cache[index] = value;
722ac902ceSMark Brown 
732ac902ceSMark Brown 	return 0;
742ac902ceSMark Brown }
752ac902ceSMark Brown 
762ac902ceSMark Brown struct regcache_ops regcache_flat_ops = {
772ac902ceSMark Brown 	.type = REGCACHE_FLAT,
782ac902ceSMark Brown 	.name = "flat",
792ac902ceSMark Brown 	.init = regcache_flat_init,
802ac902ceSMark Brown 	.exit = regcache_flat_exit,
812ac902ceSMark Brown 	.read = regcache_flat_read,
822ac902ceSMark Brown 	.write = regcache_flat_write,
832ac902ceSMark Brown };
84