1f6352424SMark Brown // SPDX-License-Identifier: GPL-2.0
2f6352424SMark Brown //
3f6352424SMark Brown // Register map access API - Memory region
4f6352424SMark Brown //
5f6352424SMark Brown // This is intended for testing only
6f6352424SMark Brown //
7f6352424SMark Brown // Copyright (c) 2023, Arm Ltd
8f6352424SMark Brown
9f6352424SMark Brown #include <linux/clk.h>
10f6352424SMark Brown #include <linux/err.h>
11f6352424SMark Brown #include <linux/io.h>
12f6352424SMark Brown #include <linux/module.h>
13f6352424SMark Brown #include <linux/regmap.h>
14f6352424SMark Brown #include <linux/slab.h>
15f6352424SMark Brown #include <linux/swab.h>
16f6352424SMark Brown
17f6352424SMark Brown #include "internal.h"
18f6352424SMark Brown
regmap_ram_write(void * context,unsigned int reg,unsigned int val)19f6352424SMark Brown static int regmap_ram_write(void *context, unsigned int reg, unsigned int val)
20f6352424SMark Brown {
21f6352424SMark Brown struct regmap_ram_data *data = context;
22f6352424SMark Brown
23f6352424SMark Brown data->vals[reg] = val;
24f6352424SMark Brown data->written[reg] = true;
25f6352424SMark Brown
26f6352424SMark Brown return 0;
27f6352424SMark Brown }
28f6352424SMark Brown
regmap_ram_read(void * context,unsigned int reg,unsigned int * val)29f6352424SMark Brown static int regmap_ram_read(void *context, unsigned int reg, unsigned int *val)
30f6352424SMark Brown {
31f6352424SMark Brown struct regmap_ram_data *data = context;
32f6352424SMark Brown
33f6352424SMark Brown *val = data->vals[reg];
34f6352424SMark Brown data->read[reg] = true;
35f6352424SMark Brown
36f6352424SMark Brown return 0;
37f6352424SMark Brown }
38f6352424SMark Brown
regmap_ram_free_context(void * context)39f6352424SMark Brown static void regmap_ram_free_context(void *context)
40f6352424SMark Brown {
41f6352424SMark Brown struct regmap_ram_data *data = context;
42f6352424SMark Brown
43f6352424SMark Brown kfree(data->vals);
44f6352424SMark Brown kfree(data->read);
45f6352424SMark Brown kfree(data->written);
46f6352424SMark Brown kfree(data);
47f6352424SMark Brown }
48f6352424SMark Brown
49f6352424SMark Brown static const struct regmap_bus regmap_ram = {
50f6352424SMark Brown .fast_io = true,
51f6352424SMark Brown .reg_write = regmap_ram_write,
52f6352424SMark Brown .reg_read = regmap_ram_read,
53f6352424SMark Brown .free_context = regmap_ram_free_context,
54f6352424SMark Brown };
55f6352424SMark Brown
__regmap_init_ram(struct device * dev,const struct regmap_config * config,struct regmap_ram_data * data,struct lock_class_key * lock_key,const char * lock_name)567b7982f1SRichard Fitzgerald struct regmap *__regmap_init_ram(struct device *dev,
577b7982f1SRichard Fitzgerald const struct regmap_config *config,
58f6352424SMark Brown struct regmap_ram_data *data,
59f6352424SMark Brown struct lock_class_key *lock_key,
60f6352424SMark Brown const char *lock_name)
61f6352424SMark Brown {
62f6352424SMark Brown struct regmap *map;
63f6352424SMark Brown
64f6352424SMark Brown if (!config->max_register) {
65f6352424SMark Brown pr_crit("No max_register specified for RAM regmap\n");
66f6352424SMark Brown return ERR_PTR(-EINVAL);
67f6352424SMark Brown }
68f6352424SMark Brown
693b201c9aSDmitry Antipov data->read = kcalloc(config->max_register + 1, sizeof(bool),
70f6352424SMark Brown GFP_KERNEL);
71f6352424SMark Brown if (!data->read)
72f6352424SMark Brown return ERR_PTR(-ENOMEM);
73f6352424SMark Brown
743b201c9aSDmitry Antipov data->written = kcalloc(config->max_register + 1, sizeof(bool),
75f6352424SMark Brown GFP_KERNEL);
76f6352424SMark Brown if (!data->written)
77f6352424SMark Brown return ERR_PTR(-ENOMEM);
78f6352424SMark Brown
797b7982f1SRichard Fitzgerald map = __regmap_init(dev, ®map_ram, data, config,
80f6352424SMark Brown lock_key, lock_name);
81f6352424SMark Brown
82f6352424SMark Brown return map;
83f6352424SMark Brown }
84f6352424SMark Brown EXPORT_SYMBOL_GPL(__regmap_init_ram);
85f6352424SMark Brown
86*92955a25SJeff Johnson MODULE_DESCRIPTION("Register map access API - Memory region");
87f6352424SMark Brown MODULE_LICENSE("GPL v2");
88