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