162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci//
362306a36Sopenharmony_ci// Register cache access API - flat caching support
462306a36Sopenharmony_ci//
562306a36Sopenharmony_ci// Copyright 2012 Wolfson Microelectronics plc
662306a36Sopenharmony_ci//
762306a36Sopenharmony_ci// Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#include <linux/device.h>
1062306a36Sopenharmony_ci#include <linux/seq_file.h>
1162306a36Sopenharmony_ci#include <linux/slab.h>
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#include "internal.h"
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_cistatic inline unsigned int regcache_flat_get_index(const struct regmap *map,
1662306a36Sopenharmony_ci						   unsigned int reg)
1762306a36Sopenharmony_ci{
1862306a36Sopenharmony_ci	return regcache_get_index_by_order(map, reg);
1962306a36Sopenharmony_ci}
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_cistatic int regcache_flat_init(struct regmap *map)
2262306a36Sopenharmony_ci{
2362306a36Sopenharmony_ci	int i;
2462306a36Sopenharmony_ci	unsigned int *cache;
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci	if (!map || map->reg_stride_order < 0 || !map->max_register)
2762306a36Sopenharmony_ci		return -EINVAL;
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci	map->cache = kcalloc(regcache_flat_get_index(map, map->max_register)
3062306a36Sopenharmony_ci			     + 1, sizeof(unsigned int), GFP_KERNEL);
3162306a36Sopenharmony_ci	if (!map->cache)
3262306a36Sopenharmony_ci		return -ENOMEM;
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci	cache = map->cache;
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci	for (i = 0; i < map->num_reg_defaults; i++) {
3762306a36Sopenharmony_ci		unsigned int reg = map->reg_defaults[i].reg;
3862306a36Sopenharmony_ci		unsigned int index = regcache_flat_get_index(map, reg);
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci		cache[index] = map->reg_defaults[i].def;
4162306a36Sopenharmony_ci	}
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci	return 0;
4462306a36Sopenharmony_ci}
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_cistatic int regcache_flat_exit(struct regmap *map)
4762306a36Sopenharmony_ci{
4862306a36Sopenharmony_ci	kfree(map->cache);
4962306a36Sopenharmony_ci	map->cache = NULL;
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci	return 0;
5262306a36Sopenharmony_ci}
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_cistatic int regcache_flat_read(struct regmap *map,
5562306a36Sopenharmony_ci			      unsigned int reg, unsigned int *value)
5662306a36Sopenharmony_ci{
5762306a36Sopenharmony_ci	unsigned int *cache = map->cache;
5862306a36Sopenharmony_ci	unsigned int index = regcache_flat_get_index(map, reg);
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci	*value = cache[index];
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci	return 0;
6362306a36Sopenharmony_ci}
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_cistatic int regcache_flat_write(struct regmap *map, unsigned int reg,
6662306a36Sopenharmony_ci			       unsigned int value)
6762306a36Sopenharmony_ci{
6862306a36Sopenharmony_ci	unsigned int *cache = map->cache;
6962306a36Sopenharmony_ci	unsigned int index = regcache_flat_get_index(map, reg);
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci	cache[index] = value;
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci	return 0;
7462306a36Sopenharmony_ci}
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_cistruct regcache_ops regcache_flat_ops = {
7762306a36Sopenharmony_ci	.type = REGCACHE_FLAT,
7862306a36Sopenharmony_ci	.name = "flat",
7962306a36Sopenharmony_ci	.init = regcache_flat_init,
8062306a36Sopenharmony_ci	.exit = regcache_flat_exit,
8162306a36Sopenharmony_ci	.read = regcache_flat_read,
8262306a36Sopenharmony_ci	.write = regcache_flat_write,
8362306a36Sopenharmony_ci};
84