summaryrefslogtreecommitdiffstats
path: root/drivers/base
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2023-03-26 15:11:12 +0100
committerMark Brown <broonie@kernel.org>2023-03-30 12:25:42 +0100
commitf6352424e37e7bf72291ceab87dc620172be0999 (patch)
treecba005c1817e797fbf88034fd306c065a329130b /drivers/base
parent1e2bae6ae8f6b404b295edd5ba11a0bb1566544c (diff)
downloadlinux-stable-f6352424e37e7bf72291ceab87dc620172be0999.tar.gz
linux-stable-f6352424e37e7bf72291ceab87dc620172be0999.tar.bz2
linux-stable-f6352424e37e7bf72291ceab87dc620172be0999.zip
regmap: Add RAM backed register map
Add a register map that is a simple array of memory, for use in KUnit testing of the framework. This is not exposed in regmap.h since I can't think of a non-test use case, it is purely for use internally. To facilitate testing we track if registers have been read or written to. Signed-off-by: Mark Brown <broonie@kernel.org> Link: https://lore.kernel.org/r/20230324-regmap-kunit-v2-1-b208801dc2c8@kernel.org
Diffstat (limited to 'drivers/base')
-rw-r--r--drivers/base/regmap/Kconfig3
-rw-r--r--drivers/base/regmap/Makefile1
-rw-r--r--drivers/base/regmap/internal.h19
-rw-r--r--drivers/base/regmap/regmap-ram.c85
4 files changed, 108 insertions, 0 deletions
diff --git a/drivers/base/regmap/Kconfig b/drivers/base/regmap/Kconfig
index 9f8dcb32c24b..3d3445bff511 100644
--- a/drivers/base/regmap/Kconfig
+++ b/drivers/base/regmap/Kconfig
@@ -41,6 +41,9 @@ config REGMAP_MMIO
config REGMAP_IRQ
bool
+config REGMAP_RAM
+ tristate
+
config REGMAP_SOUNDWIRE
tristate
depends on SOUNDWIRE
diff --git a/drivers/base/regmap/Makefile b/drivers/base/regmap/Makefile
index 8900c340e352..b4b0e8fe6c1f 100644
--- a/drivers/base/regmap/Makefile
+++ b/drivers/base/regmap/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_REGMAP) += regcache-rbtree.o regcache-flat.o
obj-$(CONFIG_DEBUG_FS) += regmap-debugfs.o
obj-$(CONFIG_REGMAP_AC97) += regmap-ac97.o
obj-$(CONFIG_REGMAP_I2C) += regmap-i2c.o
+obj-$(CONFIG_REGMAP_RAM) += regmap-ram.o
obj-$(CONFIG_REGMAP_SLIMBUS) += regmap-slimbus.o
obj-$(CONFIG_REGMAP_SPI) += regmap-spi.o
obj-$(CONFIG_REGMAP_SPMI) += regmap-spmi.o
diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h
index 919d790a01b7..10aca7119d33 100644
--- a/drivers/base/regmap/internal.h
+++ b/drivers/base/regmap/internal.h
@@ -306,4 +306,23 @@ static inline unsigned int regcache_get_index_by_order(const struct regmap *map,
return reg >> map->reg_stride_order;
}
+struct regmap_ram_data {
+ unsigned int *vals; /* Allocatd by caller */
+ bool *read;
+ bool *written;
+};
+
+/*
+ * Create a test register map with data stored in RAM, not intended
+ * for practical use.
+ */
+struct regmap *__regmap_init_ram(const struct regmap_config *config,
+ struct regmap_ram_data *data,
+ struct lock_class_key *lock_key,
+ const char *lock_name);
+
+#define regmap_init_ram(config, data) \
+ __regmap_lockdep_wrapper(__regmap_init_ram, #config, config, data)
+
+
#endif
diff --git a/drivers/base/regmap/regmap-ram.c b/drivers/base/regmap/regmap-ram.c
new file mode 100644
index 000000000000..85f34a5dee04
--- /dev/null
+++ b/drivers/base/regmap/regmap-ram.c
@@ -0,0 +1,85 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Register map access API - Memory region
+//
+// This is intended for testing only
+//
+// Copyright (c) 2023, Arm Ltd
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/swab.h>
+
+#include "internal.h"
+
+static int regmap_ram_write(void *context, unsigned int reg, unsigned int val)
+{
+ struct regmap_ram_data *data = context;
+
+ data->vals[reg] = val;
+ data->written[reg] = true;
+
+ return 0;
+}
+
+static int regmap_ram_read(void *context, unsigned int reg, unsigned int *val)
+{
+ struct regmap_ram_data *data = context;
+
+ *val = data->vals[reg];
+ data->read[reg] = true;
+
+ return 0;
+}
+
+static void regmap_ram_free_context(void *context)
+{
+ struct regmap_ram_data *data = context;
+
+ kfree(data->vals);
+ kfree(data->read);
+ kfree(data->written);
+ kfree(data);
+}
+
+static const struct regmap_bus regmap_ram = {
+ .fast_io = true,
+ .reg_write = regmap_ram_write,
+ .reg_read = regmap_ram_read,
+ .free_context = regmap_ram_free_context,
+};
+
+struct regmap *__regmap_init_ram(const struct regmap_config *config,
+ struct regmap_ram_data *data,
+ struct lock_class_key *lock_key,
+ const char *lock_name)
+{
+ struct regmap *map;
+
+ if (!config->max_register) {
+ pr_crit("No max_register specified for RAM regmap\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ data->read = kcalloc(sizeof(bool), config->max_register + 1,
+ GFP_KERNEL);
+ if (!data->read)
+ return ERR_PTR(-ENOMEM);
+
+ data->written = kcalloc(sizeof(bool), config->max_register + 1,
+ GFP_KERNEL);
+ if (!data->written)
+ return ERR_PTR(-ENOMEM);
+
+ map = __regmap_init(NULL, &regmap_ram, data, config,
+ lock_key, lock_name);
+
+ return map;
+}
+EXPORT_SYMBOL_GPL(__regmap_init_ram);
+
+MODULE_LICENSE("GPL v2");