18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci//
38c2ecf20Sopenharmony_ci// Register cache access API - flat caching support
48c2ecf20Sopenharmony_ci//
58c2ecf20Sopenharmony_ci// Copyright 2012 Wolfson Microelectronics plc
68c2ecf20Sopenharmony_ci//
78c2ecf20Sopenharmony_ci// Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#include <linux/device.h>
108c2ecf20Sopenharmony_ci#include <linux/seq_file.h>
118c2ecf20Sopenharmony_ci#include <linux/slab.h>
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#include "internal.h"
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_cistatic inline unsigned int regcache_flat_get_index(const struct regmap *map,
168c2ecf20Sopenharmony_ci						   unsigned int reg)
178c2ecf20Sopenharmony_ci{
188c2ecf20Sopenharmony_ci	return regcache_get_index_by_order(map, reg);
198c2ecf20Sopenharmony_ci}
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_cistatic int regcache_flat_init(struct regmap *map)
228c2ecf20Sopenharmony_ci{
238c2ecf20Sopenharmony_ci	int i;
248c2ecf20Sopenharmony_ci	unsigned int *cache;
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci	if (!map || map->reg_stride_order < 0 || !map->max_register)
278c2ecf20Sopenharmony_ci		return -EINVAL;
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ci	map->cache = kcalloc(regcache_flat_get_index(map, map->max_register)
308c2ecf20Sopenharmony_ci			     + 1, sizeof(unsigned int), GFP_KERNEL);
318c2ecf20Sopenharmony_ci	if (!map->cache)
328c2ecf20Sopenharmony_ci		return -ENOMEM;
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ci	cache = map->cache;
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci	for (i = 0; i < map->num_reg_defaults; i++) {
378c2ecf20Sopenharmony_ci		unsigned int reg = map->reg_defaults[i].reg;
388c2ecf20Sopenharmony_ci		unsigned int index = regcache_flat_get_index(map, reg);
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci		cache[index] = map->reg_defaults[i].def;
418c2ecf20Sopenharmony_ci	}
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci	return 0;
448c2ecf20Sopenharmony_ci}
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_cistatic int regcache_flat_exit(struct regmap *map)
478c2ecf20Sopenharmony_ci{
488c2ecf20Sopenharmony_ci	kfree(map->cache);
498c2ecf20Sopenharmony_ci	map->cache = NULL;
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci	return 0;
528c2ecf20Sopenharmony_ci}
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_cistatic int regcache_flat_read(struct regmap *map,
558c2ecf20Sopenharmony_ci			      unsigned int reg, unsigned int *value)
568c2ecf20Sopenharmony_ci{
578c2ecf20Sopenharmony_ci	unsigned int *cache = map->cache;
588c2ecf20Sopenharmony_ci	unsigned int index = regcache_flat_get_index(map, reg);
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ci	*value = cache[index];
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci	return 0;
638c2ecf20Sopenharmony_ci}
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_cistatic int regcache_flat_write(struct regmap *map, unsigned int reg,
668c2ecf20Sopenharmony_ci			       unsigned int value)
678c2ecf20Sopenharmony_ci{
688c2ecf20Sopenharmony_ci	unsigned int *cache = map->cache;
698c2ecf20Sopenharmony_ci	unsigned int index = regcache_flat_get_index(map, reg);
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ci	cache[index] = value;
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci	return 0;
748c2ecf20Sopenharmony_ci}
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_cistruct regcache_ops regcache_flat_ops = {
778c2ecf20Sopenharmony_ci	.type = REGCACHE_FLAT,
788c2ecf20Sopenharmony_ci	.name = "flat",
798c2ecf20Sopenharmony_ci	.init = regcache_flat_init,
808c2ecf20Sopenharmony_ci	.exit = regcache_flat_exit,
818c2ecf20Sopenharmony_ci	.read = regcache_flat_read,
828c2ecf20Sopenharmony_ci	.write = regcache_flat_write,
838c2ecf20Sopenharmony_ci};
84