xref: /linux/drivers/base/regmap/regmap-kunit.c (revision 36ec807b627b4c0a0a382f0ae48eac7187d14b2b)
12238959bSMark Brown // SPDX-License-Identifier: GPL-2.0
22238959bSMark Brown //
32238959bSMark Brown // regmap KUnit tests
42238959bSMark Brown //
52238959bSMark Brown // Copyright 2023 Arm Ltd
62238959bSMark Brown 
77b7982f1SRichard Fitzgerald #include <kunit/device.h>
8ce75e06eSRichard Fitzgerald #include <kunit/resource.h>
92238959bSMark Brown #include <kunit/test.h>
102238959bSMark Brown #include "internal.h"
112238959bSMark Brown 
122238959bSMark Brown #define BLOCK_TEST_SIZE 12
132238959bSMark Brown 
14ce75e06eSRichard Fitzgerald KUNIT_DEFINE_ACTION_WRAPPER(regmap_exit_action, regmap_exit, struct regmap *);
15ce75e06eSRichard Fitzgerald 
167b7982f1SRichard Fitzgerald struct regmap_test_priv {
177b7982f1SRichard Fitzgerald 	struct device *dev;
187b7982f1SRichard Fitzgerald };
197b7982f1SRichard Fitzgerald 
2048bccea9SRichard Fitzgerald struct regmap_test_param {
2148bccea9SRichard Fitzgerald 	enum regcache_type cache;
2248bccea9SRichard Fitzgerald 	enum regmap_endian val_endian;
2371091574SRichard Fitzgerald 
2471091574SRichard Fitzgerald 	unsigned int from_reg;
2548bccea9SRichard Fitzgerald };
2648bccea9SRichard Fitzgerald 
272f0dbb24SMark Brown static void get_changed_bytes(void *orig, void *new, size_t size)
282f0dbb24SMark Brown {
292f0dbb24SMark Brown 	char *o = orig;
302f0dbb24SMark Brown 	char *n = new;
312f0dbb24SMark Brown 	int i;
322f0dbb24SMark Brown 
332f0dbb24SMark Brown 	get_random_bytes(new, size);
342f0dbb24SMark Brown 
352f0dbb24SMark Brown 	/*
362f0dbb24SMark Brown 	 * This could be nicer and more efficient but we shouldn't
372f0dbb24SMark Brown 	 * super care.
382f0dbb24SMark Brown 	 */
392f0dbb24SMark Brown 	for (i = 0; i < size; i++)
402f0dbb24SMark Brown 		while (n[i] == o[i])
412f0dbb24SMark Brown 			get_random_bytes(&n[i], 1);
422f0dbb24SMark Brown }
432f0dbb24SMark Brown 
442238959bSMark Brown static const struct regmap_config test_regmap_config = {
452238959bSMark Brown 	.reg_stride = 1,
462238959bSMark Brown 	.val_bits = sizeof(unsigned int) * 8,
472238959bSMark Brown };
482238959bSMark Brown 
4948bccea9SRichard Fitzgerald static const char *regcache_type_name(enum regcache_type type)
502238959bSMark Brown {
5148bccea9SRichard Fitzgerald 	switch (type) {
5248bccea9SRichard Fitzgerald 	case REGCACHE_NONE:
5348bccea9SRichard Fitzgerald 		return "none";
5448bccea9SRichard Fitzgerald 	case REGCACHE_FLAT:
5548bccea9SRichard Fitzgerald 		return "flat";
5648bccea9SRichard Fitzgerald 	case REGCACHE_RBTREE:
5748bccea9SRichard Fitzgerald 		return "rbtree";
5848bccea9SRichard Fitzgerald 	case REGCACHE_MAPLE:
5948bccea9SRichard Fitzgerald 		return "maple";
6048bccea9SRichard Fitzgerald 	default:
6148bccea9SRichard Fitzgerald 		return NULL;
6248bccea9SRichard Fitzgerald 	}
632238959bSMark Brown }
642238959bSMark Brown 
6548bccea9SRichard Fitzgerald static const char *regmap_endian_name(enum regmap_endian endian)
6648bccea9SRichard Fitzgerald {
6748bccea9SRichard Fitzgerald 	switch (endian) {
6848bccea9SRichard Fitzgerald 	case REGMAP_ENDIAN_BIG:
6948bccea9SRichard Fitzgerald 		return "big";
7048bccea9SRichard Fitzgerald 	case REGMAP_ENDIAN_LITTLE:
7148bccea9SRichard Fitzgerald 		return "little";
7248bccea9SRichard Fitzgerald 	case REGMAP_ENDIAN_DEFAULT:
7348bccea9SRichard Fitzgerald 		return "default";
7448bccea9SRichard Fitzgerald 	case REGMAP_ENDIAN_NATIVE:
7548bccea9SRichard Fitzgerald 		return "native";
7648bccea9SRichard Fitzgerald 	default:
7748bccea9SRichard Fitzgerald 		return NULL;
7848bccea9SRichard Fitzgerald 	}
7948bccea9SRichard Fitzgerald }
8048bccea9SRichard Fitzgerald 
8148bccea9SRichard Fitzgerald static void param_to_desc(const struct regmap_test_param *param, char *desc)
8248bccea9SRichard Fitzgerald {
8371091574SRichard Fitzgerald 	snprintf(desc, KUNIT_PARAM_DESC_SIZE, "%s-%s @%#x",
8448bccea9SRichard Fitzgerald 		 regcache_type_name(param->cache),
8571091574SRichard Fitzgerald 		 regmap_endian_name(param->val_endian),
8671091574SRichard Fitzgerald 		 param->from_reg);
8748bccea9SRichard Fitzgerald }
8848bccea9SRichard Fitzgerald 
8948bccea9SRichard Fitzgerald static const struct regmap_test_param regcache_types_list[] = {
9048bccea9SRichard Fitzgerald 	{ .cache = REGCACHE_NONE },
9148bccea9SRichard Fitzgerald 	{ .cache = REGCACHE_FLAT },
9248bccea9SRichard Fitzgerald 	{ .cache = REGCACHE_RBTREE },
9348bccea9SRichard Fitzgerald 	{ .cache = REGCACHE_MAPLE },
942238959bSMark Brown };
952238959bSMark Brown 
9648bccea9SRichard Fitzgerald KUNIT_ARRAY_PARAM(regcache_types, regcache_types_list, param_to_desc);
972238959bSMark Brown 
98ac4394bfSRichard Fitzgerald static const struct regmap_test_param real_cache_types_only_list[] = {
9948bccea9SRichard Fitzgerald 	{ .cache = REGCACHE_FLAT },
10048bccea9SRichard Fitzgerald 	{ .cache = REGCACHE_RBTREE },
10148bccea9SRichard Fitzgerald 	{ .cache = REGCACHE_MAPLE },
1022238959bSMark Brown };
1032238959bSMark Brown 
104ac4394bfSRichard Fitzgerald KUNIT_ARRAY_PARAM(real_cache_types_only, real_cache_types_only_list, param_to_desc);
105ac4394bfSRichard Fitzgerald 
106ac4394bfSRichard Fitzgerald static const struct regmap_test_param real_cache_types_list[] = {
107ac4394bfSRichard Fitzgerald 	{ .cache = REGCACHE_FLAT,   .from_reg = 0 },
108ac4394bfSRichard Fitzgerald 	{ .cache = REGCACHE_FLAT,   .from_reg = 0x2001 },
109ac4394bfSRichard Fitzgerald 	{ .cache = REGCACHE_FLAT,   .from_reg = 0x2002 },
110ac4394bfSRichard Fitzgerald 	{ .cache = REGCACHE_FLAT,   .from_reg = 0x2003 },
111ac4394bfSRichard Fitzgerald 	{ .cache = REGCACHE_FLAT,   .from_reg = 0x2004 },
112ac4394bfSRichard Fitzgerald 	{ .cache = REGCACHE_RBTREE, .from_reg = 0 },
113ac4394bfSRichard Fitzgerald 	{ .cache = REGCACHE_RBTREE, .from_reg = 0x2001 },
114ac4394bfSRichard Fitzgerald 	{ .cache = REGCACHE_RBTREE, .from_reg = 0x2002 },
115ac4394bfSRichard Fitzgerald 	{ .cache = REGCACHE_RBTREE, .from_reg = 0x2003 },
116ac4394bfSRichard Fitzgerald 	{ .cache = REGCACHE_RBTREE, .from_reg = 0x2004 },
117ac4394bfSRichard Fitzgerald 	{ .cache = REGCACHE_MAPLE,  .from_reg = 0 },
118ac4394bfSRichard Fitzgerald 	{ .cache = REGCACHE_MAPLE,  .from_reg = 0x2001 },
119ac4394bfSRichard Fitzgerald 	{ .cache = REGCACHE_MAPLE,  .from_reg = 0x2002 },
120ac4394bfSRichard Fitzgerald 	{ .cache = REGCACHE_MAPLE,  .from_reg = 0x2003 },
121ac4394bfSRichard Fitzgerald 	{ .cache = REGCACHE_MAPLE,  .from_reg = 0x2004 },
122ac4394bfSRichard Fitzgerald };
123ac4394bfSRichard Fitzgerald 
12448bccea9SRichard Fitzgerald KUNIT_ARRAY_PARAM(real_cache_types, real_cache_types_list, param_to_desc);
1252238959bSMark Brown 
12648bccea9SRichard Fitzgerald static const struct regmap_test_param sparse_cache_types_list[] = {
12771091574SRichard Fitzgerald 	{ .cache = REGCACHE_RBTREE, .from_reg = 0 },
12871091574SRichard Fitzgerald 	{ .cache = REGCACHE_RBTREE, .from_reg = 0x2001 },
12971091574SRichard Fitzgerald 	{ .cache = REGCACHE_RBTREE, .from_reg = 0x2002 },
13071091574SRichard Fitzgerald 	{ .cache = REGCACHE_RBTREE, .from_reg = 0x2003 },
13171091574SRichard Fitzgerald 	{ .cache = REGCACHE_RBTREE, .from_reg = 0x2004 },
13271091574SRichard Fitzgerald 	{ .cache = REGCACHE_MAPLE,  .from_reg = 0 },
13371091574SRichard Fitzgerald 	{ .cache = REGCACHE_MAPLE,  .from_reg = 0x2001 },
13471091574SRichard Fitzgerald 	{ .cache = REGCACHE_MAPLE,  .from_reg = 0x2002 },
13571091574SRichard Fitzgerald 	{ .cache = REGCACHE_MAPLE,  .from_reg = 0x2003 },
13671091574SRichard Fitzgerald 	{ .cache = REGCACHE_MAPLE,  .from_reg = 0x2004 },
1372238959bSMark Brown };
1382238959bSMark Brown 
13948bccea9SRichard Fitzgerald KUNIT_ARRAY_PARAM(sparse_cache_types, sparse_cache_types_list, param_to_desc);
1402238959bSMark Brown 
1417b7982f1SRichard Fitzgerald static struct regmap *gen_regmap(struct kunit *test,
1427b7982f1SRichard Fitzgerald 				 struct regmap_config *config,
1432238959bSMark Brown 				 struct regmap_ram_data **data)
1442238959bSMark Brown {
14548bccea9SRichard Fitzgerald 	const struct regmap_test_param *param = test->param_value;
1467b7982f1SRichard Fitzgerald 	struct regmap_test_priv *priv = test->priv;
1472238959bSMark Brown 	unsigned int *buf;
148c3820641SRichard Fitzgerald 	struct regmap *ret = ERR_PTR(-ENOMEM);
14971091574SRichard Fitzgerald 	size_t size;
150c3820641SRichard Fitzgerald 	int i, error;
1512238959bSMark Brown 	struct reg_default *defaults;
1522238959bSMark Brown 
15348bccea9SRichard Fitzgerald 	config->cache_type = param->cache;
154a9e26169SGuenter Roeck 	config->disable_locking = config->cache_type == REGCACHE_RBTREE ||
155a9e26169SGuenter Roeck 					config->cache_type == REGCACHE_MAPLE;
156a9e26169SGuenter Roeck 
15771091574SRichard Fitzgerald 	if (config->max_register == 0) {
15871091574SRichard Fitzgerald 		config->max_register = param->from_reg;
15971091574SRichard Fitzgerald 		if (config->num_reg_defaults)
16071091574SRichard Fitzgerald 			config->max_register += (config->num_reg_defaults - 1) *
16171091574SRichard Fitzgerald 						config->reg_stride;
16271091574SRichard Fitzgerald 		else
16371091574SRichard Fitzgerald 			config->max_register += (BLOCK_TEST_SIZE * config->reg_stride);
16471091574SRichard Fitzgerald 	}
16571091574SRichard Fitzgerald 
166f82ecf76SAndy Shevchenko 	size = array_size(config->max_register + 1, sizeof(*buf));
1672238959bSMark Brown 	buf = kmalloc(size, GFP_KERNEL);
1682238959bSMark Brown 	if (!buf)
1692238959bSMark Brown 		return ERR_PTR(-ENOMEM);
1702238959bSMark Brown 
1712238959bSMark Brown 	get_random_bytes(buf, size);
1722238959bSMark Brown 
1732238959bSMark Brown 	*data = kzalloc(sizeof(**data), GFP_KERNEL);
1742238959bSMark Brown 	if (!(*data))
175c3820641SRichard Fitzgerald 		goto out_free;
1762238959bSMark Brown 	(*data)->vals = buf;
1772238959bSMark Brown 
1782238959bSMark Brown 	if (config->num_reg_defaults) {
179c3820641SRichard Fitzgerald 		defaults = kunit_kcalloc(test,
180c3820641SRichard Fitzgerald 					 config->num_reg_defaults,
1812238959bSMark Brown 					 sizeof(struct reg_default),
1822238959bSMark Brown 					 GFP_KERNEL);
1832238959bSMark Brown 		if (!defaults)
184c3820641SRichard Fitzgerald 			goto out_free;
185c3820641SRichard Fitzgerald 
1862238959bSMark Brown 		config->reg_defaults = defaults;
1872238959bSMark Brown 
1882238959bSMark Brown 		for (i = 0; i < config->num_reg_defaults; i++) {
18971091574SRichard Fitzgerald 			defaults[i].reg = param->from_reg + (i * config->reg_stride);
19071091574SRichard Fitzgerald 			defaults[i].def = buf[param->from_reg + (i * config->reg_stride)];
1912238959bSMark Brown 		}
1922238959bSMark Brown 	}
1932238959bSMark Brown 
1947b7982f1SRichard Fitzgerald 	ret = regmap_init_ram(priv->dev, config, *data);
195c3820641SRichard Fitzgerald 	if (IS_ERR(ret))
196c3820641SRichard Fitzgerald 		goto out_free;
197c3820641SRichard Fitzgerald 
198c3820641SRichard Fitzgerald 	/* This calls regmap_exit() on failure, which frees buf and *data */
199c3820641SRichard Fitzgerald 	error = kunit_add_action_or_reset(test, regmap_exit_action, ret);
200c3820641SRichard Fitzgerald 	if (error)
201c3820641SRichard Fitzgerald 		ret = ERR_PTR(error);
202c3820641SRichard Fitzgerald 
203c3820641SRichard Fitzgerald 	return ret;
204c3820641SRichard Fitzgerald 
205c3820641SRichard Fitzgerald out_free:
2062238959bSMark Brown 	kfree(buf);
2072238959bSMark Brown 	kfree(*data);
2082238959bSMark Brown 
2092238959bSMark Brown 	return ret;
2102238959bSMark Brown }
2112238959bSMark Brown 
212ac4394bfSRichard Fitzgerald static bool reg_5_false(struct device *dev, unsigned int reg)
21318003306SMark Brown {
214ac4394bfSRichard Fitzgerald 	struct kunit *test = dev_get_drvdata(dev);
215ac4394bfSRichard Fitzgerald 	const struct regmap_test_param *param = test->param_value;
216ac4394bfSRichard Fitzgerald 
217ac4394bfSRichard Fitzgerald 	return reg != (param->from_reg + 5);
21818003306SMark Brown }
21918003306SMark Brown 
2202238959bSMark Brown static void basic_read_write(struct kunit *test)
2212238959bSMark Brown {
2222238959bSMark Brown 	struct regmap *map;
2232238959bSMark Brown 	struct regmap_config config;
2242238959bSMark Brown 	struct regmap_ram_data *data;
2252238959bSMark Brown 	unsigned int val, rval;
2262238959bSMark Brown 
2272238959bSMark Brown 	config = test_regmap_config;
2282238959bSMark Brown 
2297b7982f1SRichard Fitzgerald 	map = gen_regmap(test, &config, &data);
2302238959bSMark Brown 	KUNIT_ASSERT_FALSE(test, IS_ERR(map));
2312238959bSMark Brown 	if (IS_ERR(map))
2322238959bSMark Brown 		return;
2332238959bSMark Brown 
2342238959bSMark Brown 	get_random_bytes(&val, sizeof(val));
2352238959bSMark Brown 
2362238959bSMark Brown 	/* If we write a value to a register we can read it back */
2372238959bSMark Brown 	KUNIT_EXPECT_EQ(test, 0, regmap_write(map, 0, val));
2382238959bSMark Brown 	KUNIT_EXPECT_EQ(test, 0, regmap_read(map, 0, &rval));
2392238959bSMark Brown 	KUNIT_EXPECT_EQ(test, val, rval);
2402238959bSMark Brown 
2412238959bSMark Brown 	/* If using a cache the cache satisfied the read */
24248bccea9SRichard Fitzgerald 	KUNIT_EXPECT_EQ(test, config.cache_type == REGCACHE_NONE, data->read[0]);
2432238959bSMark Brown }
2442238959bSMark Brown 
2452238959bSMark Brown static void bulk_write(struct kunit *test)
2462238959bSMark Brown {
2472238959bSMark Brown 	struct regmap *map;
2482238959bSMark Brown 	struct regmap_config config;
2492238959bSMark Brown 	struct regmap_ram_data *data;
2502238959bSMark Brown 	unsigned int val[BLOCK_TEST_SIZE], rval[BLOCK_TEST_SIZE];
2512238959bSMark Brown 	int i;
2522238959bSMark Brown 
2532238959bSMark Brown 	config = test_regmap_config;
2542238959bSMark Brown 
2557b7982f1SRichard Fitzgerald 	map = gen_regmap(test, &config, &data);
2562238959bSMark Brown 	KUNIT_ASSERT_FALSE(test, IS_ERR(map));
2572238959bSMark Brown 	if (IS_ERR(map))
2582238959bSMark Brown 		return;
2592238959bSMark Brown 
2602238959bSMark Brown 	get_random_bytes(&val, sizeof(val));
2612238959bSMark Brown 
2622238959bSMark Brown 	/*
2632238959bSMark Brown 	 * Data written via the bulk API can be read back with single
2642238959bSMark Brown 	 * reads.
2652238959bSMark Brown 	 */
2662238959bSMark Brown 	KUNIT_EXPECT_EQ(test, 0, regmap_bulk_write(map, 0, val,
2672238959bSMark Brown 						   BLOCK_TEST_SIZE));
2682238959bSMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
2692238959bSMark Brown 		KUNIT_EXPECT_EQ(test, 0, regmap_read(map, i, &rval[i]));
2702238959bSMark Brown 
2712238959bSMark Brown 	KUNIT_EXPECT_MEMEQ(test, val, rval, sizeof(val));
2722238959bSMark Brown 
2732238959bSMark Brown 	/* If using a cache the cache satisfied the read */
2742238959bSMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
27548bccea9SRichard Fitzgerald 		KUNIT_EXPECT_EQ(test, config.cache_type == REGCACHE_NONE, data->read[i]);
2762238959bSMark Brown }
2772238959bSMark Brown 
2782238959bSMark Brown static void bulk_read(struct kunit *test)
2792238959bSMark Brown {
2802238959bSMark Brown 	struct regmap *map;
2812238959bSMark Brown 	struct regmap_config config;
2822238959bSMark Brown 	struct regmap_ram_data *data;
2832238959bSMark Brown 	unsigned int val[BLOCK_TEST_SIZE], rval[BLOCK_TEST_SIZE];
2842238959bSMark Brown 	int i;
2852238959bSMark Brown 
2862238959bSMark Brown 	config = test_regmap_config;
2872238959bSMark Brown 
2887b7982f1SRichard Fitzgerald 	map = gen_regmap(test, &config, &data);
2892238959bSMark Brown 	KUNIT_ASSERT_FALSE(test, IS_ERR(map));
2902238959bSMark Brown 	if (IS_ERR(map))
2912238959bSMark Brown 		return;
2922238959bSMark Brown 
2932238959bSMark Brown 	get_random_bytes(&val, sizeof(val));
2942238959bSMark Brown 
2952238959bSMark Brown 	/* Data written as single writes can be read via the bulk API */
2962238959bSMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
2972238959bSMark Brown 		KUNIT_EXPECT_EQ(test, 0, regmap_write(map, i, val[i]));
2982238959bSMark Brown 	KUNIT_EXPECT_EQ(test, 0, regmap_bulk_read(map, 0, rval,
2992238959bSMark Brown 						  BLOCK_TEST_SIZE));
3002238959bSMark Brown 	KUNIT_EXPECT_MEMEQ(test, val, rval, sizeof(val));
3012238959bSMark Brown 
3022238959bSMark Brown 	/* If using a cache the cache satisfied the read */
3032238959bSMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
30448bccea9SRichard Fitzgerald 		KUNIT_EXPECT_EQ(test, config.cache_type == REGCACHE_NONE, data->read[i]);
3052238959bSMark Brown }
3062238959bSMark Brown 
307*c2bb8198SGuenter Roeck static void multi_write(struct kunit *test)
308*c2bb8198SGuenter Roeck {
309*c2bb8198SGuenter Roeck 	struct regmap *map;
310*c2bb8198SGuenter Roeck 	struct regmap_config config;
311*c2bb8198SGuenter Roeck 	struct regmap_ram_data *data;
312*c2bb8198SGuenter Roeck 	struct reg_sequence sequence[BLOCK_TEST_SIZE];
313*c2bb8198SGuenter Roeck 	unsigned int val[BLOCK_TEST_SIZE], rval[BLOCK_TEST_SIZE];
314*c2bb8198SGuenter Roeck 	int i;
315*c2bb8198SGuenter Roeck 
316*c2bb8198SGuenter Roeck 	config = test_regmap_config;
317*c2bb8198SGuenter Roeck 
318*c2bb8198SGuenter Roeck 	map = gen_regmap(test, &config, &data);
319*c2bb8198SGuenter Roeck 	KUNIT_ASSERT_FALSE(test, IS_ERR(map));
320*c2bb8198SGuenter Roeck 	if (IS_ERR(map))
321*c2bb8198SGuenter Roeck 		return;
322*c2bb8198SGuenter Roeck 
323*c2bb8198SGuenter Roeck 	get_random_bytes(&val, sizeof(val));
324*c2bb8198SGuenter Roeck 
325*c2bb8198SGuenter Roeck 	/*
326*c2bb8198SGuenter Roeck 	 * Data written via the multi API can be read back with single
327*c2bb8198SGuenter Roeck 	 * reads.
328*c2bb8198SGuenter Roeck 	 */
329*c2bb8198SGuenter Roeck 	for (i = 0; i < BLOCK_TEST_SIZE; i++) {
330*c2bb8198SGuenter Roeck 		sequence[i].reg = i;
331*c2bb8198SGuenter Roeck 		sequence[i].def = val[i];
332*c2bb8198SGuenter Roeck 		sequence[i].delay_us = 0;
333*c2bb8198SGuenter Roeck 	}
334*c2bb8198SGuenter Roeck 	KUNIT_EXPECT_EQ(test, 0,
335*c2bb8198SGuenter Roeck 			regmap_multi_reg_write(map, sequence, BLOCK_TEST_SIZE));
336*c2bb8198SGuenter Roeck 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
337*c2bb8198SGuenter Roeck 		KUNIT_EXPECT_EQ(test, 0, regmap_read(map, i, &rval[i]));
338*c2bb8198SGuenter Roeck 
339*c2bb8198SGuenter Roeck 	KUNIT_EXPECT_MEMEQ(test, val, rval, sizeof(val));
340*c2bb8198SGuenter Roeck 
341*c2bb8198SGuenter Roeck 	/* If using a cache the cache satisfied the read */
342*c2bb8198SGuenter Roeck 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
343*c2bb8198SGuenter Roeck 		KUNIT_EXPECT_EQ(test, config.cache_type == REGCACHE_NONE, data->read[i]);
344*c2bb8198SGuenter Roeck }
345*c2bb8198SGuenter Roeck 
346*c2bb8198SGuenter Roeck static void multi_read(struct kunit *test)
347*c2bb8198SGuenter Roeck {
348*c2bb8198SGuenter Roeck 	struct regmap *map;
349*c2bb8198SGuenter Roeck 	struct regmap_config config;
350*c2bb8198SGuenter Roeck 	struct regmap_ram_data *data;
351*c2bb8198SGuenter Roeck 	unsigned int regs[BLOCK_TEST_SIZE];
352*c2bb8198SGuenter Roeck 	unsigned int val[BLOCK_TEST_SIZE], rval[BLOCK_TEST_SIZE];
353*c2bb8198SGuenter Roeck 	int i;
354*c2bb8198SGuenter Roeck 
355*c2bb8198SGuenter Roeck 	config = test_regmap_config;
356*c2bb8198SGuenter Roeck 
357*c2bb8198SGuenter Roeck 	map = gen_regmap(test, &config, &data);
358*c2bb8198SGuenter Roeck 	KUNIT_ASSERT_FALSE(test, IS_ERR(map));
359*c2bb8198SGuenter Roeck 	if (IS_ERR(map))
360*c2bb8198SGuenter Roeck 		return;
361*c2bb8198SGuenter Roeck 
362*c2bb8198SGuenter Roeck 	get_random_bytes(&val, sizeof(val));
363*c2bb8198SGuenter Roeck 
364*c2bb8198SGuenter Roeck 	/* Data written as single writes can be read via the multi API */
365*c2bb8198SGuenter Roeck 	for (i = 0; i < BLOCK_TEST_SIZE; i++) {
366*c2bb8198SGuenter Roeck 		regs[i] = i;
367*c2bb8198SGuenter Roeck 		KUNIT_EXPECT_EQ(test, 0, regmap_write(map, i, val[i]));
368*c2bb8198SGuenter Roeck 	}
369*c2bb8198SGuenter Roeck 	KUNIT_EXPECT_EQ(test, 0,
370*c2bb8198SGuenter Roeck 			regmap_multi_reg_read(map, regs, rval, BLOCK_TEST_SIZE));
371*c2bb8198SGuenter Roeck 	KUNIT_EXPECT_MEMEQ(test, val, rval, sizeof(val));
372*c2bb8198SGuenter Roeck 
373*c2bb8198SGuenter Roeck 	/* If using a cache the cache satisfied the read */
374*c2bb8198SGuenter Roeck 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
375*c2bb8198SGuenter Roeck 		KUNIT_EXPECT_EQ(test, config.cache_type == REGCACHE_NONE, data->read[i]);
376*c2bb8198SGuenter Roeck }
377*c2bb8198SGuenter Roeck 
378f63eb9aeSRichard Fitzgerald static void read_bypassed(struct kunit *test)
379f63eb9aeSRichard Fitzgerald {
380f63eb9aeSRichard Fitzgerald 	const struct regmap_test_param *param = test->param_value;
381f63eb9aeSRichard Fitzgerald 	struct regmap *map;
382f63eb9aeSRichard Fitzgerald 	struct regmap_config config;
383f63eb9aeSRichard Fitzgerald 	struct regmap_ram_data *data;
384f63eb9aeSRichard Fitzgerald 	unsigned int val[BLOCK_TEST_SIZE], rval;
385f63eb9aeSRichard Fitzgerald 	int i;
386f63eb9aeSRichard Fitzgerald 
387f63eb9aeSRichard Fitzgerald 	config = test_regmap_config;
388f63eb9aeSRichard Fitzgerald 
389f63eb9aeSRichard Fitzgerald 	map = gen_regmap(test, &config, &data);
390f63eb9aeSRichard Fitzgerald 	KUNIT_ASSERT_FALSE(test, IS_ERR(map));
391f63eb9aeSRichard Fitzgerald 	if (IS_ERR(map))
392f63eb9aeSRichard Fitzgerald 		return;
393f63eb9aeSRichard Fitzgerald 
394f63eb9aeSRichard Fitzgerald 	KUNIT_EXPECT_FALSE(test, map->cache_bypass);
395f63eb9aeSRichard Fitzgerald 
396f63eb9aeSRichard Fitzgerald 	get_random_bytes(&val, sizeof(val));
397f63eb9aeSRichard Fitzgerald 
398f63eb9aeSRichard Fitzgerald 	/* Write some test values */
399f63eb9aeSRichard Fitzgerald 	KUNIT_EXPECT_EQ(test, 0, regmap_bulk_write(map, param->from_reg, val, ARRAY_SIZE(val)));
400f63eb9aeSRichard Fitzgerald 
401f63eb9aeSRichard Fitzgerald 	regcache_cache_only(map, true);
402f63eb9aeSRichard Fitzgerald 
403f63eb9aeSRichard Fitzgerald 	/*
404f63eb9aeSRichard Fitzgerald 	 * While in cache-only regmap_read_bypassed() should return the register
405f63eb9aeSRichard Fitzgerald 	 * value and leave the map in cache-only.
406f63eb9aeSRichard Fitzgerald 	 */
407f63eb9aeSRichard Fitzgerald 	for (i = 0; i < ARRAY_SIZE(val); i++) {
408f63eb9aeSRichard Fitzgerald 		/* Put inverted bits in rval to prove we really read the value */
409f63eb9aeSRichard Fitzgerald 		rval = ~val[i];
410f63eb9aeSRichard Fitzgerald 		KUNIT_EXPECT_EQ(test, 0, regmap_read(map, param->from_reg + i, &rval));
411f63eb9aeSRichard Fitzgerald 		KUNIT_EXPECT_EQ(test, val[i], rval);
412f63eb9aeSRichard Fitzgerald 
413f63eb9aeSRichard Fitzgerald 		rval = ~val[i];
414f63eb9aeSRichard Fitzgerald 		KUNIT_EXPECT_EQ(test, 0, regmap_read_bypassed(map, param->from_reg + i, &rval));
415f63eb9aeSRichard Fitzgerald 		KUNIT_EXPECT_EQ(test, val[i], rval);
416f63eb9aeSRichard Fitzgerald 		KUNIT_EXPECT_TRUE(test, map->cache_only);
417f63eb9aeSRichard Fitzgerald 		KUNIT_EXPECT_FALSE(test, map->cache_bypass);
418f63eb9aeSRichard Fitzgerald 	}
419f63eb9aeSRichard Fitzgerald 
420f63eb9aeSRichard Fitzgerald 	/*
421f63eb9aeSRichard Fitzgerald 	 * Change the underlying register values to prove it is returning
422f63eb9aeSRichard Fitzgerald 	 * real values not cached values.
423f63eb9aeSRichard Fitzgerald 	 */
424f63eb9aeSRichard Fitzgerald 	for (i = 0; i < ARRAY_SIZE(val); i++) {
425f63eb9aeSRichard Fitzgerald 		val[i] = ~val[i];
426f63eb9aeSRichard Fitzgerald 		data->vals[param->from_reg + i] = val[i];
427f63eb9aeSRichard Fitzgerald 	}
428f63eb9aeSRichard Fitzgerald 
429f63eb9aeSRichard Fitzgerald 	for (i = 0; i < ARRAY_SIZE(val); i++) {
430f63eb9aeSRichard Fitzgerald 		rval = ~val[i];
431f63eb9aeSRichard Fitzgerald 		KUNIT_EXPECT_EQ(test, 0, regmap_read(map, param->from_reg + i, &rval));
432f63eb9aeSRichard Fitzgerald 		KUNIT_EXPECT_NE(test, val[i], rval);
433f63eb9aeSRichard Fitzgerald 
434f63eb9aeSRichard Fitzgerald 		rval = ~val[i];
435f63eb9aeSRichard Fitzgerald 		KUNIT_EXPECT_EQ(test, 0, regmap_read_bypassed(map, param->from_reg + i, &rval));
436f63eb9aeSRichard Fitzgerald 		KUNIT_EXPECT_EQ(test, val[i], rval);
437f63eb9aeSRichard Fitzgerald 		KUNIT_EXPECT_TRUE(test, map->cache_only);
438f63eb9aeSRichard Fitzgerald 		KUNIT_EXPECT_FALSE(test, map->cache_bypass);
439f63eb9aeSRichard Fitzgerald 	}
440f63eb9aeSRichard Fitzgerald }
441f63eb9aeSRichard Fitzgerald 
442f63eb9aeSRichard Fitzgerald static void read_bypassed_volatile(struct kunit *test)
443f63eb9aeSRichard Fitzgerald {
444f63eb9aeSRichard Fitzgerald 	const struct regmap_test_param *param = test->param_value;
445f63eb9aeSRichard Fitzgerald 	struct regmap *map;
446f63eb9aeSRichard Fitzgerald 	struct regmap_config config;
447f63eb9aeSRichard Fitzgerald 	struct regmap_ram_data *data;
448f63eb9aeSRichard Fitzgerald 	unsigned int val[BLOCK_TEST_SIZE], rval;
449f63eb9aeSRichard Fitzgerald 	int i;
450f63eb9aeSRichard Fitzgerald 
451f63eb9aeSRichard Fitzgerald 	config = test_regmap_config;
452f63eb9aeSRichard Fitzgerald 	/* All registers except #5 volatile */
453f63eb9aeSRichard Fitzgerald 	config.volatile_reg = reg_5_false;
454f63eb9aeSRichard Fitzgerald 
455f63eb9aeSRichard Fitzgerald 	map = gen_regmap(test, &config, &data);
456f63eb9aeSRichard Fitzgerald 	KUNIT_ASSERT_FALSE(test, IS_ERR(map));
457f63eb9aeSRichard Fitzgerald 	if (IS_ERR(map))
458f63eb9aeSRichard Fitzgerald 		return;
459f63eb9aeSRichard Fitzgerald 
460f63eb9aeSRichard Fitzgerald 	KUNIT_EXPECT_FALSE(test, map->cache_bypass);
461f63eb9aeSRichard Fitzgerald 
462f63eb9aeSRichard Fitzgerald 	get_random_bytes(&val, sizeof(val));
463f63eb9aeSRichard Fitzgerald 
464f63eb9aeSRichard Fitzgerald 	/* Write some test values */
465f63eb9aeSRichard Fitzgerald 	KUNIT_EXPECT_EQ(test, 0, regmap_bulk_write(map, param->from_reg, val, ARRAY_SIZE(val)));
466f63eb9aeSRichard Fitzgerald 
467f63eb9aeSRichard Fitzgerald 	regcache_cache_only(map, true);
468f63eb9aeSRichard Fitzgerald 
469f63eb9aeSRichard Fitzgerald 	/*
470f63eb9aeSRichard Fitzgerald 	 * While in cache-only regmap_read_bypassed() should return the register
471f63eb9aeSRichard Fitzgerald 	 * value and leave the map in cache-only.
472f63eb9aeSRichard Fitzgerald 	 */
473f63eb9aeSRichard Fitzgerald 	for (i = 0; i < ARRAY_SIZE(val); i++) {
474f63eb9aeSRichard Fitzgerald 		/* Register #5 is non-volatile so should read from cache */
475f63eb9aeSRichard Fitzgerald 		KUNIT_EXPECT_EQ(test, (i == 5) ? 0 : -EBUSY,
476f63eb9aeSRichard Fitzgerald 				regmap_read(map, param->from_reg + i, &rval));
477f63eb9aeSRichard Fitzgerald 
478f63eb9aeSRichard Fitzgerald 		/* Put inverted bits in rval to prove we really read the value */
479f63eb9aeSRichard Fitzgerald 		rval = ~val[i];
480f63eb9aeSRichard Fitzgerald 		KUNIT_EXPECT_EQ(test, 0, regmap_read_bypassed(map, param->from_reg + i, &rval));
481f63eb9aeSRichard Fitzgerald 		KUNIT_EXPECT_EQ(test, val[i], rval);
482f63eb9aeSRichard Fitzgerald 		KUNIT_EXPECT_TRUE(test, map->cache_only);
483f63eb9aeSRichard Fitzgerald 		KUNIT_EXPECT_FALSE(test, map->cache_bypass);
484f63eb9aeSRichard Fitzgerald 	}
485f63eb9aeSRichard Fitzgerald 
486f63eb9aeSRichard Fitzgerald 	/*
487f63eb9aeSRichard Fitzgerald 	 * Change the underlying register values to prove it is returning
488f63eb9aeSRichard Fitzgerald 	 * real values not cached values.
489f63eb9aeSRichard Fitzgerald 	 */
490f63eb9aeSRichard Fitzgerald 	for (i = 0; i < ARRAY_SIZE(val); i++) {
491f63eb9aeSRichard Fitzgerald 		val[i] = ~val[i];
492f63eb9aeSRichard Fitzgerald 		data->vals[param->from_reg + i] = val[i];
493f63eb9aeSRichard Fitzgerald 	}
494f63eb9aeSRichard Fitzgerald 
495f63eb9aeSRichard Fitzgerald 	for (i = 0; i < ARRAY_SIZE(val); i++) {
496f63eb9aeSRichard Fitzgerald 		if (i == 5)
497f63eb9aeSRichard Fitzgerald 			continue;
498f63eb9aeSRichard Fitzgerald 
499f63eb9aeSRichard Fitzgerald 		rval = ~val[i];
500f63eb9aeSRichard Fitzgerald 		KUNIT_EXPECT_EQ(test, 0, regmap_read_bypassed(map, param->from_reg + i, &rval));
501f63eb9aeSRichard Fitzgerald 		KUNIT_EXPECT_EQ(test, val[i], rval);
502f63eb9aeSRichard Fitzgerald 		KUNIT_EXPECT_TRUE(test, map->cache_only);
503f63eb9aeSRichard Fitzgerald 		KUNIT_EXPECT_FALSE(test, map->cache_bypass);
504f63eb9aeSRichard Fitzgerald 	}
505f63eb9aeSRichard Fitzgerald }
506f63eb9aeSRichard Fitzgerald 
50718003306SMark Brown static void write_readonly(struct kunit *test)
50818003306SMark Brown {
50918003306SMark Brown 	struct regmap *map;
51018003306SMark Brown 	struct regmap_config config;
51118003306SMark Brown 	struct regmap_ram_data *data;
51218003306SMark Brown 	unsigned int val;
51318003306SMark Brown 	int i;
51418003306SMark Brown 
51518003306SMark Brown 	config = test_regmap_config;
51618003306SMark Brown 	config.num_reg_defaults = BLOCK_TEST_SIZE;
51718003306SMark Brown 	config.writeable_reg = reg_5_false;
51818003306SMark Brown 
5197b7982f1SRichard Fitzgerald 	map = gen_regmap(test, &config, &data);
52018003306SMark Brown 	KUNIT_ASSERT_FALSE(test, IS_ERR(map));
52118003306SMark Brown 	if (IS_ERR(map))
52218003306SMark Brown 		return;
52318003306SMark Brown 
52418003306SMark Brown 	get_random_bytes(&val, sizeof(val));
52518003306SMark Brown 
52618003306SMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
52718003306SMark Brown 		data->written[i] = false;
52818003306SMark Brown 
52918003306SMark Brown 	/* Change the value of all registers, readonly should fail */
53018003306SMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
53118003306SMark Brown 		KUNIT_EXPECT_EQ(test, i != 5, regmap_write(map, i, val) == 0);
53218003306SMark Brown 
53318003306SMark Brown 	/* Did that match what we see on the device? */
53418003306SMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
53518003306SMark Brown 		KUNIT_EXPECT_EQ(test, i != 5, data->written[i]);
53618003306SMark Brown }
53718003306SMark Brown 
538a07bff40SMark Brown static void read_writeonly(struct kunit *test)
539a07bff40SMark Brown {
540a07bff40SMark Brown 	struct regmap *map;
541a07bff40SMark Brown 	struct regmap_config config;
542a07bff40SMark Brown 	struct regmap_ram_data *data;
543a07bff40SMark Brown 	unsigned int val;
544a07bff40SMark Brown 	int i;
545a07bff40SMark Brown 
546a07bff40SMark Brown 	config = test_regmap_config;
547a07bff40SMark Brown 	config.readable_reg = reg_5_false;
548a07bff40SMark Brown 
5497b7982f1SRichard Fitzgerald 	map = gen_regmap(test, &config, &data);
550a07bff40SMark Brown 	KUNIT_ASSERT_FALSE(test, IS_ERR(map));
551a07bff40SMark Brown 	if (IS_ERR(map))
552a07bff40SMark Brown 		return;
553a07bff40SMark Brown 
554a07bff40SMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
555a07bff40SMark Brown 		data->read[i] = false;
556a07bff40SMark Brown 
557d0c99ffeSMark Brown 	/*
558d0c99ffeSMark Brown 	 * Try to read all the registers, the writeonly one should
559d0c99ffeSMark Brown 	 * fail if we aren't using the flat cache.
560d0c99ffeSMark Brown 	 */
561d0c99ffeSMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++) {
56248bccea9SRichard Fitzgerald 		if (config.cache_type != REGCACHE_FLAT) {
563d0c99ffeSMark Brown 			KUNIT_EXPECT_EQ(test, i != 5,
564d0c99ffeSMark Brown 					regmap_read(map, i, &val) == 0);
565d0c99ffeSMark Brown 		} else {
566d0c99ffeSMark Brown 			KUNIT_EXPECT_EQ(test, 0, regmap_read(map, i, &val));
567d0c99ffeSMark Brown 		}
568d0c99ffeSMark Brown 	}
569a07bff40SMark Brown 
570a07bff40SMark Brown 	/* Did we trigger a hardware access? */
571a07bff40SMark Brown 	KUNIT_EXPECT_FALSE(test, data->read[5]);
572a07bff40SMark Brown }
573a07bff40SMark Brown 
5742238959bSMark Brown static void reg_defaults(struct kunit *test)
5752238959bSMark Brown {
5762238959bSMark Brown 	struct regmap *map;
5772238959bSMark Brown 	struct regmap_config config;
5782238959bSMark Brown 	struct regmap_ram_data *data;
5792238959bSMark Brown 	unsigned int rval[BLOCK_TEST_SIZE];
5802238959bSMark Brown 	int i;
5812238959bSMark Brown 
5822238959bSMark Brown 	config = test_regmap_config;
5832238959bSMark Brown 	config.num_reg_defaults = BLOCK_TEST_SIZE;
5842238959bSMark Brown 
5857b7982f1SRichard Fitzgerald 	map = gen_regmap(test, &config, &data);
5862238959bSMark Brown 	KUNIT_ASSERT_FALSE(test, IS_ERR(map));
5872238959bSMark Brown 	if (IS_ERR(map))
5882238959bSMark Brown 		return;
5892238959bSMark Brown 
5902238959bSMark Brown 	/* Read back the expected default data */
5912238959bSMark Brown 	KUNIT_EXPECT_EQ(test, 0, regmap_bulk_read(map, 0, rval,
5922238959bSMark Brown 						  BLOCK_TEST_SIZE));
5932238959bSMark Brown 	KUNIT_EXPECT_MEMEQ(test, data->vals, rval, sizeof(rval));
5942238959bSMark Brown 
5952238959bSMark Brown 	/* The data should have been read from cache if there was one */
5962238959bSMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
59748bccea9SRichard Fitzgerald 		KUNIT_EXPECT_EQ(test, config.cache_type == REGCACHE_NONE, data->read[i]);
5982238959bSMark Brown }
5992238959bSMark Brown 
6002238959bSMark Brown static void reg_defaults_read_dev(struct kunit *test)
6012238959bSMark Brown {
6022238959bSMark Brown 	struct regmap *map;
6032238959bSMark Brown 	struct regmap_config config;
6042238959bSMark Brown 	struct regmap_ram_data *data;
6052238959bSMark Brown 	unsigned int rval[BLOCK_TEST_SIZE];
6062238959bSMark Brown 	int i;
6072238959bSMark Brown 
6082238959bSMark Brown 	config = test_regmap_config;
6092238959bSMark Brown 	config.num_reg_defaults_raw = BLOCK_TEST_SIZE;
6102238959bSMark Brown 
6117b7982f1SRichard Fitzgerald 	map = gen_regmap(test, &config, &data);
6122238959bSMark Brown 	KUNIT_ASSERT_FALSE(test, IS_ERR(map));
6132238959bSMark Brown 	if (IS_ERR(map))
6142238959bSMark Brown 		return;
6152238959bSMark Brown 
6162238959bSMark Brown 	/* We should have read the cache defaults back from the map */
6172238959bSMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++) {
61848bccea9SRichard Fitzgerald 		KUNIT_EXPECT_EQ(test, config.cache_type != REGCACHE_NONE, data->read[i]);
6192238959bSMark Brown 		data->read[i] = false;
6202238959bSMark Brown 	}
6212238959bSMark Brown 
6222238959bSMark Brown 	/* Read back the expected default data */
6232238959bSMark Brown 	KUNIT_EXPECT_EQ(test, 0, regmap_bulk_read(map, 0, rval,
6242238959bSMark Brown 						  BLOCK_TEST_SIZE));
6252238959bSMark Brown 	KUNIT_EXPECT_MEMEQ(test, data->vals, rval, sizeof(rval));
6262238959bSMark Brown 
6272238959bSMark Brown 	/* The data should have been read from cache if there was one */
6282238959bSMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
62948bccea9SRichard Fitzgerald 		KUNIT_EXPECT_EQ(test, config.cache_type == REGCACHE_NONE, data->read[i]);
6302238959bSMark Brown }
6312238959bSMark Brown 
6322238959bSMark Brown static void register_patch(struct kunit *test)
6332238959bSMark Brown {
6342238959bSMark Brown 	struct regmap *map;
6352238959bSMark Brown 	struct regmap_config config;
6362238959bSMark Brown 	struct regmap_ram_data *data;
6372238959bSMark Brown 	struct reg_sequence patch[2];
6382238959bSMark Brown 	unsigned int rval[BLOCK_TEST_SIZE];
6392238959bSMark Brown 	int i;
6402238959bSMark Brown 
6412238959bSMark Brown 	/* We need defaults so readback works */
6422238959bSMark Brown 	config = test_regmap_config;
6432238959bSMark Brown 	config.num_reg_defaults = BLOCK_TEST_SIZE;
6442238959bSMark Brown 
6457b7982f1SRichard Fitzgerald 	map = gen_regmap(test, &config, &data);
6462238959bSMark Brown 	KUNIT_ASSERT_FALSE(test, IS_ERR(map));
6472238959bSMark Brown 	if (IS_ERR(map))
6482238959bSMark Brown 		return;
6492238959bSMark Brown 
6502238959bSMark Brown 	/* Stash the original values */
6512238959bSMark Brown 	KUNIT_EXPECT_EQ(test, 0, regmap_bulk_read(map, 0, rval,
6522238959bSMark Brown 						  BLOCK_TEST_SIZE));
6532238959bSMark Brown 
6542238959bSMark Brown 	/* Patch a couple of values */
6552238959bSMark Brown 	patch[0].reg = 2;
6562238959bSMark Brown 	patch[0].def = rval[2] + 1;
6572238959bSMark Brown 	patch[0].delay_us = 0;
6582238959bSMark Brown 	patch[1].reg = 5;
6592238959bSMark Brown 	patch[1].def = rval[5] + 1;
6602238959bSMark Brown 	patch[1].delay_us = 0;
6612238959bSMark Brown 	KUNIT_EXPECT_EQ(test, 0, regmap_register_patch(map, patch,
6622238959bSMark Brown 						       ARRAY_SIZE(patch)));
6632238959bSMark Brown 
6642238959bSMark Brown 	/* Only the patched registers are written */
6652238959bSMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++) {
6662238959bSMark Brown 		switch (i) {
6672238959bSMark Brown 		case 2:
6682238959bSMark Brown 		case 5:
6692238959bSMark Brown 			KUNIT_EXPECT_TRUE(test, data->written[i]);
6702238959bSMark Brown 			KUNIT_EXPECT_EQ(test, data->vals[i], rval[i] + 1);
6712238959bSMark Brown 			break;
6722238959bSMark Brown 		default:
6732238959bSMark Brown 			KUNIT_EXPECT_FALSE(test, data->written[i]);
6742238959bSMark Brown 			KUNIT_EXPECT_EQ(test, data->vals[i], rval[i]);
6752238959bSMark Brown 			break;
6762238959bSMark Brown 		}
6772238959bSMark Brown 	}
6782238959bSMark Brown }
6792238959bSMark Brown 
6802238959bSMark Brown static void stride(struct kunit *test)
6812238959bSMark Brown {
6822238959bSMark Brown 	struct regmap *map;
6832238959bSMark Brown 	struct regmap_config config;
6842238959bSMark Brown 	struct regmap_ram_data *data;
6852238959bSMark Brown 	unsigned int rval;
6862238959bSMark Brown 	int i;
6872238959bSMark Brown 
6882238959bSMark Brown 	config = test_regmap_config;
6892238959bSMark Brown 	config.reg_stride = 2;
6902238959bSMark Brown 	config.num_reg_defaults = BLOCK_TEST_SIZE / 2;
6912238959bSMark Brown 
6927ba82218SRichard Fitzgerald 	/*
6937ba82218SRichard Fitzgerald 	 * Allow one extra register so that the read/written arrays
6947ba82218SRichard Fitzgerald 	 * are sized big enough to include an entry for the odd
6957ba82218SRichard Fitzgerald 	 * address past the final reg_default register.
6967ba82218SRichard Fitzgerald 	 */
6977ba82218SRichard Fitzgerald 	config.max_register = BLOCK_TEST_SIZE;
6987ba82218SRichard Fitzgerald 
6997b7982f1SRichard Fitzgerald 	map = gen_regmap(test, &config, &data);
7002238959bSMark Brown 	KUNIT_ASSERT_FALSE(test, IS_ERR(map));
7012238959bSMark Brown 	if (IS_ERR(map))
7022238959bSMark Brown 		return;
7032238959bSMark Brown 
7047ba82218SRichard Fitzgerald 	/* Only even addresses can be accessed, try both read and write */
7052238959bSMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++) {
7062238959bSMark Brown 		data->read[i] = false;
7072238959bSMark Brown 		data->written[i] = false;
7082238959bSMark Brown 
7092238959bSMark Brown 		if (i % 2) {
7102238959bSMark Brown 			KUNIT_EXPECT_NE(test, 0, regmap_read(map, i, &rval));
7112238959bSMark Brown 			KUNIT_EXPECT_NE(test, 0, regmap_write(map, i, rval));
7122238959bSMark Brown 			KUNIT_EXPECT_FALSE(test, data->read[i]);
7132238959bSMark Brown 			KUNIT_EXPECT_FALSE(test, data->written[i]);
7142238959bSMark Brown 		} else {
7152238959bSMark Brown 			KUNIT_EXPECT_EQ(test, 0, regmap_read(map, i, &rval));
7162238959bSMark Brown 			KUNIT_EXPECT_EQ(test, data->vals[i], rval);
71748bccea9SRichard Fitzgerald 			KUNIT_EXPECT_EQ(test, config.cache_type == REGCACHE_NONE,
7182238959bSMark Brown 					data->read[i]);
7192238959bSMark Brown 
7202238959bSMark Brown 			KUNIT_EXPECT_EQ(test, 0, regmap_write(map, i, rval));
7212238959bSMark Brown 			KUNIT_EXPECT_TRUE(test, data->written[i]);
7222238959bSMark Brown 		}
7232238959bSMark Brown 	}
7242238959bSMark Brown }
7252238959bSMark Brown 
7262238959bSMark Brown static struct regmap_range_cfg test_range = {
7272238959bSMark Brown 	.selector_reg = 1,
7282238959bSMark Brown 	.selector_mask = 0xff,
7292238959bSMark Brown 
7302238959bSMark Brown 	.window_start = 4,
7312238959bSMark Brown 	.window_len = 10,
7322238959bSMark Brown 
7332238959bSMark Brown 	.range_min = 20,
7342238959bSMark Brown 	.range_max = 40,
7352238959bSMark Brown };
7362238959bSMark Brown 
7376a2e332cSMark Brown static bool test_range_window_volatile(struct device *dev, unsigned int reg)
7382238959bSMark Brown {
7392238959bSMark Brown 	if (reg >= test_range.window_start &&
740fabe32ccSMark Brown 	    reg <= test_range.window_start + test_range.window_len)
7412238959bSMark Brown 		return true;
7422238959bSMark Brown 
7436a2e332cSMark Brown 	return false;
7446a2e332cSMark Brown }
7456a2e332cSMark Brown 
7466a2e332cSMark Brown static bool test_range_all_volatile(struct device *dev, unsigned int reg)
7476a2e332cSMark Brown {
7486a2e332cSMark Brown 	if (test_range_window_volatile(dev, reg))
7496a2e332cSMark Brown 		return true;
7506a2e332cSMark Brown 
7512238959bSMark Brown 	if (reg >= test_range.range_min && reg <= test_range.range_max)
7522238959bSMark Brown 		return true;
7532238959bSMark Brown 
7542238959bSMark Brown 	return false;
7552238959bSMark Brown }
7562238959bSMark Brown 
7572238959bSMark Brown static void basic_ranges(struct kunit *test)
7582238959bSMark Brown {
7592238959bSMark Brown 	struct regmap *map;
7602238959bSMark Brown 	struct regmap_config config;
7612238959bSMark Brown 	struct regmap_ram_data *data;
7622238959bSMark Brown 	unsigned int val;
7632238959bSMark Brown 	int i;
7642238959bSMark Brown 
7652238959bSMark Brown 	config = test_regmap_config;
7666a2e332cSMark Brown 	config.volatile_reg = test_range_all_volatile;
7672238959bSMark Brown 	config.ranges = &test_range;
7682238959bSMark Brown 	config.num_ranges = 1;
7692238959bSMark Brown 	config.max_register = test_range.range_max;
7702238959bSMark Brown 
7717b7982f1SRichard Fitzgerald 	map = gen_regmap(test, &config, &data);
7722238959bSMark Brown 	KUNIT_ASSERT_FALSE(test, IS_ERR(map));
7732238959bSMark Brown 	if (IS_ERR(map))
7742238959bSMark Brown 		return;
7752238959bSMark Brown 
7762238959bSMark Brown 	for (i = test_range.range_min; i < test_range.range_max; i++) {
7772238959bSMark Brown 		data->read[i] = false;
7782238959bSMark Brown 		data->written[i] = false;
7792238959bSMark Brown 	}
7802238959bSMark Brown 
7812238959bSMark Brown 	/* Reset the page to a non-zero value to trigger a change */
7822238959bSMark Brown 	KUNIT_EXPECT_EQ(test, 0, regmap_write(map, test_range.selector_reg,
7832238959bSMark Brown 					      test_range.range_max));
7842238959bSMark Brown 
7852238959bSMark Brown 	/* Check we set the page and use the window for writes */
7862238959bSMark Brown 	data->written[test_range.selector_reg] = false;
7872238959bSMark Brown 	data->written[test_range.window_start] = false;
7882238959bSMark Brown 	KUNIT_EXPECT_EQ(test, 0, regmap_write(map, test_range.range_min, 0));
7892238959bSMark Brown 	KUNIT_EXPECT_TRUE(test, data->written[test_range.selector_reg]);
7902238959bSMark Brown 	KUNIT_EXPECT_TRUE(test, data->written[test_range.window_start]);
7912238959bSMark Brown 
7922238959bSMark Brown 	data->written[test_range.selector_reg] = false;
7932238959bSMark Brown 	data->written[test_range.window_start] = false;
7942238959bSMark Brown 	KUNIT_EXPECT_EQ(test, 0, regmap_write(map,
7952238959bSMark Brown 					      test_range.range_min +
7962238959bSMark Brown 					      test_range.window_len,
7972238959bSMark Brown 					      0));
7982238959bSMark Brown 	KUNIT_EXPECT_TRUE(test, data->written[test_range.selector_reg]);
7992238959bSMark Brown 	KUNIT_EXPECT_TRUE(test, data->written[test_range.window_start]);
8002238959bSMark Brown 
8012238959bSMark Brown 	/* Same for reads */
8022238959bSMark Brown 	data->written[test_range.selector_reg] = false;
8032238959bSMark Brown 	data->read[test_range.window_start] = false;
8042238959bSMark Brown 	KUNIT_EXPECT_EQ(test, 0, regmap_read(map, test_range.range_min, &val));
8052238959bSMark Brown 	KUNIT_EXPECT_TRUE(test, data->written[test_range.selector_reg]);
8062238959bSMark Brown 	KUNIT_EXPECT_TRUE(test, data->read[test_range.window_start]);
8072238959bSMark Brown 
8082238959bSMark Brown 	data->written[test_range.selector_reg] = false;
8092238959bSMark Brown 	data->read[test_range.window_start] = false;
8102238959bSMark Brown 	KUNIT_EXPECT_EQ(test, 0, regmap_read(map,
8112238959bSMark Brown 					     test_range.range_min +
8122238959bSMark Brown 					     test_range.window_len,
8132238959bSMark Brown 					     &val));
8142238959bSMark Brown 	KUNIT_EXPECT_TRUE(test, data->written[test_range.selector_reg]);
8152238959bSMark Brown 	KUNIT_EXPECT_TRUE(test, data->read[test_range.window_start]);
8162238959bSMark Brown 
8172238959bSMark Brown 	/* No physical access triggered in the virtual range */
8182238959bSMark Brown 	for (i = test_range.range_min; i < test_range.range_max; i++) {
8192238959bSMark Brown 		KUNIT_EXPECT_FALSE(test, data->read[i]);
8202238959bSMark Brown 		KUNIT_EXPECT_FALSE(test, data->written[i]);
8212238959bSMark Brown 	}
8222238959bSMark Brown }
8232238959bSMark Brown 
8242238959bSMark Brown /* Try to stress dynamic creation of cache data structures */
8252238959bSMark Brown static void stress_insert(struct kunit *test)
8262238959bSMark Brown {
8272238959bSMark Brown 	struct regmap *map;
8282238959bSMark Brown 	struct regmap_config config;
8292238959bSMark Brown 	struct regmap_ram_data *data;
8302238959bSMark Brown 	unsigned int rval, *vals;
8312238959bSMark Brown 	size_t buf_sz;
8322238959bSMark Brown 	int i;
8332238959bSMark Brown 
8342238959bSMark Brown 	config = test_regmap_config;
8352238959bSMark Brown 	config.max_register = 300;
8362238959bSMark Brown 
8377b7982f1SRichard Fitzgerald 	map = gen_regmap(test, &config, &data);
8382238959bSMark Brown 	KUNIT_ASSERT_FALSE(test, IS_ERR(map));
8392238959bSMark Brown 	if (IS_ERR(map))
8402238959bSMark Brown 		return;
8412238959bSMark Brown 
842f82ecf76SAndy Shevchenko 	buf_sz = array_size(sizeof(*vals), config.max_register);
843f82ecf76SAndy Shevchenko 	vals = kunit_kmalloc(test, buf_sz, GFP_KERNEL);
8442238959bSMark Brown 	KUNIT_ASSERT_FALSE(test, vals == NULL);
8452238959bSMark Brown 
8462238959bSMark Brown 	get_random_bytes(vals, buf_sz);
8472238959bSMark Brown 
8482238959bSMark Brown 	/* Write data into the map/cache in ever decreasing strides */
8492238959bSMark Brown 	for (i = 0; i < config.max_register; i += 100)
8502238959bSMark Brown 		KUNIT_EXPECT_EQ(test, 0, regmap_write(map, i, vals[i]));
8512238959bSMark Brown 	for (i = 0; i < config.max_register; i += 50)
8522238959bSMark Brown 		KUNIT_EXPECT_EQ(test, 0, regmap_write(map, i, vals[i]));
8532238959bSMark Brown 	for (i = 0; i < config.max_register; i += 25)
8542238959bSMark Brown 		KUNIT_EXPECT_EQ(test, 0, regmap_write(map, i, vals[i]));
8552238959bSMark Brown 	for (i = 0; i < config.max_register; i += 10)
8562238959bSMark Brown 		KUNIT_EXPECT_EQ(test, 0, regmap_write(map, i, vals[i]));
8572238959bSMark Brown 	for (i = 0; i < config.max_register; i += 5)
8582238959bSMark Brown 		KUNIT_EXPECT_EQ(test, 0, regmap_write(map, i, vals[i]));
8592238959bSMark Brown 	for (i = 0; i < config.max_register; i += 3)
8602238959bSMark Brown 		KUNIT_EXPECT_EQ(test, 0, regmap_write(map, i, vals[i]));
8612238959bSMark Brown 	for (i = 0; i < config.max_register; i += 2)
8622238959bSMark Brown 		KUNIT_EXPECT_EQ(test, 0, regmap_write(map, i, vals[i]));
8632238959bSMark Brown 	for (i = 0; i < config.max_register; i++)
8642238959bSMark Brown 		KUNIT_EXPECT_EQ(test, 0, regmap_write(map, i, vals[i]));
8652238959bSMark Brown 
8662238959bSMark Brown 	/* Do reads from the cache (if there is one) match? */
8672238959bSMark Brown 	for (i = 0; i < config.max_register; i ++) {
8682238959bSMark Brown 		KUNIT_EXPECT_EQ(test, 0, regmap_read(map, i, &rval));
8692238959bSMark Brown 		KUNIT_EXPECT_EQ(test, rval, vals[i]);
87048bccea9SRichard Fitzgerald 		KUNIT_EXPECT_EQ(test, config.cache_type == REGCACHE_NONE, data->read[i]);
8712238959bSMark Brown 	}
8722238959bSMark Brown }
8732238959bSMark Brown 
8742238959bSMark Brown static void cache_bypass(struct kunit *test)
8752238959bSMark Brown {
876ac4394bfSRichard Fitzgerald 	const struct regmap_test_param *param = test->param_value;
8772238959bSMark Brown 	struct regmap *map;
8782238959bSMark Brown 	struct regmap_config config;
8792238959bSMark Brown 	struct regmap_ram_data *data;
8802238959bSMark Brown 	unsigned int val, rval;
8812238959bSMark Brown 
8822238959bSMark Brown 	config = test_regmap_config;
8832238959bSMark Brown 
8847b7982f1SRichard Fitzgerald 	map = gen_regmap(test, &config, &data);
8852238959bSMark Brown 	KUNIT_ASSERT_FALSE(test, IS_ERR(map));
8862238959bSMark Brown 	if (IS_ERR(map))
8872238959bSMark Brown 		return;
8882238959bSMark Brown 
8892238959bSMark Brown 	get_random_bytes(&val, sizeof(val));
8902238959bSMark Brown 
8912238959bSMark Brown 	/* Ensure the cache has a value in it */
892ac4394bfSRichard Fitzgerald 	KUNIT_EXPECT_EQ(test, 0, regmap_write(map, param->from_reg, val));
8932238959bSMark Brown 
8942238959bSMark Brown 	/* Bypass then write a different value */
8952238959bSMark Brown 	regcache_cache_bypass(map, true);
896ac4394bfSRichard Fitzgerald 	KUNIT_EXPECT_EQ(test, 0, regmap_write(map, param->from_reg, val + 1));
8972238959bSMark Brown 
8982238959bSMark Brown 	/* Read the bypassed value */
899ac4394bfSRichard Fitzgerald 	KUNIT_EXPECT_EQ(test, 0, regmap_read(map, param->from_reg, &rval));
9002238959bSMark Brown 	KUNIT_EXPECT_EQ(test, val + 1, rval);
901ac4394bfSRichard Fitzgerald 	KUNIT_EXPECT_EQ(test, data->vals[param->from_reg], rval);
9022238959bSMark Brown 
9032238959bSMark Brown 	/* Disable bypass, the cache should still return the original value */
9042238959bSMark Brown 	regcache_cache_bypass(map, false);
905ac4394bfSRichard Fitzgerald 	KUNIT_EXPECT_EQ(test, 0, regmap_read(map, param->from_reg, &rval));
9062238959bSMark Brown 	KUNIT_EXPECT_EQ(test, val, rval);
9072238959bSMark Brown }
9082238959bSMark Brown 
9097903d15fSRichard Fitzgerald static void cache_sync_marked_dirty(struct kunit *test)
9102238959bSMark Brown {
911ac4394bfSRichard Fitzgerald 	const struct regmap_test_param *param = test->param_value;
9122238959bSMark Brown 	struct regmap *map;
9132238959bSMark Brown 	struct regmap_config config;
9142238959bSMark Brown 	struct regmap_ram_data *data;
9152238959bSMark Brown 	unsigned int val[BLOCK_TEST_SIZE];
9162238959bSMark Brown 	int i;
9172238959bSMark Brown 
9182238959bSMark Brown 	config = test_regmap_config;
9192238959bSMark Brown 
9207b7982f1SRichard Fitzgerald 	map = gen_regmap(test, &config, &data);
9212238959bSMark Brown 	KUNIT_ASSERT_FALSE(test, IS_ERR(map));
9222238959bSMark Brown 	if (IS_ERR(map))
9232238959bSMark Brown 		return;
9242238959bSMark Brown 
9252238959bSMark Brown 	get_random_bytes(&val, sizeof(val));
9262238959bSMark Brown 
9272238959bSMark Brown 	/* Put some data into the cache */
928ac4394bfSRichard Fitzgerald 	KUNIT_EXPECT_EQ(test, 0, regmap_bulk_write(map, param->from_reg, val,
9292238959bSMark Brown 						   BLOCK_TEST_SIZE));
9302238959bSMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
931ac4394bfSRichard Fitzgerald 		data->written[param->from_reg + i] = false;
9322238959bSMark Brown 
9332238959bSMark Brown 	/* Trash the data on the device itself then resync */
9342238959bSMark Brown 	regcache_mark_dirty(map);
9352238959bSMark Brown 	memset(data->vals, 0, sizeof(val));
9362238959bSMark Brown 	KUNIT_EXPECT_EQ(test, 0, regcache_sync(map));
9372238959bSMark Brown 
9382238959bSMark Brown 	/* Did we just write the correct data out? */
939ac4394bfSRichard Fitzgerald 	KUNIT_EXPECT_MEMEQ(test, &data->vals[param->from_reg], val, sizeof(val));
9402238959bSMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
941ac4394bfSRichard Fitzgerald 		KUNIT_EXPECT_EQ(test, true, data->written[param->from_reg + i]);
9422238959bSMark Brown }
9432238959bSMark Brown 
9447903d15fSRichard Fitzgerald static void cache_sync_after_cache_only(struct kunit *test)
9457903d15fSRichard Fitzgerald {
9467903d15fSRichard Fitzgerald 	const struct regmap_test_param *param = test->param_value;
9477903d15fSRichard Fitzgerald 	struct regmap *map;
9487903d15fSRichard Fitzgerald 	struct regmap_config config;
9497903d15fSRichard Fitzgerald 	struct regmap_ram_data *data;
9507903d15fSRichard Fitzgerald 	unsigned int val[BLOCK_TEST_SIZE];
9517903d15fSRichard Fitzgerald 	unsigned int val_mask;
9527903d15fSRichard Fitzgerald 	int i;
9537903d15fSRichard Fitzgerald 
9547903d15fSRichard Fitzgerald 	config = test_regmap_config;
9557903d15fSRichard Fitzgerald 
9567903d15fSRichard Fitzgerald 	map = gen_regmap(test, &config, &data);
9577903d15fSRichard Fitzgerald 	KUNIT_ASSERT_FALSE(test, IS_ERR(map));
9587903d15fSRichard Fitzgerald 	if (IS_ERR(map))
9597903d15fSRichard Fitzgerald 		return;
9607903d15fSRichard Fitzgerald 
9617903d15fSRichard Fitzgerald 	val_mask = GENMASK(config.val_bits - 1, 0);
9627903d15fSRichard Fitzgerald 	get_random_bytes(&val, sizeof(val));
9637903d15fSRichard Fitzgerald 
9647903d15fSRichard Fitzgerald 	/* Put some data into the cache */
9657903d15fSRichard Fitzgerald 	KUNIT_EXPECT_EQ(test, 0, regmap_bulk_write(map, param->from_reg, val,
9667903d15fSRichard Fitzgerald 						   BLOCK_TEST_SIZE));
9677903d15fSRichard Fitzgerald 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
9687903d15fSRichard Fitzgerald 		data->written[param->from_reg + i] = false;
9697903d15fSRichard Fitzgerald 
9707903d15fSRichard Fitzgerald 	/* Set cache-only and change the values */
9717903d15fSRichard Fitzgerald 	regcache_cache_only(map, true);
9727903d15fSRichard Fitzgerald 	for (i = 0; i < ARRAY_SIZE(val); ++i)
9737903d15fSRichard Fitzgerald 		val[i] = ~val[i] & val_mask;
9747903d15fSRichard Fitzgerald 
9757903d15fSRichard Fitzgerald 	KUNIT_EXPECT_EQ(test, 0, regmap_bulk_write(map, param->from_reg, val,
9767903d15fSRichard Fitzgerald 						   BLOCK_TEST_SIZE));
9777903d15fSRichard Fitzgerald 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
9787903d15fSRichard Fitzgerald 		KUNIT_EXPECT_FALSE(test, data->written[param->from_reg + i]);
9797903d15fSRichard Fitzgerald 
9807903d15fSRichard Fitzgerald 	KUNIT_EXPECT_MEMNEQ(test, &data->vals[param->from_reg], val, sizeof(val));
9817903d15fSRichard Fitzgerald 
9827903d15fSRichard Fitzgerald 	/* Exit cache-only and sync the cache without marking hardware registers dirty */
9837903d15fSRichard Fitzgerald 	regcache_cache_only(map, false);
9847903d15fSRichard Fitzgerald 
9857903d15fSRichard Fitzgerald 	KUNIT_EXPECT_EQ(test, 0, regcache_sync(map));
9867903d15fSRichard Fitzgerald 
9877903d15fSRichard Fitzgerald 	/* Did we just write the correct data out? */
9887903d15fSRichard Fitzgerald 	KUNIT_EXPECT_MEMEQ(test, &data->vals[param->from_reg], val, sizeof(val));
9897903d15fSRichard Fitzgerald 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
9907903d15fSRichard Fitzgerald 		KUNIT_EXPECT_TRUE(test, data->written[param->from_reg + i]);
9917903d15fSRichard Fitzgerald }
9927903d15fSRichard Fitzgerald 
9937903d15fSRichard Fitzgerald static void cache_sync_defaults_marked_dirty(struct kunit *test)
9942238959bSMark Brown {
995ac4394bfSRichard Fitzgerald 	const struct regmap_test_param *param = test->param_value;
9962238959bSMark Brown 	struct regmap *map;
9972238959bSMark Brown 	struct regmap_config config;
9982238959bSMark Brown 	struct regmap_ram_data *data;
9992238959bSMark Brown 	unsigned int val;
10002238959bSMark Brown 	int i;
10012238959bSMark Brown 
10022238959bSMark Brown 	config = test_regmap_config;
10032238959bSMark Brown 	config.num_reg_defaults = BLOCK_TEST_SIZE;
10042238959bSMark Brown 
10057b7982f1SRichard Fitzgerald 	map = gen_regmap(test, &config, &data);
10062238959bSMark Brown 	KUNIT_ASSERT_FALSE(test, IS_ERR(map));
10072238959bSMark Brown 	if (IS_ERR(map))
10082238959bSMark Brown 		return;
10092238959bSMark Brown 
10102238959bSMark Brown 	get_random_bytes(&val, sizeof(val));
10112238959bSMark Brown 
10122238959bSMark Brown 	/* Change the value of one register */
1013ac4394bfSRichard Fitzgerald 	KUNIT_EXPECT_EQ(test, 0, regmap_write(map, param->from_reg + 2, val));
10142238959bSMark Brown 
10152238959bSMark Brown 	/* Resync */
10162238959bSMark Brown 	regcache_mark_dirty(map);
10172238959bSMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
1018ac4394bfSRichard Fitzgerald 		data->written[param->from_reg + i] = false;
10192238959bSMark Brown 	KUNIT_EXPECT_EQ(test, 0, regcache_sync(map));
10202238959bSMark Brown 
10212238959bSMark Brown 	/* Did we just sync the one register we touched? */
10222238959bSMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
1023ac4394bfSRichard Fitzgerald 		KUNIT_EXPECT_EQ(test, i == 2, data->written[param->from_reg + i]);
10242238959bSMark Brown 
10257903d15fSRichard Fitzgerald 	/* Rewrite registers back to their defaults */
10267903d15fSRichard Fitzgerald 	for (i = 0; i < config.num_reg_defaults; ++i)
10277903d15fSRichard Fitzgerald 		KUNIT_EXPECT_EQ(test, 0, regmap_write(map, config.reg_defaults[i].reg,
10287903d15fSRichard Fitzgerald 						      config.reg_defaults[i].def));
10297903d15fSRichard Fitzgerald 
10307903d15fSRichard Fitzgerald 	/*
10317903d15fSRichard Fitzgerald 	 * Resync after regcache_mark_dirty() should not write out registers
10327903d15fSRichard Fitzgerald 	 * that are at default value
10337903d15fSRichard Fitzgerald 	 */
10347903d15fSRichard Fitzgerald 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
10357903d15fSRichard Fitzgerald 		data->written[param->from_reg + i] = false;
10367903d15fSRichard Fitzgerald 	regcache_mark_dirty(map);
10377903d15fSRichard Fitzgerald 	KUNIT_EXPECT_EQ(test, 0, regcache_sync(map));
10387903d15fSRichard Fitzgerald 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
10397903d15fSRichard Fitzgerald 		KUNIT_EXPECT_FALSE(test, data->written[param->from_reg + i]);
10407903d15fSRichard Fitzgerald }
10417903d15fSRichard Fitzgerald 
10427903d15fSRichard Fitzgerald static void cache_sync_default_after_cache_only(struct kunit *test)
10437903d15fSRichard Fitzgerald {
10447903d15fSRichard Fitzgerald 	const struct regmap_test_param *param = test->param_value;
10457903d15fSRichard Fitzgerald 	struct regmap *map;
10467903d15fSRichard Fitzgerald 	struct regmap_config config;
10477903d15fSRichard Fitzgerald 	struct regmap_ram_data *data;
10487903d15fSRichard Fitzgerald 	unsigned int orig_val;
10497903d15fSRichard Fitzgerald 	int i;
10507903d15fSRichard Fitzgerald 
10517903d15fSRichard Fitzgerald 	config = test_regmap_config;
10527903d15fSRichard Fitzgerald 	config.num_reg_defaults = BLOCK_TEST_SIZE;
10537903d15fSRichard Fitzgerald 
10547903d15fSRichard Fitzgerald 	map = gen_regmap(test, &config, &data);
10557903d15fSRichard Fitzgerald 	KUNIT_ASSERT_FALSE(test, IS_ERR(map));
10567903d15fSRichard Fitzgerald 	if (IS_ERR(map))
10577903d15fSRichard Fitzgerald 		return;
10587903d15fSRichard Fitzgerald 
10597903d15fSRichard Fitzgerald 	KUNIT_EXPECT_EQ(test, 0, regmap_read(map, param->from_reg + 2, &orig_val));
10607903d15fSRichard Fitzgerald 
10617903d15fSRichard Fitzgerald 	/* Enter cache-only and change the value of one register */
10627903d15fSRichard Fitzgerald 	regcache_cache_only(map, true);
10637903d15fSRichard Fitzgerald 	KUNIT_EXPECT_EQ(test, 0, regmap_write(map, param->from_reg + 2, orig_val + 1));
10647903d15fSRichard Fitzgerald 
10657903d15fSRichard Fitzgerald 	/* Exit cache-only and resync, should write out the changed register */
10667903d15fSRichard Fitzgerald 	regcache_cache_only(map, false);
10677903d15fSRichard Fitzgerald 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
10687903d15fSRichard Fitzgerald 		data->written[param->from_reg + i] = false;
10697903d15fSRichard Fitzgerald 	KUNIT_EXPECT_EQ(test, 0, regcache_sync(map));
10707903d15fSRichard Fitzgerald 
10717903d15fSRichard Fitzgerald 	/* Was the register written out? */
10727903d15fSRichard Fitzgerald 	KUNIT_EXPECT_TRUE(test, data->written[param->from_reg + 2]);
10737903d15fSRichard Fitzgerald 	KUNIT_EXPECT_EQ(test, data->vals[param->from_reg + 2], orig_val + 1);
10747903d15fSRichard Fitzgerald 
10757903d15fSRichard Fitzgerald 	/* Enter cache-only and write register back to its default value */
10767903d15fSRichard Fitzgerald 	regcache_cache_only(map, true);
10777903d15fSRichard Fitzgerald 	KUNIT_EXPECT_EQ(test, 0, regmap_write(map, param->from_reg + 2, orig_val));
10787903d15fSRichard Fitzgerald 
10797903d15fSRichard Fitzgerald 	/* Resync should write out the new value */
10807903d15fSRichard Fitzgerald 	regcache_cache_only(map, false);
10817903d15fSRichard Fitzgerald 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
10827903d15fSRichard Fitzgerald 		data->written[param->from_reg + i] = false;
10837903d15fSRichard Fitzgerald 
10847903d15fSRichard Fitzgerald 	KUNIT_EXPECT_EQ(test, 0, regcache_sync(map));
10857903d15fSRichard Fitzgerald 	KUNIT_EXPECT_TRUE(test, data->written[param->from_reg + 2]);
10867903d15fSRichard Fitzgerald 	KUNIT_EXPECT_EQ(test, data->vals[param->from_reg + 2], orig_val);
10872238959bSMark Brown }
10882238959bSMark Brown 
1089357a1ebdSMark Brown static void cache_sync_readonly(struct kunit *test)
1090357a1ebdSMark Brown {
1091ac4394bfSRichard Fitzgerald 	const struct regmap_test_param *param = test->param_value;
1092357a1ebdSMark Brown 	struct regmap *map;
1093357a1ebdSMark Brown 	struct regmap_config config;
1094357a1ebdSMark Brown 	struct regmap_ram_data *data;
1095357a1ebdSMark Brown 	unsigned int val;
1096357a1ebdSMark Brown 	int i;
1097357a1ebdSMark Brown 
1098357a1ebdSMark Brown 	config = test_regmap_config;
1099357a1ebdSMark Brown 	config.writeable_reg = reg_5_false;
1100357a1ebdSMark Brown 
11017b7982f1SRichard Fitzgerald 	map = gen_regmap(test, &config, &data);
1102357a1ebdSMark Brown 	KUNIT_ASSERT_FALSE(test, IS_ERR(map));
1103357a1ebdSMark Brown 	if (IS_ERR(map))
1104357a1ebdSMark Brown 		return;
1105357a1ebdSMark Brown 
1106357a1ebdSMark Brown 	/* Read all registers to fill the cache */
1107357a1ebdSMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
1108ac4394bfSRichard Fitzgerald 		KUNIT_EXPECT_EQ(test, 0, regmap_read(map, param->from_reg + i, &val));
1109357a1ebdSMark Brown 
1110357a1ebdSMark Brown 	/* Change the value of all registers, readonly should fail */
1111357a1ebdSMark Brown 	get_random_bytes(&val, sizeof(val));
1112357a1ebdSMark Brown 	regcache_cache_only(map, true);
1113357a1ebdSMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
1114ac4394bfSRichard Fitzgerald 		KUNIT_EXPECT_EQ(test, i != 5, regmap_write(map, param->from_reg + i, val) == 0);
1115357a1ebdSMark Brown 	regcache_cache_only(map, false);
1116357a1ebdSMark Brown 
1117357a1ebdSMark Brown 	/* Resync */
1118357a1ebdSMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
1119ac4394bfSRichard Fitzgerald 		data->written[param->from_reg + i] = false;
1120357a1ebdSMark Brown 	KUNIT_EXPECT_EQ(test, 0, regcache_sync(map));
1121357a1ebdSMark Brown 
1122357a1ebdSMark Brown 	/* Did that match what we see on the device? */
1123357a1ebdSMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
1124ac4394bfSRichard Fitzgerald 		KUNIT_EXPECT_EQ(test, i != 5, data->written[param->from_reg + i]);
1125357a1ebdSMark Brown }
1126357a1ebdSMark Brown 
11272238959bSMark Brown static void cache_sync_patch(struct kunit *test)
11282238959bSMark Brown {
1129ac4394bfSRichard Fitzgerald 	const struct regmap_test_param *param = test->param_value;
11302238959bSMark Brown 	struct regmap *map;
11312238959bSMark Brown 	struct regmap_config config;
11322238959bSMark Brown 	struct regmap_ram_data *data;
11332238959bSMark Brown 	struct reg_sequence patch[2];
11342238959bSMark Brown 	unsigned int rval[BLOCK_TEST_SIZE], val;
11352238959bSMark Brown 	int i;
11362238959bSMark Brown 
11372238959bSMark Brown 	/* We need defaults so readback works */
11382238959bSMark Brown 	config = test_regmap_config;
11392238959bSMark Brown 	config.num_reg_defaults = BLOCK_TEST_SIZE;
11402238959bSMark Brown 
11417b7982f1SRichard Fitzgerald 	map = gen_regmap(test, &config, &data);
11422238959bSMark Brown 	KUNIT_ASSERT_FALSE(test, IS_ERR(map));
11432238959bSMark Brown 	if (IS_ERR(map))
11442238959bSMark Brown 		return;
11452238959bSMark Brown 
11462238959bSMark Brown 	/* Stash the original values */
1147ac4394bfSRichard Fitzgerald 	KUNIT_EXPECT_EQ(test, 0, regmap_bulk_read(map, param->from_reg, rval,
11482238959bSMark Brown 						  BLOCK_TEST_SIZE));
11492238959bSMark Brown 
11502238959bSMark Brown 	/* Patch a couple of values */
1151ac4394bfSRichard Fitzgerald 	patch[0].reg = param->from_reg + 2;
11522238959bSMark Brown 	patch[0].def = rval[2] + 1;
11532238959bSMark Brown 	patch[0].delay_us = 0;
1154ac4394bfSRichard Fitzgerald 	patch[1].reg = param->from_reg + 5;
11552238959bSMark Brown 	patch[1].def = rval[5] + 1;
11562238959bSMark Brown 	patch[1].delay_us = 0;
11572238959bSMark Brown 	KUNIT_EXPECT_EQ(test, 0, regmap_register_patch(map, patch,
11582238959bSMark Brown 						       ARRAY_SIZE(patch)));
11592238959bSMark Brown 
11602238959bSMark Brown 	/* Sync the cache */
11612238959bSMark Brown 	regcache_mark_dirty(map);
11622238959bSMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
1163ac4394bfSRichard Fitzgerald 		data->written[param->from_reg + i] = false;
11642238959bSMark Brown 	KUNIT_EXPECT_EQ(test, 0, regcache_sync(map));
11652238959bSMark Brown 
11662238959bSMark Brown 	/* The patch should be on the device but not in the cache */
11672238959bSMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++) {
1168ac4394bfSRichard Fitzgerald 		KUNIT_EXPECT_EQ(test, 0, regmap_read(map, param->from_reg + i, &val));
11692238959bSMark Brown 		KUNIT_EXPECT_EQ(test, val, rval[i]);
11702238959bSMark Brown 
11712238959bSMark Brown 		switch (i) {
11722238959bSMark Brown 		case 2:
11732238959bSMark Brown 		case 5:
1174ac4394bfSRichard Fitzgerald 			KUNIT_EXPECT_EQ(test, true, data->written[param->from_reg + i]);
1175ac4394bfSRichard Fitzgerald 			KUNIT_EXPECT_EQ(test, data->vals[param->from_reg + i], rval[i] + 1);
11762238959bSMark Brown 			break;
11772238959bSMark Brown 		default:
1178ac4394bfSRichard Fitzgerald 			KUNIT_EXPECT_EQ(test, false, data->written[param->from_reg + i]);
1179ac4394bfSRichard Fitzgerald 			KUNIT_EXPECT_EQ(test, data->vals[param->from_reg + i], rval[i]);
11802238959bSMark Brown 			break;
11812238959bSMark Brown 		}
11822238959bSMark Brown 	}
11832238959bSMark Brown }
11842238959bSMark Brown 
11852238959bSMark Brown static void cache_drop(struct kunit *test)
11862238959bSMark Brown {
118771091574SRichard Fitzgerald 	const struct regmap_test_param *param = test->param_value;
11882238959bSMark Brown 	struct regmap *map;
11892238959bSMark Brown 	struct regmap_config config;
11902238959bSMark Brown 	struct regmap_ram_data *data;
11912238959bSMark Brown 	unsigned int rval[BLOCK_TEST_SIZE];
11922238959bSMark Brown 	int i;
11932238959bSMark Brown 
11942238959bSMark Brown 	config = test_regmap_config;
11952238959bSMark Brown 	config.num_reg_defaults = BLOCK_TEST_SIZE;
11962238959bSMark Brown 
11977b7982f1SRichard Fitzgerald 	map = gen_regmap(test, &config, &data);
11982238959bSMark Brown 	KUNIT_ASSERT_FALSE(test, IS_ERR(map));
11992238959bSMark Brown 	if (IS_ERR(map))
12002238959bSMark Brown 		return;
12012238959bSMark Brown 
12022238959bSMark Brown 	/* Ensure the data is read from the cache */
12032238959bSMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
120471091574SRichard Fitzgerald 		data->read[param->from_reg + i] = false;
120571091574SRichard Fitzgerald 	KUNIT_EXPECT_EQ(test, 0, regmap_bulk_read(map, param->from_reg, rval,
12062238959bSMark Brown 						  BLOCK_TEST_SIZE));
12072238959bSMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++) {
120871091574SRichard Fitzgerald 		KUNIT_EXPECT_FALSE(test, data->read[param->from_reg + i]);
120971091574SRichard Fitzgerald 		data->read[param->from_reg + i] = false;
12102238959bSMark Brown 	}
121171091574SRichard Fitzgerald 	KUNIT_EXPECT_MEMEQ(test, &data->vals[param->from_reg], rval, sizeof(rval));
12122238959bSMark Brown 
12132238959bSMark Brown 	/* Drop some registers */
121471091574SRichard Fitzgerald 	KUNIT_EXPECT_EQ(test, 0, regcache_drop_region(map, param->from_reg + 3,
121571091574SRichard Fitzgerald 						      param->from_reg + 5));
12162238959bSMark Brown 
12172238959bSMark Brown 	/* Reread and check only the dropped registers hit the device. */
121871091574SRichard Fitzgerald 	KUNIT_EXPECT_EQ(test, 0, regmap_bulk_read(map, param->from_reg, rval,
12192238959bSMark Brown 						  BLOCK_TEST_SIZE));
12202238959bSMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
122171091574SRichard Fitzgerald 		KUNIT_EXPECT_EQ(test, data->read[param->from_reg + i], i >= 3 && i <= 5);
122271091574SRichard Fitzgerald 	KUNIT_EXPECT_MEMEQ(test, &data->vals[param->from_reg], rval, sizeof(rval));
12232238959bSMark Brown }
12242238959bSMark Brown 
1225468d277eSRichard Fitzgerald static void cache_drop_with_non_contiguous_ranges(struct kunit *test)
1226468d277eSRichard Fitzgerald {
1227468d277eSRichard Fitzgerald 	const struct regmap_test_param *param = test->param_value;
1228468d277eSRichard Fitzgerald 	struct regmap *map;
1229468d277eSRichard Fitzgerald 	struct regmap_config config;
1230468d277eSRichard Fitzgerald 	struct regmap_ram_data *data;
1231468d277eSRichard Fitzgerald 	unsigned int val[4][BLOCK_TEST_SIZE];
1232468d277eSRichard Fitzgerald 	unsigned int reg;
1233468d277eSRichard Fitzgerald 	const int num_ranges = ARRAY_SIZE(val) * 2;
1234468d277eSRichard Fitzgerald 	int rangeidx, i;
1235468d277eSRichard Fitzgerald 
1236468d277eSRichard Fitzgerald 	static_assert(ARRAY_SIZE(val) == 4);
1237468d277eSRichard Fitzgerald 
1238468d277eSRichard Fitzgerald 	config = test_regmap_config;
1239468d277eSRichard Fitzgerald 	config.max_register = param->from_reg + (num_ranges * BLOCK_TEST_SIZE);
1240468d277eSRichard Fitzgerald 
1241468d277eSRichard Fitzgerald 	map = gen_regmap(test, &config, &data);
1242468d277eSRichard Fitzgerald 	KUNIT_ASSERT_FALSE(test, IS_ERR(map));
1243468d277eSRichard Fitzgerald 	if (IS_ERR(map))
1244468d277eSRichard Fitzgerald 		return;
1245468d277eSRichard Fitzgerald 
1246468d277eSRichard Fitzgerald 	for (i = 0; i < config.max_register + 1; i++)
1247468d277eSRichard Fitzgerald 		data->written[i] = false;
1248468d277eSRichard Fitzgerald 
1249468d277eSRichard Fitzgerald 	/* Create non-contiguous cache blocks by writing every other range */
1250468d277eSRichard Fitzgerald 	get_random_bytes(&val, sizeof(val));
1251468d277eSRichard Fitzgerald 	for (rangeidx = 0; rangeidx < num_ranges; rangeidx += 2) {
1252468d277eSRichard Fitzgerald 		reg = param->from_reg + (rangeidx * BLOCK_TEST_SIZE);
1253468d277eSRichard Fitzgerald 		KUNIT_EXPECT_EQ(test, 0, regmap_bulk_write(map, reg,
1254468d277eSRichard Fitzgerald 							   &val[rangeidx / 2],
1255468d277eSRichard Fitzgerald 							   BLOCK_TEST_SIZE));
1256468d277eSRichard Fitzgerald 		KUNIT_EXPECT_MEMEQ(test, &data->vals[reg],
1257468d277eSRichard Fitzgerald 				   &val[rangeidx / 2], sizeof(val[rangeidx / 2]));
1258468d277eSRichard Fitzgerald 	}
1259468d277eSRichard Fitzgerald 
1260468d277eSRichard Fitzgerald 	/* Check that odd ranges weren't written */
1261468d277eSRichard Fitzgerald 	for (rangeidx = 1; rangeidx < num_ranges; rangeidx += 2) {
1262468d277eSRichard Fitzgerald 		reg = param->from_reg + (rangeidx * BLOCK_TEST_SIZE);
1263468d277eSRichard Fitzgerald 		for (i = 0; i < BLOCK_TEST_SIZE; i++)
1264468d277eSRichard Fitzgerald 			KUNIT_EXPECT_FALSE(test, data->written[reg + i]);
1265468d277eSRichard Fitzgerald 	}
1266468d277eSRichard Fitzgerald 
1267468d277eSRichard Fitzgerald 	/* Drop range 2 */
1268468d277eSRichard Fitzgerald 	reg = param->from_reg + (2 * BLOCK_TEST_SIZE);
1269468d277eSRichard Fitzgerald 	KUNIT_EXPECT_EQ(test, 0, regcache_drop_region(map, reg, reg + BLOCK_TEST_SIZE - 1));
1270468d277eSRichard Fitzgerald 
1271468d277eSRichard Fitzgerald 	/* Drop part of range 4 */
1272468d277eSRichard Fitzgerald 	reg = param->from_reg + (4 * BLOCK_TEST_SIZE);
1273468d277eSRichard Fitzgerald 	KUNIT_EXPECT_EQ(test, 0, regcache_drop_region(map, reg + 3, reg + 5));
1274468d277eSRichard Fitzgerald 
1275468d277eSRichard Fitzgerald 	/* Mark dirty and reset mock registers to 0 */
1276468d277eSRichard Fitzgerald 	regcache_mark_dirty(map);
1277468d277eSRichard Fitzgerald 	for (i = 0; i < config.max_register + 1; i++) {
1278468d277eSRichard Fitzgerald 		data->vals[i] = 0;
1279468d277eSRichard Fitzgerald 		data->written[i] = false;
1280468d277eSRichard Fitzgerald 	}
1281468d277eSRichard Fitzgerald 
1282468d277eSRichard Fitzgerald 	/* The registers that were dropped from range 4 should now remain at 0 */
1283468d277eSRichard Fitzgerald 	val[4 / 2][3] = 0;
1284468d277eSRichard Fitzgerald 	val[4 / 2][4] = 0;
1285468d277eSRichard Fitzgerald 	val[4 / 2][5] = 0;
1286468d277eSRichard Fitzgerald 
1287468d277eSRichard Fitzgerald 	/* Sync and check that the expected register ranges were written */
1288468d277eSRichard Fitzgerald 	KUNIT_EXPECT_EQ(test, 0, regcache_sync(map));
1289468d277eSRichard Fitzgerald 
1290468d277eSRichard Fitzgerald 	/* Check that odd ranges weren't written */
1291468d277eSRichard Fitzgerald 	for (rangeidx = 1; rangeidx < num_ranges; rangeidx += 2) {
1292468d277eSRichard Fitzgerald 		reg = param->from_reg + (rangeidx * BLOCK_TEST_SIZE);
1293468d277eSRichard Fitzgerald 		for (i = 0; i < BLOCK_TEST_SIZE; i++)
1294468d277eSRichard Fitzgerald 			KUNIT_EXPECT_FALSE(test, data->written[reg + i]);
1295468d277eSRichard Fitzgerald 	}
1296468d277eSRichard Fitzgerald 
1297468d277eSRichard Fitzgerald 	/* Check that even ranges (except 2 and 4) were written */
1298468d277eSRichard Fitzgerald 	for (rangeidx = 0; rangeidx < num_ranges; rangeidx += 2) {
1299468d277eSRichard Fitzgerald 		if ((rangeidx == 2) || (rangeidx == 4))
1300468d277eSRichard Fitzgerald 			continue;
1301468d277eSRichard Fitzgerald 
1302468d277eSRichard Fitzgerald 		reg = param->from_reg + (rangeidx * BLOCK_TEST_SIZE);
1303468d277eSRichard Fitzgerald 		for (i = 0; i < BLOCK_TEST_SIZE; i++)
1304468d277eSRichard Fitzgerald 			KUNIT_EXPECT_TRUE(test, data->written[reg + i]);
1305468d277eSRichard Fitzgerald 
1306468d277eSRichard Fitzgerald 		KUNIT_EXPECT_MEMEQ(test, &data->vals[reg],
1307468d277eSRichard Fitzgerald 				   &val[rangeidx / 2], sizeof(val[rangeidx / 2]));
1308468d277eSRichard Fitzgerald 	}
1309468d277eSRichard Fitzgerald 
1310468d277eSRichard Fitzgerald 	/* Check that range 2 wasn't written */
1311468d277eSRichard Fitzgerald 	reg = param->from_reg + (2 * BLOCK_TEST_SIZE);
1312468d277eSRichard Fitzgerald 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
1313468d277eSRichard Fitzgerald 		KUNIT_EXPECT_FALSE(test, data->written[reg + i]);
1314468d277eSRichard Fitzgerald 
1315468d277eSRichard Fitzgerald 	/* Check that range 4 was partially written */
1316468d277eSRichard Fitzgerald 	reg = param->from_reg + (4 * BLOCK_TEST_SIZE);
1317468d277eSRichard Fitzgerald 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
1318468d277eSRichard Fitzgerald 		KUNIT_EXPECT_EQ(test, data->written[reg + i], i < 3 || i > 5);
1319468d277eSRichard Fitzgerald 
1320468d277eSRichard Fitzgerald 	KUNIT_EXPECT_MEMEQ(test, &data->vals[reg], &val[4 / 2], sizeof(val[4 / 2]));
1321468d277eSRichard Fitzgerald 
1322468d277eSRichard Fitzgerald 	/* Nothing before param->from_reg should have been written */
1323468d277eSRichard Fitzgerald 	for (i = 0; i < param->from_reg; i++)
1324468d277eSRichard Fitzgerald 		KUNIT_EXPECT_FALSE(test, data->written[i]);
1325468d277eSRichard Fitzgerald }
1326468d277eSRichard Fitzgerald 
13277dd52d30SRichard Fitzgerald static void cache_drop_all_and_sync_marked_dirty(struct kunit *test)
13287dd52d30SRichard Fitzgerald {
13297dd52d30SRichard Fitzgerald 	const struct regmap_test_param *param = test->param_value;
13307dd52d30SRichard Fitzgerald 	struct regmap *map;
13317dd52d30SRichard Fitzgerald 	struct regmap_config config;
13327dd52d30SRichard Fitzgerald 	struct regmap_ram_data *data;
13337dd52d30SRichard Fitzgerald 	unsigned int rval[BLOCK_TEST_SIZE];
13347dd52d30SRichard Fitzgerald 	int i;
13357dd52d30SRichard Fitzgerald 
13367dd52d30SRichard Fitzgerald 	config = test_regmap_config;
13377dd52d30SRichard Fitzgerald 	config.num_reg_defaults = BLOCK_TEST_SIZE;
13387dd52d30SRichard Fitzgerald 
13397dd52d30SRichard Fitzgerald 	map = gen_regmap(test, &config, &data);
13407dd52d30SRichard Fitzgerald 	KUNIT_ASSERT_FALSE(test, IS_ERR(map));
13417dd52d30SRichard Fitzgerald 	if (IS_ERR(map))
13427dd52d30SRichard Fitzgerald 		return;
13437dd52d30SRichard Fitzgerald 
13447dd52d30SRichard Fitzgerald 	/* Ensure the data is read from the cache */
13457dd52d30SRichard Fitzgerald 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
13467dd52d30SRichard Fitzgerald 		data->read[param->from_reg + i] = false;
13477dd52d30SRichard Fitzgerald 	KUNIT_EXPECT_EQ(test, 0, regmap_bulk_read(map, param->from_reg, rval,
13487dd52d30SRichard Fitzgerald 						  BLOCK_TEST_SIZE));
13497dd52d30SRichard Fitzgerald 	KUNIT_EXPECT_MEMEQ(test, &data->vals[param->from_reg], rval, sizeof(rval));
13507dd52d30SRichard Fitzgerald 
13517dd52d30SRichard Fitzgerald 	/* Change all values in cache from defaults */
13527dd52d30SRichard Fitzgerald 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
13537dd52d30SRichard Fitzgerald 		KUNIT_EXPECT_EQ(test, 0, regmap_write(map, param->from_reg + i, rval[i] + 1));
13547dd52d30SRichard Fitzgerald 
13557dd52d30SRichard Fitzgerald 	/* Drop all registers */
13567dd52d30SRichard Fitzgerald 	KUNIT_EXPECT_EQ(test, 0, regcache_drop_region(map, 0, config.max_register));
13577dd52d30SRichard Fitzgerald 
13587dd52d30SRichard Fitzgerald 	/* Mark dirty and cache sync should not write anything. */
13597dd52d30SRichard Fitzgerald 	regcache_mark_dirty(map);
13607dd52d30SRichard Fitzgerald 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
13617dd52d30SRichard Fitzgerald 		data->written[param->from_reg + i] = false;
13627dd52d30SRichard Fitzgerald 
13637dd52d30SRichard Fitzgerald 	KUNIT_EXPECT_EQ(test, 0, regcache_sync(map));
13647dd52d30SRichard Fitzgerald 	for (i = 0; i <= config.max_register; i++)
13657dd52d30SRichard Fitzgerald 		KUNIT_EXPECT_FALSE(test, data->written[i]);
13667dd52d30SRichard Fitzgerald }
13677dd52d30SRichard Fitzgerald 
13687dd52d30SRichard Fitzgerald static void cache_drop_all_and_sync_no_defaults(struct kunit *test)
13697dd52d30SRichard Fitzgerald {
13707dd52d30SRichard Fitzgerald 	const struct regmap_test_param *param = test->param_value;
13717dd52d30SRichard Fitzgerald 	struct regmap *map;
13727dd52d30SRichard Fitzgerald 	struct regmap_config config;
13737dd52d30SRichard Fitzgerald 	struct regmap_ram_data *data;
13747dd52d30SRichard Fitzgerald 	unsigned int rval[BLOCK_TEST_SIZE];
13757dd52d30SRichard Fitzgerald 	int i;
13767dd52d30SRichard Fitzgerald 
13777dd52d30SRichard Fitzgerald 	config = test_regmap_config;
13787dd52d30SRichard Fitzgerald 
13797dd52d30SRichard Fitzgerald 	map = gen_regmap(test, &config, &data);
13807dd52d30SRichard Fitzgerald 	KUNIT_ASSERT_FALSE(test, IS_ERR(map));
13817dd52d30SRichard Fitzgerald 	if (IS_ERR(map))
13827dd52d30SRichard Fitzgerald 		return;
13837dd52d30SRichard Fitzgerald 
13847dd52d30SRichard Fitzgerald 	/* Ensure the data is read from the cache */
13857dd52d30SRichard Fitzgerald 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
13867dd52d30SRichard Fitzgerald 		data->read[param->from_reg + i] = false;
13877dd52d30SRichard Fitzgerald 	KUNIT_EXPECT_EQ(test, 0, regmap_bulk_read(map, param->from_reg, rval,
13887dd52d30SRichard Fitzgerald 						  BLOCK_TEST_SIZE));
13897dd52d30SRichard Fitzgerald 	KUNIT_EXPECT_MEMEQ(test, &data->vals[param->from_reg], rval, sizeof(rval));
13907dd52d30SRichard Fitzgerald 
13917dd52d30SRichard Fitzgerald 	/* Change all values in cache */
13927dd52d30SRichard Fitzgerald 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
13937dd52d30SRichard Fitzgerald 		KUNIT_EXPECT_EQ(test, 0, regmap_write(map, param->from_reg + i, rval[i] + 1));
13947dd52d30SRichard Fitzgerald 
13957dd52d30SRichard Fitzgerald 	/* Drop all registers */
13967dd52d30SRichard Fitzgerald 	KUNIT_EXPECT_EQ(test, 0, regcache_drop_region(map, 0, config.max_register));
13977dd52d30SRichard Fitzgerald 
13987dd52d30SRichard Fitzgerald 	/*
13997dd52d30SRichard Fitzgerald 	 * Sync cache without marking it dirty. All registers were dropped
14007dd52d30SRichard Fitzgerald 	 * so the cache should not have any entries to write out.
14017dd52d30SRichard Fitzgerald 	 */
14027dd52d30SRichard Fitzgerald 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
14037dd52d30SRichard Fitzgerald 		data->written[param->from_reg + i] = false;
14047dd52d30SRichard Fitzgerald 
14057dd52d30SRichard Fitzgerald 	KUNIT_EXPECT_EQ(test, 0, regcache_sync(map));
14067dd52d30SRichard Fitzgerald 	for (i = 0; i <= config.max_register; i++)
14077dd52d30SRichard Fitzgerald 		KUNIT_EXPECT_FALSE(test, data->written[i]);
14087dd52d30SRichard Fitzgerald }
14097dd52d30SRichard Fitzgerald 
14107dd52d30SRichard Fitzgerald static void cache_drop_all_and_sync_has_defaults(struct kunit *test)
14117dd52d30SRichard Fitzgerald {
14127dd52d30SRichard Fitzgerald 	const struct regmap_test_param *param = test->param_value;
14137dd52d30SRichard Fitzgerald 	struct regmap *map;
14147dd52d30SRichard Fitzgerald 	struct regmap_config config;
14157dd52d30SRichard Fitzgerald 	struct regmap_ram_data *data;
14167dd52d30SRichard Fitzgerald 	unsigned int rval[BLOCK_TEST_SIZE];
14177dd52d30SRichard Fitzgerald 	int i;
14187dd52d30SRichard Fitzgerald 
14197dd52d30SRichard Fitzgerald 	config = test_regmap_config;
14207dd52d30SRichard Fitzgerald 	config.num_reg_defaults = BLOCK_TEST_SIZE;
14217dd52d30SRichard Fitzgerald 
14227dd52d30SRichard Fitzgerald 	map = gen_regmap(test, &config, &data);
14237dd52d30SRichard Fitzgerald 	KUNIT_ASSERT_FALSE(test, IS_ERR(map));
14247dd52d30SRichard Fitzgerald 	if (IS_ERR(map))
14257dd52d30SRichard Fitzgerald 		return;
14267dd52d30SRichard Fitzgerald 
14277dd52d30SRichard Fitzgerald 	/* Ensure the data is read from the cache */
14287dd52d30SRichard Fitzgerald 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
14297dd52d30SRichard Fitzgerald 		data->read[param->from_reg + i] = false;
14307dd52d30SRichard Fitzgerald 	KUNIT_EXPECT_EQ(test, 0, regmap_bulk_read(map, param->from_reg, rval,
14317dd52d30SRichard Fitzgerald 						  BLOCK_TEST_SIZE));
14327dd52d30SRichard Fitzgerald 	KUNIT_EXPECT_MEMEQ(test, &data->vals[param->from_reg], rval, sizeof(rval));
14337dd52d30SRichard Fitzgerald 
14347dd52d30SRichard Fitzgerald 	/* Change all values in cache from defaults */
14357dd52d30SRichard Fitzgerald 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
14367dd52d30SRichard Fitzgerald 		KUNIT_EXPECT_EQ(test, 0, regmap_write(map, param->from_reg + i, rval[i] + 1));
14377dd52d30SRichard Fitzgerald 
14387dd52d30SRichard Fitzgerald 	/* Drop all registers */
14397dd52d30SRichard Fitzgerald 	KUNIT_EXPECT_EQ(test, 0, regcache_drop_region(map, 0, config.max_register));
14407dd52d30SRichard Fitzgerald 
14417dd52d30SRichard Fitzgerald 	/*
14427dd52d30SRichard Fitzgerald 	 * Sync cache without marking it dirty. All registers were dropped
14437dd52d30SRichard Fitzgerald 	 * so the cache should not have any entries to write out.
14447dd52d30SRichard Fitzgerald 	 */
14457dd52d30SRichard Fitzgerald 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
14467dd52d30SRichard Fitzgerald 		data->written[param->from_reg + i] = false;
14477dd52d30SRichard Fitzgerald 
14487dd52d30SRichard Fitzgerald 	KUNIT_EXPECT_EQ(test, 0, regcache_sync(map));
14497dd52d30SRichard Fitzgerald 	for (i = 0; i <= config.max_register; i++)
14507dd52d30SRichard Fitzgerald 		KUNIT_EXPECT_FALSE(test, data->written[i]);
14517dd52d30SRichard Fitzgerald }
14527dd52d30SRichard Fitzgerald 
1453d881ee5aSMark Brown static void cache_present(struct kunit *test)
1454d881ee5aSMark Brown {
145571091574SRichard Fitzgerald 	const struct regmap_test_param *param = test->param_value;
1456d881ee5aSMark Brown 	struct regmap *map;
1457d881ee5aSMark Brown 	struct regmap_config config;
1458d881ee5aSMark Brown 	struct regmap_ram_data *data;
1459d881ee5aSMark Brown 	unsigned int val;
1460d881ee5aSMark Brown 	int i;
1461d881ee5aSMark Brown 
1462d881ee5aSMark Brown 	config = test_regmap_config;
1463d881ee5aSMark Brown 
14647b7982f1SRichard Fitzgerald 	map = gen_regmap(test, &config, &data);
1465d881ee5aSMark Brown 	KUNIT_ASSERT_FALSE(test, IS_ERR(map));
1466d881ee5aSMark Brown 	if (IS_ERR(map))
1467d881ee5aSMark Brown 		return;
1468d881ee5aSMark Brown 
1469d881ee5aSMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
147071091574SRichard Fitzgerald 		data->read[param->from_reg + i] = false;
1471d881ee5aSMark Brown 
1472d881ee5aSMark Brown 	/* No defaults so no registers cached. */
1473d881ee5aSMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
147471091574SRichard Fitzgerald 		KUNIT_ASSERT_FALSE(test, regcache_reg_cached(map, param->from_reg + i));
1475d881ee5aSMark Brown 
1476d881ee5aSMark Brown 	/* We didn't trigger any reads */
1477d881ee5aSMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
147871091574SRichard Fitzgerald 		KUNIT_ASSERT_FALSE(test, data->read[param->from_reg + i]);
1479d881ee5aSMark Brown 
1480d881ee5aSMark Brown 	/* Fill the cache */
1481d881ee5aSMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
148271091574SRichard Fitzgerald 		KUNIT_EXPECT_EQ(test, 0, regmap_read(map, param->from_reg + i, &val));
1483d881ee5aSMark Brown 
1484d881ee5aSMark Brown 	/* Now everything should be cached */
1485d881ee5aSMark Brown 	for (i = 0; i < BLOCK_TEST_SIZE; i++)
148671091574SRichard Fitzgerald 		KUNIT_ASSERT_TRUE(test, regcache_reg_cached(map, param->from_reg + i));
1487d881ee5aSMark Brown }
1488d881ee5aSMark Brown 
14896a2e332cSMark Brown /* Check that caching the window register works with sync */
14906a2e332cSMark Brown static void cache_range_window_reg(struct kunit *test)
14916a2e332cSMark Brown {
14926a2e332cSMark Brown 	struct regmap *map;
14936a2e332cSMark Brown 	struct regmap_config config;
14946a2e332cSMark Brown 	struct regmap_ram_data *data;
14956a2e332cSMark Brown 	unsigned int val;
14966a2e332cSMark Brown 	int i;
14976a2e332cSMark Brown 
14986a2e332cSMark Brown 	config = test_regmap_config;
14996a2e332cSMark Brown 	config.volatile_reg = test_range_window_volatile;
15006a2e332cSMark Brown 	config.ranges = &test_range;
15016a2e332cSMark Brown 	config.num_ranges = 1;
15026a2e332cSMark Brown 	config.max_register = test_range.range_max;
15036a2e332cSMark Brown 
15047b7982f1SRichard Fitzgerald 	map = gen_regmap(test, &config, &data);
15056a2e332cSMark Brown 	KUNIT_ASSERT_FALSE(test, IS_ERR(map));
15066a2e332cSMark Brown 	if (IS_ERR(map))
15076a2e332cSMark Brown 		return;
15086a2e332cSMark Brown 
15096a2e332cSMark Brown 	/* Write new values to the entire range */
15106a2e332cSMark Brown 	for (i = test_range.range_min; i <= test_range.range_max; i++)
15116a2e332cSMark Brown 		KUNIT_ASSERT_EQ(test, 0, regmap_write(map, i, 0));
15126a2e332cSMark Brown 
15136a2e332cSMark Brown 	val = data->vals[test_range.selector_reg] & test_range.selector_mask;
15146a2e332cSMark Brown 	KUNIT_ASSERT_EQ(test, val, 2);
15156a2e332cSMark Brown 
15166a2e332cSMark Brown 	/* Write to the first register in the range to reset the page */
15176a2e332cSMark Brown 	KUNIT_ASSERT_EQ(test, 0, regmap_write(map, test_range.range_min, 0));
15186a2e332cSMark Brown 	val = data->vals[test_range.selector_reg] & test_range.selector_mask;
15196a2e332cSMark Brown 	KUNIT_ASSERT_EQ(test, val, 0);
15206a2e332cSMark Brown 
15216a2e332cSMark Brown 	/* Trigger a cache sync */
15226a2e332cSMark Brown 	regcache_mark_dirty(map);
15236a2e332cSMark Brown 	KUNIT_ASSERT_EQ(test, 0, regcache_sync(map));
15246a2e332cSMark Brown 
15256a2e332cSMark Brown 	/* Write to the first register again, the page should be reset */
15266a2e332cSMark Brown 	KUNIT_ASSERT_EQ(test, 0, regmap_write(map, test_range.range_min, 0));
15276a2e332cSMark Brown 	val = data->vals[test_range.selector_reg] & test_range.selector_mask;
15286a2e332cSMark Brown 	KUNIT_ASSERT_EQ(test, val, 0);
15296a2e332cSMark Brown 
15306a2e332cSMark Brown 	/* Trigger another cache sync */
15316a2e332cSMark Brown 	regcache_mark_dirty(map);
15326a2e332cSMark Brown 	KUNIT_ASSERT_EQ(test, 0, regcache_sync(map));
15336a2e332cSMark Brown 
15346a2e332cSMark Brown 	/* Write to the last register again, the page should be reset */
15356a2e332cSMark Brown 	KUNIT_ASSERT_EQ(test, 0, regmap_write(map, test_range.range_max, 0));
15366a2e332cSMark Brown 	val = data->vals[test_range.selector_reg] & test_range.selector_mask;
15376a2e332cSMark Brown 	KUNIT_ASSERT_EQ(test, val, 2);
15386a2e332cSMark Brown }
15396a2e332cSMark Brown 
154048bccea9SRichard Fitzgerald static const struct regmap_test_param raw_types_list[] = {
154148bccea9SRichard Fitzgerald 	{ .cache = REGCACHE_NONE,   .val_endian = REGMAP_ENDIAN_LITTLE },
154248bccea9SRichard Fitzgerald 	{ .cache = REGCACHE_NONE,   .val_endian = REGMAP_ENDIAN_BIG },
154348bccea9SRichard Fitzgerald 	{ .cache = REGCACHE_FLAT,   .val_endian = REGMAP_ENDIAN_LITTLE },
154448bccea9SRichard Fitzgerald 	{ .cache = REGCACHE_FLAT,   .val_endian = REGMAP_ENDIAN_BIG },
154548bccea9SRichard Fitzgerald 	{ .cache = REGCACHE_RBTREE, .val_endian = REGMAP_ENDIAN_LITTLE },
154648bccea9SRichard Fitzgerald 	{ .cache = REGCACHE_RBTREE, .val_endian = REGMAP_ENDIAN_BIG },
154748bccea9SRichard Fitzgerald 	{ .cache = REGCACHE_MAPLE,  .val_endian = REGMAP_ENDIAN_LITTLE },
154848bccea9SRichard Fitzgerald 	{ .cache = REGCACHE_MAPLE,  .val_endian = REGMAP_ENDIAN_BIG },
1549155a6bd6SMark Brown };
1550155a6bd6SMark Brown 
155148bccea9SRichard Fitzgerald KUNIT_ARRAY_PARAM(raw_test_types, raw_types_list, param_to_desc);
1552155a6bd6SMark Brown 
155348bccea9SRichard Fitzgerald static const struct regmap_test_param raw_cache_types_list[] = {
155448bccea9SRichard Fitzgerald 	{ .cache = REGCACHE_FLAT,   .val_endian = REGMAP_ENDIAN_LITTLE },
155548bccea9SRichard Fitzgerald 	{ .cache = REGCACHE_FLAT,   .val_endian = REGMAP_ENDIAN_BIG },
155648bccea9SRichard Fitzgerald 	{ .cache = REGCACHE_RBTREE, .val_endian = REGMAP_ENDIAN_LITTLE },
155748bccea9SRichard Fitzgerald 	{ .cache = REGCACHE_RBTREE, .val_endian = REGMAP_ENDIAN_BIG },
155848bccea9SRichard Fitzgerald 	{ .cache = REGCACHE_MAPLE,  .val_endian = REGMAP_ENDIAN_LITTLE },
155948bccea9SRichard Fitzgerald 	{ .cache = REGCACHE_MAPLE,  .val_endian = REGMAP_ENDIAN_BIG },
1560155a6bd6SMark Brown };
1561155a6bd6SMark Brown 
156248bccea9SRichard Fitzgerald KUNIT_ARRAY_PARAM(raw_test_cache_types, raw_cache_types_list, param_to_desc);
1563155a6bd6SMark Brown 
1564155a6bd6SMark Brown static const struct regmap_config raw_regmap_config = {
1565155a6bd6SMark Brown 	.max_register = BLOCK_TEST_SIZE,
1566155a6bd6SMark Brown 
1567155a6bd6SMark Brown 	.reg_format_endian = REGMAP_ENDIAN_LITTLE,
1568155a6bd6SMark Brown 	.reg_bits = 16,
1569155a6bd6SMark Brown 	.val_bits = 16,
1570155a6bd6SMark Brown };
1571155a6bd6SMark Brown 
15727b7982f1SRichard Fitzgerald static struct regmap *gen_raw_regmap(struct kunit *test,
15737b7982f1SRichard Fitzgerald 				     struct regmap_config *config,
1574155a6bd6SMark Brown 				     struct regmap_ram_data **data)
1575155a6bd6SMark Brown {
15767b7982f1SRichard Fitzgerald 	struct regmap_test_priv *priv = test->priv;
157748bccea9SRichard Fitzgerald 	const struct regmap_test_param *param = test->param_value;
1578155a6bd6SMark Brown 	u16 *buf;
1579c3820641SRichard Fitzgerald 	struct regmap *ret = ERR_PTR(-ENOMEM);
1580c3820641SRichard Fitzgerald 	int i, error;
1581155a6bd6SMark Brown 	struct reg_default *defaults;
1582f82ecf76SAndy Shevchenko 	size_t size;
1583155a6bd6SMark Brown 
158448bccea9SRichard Fitzgerald 	config->cache_type = param->cache;
158548bccea9SRichard Fitzgerald 	config->val_format_endian = param->val_endian;
1586a9e26169SGuenter Roeck 	config->disable_locking = config->cache_type == REGCACHE_RBTREE ||
1587a9e26169SGuenter Roeck 					config->cache_type == REGCACHE_MAPLE;
1588155a6bd6SMark Brown 
1589f82ecf76SAndy Shevchenko 	size = array_size(config->max_register + 1, BITS_TO_BYTES(config->reg_bits));
1590155a6bd6SMark Brown 	buf = kmalloc(size, GFP_KERNEL);
1591155a6bd6SMark Brown 	if (!buf)
1592155a6bd6SMark Brown 		return ERR_PTR(-ENOMEM);
1593155a6bd6SMark Brown 
1594155a6bd6SMark Brown 	get_random_bytes(buf, size);
1595155a6bd6SMark Brown 
1596155a6bd6SMark Brown 	*data = kzalloc(sizeof(**data), GFP_KERNEL);
1597155a6bd6SMark Brown 	if (!(*data))
1598c3820641SRichard Fitzgerald 		goto out_free;
1599155a6bd6SMark Brown 	(*data)->vals = (void *)buf;
1600155a6bd6SMark Brown 
1601155a6bd6SMark Brown 	config->num_reg_defaults = config->max_register + 1;
1602c3820641SRichard Fitzgerald 	defaults = kunit_kcalloc(test,
1603c3820641SRichard Fitzgerald 				 config->num_reg_defaults,
1604155a6bd6SMark Brown 				 sizeof(struct reg_default),
1605155a6bd6SMark Brown 				 GFP_KERNEL);
1606155a6bd6SMark Brown 	if (!defaults)
1607c3820641SRichard Fitzgerald 		goto out_free;
1608155a6bd6SMark Brown 	config->reg_defaults = defaults;
1609155a6bd6SMark Brown 
1610155a6bd6SMark Brown 	for (i = 0; i < config->num_reg_defaults; i++) {
1611155a6bd6SMark Brown 		defaults[i].reg = i;
161248bccea9SRichard Fitzgerald 		switch (param->val_endian) {
1613155a6bd6SMark Brown 		case REGMAP_ENDIAN_LITTLE:
1614155a6bd6SMark Brown 			defaults[i].def = le16_to_cpu(buf[i]);
1615155a6bd6SMark Brown 			break;
1616155a6bd6SMark Brown 		case REGMAP_ENDIAN_BIG:
1617155a6bd6SMark Brown 			defaults[i].def = be16_to_cpu(buf[i]);
1618155a6bd6SMark Brown 			break;
1619155a6bd6SMark Brown 		default:
1620c3820641SRichard Fitzgerald 			ret = ERR_PTR(-EINVAL);
1621c3820641SRichard Fitzgerald 			goto out_free;
1622155a6bd6SMark Brown 		}
1623155a6bd6SMark Brown 	}
1624155a6bd6SMark Brown 
1625155a6bd6SMark Brown 	/*
1626155a6bd6SMark Brown 	 * We use the defaults in the tests but they don't make sense
1627155a6bd6SMark Brown 	 * to the core if there's no cache.
1628155a6bd6SMark Brown 	 */
1629155a6bd6SMark Brown 	if (config->cache_type == REGCACHE_NONE)
1630155a6bd6SMark Brown 		config->num_reg_defaults = 0;
1631155a6bd6SMark Brown 
16327b7982f1SRichard Fitzgerald 	ret = regmap_init_raw_ram(priv->dev, config, *data);
1633c3820641SRichard Fitzgerald 	if (IS_ERR(ret))
1634c3820641SRichard Fitzgerald 		goto out_free;
1635c3820641SRichard Fitzgerald 
1636c3820641SRichard Fitzgerald 	/* This calls regmap_exit() on failure, which frees buf and *data */
1637c3820641SRichard Fitzgerald 	error = kunit_add_action_or_reset(test, regmap_exit_action, ret);
1638c3820641SRichard Fitzgerald 	if (error)
1639c3820641SRichard Fitzgerald 		ret = ERR_PTR(error);
1640c3820641SRichard Fitzgerald 
1641c3820641SRichard Fitzgerald 	return ret;
1642c3820641SRichard Fitzgerald 
1643c3820641SRichard Fitzgerald out_free:
1644155a6bd6SMark Brown 	kfree(buf);
1645155a6bd6SMark Brown 	kfree(*data);
1646155a6bd6SMark Brown 
1647155a6bd6SMark Brown 	return ret;
1648155a6bd6SMark Brown }
1649155a6bd6SMark Brown 
1650155a6bd6SMark Brown static void raw_read_defaults_single(struct kunit *test)
1651155a6bd6SMark Brown {
1652155a6bd6SMark Brown 	struct regmap *map;
1653155a6bd6SMark Brown 	struct regmap_config config;
1654155a6bd6SMark Brown 	struct regmap_ram_data *data;
1655155a6bd6SMark Brown 	unsigned int rval;
1656155a6bd6SMark Brown 	int i;
1657155a6bd6SMark Brown 
1658155a6bd6SMark Brown 	config = raw_regmap_config;
1659155a6bd6SMark Brown 
166048bccea9SRichard Fitzgerald 	map = gen_raw_regmap(test, &config, &data);
1661155a6bd6SMark Brown 	KUNIT_ASSERT_FALSE(test, IS_ERR(map));
1662155a6bd6SMark Brown 	if (IS_ERR(map))
1663155a6bd6SMark Brown 		return;
1664155a6bd6SMark Brown 
1665155a6bd6SMark Brown 	/* Check that we can read the defaults via the API */
1666155a6bd6SMark Brown 	for (i = 0; i < config.max_register + 1; i++) {
1667155a6bd6SMark Brown 		KUNIT_EXPECT_EQ(test, 0, regmap_read(map, i, &rval));
1668155a6bd6SMark Brown 		KUNIT_EXPECT_EQ(test, config.reg_defaults[i].def, rval);
1669155a6bd6SMark Brown 	}
1670155a6bd6SMark Brown }
1671155a6bd6SMark Brown 
1672155a6bd6SMark Brown static void raw_read_defaults(struct kunit *test)
1673155a6bd6SMark Brown {
1674155a6bd6SMark Brown 	struct regmap *map;
1675155a6bd6SMark Brown 	struct regmap_config config;
1676155a6bd6SMark Brown 	struct regmap_ram_data *data;
1677155a6bd6SMark Brown 	u16 *rval;
1678155a6bd6SMark Brown 	u16 def;
1679155a6bd6SMark Brown 	size_t val_len;
1680155a6bd6SMark Brown 	int i;
1681155a6bd6SMark Brown 
1682155a6bd6SMark Brown 	config = raw_regmap_config;
1683155a6bd6SMark Brown 
168448bccea9SRichard Fitzgerald 	map = gen_raw_regmap(test, &config, &data);
1685155a6bd6SMark Brown 	KUNIT_ASSERT_FALSE(test, IS_ERR(map));
1686155a6bd6SMark Brown 	if (IS_ERR(map))
1687155a6bd6SMark Brown 		return;
1688155a6bd6SMark Brown 
1689f82ecf76SAndy Shevchenko 	val_len = array_size(sizeof(*rval), config.max_register + 1);
1690d6f2fd7aSRichard Fitzgerald 	rval = kunit_kmalloc(test, val_len, GFP_KERNEL);
1691155a6bd6SMark Brown 	KUNIT_ASSERT_TRUE(test, rval != NULL);
1692155a6bd6SMark Brown 	if (!rval)
1693155a6bd6SMark Brown 		return;
1694155a6bd6SMark Brown 
1695155a6bd6SMark Brown 	/* Check that we can read the defaults via the API */
1696155a6bd6SMark Brown 	KUNIT_EXPECT_EQ(test, 0, regmap_raw_read(map, 0, rval, val_len));
1697155a6bd6SMark Brown 	for (i = 0; i < config.max_register + 1; i++) {
1698155a6bd6SMark Brown 		def = config.reg_defaults[i].def;
1699155a6bd6SMark Brown 		if (config.val_format_endian == REGMAP_ENDIAN_BIG) {
1700866f7021SRichard Fitzgerald 			KUNIT_EXPECT_EQ(test, def, be16_to_cpu((__force __be16)rval[i]));
1701155a6bd6SMark Brown 		} else {
1702866f7021SRichard Fitzgerald 			KUNIT_EXPECT_EQ(test, def, le16_to_cpu((__force __le16)rval[i]));
1703155a6bd6SMark Brown 		}
1704155a6bd6SMark Brown 	}
1705155a6bd6SMark Brown }
1706155a6bd6SMark Brown 
1707155a6bd6SMark Brown static void raw_write_read_single(struct kunit *test)
1708155a6bd6SMark Brown {
1709155a6bd6SMark Brown 	struct regmap *map;
1710155a6bd6SMark Brown 	struct regmap_config config;
1711155a6bd6SMark Brown 	struct regmap_ram_data *data;
1712155a6bd6SMark Brown 	u16 val;
1713155a6bd6SMark Brown 	unsigned int rval;
1714155a6bd6SMark Brown 
1715155a6bd6SMark Brown 	config = raw_regmap_config;
1716155a6bd6SMark Brown 
171748bccea9SRichard Fitzgerald 	map = gen_raw_regmap(test, &config, &data);
1718155a6bd6SMark Brown 	KUNIT_ASSERT_FALSE(test, IS_ERR(map));
1719155a6bd6SMark Brown 	if (IS_ERR(map))
1720155a6bd6SMark Brown 		return;
1721155a6bd6SMark Brown 
1722155a6bd6SMark Brown 	get_random_bytes(&val, sizeof(val));
1723155a6bd6SMark Brown 
1724155a6bd6SMark Brown 	/* If we write a value to a register we can read it back */
1725155a6bd6SMark Brown 	KUNIT_EXPECT_EQ(test, 0, regmap_write(map, 0, val));
1726155a6bd6SMark Brown 	KUNIT_EXPECT_EQ(test, 0, regmap_read(map, 0, &rval));
1727155a6bd6SMark Brown 	KUNIT_EXPECT_EQ(test, val, rval);
1728155a6bd6SMark Brown }
1729155a6bd6SMark Brown 
1730155a6bd6SMark Brown static void raw_write(struct kunit *test)
1731155a6bd6SMark Brown {
1732155a6bd6SMark Brown 	struct regmap *map;
1733155a6bd6SMark Brown 	struct regmap_config config;
1734155a6bd6SMark Brown 	struct regmap_ram_data *data;
1735155a6bd6SMark Brown 	u16 *hw_buf;
1736155a6bd6SMark Brown 	u16 val[2];
1737155a6bd6SMark Brown 	unsigned int rval;
1738155a6bd6SMark Brown 	int i;
1739155a6bd6SMark Brown 
1740155a6bd6SMark Brown 	config = raw_regmap_config;
1741155a6bd6SMark Brown 
174248bccea9SRichard Fitzgerald 	map = gen_raw_regmap(test, &config, &data);
1743155a6bd6SMark Brown 	KUNIT_ASSERT_FALSE(test, IS_ERR(map));
1744155a6bd6SMark Brown 	if (IS_ERR(map))
1745155a6bd6SMark Brown 		return;
1746155a6bd6SMark Brown 
1747155a6bd6SMark Brown 	hw_buf = (u16 *)data->vals;
1748155a6bd6SMark Brown 
1749155a6bd6SMark Brown 	get_random_bytes(&val, sizeof(val));
1750155a6bd6SMark Brown 
1751155a6bd6SMark Brown 	/* Do a raw write */
1752155a6bd6SMark Brown 	KUNIT_EXPECT_EQ(test, 0, regmap_raw_write(map, 2, val, sizeof(val)));
1753155a6bd6SMark Brown 
1754155a6bd6SMark Brown 	/* We should read back the new values, and defaults for the rest */
1755155a6bd6SMark Brown 	for (i = 0; i < config.max_register + 1; i++) {
1756155a6bd6SMark Brown 		KUNIT_EXPECT_EQ(test, 0, regmap_read(map, i, &rval));
1757155a6bd6SMark Brown 
1758155a6bd6SMark Brown 		switch (i) {
1759155a6bd6SMark Brown 		case 2:
1760155a6bd6SMark Brown 		case 3:
1761155a6bd6SMark Brown 			if (config.val_format_endian == REGMAP_ENDIAN_BIG) {
1762155a6bd6SMark Brown 				KUNIT_EXPECT_EQ(test, rval,
1763866f7021SRichard Fitzgerald 						be16_to_cpu((__force __be16)val[i % 2]));
1764155a6bd6SMark Brown 			} else {
1765155a6bd6SMark Brown 				KUNIT_EXPECT_EQ(test, rval,
1766866f7021SRichard Fitzgerald 						le16_to_cpu((__force __le16)val[i % 2]));
1767155a6bd6SMark Brown 			}
1768155a6bd6SMark Brown 			break;
1769155a6bd6SMark Brown 		default:
1770155a6bd6SMark Brown 			KUNIT_EXPECT_EQ(test, config.reg_defaults[i].def, rval);
1771155a6bd6SMark Brown 			break;
1772155a6bd6SMark Brown 		}
1773155a6bd6SMark Brown 	}
1774155a6bd6SMark Brown 
1775155a6bd6SMark Brown 	/* The values should appear in the "hardware" */
1776155a6bd6SMark Brown 	KUNIT_EXPECT_MEMEQ(test, &hw_buf[2], val, sizeof(val));
1777155a6bd6SMark Brown }
1778155a6bd6SMark Brown 
1779d958d978SBen Wolsieffer static bool reg_zero(struct device *dev, unsigned int reg)
1780d958d978SBen Wolsieffer {
1781d958d978SBen Wolsieffer 	return reg == 0;
1782d958d978SBen Wolsieffer }
1783d958d978SBen Wolsieffer 
1784d958d978SBen Wolsieffer static bool ram_reg_zero(struct regmap_ram_data *data, unsigned int reg)
1785d958d978SBen Wolsieffer {
1786d958d978SBen Wolsieffer 	return reg == 0;
1787d958d978SBen Wolsieffer }
1788d958d978SBen Wolsieffer 
1789d958d978SBen Wolsieffer static void raw_noinc_write(struct kunit *test)
1790d958d978SBen Wolsieffer {
1791d958d978SBen Wolsieffer 	struct regmap *map;
1792d958d978SBen Wolsieffer 	struct regmap_config config;
1793d958d978SBen Wolsieffer 	struct regmap_ram_data *data;
17947011b51fSBen Wolsieffer 	unsigned int val;
17957011b51fSBen Wolsieffer 	u16 val_test, val_last;
1796d958d978SBen Wolsieffer 	u16 val_array[BLOCK_TEST_SIZE];
1797d958d978SBen Wolsieffer 
1798d958d978SBen Wolsieffer 	config = raw_regmap_config;
1799d958d978SBen Wolsieffer 	config.volatile_reg = reg_zero;
1800d958d978SBen Wolsieffer 	config.writeable_noinc_reg = reg_zero;
1801d958d978SBen Wolsieffer 	config.readable_noinc_reg = reg_zero;
1802d958d978SBen Wolsieffer 
180348bccea9SRichard Fitzgerald 	map = gen_raw_regmap(test, &config, &data);
1804d958d978SBen Wolsieffer 	KUNIT_ASSERT_FALSE(test, IS_ERR(map));
1805d958d978SBen Wolsieffer 	if (IS_ERR(map))
1806d958d978SBen Wolsieffer 		return;
1807d958d978SBen Wolsieffer 
1808d958d978SBen Wolsieffer 	data->noinc_reg = ram_reg_zero;
1809d958d978SBen Wolsieffer 
1810d958d978SBen Wolsieffer 	get_random_bytes(&val_array, sizeof(val_array));
1811d958d978SBen Wolsieffer 
1812d958d978SBen Wolsieffer 	if (config.val_format_endian == REGMAP_ENDIAN_BIG) {
1813d958d978SBen Wolsieffer 		val_test = be16_to_cpu(val_array[1]) + 100;
1814d958d978SBen Wolsieffer 		val_last = be16_to_cpu(val_array[BLOCK_TEST_SIZE - 1]);
1815d958d978SBen Wolsieffer 	} else {
1816d958d978SBen Wolsieffer 		val_test = le16_to_cpu(val_array[1]) + 100;
1817d958d978SBen Wolsieffer 		val_last = le16_to_cpu(val_array[BLOCK_TEST_SIZE - 1]);
1818d958d978SBen Wolsieffer 	}
1819d958d978SBen Wolsieffer 
1820d958d978SBen Wolsieffer 	/* Put some data into the register following the noinc register */
1821d958d978SBen Wolsieffer 	KUNIT_EXPECT_EQ(test, 0, regmap_write(map, 1, val_test));
1822d958d978SBen Wolsieffer 
1823d958d978SBen Wolsieffer 	/* Write some data to the noinc register */
1824d958d978SBen Wolsieffer 	KUNIT_EXPECT_EQ(test, 0, regmap_noinc_write(map, 0, val_array,
1825d958d978SBen Wolsieffer 						    sizeof(val_array)));
1826d958d978SBen Wolsieffer 
1827d958d978SBen Wolsieffer 	/* We should read back the last value written */
1828d958d978SBen Wolsieffer 	KUNIT_EXPECT_EQ(test, 0, regmap_read(map, 0, &val));
1829d958d978SBen Wolsieffer 	KUNIT_ASSERT_EQ(test, val_last, val);
1830d958d978SBen Wolsieffer 
1831d958d978SBen Wolsieffer 	/* Make sure we didn't touch the register after the noinc register */
1832d958d978SBen Wolsieffer 	KUNIT_EXPECT_EQ(test, 0, regmap_read(map, 1, &val));
1833d958d978SBen Wolsieffer 	KUNIT_ASSERT_EQ(test, val_test, val);
1834d958d978SBen Wolsieffer }
1835d958d978SBen Wolsieffer 
1836155a6bd6SMark Brown static void raw_sync(struct kunit *test)
1837155a6bd6SMark Brown {
1838155a6bd6SMark Brown 	struct regmap *map;
1839155a6bd6SMark Brown 	struct regmap_config config;
1840155a6bd6SMark Brown 	struct regmap_ram_data *data;
18412f0dbb24SMark Brown 	u16 val[3];
1842155a6bd6SMark Brown 	u16 *hw_buf;
1843155a6bd6SMark Brown 	unsigned int rval;
1844155a6bd6SMark Brown 	int i;
1845155a6bd6SMark Brown 
1846155a6bd6SMark Brown 	config = raw_regmap_config;
1847155a6bd6SMark Brown 
184848bccea9SRichard Fitzgerald 	map = gen_raw_regmap(test, &config, &data);
1849155a6bd6SMark Brown 	KUNIT_ASSERT_FALSE(test, IS_ERR(map));
1850155a6bd6SMark Brown 	if (IS_ERR(map))
1851155a6bd6SMark Brown 		return;
1852155a6bd6SMark Brown 
1853155a6bd6SMark Brown 	hw_buf = (u16 *)data->vals;
1854155a6bd6SMark Brown 
18552f0dbb24SMark Brown 	get_changed_bytes(&hw_buf[2], &val[0], sizeof(val));
1856155a6bd6SMark Brown 
1857155a6bd6SMark Brown 	/* Do a regular write and a raw write in cache only mode */
1858155a6bd6SMark Brown 	regcache_cache_only(map, true);
18592f0dbb24SMark Brown 	KUNIT_EXPECT_EQ(test, 0, regmap_raw_write(map, 2, val,
18602f0dbb24SMark Brown 						  sizeof(u16) * 2));
18612f0dbb24SMark Brown 	KUNIT_EXPECT_EQ(test, 0, regmap_write(map, 4, val[2]));
1862155a6bd6SMark Brown 
1863155a6bd6SMark Brown 	/* We should read back the new values, and defaults for the rest */
1864155a6bd6SMark Brown 	for (i = 0; i < config.max_register + 1; i++) {
1865155a6bd6SMark Brown 		KUNIT_EXPECT_EQ(test, 0, regmap_read(map, i, &rval));
1866155a6bd6SMark Brown 
1867155a6bd6SMark Brown 		switch (i) {
1868155a6bd6SMark Brown 		case 2:
1869155a6bd6SMark Brown 		case 3:
1870155a6bd6SMark Brown 			if (config.val_format_endian == REGMAP_ENDIAN_BIG) {
1871155a6bd6SMark Brown 				KUNIT_EXPECT_EQ(test, rval,
1872866f7021SRichard Fitzgerald 						be16_to_cpu((__force __be16)val[i - 2]));
1873155a6bd6SMark Brown 			} else {
1874155a6bd6SMark Brown 				KUNIT_EXPECT_EQ(test, rval,
1875866f7021SRichard Fitzgerald 						le16_to_cpu((__force __le16)val[i - 2]));
1876155a6bd6SMark Brown 			}
1877155a6bd6SMark Brown 			break;
18782f0dbb24SMark Brown 		case 4:
18792f0dbb24SMark Brown 			KUNIT_EXPECT_EQ(test, rval, val[i - 2]);
18802f0dbb24SMark Brown 			break;
1881155a6bd6SMark Brown 		default:
1882155a6bd6SMark Brown 			KUNIT_EXPECT_EQ(test, config.reg_defaults[i].def, rval);
1883155a6bd6SMark Brown 			break;
1884155a6bd6SMark Brown 		}
1885155a6bd6SMark Brown 	}
1886155a6bd6SMark Brown 
18872f0dbb24SMark Brown 	/*
18882f0dbb24SMark Brown 	 * The value written via _write() was translated by the core,
18892f0dbb24SMark Brown 	 * translate the original copy for comparison purposes.
18902f0dbb24SMark Brown 	 */
18912f0dbb24SMark Brown 	if (config.val_format_endian == REGMAP_ENDIAN_BIG)
18922f0dbb24SMark Brown 		val[2] = cpu_to_be16(val[2]);
18932f0dbb24SMark Brown 	else
18942f0dbb24SMark Brown 		val[2] = cpu_to_le16(val[2]);
18952f0dbb24SMark Brown 
1896155a6bd6SMark Brown 	/* The values should not appear in the "hardware" */
18972f0dbb24SMark Brown 	KUNIT_EXPECT_MEMNEQ(test, &hw_buf[2], &val[0], sizeof(val));
1898155a6bd6SMark Brown 
1899155a6bd6SMark Brown 	for (i = 0; i < config.max_register + 1; i++)
1900155a6bd6SMark Brown 		data->written[i] = false;
1901155a6bd6SMark Brown 
1902155a6bd6SMark Brown 	/* Do the sync */
1903155a6bd6SMark Brown 	regcache_cache_only(map, false);
1904155a6bd6SMark Brown 	regcache_mark_dirty(map);
1905155a6bd6SMark Brown 	KUNIT_EXPECT_EQ(test, 0, regcache_sync(map));
1906155a6bd6SMark Brown 
1907155a6bd6SMark Brown 	/* The values should now appear in the "hardware" */
19082f0dbb24SMark Brown 	KUNIT_EXPECT_MEMEQ(test, &hw_buf[2], &val[0], sizeof(val));
1909155a6bd6SMark Brown }
1910155a6bd6SMark Brown 
1911bb92804bSMark Brown static void raw_ranges(struct kunit *test)
1912bb92804bSMark Brown {
1913bb92804bSMark Brown 	struct regmap *map;
1914bb92804bSMark Brown 	struct regmap_config config;
1915bb92804bSMark Brown 	struct regmap_ram_data *data;
1916bb92804bSMark Brown 	unsigned int val;
1917bb92804bSMark Brown 	int i;
1918bb92804bSMark Brown 
1919bb92804bSMark Brown 	config = raw_regmap_config;
1920bb92804bSMark Brown 	config.volatile_reg = test_range_all_volatile;
1921bb92804bSMark Brown 	config.ranges = &test_range;
1922bb92804bSMark Brown 	config.num_ranges = 1;
1923bb92804bSMark Brown 	config.max_register = test_range.range_max;
1924bb92804bSMark Brown 
192548bccea9SRichard Fitzgerald 	map = gen_raw_regmap(test, &config, &data);
1926bb92804bSMark Brown 	KUNIT_ASSERT_FALSE(test, IS_ERR(map));
1927bb92804bSMark Brown 	if (IS_ERR(map))
1928bb92804bSMark Brown 		return;
1929bb92804bSMark Brown 
1930bb92804bSMark Brown 	/* Reset the page to a non-zero value to trigger a change */
1931bb92804bSMark Brown 	KUNIT_EXPECT_EQ(test, 0, regmap_write(map, test_range.selector_reg,
1932bb92804bSMark Brown 					      test_range.range_max));
1933bb92804bSMark Brown 
1934bb92804bSMark Brown 	/* Check we set the page and use the window for writes */
1935bb92804bSMark Brown 	data->written[test_range.selector_reg] = false;
1936bb92804bSMark Brown 	data->written[test_range.window_start] = false;
1937bb92804bSMark Brown 	KUNIT_EXPECT_EQ(test, 0, regmap_write(map, test_range.range_min, 0));
1938bb92804bSMark Brown 	KUNIT_EXPECT_TRUE(test, data->written[test_range.selector_reg]);
1939bb92804bSMark Brown 	KUNIT_EXPECT_TRUE(test, data->written[test_range.window_start]);
1940bb92804bSMark Brown 
1941bb92804bSMark Brown 	data->written[test_range.selector_reg] = false;
1942bb92804bSMark Brown 	data->written[test_range.window_start] = false;
1943bb92804bSMark Brown 	KUNIT_EXPECT_EQ(test, 0, regmap_write(map,
1944bb92804bSMark Brown 					      test_range.range_min +
1945bb92804bSMark Brown 					      test_range.window_len,
1946bb92804bSMark Brown 					      0));
1947bb92804bSMark Brown 	KUNIT_EXPECT_TRUE(test, data->written[test_range.selector_reg]);
1948bb92804bSMark Brown 	KUNIT_EXPECT_TRUE(test, data->written[test_range.window_start]);
1949bb92804bSMark Brown 
1950bb92804bSMark Brown 	/* Same for reads */
1951bb92804bSMark Brown 	data->written[test_range.selector_reg] = false;
1952bb92804bSMark Brown 	data->read[test_range.window_start] = false;
1953bb92804bSMark Brown 	KUNIT_EXPECT_EQ(test, 0, regmap_read(map, test_range.range_min, &val));
1954bb92804bSMark Brown 	KUNIT_EXPECT_TRUE(test, data->written[test_range.selector_reg]);
1955bb92804bSMark Brown 	KUNIT_EXPECT_TRUE(test, data->read[test_range.window_start]);
1956bb92804bSMark Brown 
1957bb92804bSMark Brown 	data->written[test_range.selector_reg] = false;
1958bb92804bSMark Brown 	data->read[test_range.window_start] = false;
1959bb92804bSMark Brown 	KUNIT_EXPECT_EQ(test, 0, regmap_read(map,
1960bb92804bSMark Brown 					     test_range.range_min +
1961bb92804bSMark Brown 					     test_range.window_len,
1962bb92804bSMark Brown 					     &val));
1963bb92804bSMark Brown 	KUNIT_EXPECT_TRUE(test, data->written[test_range.selector_reg]);
1964bb92804bSMark Brown 	KUNIT_EXPECT_TRUE(test, data->read[test_range.window_start]);
1965bb92804bSMark Brown 
1966bb92804bSMark Brown 	/* No physical access triggered in the virtual range */
1967bb92804bSMark Brown 	for (i = test_range.range_min; i < test_range.range_max; i++) {
1968bb92804bSMark Brown 		KUNIT_EXPECT_FALSE(test, data->read[i]);
1969bb92804bSMark Brown 		KUNIT_EXPECT_FALSE(test, data->written[i]);
1970bb92804bSMark Brown 	}
1971bb92804bSMark Brown }
1972bb92804bSMark Brown 
19732238959bSMark Brown static struct kunit_case regmap_test_cases[] = {
19742238959bSMark Brown 	KUNIT_CASE_PARAM(basic_read_write, regcache_types_gen_params),
1975f63eb9aeSRichard Fitzgerald 	KUNIT_CASE_PARAM(read_bypassed, real_cache_types_gen_params),
1976f63eb9aeSRichard Fitzgerald 	KUNIT_CASE_PARAM(read_bypassed_volatile, real_cache_types_gen_params),
19772238959bSMark Brown 	KUNIT_CASE_PARAM(bulk_write, regcache_types_gen_params),
19782238959bSMark Brown 	KUNIT_CASE_PARAM(bulk_read, regcache_types_gen_params),
1979*c2bb8198SGuenter Roeck 	KUNIT_CASE_PARAM(multi_write, regcache_types_gen_params),
1980*c2bb8198SGuenter Roeck 	KUNIT_CASE_PARAM(multi_read, regcache_types_gen_params),
198118003306SMark Brown 	KUNIT_CASE_PARAM(write_readonly, regcache_types_gen_params),
1982a07bff40SMark Brown 	KUNIT_CASE_PARAM(read_writeonly, regcache_types_gen_params),
19832238959bSMark Brown 	KUNIT_CASE_PARAM(reg_defaults, regcache_types_gen_params),
19842238959bSMark Brown 	KUNIT_CASE_PARAM(reg_defaults_read_dev, regcache_types_gen_params),
19852238959bSMark Brown 	KUNIT_CASE_PARAM(register_patch, regcache_types_gen_params),
19862238959bSMark Brown 	KUNIT_CASE_PARAM(stride, regcache_types_gen_params),
19872238959bSMark Brown 	KUNIT_CASE_PARAM(basic_ranges, regcache_types_gen_params),
19882238959bSMark Brown 	KUNIT_CASE_PARAM(stress_insert, regcache_types_gen_params),
19892238959bSMark Brown 	KUNIT_CASE_PARAM(cache_bypass, real_cache_types_gen_params),
19907903d15fSRichard Fitzgerald 	KUNIT_CASE_PARAM(cache_sync_marked_dirty, real_cache_types_gen_params),
19917903d15fSRichard Fitzgerald 	KUNIT_CASE_PARAM(cache_sync_after_cache_only, real_cache_types_gen_params),
19927903d15fSRichard Fitzgerald 	KUNIT_CASE_PARAM(cache_sync_defaults_marked_dirty, real_cache_types_gen_params),
19937903d15fSRichard Fitzgerald 	KUNIT_CASE_PARAM(cache_sync_default_after_cache_only, real_cache_types_gen_params),
1994357a1ebdSMark Brown 	KUNIT_CASE_PARAM(cache_sync_readonly, real_cache_types_gen_params),
19952238959bSMark Brown 	KUNIT_CASE_PARAM(cache_sync_patch, real_cache_types_gen_params),
19962238959bSMark Brown 	KUNIT_CASE_PARAM(cache_drop, sparse_cache_types_gen_params),
1997468d277eSRichard Fitzgerald 	KUNIT_CASE_PARAM(cache_drop_with_non_contiguous_ranges, sparse_cache_types_gen_params),
19987dd52d30SRichard Fitzgerald 	KUNIT_CASE_PARAM(cache_drop_all_and_sync_marked_dirty, sparse_cache_types_gen_params),
19997dd52d30SRichard Fitzgerald 	KUNIT_CASE_PARAM(cache_drop_all_and_sync_no_defaults, sparse_cache_types_gen_params),
20007dd52d30SRichard Fitzgerald 	KUNIT_CASE_PARAM(cache_drop_all_and_sync_has_defaults, sparse_cache_types_gen_params),
2001d881ee5aSMark Brown 	KUNIT_CASE_PARAM(cache_present, sparse_cache_types_gen_params),
2002ac4394bfSRichard Fitzgerald 	KUNIT_CASE_PARAM(cache_range_window_reg, real_cache_types_only_gen_params),
2003155a6bd6SMark Brown 
2004155a6bd6SMark Brown 	KUNIT_CASE_PARAM(raw_read_defaults_single, raw_test_types_gen_params),
2005155a6bd6SMark Brown 	KUNIT_CASE_PARAM(raw_read_defaults, raw_test_types_gen_params),
2006155a6bd6SMark Brown 	KUNIT_CASE_PARAM(raw_write_read_single, raw_test_types_gen_params),
2007155a6bd6SMark Brown 	KUNIT_CASE_PARAM(raw_write, raw_test_types_gen_params),
2008d958d978SBen Wolsieffer 	KUNIT_CASE_PARAM(raw_noinc_write, raw_test_types_gen_params),
2009155a6bd6SMark Brown 	KUNIT_CASE_PARAM(raw_sync, raw_test_cache_types_gen_params),
2010bb92804bSMark Brown 	KUNIT_CASE_PARAM(raw_ranges, raw_test_cache_types_gen_params),
20112238959bSMark Brown 	{}
20122238959bSMark Brown };
20132238959bSMark Brown 
20147b7982f1SRichard Fitzgerald static int regmap_test_init(struct kunit *test)
20157b7982f1SRichard Fitzgerald {
20167b7982f1SRichard Fitzgerald 	struct regmap_test_priv *priv;
20177b7982f1SRichard Fitzgerald 	struct device *dev;
20187b7982f1SRichard Fitzgerald 
20197b7982f1SRichard Fitzgerald 	priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
20207b7982f1SRichard Fitzgerald 	if (!priv)
20217b7982f1SRichard Fitzgerald 		return -ENOMEM;
20227b7982f1SRichard Fitzgerald 
20237b7982f1SRichard Fitzgerald 	test->priv = priv;
20247b7982f1SRichard Fitzgerald 
20257b7982f1SRichard Fitzgerald 	dev = kunit_device_register(test, "regmap_test");
2026991b5e2aSDan Carpenter 	if (IS_ERR(dev))
2027991b5e2aSDan Carpenter 		return PTR_ERR(dev);
20287b7982f1SRichard Fitzgerald 
2029991b5e2aSDan Carpenter 	priv->dev = get_device(dev);
20307b7982f1SRichard Fitzgerald 	dev_set_drvdata(dev, test);
20317b7982f1SRichard Fitzgerald 
20327b7982f1SRichard Fitzgerald 	return 0;
20337b7982f1SRichard Fitzgerald }
20347b7982f1SRichard Fitzgerald 
20357b7982f1SRichard Fitzgerald static void regmap_test_exit(struct kunit *test)
20367b7982f1SRichard Fitzgerald {
20377b7982f1SRichard Fitzgerald 	struct regmap_test_priv *priv = test->priv;
20387b7982f1SRichard Fitzgerald 
20397b7982f1SRichard Fitzgerald 	/* Destroy the dummy struct device */
20407b7982f1SRichard Fitzgerald 	if (priv && priv->dev)
20417b7982f1SRichard Fitzgerald 		put_device(priv->dev);
20427b7982f1SRichard Fitzgerald }
20437b7982f1SRichard Fitzgerald 
20442238959bSMark Brown static struct kunit_suite regmap_test_suite = {
20452238959bSMark Brown 	.name = "regmap",
20467b7982f1SRichard Fitzgerald 	.init = regmap_test_init,
20477b7982f1SRichard Fitzgerald 	.exit = regmap_test_exit,
20482238959bSMark Brown 	.test_cases = regmap_test_cases,
20492238959bSMark Brown };
20502238959bSMark Brown kunit_test_suite(regmap_test_suite);
20512238959bSMark Brown 
2052a8bd7789SJeff Johnson MODULE_DESCRIPTION("Regmap KUnit tests");
20532238959bSMark Brown MODULE_LICENSE("GPL v2");
2054